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