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