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