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