]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/if_ndis/if_ndis.c
Merge OpenSSL 1.0.2d.
[FreeBSD/FreeBSD.git] / sys / dev / if_ndis / if_ndis.c
1 /*-
2  * Copyright (c) 2003
3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
33  * then hacked upon mercilessly by my.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sockio.h>
42 #include <sys/mbuf.h>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
45 #include <sys/priv.h>
46 #include <sys/kernel.h>
47 #include <sys/socket.h>
48 #include <sys/queue.h>
49 #include <sys/module.h>
50 #include <sys/proc.h>
51 #include <sys/sysctl.h>
52 #include <sys/kthread.h>
53 #include <sys/limits.h>
54
55 #include <net/if.h>
56 #include <net/if_var.h>
57 #include <net/if_arp.h>
58 #include <net/ethernet.h>
59 #include <net/if_dl.h>
60 #include <net/if_media.h>
61 #include <net/if_types.h>
62 #include <net/route.h>
63
64 #include <net/bpf.h>
65
66 #include <machine/bus.h>
67 #include <machine/resource.h>
68 #include <sys/bus.h>
69 #include <sys/rman.h>
70
71 #include <net80211/ieee80211_var.h>
72 #include <net80211/ieee80211_ioctl.h>
73 #include <net80211/ieee80211_regdomain.h>
74
75 #include <dev/pci/pcireg.h>
76 #include <dev/pci/pcivar.h>
77 #include <dev/usb/usb.h>
78 #include <dev/usb/usbdi.h>
79
80 #include <compat/ndis/pe_var.h>
81 #include <compat/ndis/cfg_var.h>
82 #include <compat/ndis/resource_var.h>
83 #include <compat/ndis/ntoskrnl_var.h>
84 #include <compat/ndis/hal_var.h>
85 #include <compat/ndis/ndis_var.h>
86 #include <compat/ndis/usbd_var.h>
87 #include <dev/if_ndis/if_ndisvar.h>
88
89 #define NDIS_DEBUG
90 #ifdef NDIS_DEBUG
91 #define DPRINTF(x)      do { if (ndis_debug > 0) printf x; } while (0)
92 int ndis_debug = 0;
93 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
94     "if_ndis debug level");
95 #else
96 #define DPRINTF(x)
97 #endif
98
99 SYSCTL_DECL(_hw_ndisusb);
100 int ndisusb_halt = 1;
101 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
102     "Halt NDIS USB driver when it's attached");
103
104 /* 0 - 30 dBm to mW conversion table */
105 static const uint16_t dBm2mW[] = {
106         1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
107         3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
108         10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
109         32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
110         100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
111         316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
112         1000
113 };
114
115 MODULE_DEPEND(ndis, ether, 1, 1, 1);
116 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
117 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
118
119 MODULE_VERSION(ndis, 1);
120
121 int ndis_attach                 (device_t);
122 int ndis_detach                 (device_t);
123 int ndis_suspend                (device_t);
124 int ndis_resume                 (device_t);
125 void ndis_shutdown              (device_t);
126
127 int ndisdrv_modevent            (module_t, int, void *);
128
129 static void ndis_txeof          (ndis_handle, ndis_packet *, ndis_status);
130 static void ndis_rxeof          (ndis_handle, ndis_packet **, uint32_t);
131 static void ndis_rxeof_eth      (ndis_handle, ndis_handle, char *, void *,
132                                  uint32_t, void *, uint32_t, uint32_t);
133 static void ndis_rxeof_done     (ndis_handle);
134 static void ndis_rxeof_xfr      (kdpc *, ndis_handle, void *, void *);
135 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
136                                  uint32_t, uint32_t);
137 static void ndis_linksts        (ndis_handle, ndis_status, void *, uint32_t);
138 static void ndis_linksts_done   (ndis_handle);
139
140 /* We need to wrap these functions for amd64. */
141 static funcptr ndis_txeof_wrap;
142 static funcptr ndis_rxeof_wrap;
143 static funcptr ndis_rxeof_eth_wrap;
144 static funcptr ndis_rxeof_done_wrap;
145 static funcptr ndis_rxeof_xfr_wrap;
146 static funcptr ndis_rxeof_xfr_done_wrap;
147 static funcptr ndis_linksts_wrap;
148 static funcptr ndis_linksts_done_wrap;
149 static funcptr ndis_ticktask_wrap;
150 static funcptr ndis_starttask_wrap;
151 static funcptr ndis_resettask_wrap;
152 static funcptr ndis_inputtask_wrap;
153
154 static struct   ieee80211vap *ndis_vap_create(struct ieee80211com *,
155                     const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
156                     const uint8_t [IEEE80211_ADDR_LEN],
157                     const uint8_t [IEEE80211_ADDR_LEN]);
158 static void ndis_vap_delete     (struct ieee80211vap *);
159 static void ndis_tick           (void *);
160 static void ndis_ticktask       (device_object *, void *);
161 static int ndis_raw_xmit        (struct ieee80211_node *, struct mbuf *,
162         const struct ieee80211_bpf_params *);
163 static void ndis_update_mcast   (struct ieee80211com *);
164 static void ndis_update_promisc (struct ieee80211com *);
165 static void ndis_start          (struct ifnet *);
166 static void ndis_starttask      (device_object *, void *);
167 static void ndis_resettask      (device_object *, void *);
168 static void ndis_inputtask      (device_object *, void *);
169 static int ndis_ioctl           (struct ifnet *, u_long, caddr_t);
170 static int ndis_newstate        (struct ieee80211vap *, enum ieee80211_state,
171         int);
172 static int ndis_nettype_chan    (uint32_t);
173 static int ndis_nettype_mode    (uint32_t);
174 static void ndis_scan           (void *);
175 static void ndis_scan_results   (struct ndis_softc *);
176 static void ndis_scan_start     (struct ieee80211com *);
177 static void ndis_scan_end       (struct ieee80211com *);
178 static void ndis_set_channel    (struct ieee80211com *);
179 static void ndis_scan_curchan   (struct ieee80211_scan_state *, unsigned long);
180 static void ndis_scan_mindwell  (struct ieee80211_scan_state *);
181 static void ndis_init           (void *);
182 static void ndis_stop           (struct ndis_softc *);
183 static int ndis_ifmedia_upd     (struct ifnet *);
184 static void ndis_ifmedia_sts    (struct ifnet *, struct ifmediareq *);
185 static int ndis_get_bssid_list  (struct ndis_softc *,
186                                         ndis_80211_bssid_list_ex **);
187 static int ndis_get_assoc       (struct ndis_softc *, ndis_wlan_bssid_ex **);
188 static int ndis_probe_offload   (struct ndis_softc *);
189 static int ndis_set_offload     (struct ndis_softc *);
190 static void ndis_getstate_80211 (struct ndis_softc *);
191 static void ndis_setstate_80211 (struct ndis_softc *);
192 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
193 static void ndis_media_status   (struct ifnet *, struct ifmediareq *);
194 static int ndis_set_cipher      (struct ndis_softc *, int);
195 static int ndis_set_wpa         (struct ndis_softc *, void *, int);
196 static int ndis_add_key         (struct ieee80211vap *,
197         const struct ieee80211_key *);
198 static int ndis_del_key         (struct ieee80211vap *,
199         const struct ieee80211_key *);
200 static void ndis_setmulti       (struct ndis_softc *);
201 static void ndis_map_sclist     (void *, bus_dma_segment_t *,
202         int, bus_size_t, int);
203 static int ndis_ifattach(struct ndis_softc *);
204
205 static int ndis_80211attach(struct ndis_softc *);
206 static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
207 static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
208 static void ndis_80211parent(struct ieee80211com *);
209
210 static int ndisdrv_loaded = 0;
211
212 /*
213  * This routine should call windrv_load() once for each driver
214  * image. This will do the relocation and dynalinking for the
215  * image, and create a Windows driver object which will be
216  * saved in our driver database.
217  */
218 int
219 ndisdrv_modevent(mod, cmd, arg)
220         module_t                mod;
221         int                     cmd;
222         void                    *arg;
223 {
224         int                     error = 0;
225
226         switch (cmd) {
227         case MOD_LOAD:
228                 ndisdrv_loaded++;
229                 if (ndisdrv_loaded > 1)
230                         break;
231                 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
232                     3, WINDRV_WRAP_STDCALL);
233                 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
234                     8, WINDRV_WRAP_STDCALL);
235                 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
236                     1, WINDRV_WRAP_STDCALL);
237                 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
238                     4, WINDRV_WRAP_STDCALL);
239                 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
240                     &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
241                 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
242                     3, WINDRV_WRAP_STDCALL);
243                 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
244                     4, WINDRV_WRAP_STDCALL);
245                 windrv_wrap((funcptr)ndis_linksts_done,
246                     &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
247                 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
248                     2, WINDRV_WRAP_STDCALL);
249                 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
250                     2, WINDRV_WRAP_STDCALL);
251                 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
252                     2, WINDRV_WRAP_STDCALL);
253                 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
254                     2, WINDRV_WRAP_STDCALL);
255                 break;
256         case MOD_UNLOAD:
257                 ndisdrv_loaded--;
258                 if (ndisdrv_loaded > 0)
259                         break;
260                 /* fallthrough */
261         case MOD_SHUTDOWN:
262                 windrv_unwrap(ndis_rxeof_wrap);
263                 windrv_unwrap(ndis_rxeof_eth_wrap);
264                 windrv_unwrap(ndis_rxeof_done_wrap);
265                 windrv_unwrap(ndis_rxeof_xfr_wrap);
266                 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
267                 windrv_unwrap(ndis_txeof_wrap);
268                 windrv_unwrap(ndis_linksts_wrap);
269                 windrv_unwrap(ndis_linksts_done_wrap);
270                 windrv_unwrap(ndis_ticktask_wrap);
271                 windrv_unwrap(ndis_starttask_wrap);
272                 windrv_unwrap(ndis_resettask_wrap);
273                 windrv_unwrap(ndis_inputtask_wrap);
274                 break;
275         default:
276                 error = EINVAL;
277                 break;
278         }
279
280         return (error);
281 }
282
283 /*
284  * Program the 64-bit multicast hash filter.
285  */
286 static void
287 ndis_setmulti(sc)
288         struct ndis_softc       *sc;
289 {
290         struct ifnet            *ifp;
291         struct ifmultiaddr      *ifma;
292         int                     len, mclistsz, error;
293         uint8_t                 *mclist;
294
295         ifp = sc->ifp;
296
297         if (!NDIS_INITIALIZED(sc))
298                 return;
299
300         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
302                 len = sizeof(sc->ndis_filter);
303                 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
304                     &sc->ndis_filter, &len);
305                 if (error)
306                         device_printf(sc->ndis_dev,
307                             "set allmulti failed: %d\n", error);
308                 return;
309         }
310
311         if (TAILQ_EMPTY(&ifp->if_multiaddrs))
312                 return;
313
314         len = sizeof(mclistsz);
315         ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
316
317         mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
318
319         if (mclist == NULL) {
320                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
321                 goto out;
322         }
323
324         sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
325
326         len = 0;
327         if_maddr_rlock(ifp);
328         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
329                 if (ifma->ifma_addr->sa_family != AF_LINK)
330                         continue;
331                 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
332                     mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
333                 len++;
334                 if (len > mclistsz) {
335                         if_maddr_runlock(ifp);
336                         sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
337                         sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
338                         goto out;
339                 }
340         }
341         if_maddr_runlock(ifp);
342
343         len = len * ETHER_ADDR_LEN;
344         error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
345         if (error) {
346                 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
347                 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
348                 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
349         }
350
351 out:
352         free(mclist, M_TEMP);
353
354         len = sizeof(sc->ndis_filter);
355         error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
356             &sc->ndis_filter, &len);
357         if (error)
358                 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
359 }
360
361 static int
362 ndis_set_offload(sc)
363         struct ndis_softc       *sc;
364 {
365         ndis_task_offload       *nto;
366         ndis_task_offload_hdr   *ntoh;
367         ndis_task_tcpip_csum    *nttc;
368         struct ifnet            *ifp;
369         int                     len, error;
370
371         ifp = sc->ifp;
372
373         if (!NDIS_INITIALIZED(sc))
374                 return (EINVAL);
375
376         /* See if there's anything to set. */
377
378         error = ndis_probe_offload(sc);
379         if (error)
380                 return (error);
381                 
382         if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
383                 return (0);
384
385         len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
386             sizeof(ndis_task_tcpip_csum);
387
388         ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
389
390         if (ntoh == NULL)
391                 return (ENOMEM);
392
393         ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
394         ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
395         ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
396         ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
397         ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
398         ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
399
400         nto = (ndis_task_offload *)((char *)ntoh +
401             ntoh->ntoh_offset_firsttask);
402
403         nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
404         nto->nto_len = sizeof(ndis_task_offload);
405         nto->nto_task = NDIS_TASK_TCPIP_CSUM;
406         nto->nto_offset_nexttask = 0;
407         nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
408
409         nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
410
411         if (ifp->if_capenable & IFCAP_TXCSUM)
412                 nttc->nttc_v4tx = sc->ndis_v4tx;
413
414         if (ifp->if_capenable & IFCAP_RXCSUM)
415                 nttc->nttc_v4rx = sc->ndis_v4rx;
416
417         error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418         free(ntoh, M_TEMP);
419
420         return (error);
421 }
422
423 static int
424 ndis_probe_offload(sc)
425         struct ndis_softc       *sc;
426 {
427         ndis_task_offload       *nto;
428         ndis_task_offload_hdr   *ntoh;
429         ndis_task_tcpip_csum    *nttc = NULL;
430         struct ifnet            *ifp;
431         int                     len, error, dummy;
432
433         ifp = sc->ifp;
434
435         len = sizeof(dummy);
436         error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
437
438         if (error != ENOSPC)
439                 return (error);
440
441         ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
442
443         if (ntoh == NULL)
444                 return (ENOMEM);
445
446         ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
447         ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
448         ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
449         ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
450         ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
451
452         error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
453
454         if (error) {
455                 free(ntoh, M_TEMP);
456                 return (error);
457         }
458
459         if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
460                 free(ntoh, M_TEMP);
461                 return (EINVAL);
462         }
463
464         nto = (ndis_task_offload *)((char *)ntoh +
465             ntoh->ntoh_offset_firsttask);
466
467         while (1) {
468                 switch (nto->nto_task) {
469                 case NDIS_TASK_TCPIP_CSUM:
470                         nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
471                         break;
472                 /* Don't handle these yet. */
473                 case NDIS_TASK_IPSEC:
474                 case NDIS_TASK_TCP_LARGESEND:
475                 default:
476                         break;
477                 }
478                 if (nto->nto_offset_nexttask == 0)
479                         break;
480                 nto = (ndis_task_offload *)((char *)nto +
481                     nto->nto_offset_nexttask);
482         }
483
484         if (nttc == NULL) {
485                 free(ntoh, M_TEMP);
486                 return (ENOENT);
487         }
488
489         sc->ndis_v4tx = nttc->nttc_v4tx;
490         sc->ndis_v4rx = nttc->nttc_v4rx;
491
492         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
493                 sc->ndis_hwassist |= CSUM_IP;
494         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
495                 sc->ndis_hwassist |= CSUM_TCP;
496         if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
497                 sc->ndis_hwassist |= CSUM_UDP;
498
499         if (sc->ndis_hwassist)
500                 ifp->if_capabilities |= IFCAP_TXCSUM;
501
502         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
503                 ifp->if_capabilities |= IFCAP_RXCSUM;
504         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
505                 ifp->if_capabilities |= IFCAP_RXCSUM;
506         if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
507                 ifp->if_capabilities |= IFCAP_RXCSUM;
508
509         free(ntoh, M_TEMP);
510         return (0);
511 }
512
513 static int
514 ndis_nettype_chan(uint32_t type)
515 {
516         switch (type) {
517         case NDIS_80211_NETTYPE_11FH:           return (IEEE80211_CHAN_FHSS);
518         case NDIS_80211_NETTYPE_11DS:           return (IEEE80211_CHAN_B);
519         case NDIS_80211_NETTYPE_11OFDM5:        return (IEEE80211_CHAN_A);
520         case NDIS_80211_NETTYPE_11OFDM24:       return (IEEE80211_CHAN_G);
521         }
522         DPRINTF(("unknown channel nettype %d\n", type));
523         return (IEEE80211_CHAN_B);      /* Default to 11B chan */
524 }
525
526 static int
527 ndis_nettype_mode(uint32_t type)
528 {
529         switch (type) {
530         case NDIS_80211_NETTYPE_11FH:           return (IEEE80211_MODE_FH);
531         case NDIS_80211_NETTYPE_11DS:           return (IEEE80211_MODE_11B);
532         case NDIS_80211_NETTYPE_11OFDM5:        return (IEEE80211_MODE_11A);
533         case NDIS_80211_NETTYPE_11OFDM24:       return (IEEE80211_MODE_11G);
534         }
535         DPRINTF(("unknown mode nettype %d\n", type));
536         return (IEEE80211_MODE_AUTO);
537 }
538
539 /*
540  * Attach the interface. Allocate softc structures, do ifmedia
541  * setup and ethernet/BPF attach.
542  */
543 int
544 ndis_attach(device_t dev)
545 {
546         struct ndis_softc       *sc;
547         driver_object           *pdrv;
548         device_object           *pdo;
549         int                     error = 0, len;
550         int                     i;
551
552         sc = device_get_softc(dev);
553
554         mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
555             MTX_DEF);
556         KeInitializeSpinLock(&sc->ndis_rxlock);
557         KeInitializeSpinLock(&sc->ndisusb_tasklock);
558         KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
559         InitializeListHead(&sc->ndis_shlist);
560         InitializeListHead(&sc->ndisusb_tasklist);
561         InitializeListHead(&sc->ndisusb_xferdonelist);
562         callout_init(&sc->ndis_stat_callout, 1);
563         mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
564
565         if (sc->ndis_iftype == PCMCIABus) {
566                 error = ndis_alloc_amem(sc);
567                 if (error) {
568                         device_printf(dev, "failed to allocate "
569                             "attribute memory\n");
570                         goto fail;
571                 }
572         }
573
574         /* Create sysctl registry nodes */
575         ndis_create_sysctls(sc);
576
577         /* Find the PDO for this device instance. */
578
579         if (sc->ndis_iftype == PCIBus)
580                 pdrv = windrv_lookup(0, "PCI Bus");
581         else if (sc->ndis_iftype == PCMCIABus)
582                 pdrv = windrv_lookup(0, "PCCARD Bus");
583         else
584                 pdrv = windrv_lookup(0, "USB Bus");
585         pdo = windrv_find_pdo(pdrv, dev);
586
587         /*
588          * Create a new functional device object for this
589          * device. This is what creates the miniport block
590          * for this device instance.
591          */
592
593         if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
594                 device_printf(dev, "failed to create FDO!\n");
595                 error = ENXIO;
596                 goto fail;
597         }
598
599         /* Tell the user what version of the API the driver is using. */
600         device_printf(dev, "NDIS API version: %d.%d\n",
601             sc->ndis_chars->nmc_version_major,
602             sc->ndis_chars->nmc_version_minor);
603
604         /* Do resource conversion. */
605         if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
606                 ndis_convert_res(sc);
607         else
608                 sc->ndis_block->nmb_rlist = NULL;
609
610         /* Install our RX and TX interrupt handlers. */
611         sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
612         sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
613         sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
614         sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
615         sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
616
617         /* Override the status handler so we can detect link changes. */
618         sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
619         sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
620
621         /* Set up work item handlers. */
622         sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623         sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624         sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625         sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626         sc->ndisusb_xferdoneitem =
627             IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
628         sc->ndisusb_taskitem =
629             IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630         KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
631
632         /* Call driver's init routine. */
633         if (ndis_init_nic(sc)) {
634                 device_printf(dev, "init handler failed\n");
635                 error = ENXIO;
636                 goto fail;
637         }
638
639         /*
640          * Figure out how big to make the TX buffer pool.
641          */
642         len = sizeof(sc->ndis_maxpkts);
643         if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
644                     &sc->ndis_maxpkts, &len)) {
645                 device_printf(dev, "failed to get max TX packets\n");
646                 error = ENXIO;
647                 goto fail;
648         }
649
650         /*
651          * If this is a deserialized miniport, we don't have
652          * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
653          */
654         if (!NDIS_SERIALIZED(sc->ndis_block))
655                 sc->ndis_maxpkts = NDIS_TXPKTS;
656
657         /* Enforce some sanity, just in case. */
658
659         if (sc->ndis_maxpkts == 0)
660                 sc->ndis_maxpkts = 10;
661
662         sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
663             sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
664
665         /* Allocate a pool of ndis_packets for TX encapsulation. */
666
667         NdisAllocatePacketPool(&i, &sc->ndis_txpool,
668             sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
669
670         if (i != NDIS_STATUS_SUCCESS) {
671                 sc->ndis_txpool = NULL;
672                 device_printf(dev, "failed to allocate TX packet pool");
673                 error = ENOMEM;
674                 goto fail;
675         }
676
677         sc->ndis_txpending = sc->ndis_maxpkts;
678
679         sc->ndis_oidcnt = 0;
680         /* Get supported oid list. */
681         ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
682
683         /* If the NDIS module requested scatter/gather, init maps. */
684         if (sc->ndis_sc)
685                 ndis_init_dma(sc);
686
687         /*
688          * See if the OID_802_11_CONFIGURATION OID is
689          * supported by this driver. If it is, then this an 802.11
690          * wireless driver, and we should set up media for wireless.
691          */
692         for (i = 0; i < sc->ndis_oidcnt; i++)
693                 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
694                         sc->ndis_80211 = 1;
695                         break;
696                 }
697
698         if (sc->ndis_80211)
699                 error = ndis_80211attach(sc);
700         else
701                 error = ndis_ifattach(sc);
702
703 fail:
704         if (error) {
705                 ndis_detach(dev);
706                 return (error);
707         }
708
709         if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
710                 return (error);
711
712         DPRINTF(("attach done.\n"));
713         /* We're done talking to the NIC for now; halt it. */
714         ndis_halt_nic(sc);
715         DPRINTF(("halting done.\n"));
716
717         return (error);
718 }
719
720 static int
721 ndis_80211attach(struct ndis_softc *sc)
722 {
723         struct ieee80211com     *ic = &sc->ndis_ic;
724         ndis_80211_rates_ex     rates;
725         struct ndis_80211_nettype_list *ntl;
726         uint32_t                arg;
727         int                     mode, i, r, len;
728         uint8_t                 bands = 0;
729
730         callout_init(&sc->ndis_scan_callout, 1);
731
732         ic->ic_softc = sc;
733         ic->ic_ioctl = ndis_80211ioctl;
734         ic->ic_name = device_get_nameunit(sc->ndis_dev);
735         ic->ic_opmode = IEEE80211_M_STA;
736         ic->ic_phytype = IEEE80211_T_DS;
737         ic->ic_caps = IEEE80211_C_8023ENCAP |
738                 IEEE80211_C_STA | IEEE80211_C_IBSS;
739         setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
740         len = 0;
741         r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
742         if (r != ENOSPC)
743                 goto nonettypes;
744         ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
745         r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
746         if (r != 0) {
747                 free(ntl, M_DEVBUF);
748                 goto nonettypes;
749         }
750
751         for (i = 0; i < ntl->ntl_items; i++) {
752                 mode = ndis_nettype_mode(ntl->ntl_type[i]);
753                 if (mode) {
754                         setbit(ic->ic_modecaps, mode);
755                         setbit(&bands, mode);
756                 } else
757                         device_printf(sc->ndis_dev, "Unknown nettype %d\n",
758                             ntl->ntl_type[i]);
759         }
760         free(ntl, M_DEVBUF);
761 nonettypes:
762         /* Default to 11b channels if the card did not supply any */
763         if (bands == 0) {
764                 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
765                 setbit(&bands, IEEE80211_MODE_11B);
766         }
767         len = sizeof(rates);
768         bzero((char *)&rates, len);
769         r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
770         if (r != 0)
771                 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
772         /*
773          * Since the supported rates only up to 8 can be supported,
774          * if this is not 802.11b we're just going to be faking it
775          * all up to heck.
776          */
777
778 #define TESTSETRATE(x, y)                                               \
779         do {                                                            \
780                 int                     i;                              \
781                 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) {   \
782                         if (ic->ic_sup_rates[x].rs_rates[i] == (y))     \
783                                 break;                                  \
784                 }                                                       \
785                 if (i == ic->ic_sup_rates[x].rs_nrates) {               \
786                         ic->ic_sup_rates[x].rs_rates[i] = (y);          \
787                         ic->ic_sup_rates[x].rs_nrates++;                \
788                 }                                                       \
789         } while (0)
790
791 #define SETRATE(x, y)   \
792         ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
793 #define INCRATE(x)      \
794         ic->ic_sup_rates[x].rs_nrates++
795
796         ic->ic_curmode = IEEE80211_MODE_AUTO;
797         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
798                 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
799         if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
800                 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
801         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
802                 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
803         for (i = 0; i < len; i++) {
804                 switch (rates[i] & IEEE80211_RATE_VAL) {
805                 case 2:
806                 case 4:
807                 case 11:
808                 case 10:
809                 case 22:
810                         if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
811                                 /* Lazy-init 802.11b. */
812                                 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
813                                 ic->ic_sup_rates[IEEE80211_MODE_11B].
814                                     rs_nrates = 0;
815                         }
816                         SETRATE(IEEE80211_MODE_11B, rates[i]);
817                         INCRATE(IEEE80211_MODE_11B);
818                         break;
819                 default:
820                         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
821                                 SETRATE(IEEE80211_MODE_11A, rates[i]);
822                                 INCRATE(IEEE80211_MODE_11A);
823                         }
824                         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
825                                 SETRATE(IEEE80211_MODE_11G, rates[i]);
826                                 INCRATE(IEEE80211_MODE_11G);
827                         }
828                         break;
829                 }
830         }
831
832         /*
833          * If the hardware supports 802.11g, it most
834          * likely supports 802.11b and all of the
835          * 802.11b and 802.11g speeds, so maybe we can
836          * just cheat here.  Just how in the heck do
837          * we detect turbo modes, though?
838          */
839         if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
840                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
841                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
842                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
843                 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
844         }
845         if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
846                 TESTSETRATE(IEEE80211_MODE_11G, 48);
847                 TESTSETRATE(IEEE80211_MODE_11G, 72);
848                 TESTSETRATE(IEEE80211_MODE_11G, 96);
849                 TESTSETRATE(IEEE80211_MODE_11G, 108);
850         }
851         if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
852                 TESTSETRATE(IEEE80211_MODE_11A, 48);
853                 TESTSETRATE(IEEE80211_MODE_11A, 72);
854                 TESTSETRATE(IEEE80211_MODE_11A, 96);
855                 TESTSETRATE(IEEE80211_MODE_11A, 108);
856         }
857
858 #undef SETRATE
859 #undef INCRATE
860 #undef TESTSETRATE
861
862         ieee80211_init_channels(ic, NULL, &bands);
863
864         /*
865          * To test for WPA support, we need to see if we can
866          * set AUTHENTICATION_MODE to WPA and read it back
867          * successfully.
868          */
869         i = sizeof(arg);
870         arg = NDIS_80211_AUTHMODE_WPA;
871         r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
872         if (r == 0) {
873                 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
874                 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
875                         ic->ic_caps |= IEEE80211_C_WPA;
876         }
877
878         /*
879          * To test for supported ciphers, we set each
880          * available encryption type in descending order.
881          * If ENC3 works, then we have WEP, TKIP and AES.
882          * If only ENC2 works, then we have WEP and TKIP.
883          * If only ENC1 works, then we have just WEP.
884          */
885         i = sizeof(arg);
886         arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
887         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
888         if (r == 0) {
889                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
890                                   |  IEEE80211_CRYPTO_TKIP
891                                   |  IEEE80211_CRYPTO_AES_CCM;
892                 goto got_crypto;
893         }
894         arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
895         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
896         if (r == 0) {
897                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
898                                   |  IEEE80211_CRYPTO_TKIP;
899                 goto got_crypto;
900         }
901         arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
902         r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
903         if (r == 0)
904                 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
905 got_crypto:
906         i = sizeof(arg);
907         r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
908         if (r == 0)
909                 ic->ic_caps |= IEEE80211_C_PMGT;
910
911         r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
912         if (r == 0)
913                 ic->ic_caps |= IEEE80211_C_TXPMGT;
914
915         /*
916          * Get station address from the driver.
917          */
918         len = sizeof(ic->ic_macaddr);
919         ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
920
921         ieee80211_ifattach(ic);
922         ic->ic_raw_xmit = ndis_raw_xmit;
923         ic->ic_scan_start = ndis_scan_start;
924         ic->ic_scan_end = ndis_scan_end;
925         ic->ic_set_channel = ndis_set_channel;
926         ic->ic_scan_curchan = ndis_scan_curchan;
927         ic->ic_scan_mindwell = ndis_scan_mindwell;
928         ic->ic_bsschan = IEEE80211_CHAN_ANYC;
929         ic->ic_vap_create = ndis_vap_create;
930         ic->ic_vap_delete = ndis_vap_delete;
931         ic->ic_update_mcast = ndis_update_mcast;
932         ic->ic_update_promisc = ndis_update_promisc;
933         ic->ic_transmit = ndis_80211transmit;
934         ic->ic_parent = ndis_80211parent;
935
936         if (bootverbose)
937                 ieee80211_announce(ic);
938
939         return (0);
940 }
941
942 static int
943 ndis_ifattach(struct ndis_softc *sc)
944 {
945         struct ifnet *ifp;
946         u_char eaddr[ETHER_ADDR_LEN];
947         int len;
948
949         ifp = if_alloc(IFT_ETHER);
950         if (ifp == NULL)
951                 return (ENOSPC);
952         sc->ifp = ifp;
953         ifp->if_softc = sc;
954
955         /* Check for task offload support. */
956         ndis_probe_offload(sc);
957
958         /*
959          * Get station address from the driver.
960          */
961         len = sizeof(eaddr);
962         ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
963
964         if_initname(ifp, device_get_name(sc->ndis_dev),
965             device_get_unit(sc->ndis_dev));
966         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
967         ifp->if_ioctl = ndis_ioctl;
968         ifp->if_start = ndis_start;
969         ifp->if_init = ndis_init;
970         ifp->if_baudrate = 10000000;
971         IFQ_SET_MAXLEN(&ifp->if_snd, 50);
972         ifp->if_snd.ifq_drv_maxlen = 25;
973         IFQ_SET_READY(&ifp->if_snd);
974         ifp->if_capenable = ifp->if_capabilities;
975         ifp->if_hwassist = sc->ndis_hwassist;
976
977         ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
978             ndis_ifmedia_sts);
979         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
980         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
981         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
982         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
983         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
984         ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
985         ether_ifattach(ifp, eaddr);
986
987         return (0);
988 }
989
990 static struct ieee80211vap *
991 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
992     enum ieee80211_opmode opmode, int flags,
993     const uint8_t bssid[IEEE80211_ADDR_LEN],
994     const uint8_t mac[IEEE80211_ADDR_LEN])
995 {
996         struct ndis_vap *nvp;
997         struct ieee80211vap *vap;
998
999         if (!TAILQ_EMPTY(&ic->ic_vaps))         /* only one at a time */
1000                 return NULL;
1001         nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1002         vap = &nvp->vap;
1003         ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1004         /* override with driver methods */
1005         nvp->newstate = vap->iv_newstate;
1006         vap->iv_newstate = ndis_newstate;
1007
1008         /* complete setup */
1009         ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1010             mac);
1011         ic->ic_opmode = opmode;
1012         /* install key handing routines */
1013         vap->iv_key_set = ndis_add_key;
1014         vap->iv_key_delete = ndis_del_key;
1015         return vap;
1016 }
1017
1018 static void
1019 ndis_vap_delete(struct ieee80211vap *vap)
1020 {
1021         struct ndis_vap *nvp = NDIS_VAP(vap);
1022         struct ieee80211com *ic = vap->iv_ic;
1023         struct ndis_softc *sc = ic->ic_softc;
1024
1025         ndis_stop(sc);
1026         callout_drain(&sc->ndis_scan_callout);
1027         ieee80211_vap_detach(vap);
1028         free(nvp, M_80211_VAP);
1029 }
1030
1031 /*
1032  * Shutdown hardware and free up resources. This can be called any
1033  * time after the mutex has been initialized. It is called in both
1034  * the error case in attach and the normal detach case so it needs
1035  * to be careful about only freeing resources that have actually been
1036  * allocated.
1037  */
1038 int
1039 ndis_detach(device_t dev)
1040 {
1041         struct ifnet            *ifp;
1042         struct ndis_softc       *sc;
1043         driver_object           *drv;
1044
1045         sc = device_get_softc(dev);
1046         NDIS_LOCK(sc);
1047         if (!sc->ndis_80211)
1048                 ifp = sc->ifp;
1049         else
1050                 ifp = NULL;
1051         if (ifp != NULL)
1052                 ifp->if_flags &= ~IFF_UP;
1053         if (device_is_attached(dev)) {
1054                 NDIS_UNLOCK(sc);
1055                 ndis_stop(sc);
1056                 if (sc->ndis_80211)
1057                         ieee80211_ifdetach(&sc->ndis_ic);
1058                 else if (ifp != NULL)
1059                         ether_ifdetach(ifp);
1060         } else
1061                 NDIS_UNLOCK(sc);
1062
1063         if (sc->ndis_tickitem != NULL)
1064                 IoFreeWorkItem(sc->ndis_tickitem);
1065         if (sc->ndis_startitem != NULL)
1066                 IoFreeWorkItem(sc->ndis_startitem);
1067         if (sc->ndis_resetitem != NULL)
1068                 IoFreeWorkItem(sc->ndis_resetitem);
1069         if (sc->ndis_inputitem != NULL)
1070                 IoFreeWorkItem(sc->ndis_inputitem);
1071         if (sc->ndisusb_xferdoneitem != NULL)
1072                 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1073         if (sc->ndisusb_taskitem != NULL)
1074                 IoFreeWorkItem(sc->ndisusb_taskitem);
1075
1076         bus_generic_detach(dev);
1077         ndis_unload_driver(sc);
1078
1079         if (sc->ndis_irq)
1080                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1081         if (sc->ndis_res_io)
1082                 bus_release_resource(dev, SYS_RES_IOPORT,
1083                     sc->ndis_io_rid, sc->ndis_res_io);
1084         if (sc->ndis_res_mem)
1085                 bus_release_resource(dev, SYS_RES_MEMORY,
1086                     sc->ndis_mem_rid, sc->ndis_res_mem);
1087         if (sc->ndis_res_altmem)
1088                 bus_release_resource(dev, SYS_RES_MEMORY,
1089                     sc->ndis_altmem_rid, sc->ndis_res_altmem);
1090
1091         if (ifp != NULL)
1092                 if_free(ifp);
1093
1094         if (sc->ndis_iftype == PCMCIABus)
1095                 ndis_free_amem(sc);
1096
1097         if (sc->ndis_sc)
1098                 ndis_destroy_dma(sc);
1099
1100         if (sc->ndis_txarray)
1101                 free(sc->ndis_txarray, M_DEVBUF);
1102
1103         if (!sc->ndis_80211)
1104                 ifmedia_removeall(&sc->ifmedia);
1105
1106         if (sc->ndis_txpool != NULL)
1107                 NdisFreePacketPool(sc->ndis_txpool);
1108
1109         /* Destroy the PDO for this device. */
1110         
1111         if (sc->ndis_iftype == PCIBus)
1112                 drv = windrv_lookup(0, "PCI Bus");
1113         else if (sc->ndis_iftype == PCMCIABus)
1114                 drv = windrv_lookup(0, "PCCARD Bus");
1115         else
1116                 drv = windrv_lookup(0, "USB Bus");
1117         if (drv == NULL)
1118                 panic("couldn't find driver object");
1119         windrv_destroy_pdo(drv, dev);
1120
1121         if (sc->ndis_iftype == PCIBus)
1122                 bus_dma_tag_destroy(sc->ndis_parent_tag);
1123
1124         return (0);
1125 }
1126
1127 int
1128 ndis_suspend(dev)
1129         device_t                dev;
1130 {
1131         struct ndis_softc       *sc;
1132         struct ifnet            *ifp;
1133
1134         sc = device_get_softc(dev);
1135         ifp = sc->ifp;
1136
1137 #ifdef notdef
1138         if (NDIS_INITIALIZED(sc))
1139                 ndis_stop(sc);
1140 #endif
1141
1142         return (0);
1143 }
1144
1145 int
1146 ndis_resume(dev)
1147         device_t                dev;
1148 {
1149         struct ndis_softc       *sc;
1150         struct ifnet            *ifp;
1151
1152         sc = device_get_softc(dev);
1153         ifp = sc->ifp;
1154
1155         if (NDIS_INITIALIZED(sc))
1156                 ndis_init(sc);
1157
1158         return (0);
1159 }
1160
1161 /*
1162  * The following bunch of routines are here to support drivers that
1163  * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1164  * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1165  * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1166  * miniports.
1167  */
1168 static void
1169 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1170         ndis_handle             adapter;
1171         ndis_handle             ctx;
1172         char                    *addr;
1173         void                    *hdr;
1174         uint32_t                hdrlen;
1175         void                    *lookahead;
1176         uint32_t                lookaheadlen;
1177         uint32_t                pktlen;
1178 {
1179         ndis_miniport_block     *block;
1180         uint8_t                 irql = 0;
1181         uint32_t                status;
1182         ndis_buffer             *b;
1183         ndis_packet             *p;
1184         struct mbuf             *m;
1185         ndis_ethpriv            *priv;
1186
1187         block = adapter;
1188
1189         m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1190         if (m == NULL)
1191                 return;
1192
1193         /* Save the data provided to us so far. */
1194
1195         m->m_len = lookaheadlen + hdrlen;
1196         m->m_pkthdr.len = pktlen + hdrlen;
1197         m->m_next = NULL;
1198         m_copyback(m, 0, hdrlen, hdr);
1199         m_copyback(m, hdrlen, lookaheadlen, lookahead);
1200
1201         /* Now create a fake NDIS_PACKET to hold the data */
1202
1203         NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1204
1205         if (status != NDIS_STATUS_SUCCESS) {
1206                 m_freem(m);
1207                 return;
1208         }
1209
1210         p->np_m0 = m;
1211
1212         b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1213
1214         if (b == NULL) {
1215                 NdisFreePacket(p);
1216                 m_freem(m);
1217                 return;
1218         }
1219
1220         p->np_private.npp_head = p->np_private.npp_tail = b;
1221         p->np_private.npp_totlen = m->m_pkthdr.len;
1222
1223         /* Save the packet RX context somewhere. */
1224         priv = (ndis_ethpriv *)&p->np_protocolreserved;
1225         priv->nep_ctx = ctx;
1226
1227         if (!NDIS_SERIALIZED(block))
1228                 KeAcquireSpinLock(&block->nmb_lock, &irql);
1229
1230         InsertTailList((&block->nmb_packetlist), (&p->np_list));
1231
1232         if (!NDIS_SERIALIZED(block))
1233                 KeReleaseSpinLock(&block->nmb_lock, irql);
1234 }
1235
1236 /*
1237  * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1238  * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1239  * miniports.
1240  */
1241 static void
1242 ndis_rxeof_done(adapter)
1243         ndis_handle             adapter;
1244 {
1245         struct ndis_softc       *sc;
1246         ndis_miniport_block     *block;
1247
1248         block = adapter;
1249
1250         /* Schedule transfer/RX of queued packets. */
1251
1252         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1253
1254         KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1255 }
1256
1257 /*
1258  * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1259  */
1260 static void
1261 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1262         kdpc                    *dpc;
1263         ndis_handle             adapter;
1264         void                    *sysarg1;
1265         void                    *sysarg2;
1266 {
1267         ndis_miniport_block     *block;
1268         struct ndis_softc       *sc;
1269         ndis_packet             *p;
1270         list_entry              *l;
1271         uint32_t                status;
1272         ndis_ethpriv            *priv;
1273         struct ifnet            *ifp;
1274         struct mbuf             *m;
1275
1276         block = adapter;
1277         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1278         ifp = sc->ifp;
1279
1280         KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1281
1282         l = block->nmb_packetlist.nle_flink;
1283         while(!IsListEmpty(&block->nmb_packetlist)) {
1284                 l = RemoveHeadList((&block->nmb_packetlist));
1285                 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1286                 InitializeListHead((&p->np_list));
1287
1288                 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1289                 m = p->np_m0;
1290                 p->np_softc = sc;
1291                 p->np_m0 = NULL;
1292
1293                 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1294
1295                 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1296                     p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1297                     m->m_len, m->m_pkthdr.len - m->m_len);
1298
1299                 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1300
1301                 /*
1302                  * If status is NDIS_STATUS_PENDING, do nothing and
1303                  * wait for a callback to the ndis_rxeof_xfr_done()
1304                  * handler.
1305                  */
1306
1307                 m->m_len = m->m_pkthdr.len;
1308                 m->m_pkthdr.rcvif = ifp;
1309
1310                 if (status == NDIS_STATUS_SUCCESS) {
1311                         IoFreeMdl(p->np_private.npp_head);
1312                         NdisFreePacket(p);
1313                         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1314                         mbufq_enqueue(&sc->ndis_rxqueue, m);
1315                         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1316                         IoQueueWorkItem(sc->ndis_inputitem,
1317                             (io_workitem_func)ndis_inputtask_wrap,
1318                             WORKQUEUE_CRITICAL, sc);
1319                 }
1320
1321                 if (status == NDIS_STATUS_FAILURE)
1322                         m_freem(m);
1323
1324                 /* Advance to next packet */
1325                 l = block->nmb_packetlist.nle_flink;
1326         }
1327
1328         KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1329 }
1330
1331 /*
1332  * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1333  */
1334 static void
1335 ndis_rxeof_xfr_done(adapter, packet, status, len)
1336         ndis_handle             adapter;
1337         ndis_packet             *packet;
1338         uint32_t                status;
1339         uint32_t                len;
1340 {
1341         ndis_miniport_block     *block;
1342         struct ndis_softc       *sc;
1343         struct ifnet            *ifp;
1344         struct mbuf             *m;
1345
1346         block = adapter;
1347         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1348         ifp = sc->ifp;
1349
1350         m = packet->np_m0;
1351         IoFreeMdl(packet->np_private.npp_head);
1352         NdisFreePacket(packet);
1353
1354         if (status != NDIS_STATUS_SUCCESS) {
1355                 m_freem(m);
1356                 return;
1357         }
1358
1359         m->m_len = m->m_pkthdr.len;
1360         m->m_pkthdr.rcvif = ifp;
1361         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1362         mbufq_enqueue(&sc->ndis_rxqueue, m);
1363         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1364         IoQueueWorkItem(sc->ndis_inputitem,
1365             (io_workitem_func)ndis_inputtask_wrap,
1366             WORKQUEUE_CRITICAL, sc);
1367 }
1368 /*
1369  * A frame has been uploaded: pass the resulting mbuf chain up to
1370  * the higher level protocols.
1371  *
1372  * When handling received NDIS packets, the 'status' field in the
1373  * out-of-band portion of the ndis_packet has special meaning. In the
1374  * most common case, the underlying NDIS driver will set this field
1375  * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1376  * take posession of it. We then change the status field to
1377  * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1378  * and that we will return it at some point in the future via the
1379  * return packet handler.
1380  *
1381  * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1382  * this means the driver is running out of packet/buffer resources and
1383  * wants to maintain ownership of the packet. In this case, we have to
1384  * copy the packet data into local storage and let the driver keep the
1385  * packet.
1386  */
1387 static void
1388 ndis_rxeof(adapter, packets, pktcnt)
1389         ndis_handle             adapter;
1390         ndis_packet             **packets;
1391         uint32_t                pktcnt;
1392 {
1393         struct ndis_softc       *sc;
1394         ndis_miniport_block     *block;
1395         ndis_packet             *p;
1396         uint32_t                s;
1397         ndis_tcpip_csum         *csum;
1398         struct ifnet            *ifp;
1399         struct mbuf             *m0, *m;
1400         int                     i;
1401
1402         block = (ndis_miniport_block *)adapter;
1403         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1404         ifp = sc->ifp;
1405
1406         /*
1407          * There's a slim chance the driver may indicate some packets
1408          * before we're completely ready to handle them. If we detect this,
1409          * we need to return them to the miniport and ignore them.
1410          */
1411         if (!sc->ndis_running) {
1412                 for (i = 0; i < pktcnt; i++) {
1413                         p = packets[i];
1414                         if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1415                                 p->np_refcnt++;
1416                                 (void)ndis_return_packet(NULL ,p, block);
1417                         }
1418                 }
1419                 return;
1420         }
1421
1422         for (i = 0; i < pktcnt; i++) {
1423                 p = packets[i];
1424                 /* Stash the softc here so ptom can use it. */
1425                 p->np_softc = sc;
1426                 if (ndis_ptom(&m0, p)) {
1427                         device_printf(sc->ndis_dev, "ptom failed\n");
1428                         if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1429                                 (void)ndis_return_packet(NULL, p, block);
1430                 } else {
1431 #ifdef notdef
1432                         if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1433                                 m = m_dup(m0, M_NOWAIT);
1434                                 /*
1435                                  * NOTE: we want to destroy the mbuf here, but
1436                                  * we don't actually want to return it to the
1437                                  * driver via the return packet handler. By
1438                                  * bumping np_refcnt, we can prevent the
1439                                  * ndis_return_packet() routine from actually
1440                                  * doing anything.
1441                                  */
1442                                 p->np_refcnt++;
1443                                 m_freem(m0);
1444                                 if (m == NULL)
1445                                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1446                                 else
1447                                         m0 = m;
1448                         } else
1449                                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1450 #endif
1451                         m = m_dup(m0, M_NOWAIT);
1452                         if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1453                                 p->np_refcnt++;
1454                         else
1455                                 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1456                         m_freem(m0);
1457                         if (m == NULL) {
1458                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1459                                 continue;
1460                         }
1461                         m0 = m;
1462                         m0->m_pkthdr.rcvif = ifp;
1463
1464                         /* Deal with checksum offload. */
1465
1466                         if (ifp->if_capenable & IFCAP_RXCSUM &&
1467                             p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1468                                 s = (uintptr_t)
1469                                     p->np_ext.npe_info[ndis_tcpipcsum_info];
1470                                 csum = (ndis_tcpip_csum *)&s;
1471                                 if (csum->u.ntc_rxflags &
1472                                     NDIS_RXCSUM_IP_PASSED)
1473                                         m0->m_pkthdr.csum_flags |=
1474                                             CSUM_IP_CHECKED|CSUM_IP_VALID;
1475                                 if (csum->u.ntc_rxflags &
1476                                     (NDIS_RXCSUM_TCP_PASSED |
1477                                     NDIS_RXCSUM_UDP_PASSED)) {
1478                                         m0->m_pkthdr.csum_flags |=
1479                                             CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1480                                         m0->m_pkthdr.csum_data = 0xFFFF;
1481                                 }
1482                         }
1483
1484                         KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1485                         mbufq_enqueue(&sc->ndis_rxqueue, m0);
1486                         KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1487                         IoQueueWorkItem(sc->ndis_inputitem,
1488                             (io_workitem_func)ndis_inputtask_wrap,
1489                             WORKQUEUE_CRITICAL, sc);
1490                 }
1491         }
1492 }
1493
1494 /*
1495  * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1496  * packets into the stack in order to avoid calling (*ifp->if_input)()
1497  * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1498  * 'dispatch level' per-cpu sleep lock).
1499  */
1500 static void
1501 ndis_inputtask(device_object *dobj, void *arg)
1502 {
1503         ndis_miniport_block     *block;
1504         struct ndis_softc       *sc = arg;
1505         struct mbuf             *m;
1506         uint8_t                 irql;
1507
1508         block = dobj->do_devext;
1509
1510         KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1511         while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1512                 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1513                 if ((sc->ndis_80211 != 0)) {
1514                         struct ieee80211com *ic = &sc->ndis_ic;
1515                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1516
1517                         if (vap != NULL)
1518                                 vap->iv_deliver_data(vap, vap->iv_bss, m);
1519                 } else {
1520                         struct ifnet *ifp = sc->ifp;
1521
1522                         (*ifp->if_input)(ifp, m);
1523                 }
1524                 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1525         }
1526         KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1527 }
1528
1529 /*
1530  * A frame was downloaded to the chip. It's safe for us to clean up
1531  * the list buffers.
1532  */
1533 static void
1534 ndis_txeof(adapter, packet, status)
1535         ndis_handle             adapter;
1536         ndis_packet             *packet;
1537         ndis_status             status;
1538
1539 {
1540         struct ndis_softc       *sc;
1541         ndis_miniport_block     *block;
1542         struct ifnet            *ifp;
1543         int                     idx;
1544         struct mbuf             *m;
1545
1546         block = (ndis_miniport_block *)adapter;
1547         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1548         ifp = sc->ifp;
1549
1550         m = packet->np_m0;
1551         idx = packet->np_txidx;
1552         if (sc->ndis_sc)
1553                 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1554
1555         ndis_free_packet(packet);
1556         m_freem(m);
1557
1558         NDIS_LOCK(sc);
1559         sc->ndis_txarray[idx] = NULL;
1560         sc->ndis_txpending++;
1561
1562         if (status == NDIS_STATUS_SUCCESS)
1563                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1564         else
1565                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1566
1567         sc->ndis_tx_timer = 0;
1568         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1569
1570         NDIS_UNLOCK(sc);
1571
1572         IoQueueWorkItem(sc->ndis_startitem,
1573             (io_workitem_func)ndis_starttask_wrap,
1574             WORKQUEUE_CRITICAL, ifp);
1575 }
1576
1577 static void
1578 ndis_linksts(adapter, status, sbuf, slen)
1579         ndis_handle             adapter;
1580         ndis_status             status;
1581         void                    *sbuf;
1582         uint32_t                slen;
1583 {
1584         ndis_miniport_block     *block;
1585         struct ndis_softc       *sc;
1586
1587         block = adapter;
1588         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1589         sc->ndis_sts = status;
1590
1591         /* Event list is all full up, drop this one. */
1592
1593         NDIS_LOCK(sc);
1594         if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1595                 NDIS_UNLOCK(sc);
1596                 return;
1597         }
1598
1599         /* Cache the event. */
1600
1601         if (slen) {
1602                 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1603                     M_TEMP, M_NOWAIT);
1604                 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1605                         NDIS_UNLOCK(sc);
1606                         return;
1607                 }
1608                 bcopy((char *)sbuf,
1609                     sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1610         }
1611         sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1612         sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1613         NDIS_EVTINC(sc->ndis_evtpidx);
1614         NDIS_UNLOCK(sc);
1615 }
1616
1617 static void
1618 ndis_linksts_done(adapter)
1619         ndis_handle             adapter;
1620 {
1621         ndis_miniport_block     *block;
1622         struct ndis_softc       *sc;
1623         struct ifnet            *ifp;
1624
1625         block = adapter;
1626         sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1627         ifp = sc->ifp;
1628
1629         if (!NDIS_INITIALIZED(sc))
1630                 return;
1631
1632         switch (sc->ndis_sts) {
1633         case NDIS_STATUS_MEDIA_CONNECT:
1634                 IoQueueWorkItem(sc->ndis_tickitem, 
1635                     (io_workitem_func)ndis_ticktask_wrap,
1636                     WORKQUEUE_CRITICAL, sc);
1637                 IoQueueWorkItem(sc->ndis_startitem,
1638                     (io_workitem_func)ndis_starttask_wrap,
1639                     WORKQUEUE_CRITICAL, ifp);
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                 IoQueueWorkItem(sc->ndis_startitem,
1675                     (io_workitem_func)ndis_starttask_wrap,
1676                     WORKQUEUE_CRITICAL, sc->ifp);
1677         }
1678
1679         callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1680 }
1681
1682 static void
1683 ndis_ticktask(device_object *d, void *xsc)
1684 {
1685         struct ndis_softc       *sc = xsc;
1686         ndis_checkforhang_handler hangfunc;
1687         uint8_t                 rval;
1688
1689         NDIS_LOCK(sc);
1690         if (!NDIS_INITIALIZED(sc)) {
1691                 NDIS_UNLOCK(sc);
1692                 return;
1693         }
1694         NDIS_UNLOCK(sc);
1695
1696         hangfunc = sc->ndis_chars->nmc_checkhang_func;
1697
1698         if (hangfunc != NULL) {
1699                 rval = MSCALL1(hangfunc,
1700                     sc->ndis_block->nmb_miniportadapterctx);
1701                 if (rval == TRUE) {
1702                         ndis_reset_nic(sc);
1703                         return;
1704                 }
1705         }
1706
1707         NDIS_LOCK(sc);
1708         if (sc->ndis_link == 0 &&
1709             sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1710                 sc->ndis_link = 1;
1711                 if (sc->ndis_80211 != 0) {
1712                         struct ieee80211com *ic = &sc->ndis_ic;
1713                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1714
1715                         if (vap != NULL) {
1716                                 NDIS_UNLOCK(sc);
1717                                 ndis_getstate_80211(sc);
1718                                 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1719                                 NDIS_LOCK(sc);
1720                                 if_link_state_change(vap->iv_ifp,
1721                                     LINK_STATE_UP);
1722                         }
1723                 } else
1724                         if_link_state_change(sc->ifp, LINK_STATE_UP);
1725         }
1726
1727         if (sc->ndis_link == 1 &&
1728             sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1729                 sc->ndis_link = 0;
1730                 if (sc->ndis_80211 != 0) {
1731                         struct ieee80211com *ic = &sc->ndis_ic;
1732                         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1733
1734                         if (vap != NULL) {
1735                                 NDIS_UNLOCK(sc);
1736                                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1737                                 NDIS_LOCK(sc);
1738                                 if_link_state_change(vap->iv_ifp,
1739                                     LINK_STATE_DOWN);
1740                         }
1741                 } else
1742                         if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1743         }
1744
1745         NDIS_UNLOCK(sc);
1746 }
1747
1748 static void
1749 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1750         void                    *arg;
1751         bus_dma_segment_t       *segs;
1752         int                     nseg;
1753         bus_size_t              mapsize;
1754         int                     error;
1755
1756 {
1757         struct ndis_sc_list     *sclist;
1758         int                     i;
1759
1760         if (error || arg == NULL)
1761                 return;
1762
1763         sclist = arg;
1764
1765         sclist->nsl_frags = nseg;
1766
1767         for (i = 0; i < nseg; i++) {
1768                 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1769                 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1770         }
1771 }
1772
1773 static int
1774 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1775         const struct ieee80211_bpf_params *params)
1776 {
1777         /* no support; just discard */
1778         m_freem(m);
1779         ieee80211_free_node(ni);
1780         return (0);
1781 }
1782
1783 static void
1784 ndis_update_mcast(struct ieee80211com *ic)
1785 {
1786        struct ndis_softc *sc = ic->ic_softc;
1787
1788        ndis_setmulti(sc);
1789 }
1790
1791 static void
1792 ndis_update_promisc(struct ieee80211com *ic)
1793 {
1794        /* not supported */
1795 }
1796
1797 static void
1798 ndis_starttask(d, arg)
1799         device_object           *d;
1800         void                    *arg;
1801 {
1802         struct ifnet            *ifp;
1803
1804         ifp = arg;
1805
1806         if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1807                 ndis_start(ifp);
1808 }
1809
1810 /*
1811  * Main transmit routine. To make NDIS drivers happy, we need to
1812  * transform mbuf chains into NDIS packets and feed them to the
1813  * send packet routines. Most drivers allow you to send several
1814  * packets at once (up to the maxpkts limit). Unfortunately, rather
1815  * that accepting them in the form of a linked list, they expect
1816  * a contiguous array of pointers to packets.
1817  *
1818  * For those drivers which use the NDIS scatter/gather DMA mechanism,
1819  * we need to perform busdma work here. Those that use map registers
1820  * will do the mapping themselves on a buffer by buffer basis.
1821  */
1822 static void
1823 ndis_start(ifp)
1824         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 < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
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 < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); 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_ioctl(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->ifr_data, &oid, sizeof(oid));
2967                 if (error)
2968                         break;
2969                 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2970                 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2971         }
2972
2973         if (error) {
2974                 free(oidbuf, M_TEMP);
2975                 return (error);
2976         }
2977
2978         switch (cmd) {
2979         case SIOCGDRVSPEC:
2980                 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2981                 break;
2982         case SIOCSDRVSPEC:
2983                 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2984                 break;
2985         case SIOCGPRIVATE_0:
2986                 NDIS_LOCK(sc);
2987                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2988                         error = ENOENT;
2989                         NDIS_UNLOCK(sc);
2990                         break;
2991                 }
2992                 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2993                 if (error) {
2994                         NDIS_UNLOCK(sc);
2995                         break;
2996                 }
2997                 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2998                         error = ENOSPC;
2999                         NDIS_UNLOCK(sc);
3000                         break;
3001                 }
3002                 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3003                     ifr->ifr_data, sizeof(uint32_t) * 2);
3004                 if (error) {
3005                         NDIS_UNLOCK(sc);
3006                         break;
3007                 }
3008                 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3009                         error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3010                             ifr->ifr_data + (sizeof(uint32_t) * 2),
3011                             sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3012                         if (error) {
3013                                 NDIS_UNLOCK(sc);
3014                                 break;
3015                         }
3016                         free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3017                         sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3018                 }
3019                 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3020                 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3021                 NDIS_EVTINC(sc->ndis_evtcidx);
3022                 NDIS_UNLOCK(sc);
3023                 break;
3024         default:
3025                 error = ENOTTY;
3026                 break;
3027         }
3028
3029         switch (cmd) {
3030         case SIOCGDRVSPEC:
3031         case SIOCSDRVSPEC:
3032                 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3033                 if (error)
3034                         break;
3035                 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3036         }
3037
3038         free(oidbuf, M_TEMP);
3039
3040         return (error);
3041 }
3042
3043 int
3044 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3045 {
3046         struct ndis_softc       *sc = vap->iv_ic->ic_softc;
3047         ndis_80211_key          rkey;
3048         int                     len, error = 0;
3049
3050         bzero((char *)&rkey, sizeof(rkey));
3051         len = sizeof(rkey);
3052
3053         rkey.nk_len = len;
3054         rkey.nk_keyidx = key->wk_keyix;
3055
3056         bcopy(vap->iv_ifp->if_broadcastaddr,
3057             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3058
3059         error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3060
3061         if (error)
3062                 return (0);
3063
3064         return (1);
3065 }
3066
3067 /*
3068  * In theory this could be called for any key, but we'll
3069  * only use it for WPA TKIP or AES keys. These need to be
3070  * set after initial authentication with the AP.
3071  */
3072 static int
3073 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3074 {
3075         struct ndis_softc       *sc = vap->iv_ic->ic_softc;
3076         ndis_80211_key          rkey;
3077         int                     len, error = 0;
3078
3079         switch (key->wk_cipher->ic_cipher) {
3080         case IEEE80211_CIPHER_TKIP:
3081
3082                 len = sizeof(ndis_80211_key);
3083                 bzero((char *)&rkey, sizeof(rkey));
3084
3085                 rkey.nk_len = len;
3086                 rkey.nk_keylen = key->wk_keylen;
3087
3088                 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3089                         rkey.nk_keylen += 16;
3090
3091                 /* key index - gets weird in NDIS */
3092
3093                 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3094                         rkey.nk_keyidx = key->wk_keyix;
3095                 else
3096                         rkey.nk_keyidx = 0;
3097
3098                 if (key->wk_flags & IEEE80211_KEY_XMIT)
3099                         rkey.nk_keyidx |= 1 << 31;
3100
3101                 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3102                         bcopy(ieee80211broadcastaddr,
3103                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3104                 } else {
3105                         bcopy(vap->iv_bss->ni_bssid,
3106                             rkey.nk_bssid, IEEE80211_ADDR_LEN);
3107                         /* pairwise key */
3108                         rkey.nk_keyidx |= 1 << 30;
3109                 }
3110
3111                 /* need to set bit 29 based on keyrsc */
3112                 rkey.nk_keyrsc = key->wk_keyrsc[0];     /* XXX need tid */
3113
3114                 if (rkey.nk_keyrsc)
3115                         rkey.nk_keyidx |= 1 << 29;
3116
3117                 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3118                         bcopy(key->wk_key, rkey.nk_keydata, 16);
3119                         bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3120                         bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3121                 } else
3122                         bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3123
3124                 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3125                 break;
3126         case IEEE80211_CIPHER_WEP:
3127                 error = 0;
3128                 break;
3129         /*
3130          * I don't know how to set up keys for the AES
3131          * cipher yet. Is it the same as TKIP?
3132          */
3133         case IEEE80211_CIPHER_AES_CCM:
3134         default:
3135                 error = ENOTTY;
3136                 break;
3137         }
3138
3139         /* We need to return 1 for success, 0 for failure. */
3140
3141         if (error)
3142                 return (0);
3143
3144         return (1);
3145 }
3146
3147 static void
3148 ndis_resettask(d, arg)
3149         device_object           *d;
3150         void                    *arg;
3151 {
3152         struct ndis_softc               *sc;
3153
3154         sc = arg;
3155         ndis_reset_nic(sc);
3156 }
3157
3158 /*
3159  * Stop the adapter and free any mbufs allocated to the
3160  * RX and TX lists.
3161  */
3162 static void
3163 ndis_stop(struct ndis_softc *sc)
3164 {
3165         int                     i;
3166
3167         callout_drain(&sc->ndis_stat_callout);
3168
3169         NDIS_LOCK(sc);
3170         sc->ndis_tx_timer = 0;
3171         sc->ndis_link = 0;
3172         if (!sc->ndis_80211)
3173                 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3174         sc->ndis_running = 0;
3175         NDIS_UNLOCK(sc);
3176
3177         if (sc->ndis_iftype != PNPBus ||
3178             (sc->ndis_iftype == PNPBus &&
3179              !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3180              ndisusb_halt != 0))
3181                 ndis_halt_nic(sc);
3182
3183         NDIS_LOCK(sc);
3184         for (i = 0; i < NDIS_EVENTS; i++) {
3185                 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3186                         free(sc->ndis_evt[i].ne_buf, M_TEMP);
3187                         sc->ndis_evt[i].ne_buf = NULL;
3188                 }
3189                 sc->ndis_evt[i].ne_sts = 0;
3190                 sc->ndis_evt[i].ne_len = 0;
3191         }
3192         sc->ndis_evtcidx = 0;
3193         sc->ndis_evtpidx = 0;
3194         NDIS_UNLOCK(sc);
3195 }
3196
3197 /*
3198  * Stop all chip I/O so that the kernel's probe routines don't
3199  * get confused by errant DMAs when rebooting.
3200  */
3201 void
3202 ndis_shutdown(dev)
3203         device_t                dev;
3204 {
3205         struct ndis_softc               *sc;
3206
3207         sc = device_get_softc(dev);
3208         ndis_stop(sc);
3209 }
3210
3211 static int
3212 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3213 {
3214         struct ndis_vap *nvp = NDIS_VAP(vap);
3215         struct ieee80211com *ic = vap->iv_ic;
3216         struct ndis_softc *sc = ic->ic_softc;
3217         enum ieee80211_state ostate;
3218
3219         DPRINTF(("%s: %s -> %s\n", __func__,
3220                 ieee80211_state_name[vap->iv_state],
3221                 ieee80211_state_name[nstate]));
3222
3223         ostate = vap->iv_state;
3224         vap->iv_state = nstate;
3225
3226         switch (nstate) {
3227         /* pass on to net80211 */
3228         case IEEE80211_S_INIT:
3229         case IEEE80211_S_SCAN:
3230                 return nvp->newstate(vap, nstate, arg);
3231         case IEEE80211_S_ASSOC:
3232                 if (ostate != IEEE80211_S_AUTH) {
3233                         IEEE80211_UNLOCK(ic);
3234                         ndis_auth_and_assoc(sc, vap);
3235                         IEEE80211_LOCK(ic);
3236                 }
3237                 break;
3238         case IEEE80211_S_AUTH:
3239                 IEEE80211_UNLOCK(ic);
3240                 ndis_auth_and_assoc(sc, vap);
3241                 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3242                         ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3243                 IEEE80211_LOCK(ic);
3244                 break;
3245         default:
3246                 break;
3247         }
3248         return (0);
3249 }
3250
3251 static void
3252 ndis_scan(void *arg)
3253 {
3254         struct ieee80211vap *vap = arg;
3255
3256         ieee80211_scan_done(vap);
3257 }
3258
3259 static void
3260 ndis_scan_results(struct ndis_softc *sc)
3261 {
3262         struct ieee80211com *ic = &sc->ndis_ic;
3263         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3264         ndis_80211_bssid_list_ex *bl;
3265         ndis_wlan_bssid_ex      *wb;
3266         struct ieee80211_scanparams sp;
3267         struct ieee80211_frame wh;
3268         struct ieee80211_channel *saved_chan;
3269         int i, j;
3270         int rssi, noise, freq, chanflag;
3271         uint8_t ssid[2+IEEE80211_NWID_LEN];
3272         uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3273         uint8_t *frm, *efrm;
3274
3275         saved_chan = ic->ic_curchan;
3276         noise = -96;
3277
3278         if (ndis_get_bssid_list(sc, &bl))
3279                 return;
3280
3281         DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3282         wb = &bl->nblx_bssid[0];
3283         for (i = 0; i < bl->nblx_items; i++) {
3284                 memset(&sp, 0, sizeof(sp));
3285
3286                 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3287                 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3288                 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3289                 rssi = max(0, min(rssi, 100));  /* limit 0 <= rssi <= 100 */
3290                 if (wb->nwbx_privacy)
3291                         sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3292                 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3293                 switch (wb->nwbx_netinfra) {
3294                         case NDIS_80211_NET_INFRA_IBSS:
3295                                 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3296                                 break;
3297                         case NDIS_80211_NET_INFRA_BSS:
3298                                 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3299                                 break;
3300                 }
3301                 sp.rates = &rates[0];
3302                 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3303                         /* XXX - check units */
3304                         if (wb->nwbx_supportedrates[j] == 0)
3305                                 break;
3306                         rates[2 + j] =
3307                         wb->nwbx_supportedrates[j] & 0x7f;
3308                 }
3309                 rates[1] = j;
3310                 sp.ssid = (uint8_t *)&ssid[0];
3311                 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3312                     wb->nwbx_ssid.ns_ssidlen);
3313                 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3314
3315                 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3316                 freq = wb->nwbx_config.nc_dsconfig / 1000;
3317                 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3318                 /* Hack ic->ic_curchan to be in sync with the scan result */
3319                 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3320                 if (ic->ic_curchan == NULL)
3321                         ic->ic_curchan = &ic->ic_channels[0];
3322
3323                 /* Process extended info from AP */
3324                 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3325                         frm = (uint8_t *)&wb->nwbx_ies;
3326                         efrm = frm + wb->nwbx_ielen;
3327                         if (efrm - frm < 12)
3328                                 goto done;
3329                         sp.tstamp = frm;                        frm += 8;
3330                         sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3331                         sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3332                         sp.ies = frm;
3333                         sp.ies_len = efrm - frm;
3334                 }
3335 done:
3336                 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3337                     ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3338                     rssi));
3339                 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3340                 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3341         }
3342         free(bl, M_DEVBUF);
3343         /* Restore the channel after messing with it */
3344         ic->ic_curchan = saved_chan;
3345 }
3346
3347 static void
3348 ndis_scan_start(struct ieee80211com *ic)
3349 {
3350         struct ndis_softc *sc = ic->ic_softc;
3351         struct ieee80211vap *vap;
3352         struct ieee80211_scan_state *ss;
3353         ndis_80211_ssid ssid;
3354         int error, len;
3355
3356         ss = ic->ic_scan;
3357         vap = TAILQ_FIRST(&ic->ic_vaps);
3358
3359         if (!NDIS_INITIALIZED(sc)) {
3360                 DPRINTF(("%s: scan aborted\n", __func__));
3361                 ieee80211_cancel_scan(vap);
3362                 return;
3363         }
3364
3365         len = sizeof(ssid);
3366         bzero((char *)&ssid, len);
3367         if (ss->ss_nssid == 0)
3368                 ssid.ns_ssidlen = 1;
3369         else {
3370                 /* Perform a directed scan */
3371                 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3372                 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3373         }
3374
3375         error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3376         if (error)
3377                 DPRINTF(("%s: set ESSID failed\n", __func__));
3378
3379         len = 0;
3380         error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3381         if (error) {
3382                 DPRINTF(("%s: scan command failed\n", __func__));
3383                 ieee80211_cancel_scan(vap);
3384                 return;
3385         }
3386         /* Set a timer to collect the results */
3387         callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3388 }
3389
3390 static void
3391 ndis_set_channel(struct ieee80211com *ic)
3392 {
3393         /* ignore */
3394 }
3395
3396 static void
3397 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3398 {
3399         /* ignore */
3400 }
3401
3402 static void
3403 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3404 {
3405         /* NB: don't try to abort scan; wait for firmware to finish */
3406 }
3407
3408 static void
3409 ndis_scan_end(struct ieee80211com *ic)
3410 {
3411         struct ndis_softc *sc = ic->ic_softc;
3412
3413         ndis_scan_results(sc);
3414 }