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