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