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