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