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