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