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