d373f3b6f974b5667241f7c51bc54013fd1f0d28
[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 *, struct ifaltq_subque *);
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                                 IFNET_STAT_INC(ifp, ierrors, 1);
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                 IFNET_STAT_INC(ifp, opackets, 1);
1556         else
1557                 IFNET_STAT_INC(ifp, oerrors, 1);
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                 IFNET_STAT_INC(sc->ifp, oerrors, 1);
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                 if_devstart(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, struct ifaltq_subque *ifsq)
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         ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
1805
1806         sc = ifp->if_softc;
1807
1808         NDIS_LOCK(sc);
1809         if (!sc->ndis_link) {
1810                 ifq_purge(&ifp->if_snd);
1811                 NDIS_UNLOCK(sc);
1812                 return;
1813         }
1814
1815         if (ifq_is_oactive(&ifp->if_snd)) {
1816                 NDIS_UNLOCK(sc);
1817                 return;
1818         }
1819
1820         p0 = &sc->ndis_txarray[sc->ndis_txidx];
1821
1822         while(sc->ndis_txpending) {
1823                 m = ifq_dequeue(&ifp->if_snd, NULL);
1824                 if (m == NULL)
1825                         break;
1826
1827                 NdisAllocatePacket(&status,
1828                     &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1829
1830                 if (status != NDIS_STATUS_SUCCESS)
1831                         break;
1832
1833                 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1834                         ifq_prepend(&ifp->if_snd, m);
1835                         NDIS_UNLOCK(sc);
1836                         return;
1837                 }
1838
1839                 /*
1840                  * Save pointer to original mbuf
1841                  * so we can free it later.
1842                  */
1843
1844                 p = sc->ndis_txarray[sc->ndis_txidx];
1845                 p->np_txidx = sc->ndis_txidx;
1846                 p->np_m0 = m;
1847                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1848
1849                 /*
1850                  * Do scatter/gather processing, if driver requested it.
1851                  */
1852                 if (sc->ndis_sc) {
1853                         bus_dmamap_load_mbuf(sc->ndis_ttag,
1854                             sc->ndis_tmaps[sc->ndis_txidx], m,
1855                             ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1856                         bus_dmamap_sync(sc->ndis_ttag,
1857                             sc->ndis_tmaps[sc->ndis_txidx],
1858                             BUS_DMASYNC_PREREAD);
1859                         p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1860                 }
1861
1862                 /* Handle checksum offload. */
1863
1864                 if (ifp->if_capenable & IFCAP_TXCSUM &&
1865                     m->m_pkthdr.csum_flags) {
1866                         csum = (ndis_tcpip_csum *)
1867                                 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1868                         csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1869                         if (m->m_pkthdr.csum_flags & CSUM_IP)
1870                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1871                         if (m->m_pkthdr.csum_flags & CSUM_TCP)
1872                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1873                         if (m->m_pkthdr.csum_flags & CSUM_UDP)
1874                                 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1875                         p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1876                 }
1877
1878                 NDIS_INC(sc);
1879                 sc->ndis_txpending--;
1880
1881                 pcnt++;
1882
1883                 /*
1884                  * If there's a BPF listener, bounce a copy of this frame
1885                  * to him.
1886                  */
1887                 if (!sc->ndis_80211)    /* XXX handle 80211 */
1888                         BPF_MTAP(ifp, m);
1889
1890                 /*
1891                  * The array that p0 points to must appear contiguous,
1892                  * so we must not wrap past the end of sc->ndis_txarray[].
1893                  * If it looks like we're about to wrap, break out here
1894                  * so the this batch of packets can be transmitted, then
1895                  * wait for txeof to ask us to send the rest.
1896                  */
1897                 if (sc->ndis_txidx == 0)
1898                         break;
1899         }
1900
1901         if (pcnt == 0) {
1902                 NDIS_UNLOCK(sc);
1903                 return;
1904         }
1905
1906         if (sc->ndis_txpending == 0)
1907                 ifq_set_oactive(&ifp->if_snd);
1908
1909         /*
1910          * Set a timeout in case the chip goes out to lunch.
1911          */
1912         sc->ndis_tx_timer = 5;
1913
1914         NDIS_UNLOCK(sc);
1915
1916         /*
1917          * According to NDIS documentation, if a driver exports
1918          * a MiniportSendPackets() routine, we prefer that over
1919          * a MiniportSend() routine (which sends just a single
1920          * packet).
1921          */
1922         if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1923                 ndis_send_packets(sc, p0, pcnt);
1924         else
1925                 ndis_send_packet(sc, p);
1926
1927         return;
1928 }
1929
1930 static void
1931 ndis_init(void *xsc)
1932 {
1933         struct ndis_softc       *sc = xsc;
1934         struct ifnet            *ifp = sc->ifp;
1935         struct ieee80211com     *ic = ifp->if_l2com;
1936         int                     i, len, error;
1937
1938         /*
1939          * Avoid reintializing the link unnecessarily.
1940          * This should be dealt with in a better way by
1941          * fixing the upper layer modules so they don't
1942          * call ifp->if_init() quite as often.
1943          */
1944         if (sc->ndis_link)
1945                 return;
1946
1947         /*
1948          * Cancel pending I/O and free all RX/TX buffers.
1949          */
1950         ndis_stop(sc);
1951
1952         if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1953                 error = ndis_init_nic(sc);
1954                 if (error != 0) {
1955                         device_printf(sc->ndis_dev,
1956                             "failed to initialize the device: %d\n", error);
1957                         return;
1958                 }
1959         }
1960
1961         /* Init our MAC address */
1962
1963         /* Program the packet filter */
1964
1965         sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1966
1967         if (ifp->if_flags & IFF_BROADCAST)
1968                 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1969
1970         if (ifp->if_flags & IFF_PROMISC)
1971                 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1972
1973         len = sizeof(sc->ndis_filter);
1974
1975         error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1976             &sc->ndis_filter, &len);
1977
1978         if (error)
1979                 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1980
1981         /*
1982          * Set lookahead.
1983          */
1984         i = ifp->if_mtu;
1985         len = sizeof(i);
1986         ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1987
1988         /*
1989          * Program the multicast filter, if necessary.
1990          */
1991         ndis_setmulti(sc);
1992
1993         /* Setup task offload. */
1994         ndis_set_offload(sc);
1995
1996         NDIS_LOCK(sc);
1997
1998         sc->ndis_txidx = 0;
1999         sc->ndis_txpending = sc->ndis_maxpkts;
2000         sc->ndis_link = 0;
2001
2002         sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
2003         if_link_state_change(sc->ifp);
2004
2005         ifp->if_flags |= IFF_RUNNING;
2006         ifq_clr_oactive(&ifp->if_snd);
2007         sc->ndis_tx_timer = 0;
2008
2009         /*
2010          * Some drivers don't set this value. The NDIS spec says
2011          * the default checkforhang timeout is "approximately 2
2012          * seconds." We use 3 seconds, because it seems for some
2013          * drivers, exactly 2 seconds is too fast.
2014          */
2015         if (sc->ndis_block->nmb_checkforhangsecs == 0)
2016                 sc->ndis_block->nmb_checkforhangsecs = 3;
2017
2018         sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2019         callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2020         NDIS_UNLOCK(sc);
2021
2022         /* XXX force handling */
2023         if (sc->ndis_80211)
2024                 ieee80211_start_all(ic);        /* start all vap's */
2025 }
2026
2027 /*
2028  * Set media options.
2029  */
2030 static int
2031 ndis_ifmedia_upd(struct ifnet *ifp)
2032 {
2033         struct ndis_softc               *sc;
2034
2035         sc = ifp->if_softc;
2036
2037         if (NDIS_INITIALIZED(sc))
2038                 ndis_init(sc);
2039
2040         return (0);
2041 }
2042
2043 /*
2044  * Report current media status.
2045  */
2046 static void
2047 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2048 {
2049         struct ndis_softc       *sc;
2050         uint32_t                media_info;
2051         ndis_media_state        linkstate;
2052         int                     len;
2053
2054         ifmr->ifm_status = IFM_AVALID;
2055         ifmr->ifm_active = IFM_ETHER;
2056         sc = ifp->if_softc;
2057
2058         if (!NDIS_INITIALIZED(sc))
2059                 return;
2060
2061         len = sizeof(linkstate);
2062         ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2063             (void *)&linkstate, &len);
2064
2065         len = sizeof(media_info);
2066         ndis_get_info(sc, OID_GEN_LINK_SPEED,
2067             (void *)&media_info, &len);
2068
2069         if (linkstate == nmc_connected)
2070                 ifmr->ifm_status |= IFM_ACTIVE;
2071
2072         switch (media_info) {
2073         case 100000:
2074                 ifmr->ifm_active |= IFM_10_T;
2075                 break;
2076         case 1000000:
2077                 ifmr->ifm_active |= IFM_100_TX;
2078                 break;
2079         case 10000000:
2080                 ifmr->ifm_active |= IFM_1000_T;
2081                 break;
2082         default:
2083                 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2084                 break;
2085         }
2086 }
2087
2088 static int
2089 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2090 {
2091         struct ieee80211com     *ic;
2092         int                     rval = 0, len;
2093         uint32_t                arg, save;
2094
2095         ic = sc->ifp->if_l2com;
2096
2097         len = sizeof(arg);
2098
2099         if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2100                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2101                         return (ENOTSUP);
2102                 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2103         }
2104
2105         if (cipher == WPA_CSE_TKIP) {
2106                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2107                         return (ENOTSUP);
2108                 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2109         }
2110
2111         if (cipher == WPA_CSE_CCMP) {
2112                 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2113                         return (ENOTSUP);
2114                 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2115         }
2116
2117         DPRINTF(("Setting cipher to %d\n", arg));
2118         save = arg;
2119         rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2120
2121         if (rval)
2122                 return (rval);
2123
2124         /* Check that the cipher was set correctly. */
2125
2126         len = sizeof(save);
2127         rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2128
2129         if (rval != 0 || arg != save)
2130                 return (ENODEV);
2131
2132         return (0);
2133 }
2134
2135 /*
2136  * WPA is hairy to set up. Do the work in a separate routine
2137  * so we don't clutter the setstate function too much.
2138  * Important yet undocumented fact: first we have to set the
2139  * authentication mode, _then_ we enable the ciphers. If one
2140  * of the WPA authentication modes isn't enabled, the driver
2141  * might not permit the TKIP or AES ciphers to be selected.
2142  */
2143 static int
2144 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2145 {
2146         struct ieee80211_ie_wpa *w;
2147         struct ndis_ie          *n;
2148         char                    *pos;
2149         uint32_t                arg;
2150         int                     i;
2151
2152         /*
2153          * Apparently, the only way for us to know what ciphers
2154          * and key management/authentication mode to use is for
2155          * us to inspect the optional information element (IE)
2156          * stored in the 802.11 state machine. This IE should be
2157          * supplied by the WPA supplicant.
2158          */
2159
2160         w = (struct ieee80211_ie_wpa *)ie;
2161
2162         /* Check for the right kind of IE. */
2163         if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2164                 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2165                 return (EINVAL);
2166         }
2167
2168         /* Skip over the ucast cipher OIDs. */
2169         pos = (char *)&w->wpa_uciphers[0];
2170         pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2171
2172         /* Skip over the authmode count. */
2173         pos += sizeof(u_int16_t);
2174
2175         /*
2176          * Check for the authentication modes. I'm
2177          * pretty sure there's only supposed to be one.
2178          */
2179
2180         n = (struct ndis_ie *)pos;
2181         if (n->ni_val == WPA_ASE_NONE)
2182                 arg = NDIS_80211_AUTHMODE_WPANONE;
2183
2184         if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2185                 arg = NDIS_80211_AUTHMODE_WPA;
2186
2187         if (n->ni_val == WPA_ASE_8021X_PSK)
2188                 arg = NDIS_80211_AUTHMODE_WPAPSK;
2189
2190         DPRINTF(("Setting WPA auth mode to %d\n", arg));
2191         i = sizeof(arg);
2192         if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2193                 return (ENOTSUP);
2194         i = sizeof(arg);
2195         ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2196
2197         /* Now configure the desired ciphers. */
2198
2199         /* First, set up the multicast group cipher. */
2200         n = (struct ndis_ie *)&w->wpa_mcipher[0];
2201
2202         if (ndis_set_cipher(sc, n->ni_val))
2203                 return (ENOTSUP);
2204
2205         /* Now start looking around for the unicast ciphers. */
2206         pos = (char *)&w->wpa_uciphers[0];
2207         n = (struct ndis_ie *)pos;
2208
2209         for (i = 0; i < w->wpa_uciphercnt; i++) {
2210                 if (ndis_set_cipher(sc, n->ni_val))
2211                         return (ENOTSUP);
2212                 n++;
2213         }
2214
2215         return (0);
2216 }
2217
2218 static void
2219 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2220 {
2221         struct ieee80211vap *vap = ifp->if_softc;
2222         struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2223         uint32_t txrate;
2224         int len;
2225
2226         if (!NDIS_INITIALIZED(sc))
2227                 return;
2228
2229         len = sizeof(txrate);
2230         if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2231                 vap->iv_bss->ni_txrate = txrate / 5000;
2232         ieee80211_media_status(ifp, imr);
2233 }
2234
2235 static void
2236 ndis_setstate_80211(struct ndis_softc *sc)
2237 {
2238         struct ieee80211com     *ic;
2239         struct ieee80211vap     *vap;
2240         ndis_80211_macaddr      bssid;
2241         ndis_80211_config       config;
2242         int                     rval = 0, len;
2243         uint32_t                arg;
2244         struct ifnet            *ifp;
2245         char ethstr[ETHER_ADDRSTRLEN + 1];
2246
2247         ifp = sc->ifp;
2248         ic = ifp->if_l2com;
2249         vap = TAILQ_FIRST(&ic->ic_vaps);
2250
2251         if (!NDIS_INITIALIZED(sc)) {
2252                 DPRINTF(("%s: NDIS not initialized\n", __func__));
2253                 return;
2254         }
2255
2256         /* Disassociate and turn off radio. */
2257         len = sizeof(arg);
2258         arg = 1;
2259         ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2260
2261         /* Set network infrastructure mode. */
2262
2263         len = sizeof(arg);
2264         if (ic->ic_opmode == IEEE80211_M_IBSS)
2265                 arg = NDIS_80211_NET_INFRA_IBSS;
2266         else
2267                 arg = NDIS_80211_NET_INFRA_BSS;
2268
2269         rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2270
2271         if (rval)
2272                 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2273
2274         /* Set power management */
2275         len = sizeof(arg);
2276         if (vap->iv_flags & IEEE80211_F_PMGTON)
2277                 arg = NDIS_80211_POWERMODE_FAST_PSP;
2278         else
2279                 arg = NDIS_80211_POWERMODE_CAM;
2280         ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2281
2282         /* Set TX power */
2283         if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2284             ic->ic_txpowlimit < NELEM(dBm2mW)) {
2285                 arg = dBm2mW[ic->ic_txpowlimit];
2286                 len = sizeof(arg);
2287                 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2288         }
2289
2290         /*
2291          * Default encryption mode to off, authentication
2292          * to open and privacy to 'accept everything.'
2293          */
2294         len = sizeof(arg);
2295         arg = NDIS_80211_WEPSTAT_DISABLED;
2296         ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2297
2298         len = sizeof(arg);
2299         arg = NDIS_80211_AUTHMODE_OPEN;
2300         ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2301
2302         /*
2303          * Note that OID_802_11_PRIVACY_FILTER is optional:
2304          * not all drivers implement it.
2305          */
2306         len = sizeof(arg);
2307         arg = NDIS_80211_PRIVFILT_8021XWEP;
2308         ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2309
2310         len = sizeof(config);
2311         bzero((char *)&config, len);
2312         config.nc_length = len;
2313         config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2314         rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2315
2316         /*
2317          * Some drivers expect us to initialize these values, so
2318          * provide some defaults.
2319          */
2320
2321         if (config.nc_beaconperiod == 0)
2322                 config.nc_beaconperiod = 100;
2323         if (config.nc_atimwin == 0)
2324                 config.nc_atimwin = 100;
2325         if (config.nc_fhconfig.ncf_dwelltime == 0)
2326                 config.nc_fhconfig.ncf_dwelltime = 200;
2327         if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2328                 int chan;
2329
2330                 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2331                 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2332                         config.nc_dsconfig =
2333                                 ic->ic_bsschan->ic_freq * 1000;
2334                         len = sizeof(config);
2335                         config.nc_length = len;
2336                         config.nc_fhconfig.ncf_length =
2337                             sizeof(ndis_80211_config_fh);
2338                         DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2339                         rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2340                             &config, &len);
2341                         if (rval)
2342                                 device_printf(sc->ndis_dev, "couldn't change "
2343                                     "DS config to %ukHz: %d\n",
2344                                     config.nc_dsconfig, rval);
2345                 }
2346         } else if (rval)
2347                 device_printf(sc->ndis_dev, "couldn't retrieve "
2348                     "channel info: %d\n", rval);
2349
2350         /* Set the BSSID to our value so the driver doesn't associate */
2351         len = IEEE80211_ADDR_LEN;
2352         bcopy(IF_LLADDR(ifp), bssid, len);
2353         DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2354         rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2355         if (rval)
2356                 device_printf(sc->ndis_dev,
2357                     "setting BSSID failed: %d\n", rval);
2358 }
2359
2360 static void
2361 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2362 {
2363         struct ieee80211_node   *ni;
2364         ndis_80211_ssid         ssid;
2365         ndis_80211_macaddr      bssid;
2366         ndis_80211_wep          wep;
2367         int                     i, rval = 0, len, error;
2368         uint32_t                arg;
2369         struct ifnet            *ifp;
2370         char ethstr[ETHER_ADDRSTRLEN + 1];
2371
2372         ifp = sc->ifp;
2373         ni = vap->iv_bss;
2374
2375         if (!NDIS_INITIALIZED(sc)) {
2376                 DPRINTF(("%s: NDIS not initialized\n", __func__));
2377                 return;
2378         }
2379
2380         /* Initial setup */
2381         ndis_setstate_80211(sc);
2382
2383         /* Set network infrastructure mode. */
2384
2385         len = sizeof(arg);
2386         if (vap->iv_opmode == IEEE80211_M_IBSS)
2387                 arg = NDIS_80211_NET_INFRA_IBSS;
2388         else
2389                 arg = NDIS_80211_NET_INFRA_BSS;
2390
2391         rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2392
2393         if (rval)
2394                 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2395
2396         /* Set RTS threshold */
2397
2398         len = sizeof(arg);
2399         arg = vap->iv_rtsthreshold;
2400         ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2401
2402         /* Set fragmentation threshold */
2403
2404         len = sizeof(arg);
2405         arg = vap->iv_fragthreshold;
2406         ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2407
2408         /* Set WEP */
2409
2410         if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2411             !(vap->iv_flags & IEEE80211_F_WPA)) {
2412                 int keys_set = 0;
2413
2414                 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2415                         len = sizeof(arg);
2416                         arg = NDIS_80211_AUTHMODE_SHARED;
2417                         DPRINTF(("Setting shared auth\n"));
2418                         ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2419                             &arg, &len);
2420                 }
2421                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2422                         if (vap->iv_nw_keys[i].wk_keylen) {
2423                                 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2424                                     IEEE80211_CIPHER_WEP)
2425                                         continue;
2426                                 bzero((char *)&wep, sizeof(wep));
2427                                 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2428
2429                                 /*
2430                                  * 5, 13 and 16 are the only valid
2431                                  * key lengths. Anything in between
2432                                  * will be zero padded out to the
2433                                  * next highest boundary.
2434                                  */
2435                                 if (vap->iv_nw_keys[i].wk_keylen < 5)
2436                                         wep.nw_keylen = 5;
2437                                 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2438                                      vap->iv_nw_keys[i].wk_keylen < 13)
2439                                         wep.nw_keylen = 13;
2440                                 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2441                                      vap->iv_nw_keys[i].wk_keylen < 16)
2442                                         wep.nw_keylen = 16;
2443
2444                                 wep.nw_keyidx = i;
2445                                 wep.nw_length = (sizeof(uint32_t) * 3)
2446                                     + wep.nw_keylen;
2447                                 if (i == vap->iv_def_txkey)
2448                                         wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2449                                 bcopy(vap->iv_nw_keys[i].wk_key,
2450                                     wep.nw_keydata, wep.nw_length);
2451                                 len = sizeof(wep);
2452                                 DPRINTF(("Setting WEP key %d\n", i));
2453                                 rval = ndis_set_info(sc,
2454                                     OID_802_11_ADD_WEP, &wep, &len);
2455                                 if (rval)
2456                                         device_printf(sc->ndis_dev,
2457                                             "set wepkey failed: %d\n", rval);
2458                                 keys_set++;
2459                         }
2460                 }
2461                 if (keys_set) {
2462                         DPRINTF(("Setting WEP on\n"));
2463                         arg = NDIS_80211_WEPSTAT_ENABLED;
2464                         len = sizeof(arg);
2465                         rval = ndis_set_info(sc,
2466                             OID_802_11_WEP_STATUS, &arg, &len);
2467                         if (rval)
2468                                 device_printf(sc->ndis_dev,
2469                                     "enable WEP failed: %d\n", rval);
2470                         if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2471                                 arg = NDIS_80211_PRIVFILT_8021XWEP;
2472                         else
2473                                 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2474
2475                         len = sizeof(arg);
2476                         ndis_set_info(sc,
2477                             OID_802_11_PRIVACY_FILTER, &arg, &len);
2478                 }
2479         }
2480
2481         /* Set up WPA. */
2482         if ((vap->iv_flags & IEEE80211_F_WPA) &&
2483             vap->iv_appie_assocreq != NULL) {
2484                 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2485                 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2486                 if (error != 0)
2487                         device_printf(sc->ndis_dev, "WPA setup failed\n");
2488         }
2489
2490 #ifdef notyet
2491         /* Set network type. */
2492
2493         arg = 0;
2494
2495         switch (vap->iv_curmode) {
2496         case IEEE80211_MODE_11A:
2497                 arg = NDIS_80211_NETTYPE_11OFDM5;
2498                 break;
2499         case IEEE80211_MODE_11B:
2500                 arg = NDIS_80211_NETTYPE_11DS;
2501                 break;
2502         case IEEE80211_MODE_11G:
2503                 arg = NDIS_80211_NETTYPE_11OFDM24;
2504                 break;
2505         default:
2506                 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2507                     vap->iv_curmode);
2508         }
2509
2510         if (arg) {
2511                 DPRINTF(("Setting network type to %d\n", arg));
2512                 len = sizeof(arg);
2513                 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2514                     &arg, &len);
2515                 if (rval)
2516                         device_printf(sc->ndis_dev,
2517                             "set nettype failed: %d\n", rval);
2518         }
2519 #endif
2520
2521         /*
2522          * If the user selected a specific BSSID, try
2523          * to use that one. This is useful in the case where
2524          * there are several APs in range with the same network
2525          * name. To delete the BSSID, we use the broadcast
2526          * address as the BSSID.
2527          * Note that some drivers seem to allow setting a BSSID
2528          * in ad-hoc mode, which has the effect of forcing the
2529          * NIC to create an ad-hoc cell with a specific BSSID,
2530          * instead of a randomly chosen one. However, the net80211
2531          * code makes the assumtion that the BSSID setting is invalid
2532          * when you're in ad-hoc mode, so we don't allow that here.
2533          */
2534
2535         len = IEEE80211_ADDR_LEN;
2536         if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2537             vap->iv_opmode != IEEE80211_M_IBSS)
2538                 bcopy(ni->ni_bssid, bssid, len);
2539         else
2540                 bcopy(ifp->if_broadcastaddr, bssid, len);
2541
2542         DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2543         rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2544         if (rval)
2545                 device_printf(sc->ndis_dev,
2546                     "setting BSSID failed: %d\n", rval);
2547
2548         /* Set SSID -- always do this last. */
2549
2550 #ifdef NDIS_DEBUG
2551         if (ndis_debug > 0) {
2552                 kprintf("Setting ESSID to ");
2553                 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2554                 kprintf("\n");
2555         }
2556 #endif
2557
2558         len = sizeof(ssid);
2559         bzero((char *)&ssid, len);
2560         ssid.ns_ssidlen = ni->ni_esslen;
2561         if (ssid.ns_ssidlen == 0) {
2562                 ssid.ns_ssidlen = 1;
2563         } else
2564                 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2565
2566         rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2567
2568         if (rval)
2569                 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2570
2571         return;
2572 }
2573
2574 static int
2575 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2576 {
2577         int     len, error;
2578
2579         len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2580         *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2581         if (*bl == NULL)
2582                 return (ENOMEM);
2583
2584         error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2585         if (error == ENOSPC) {
2586                 kfree(*bl, M_DEVBUF);
2587                 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2588                 if (*bl == NULL)
2589                         return (ENOMEM);
2590
2591                 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2592         }
2593         if (error) {
2594                 DPRINTF(("%s: failed to read\n", __func__));
2595                 kfree(*bl, M_DEVBUF);
2596                 return (error);
2597         }
2598
2599         return (0);
2600 }
2601
2602 static int
2603 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2604 {
2605         struct ifnet *ifp = sc->ifp;
2606         struct ieee80211com *ic = ifp->if_l2com;
2607         struct ieee80211vap     *vap;
2608         struct ieee80211_node   *ni;
2609         ndis_80211_bssid_list_ex        *bl;
2610         ndis_wlan_bssid_ex      *bs;
2611         ndis_80211_macaddr      bssid;
2612         int                     i, len, error;
2613
2614         if (!sc->ndis_link)
2615                 return (ENOENT);
2616
2617         len = sizeof(bssid);
2618         error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2619         if (error) {
2620                 device_printf(sc->ndis_dev, "failed to get bssid\n");
2621                 return (ENOENT);
2622         }
2623
2624         vap = TAILQ_FIRST(&ic->ic_vaps);
2625         ni = vap->iv_bss;
2626
2627         error = ndis_get_bssid_list(sc, &bl);
2628         if (error)
2629                 return (error);
2630
2631         bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2632         for (i = 0; i < bl->nblx_items; i++) {
2633                 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2634                         *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2635                         if (*assoc == NULL) {
2636                                 kfree(bl, M_TEMP);
2637                                 return (ENOMEM);
2638                         }
2639                         bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2640                         kfree(bl, M_TEMP);
2641                         if (ic->ic_opmode == IEEE80211_M_STA)
2642                                 ni->ni_associd = 1 | 0xc000; /* fake associd */
2643                         return (0);
2644                 }
2645                 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2646         }
2647
2648         kfree(bl, M_TEMP);
2649         return (ENOENT);
2650 }
2651
2652 static void
2653 ndis_getstate_80211(struct ndis_softc *sc)
2654 {
2655         struct ieee80211com     *ic;
2656         struct ieee80211vap     *vap;
2657         struct ieee80211_node   *ni;
2658         ndis_wlan_bssid_ex      *bs;
2659         int                     rval, len, i = 0;
2660         int                     chanflag;
2661         uint32_t                arg;
2662         struct ifnet            *ifp;
2663
2664         ifp = sc->ifp;
2665         ic = ifp->if_l2com;
2666         vap = TAILQ_FIRST(&ic->ic_vaps);
2667         ni = vap->iv_bss;
2668
2669         if (!NDIS_INITIALIZED(sc))
2670                 return;
2671
2672         if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2673                 return;
2674
2675         /* We're associated, retrieve info on the current bssid. */
2676         ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2677         chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2678         IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2679
2680         /* Get SSID from current association info. */
2681         bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2682             bs->nwbx_ssid.ns_ssidlen);
2683         ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2684
2685         if (ic->ic_caps & IEEE80211_C_PMGT) {
2686                 len = sizeof(arg);
2687                 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2688
2689                 if (rval)
2690                         device_printf(sc->ndis_dev,
2691                             "get power mode failed: %d\n", rval);
2692                 if (arg == NDIS_80211_POWERMODE_CAM)
2693                         vap->iv_flags &= ~IEEE80211_F_PMGTON;
2694                 else
2695                         vap->iv_flags |= IEEE80211_F_PMGTON;
2696         }
2697
2698         /* Get TX power */
2699         if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2700                 len = sizeof(arg);
2701                 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2702                 for (i = 0; i < NELEM(dBm2mW); i++)
2703                         if (dBm2mW[i] >= arg)
2704                                 break;
2705                 ic->ic_txpowlimit = i;
2706         }
2707
2708         /*
2709          * Use the current association information to reflect
2710          * what channel we're on.
2711          */
2712         ic->ic_curchan = ieee80211_find_channel(ic,
2713             bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2714         if (ic->ic_curchan == NULL)
2715                 ic->ic_curchan = &ic->ic_channels[0];
2716         ni->ni_chan = ic->ic_curchan;
2717         ic->ic_bsschan = ic->ic_curchan;
2718
2719         kfree(bs, M_TEMP);
2720
2721         /*
2722          * Determine current authentication mode.
2723          */
2724         len = sizeof(arg);
2725         rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2726         if (rval)
2727                 device_printf(sc->ndis_dev,
2728                     "get authmode status failed: %d\n", rval);
2729         else {
2730                 vap->iv_flags &= ~IEEE80211_F_WPA;
2731                 switch (arg) {
2732                 case NDIS_80211_AUTHMODE_OPEN:
2733                         ni->ni_authmode = IEEE80211_AUTH_OPEN;
2734                         break;
2735                 case NDIS_80211_AUTHMODE_SHARED:
2736                         ni->ni_authmode = IEEE80211_AUTH_SHARED;
2737                         break;
2738                 case NDIS_80211_AUTHMODE_AUTO:
2739                         ni->ni_authmode = IEEE80211_AUTH_AUTO;
2740                         break;
2741                 case NDIS_80211_AUTHMODE_WPA:
2742                 case NDIS_80211_AUTHMODE_WPAPSK:
2743                 case NDIS_80211_AUTHMODE_WPANONE:
2744                         ni->ni_authmode = IEEE80211_AUTH_WPA;
2745                         vap->iv_flags |= IEEE80211_F_WPA1;
2746                         break;
2747                 case NDIS_80211_AUTHMODE_WPA2:
2748                 case NDIS_80211_AUTHMODE_WPA2PSK:
2749                         ni->ni_authmode = IEEE80211_AUTH_WPA;
2750                         vap->iv_flags |= IEEE80211_F_WPA2;
2751                         break;
2752                 default:
2753                         ni->ni_authmode = IEEE80211_AUTH_NONE;
2754                         break;
2755                 }
2756         }
2757
2758         len = sizeof(arg);
2759         rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2760
2761         if (rval)
2762                 device_printf(sc->ndis_dev,
2763                     "get wep status failed: %d\n", rval);
2764
2765         if (arg == NDIS_80211_WEPSTAT_ENABLED)
2766                 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2767         else
2768                 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2769 }
2770
2771 static int
2772 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2773 {
2774         struct ndis_softc       *sc = ifp->if_softc;
2775         struct ifreq            *ifr = (struct ifreq *) data;
2776         int                     i, error = 0;
2777
2778         /*NDIS_LOCK(sc);*/
2779
2780         switch (command) {
2781         case SIOCSIFFLAGS:
2782                 if (ifp->if_flags & IFF_UP) {
2783                         if (ifp->if_flags & IFF_RUNNING &&
2784                             ifp->if_flags & IFF_PROMISC &&
2785                             !(sc->ndis_if_flags & IFF_PROMISC)) {
2786                                 sc->ndis_filter |=
2787                                     NDIS_PACKET_TYPE_PROMISCUOUS;
2788                                 i = sizeof(sc->ndis_filter);
2789                                 error = ndis_set_info(sc,
2790                                     OID_GEN_CURRENT_PACKET_FILTER,
2791                                     &sc->ndis_filter, &i);
2792                         } else if (ifp->if_flags & IFF_RUNNING &&
2793                             !(ifp->if_flags & IFF_PROMISC) &&
2794                             sc->ndis_if_flags & IFF_PROMISC) {
2795                                 sc->ndis_filter &=
2796                                     ~NDIS_PACKET_TYPE_PROMISCUOUS;
2797                                 i = sizeof(sc->ndis_filter);
2798                                 error = ndis_set_info(sc,
2799                                     OID_GEN_CURRENT_PACKET_FILTER,
2800                                     &sc->ndis_filter, &i);
2801                         } else
2802                                 ndis_init(sc);
2803                 } else {
2804                         if (ifp->if_flags & IFF_RUNNING)
2805                                 ndis_stop(sc);
2806                 }
2807                 sc->ndis_if_flags = ifp->if_flags;
2808                 error = 0;
2809                 break;
2810         case SIOCADDMULTI:
2811         case SIOCDELMULTI:
2812                 ndis_setmulti(sc);
2813                 error = 0;
2814                 break;
2815         case SIOCGIFMEDIA:
2816         case SIOCSIFMEDIA:
2817                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2818                 break;
2819         case SIOCSIFCAP:
2820                 ifp->if_capenable = ifr->ifr_reqcap;
2821                 if (ifp->if_capenable & IFCAP_TXCSUM)
2822                         ifp->if_hwassist = sc->ndis_hwassist;
2823                 else
2824                         ifp->if_hwassist = 0;
2825                 ndis_set_offload(sc);
2826                 break;
2827         default:
2828                 error = ether_ioctl(ifp, command, data);
2829                 break;
2830         }
2831
2832         /*NDIS_UNLOCK(sc);*/
2833
2834         return(error);
2835 }
2836
2837 static int
2838 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2839     struct ucred *cr)
2840 {
2841         struct ndis_softc       *sc = ifp->if_softc;
2842         struct ieee80211com     *ic = ifp->if_l2com;
2843         struct ifreq            *ifr = (struct ifreq *) data;
2844         struct ndis_oid_data    oid;
2845         struct ndis_evt         evt;
2846         void                    *oidbuf;
2847         int                     error = 0;
2848
2849         switch (command) {
2850         case SIOCSIFFLAGS:
2851                 /*NDIS_LOCK(sc);*/
2852                 if (ifp->if_flags & IFF_UP) {
2853                         if (!(ifp->if_flags & IFF_RUNNING))
2854                                 ndis_init(sc);
2855                 } else {
2856                         if (ifp->if_flags & IFF_RUNNING)
2857                                 ndis_stop(sc);
2858                 }
2859                 sc->ndis_if_flags = ifp->if_flags;
2860                 error = 0;
2861                 /*NDIS_UNLOCK(sc);*/
2862                 break;
2863         case SIOCGDRVSPEC:
2864                 if ((error = priv_check(curthread, PRIV_DRIVER)))
2865                         break;
2866                 error =  copyin(ifr->ifr_data, &oid, sizeof(oid));
2867                 if (error)
2868                         break;
2869                 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2870                 if (oidbuf == NULL) {
2871                         error = ENOMEM;
2872                         break;
2873                 }
2874                 error =  copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2875                 if (error) {
2876                         kfree(oidbuf, M_TEMP);
2877                         break;
2878                 }
2879                 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2880                 if (error) {
2881                         kfree(oidbuf, M_TEMP);
2882                         break;
2883                 }
2884                 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2885                 if (error) {
2886                         kfree(oidbuf, M_TEMP);
2887                         break;
2888                 }
2889                 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2890                 kfree(oidbuf, M_TEMP);
2891                 break;
2892         case SIOCSDRVSPEC:
2893                 if ((error = priv_check(curthread, PRIV_DRIVER)))
2894                         break;
2895                 error =  copyin(ifr->ifr_data, &oid, sizeof(oid));
2896                 if (error)
2897                         break;
2898                 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2899                 if (oidbuf == NULL) {
2900                         error = ENOMEM;
2901                         break;
2902                 }
2903                 error =  copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2904                 if (error) {
2905                         kfree(oidbuf, M_TEMP);
2906                         break;
2907                 }
2908                 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2909                 if (error) {
2910                         kfree(oidbuf, M_TEMP);
2911                         break;
2912                 }
2913                 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2914                 if (error) {
2915                         kfree(oidbuf, M_TEMP);
2916                         break;
2917                 }
2918                 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2919                 kfree(oidbuf, M_TEMP);
2920                 break;
2921         case SIOCGPRIVATE_0:
2922                 if ((error = priv_check(curthread, PRIV_DRIVER)))
2923                         break;
2924                 NDIS_LOCK(sc);
2925                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2926                         error = ENOENT;
2927                         NDIS_UNLOCK(sc);
2928                         break;
2929                 }
2930                 error =  copyin(ifr->ifr_data, &evt, sizeof(evt));
2931                 if (error) {
2932                         NDIS_UNLOCK(sc);
2933                         break;
2934                 }
2935                 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2936                         error = ENOSPC;
2937                         NDIS_UNLOCK(sc);
2938                         break;
2939                 }
2940                 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2941                     ifr->ifr_data, sizeof(uint32_t) * 2);
2942                 if (error) {
2943                         NDIS_UNLOCK(sc);
2944                         break;
2945                 }
2946                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2947                         error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2948                             (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2949                             sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2950                         if (error) {
2951                                 NDIS_UNLOCK(sc);
2952                                 break;
2953                         }
2954                         kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2955                         sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2956                 }
2957                 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2958                 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2959                 NDIS_EVTINC(sc->ndis_evtcidx);
2960                 NDIS_UNLOCK(sc);
2961                 break;
2962         case SIOCGIFMEDIA:
2963                 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2964                 break;
2965         case SIOCGIFADDR:
2966                 error = ether_ioctl(ifp, command, data);
2967                 break;
2968         default:
2969                 error = EINVAL;
2970                 break;
2971         }
2972         return (error);
2973 }
2974
2975 int
2976 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2977 {
2978         struct ndis_softc       *sc;
2979         ndis_80211_key          rkey;
2980         int                     len, error = 0;
2981
2982         sc = vap->iv_ic->ic_ifp->if_softc;
2983
2984         bzero((char *)&rkey, sizeof(rkey));
2985         len = sizeof(rkey);
2986
2987         rkey.nk_len = len;
2988         rkey.nk_keyidx = key->wk_keyix;
2989
2990         bcopy(vap->iv_ifp->if_broadcastaddr,
2991             rkey.nk_bssid, IEEE80211_ADDR_LEN);
2992
2993         error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
2994
2995         if (error)
2996                 return (0);
2997
2998         return (1);
2999 }
3000
3001 /*
3002  * In theory this could be called for any key, but we'll
3003  * only use it for WPA TKIP or AES keys. These need to be
3004  * set after initial authentication with the AP.
3005  */
3006 static int
3007 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
3008     const uint8_t mac[IEEE80211_ADDR_LEN])
3009 {
3010         struct ndis_softc       *sc;
3011         struct ifnet            *ifp;
3012         ndis_80211_key          rkey;
3013         int                     len, error = 0;
3014
3015         ifp = vap->iv_ic->ic_ifp;
3016         sc = ifp->if_softc;
3017
3018         switch (key->wk_cipher->ic_cipher) {
3019         case IEEE80211_CIPHER_TKIP:
3020
3021                 len = sizeof(ndis_80211_key);
3022                 bzero((char *)&rkey, sizeof(rkey));
3023
3024                 rkey.nk_len = len;
3025                 rkey.nk_keylen = key->wk_keylen;
3026
3027                 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3028                         rkey.nk_keylen += 16;
3029
3030                 /* key index - gets weird in NDIS */
3031
3032                 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3033                         rkey.nk_keyidx = key->wk_keyix;
3034                 else
3035                         rkey.nk_keyidx = 0;
3036
3037                 if (key->wk_flags & IEEE80211_KEY_XMIT)
3038                         rkey.nk_keyidx |= 1 << 31;
3039
3040                 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3041                         bcopy(ifp->if_broadcastaddr,
3042                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3043                 } else {
3044                         bcopy(vap->iv_bss->ni_bssid,
3045                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3046                         /* pairwise key */
3047                         rkey.nk_keyidx |= 1 << 30;
3048                 }
3049
3050                 /* need to set bit 29 based on keyrsc */
3051                 rkey.nk_keyrsc = key->wk_keyrsc[0];     /* XXX need tid */
3052
3053                 if (rkey.nk_keyrsc)
3054                         rkey.nk_keyidx |= 1 << 29;
3055
3056                 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3057                         bcopy(key->wk_key, rkey.nk_keydata, 16);
3058                         bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3059                         bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3060                 } else
3061                         bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3062
3063                 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3064                 break;
3065         case IEEE80211_CIPHER_WEP:
3066                 error = 0;
3067                 break;
3068         /*
3069          * I don't know how to set up keys for the AES
3070          * cipher yet. Is it the same as TKIP?
3071          */
3072         case IEEE80211_CIPHER_AES_CCM:
3073         default:
3074                 error = ENOTTY;
3075                 break;
3076         }
3077
3078         /* We need to return 1 for success, 0 for failure. */
3079
3080         if (error)
3081                 return (0);
3082
3083         return (1);
3084 }
3085
3086 static void
3087 ndis_resettask(device_object *d, void *arg)
3088 {
3089         struct ndis_softc               *sc;
3090
3091         sc = arg;
3092         ndis_reset_nic(sc);
3093 }
3094
3095 /*
3096  * Stop the adapter and free any mbufs allocated to the
3097  * RX and TX lists.
3098  */
3099 static void
3100 ndis_stop(struct ndis_softc *sc)
3101 {
3102         struct ifnet            *ifp;
3103         int                     i;
3104
3105         ifp = sc->ifp;
3106         callout_stop(&sc->ndis_stat_callout); /* XXX swildner callout_drain() */
3107
3108         NDIS_LOCK(sc);
3109         sc->ndis_tx_timer = 0;
3110         sc->ndis_link = 0;
3111         ifp->if_flags &= ~IFF_RUNNING;
3112         ifq_clr_oactive(&ifp->if_snd);
3113         NDIS_UNLOCK(sc);
3114
3115         if (sc->ndis_iftype != PNPBus ||
3116             (sc->ndis_iftype == PNPBus &&
3117              !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3118              ndisusb_halt != 0))
3119                 ndis_halt_nic(sc);
3120
3121         NDIS_LOCK(sc);
3122         for (i = 0; i < NDIS_EVENTS; i++) {
3123                 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3124                         kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3125                         sc->ndis_evt[i].ne_buf = NULL;
3126                 }
3127                 sc->ndis_evt[i].ne_sts = 0;
3128                 sc->ndis_evt[i].ne_len = 0;
3129         }
3130         sc->ndis_evtcidx = 0;
3131         sc->ndis_evtpidx = 0;
3132         NDIS_UNLOCK(sc);
3133 }
3134
3135 /*
3136  * Stop all chip I/O so that the kernel's probe routines don't
3137  * get confused by errant DMAs when rebooting.
3138  */
3139 void
3140 ndis_shutdown(device_t dev)
3141 {
3142         struct ndis_softc               *sc;
3143
3144         wlan_serialize_enter();
3145         sc = device_get_softc(dev);
3146         ndis_stop(sc);
3147         wlan_serialize_exit();
3148 }
3149
3150 static int
3151 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3152 {
3153         struct ndis_vap *nvp = NDIS_VAP(vap);
3154         struct ieee80211com *ic = vap->iv_ic;
3155         struct ifnet *ifp = ic->ic_ifp;
3156         struct ndis_softc *sc = ifp->if_softc;
3157         enum ieee80211_state ostate;
3158
3159         DPRINTF(("%s: %s -> %s\n", __func__,
3160                 ieee80211_state_name[vap->iv_state],
3161                 ieee80211_state_name[nstate]));
3162
3163         ostate = vap->iv_state;
3164         vap->iv_state = nstate;
3165
3166         switch (nstate) {
3167         /* pass on to net80211 */
3168         case IEEE80211_S_INIT:
3169         case IEEE80211_S_SCAN:
3170                 return nvp->newstate(vap, nstate, arg);
3171         case IEEE80211_S_ASSOC:
3172                 if (ostate != IEEE80211_S_AUTH) {
3173                         wlan_serialize_exit();
3174                         ndis_auth_and_assoc(sc, vap);
3175                         wlan_serialize_enter();
3176                 }
3177                 break;
3178         case IEEE80211_S_AUTH:
3179                 wlan_serialize_exit();
3180                 ndis_auth_and_assoc(sc, vap);
3181                 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3182                         ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3183                 wlan_serialize_enter();
3184                 break;
3185         default:
3186                 break;
3187         }
3188         return (0);
3189 }
3190
3191 static void
3192 ndis_scan(void *arg)
3193 {
3194         struct ieee80211vap *vap = arg;
3195
3196         ieee80211_scan_done(vap);
3197 }
3198
3199 static void
3200 ndis_scan_results(struct ndis_softc *sc)
3201 {
3202         struct ieee80211com *ic;
3203         struct ieee80211vap *vap;
3204         ndis_80211_bssid_list_ex *bl;
3205         ndis_wlan_bssid_ex      *wb;
3206         struct ieee80211_scanparams sp;
3207         struct ieee80211_frame wh;
3208         struct ieee80211_channel *saved_chan;
3209         int i, j;
3210         int rssi, noise, freq, chanflag;
3211         uint8_t ssid[2+IEEE80211_NWID_LEN];
3212         uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3213         uint8_t *frm, *efrm;
3214         char ethstr[ETHER_ADDRSTRLEN + 1];
3215
3216         ic = sc->ifp->if_l2com;
3217         vap = TAILQ_FIRST(&ic->ic_vaps);
3218         saved_chan = ic->ic_curchan;
3219         noise = -96;
3220
3221         if (ndis_get_bssid_list(sc, &bl))
3222                 return;
3223
3224         DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3225         wb = &bl->nblx_bssid[0];
3226         for (i = 0; i < bl->nblx_items; i++) {
3227                 memset(&sp, 0, sizeof(sp));
3228
3229                 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3230                 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3231                 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3232                 rssi = max(0, min(rssi, 100));  /* limit 0 <= rssi <= 100 */
3233                 if (wb->nwbx_privacy)
3234                         sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3235                 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3236                 switch (wb->nwbx_netinfra) {
3237                         case NDIS_80211_NET_INFRA_IBSS:
3238                                 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3239                                 break;
3240                         case NDIS_80211_NET_INFRA_BSS:
3241                                 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3242                                 break;
3243                 }
3244                 sp.rates = &rates[0];
3245                 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3246                         /* XXX - check units */
3247                         if (wb->nwbx_supportedrates[j] == 0)
3248                                 break;
3249                         rates[2 + j] =
3250                         wb->nwbx_supportedrates[j] & 0x7f;
3251                 }
3252                 rates[1] = j;
3253                 sp.ssid = &ssid[0];
3254                 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3255                     wb->nwbx_ssid.ns_ssidlen);
3256                 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3257
3258                 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3259                 freq = wb->nwbx_config.nc_dsconfig / 1000;
3260                 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3261                 /* Hack ic->ic_curchan to be in sync with the scan result */
3262                 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3263                 if (ic->ic_curchan == NULL)
3264                         ic->ic_curchan = &ic->ic_channels[0];
3265
3266                 /* Process extended info from AP */
3267                 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3268                         frm = (uint8_t *)&wb->nwbx_ies;
3269                         efrm = frm + wb->nwbx_ielen;
3270                         if (efrm - frm < 12)
3271                                 goto done;
3272                         sp.tstamp = frm;                        frm += 8;
3273                         sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3274                         sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3275                         sp.ies = frm;
3276                         sp.ies_len = efrm - frm;
3277                 }
3278 done:
3279                 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3280                     kether_ntoa(wb->nwbx_macaddr, ethstr), freq, sp.bchan, chanflag,
3281                     rssi));
3282                 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3283                 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3284         }
3285         kfree(bl, M_DEVBUF);
3286         /* Restore the channel after messing with it */
3287         ic->ic_curchan = saved_chan;
3288 }
3289
3290 static void
3291 ndis_scan_start(struct ieee80211com *ic)
3292 {
3293         struct ifnet *ifp = ic->ic_ifp;
3294         struct ndis_softc *sc = ifp->if_softc;
3295         struct ieee80211vap *vap;
3296         struct ieee80211_scan_state *ss;
3297         ndis_80211_ssid ssid;
3298         int error, len;
3299
3300         ss = ic->ic_scan;
3301         vap = TAILQ_FIRST(&ic->ic_vaps);
3302
3303         if (!NDIS_INITIALIZED(sc)) {
3304                 DPRINTF(("%s: scan aborted\n", __func__));
3305                 ieee80211_cancel_scan(vap);
3306                 return;
3307         }
3308
3309         len = sizeof(ssid);
3310         bzero((char *)&ssid, len);
3311         if (ss->ss_nssid == 0)
3312                 ssid.ns_ssidlen = 1;
3313         else {
3314                 /* Perform a directed scan */
3315                 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3316                 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3317         }
3318
3319         error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3320         if (error)
3321                 DPRINTF(("%s: set ESSID failed\n", __func__));
3322
3323         len = 0;
3324         error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3325         if (error) {
3326                 DPRINTF(("%s: scan command failed\n", __func__));
3327                 ieee80211_cancel_scan(vap);
3328                 return;
3329         }
3330         /* Set a timer to collect the results */
3331         callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3332 }
3333
3334 static void
3335 ndis_set_channel(struct ieee80211com *ic)
3336 {
3337         /* ignore */
3338 }
3339
3340 static void
3341 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3342 {
3343         /* ignore */
3344 }
3345
3346 static void
3347 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3348 {
3349         /* NB: don't try to abort scan; wait for firmware to finish */
3350 }
3351
3352 static void
3353 ndis_scan_end(struct ieee80211com *ic)
3354 {
3355         struct ndis_softc *sc = ic->ic_ifp->if_softc;
3356
3357         ndis_scan_results(sc);
3358 }