]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/if_ndis/if_ndis.c
Import CK as of commit 5221ae2f3722a78c7fc41e47069ad94983d3bccb.
[FreeBSD/FreeBSD.git] / sys / dev / if_ndis / if_ndis.c
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2003
5  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
35  * then hacked upon mercilessly by my.
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/sockio.h>
44 #include <sys/mbuf.h>
45 #include <sys/malloc.h>
46 #include <sys/endian.h>
47 #include <sys/priv.h>
48 #include <sys/kernel.h>
49 #include <sys/socket.h>
50 #include <sys/queue.h>
51 #include <sys/module.h>
52 #include <sys/proc.h>
53 #include <sys/sysctl.h>
54 #include <sys/kthread.h>
55 #include <sys/limits.h>
56
57 #include <net/if.h>
58 #include <net/if_var.h>
59 #include <net/if_arp.h>
60 #include <net/ethernet.h>
61 #include <net/if_dl.h>
62 #include <net/if_media.h>
63 #include <net/if_types.h>
64 #include <net/route.h>
65
66 #include <net/bpf.h>
67
68 #include <machine/bus.h>
69 #include <machine/resource.h>
70 #include <sys/bus.h>
71 #include <sys/rman.h>
72
73 #include <net80211/ieee80211_var.h>
74 #include <net80211/ieee80211_ioctl.h>
75 #include <net80211/ieee80211_regdomain.h>
76
77 #include <dev/pci/pcireg.h>
78 #include <dev/pci/pcivar.h>
79 #include <dev/usb/usb.h>
80 #include <dev/usb/usbdi.h>
81
82 #include <compat/ndis/pe_var.h>
83 #include <compat/ndis/cfg_var.h>
84 #include <compat/ndis/resource_var.h>
85 #include <compat/ndis/ntoskrnl_var.h>
86 #include <compat/ndis/hal_var.h>
87 #include <compat/ndis/ndis_var.h>
88 #include <compat/ndis/usbd_var.h>
89 #include <dev/if_ndis/if_ndisvar.h>
90
91 #define NDIS_DEBUG
92 #ifdef NDIS_DEBUG
93 #define DPRINTF(x)      do { if (ndis_debug > 0) printf x; } while (0)
94 int ndis_debug = 0;
95 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
96     "if_ndis debug level");
97 #else
98 #define DPRINTF(x)
99 #endif
100
101 SYSCTL_DECL(_hw_ndisusb);
102 int ndisusb_halt = 1;
103 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
104     "Halt NDIS USB driver when it's attached");
105
106 /* 0 - 30 dBm to mW conversion table */
107 static const uint16_t dBm2mW[] = {
108         1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
109         3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
110         10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
111         32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
112         100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
113         316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
114         1000
115 };
116
117 MODULE_DEPEND(ndis, ether, 1, 1, 1);
118 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
119 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
120
121 MODULE_VERSION(ndis, 1);
122
123 int ndis_attach                 (device_t);
124 int ndis_detach                 (device_t);
125 int ndis_suspend                (device_t);
126 int ndis_resume                 (device_t);
127 void ndis_shutdown              (device_t);
128
129 int ndisdrv_modevent            (module_t, int, void *);
130
131 static void ndis_txeof          (ndis_handle, ndis_packet *, ndis_status);
132 static void ndis_rxeof          (ndis_handle, ndis_packet **, uint32_t);
133 static void ndis_rxeof_eth      (ndis_handle, ndis_handle, char *, void *,
134                                  uint32_t, void *, uint32_t, uint32_t);
135 static void ndis_rxeof_done     (ndis_handle);
136 static void ndis_rxeof_xfr      (kdpc *, ndis_handle, void *, void *);
137 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
138                                  uint32_t, uint32_t);
139 static void ndis_linksts        (ndis_handle, ndis_status, void *, uint32_t);
140 static void ndis_linksts_done   (ndis_handle);
141
142 /* We need to wrap these functions for amd64. */
143 static funcptr ndis_txeof_wrap;
144 static funcptr ndis_rxeof_wrap;
145 static funcptr ndis_rxeof_eth_wrap;
146 static funcptr ndis_rxeof_done_wrap;
147 static funcptr ndis_rxeof_xfr_wrap;
148 static funcptr ndis_rxeof_xfr_done_wrap;
149 static funcptr ndis_linksts_wrap;
150 static funcptr ndis_linksts_done_wrap;
151 static funcptr ndis_ticktask_wrap;
152 static funcptr ndis_ifstarttask_wrap;
153 static funcptr ndis_resettask_wrap;
154 static funcptr ndis_inputtask_wrap;
155
156 static struct   ieee80211vap *ndis_vap_create(struct ieee80211com *,
157                     const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
158                     const uint8_t [IEEE80211_ADDR_LEN],
159                     const uint8_t [IEEE80211_ADDR_LEN]);
160 static void ndis_vap_delete     (struct ieee80211vap *);
161 static void ndis_tick           (void *);
162 static void ndis_ticktask       (device_object *, void *);
163 static int ndis_raw_xmit        (struct ieee80211_node *, struct mbuf *,
164         const struct ieee80211_bpf_params *);
165 static void ndis_update_mcast   (struct ieee80211com *);
166 static void ndis_update_promisc (struct ieee80211com *);
167 static void ndis_ifstart        (struct ifnet *);
168 static void ndis_ifstarttask    (device_object *, void *);
169 static void ndis_resettask      (device_object *, void *);
170 static void ndis_inputtask      (device_object *, void *);
171 static int ndis_ifioctl         (struct ifnet *, u_long, caddr_t);
172 static int ndis_newstate        (struct ieee80211vap *, enum ieee80211_state,
173         int);
174 static int ndis_nettype_chan    (uint32_t);
175 static int ndis_nettype_mode    (uint32_t);
176 static void ndis_scan           (void *);
177 static void ndis_scan_results   (struct ndis_softc *);
178 static void ndis_scan_start     (struct ieee80211com *);
179 static void ndis_scan_end       (struct ieee80211com *);
180 static void ndis_set_channel    (struct ieee80211com *);
181 static void ndis_scan_curchan   (struct ieee80211_scan_state *, unsigned long);
182 static void ndis_scan_mindwell  (struct ieee80211_scan_state *);
183 static void ndis_init           (void *);
184 static void ndis_stop           (struct ndis_softc *);
185 static int ndis_ifmedia_upd     (struct ifnet *);
186 static void ndis_ifmedia_sts    (struct ifnet *, struct ifmediareq *);
187 static int ndis_get_bssid_list  (struct ndis_softc *,
188                                         ndis_80211_bssid_list_ex **);
189 static int ndis_get_assoc       (struct ndis_softc *, ndis_wlan_bssid_ex **);
190 static int ndis_probe_offload   (struct ndis_softc *);
191 static int ndis_set_offload     (struct ndis_softc *);
192 static void ndis_getstate_80211 (struct ndis_softc *);
193 static void ndis_setstate_80211 (struct ndis_softc *);
194 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
195 static void ndis_media_status   (struct ifnet *, struct ifmediareq *);
196 static int ndis_set_cipher      (struct ndis_softc *, int);
197 static int ndis_set_wpa         (struct ndis_softc *, void *, int);
198 static int ndis_add_key         (struct ieee80211vap *,
199         const struct ieee80211_key *);
200 static int ndis_del_key         (struct ieee80211vap *,
201         const struct ieee80211_key *);
202 static void ndis_setmulti       (struct ndis_softc *);
203 static void ndis_map_sclist     (void *, bus_dma_segment_t *,
204         int, bus_size_t, int);
205 static int ndis_ifattach(struct ndis_softc *);
206
207 static int ndis_80211attach(struct ndis_softc *);
208 static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
209 static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
210 static void ndis_80211parent(struct ieee80211com *);
211
212 static int ndisdrv_loaded = 0;
213
214 /*
215  * This routine should call windrv_load() once for each driver
216  * image. This will do the relocation and dynalinking for the
217  * image, and create a Windows driver object which will be
218  * saved in our driver database.
219  */
220 int
221 ndisdrv_modevent(mod, cmd, arg)
222         module_t                mod;
223         int                     cmd;
224         void                    *arg;
225 {
226         int                     error = 0;
227
228         switch (cmd) {
229         case MOD_LOAD:
230                 ndisdrv_loaded++;
231                 if (ndisdrv_loaded > 1)
232                         break;
233                 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
234                     3, WINDRV_WRAP_STDCALL);
235                 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
236                     8, WINDRV_WRAP_STDCALL);
237                 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
238                     1, WINDRV_WRAP_STDCALL);
239                 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
240                     4, WINDRV_WRAP_STDCALL);
241                 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
242                     &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
243                 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
244                     3, WINDRV_WRAP_STDCALL);
245                 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
246                     4, WINDRV_WRAP_STDCALL);
247                 windrv_wrap((funcptr)ndis_linksts_done,
248                     &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
249                 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
250                     2, WINDRV_WRAP_STDCALL);
251                 windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap,
252                     2, WINDRV_WRAP_STDCALL);
253                 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
254                     2, WINDRV_WRAP_STDCALL);
255                 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
256                     2, WINDRV_WRAP_STDCALL);
257                 break;
258         case MOD_UNLOAD:
259                 ndisdrv_loaded--;
260                 if (ndisdrv_loaded > 0)
261                         break;
262                 /* fallthrough */
263         case MOD_SHUTDOWN:
264                 windrv_unwrap(ndis_rxeof_wrap);
265                 windrv_unwrap(ndis_rxeof_eth_wrap);
266                 windrv_unwrap(ndis_rxeof_done_wrap);
267                 windrv_unwrap(ndis_rxeof_xfr_wrap);
268                 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
269                 windrv_unwrap(ndis_txeof_wrap);
270                 windrv_unwrap(ndis_linksts_wrap);
271                 windrv_unwrap(ndis_linksts_done_wrap);
272                 windrv_unwrap(ndis_ticktask_wrap);
273                 windrv_unwrap(ndis_ifstarttask_wrap);
274                 windrv_unwrap(ndis_resettask_wrap);
275                 windrv_unwrap(ndis_inputtask_wrap);
276                 break;
277         default:
278                 error = EINVAL;
279                 break;
280         }
281
282         return (error);
283 }
284
285 /*
286  * Program the 64-bit multicast hash filter.
287  */
288 static void
289 ndis_setmulti(sc)
290         struct ndis_softc       *sc;
291 {
292         struct ifnet            *ifp;
293         struct ifmultiaddr      *ifma;
294         int                     len, mclistsz, error;
295         uint8_t                 *mclist;
296
297
298         if (!NDIS_INITIALIZED(sc))
299                 return;
300
301         if (sc->ndis_80211)
302                 return;
303
304         ifp = sc->ifp;
305         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
306                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
307                 len = sizeof(sc->ndis_filter);
308                 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
309                     &sc->ndis_filter, &len);
310                 if (error)
311                         device_printf(sc->ndis_dev,
312                             "set allmulti failed: %d\n", error);
313                 return;
314         }
315
316         if (CK_STAILQ_EMPTY(&ifp->if_multiaddrs))
317                 return;
318
319         len = sizeof(mclistsz);
320         ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
321
322         mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
323
324         if (mclist == NULL) {
325                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
326                 goto out;
327         }
328
329         sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
330
331         len = 0;
332         if_maddr_rlock(ifp);
333         CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
334                 if (ifma->ifma_addr->sa_family != AF_LINK)
335                         continue;
336                 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
337                     mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
338                 len++;
339                 if (len > mclistsz) {
340                         if_maddr_runlock(ifp);
341                         sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
342                         sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
343                         goto out;
344                 }
345         }
346         if_maddr_runlock(ifp);
347
348         len = len * ETHER_ADDR_LEN;
349         error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
350         if (error) {
351                 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
352                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
353                 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
354         }
355
356 out:
357         free(mclist, M_TEMP);
358
359         len = sizeof(sc->ndis_filter);
360         error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
361             &sc->ndis_filter, &len);
362         if (error)
363                 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
364 }
365
366 static int
367 ndis_set_offload(sc)
368         struct ndis_softc       *sc;
369 {
370         ndis_task_offload       *nto;
371         ndis_task_offload_hdr   *ntoh;
372         ndis_task_tcpip_csum    *nttc;
373         struct ifnet            *ifp;
374         int                     len, error;
375
376         if (!NDIS_INITIALIZED(sc))
377                 return (EINVAL);
378
379         if (sc->ndis_80211)
380                 return (EINVAL);
381         /* See if there's anything to set. */
382
383         ifp = sc->ifp;
384         error = ndis_probe_offload(sc);
385         if (error)
386                 return (error);
387                 
388         if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
389                 return (0);
390
391         len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
392             sizeof(ndis_task_tcpip_csum);
393
394         ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
395
396         if (ntoh == NULL)
397                 return (ENOMEM);
398
399         ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
400         ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
401         ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
402         ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
403         ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
404         ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
405
406         nto = (ndis_task_offload *)((char *)ntoh +
407             ntoh->ntoh_offset_firsttask);
408
409         nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
410         nto->nto_len = sizeof(ndis_task_offload);
411         nto->nto_task = NDIS_TASK_TCPIP_CSUM;
412         nto->nto_offset_nexttask = 0;
413         nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
414
415         nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
416
417         if (ifp->if_capenable & IFCAP_TXCSUM)
418                 nttc->nttc_v4tx = sc->ndis_v4tx;
419
420         if (ifp->if_capenable & IFCAP_RXCSUM)
421                 nttc->nttc_v4rx = sc->ndis_v4rx;
422
423         error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
424         free(ntoh, M_TEMP);
425
426         return (error);
427 }
428
429 static int
430 ndis_probe_offload(sc)
431         struct ndis_softc       *sc;
432 {
433         ndis_task_offload       *nto;
434         ndis_task_offload_hdr   *ntoh;
435         ndis_task_tcpip_csum    *nttc = NULL;
436         struct ifnet            *ifp;
437         int                     len, error, dummy;
438
439         ifp = sc->ifp;
440
441         len = sizeof(dummy);
442         error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
443
444         if (error != ENOSPC)
445                 return (error);
446
447         ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
448
449         if (ntoh == NULL)
450                 return (ENOMEM);
451
452         ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
453         ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
454         ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
455         ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
456         ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
457
458         error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
459
460         if (error) {
461                 free(ntoh, M_TEMP);
462                 return (error);
463         }
464
465         if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
466                 free(ntoh, M_TEMP);
467                 return (EINVAL);
468         }
469
470         nto = (ndis_task_offload *)((char *)ntoh +
471             ntoh->ntoh_offset_firsttask);
472
473         while (1) {
474                 switch (nto->nto_task) {
475                 case NDIS_TASK_TCPIP_CSUM:
476                         nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
477                         break;
478                 /* Don't handle these yet. */
479                 case NDIS_TASK_IPSEC:
480                 case NDIS_TASK_TCP_LARGESEND:
481                 default:
482                         break;
483                 }
484                 if (nto->nto_offset_nexttask == 0)
485                         break;
486                 nto = (ndis_task_offload *)((char *)nto +
487                     nto->nto_offset_nexttask);
488         }
489
490         if (nttc == NULL) {
491                 free(ntoh, M_TEMP);
492                 return (ENOENT);
493         }
494
495         sc->ndis_v4tx = nttc->nttc_v4tx;
496         sc->ndis_v4rx = nttc->nttc_v4rx;
497
498         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
499                 sc->ndis_hwassist |= CSUM_IP;
500         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
501                 sc->ndis_hwassist |= CSUM_TCP;
502         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
503                 sc->ndis_hwassist |= CSUM_UDP;
504
505         if (sc->ndis_hwassist)
506                 ifp->if_capabilities |= IFCAP_TXCSUM;
507
508         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
509                 ifp->if_capabilities |= IFCAP_RXCSUM;
510         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
511                 ifp->if_capabilities |= IFCAP_RXCSUM;
512         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
513                 ifp->if_capabilities |= IFCAP_RXCSUM;
514
515         free(ntoh, M_TEMP);
516         return (0);
517 }
518
519 static int
520 ndis_nettype_chan(uint32_t type)
521 {
522         switch (type) {
523         case NDIS_80211_NETTYPE_11FH:           return (IEEE80211_CHAN_FHSS);
524         case NDIS_80211_NETTYPE_11DS:           return (IEEE80211_CHAN_B);
525         case NDIS_80211_NETTYPE_11OFDM5:        return (IEEE80211_CHAN_A);
526         case NDIS_80211_NETTYPE_11OFDM24:       return (IEEE80211_CHAN_G);
527         }
528         DPRINTF(("unknown channel nettype %d\n", type));
529         return (IEEE80211_CHAN_B);      /* Default to 11B chan */
530 }
531
532 static int
533 ndis_nettype_mode(uint32_t type)
534 {
535         switch (type) {
536         case NDIS_80211_NETTYPE_11FH:           return (IEEE80211_MODE_FH);
537         case NDIS_80211_NETTYPE_11DS:           return (IEEE80211_MODE_11B);
538         case NDIS_80211_NETTYPE_11OFDM5:        return (IEEE80211_MODE_11A);
539         case NDIS_80211_NETTYPE_11OFDM24:       return (IEEE80211_MODE_11G);
540         }
541         DPRINTF(("unknown mode nettype %d\n", type));
542         return (IEEE80211_MODE_AUTO);
543 }
544
545 /*
546  * Attach the interface. Allocate softc structures, do ifmedia
547  * setup and ethernet/BPF attach.
548  */
549 int
550 ndis_attach(device_t dev)
551 {
552         struct ndis_softc       *sc;
553         driver_object           *pdrv;
554         device_object           *pdo;
555         int                     error = 0, len;
556         int                     i;
557
558         sc = device_get_softc(dev);
559
560         mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
561             MTX_DEF);
562         KeInitializeSpinLock(&sc->ndis_rxlock);
563         KeInitializeSpinLock(&sc->ndisusb_tasklock);
564         KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
565         InitializeListHead(&sc->ndis_shlist);
566         InitializeListHead(&sc->ndisusb_tasklist);
567         InitializeListHead(&sc->ndisusb_xferdonelist);
568         callout_init(&sc->ndis_stat_callout, 1);
569         mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
570
571         if (sc->ndis_iftype == PCMCIABus) {
572                 error = ndis_alloc_amem(sc);
573                 if (error) {
574                         device_printf(dev, "failed to allocate "
575                             "attribute memory\n");
576                         goto fail;
577                 }
578         }
579
580         /* Create sysctl registry nodes */
581         ndis_create_sysctls(sc);
582
583         /* Find the PDO for this device instance. */
584
585         if (sc->ndis_iftype == PCIBus)
586                 pdrv = windrv_lookup(0, "PCI Bus");
587         else if (sc->ndis_iftype == PCMCIABus)
588                 pdrv = windrv_lookup(0, "PCCARD Bus");
589         else
590                 pdrv = windrv_lookup(0, "USB Bus");
591         pdo = windrv_find_pdo(pdrv, dev);
592
593         /*
594          * Create a new functional device object for this
595          * device. This is what creates the miniport block
596          * for this device instance.
597          */
598
599         if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
600                 device_printf(dev, "failed to create FDO!\n");
601                 error = ENXIO;
602                 goto fail;
603         }
604
605         /* Tell the user what version of the API the driver is using. */
606         device_printf(dev, "NDIS API version: %d.%d\n",
607             sc->ndis_chars->nmc_version_major,
608             sc->ndis_chars->nmc_version_minor);
609
610         /* Do resource conversion. */
611         if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
612                 ndis_convert_res(sc);
613         else
614                 sc->ndis_block->nmb_rlist = NULL;
615
616         /* Install our RX and TX interrupt handlers. */
617         sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
618         sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
619         sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
620         sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
621         sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
622
623         /* Override the status handler so we can detect link changes. */
624         sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
625         sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
626
627         /* Set up work item handlers. */
628         sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
629         sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630         sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
631         sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
632         sc->ndisusb_xferdoneitem =
633             IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
634         sc->ndisusb_taskitem =
635             IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
636         KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
637
638         /* Call driver's init routine. */
639         if (ndis_init_nic(sc)) {
640                 device_printf(dev, "init handler failed\n");
641                 error = ENXIO;
642                 goto fail;
643         }
644
645         /*
646          * Figure out how big to make the TX buffer pool.
647          */
648         len = sizeof(sc->ndis_maxpkts);
649         if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
650                     &sc->ndis_maxpkts, &len)) {
651                 device_printf(dev, "failed to get max TX packets\n");
652                 error = ENXIO;
653                 goto fail;
654         }
655
656         /*
657          * If this is a deserialized miniport, we don't have
658          * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
659          */
660         if (!NDIS_SERIALIZED(sc->ndis_block))
661                 sc->ndis_maxpkts = NDIS_TXPKTS;
662
663         /* Enforce some sanity, just in case. */
664
665         if (sc->ndis_maxpkts == 0)
666                 sc->ndis_maxpkts = 10;
667
668         sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
669             sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
670
671         /* Allocate a pool of ndis_packets for TX encapsulation. */
672
673         NdisAllocatePacketPool(&i, &sc->ndis_txpool,
674             sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
675
676         if (i != NDIS_STATUS_SUCCESS) {
677                 sc->ndis_txpool = NULL;
678                 device_printf(dev, "failed to allocate TX packet pool");
679                 error = ENOMEM;
680                 goto fail;
681         }
682
683         sc->ndis_txpending = sc->ndis_maxpkts;
684
685         sc->ndis_oidcnt = 0;
686         /* Get supported oid list. */
687         ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
688
689         /* If the NDIS module requested scatter/gather, init maps. */
690         if (sc->ndis_sc)
691                 ndis_init_dma(sc);
692
693         /*
694          * See if the OID_802_11_CONFIGURATION OID is
695          * supported by this driver. If it is, then this an 802.11
696          * wireless driver, and we should set up media for wireless.
697          */
698         for (i = 0; i < sc->ndis_oidcnt; i++)
699                 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
700                         sc->ndis_80211 = 1;
701                         break;
702                 }
703
704         if (sc->ndis_80211)
705                 error = ndis_80211attach(sc);
706         else
707                 error = ndis_ifattach(sc);
708
709 fail:
710         if (error) {
711                 ndis_detach(dev);
712                 return (error);
713         }
714
715         if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
716                 return (error);
717
718         DPRINTF(("attach done.\n"));
719         /* We're done talking to the NIC for now; halt it. */
720         ndis_halt_nic(sc);
721         DPRINTF(("halting done.\n"));
722
723         return (error);
724 }
725
726 static int
727 ndis_80211attach(struct ndis_softc *sc)
728 {
729         struct ieee80211com     *ic = &sc->ndis_ic;
730         ndis_80211_rates_ex     rates;
731         struct ndis_80211_nettype_list *ntl;
732         uint32_t                arg;
733         int                     mode, i, r, len, nonettypes = 1;
734         uint8_t                 bands[IEEE80211_MODE_BYTES] = { 0 };
735
736         callout_init(&sc->ndis_scan_callout, 1);
737
738         ic->ic_softc = sc;
739         ic->ic_ioctl = ndis_80211ioctl;
740         ic->ic_name = device_get_nameunit(sc->ndis_dev);
741         ic->ic_opmode = IEEE80211_M_STA;
742         ic->ic_phytype = IEEE80211_T_DS;
743         ic->ic_caps = IEEE80211_C_8023ENCAP |
744                 IEEE80211_C_STA | IEEE80211_C_IBSS;
745         setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
746         len = 0;
747         r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
748         if (r != ENOSPC)
749                 goto nonettypes;
750         ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
751         r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
752         if (r != 0) {
753                 free(ntl, M_DEVBUF);
754                 goto nonettypes;
755         }
756
757         for (i = 0; i < ntl->ntl_items; i++) {
758                 mode = ndis_nettype_mode(ntl->ntl_type[i]);
759                 if (mode) {
760                         nonettypes = 0;
761                         setbit(ic->ic_modecaps, mode);
762                         setbit(bands, mode);
763                 } else
764                         device_printf(sc->ndis_dev, "Unknown nettype %d\n",
765                             ntl->ntl_type[i]);
766         }
767         free(ntl, M_DEVBUF);
768 nonettypes:
769         /* Default to 11b channels if the card did not supply any */
770         if (nonettypes) {
771                 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
772                 setbit(bands, IEEE80211_MODE_11B);
773         }
774         len = sizeof(rates);
775         bzero((char *)&rates, len);
776         r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
777         if (r != 0)
778                 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
779         /*
780          * Since the supported rates only up to 8 can be supported,
781          * if this is not 802.11b we're just going to be faking it
782          * all up to heck.
783          */
784
785 #define TESTSETRATE(x, y)                                               \
786         do {                                                            \
787                 int                     i;                              \
788                 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) {   \
789                         if (ic->ic_sup_rates[x].rs_rates[i] == (y))     \
790                                 break;                                  \
791                 }                                                       \
792                 if (i == ic->ic_sup_rates[x].rs_nrates) {               \
793                         ic->ic_sup_rates[x].rs_rates[i] = (y);          \
794                         ic->ic_sup_rates[x].rs_nrates++;                \
795                 }                                                       \
796         } while (0)
797
798 #define SETRATE(x, y)   \
799         ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
800 #define INCRATE(x)      \
801         ic->ic_sup_rates[x].rs_nrates++
802
803         ic->ic_curmode = IEEE80211_MODE_AUTO;
804         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
805                 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
806         if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
807                 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
808         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
809                 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
810         for (i = 0; i < len; i++) {
811                 switch (rates[i] & IEEE80211_RATE_VAL) {
812                 case 2:
813                 case 4:
814                 case 11:
815                 case 10:
816                 case 22:
817                         if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
818                                 /* Lazy-init 802.11b. */
819                                 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
820                                 ic->ic_sup_rates[IEEE80211_MODE_11B].
821                                     rs_nrates = 0;
822                         }
823                         SETRATE(IEEE80211_MODE_11B, rates[i]);
824                         INCRATE(IEEE80211_MODE_11B);
825                         break;
826                 default:
827                         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
828                                 SETRATE(IEEE80211_MODE_11A, rates[i]);
829                                 INCRATE(IEEE80211_MODE_11A);
830                         }
831                         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
832                                 SETRATE(IEEE80211_MODE_11G, rates[i]);
833                                 INCRATE(IEEE80211_MODE_11G);
834                         }
835                         break;
836                 }
837         }
838
839         /*
840          * If the hardware supports 802.11g, it most
841          * likely supports 802.11b and all of the
842          * 802.11b and 802.11g speeds, so maybe we can
843          * just cheat here.  Just how in the heck do
844          * we detect turbo modes, though?
845          */
846         if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
847                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
848                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
849                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
850                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
851         }
852         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
853                 TESTSETRATE(IEEE80211_MODE_11G, 48);
854                 TESTSETRATE(IEEE80211_MODE_11G, 72);
855                 TESTSETRATE(IEEE80211_MODE_11G, 96);
856                 TESTSETRATE(IEEE80211_MODE_11G, 108);
857         }
858         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
859                 TESTSETRATE(IEEE80211_MODE_11A, 48);
860                 TESTSETRATE(IEEE80211_MODE_11A, 72);
861                 TESTSETRATE(IEEE80211_MODE_11A, 96);
862                 TESTSETRATE(IEEE80211_MODE_11A, 108);
863         }
864
865 #undef SETRATE
866 #undef INCRATE
867 #undef TESTSETRATE
868
869         ieee80211_init_channels(ic, NULL, bands);
870
871         /*
872          * To test for WPA support, we need to see if we can
873          * set AUTHENTICATION_MODE to WPA and read it back
874          * successfully.
875          */
876         i = sizeof(arg);
877         arg = NDIS_80211_AUTHMODE_WPA;
878         r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
879         if (r == 0) {
880                 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
881                 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
882                         ic->ic_caps |= IEEE80211_C_WPA;
883         }
884
885         /*
886          * To test for supported ciphers, we set each
887          * available encryption type in descending order.
888          * If ENC3 works, then we have WEP, TKIP and AES.
889          * If only ENC2 works, then we have WEP and TKIP.
890          * If only ENC1 works, then we have just WEP.
891          */
892         i = sizeof(arg);
893         arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
894         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
895         if (r == 0) {
896                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
897                                   |  IEEE80211_CRYPTO_TKIP
898                                   |  IEEE80211_CRYPTO_AES_CCM;
899                 goto got_crypto;
900         }
901         arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
902         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
903         if (r == 0) {
904                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
905                                   |  IEEE80211_CRYPTO_TKIP;
906                 goto got_crypto;
907         }
908         arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
909         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
910         if (r == 0)
911                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
912 got_crypto:
913         i = sizeof(arg);
914         r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
915         if (r == 0)
916                 ic->ic_caps |= IEEE80211_C_PMGT;
917
918         r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
919         if (r == 0)
920                 ic->ic_caps |= IEEE80211_C_TXPMGT;
921
922         /*
923          * Get station address from the driver.
924          */
925         len = sizeof(ic->ic_macaddr);
926         ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
927
928         ieee80211_ifattach(ic);
929         ic->ic_raw_xmit = ndis_raw_xmit;
930         ic->ic_scan_start = ndis_scan_start;
931         ic->ic_scan_end = ndis_scan_end;
932         ic->ic_set_channel = ndis_set_channel;
933         ic->ic_scan_curchan = ndis_scan_curchan;
934         ic->ic_scan_mindwell = ndis_scan_mindwell;
935         ic->ic_bsschan = IEEE80211_CHAN_ANYC;
936         ic->ic_vap_create = ndis_vap_create;
937         ic->ic_vap_delete = ndis_vap_delete;
938         ic->ic_update_mcast = ndis_update_mcast;
939         ic->ic_update_promisc = ndis_update_promisc;
940         ic->ic_transmit = ndis_80211transmit;
941         ic->ic_parent = ndis_80211parent;
942
943         if (bootverbose)
944                 ieee80211_announce(ic);
945
946         return (0);
947 }
948
949 static int
950 ndis_ifattach(struct ndis_softc *sc)
951 {
952         struct ifnet *ifp;
953         u_char eaddr[ETHER_ADDR_LEN];
954         int len;
955
956         ifp = if_alloc(IFT_ETHER);
957         if (ifp == NULL)
958                 return (ENOSPC);
959         sc->ifp = ifp;
960         ifp->if_softc = sc;
961
962         /* Check for task offload support. */
963         ndis_probe_offload(sc);
964
965         /*
966          * Get station address from the driver.
967          */
968         len = sizeof(eaddr);
969         ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
970
971         if_initname(ifp, device_get_name(sc->ndis_dev),
972             device_get_unit(sc->ndis_dev));
973         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
974         ifp->if_ioctl = ndis_ifioctl;
975         ifp->if_start = ndis_ifstart;
976         ifp->if_init = ndis_init;
977         ifp->if_baudrate = 10000000;
978         IFQ_SET_MAXLEN(&ifp->if_snd, 50);
979         ifp->if_snd.ifq_drv_maxlen = 25;
980         IFQ_SET_READY(&ifp->if_snd);
981         ifp->if_capenable = ifp->if_capabilities;
982         ifp->if_hwassist = sc->ndis_hwassist;
983
984         ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
985             ndis_ifmedia_sts);
986         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
987         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
988         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
989         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
990         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
991         ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
992         ether_ifattach(ifp, eaddr);
993
994         return (0);
995 }
996
997 static struct ieee80211vap *
998 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
999     enum ieee80211_opmode opmode, int flags,
1000     const uint8_t bssid[IEEE80211_ADDR_LEN],
1001     const uint8_t mac[IEEE80211_ADDR_LEN])
1002 {
1003         struct ndis_vap *nvp;
1004         struct ieee80211vap *vap;
1005
1006         if (!TAILQ_EMPTY(&ic->ic_vaps))         /* only one at a time */
1007                 return NULL;
1008         nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1009         vap = &nvp->vap;
1010         ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1011         /* override with driver methods */
1012         nvp->newstate = vap->iv_newstate;
1013         vap->iv_newstate = ndis_newstate;
1014
1015         /* complete setup */
1016         ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1017             mac);
1018         ic->ic_opmode = opmode;
1019         /* install key handing routines */
1020         vap->iv_key_set = ndis_add_key;
1021         vap->iv_key_delete = ndis_del_key;
1022         return vap;
1023 }
1024
1025 static void
1026 ndis_vap_delete(struct ieee80211vap *vap)
1027 {
1028         struct ndis_vap *nvp = NDIS_VAP(vap);
1029         struct ieee80211com *ic = vap->iv_ic;
1030         struct ndis_softc *sc = ic->ic_softc;
1031
1032         ndis_stop(sc);
1033         callout_drain(&sc->ndis_scan_callout);
1034         ieee80211_vap_detach(vap);
1035         free(nvp, M_80211_VAP);
1036 }
1037
1038 /*
1039  * Shutdown hardware and free up resources. This can be called any
1040  * time after the mutex has been initialized. It is called in both
1041  * the error case in attach and the normal detach case so it needs
1042  * to be careful about only freeing resources that have actually been
1043  * allocated.
1044  */
1045 int
1046 ndis_detach(device_t dev)
1047 {
1048         struct ifnet            *ifp;
1049         struct ndis_softc       *sc;
1050         driver_object           *drv;
1051
1052         sc = device_get_softc(dev);
1053         NDIS_LOCK(sc);
1054         if (!sc->ndis_80211)
1055                 ifp = sc->ifp;
1056         else
1057                 ifp = NULL;
1058         if (ifp != NULL)
1059                 ifp->if_flags &= ~IFF_UP;
1060         if (device_is_attached(dev)) {
1061                 NDIS_UNLOCK(sc);
1062                 ndis_stop(sc);
1063                 if (sc->ndis_80211)
1064                         ieee80211_ifdetach(&sc->ndis_ic);
1065                 else if (ifp != NULL)
1066                         ether_ifdetach(ifp);
1067         } else
1068                 NDIS_UNLOCK(sc);
1069
1070         if (sc->ndis_tickitem != NULL)
1071                 IoFreeWorkItem(sc->ndis_tickitem);
1072         if (sc->ndis_startitem != NULL)
1073                 IoFreeWorkItem(sc->ndis_startitem);
1074         if (sc->ndis_resetitem != NULL)
1075                 IoFreeWorkItem(sc->ndis_resetitem);
1076         if (sc->ndis_inputitem != NULL)
1077                 IoFreeWorkItem(sc->ndis_inputitem);
1078         if (sc->ndisusb_xferdoneitem != NULL)
1079                 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1080         if (sc->ndisusb_taskitem != NULL)
1081                 IoFreeWorkItem(sc->ndisusb_taskitem);
1082
1083         bus_generic_detach(dev);
1084         ndis_unload_driver(sc);
1085
1086         if (sc->ndis_irq)
1087                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1088         if (sc->ndis_res_io)
1089                 bus_release_resource(dev, SYS_RES_IOPORT,
1090                     sc->ndis_io_rid, sc->ndis_res_io);
1091         if (sc->ndis_res_mem)
1092                 bus_release_resource(dev, SYS_RES_MEMORY,
1093                     sc->ndis_mem_rid, sc->ndis_res_mem);
1094         if (sc->ndis_res_altmem)
1095                 bus_release_resource(dev, SYS_RES_MEMORY,
1096                     sc->ndis_altmem_rid, sc->ndis_res_altmem);
1097
1098         if (ifp != NULL)
1099                 if_free(ifp);
1100
1101         if (sc->ndis_iftype == PCMCIABus)
1102                 ndis_free_amem(sc);
1103
1104         if (sc->ndis_sc)
1105                 ndis_destroy_dma(sc);
1106
1107         if (sc->ndis_txarray)
1108                 free(sc->ndis_txarray, M_DEVBUF);
1109
1110         if (!sc->ndis_80211)
1111                 ifmedia_removeall(&sc->ifmedia);
1112
1113         if (sc->ndis_txpool != NULL)
1114                 NdisFreePacketPool(sc->ndis_txpool);
1115
1116         /* Destroy the PDO for this device. */
1117         
1118         if (sc->ndis_iftype == PCIBus)
1119                 drv = windrv_lookup(0, "PCI Bus");
1120         else if (sc->ndis_iftype == PCMCIABus)
1121                 drv = windrv_lookup(0, "PCCARD Bus");
1122         else
1123                 drv = windrv_lookup(0, "USB Bus");
1124         if (drv == NULL)
1125                 panic("couldn't find driver object");
1126         windrv_destroy_pdo(drv, dev);
1127
1128         if (sc->ndis_iftype == PCIBus)
1129                 bus_dma_tag_destroy(sc->ndis_parent_tag);
1130
1131         return (0);
1132 }
1133
1134 int
1135 ndis_suspend(dev)
1136         device_t                dev;
1137 {
1138         struct ndis_softc       *sc;
1139         struct ifnet            *ifp;
1140
1141         sc = device_get_softc(dev);
1142         ifp = sc->ifp;
1143
1144 #ifdef notdef
1145         if (NDIS_INITIALIZED(sc))
1146                 ndis_stop(sc);
1147 #endif
1148
1149         return (0);
1150 }
1151
1152 int
1153 ndis_resume(dev)
1154         device_t                dev;
1155 {
1156         struct ndis_softc       *sc;
1157         struct ifnet            *ifp;
1158
1159         sc = device_get_softc(dev);
1160         ifp = sc->ifp;
1161
1162         if (NDIS_INITIALIZED(sc))
1163                 ndis_init(sc);
1164
1165         return (0);
1166 }
1167
1168 /*
1169  * The following bunch of routines are here to support drivers that
1170  * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1171  * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1172  * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1173  * miniports.
1174  */
1175 static void
1176 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1177         ndis_handle             adapter;
1178         ndis_handle             ctx;
1179         char                    *addr;
1180         void                    *hdr;
1181         uint32_t                hdrlen;
1182         void                    *lookahead;
1183         uint32_t                lookaheadlen;
1184         uint32_t                pktlen;
1185 {
1186         ndis_miniport_block     *block;
1187         uint8_t                 irql = 0;
1188         uint32_t                status;
1189         ndis_buffer             *b;
1190         ndis_packet             *p;
1191         struct mbuf             *m;
1192         ndis_ethpriv            *priv;
1193
1194         block = adapter;
1195
1196         m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1197         if (m == NULL)
1198                 return;
1199
1200         /* Save the data provided to us so far. */
1201
1202         m->m_len = lookaheadlen + hdrlen;
1203         m->m_pkthdr.len = pktlen + hdrlen;
1204         m->m_next = NULL;
1205         m_copyback(m, 0, hdrlen, hdr);
1206         m_copyback(m, hdrlen, lookaheadlen, lookahead);
1207
1208         /* Now create a fake NDIS_PACKET to hold the data */
1209
1210         NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1211
1212         if (status != NDIS_STATUS_SUCCESS) {
1213                 m_freem(m);
1214                 return;
1215         }
1216
1217         p->np_m0 = m;
1218
1219         b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1220
1221         if (b == NULL) {
1222                 NdisFreePacket(p);
1223                 m_freem(m);
1224                 return;
1225         }
1226
1227         p->np_private.npp_head = p->np_private.npp_tail = b;
1228         p->np_private.npp_totlen = m->m_pkthdr.len;
1229
1230         /* Save the packet RX context somewhere. */
1231         priv = (ndis_ethpriv *)&p->np_protocolreserved;
1232         priv->nep_ctx = ctx;
1233
1234         if (!NDIS_SERIALIZED(block))
1235                 KeAcquireSpinLock(&block->nmb_lock, &irql);
1236
1237         InsertTailList((&block->nmb_packetlist), (&p->np_list));
1238
1239         if (!NDIS_SERIALIZED(block))
1240                 KeReleaseSpinLock(&block->nmb_lock, irql);
1241 }
1242
1243 /*
1244  * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1245  * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1246  * miniports.
1247  */
1248 static void
1249 ndis_rxeof_done(adapter)
1250         ndis_handle             adapter;
1251 {
1252         struct ndis_softc       *sc;
1253         ndis_miniport_block     *block;
1254
1255         block = adapter;
1256
1257         /* Schedule transfer/RX of queued packets. */
1258
1259         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1260
1261         KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1262 }
1263
1264 /*
1265  * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1266  */
1267 static void
1268 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1269         kdpc                    *dpc;
1270         ndis_handle             adapter;
1271         void                    *sysarg1;
1272         void                    *sysarg2;
1273 {
1274         ndis_miniport_block     *block;
1275         struct ndis_softc       *sc;
1276         ndis_packet             *p;
1277         list_entry              *l;
1278         uint32_t                status;
1279         ndis_ethpriv            *priv;
1280         struct ifnet            *ifp;
1281         struct mbuf             *m;
1282
1283         block = adapter;
1284         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1285         ifp = sc->ifp;
1286
1287         KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1288
1289         l = block->nmb_packetlist.nle_flink;
1290         while(!IsListEmpty(&block->nmb_packetlist)) {
1291                 l = RemoveHeadList((&block->nmb_packetlist));
1292                 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1293                 InitializeListHead((&p->np_list));
1294
1295                 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1296                 m = p->np_m0;
1297                 p->np_softc = sc;
1298                 p->np_m0 = NULL;
1299
1300                 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1301
1302                 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1303                     p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1304                     m->m_len, m->m_pkthdr.len - m->m_len);
1305
1306                 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1307
1308                 /*
1309                  * If status is NDIS_STATUS_PENDING, do nothing and
1310                  * wait for a callback to the ndis_rxeof_xfr_done()
1311                  * handler.
1312                  */
1313
1314                 m->m_len = m->m_pkthdr.len;
1315                 m->m_pkthdr.rcvif = ifp;
1316
1317                 if (status == NDIS_STATUS_SUCCESS) {
1318                         IoFreeMdl(p->np_private.npp_head);
1319                         NdisFreePacket(p);
1320                         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1321                         mbufq_enqueue(&sc->ndis_rxqueue, m);
1322                         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1323                         IoQueueWorkItem(sc->ndis_inputitem,
1324                             (io_workitem_func)ndis_inputtask_wrap,
1325                             WORKQUEUE_CRITICAL, sc);
1326                 }
1327
1328                 if (status == NDIS_STATUS_FAILURE)
1329                         m_freem(m);
1330
1331                 /* Advance to next packet */
1332                 l = block->nmb_packetlist.nle_flink;
1333         }
1334
1335         KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1336 }
1337
1338 /*
1339  * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1340  */
1341 static void
1342 ndis_rxeof_xfr_done(adapter, packet, status, len)
1343         ndis_handle             adapter;
1344         ndis_packet             *packet;
1345         uint32_t                status;
1346         uint32_t                len;
1347 {
1348         ndis_miniport_block     *block;
1349         struct ndis_softc       *sc;
1350         struct ifnet            *ifp;
1351         struct mbuf             *m;
1352
1353         block = adapter;
1354         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1355         ifp = sc->ifp;
1356
1357         m = packet->np_m0;
1358         IoFreeMdl(packet->np_private.npp_head);
1359         NdisFreePacket(packet);
1360
1361         if (status != NDIS_STATUS_SUCCESS) {
1362                 m_freem(m);
1363                 return;
1364         }
1365
1366         m->m_len = m->m_pkthdr.len;
1367         m->m_pkthdr.rcvif = ifp;
1368         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1369         mbufq_enqueue(&sc->ndis_rxqueue, m);
1370         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1371         IoQueueWorkItem(sc->ndis_inputitem,
1372             (io_workitem_func)ndis_inputtask_wrap,
1373             WORKQUEUE_CRITICAL, sc);
1374 }
1375 /*
1376  * A frame has been uploaded: pass the resulting mbuf chain up to
1377  * the higher level protocols.
1378  *
1379  * When handling received NDIS packets, the 'status' field in the
1380  * out-of-band portion of the ndis_packet has special meaning. In the
1381  * most common case, the underlying NDIS driver will set this field
1382  * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1383  * take possession of it. We then change the status field to
1384  * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1385  * and that we will return it at some point in the future via the
1386  * return packet handler.
1387  *
1388  * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1389  * this means the driver is running out of packet/buffer resources and
1390  * wants to maintain ownership of the packet. In this case, we have to
1391  * copy the packet data into local storage and let the driver keep the
1392  * packet.
1393  */
1394 static void
1395 ndis_rxeof(adapter, packets, pktcnt)
1396         ndis_handle             adapter;
1397         ndis_packet             **packets;
1398         uint32_t                pktcnt;
1399 {
1400         struct ndis_softc       *sc;
1401         ndis_miniport_block     *block;
1402         ndis_packet             *p;
1403         uint32_t                s;
1404         ndis_tcpip_csum         *csum;
1405         struct ifnet            *ifp;
1406         struct mbuf             *m0, *m;
1407         int                     i;
1408
1409         block = (ndis_miniport_block *)adapter;
1410         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1411         ifp = sc->ifp;
1412
1413         /*
1414          * There's a slim chance the driver may indicate some packets
1415          * before we're completely ready to handle them. If we detect this,
1416          * we need to return them to the miniport and ignore them.
1417          */
1418         if (!sc->ndis_running) {
1419                 for (i = 0; i < pktcnt; i++) {
1420                         p = packets[i];
1421                         if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1422                                 p->np_refcnt++;
1423                                 ndis_return_packet(p);
1424                         }
1425                 }
1426                 return;
1427         }
1428
1429         for (i = 0; i < pktcnt; i++) {
1430                 p = packets[i];
1431                 /* Stash the softc here so ptom can use it. */
1432                 p->np_softc = sc;
1433                 if (ndis_ptom(&m0, p)) {
1434                         device_printf(sc->ndis_dev, "ptom failed\n");
1435                         if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1436                                 ndis_return_packet(p);
1437                 } else {
1438 #ifdef notdef
1439                         if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1440                                 m = m_dup(m0, M_NOWAIT);
1441                                 /*
1442                                  * NOTE: we want to destroy the mbuf here, but
1443                                  * we don't actually want to return it to the
1444                                  * driver via the return packet handler. By
1445                                  * bumping np_refcnt, we can prevent the
1446                                  * ndis_return_packet() routine from actually
1447                                  * doing anything.
1448                                  */
1449                                 p->np_refcnt++;
1450                                 m_freem(m0);
1451                                 if (m == NULL)
1452                                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1453                                 else
1454                                         m0 = m;
1455                         } else
1456                                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457 #endif
1458                         m = m_dup(m0, M_NOWAIT);
1459                         if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1460                                 p->np_refcnt++;
1461                         else
1462                                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1463                         m_freem(m0);
1464                         if (m == NULL) {
1465                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1466                                 continue;
1467                         }
1468                         m0 = m;
1469                         m0->m_pkthdr.rcvif = ifp;
1470
1471                         /* Deal with checksum offload. */
1472
1473                         if (ifp->if_capenable & IFCAP_RXCSUM &&
1474                             p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1475                                 s = (uintptr_t)
1476                                     p->np_ext.npe_info[ndis_tcpipcsum_info];
1477                                 csum = (ndis_tcpip_csum *)&s;
1478                                 if (csum->u.ntc_rxflags &
1479                                     NDIS_RXCSUM_IP_PASSED)
1480                                         m0->m_pkthdr.csum_flags |=
1481                                             CSUM_IP_CHECKED|CSUM_IP_VALID;
1482                                 if (csum->u.ntc_rxflags &
1483                                     (NDIS_RXCSUM_TCP_PASSED |
1484                                     NDIS_RXCSUM_UDP_PASSED)) {
1485                                         m0->m_pkthdr.csum_flags |=
1486                                             CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1487                                         m0->m_pkthdr.csum_data = 0xFFFF;
1488                                 }
1489                         }
1490
1491                         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1492                         mbufq_enqueue(&sc->ndis_rxqueue, m0);
1493                         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1494                         IoQueueWorkItem(sc->ndis_inputitem,
1495                             (io_workitem_func)ndis_inputtask_wrap,
1496                             WORKQUEUE_CRITICAL, sc);
1497                 }
1498         }
1499 }
1500
1501 /*
1502  * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1503  * packets into the stack in order to avoid calling (*ifp->if_input)()
1504  * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1505  * 'dispatch level' per-cpu sleep lock).
1506  */
1507 static void
1508 ndis_inputtask(device_object *dobj, void *arg)
1509 {
1510         ndis_miniport_block     *block;
1511         struct ndis_softc       *sc = arg;
1512         struct mbuf             *m;
1513         uint8_t                 irql;
1514
1515         block = dobj->do_devext;
1516
1517         KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1518         while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1519                 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1520                 if ((sc->ndis_80211 != 0)) {
1521                         struct ieee80211com *ic = &sc->ndis_ic;
1522                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1523
1524                         if (vap != NULL)
1525                                 vap->iv_deliver_data(vap, vap->iv_bss, m);
1526                 } else {
1527                         struct ifnet *ifp = sc->ifp;
1528
1529                         (*ifp->if_input)(ifp, m);
1530                 }
1531                 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1532         }
1533         KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1534 }
1535
1536 /*
1537  * A frame was downloaded to the chip. It's safe for us to clean up
1538  * the list buffers.
1539  */
1540 static void
1541 ndis_txeof(adapter, packet, status)
1542         ndis_handle             adapter;
1543         ndis_packet             *packet;
1544         ndis_status             status;
1545
1546 {
1547         struct ndis_softc       *sc;
1548         ndis_miniport_block     *block;
1549         struct ifnet            *ifp;
1550         int                     idx;
1551         struct mbuf             *m;
1552
1553         block = (ndis_miniport_block *)adapter;
1554         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1555         ifp = sc->ifp;
1556
1557         m = packet->np_m0;
1558         idx = packet->np_txidx;
1559         if (sc->ndis_sc)
1560                 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1561
1562         ndis_free_packet(packet);
1563         m_freem(m);
1564
1565         NDIS_LOCK(sc);
1566         sc->ndis_txarray[idx] = NULL;
1567         sc->ndis_txpending++;
1568
1569         if (!sc->ndis_80211) {
1570                 struct ifnet            *ifp = sc->ifp;
1571                 if (status == NDIS_STATUS_SUCCESS)
1572                         if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1573                 else
1574                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1575                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1576         }
1577         sc->ndis_tx_timer = 0;
1578
1579         NDIS_UNLOCK(sc);
1580
1581         if (!sc->ndis_80211)
1582                 IoQueueWorkItem(sc->ndis_startitem,
1583                     (io_workitem_func)ndis_ifstarttask_wrap,
1584                     WORKQUEUE_CRITICAL, sc);
1585         DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1586 }
1587
1588 static void
1589 ndis_linksts(adapter, status, sbuf, slen)
1590         ndis_handle             adapter;
1591         ndis_status             status;
1592         void                    *sbuf;
1593         uint32_t                slen;
1594 {
1595         ndis_miniport_block     *block;
1596         struct ndis_softc       *sc;
1597
1598         block = adapter;
1599         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1600         sc->ndis_sts = status;
1601
1602         /* Event list is all full up, drop this one. */
1603
1604         NDIS_LOCK(sc);
1605         if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1606                 NDIS_UNLOCK(sc);
1607                 return;
1608         }
1609
1610         /* Cache the event. */
1611
1612         if (slen) {
1613                 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1614                     M_TEMP, M_NOWAIT);
1615                 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1616                         NDIS_UNLOCK(sc);
1617                         return;
1618                 }
1619                 bcopy((char *)sbuf,
1620                     sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1621         }
1622         sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1623         sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1624         NDIS_EVTINC(sc->ndis_evtpidx);
1625         NDIS_UNLOCK(sc);
1626 }
1627
1628 static void
1629 ndis_linksts_done(adapter)
1630         ndis_handle             adapter;
1631 {
1632         ndis_miniport_block     *block;
1633         struct ndis_softc       *sc;
1634         struct ifnet            *ifp;
1635
1636         block = adapter;
1637         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1638         ifp = sc->ifp;
1639
1640         if (!NDIS_INITIALIZED(sc))
1641                 return;
1642
1643         switch (sc->ndis_sts) {
1644         case NDIS_STATUS_MEDIA_CONNECT:
1645                 IoQueueWorkItem(sc->ndis_tickitem, 
1646                     (io_workitem_func)ndis_ticktask_wrap,
1647                     WORKQUEUE_CRITICAL, sc);
1648                 if (!sc->ndis_80211)
1649                         IoQueueWorkItem(sc->ndis_startitem,
1650                             (io_workitem_func)ndis_ifstarttask_wrap,
1651                             WORKQUEUE_CRITICAL, sc);
1652                 break;
1653         case NDIS_STATUS_MEDIA_DISCONNECT:
1654                 if (sc->ndis_link)
1655                         IoQueueWorkItem(sc->ndis_tickitem,
1656                             (io_workitem_func)ndis_ticktask_wrap,
1657                             WORKQUEUE_CRITICAL, sc);
1658                 break;
1659         default:
1660                 break;
1661         }
1662 }
1663
1664 static void
1665 ndis_tick(xsc)
1666         void                    *xsc;
1667 {
1668         struct ndis_softc       *sc;
1669
1670         sc = xsc;
1671
1672         if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1673                 IoQueueWorkItem(sc->ndis_tickitem,
1674                     (io_workitem_func)ndis_ticktask_wrap,
1675                     WORKQUEUE_CRITICAL, sc);
1676                 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1677         }
1678
1679         if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1680                 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1681                 device_printf(sc->ndis_dev, "watchdog timeout\n");
1682
1683                 IoQueueWorkItem(sc->ndis_resetitem,
1684                     (io_workitem_func)ndis_resettask_wrap,
1685                     WORKQUEUE_CRITICAL, sc);
1686                 if (!sc->ndis_80211)
1687                         IoQueueWorkItem(sc->ndis_startitem,
1688                             (io_workitem_func)ndis_ifstarttask_wrap,
1689                             WORKQUEUE_CRITICAL, sc);
1690         }
1691
1692         callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1693 }
1694
1695 static void
1696 ndis_ticktask(device_object *d, void *xsc)
1697 {
1698         struct ndis_softc       *sc = xsc;
1699         ndis_checkforhang_handler hangfunc;
1700         uint8_t                 rval;
1701
1702         NDIS_LOCK(sc);
1703         if (!NDIS_INITIALIZED(sc)) {
1704                 NDIS_UNLOCK(sc);
1705                 return;
1706         }
1707         NDIS_UNLOCK(sc);
1708
1709         hangfunc = sc->ndis_chars->nmc_checkhang_func;
1710
1711         if (hangfunc != NULL) {
1712                 rval = MSCALL1(hangfunc,
1713                     sc->ndis_block->nmb_miniportadapterctx);
1714                 if (rval == TRUE) {
1715                         ndis_reset_nic(sc);
1716                         return;
1717                 }
1718         }
1719
1720         NDIS_LOCK(sc);
1721         if (sc->ndis_link == 0 &&
1722             sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1723                 sc->ndis_link = 1;
1724                 if (sc->ndis_80211 != 0) {
1725                         struct ieee80211com *ic = &sc->ndis_ic;
1726                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1727
1728                         if (vap != NULL) {
1729                                 NDIS_UNLOCK(sc);
1730                                 ndis_getstate_80211(sc);
1731                                 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1732                                 NDIS_LOCK(sc);
1733                                 if_link_state_change(vap->iv_ifp,
1734                                     LINK_STATE_UP);
1735                         }
1736                 } else
1737                         if_link_state_change(sc->ifp, LINK_STATE_UP);
1738         }
1739
1740         if (sc->ndis_link == 1 &&
1741             sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1742                 sc->ndis_link = 0;
1743                 if (sc->ndis_80211 != 0) {
1744                         struct ieee80211com *ic = &sc->ndis_ic;
1745                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1746
1747                         if (vap != NULL) {
1748                                 NDIS_UNLOCK(sc);
1749                                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1750                                 NDIS_LOCK(sc);
1751                                 if_link_state_change(vap->iv_ifp,
1752                                     LINK_STATE_DOWN);
1753                         }
1754                 } else
1755                         if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1756         }
1757
1758         NDIS_UNLOCK(sc);
1759 }
1760
1761 static void
1762 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1763         void                    *arg;
1764         bus_dma_segment_t       *segs;
1765         int                     nseg;
1766         bus_size_t              mapsize;
1767         int                     error;
1768
1769 {
1770         struct ndis_sc_list     *sclist;
1771         int                     i;
1772
1773         if (error || arg == NULL)
1774                 return;
1775
1776         sclist = arg;
1777
1778         sclist->nsl_frags = nseg;
1779
1780         for (i = 0; i < nseg; i++) {
1781                 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1782                 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1783         }
1784 }
1785
1786 static int
1787 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1788         const struct ieee80211_bpf_params *params)
1789 {
1790         /* no support; just discard */
1791         m_freem(m);
1792         ieee80211_free_node(ni);
1793         return (0);
1794 }
1795
1796 static void
1797 ndis_update_mcast(struct ieee80211com *ic)
1798 {
1799        struct ndis_softc *sc = ic->ic_softc;
1800
1801        ndis_setmulti(sc);
1802 }
1803
1804 static void
1805 ndis_update_promisc(struct ieee80211com *ic)
1806 {
1807        /* not supported */
1808 }
1809
1810 static void
1811 ndis_ifstarttask(device_object *d, void *arg)
1812 {
1813         struct ndis_softc       *sc = arg;
1814         DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1815         if (sc->ndis_80211)
1816                 return;
1817
1818         struct ifnet            *ifp = sc->ifp;
1819         if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1820                 ndis_ifstart(ifp);
1821 }
1822
1823 /*
1824  * Main transmit routine. To make NDIS drivers happy, we need to
1825  * transform mbuf chains into NDIS packets and feed them to the
1826  * send packet routines. Most drivers allow you to send several
1827  * packets at once (up to the maxpkts limit). Unfortunately, rather
1828  * that accepting them in the form of a linked list, they expect
1829  * a contiguous array of pointers to packets.
1830  *
1831  * For those drivers which use the NDIS scatter/gather DMA mechanism,
1832  * we need to perform busdma work here. Those that use map registers
1833  * will do the mapping themselves on a buffer by buffer basis.
1834  */
1835 static void
1836 ndis_ifstart(struct ifnet *ifp)
1837 {
1838         struct ndis_softc       *sc;
1839         struct mbuf             *m = NULL;
1840         ndis_packet             **p0 = NULL, *p = NULL;
1841         ndis_tcpip_csum         *csum;
1842         int                     pcnt = 0, status;
1843
1844         sc = ifp->if_softc;
1845
1846         NDIS_LOCK(sc);
1847         if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1848                 NDIS_UNLOCK(sc);
1849                 return;
1850         }
1851
1852         p0 = &sc->ndis_txarray[sc->ndis_txidx];
1853
1854         while(sc->ndis_txpending) {
1855                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1856                 if (m == NULL)
1857                         break;
1858
1859                 NdisAllocatePacket(&status,
1860                     &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1861
1862                 if (status != NDIS_STATUS_SUCCESS)
1863                         break;
1864
1865                 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1866                         IFQ_DRV_PREPEND(&ifp->if_snd, m);
1867                         NDIS_UNLOCK(sc);
1868                         return;
1869                 }
1870
1871                 /*
1872                  * Save pointer to original mbuf
1873                  * so we can free it later.
1874                  */
1875
1876                 p = sc->ndis_txarray[sc->ndis_txidx];
1877                 p->np_txidx = sc->ndis_txidx;
1878                 p->np_m0 = m;
1879                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1880
1881                 /*
1882                  * Do scatter/gather processing, if driver requested it.
1883                  */
1884                 if (sc->ndis_sc) {
1885                         bus_dmamap_load_mbuf(sc->ndis_ttag,
1886                             sc->ndis_tmaps[sc->ndis_txidx], m,
1887                             ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1888                         bus_dmamap_sync(sc->ndis_ttag,
1889                             sc->ndis_tmaps[sc->ndis_txidx],
1890                             BUS_DMASYNC_PREREAD);
1891                         p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1892                 }
1893
1894                 /* Handle checksum offload. */
1895
1896                 if (ifp->if_capenable & IFCAP_TXCSUM &&
1897                     m->m_pkthdr.csum_flags) {
1898                         csum = (ndis_tcpip_csum *)
1899                                 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1900                         csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1901                         if (m->m_pkthdr.csum_flags & CSUM_IP)
1902                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1903                         if (m->m_pkthdr.csum_flags & CSUM_TCP)
1904                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1905                         if (m->m_pkthdr.csum_flags & CSUM_UDP)
1906                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1907                         p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1908                 }
1909
1910                 NDIS_INC(sc);
1911                 sc->ndis_txpending--;
1912
1913                 pcnt++;
1914
1915                 /*
1916                  * If there's a BPF listener, bounce a copy of this frame
1917                  * to him.
1918                  */
1919                 if (!sc->ndis_80211)    /* XXX handle 80211 */
1920                         BPF_MTAP(ifp, m);
1921
1922                 /*
1923                  * The array that p0 points to must appear contiguous,
1924                  * so we must not wrap past the end of sc->ndis_txarray[].
1925                  * If it looks like we're about to wrap, break out here
1926                  * so the this batch of packets can be transmitted, then
1927                  * wait for txeof to ask us to send the rest.
1928                  */
1929                 if (sc->ndis_txidx == 0)
1930                         break;
1931         }
1932
1933         if (pcnt == 0) {
1934                 NDIS_UNLOCK(sc);
1935                 return;
1936         }
1937
1938         if (sc->ndis_txpending == 0)
1939                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1940
1941         /*
1942          * Set a timeout in case the chip goes out to lunch.
1943          */
1944         sc->ndis_tx_timer = 5;
1945
1946         NDIS_UNLOCK(sc);
1947
1948         /*
1949          * According to NDIS documentation, if a driver exports
1950          * a MiniportSendPackets() routine, we prefer that over
1951          * a MiniportSend() routine (which sends just a single
1952          * packet).
1953          */
1954         if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1955                 ndis_send_packets(sc, p0, pcnt);
1956         else
1957                 ndis_send_packet(sc, p);
1958
1959         return;
1960 }
1961
1962 static int
1963 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1964 {
1965         struct ndis_softc *sc = ic->ic_softc;
1966         ndis_packet **p0 = NULL, *p = NULL;
1967         int status;
1968
1969         NDIS_LOCK(sc);
1970         if (!sc->ndis_link || !sc->ndis_running) {
1971                 NDIS_UNLOCK(sc);
1972                 return (ENXIO);
1973         }
1974
1975         if (sc->ndis_txpending == 0) {
1976                 NDIS_UNLOCK(sc);
1977                 return (ENOBUFS);
1978         }
1979
1980         p0 = &sc->ndis_txarray[sc->ndis_txidx];
1981
1982         NdisAllocatePacket(&status,
1983             &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1984
1985         if (status != NDIS_STATUS_SUCCESS) {
1986                 NDIS_UNLOCK(sc);
1987                 return (ENOBUFS);
1988         }
1989
1990         if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1991                 NDIS_UNLOCK(sc);
1992                 return (ENOBUFS);
1993         }
1994
1995         /*
1996          * Save pointer to original mbuf
1997          * so we can free it later.
1998          */
1999
2000         p = sc->ndis_txarray[sc->ndis_txidx];
2001         p->np_txidx = sc->ndis_txidx;
2002         p->np_m0 = m;
2003         p->np_oob.npo_status = NDIS_STATUS_PENDING;
2004
2005         /*
2006          * Do scatter/gather processing, if driver requested it.
2007          */
2008         if (sc->ndis_sc) {
2009                 bus_dmamap_load_mbuf(sc->ndis_ttag,
2010                     sc->ndis_tmaps[sc->ndis_txidx], m,
2011                     ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2012                 bus_dmamap_sync(sc->ndis_ttag,
2013                     sc->ndis_tmaps[sc->ndis_txidx],
2014                     BUS_DMASYNC_PREREAD);
2015                 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2016         }
2017
2018         NDIS_INC(sc);
2019         sc->ndis_txpending--;
2020
2021         /*
2022          * Set a timeout in case the chip goes out to lunch.
2023          */
2024         sc->ndis_tx_timer = 5;
2025         NDIS_UNLOCK(sc);
2026
2027         /*
2028          * According to NDIS documentation, if a driver exports
2029          * a MiniportSendPackets() routine, we prefer that over
2030          * a MiniportSend() routine (which sends just a single
2031          * packet).
2032          */
2033         if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2034                 ndis_send_packets(sc, p0, 1);
2035         else
2036                 ndis_send_packet(sc, p);
2037
2038         return (0);
2039 }
2040
2041 static void
2042 ndis_80211parent(struct ieee80211com *ic)
2043 {
2044         struct ndis_softc *sc = ic->ic_softc;
2045
2046         /*NDIS_LOCK(sc);*/
2047         if (ic->ic_nrunning > 0) {
2048                 if (!sc->ndis_running)
2049                         ndis_init(sc);
2050         } else if (sc->ndis_running)
2051                 ndis_stop(sc);
2052         /*NDIS_UNLOCK(sc);*/
2053 }
2054
2055 static void
2056 ndis_init(void *xsc)
2057 {
2058         struct ndis_softc       *sc = xsc;
2059         int                     i, len, error;
2060
2061         /*
2062          * Avoid reintializing the link unnecessarily.
2063          * This should be dealt with in a better way by
2064          * fixing the upper layer modules so they don't
2065          * call ifp->if_init() quite as often.
2066          */
2067         if (sc->ndis_link)
2068                 return;
2069
2070         /*
2071          * Cancel pending I/O and free all RX/TX buffers.
2072          */
2073         ndis_stop(sc);
2074
2075         if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2076                 error = ndis_init_nic(sc);
2077                 if (error != 0) {
2078                         device_printf(sc->ndis_dev,
2079                             "failed to initialize the device: %d\n", error);
2080                         return;
2081                 }
2082         }
2083
2084         /* Program the packet filter */
2085         sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2086             NDIS_PACKET_TYPE_BROADCAST;
2087
2088         if (sc->ndis_80211) {
2089                 struct ieee80211com *ic = &sc->ndis_ic;
2090
2091                 if (ic->ic_promisc > 0)
2092                         sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2093         } else {
2094                 struct ifnet *ifp = sc->ifp;
2095
2096                 if (ifp->if_flags & IFF_PROMISC)
2097                         sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2098         }
2099
2100         len = sizeof(sc->ndis_filter);
2101
2102         error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2103             &sc->ndis_filter, &len);
2104
2105         if (error)
2106                 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2107
2108         /*
2109          * Set lookahead.
2110          */
2111         if (sc->ndis_80211)
2112                 i = ETHERMTU;
2113         else
2114                 i = sc->ifp->if_mtu;
2115         len = sizeof(i);
2116         ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2117
2118         /*
2119          * Program the multicast filter, if necessary.
2120          */
2121         ndis_setmulti(sc);
2122
2123         /* Setup task offload. */
2124         ndis_set_offload(sc);
2125
2126         NDIS_LOCK(sc);
2127
2128         sc->ndis_txidx = 0;
2129         sc->ndis_txpending = sc->ndis_maxpkts;
2130         sc->ndis_link = 0;
2131
2132         if (!sc->ndis_80211) {
2133                 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2134                 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2135                 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2136         }
2137
2138         sc->ndis_tx_timer = 0;
2139
2140         /*
2141          * Some drivers don't set this value. The NDIS spec says
2142          * the default checkforhang timeout is "approximately 2
2143          * seconds." We use 3 seconds, because it seems for some
2144          * drivers, exactly 2 seconds is too fast.
2145          */
2146         if (sc->ndis_block->nmb_checkforhangsecs == 0)
2147                 sc->ndis_block->nmb_checkforhangsecs = 3;
2148
2149         sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2150         callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2151         sc->ndis_running = 1;
2152         NDIS_UNLOCK(sc);
2153
2154         /* XXX force handling */
2155         if (sc->ndis_80211)
2156                 ieee80211_start_all(&sc->ndis_ic);      /* start all vap's */
2157 }
2158
2159 /*
2160  * Set media options.
2161  */
2162 static int
2163 ndis_ifmedia_upd(ifp)
2164         struct ifnet            *ifp;
2165 {
2166         struct ndis_softc               *sc;
2167
2168         sc = ifp->if_softc;
2169
2170         if (NDIS_INITIALIZED(sc))
2171                 ndis_init(sc);
2172
2173         return (0);
2174 }
2175
2176 /*
2177  * Report current media status.
2178  */
2179 static void
2180 ndis_ifmedia_sts(ifp, ifmr)
2181         struct ifnet            *ifp;
2182         struct ifmediareq       *ifmr;
2183 {
2184         struct ndis_softc       *sc;
2185         uint32_t                media_info;
2186         ndis_media_state        linkstate;
2187         int                     len;
2188
2189         ifmr->ifm_status = IFM_AVALID;
2190         ifmr->ifm_active = IFM_ETHER;
2191         sc = ifp->if_softc;
2192
2193         if (!NDIS_INITIALIZED(sc))
2194                 return;
2195
2196         len = sizeof(linkstate);
2197         ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2198             (void *)&linkstate, &len);
2199
2200         len = sizeof(media_info);
2201         ndis_get_info(sc, OID_GEN_LINK_SPEED,
2202             (void *)&media_info, &len);
2203
2204         if (linkstate == nmc_connected)
2205                 ifmr->ifm_status |= IFM_ACTIVE;
2206
2207         switch (media_info) {
2208         case 100000:
2209                 ifmr->ifm_active |= IFM_10_T;
2210                 break;
2211         case 1000000:
2212                 ifmr->ifm_active |= IFM_100_TX;
2213                 break;
2214         case 10000000:
2215                 ifmr->ifm_active |= IFM_1000_T;
2216                 break;
2217         default:
2218                 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2219                 break;
2220         }
2221 }
2222
2223 static int
2224 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2225 {
2226         struct ieee80211com     *ic = &sc->ndis_ic;
2227         int                     rval = 0, len;
2228         uint32_t                arg, save;
2229
2230         len = sizeof(arg);
2231
2232         if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2233                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2234                         return (ENOTSUP);
2235                 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2236         }
2237
2238         if (cipher == WPA_CSE_TKIP) {
2239                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2240                         return (ENOTSUP);
2241                 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2242         }
2243
2244         if (cipher == WPA_CSE_CCMP) {
2245                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2246                         return (ENOTSUP);
2247                 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2248         }
2249
2250         DPRINTF(("Setting cipher to %d\n", arg));
2251         save = arg;
2252         rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2253
2254         if (rval)
2255                 return (rval);
2256
2257         /* Check that the cipher was set correctly. */
2258
2259         len = sizeof(save);
2260         rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2261
2262         if (rval != 0 || arg != save)
2263                 return (ENODEV);
2264
2265         return (0);
2266 }
2267
2268 /*
2269  * WPA is hairy to set up. Do the work in a separate routine
2270  * so we don't clutter the setstate function too much.
2271  * Important yet undocumented fact: first we have to set the
2272  * authentication mode, _then_ we enable the ciphers. If one
2273  * of the WPA authentication modes isn't enabled, the driver
2274  * might not permit the TKIP or AES ciphers to be selected.
2275  */
2276 static int
2277 ndis_set_wpa(sc, ie, ielen)
2278         struct ndis_softc       *sc;
2279         void                    *ie;
2280         int                     ielen;
2281 {
2282         struct ieee80211_ie_wpa *w;
2283         struct ndis_ie          *n;
2284         char                    *pos;
2285         uint32_t                arg;
2286         int                     i;
2287
2288         /*
2289          * Apparently, the only way for us to know what ciphers
2290          * and key management/authentication mode to use is for
2291          * us to inspect the optional information element (IE)
2292          * stored in the 802.11 state machine. This IE should be
2293          * supplied by the WPA supplicant.
2294          */
2295
2296         w = (struct ieee80211_ie_wpa *)ie;
2297
2298         /* Check for the right kind of IE. */
2299         if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2300                 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2301                 return (EINVAL);
2302         }
2303
2304         /* Skip over the ucast cipher OIDs. */
2305         pos = (char *)&w->wpa_uciphers[0];
2306         pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2307
2308         /* Skip over the authmode count. */
2309         pos += sizeof(u_int16_t);
2310
2311         /*
2312          * Check for the authentication modes. I'm
2313          * pretty sure there's only supposed to be one.
2314          */
2315
2316         n = (struct ndis_ie *)pos;
2317         if (n->ni_val == WPA_ASE_NONE)
2318                 arg = NDIS_80211_AUTHMODE_WPANONE;
2319
2320         if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2321                 arg = NDIS_80211_AUTHMODE_WPA;
2322
2323         if (n->ni_val == WPA_ASE_8021X_PSK)
2324                 arg = NDIS_80211_AUTHMODE_WPAPSK;
2325
2326         DPRINTF(("Setting WPA auth mode to %d\n", arg));
2327         i = sizeof(arg);
2328         if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2329                 return (ENOTSUP);
2330         i = sizeof(arg);
2331         ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2332
2333         /* Now configure the desired ciphers. */
2334
2335         /* First, set up the multicast group cipher. */
2336         n = (struct ndis_ie *)&w->wpa_mcipher[0];
2337
2338         if (ndis_set_cipher(sc, n->ni_val))
2339                 return (ENOTSUP);
2340
2341         /* Now start looking around for the unicast ciphers. */
2342         pos = (char *)&w->wpa_uciphers[0];
2343         n = (struct ndis_ie *)pos;
2344
2345         for (i = 0; i < w->wpa_uciphercnt; i++) {
2346                 if (ndis_set_cipher(sc, n->ni_val))
2347                         return (ENOTSUP);
2348                 n++;
2349         }
2350
2351         return (0);
2352 }
2353
2354 static void
2355 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2356 {
2357         struct ieee80211vap *vap = ifp->if_softc;
2358         struct ndis_softc *sc = vap->iv_ic->ic_softc;
2359         uint32_t txrate;
2360         int len;
2361
2362         if (!NDIS_INITIALIZED(sc))
2363                 return;
2364
2365         len = sizeof(txrate);
2366         if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2367                 vap->iv_bss->ni_txrate = txrate / 5000;
2368         ieee80211_media_status(ifp, imr);
2369 }
2370
2371 static void
2372 ndis_setstate_80211(struct ndis_softc *sc)
2373 {
2374         struct ieee80211com     *ic = &sc->ndis_ic;
2375         struct ieee80211vap     *vap = TAILQ_FIRST(&ic->ic_vaps);
2376         ndis_80211_macaddr      bssid;
2377         ndis_80211_config       config;
2378         int                     rval = 0, len;
2379         uint32_t                arg;
2380
2381         if (!NDIS_INITIALIZED(sc)) {
2382                 DPRINTF(("%s: NDIS not initialized\n", __func__));
2383                 return;
2384         }
2385
2386         /* Disassociate and turn off radio. */
2387         len = sizeof(arg);
2388         arg = 1;
2389         ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2390
2391         /* Set network infrastructure mode. */
2392
2393         len = sizeof(arg);
2394         if (ic->ic_opmode == IEEE80211_M_IBSS)
2395                 arg = NDIS_80211_NET_INFRA_IBSS;
2396         else
2397                 arg = NDIS_80211_NET_INFRA_BSS;
2398
2399         rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2400
2401         if (rval)
2402                 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2403
2404         /* Set power management */
2405         len = sizeof(arg);
2406         if (vap->iv_flags & IEEE80211_F_PMGTON)
2407                 arg = NDIS_80211_POWERMODE_FAST_PSP;
2408         else
2409                 arg = NDIS_80211_POWERMODE_CAM;
2410         ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2411
2412         /* Set TX power */
2413         if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2414             ic->ic_txpowlimit < nitems(dBm2mW)) {
2415                 arg = dBm2mW[ic->ic_txpowlimit];
2416                 len = sizeof(arg);
2417                 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2418         }
2419
2420         /*
2421          * Default encryption mode to off, authentication
2422          * to open and privacy to 'accept everything.'
2423          */
2424         len = sizeof(arg);
2425         arg = NDIS_80211_WEPSTAT_DISABLED;
2426         ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2427
2428         len = sizeof(arg);
2429         arg = NDIS_80211_AUTHMODE_OPEN;
2430         ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2431
2432         /*
2433          * Note that OID_802_11_PRIVACY_FILTER is optional:
2434          * not all drivers implement it.
2435          */
2436         len = sizeof(arg);
2437         arg = NDIS_80211_PRIVFILT_8021XWEP;
2438         ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2439
2440         len = sizeof(config);
2441         bzero((char *)&config, len);
2442         config.nc_length = len;
2443         config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2444         rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len); 
2445
2446         /*
2447          * Some drivers expect us to initialize these values, so
2448          * provide some defaults.
2449          */
2450
2451         if (config.nc_beaconperiod == 0)
2452                 config.nc_beaconperiod = 100;
2453         if (config.nc_atimwin == 0)
2454                 config.nc_atimwin = 100;
2455         if (config.nc_fhconfig.ncf_dwelltime == 0)
2456                 config.nc_fhconfig.ncf_dwelltime = 200;
2457         if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) { 
2458                 int chan, chanflag;
2459
2460                 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2461                 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2462                     IEEE80211_CHAN_5GHZ;
2463                 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2464                         config.nc_dsconfig =
2465                                 ic->ic_bsschan->ic_freq * 1000;
2466                         len = sizeof(config);
2467                         config.nc_length = len;
2468                         config.nc_fhconfig.ncf_length =
2469                             sizeof(ndis_80211_config_fh);
2470                         DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2471                         rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2472                             &config, &len);
2473                         if (rval)
2474                                 device_printf(sc->ndis_dev, "couldn't change "
2475                                     "DS config to %ukHz: %d\n",
2476                                     config.nc_dsconfig, rval);
2477                 }
2478         } else if (rval)
2479                 device_printf(sc->ndis_dev, "couldn't retrieve "
2480                     "channel info: %d\n", rval);
2481
2482         /* Set the BSSID to our value so the driver doesn't associate */
2483         len = IEEE80211_ADDR_LEN;
2484         bcopy(vap->iv_myaddr, bssid, len);
2485         DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2486         rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2487         if (rval)
2488                 device_printf(sc->ndis_dev,
2489                     "setting BSSID failed: %d\n", rval);
2490 }
2491
2492 static void
2493 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2494 {
2495         struct ieee80211_node   *ni = vap->iv_bss;
2496         ndis_80211_ssid         ssid;
2497         ndis_80211_macaddr      bssid;
2498         ndis_80211_wep          wep;
2499         int                     i, rval = 0, len, error;
2500         uint32_t                arg;
2501
2502         if (!NDIS_INITIALIZED(sc)) {
2503                 DPRINTF(("%s: NDIS not initialized\n", __func__));
2504                 return;
2505         }
2506
2507         /* Initial setup */
2508         ndis_setstate_80211(sc);
2509
2510         /* Set network infrastructure mode. */
2511
2512         len = sizeof(arg);
2513         if (vap->iv_opmode == IEEE80211_M_IBSS)
2514                 arg = NDIS_80211_NET_INFRA_IBSS;
2515         else
2516                 arg = NDIS_80211_NET_INFRA_BSS;
2517
2518         rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2519
2520         if (rval)
2521                 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2522
2523         /* Set RTS threshold */
2524
2525         len = sizeof(arg);
2526         arg = vap->iv_rtsthreshold;
2527         ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2528
2529         /* Set fragmentation threshold */
2530
2531         len = sizeof(arg);
2532         arg = vap->iv_fragthreshold;
2533         ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2534
2535         /* Set WEP */
2536
2537         if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2538             !(vap->iv_flags & IEEE80211_F_WPA)) {
2539                 int keys_set = 0;
2540
2541                 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2542                         len = sizeof(arg);
2543                         arg = NDIS_80211_AUTHMODE_SHARED;
2544                         DPRINTF(("Setting shared auth\n"));
2545                         ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2546                             &arg, &len);
2547                 }
2548                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2549                         if (vap->iv_nw_keys[i].wk_keylen) {
2550                                 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2551                                     IEEE80211_CIPHER_WEP)
2552                                         continue;
2553                                 bzero((char *)&wep, sizeof(wep));
2554                                 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2555
2556                                 /*
2557                                  * 5, 13 and 16 are the only valid
2558                                  * key lengths. Anything in between
2559                                  * will be zero padded out to the
2560                                  * next highest boundary.
2561                                  */
2562                                 if (vap->iv_nw_keys[i].wk_keylen < 5)
2563                                         wep.nw_keylen = 5;
2564                                 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2565                                      vap->iv_nw_keys[i].wk_keylen < 13)
2566                                         wep.nw_keylen = 13;
2567                                 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2568                                      vap->iv_nw_keys[i].wk_keylen < 16)
2569                                         wep.nw_keylen = 16;
2570
2571                                 wep.nw_keyidx = i;
2572                                 wep.nw_length = (sizeof(uint32_t) * 3)
2573                                     + wep.nw_keylen;
2574                                 if (i == vap->iv_def_txkey)
2575                                         wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2576                                 bcopy(vap->iv_nw_keys[i].wk_key,
2577                                     wep.nw_keydata, wep.nw_length);
2578                                 len = sizeof(wep);
2579                                 DPRINTF(("Setting WEP key %d\n", i));
2580                                 rval = ndis_set_info(sc,
2581                                     OID_802_11_ADD_WEP, &wep, &len);
2582                                 if (rval)
2583                                         device_printf(sc->ndis_dev,
2584                                             "set wepkey failed: %d\n", rval);
2585                                 keys_set++;
2586                         }
2587                 }
2588                 if (keys_set) {
2589                         DPRINTF(("Setting WEP on\n"));
2590                         arg = NDIS_80211_WEPSTAT_ENABLED;
2591                         len = sizeof(arg);
2592                         rval = ndis_set_info(sc,
2593                             OID_802_11_WEP_STATUS, &arg, &len);
2594                         if (rval)
2595                                 device_printf(sc->ndis_dev,
2596                                     "enable WEP failed: %d\n", rval);
2597                         if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2598                                 arg = NDIS_80211_PRIVFILT_8021XWEP;
2599                         else
2600                                 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2601
2602                         len = sizeof(arg);
2603                         ndis_set_info(sc,
2604                             OID_802_11_PRIVACY_FILTER, &arg, &len);
2605                 }
2606         }
2607
2608         /* Set up WPA. */
2609         if ((vap->iv_flags & IEEE80211_F_WPA) &&
2610             vap->iv_appie_assocreq != NULL) {
2611                 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2612                 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2613                 if (error != 0)
2614                         device_printf(sc->ndis_dev, "WPA setup failed\n");
2615         }
2616
2617 #ifdef notyet
2618         /* Set network type. */
2619
2620         arg = 0;
2621
2622         switch (vap->iv_curmode) {
2623         case IEEE80211_MODE_11A:
2624                 arg = NDIS_80211_NETTYPE_11OFDM5;
2625                 break;
2626         case IEEE80211_MODE_11B:
2627                 arg = NDIS_80211_NETTYPE_11DS;
2628                 break;
2629         case IEEE80211_MODE_11G:
2630                 arg = NDIS_80211_NETTYPE_11OFDM24;
2631                 break;
2632         default:
2633                 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2634                     vap->iv_curmode);
2635         }
2636
2637         if (arg) {
2638                 DPRINTF(("Setting network type to %d\n", arg));
2639                 len = sizeof(arg);
2640                 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2641                     &arg, &len);
2642                 if (rval)
2643                         device_printf(sc->ndis_dev,
2644                             "set nettype failed: %d\n", rval);
2645         }
2646 #endif
2647
2648         /*
2649          * If the user selected a specific BSSID, try
2650          * to use that one. This is useful in the case where
2651          * there are several APs in range with the same network
2652          * name. To delete the BSSID, we use the broadcast
2653          * address as the BSSID.
2654          * Note that some drivers seem to allow setting a BSSID
2655          * in ad-hoc mode, which has the effect of forcing the
2656          * NIC to create an ad-hoc cell with a specific BSSID,
2657          * instead of a randomly chosen one. However, the net80211
2658          * code makes the assumtion that the BSSID setting is invalid
2659          * when you're in ad-hoc mode, so we don't allow that here.
2660          */
2661
2662         len = IEEE80211_ADDR_LEN;
2663         if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2664             vap->iv_opmode != IEEE80211_M_IBSS)
2665                 bcopy(ni->ni_bssid, bssid, len);
2666         else
2667                 bcopy(ieee80211broadcastaddr, bssid, len);
2668
2669         DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2670         rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2671         if (rval)
2672                 device_printf(sc->ndis_dev,
2673                     "setting BSSID failed: %d\n", rval);
2674
2675         /* Set SSID -- always do this last. */
2676
2677 #ifdef NDIS_DEBUG
2678         if (ndis_debug > 0) {
2679                 printf("Setting ESSID to ");
2680                 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2681                 printf("\n");
2682         }
2683 #endif
2684
2685         len = sizeof(ssid);
2686         bzero((char *)&ssid, len);
2687         ssid.ns_ssidlen = ni->ni_esslen;
2688         if (ssid.ns_ssidlen == 0) {
2689                 ssid.ns_ssidlen = 1;
2690         } else
2691                 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2692
2693         rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2694
2695         if (rval)
2696                 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2697
2698         return;
2699 }
2700
2701 static int
2702 ndis_get_bssid_list(sc, bl)
2703         struct ndis_softc       *sc;
2704         ndis_80211_bssid_list_ex        **bl;
2705 {
2706         int     len, error;
2707
2708         len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2709         *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2710         if (*bl == NULL)
2711                 return (ENOMEM);
2712
2713         error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2714         if (error == ENOSPC) {
2715                 free(*bl, M_DEVBUF);
2716                 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2717                 if (*bl == NULL)
2718                         return (ENOMEM);
2719
2720                 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2721         }
2722         if (error) {
2723                 DPRINTF(("%s: failed to read\n", __func__));
2724                 free(*bl, M_DEVBUF);
2725                 return (error);
2726         }
2727
2728         return (0);
2729 }
2730
2731 static int
2732 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2733 {
2734         struct ieee80211com *ic = &sc->ndis_ic;
2735         struct ieee80211vap     *vap;
2736         struct ieee80211_node   *ni;
2737         ndis_80211_bssid_list_ex        *bl;
2738         ndis_wlan_bssid_ex      *bs;
2739         ndis_80211_macaddr      bssid;
2740         int                     i, len, error;
2741
2742         if (!sc->ndis_link)
2743                 return (ENOENT);
2744
2745         len = sizeof(bssid);
2746         error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2747         if (error) {
2748                 device_printf(sc->ndis_dev, "failed to get bssid\n");
2749                 return (ENOENT);
2750         }
2751
2752         vap = TAILQ_FIRST(&ic->ic_vaps);
2753         ni = vap->iv_bss;
2754
2755         error = ndis_get_bssid_list(sc, &bl);
2756         if (error)
2757                 return (error);
2758
2759         bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2760         for (i = 0; i < bl->nblx_items; i++) {
2761                 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2762                         *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2763                         if (*assoc == NULL) {
2764                                 free(bl, M_TEMP);
2765                                 return (ENOMEM);
2766                         }
2767                         bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2768                         free(bl, M_TEMP);
2769                         if (ic->ic_opmode == IEEE80211_M_STA)
2770                                 ni->ni_associd = 1 | 0xc000; /* fake associd */
2771                         return (0);
2772                 }
2773                 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2774         }
2775
2776         free(bl, M_TEMP);
2777         return (ENOENT);
2778 }
2779
2780 static void
2781 ndis_getstate_80211(struct ndis_softc *sc)
2782 {
2783         struct ieee80211com     *ic = &sc->ndis_ic;
2784         struct ieee80211vap     *vap = TAILQ_FIRST(&ic->ic_vaps);
2785         struct ieee80211_node   *ni = vap->iv_bss;
2786         ndis_wlan_bssid_ex      *bs;
2787         int                     rval, len, i = 0;
2788         int                     chanflag;
2789         uint32_t                arg;
2790
2791         if (!NDIS_INITIALIZED(sc))
2792                 return;
2793
2794         if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2795                 return;
2796
2797         /* We're associated, retrieve info on the current bssid. */
2798         ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2799         chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2800         IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2801
2802         /* Get SSID from current association info. */
2803         bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2804             bs->nwbx_ssid.ns_ssidlen);
2805         ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2806
2807         if (ic->ic_caps & IEEE80211_C_PMGT) {
2808                 len = sizeof(arg);
2809                 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2810
2811                 if (rval)
2812                         device_printf(sc->ndis_dev,
2813                             "get power mode failed: %d\n", rval);
2814                 if (arg == NDIS_80211_POWERMODE_CAM)
2815                         vap->iv_flags &= ~IEEE80211_F_PMGTON;
2816                 else
2817                         vap->iv_flags |= IEEE80211_F_PMGTON;
2818         }
2819
2820         /* Get TX power */
2821         if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2822                 len = sizeof(arg);
2823                 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2824                 for (i = 0; i < nitems(dBm2mW); i++)
2825                         if (dBm2mW[i] >= arg)
2826                                 break;
2827                 ic->ic_txpowlimit = i;
2828         }
2829
2830         /*
2831          * Use the current association information to reflect
2832          * what channel we're on.
2833          */
2834         ic->ic_curchan = ieee80211_find_channel(ic,
2835             bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2836         if (ic->ic_curchan == NULL)
2837                 ic->ic_curchan = &ic->ic_channels[0];
2838         ni->ni_chan = ic->ic_curchan;
2839         ic->ic_bsschan = ic->ic_curchan;
2840
2841         free(bs, M_TEMP);
2842
2843         /*
2844          * Determine current authentication mode.
2845          */
2846         len = sizeof(arg);
2847         rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2848         if (rval)
2849                 device_printf(sc->ndis_dev,
2850                     "get authmode status failed: %d\n", rval);
2851         else {
2852                 vap->iv_flags &= ~IEEE80211_F_WPA;
2853                 switch (arg) {
2854                 case NDIS_80211_AUTHMODE_OPEN:
2855                         ni->ni_authmode = IEEE80211_AUTH_OPEN;
2856                         break;
2857                 case NDIS_80211_AUTHMODE_SHARED:
2858                         ni->ni_authmode = IEEE80211_AUTH_SHARED;
2859                         break;
2860                 case NDIS_80211_AUTHMODE_AUTO:
2861                         ni->ni_authmode = IEEE80211_AUTH_AUTO;
2862                         break;
2863                 case NDIS_80211_AUTHMODE_WPA:
2864                 case NDIS_80211_AUTHMODE_WPAPSK:
2865                 case NDIS_80211_AUTHMODE_WPANONE:
2866                         ni->ni_authmode = IEEE80211_AUTH_WPA;
2867                         vap->iv_flags |= IEEE80211_F_WPA1;
2868                         break;
2869                 case NDIS_80211_AUTHMODE_WPA2:
2870                 case NDIS_80211_AUTHMODE_WPA2PSK:
2871                         ni->ni_authmode = IEEE80211_AUTH_WPA;
2872                         vap->iv_flags |= IEEE80211_F_WPA2;
2873                         break;
2874                 default:
2875                         ni->ni_authmode = IEEE80211_AUTH_NONE;
2876                         break;
2877                 }
2878         }
2879
2880         len = sizeof(arg);
2881         rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2882
2883         if (rval)
2884                 device_printf(sc->ndis_dev,
2885                     "get wep status failed: %d\n", rval);
2886
2887         if (arg == NDIS_80211_WEPSTAT_ENABLED)
2888                 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2889         else
2890                 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2891 }
2892
2893 static int
2894 ndis_ifioctl(ifp, command, data)
2895         struct ifnet            *ifp;
2896         u_long                  command;
2897         caddr_t                 data;
2898 {
2899         struct ndis_softc       *sc = ifp->if_softc;
2900         struct ifreq            *ifr = (struct ifreq *) data;
2901         int                     i, error = 0;
2902
2903         /*NDIS_LOCK(sc);*/
2904
2905         switch (command) {
2906         case SIOCSIFFLAGS:
2907                 if (ifp->if_flags & IFF_UP) {
2908                         if (sc->ndis_running &&
2909                             ifp->if_flags & IFF_PROMISC &&
2910                             !(sc->ndis_if_flags & IFF_PROMISC)) {
2911                                 sc->ndis_filter |=
2912                                     NDIS_PACKET_TYPE_PROMISCUOUS;
2913                                 i = sizeof(sc->ndis_filter);
2914                                 error = ndis_set_info(sc,
2915                                     OID_GEN_CURRENT_PACKET_FILTER,
2916                                     &sc->ndis_filter, &i);
2917                         } else if (sc->ndis_running &&
2918                             !(ifp->if_flags & IFF_PROMISC) &&
2919                             sc->ndis_if_flags & IFF_PROMISC) {
2920                                 sc->ndis_filter &=
2921                                     ~NDIS_PACKET_TYPE_PROMISCUOUS;
2922                                 i = sizeof(sc->ndis_filter);
2923                                 error = ndis_set_info(sc,
2924                                     OID_GEN_CURRENT_PACKET_FILTER,
2925                                     &sc->ndis_filter, &i);
2926                         } else
2927                                 ndis_init(sc);
2928                 } else {
2929                         if (sc->ndis_running)
2930                                 ndis_stop(sc);
2931                 }
2932                 sc->ndis_if_flags = ifp->if_flags;
2933                 error = 0;
2934                 break;
2935         case SIOCADDMULTI:
2936         case SIOCDELMULTI:
2937                 ndis_setmulti(sc);
2938                 error = 0;
2939                 break;
2940         case SIOCGIFMEDIA:
2941         case SIOCSIFMEDIA:
2942                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2943                 break;
2944         case SIOCSIFCAP:
2945                 ifp->if_capenable = ifr->ifr_reqcap;
2946                 if (ifp->if_capenable & IFCAP_TXCSUM)
2947                         ifp->if_hwassist = sc->ndis_hwassist;
2948                 else
2949                         ifp->if_hwassist = 0;
2950                 ndis_set_offload(sc);
2951                 break;
2952         default:
2953                 error = ether_ioctl(ifp, command, data);
2954                 break;
2955         }
2956
2957         /*NDIS_UNLOCK(sc);*/
2958
2959         return(error);
2960 }
2961
2962 static int
2963 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2964 {
2965         struct ndis_softc *sc = ic->ic_softc;
2966         struct ifreq *ifr = data;
2967         struct ndis_oid_data oid;
2968         struct ndis_evt evt;
2969         void *oidbuf = NULL;
2970         int error = 0;
2971
2972         if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2973                 return (error);
2974
2975         switch (cmd) {
2976         case SIOCGDRVSPEC:
2977         case SIOCSDRVSPEC:
2978                 error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid));
2979                 if (error)
2980                         break;
2981                 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2982                 error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid),
2983                     oidbuf, oid.len);
2984         }
2985
2986         if (error) {
2987                 free(oidbuf, M_TEMP);
2988                 return (error);
2989         }
2990
2991         switch (cmd) {
2992         case SIOCGDRVSPEC:
2993                 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2994                 break;
2995         case SIOCSDRVSPEC:
2996                 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2997                 break;
2998         case SIOCGPRIVATE_0:
2999                 NDIS_LOCK(sc);
3000                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3001                         error = ENOENT;
3002                         NDIS_UNLOCK(sc);
3003                         break;
3004                 }
3005                 error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt));
3006                 if (error) {
3007                         NDIS_UNLOCK(sc);
3008                         break;
3009                 }
3010                 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3011                         error = ENOSPC;
3012                         NDIS_UNLOCK(sc);
3013                         break;
3014                 }
3015                 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3016                     ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2);
3017                 if (error) {
3018                         NDIS_UNLOCK(sc);
3019                         break;
3020                 }
3021                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3022                         error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3023                             (caddr_t)ifr_data_get_ptr(ifr) +
3024                             (sizeof(uint32_t) * 2),
3025                             sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3026                         if (error) {
3027                                 NDIS_UNLOCK(sc);
3028                                 break;
3029                         }
3030                         free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3031                         sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3032                 }
3033                 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3034                 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3035                 NDIS_EVTINC(sc->ndis_evtcidx);
3036                 NDIS_UNLOCK(sc);
3037                 break;
3038         default:
3039                 error = ENOTTY;
3040                 break;
3041         }
3042
3043         switch (cmd) {
3044         case SIOCGDRVSPEC:
3045         case SIOCSDRVSPEC:
3046                 error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid));
3047                 if (error)
3048                         break;
3049                 error = copyout(oidbuf,
3050                     (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len);
3051         }
3052
3053         free(oidbuf, M_TEMP);
3054
3055         return (error);
3056 }
3057
3058 int
3059 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3060 {
3061         struct ndis_softc       *sc = vap->iv_ic->ic_softc;
3062         ndis_80211_key          rkey;
3063         int                     len, error = 0;
3064
3065         bzero((char *)&rkey, sizeof(rkey));
3066         len = sizeof(rkey);
3067
3068         rkey.nk_len = len;
3069         rkey.nk_keyidx = key->wk_keyix;
3070
3071         bcopy(vap->iv_ifp->if_broadcastaddr,
3072             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3073
3074         error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3075
3076         if (error)
3077                 return (0);
3078
3079         return (1);
3080 }
3081
3082 /*
3083  * In theory this could be called for any key, but we'll
3084  * only use it for WPA TKIP or AES keys. These need to be
3085  * set after initial authentication with the AP.
3086  */
3087 static int
3088 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3089 {
3090         struct ndis_softc       *sc = vap->iv_ic->ic_softc;
3091         ndis_80211_key          rkey;
3092         int                     len, error = 0;
3093
3094         switch (key->wk_cipher->ic_cipher) {
3095         case IEEE80211_CIPHER_TKIP:
3096
3097                 len = sizeof(ndis_80211_key);
3098                 bzero((char *)&rkey, sizeof(rkey));
3099
3100                 rkey.nk_len = len;
3101                 rkey.nk_keylen = key->wk_keylen;
3102
3103                 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3104                         rkey.nk_keylen += 16;
3105
3106                 /* key index - gets weird in NDIS */
3107
3108                 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3109                         rkey.nk_keyidx = key->wk_keyix;
3110                 else
3111                         rkey.nk_keyidx = 0;
3112
3113                 if (key->wk_flags & IEEE80211_KEY_XMIT)
3114                         rkey.nk_keyidx |= 1 << 31;
3115
3116                 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3117                         bcopy(ieee80211broadcastaddr,
3118                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3119                 } else {
3120                         bcopy(vap->iv_bss->ni_bssid,
3121                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3122                         /* pairwise key */
3123                         rkey.nk_keyidx |= 1 << 30;
3124                 }
3125
3126                 /* need to set bit 29 based on keyrsc */
3127                 rkey.nk_keyrsc = key->wk_keyrsc[0];     /* XXX need tid */
3128
3129                 if (rkey.nk_keyrsc)
3130                         rkey.nk_keyidx |= 1 << 29;
3131
3132                 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3133                         bcopy(key->wk_key, rkey.nk_keydata, 16);
3134                         bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3135                         bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3136                 } else
3137                         bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3138
3139                 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3140                 break;
3141         case IEEE80211_CIPHER_WEP:
3142                 error = 0;
3143                 break;
3144         /*
3145          * I don't know how to set up keys for the AES
3146          * cipher yet. Is it the same as TKIP?
3147          */
3148         case IEEE80211_CIPHER_AES_CCM:
3149         default:
3150                 error = ENOTTY;
3151                 break;
3152         }
3153
3154         /* We need to return 1 for success, 0 for failure. */
3155
3156         if (error)
3157                 return (0);
3158
3159         return (1);
3160 }
3161
3162 static void
3163 ndis_resettask(d, arg)
3164         device_object           *d;
3165         void                    *arg;
3166 {
3167         struct ndis_softc               *sc;
3168
3169         sc = arg;
3170         ndis_reset_nic(sc);
3171 }
3172
3173 /*
3174  * Stop the adapter and free any mbufs allocated to the
3175  * RX and TX lists.
3176  */
3177 static void
3178 ndis_stop(struct ndis_softc *sc)
3179 {
3180         int                     i;
3181
3182         callout_drain(&sc->ndis_stat_callout);
3183
3184         NDIS_LOCK(sc);
3185         sc->ndis_tx_timer = 0;
3186         sc->ndis_link = 0;
3187         if (!sc->ndis_80211)
3188                 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3189         sc->ndis_running = 0;
3190         NDIS_UNLOCK(sc);
3191
3192         if (sc->ndis_iftype != PNPBus ||
3193             (sc->ndis_iftype == PNPBus &&
3194              !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3195              ndisusb_halt != 0))
3196                 ndis_halt_nic(sc);
3197
3198         NDIS_LOCK(sc);
3199         for (i = 0; i < NDIS_EVENTS; i++) {
3200                 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3201                         free(sc->ndis_evt[i].ne_buf, M_TEMP);
3202                         sc->ndis_evt[i].ne_buf = NULL;
3203                 }
3204                 sc->ndis_evt[i].ne_sts = 0;
3205                 sc->ndis_evt[i].ne_len = 0;
3206         }
3207         sc->ndis_evtcidx = 0;
3208         sc->ndis_evtpidx = 0;
3209         NDIS_UNLOCK(sc);
3210 }
3211
3212 /*
3213  * Stop all chip I/O so that the kernel's probe routines don't
3214  * get confused by errant DMAs when rebooting.
3215  */
3216 void
3217 ndis_shutdown(dev)
3218         device_t                dev;
3219 {
3220         struct ndis_softc               *sc;
3221
3222         sc = device_get_softc(dev);
3223         ndis_stop(sc);
3224 }
3225
3226 static int
3227 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3228 {
3229         struct ndis_vap *nvp = NDIS_VAP(vap);
3230         struct ieee80211com *ic = vap->iv_ic;
3231         struct ndis_softc *sc = ic->ic_softc;
3232         enum ieee80211_state ostate;
3233
3234         DPRINTF(("%s: %s -> %s\n", __func__,
3235                 ieee80211_state_name[vap->iv_state],
3236                 ieee80211_state_name[nstate]));
3237
3238         ostate = vap->iv_state;
3239         vap->iv_state = nstate;
3240
3241         switch (nstate) {
3242         /* pass on to net80211 */
3243         case IEEE80211_S_INIT:
3244         case IEEE80211_S_SCAN:
3245                 return nvp->newstate(vap, nstate, arg);
3246         case IEEE80211_S_ASSOC:
3247                 if (ostate != IEEE80211_S_AUTH) {
3248                         IEEE80211_UNLOCK(ic);
3249                         ndis_auth_and_assoc(sc, vap);
3250                         IEEE80211_LOCK(ic);
3251                 }
3252                 break;
3253         case IEEE80211_S_AUTH:
3254                 IEEE80211_UNLOCK(ic);
3255                 ndis_auth_and_assoc(sc, vap);
3256                 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3257                         ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3258                 IEEE80211_LOCK(ic);
3259                 break;
3260         default:
3261                 break;
3262         }
3263         return (0);
3264 }
3265
3266 static void
3267 ndis_scan(void *arg)
3268 {
3269         struct ieee80211vap *vap = arg;
3270
3271         ieee80211_scan_done(vap);
3272 }
3273
3274 static void
3275 ndis_scan_results(struct ndis_softc *sc)
3276 {
3277         struct ieee80211com *ic = &sc->ndis_ic;
3278         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3279         ndis_80211_bssid_list_ex *bl;
3280         ndis_wlan_bssid_ex      *wb;
3281         struct ieee80211_scanparams sp;
3282         struct ieee80211_frame wh;
3283         struct ieee80211_channel *saved_chan;
3284         int i, j;
3285         int rssi, noise, freq, chanflag;
3286         uint8_t ssid[2+IEEE80211_NWID_LEN];
3287         uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3288         uint8_t *frm, *efrm;
3289
3290         saved_chan = ic->ic_curchan;
3291         noise = -96;
3292
3293         if (ndis_get_bssid_list(sc, &bl))
3294                 return;
3295
3296         DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3297         wb = &bl->nblx_bssid[0];
3298         for (i = 0; i < bl->nblx_items; i++) {
3299                 memset(&sp, 0, sizeof(sp));
3300
3301                 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3302                 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3303                 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3304                 rssi = max(0, min(rssi, 100));  /* limit 0 <= rssi <= 100 */
3305                 if (wb->nwbx_privacy)
3306                         sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3307                 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3308                 switch (wb->nwbx_netinfra) {
3309                         case NDIS_80211_NET_INFRA_IBSS:
3310                                 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3311                                 break;
3312                         case NDIS_80211_NET_INFRA_BSS:
3313                                 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3314                                 break;
3315                 }
3316                 sp.rates = &rates[0];
3317                 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3318                         /* XXX - check units */
3319                         if (wb->nwbx_supportedrates[j] == 0)
3320                                 break;
3321                         rates[2 + j] =
3322                         wb->nwbx_supportedrates[j] & 0x7f;
3323                 }
3324                 rates[1] = j;
3325                 sp.ssid = (uint8_t *)&ssid[0];
3326                 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3327                     wb->nwbx_ssid.ns_ssidlen);
3328                 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3329
3330                 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3331                 freq = wb->nwbx_config.nc_dsconfig / 1000;
3332                 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3333                 /* Hack ic->ic_curchan to be in sync with the scan result */
3334                 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3335                 if (ic->ic_curchan == NULL)
3336                         ic->ic_curchan = &ic->ic_channels[0];
3337
3338                 /* Process extended info from AP */
3339                 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3340                         frm = (uint8_t *)&wb->nwbx_ies;
3341                         efrm = frm + wb->nwbx_ielen;
3342                         if (efrm - frm < 12)
3343                                 goto done;
3344                         sp.tstamp = frm;                        frm += 8;
3345                         sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3346                         sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3347                         sp.ies = frm;
3348                         sp.ies_len = efrm - frm;
3349                 }
3350 done:
3351                 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3352                     ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3353                     rssi));
3354                 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3355                 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3356         }
3357         free(bl, M_DEVBUF);
3358         /* Restore the channel after messing with it */
3359         ic->ic_curchan = saved_chan;
3360 }
3361
3362 static void
3363 ndis_scan_start(struct ieee80211com *ic)
3364 {
3365         struct ndis_softc *sc = ic->ic_softc;
3366         struct ieee80211vap *vap;
3367         struct ieee80211_scan_state *ss;
3368         ndis_80211_ssid ssid;
3369         int error, len;
3370
3371         ss = ic->ic_scan;
3372         vap = TAILQ_FIRST(&ic->ic_vaps);
3373
3374         if (!NDIS_INITIALIZED(sc)) {
3375                 DPRINTF(("%s: scan aborted\n", __func__));
3376                 ieee80211_cancel_scan(vap);
3377                 return;
3378         }
3379
3380         len = sizeof(ssid);
3381         bzero((char *)&ssid, len);
3382         if (ss->ss_nssid == 0)
3383                 ssid.ns_ssidlen = 1;
3384         else {
3385                 /* Perform a directed scan */
3386                 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3387                 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3388         }
3389
3390         error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3391         if (error)
3392                 DPRINTF(("%s: set ESSID failed\n", __func__));
3393
3394         len = 0;
3395         error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3396         if (error) {
3397                 DPRINTF(("%s: scan command failed\n", __func__));
3398                 ieee80211_cancel_scan(vap);
3399                 return;
3400         }
3401         /* Set a timer to collect the results */
3402         callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3403 }
3404
3405 static void
3406 ndis_set_channel(struct ieee80211com *ic)
3407 {
3408         /* ignore */
3409 }
3410
3411 static void
3412 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3413 {
3414         /* ignore */
3415 }
3416
3417 static void
3418 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3419 {
3420         /* NB: don't try to abort scan; wait for firmware to finish */
3421 }
3422
3423 static void
3424 ndis_scan_end(struct ieee80211com *ic)
3425 {
3426         struct ndis_softc *sc = ic->ic_softc;
3427
3428         ndis_scan_results(sc);
3429 }