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