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