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