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