3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
32 * $FreeBSD: src/sys/dev/if_ndis/if_ndis.c,v 1.181 2012/11/17 01:51:54 svnexp Exp $
34 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
35 * then hacked upon mercilessly by me.
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/sockio.h>
42 #include <sys/malloc.h>
43 #include <sys/endian.h>
45 #include <sys/kernel.h>
46 #include <sys/socket.h>
47 #include <sys/queue.h>
48 #include <sys/module.h>
50 #include <sys/sysctl.h>
51 #include <sys/kthread.h>
54 #include <net/if_arp.h>
55 #include <net/ethernet.h>
56 #include <net/if_dl.h>
57 #include <net/if_media.h>
58 #include <net/if_types.h>
59 #include <net/route.h>
62 #include <net/ifq_var.h>
66 #include <sys/mplock2.h>
68 #include <netproto/802_11/ieee80211_var.h>
69 #include <netproto/802_11/ieee80211_ioctl.h>
70 #include <netproto/802_11/ieee80211_regdomain.h>
72 #include <bus/pci/pcireg.h>
73 #include <bus/pci/pcivar.h>
74 #include <bus/u4b/usb.h>
75 #include <bus/u4b/usbdi.h>
77 #include <emulation/ndis/pe_var.h>
78 #include <emulation/ndis/cfg_var.h>
79 #include <emulation/ndis/resource_var.h>
80 #include <emulation/ndis/ntoskrnl_var.h>
81 #include <emulation/ndis/hal_var.h>
82 #include <emulation/ndis/ndis_var.h>
83 #include <emulation/ndis/u4bd_var.h>
84 #include <dev/netif/ndis/if_ndisvar.h>
88 #define DPRINTF(x) do { if (ndis_debug > 0) kprintf x; } while (0)
90 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
91 "if_ndis debug level");
96 SYSCTL_DECL(_hw_ndisusb);
98 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
99 "Halt NDIS USB driver when it's attached");
101 /* 0 - 30 dBm to mW conversion table */
102 static const uint16_t dBm2mW[] = {
103 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
104 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
105 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
106 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
107 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
108 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
112 MODULE_DEPEND(if_ndis, ether, 1, 1, 1);
113 MODULE_DEPEND(if_ndis, wlan, 1, 1, 1);
114 MODULE_DEPEND(if_ndis, ndis, 1, 1, 1);
116 MODULE_VERSION(if_ndis, 1);
118 int ndis_attach (device_t);
119 int ndis_detach (device_t);
120 int ndis_suspend (device_t);
121 int ndis_resume (device_t);
122 void ndis_shutdown (device_t);
124 int ndisdrv_modevent (module_t, int, void *);
126 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
127 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
128 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
129 uint32_t, void *, uint32_t, uint32_t);
130 static void ndis_rxeof_done (ndis_handle);
131 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
132 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
134 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
135 static void ndis_linksts_done (ndis_handle);
137 /* We need to wrap these functions for amd64. */
138 static funcptr ndis_txeof_wrap;
139 static funcptr ndis_rxeof_wrap;
140 static funcptr ndis_rxeof_eth_wrap;
141 static funcptr ndis_rxeof_done_wrap;
142 static funcptr ndis_rxeof_xfr_wrap;
143 static funcptr ndis_rxeof_xfr_done_wrap;
144 static funcptr ndis_linksts_wrap;
145 static funcptr ndis_linksts_done_wrap;
146 static funcptr ndis_ticktask_wrap;
147 static funcptr ndis_starttask_wrap;
148 static funcptr ndis_resettask_wrap;
149 static funcptr ndis_inputtask_wrap;
151 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
152 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
153 const uint8_t [IEEE80211_ADDR_LEN],
154 const uint8_t [IEEE80211_ADDR_LEN]);
155 static void ndis_vap_delete (struct ieee80211vap *);
156 static void ndis_tick (void *);
157 static void ndis_ticktask (device_object *, void *);
158 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
159 const struct ieee80211_bpf_params *);
160 static void ndis_update_mcast (struct ifnet *ifp);
161 static void ndis_update_promisc (struct ifnet *ifp);
162 static void ndis_start (struct ifnet *, struct ifaltq_subque *);
163 static void ndis_starttask (device_object *, void *);
164 static void ndis_resettask (device_object *, void *);
165 static void ndis_inputtask (device_object *, void *);
166 static int ndis_ioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
167 static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t, struct ucred *);
168 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
170 static int ndis_nettype_chan (uint32_t);
171 static int ndis_nettype_mode (uint32_t);
172 static void ndis_scan (void *);
173 static void ndis_scan_results (struct ndis_softc *);
174 static void ndis_scan_start (struct ieee80211com *);
175 static void ndis_scan_end (struct ieee80211com *);
176 static void ndis_set_channel (struct ieee80211com *);
177 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
178 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
179 static void ndis_init (void *);
180 static void ndis_stop (struct ndis_softc *);
181 static int ndis_ifmedia_upd (struct ifnet *);
182 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
183 static int ndis_get_bssid_list (struct ndis_softc *,
184 ndis_80211_bssid_list_ex **);
185 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
186 static int ndis_probe_offload (struct ndis_softc *);
187 static int ndis_set_offload (struct ndis_softc *);
188 static void ndis_getstate_80211 (struct ndis_softc *);
189 static void ndis_setstate_80211 (struct ndis_softc *);
190 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
191 static void ndis_media_status (struct ifnet *, struct ifmediareq *);
192 static int ndis_set_cipher (struct ndis_softc *, int);
193 static int ndis_set_wpa (struct ndis_softc *, void *, int);
194 static int ndis_add_key (struct ieee80211vap *,
195 const struct ieee80211_key *, const u_int8_t []);
196 static int ndis_del_key (struct ieee80211vap *,
197 const struct ieee80211_key *);
199 static void ndis_setmulti (struct ndis_softc *);
200 static void ndis_map_sclist (void *, bus_dma_segment_t *,
201 int, bus_size_t, int);
203 static int ndisdrv_loaded = 0;
206 * This routine should call windrv_load() once for each driver
207 * image. This will do the relocation and dynalinking for the
208 * image, and create a Windows driver object which will be
209 * saved in our driver database.
212 ndisdrv_modevent(module_t mod, int cmd, void *arg)
219 if (ndisdrv_loaded > 1)
221 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
222 3, WINDRV_WRAP_STDCALL);
223 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
224 8, WINDRV_WRAP_STDCALL);
225 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
226 1, WINDRV_WRAP_STDCALL);
227 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
228 4, WINDRV_WRAP_STDCALL);
229 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
230 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
231 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
232 3, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
234 4, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_linksts_done,
236 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
238 2, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
240 2, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
242 2, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
244 2, WINDRV_WRAP_STDCALL);
248 if (ndisdrv_loaded > 0)
252 windrv_unwrap(ndis_rxeof_wrap);
253 windrv_unwrap(ndis_rxeof_eth_wrap);
254 windrv_unwrap(ndis_rxeof_done_wrap);
255 windrv_unwrap(ndis_rxeof_xfr_wrap);
256 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
257 windrv_unwrap(ndis_txeof_wrap);
258 windrv_unwrap(ndis_linksts_wrap);
259 windrv_unwrap(ndis_linksts_done_wrap);
260 windrv_unwrap(ndis_ticktask_wrap);
261 windrv_unwrap(ndis_starttask_wrap);
262 windrv_unwrap(ndis_resettask_wrap);
263 windrv_unwrap(ndis_inputtask_wrap);
274 * Program the 64-bit multicast hash filter.
277 ndis_setmulti(struct ndis_softc *sc)
280 struct ifmultiaddr *ifma;
281 int len, mclistsz, error;
286 if (!NDIS_INITIALIZED(sc))
289 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
290 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
291 len = sizeof(sc->ndis_filter);
292 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
293 &sc->ndis_filter, &len);
295 device_printf(sc->ndis_dev,
296 "set allmulti failed: %d\n", error);
300 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
303 len = sizeof(mclistsz);
304 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
306 mclist = kmalloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
308 if (mclist == NULL) {
309 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
313 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
316 #if 0 /* XXX swildner */
319 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
320 if (ifma->ifma_addr->sa_family != AF_LINK)
322 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
323 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
325 if (len > mclistsz) {
326 #if 0 /* XXX swildner */
327 if_maddr_runlock(ifp);
329 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
330 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
334 #if 0 /* XXX swildner */
335 if_maddr_runlock(ifp);
338 len = len * ETHER_ADDR_LEN;
339 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
341 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
342 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
343 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
347 kfree(mclist, M_TEMP);
349 len = sizeof(sc->ndis_filter);
350 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
351 &sc->ndis_filter, &len);
353 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
357 ndis_set_offload(struct ndis_softc *sc)
359 ndis_task_offload *nto;
360 ndis_task_offload_hdr *ntoh;
361 ndis_task_tcpip_csum *nttc;
367 if (!NDIS_INITIALIZED(sc))
370 /* See if there's anything to set. */
372 error = ndis_probe_offload(sc);
376 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
379 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
380 sizeof(ndis_task_tcpip_csum);
382 ntoh = kmalloc(len, M_TEMP, M_NOWAIT|M_ZERO);
387 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
388 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
389 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
390 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
391 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
392 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
394 nto = (ndis_task_offload *)((char *)ntoh +
395 ntoh->ntoh_offset_firsttask);
397 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
398 nto->nto_len = sizeof(ndis_task_offload);
399 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
400 nto->nto_offset_nexttask = 0;
401 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
403 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
405 if (ifp->if_capenable & IFCAP_TXCSUM)
406 nttc->nttc_v4tx = sc->ndis_v4tx;
408 if (ifp->if_capenable & IFCAP_RXCSUM)
409 nttc->nttc_v4rx = sc->ndis_v4rx;
411 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418 ndis_probe_offload(struct ndis_softc *sc)
420 ndis_task_offload *nto;
421 ndis_task_offload_hdr *ntoh;
422 ndis_task_tcpip_csum *nttc = NULL;
424 int len, error, dummy;
429 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
434 ntoh = kmalloc(len, M_TEMP, M_NOWAIT|M_ZERO);
439 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
440 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
441 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
442 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
443 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
445 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
452 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
457 nto = (ndis_task_offload *)((char *)ntoh +
458 ntoh->ntoh_offset_firsttask);
461 switch (nto->nto_task) {
462 case NDIS_TASK_TCPIP_CSUM:
463 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
465 /* Don't handle these yet. */
466 case NDIS_TASK_IPSEC:
467 case NDIS_TASK_TCP_LARGESEND:
471 if (nto->nto_offset_nexttask == 0)
473 nto = (ndis_task_offload *)((char *)nto +
474 nto->nto_offset_nexttask);
482 sc->ndis_v4tx = nttc->nttc_v4tx;
483 sc->ndis_v4rx = nttc->nttc_v4rx;
485 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
486 sc->ndis_hwassist |= CSUM_IP;
487 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
488 sc->ndis_hwassist |= CSUM_TCP;
489 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
490 sc->ndis_hwassist |= CSUM_UDP;
492 if (sc->ndis_hwassist)
493 ifp->if_capabilities |= IFCAP_TXCSUM;
495 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
496 ifp->if_capabilities |= IFCAP_RXCSUM;
497 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
498 ifp->if_capabilities |= IFCAP_RXCSUM;
499 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
500 ifp->if_capabilities |= IFCAP_RXCSUM;
507 ndis_nettype_chan(uint32_t type)
510 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
511 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
512 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
513 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
515 DPRINTF(("unknown channel nettype %d\n", type));
516 return (IEEE80211_CHAN_B); /* Default to 11B chan */
520 ndis_nettype_mode(uint32_t type)
523 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
524 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
525 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
526 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
528 DPRINTF(("unknown mode nettype %d\n", type));
529 return (IEEE80211_MODE_AUTO);
533 * Attach the interface. Allocate softc structures, do ifmedia
534 * setup and ethernet/BPF attach.
537 ndis_attach(device_t dev)
539 u_char eaddr[ETHER_ADDR_LEN];
540 struct ndis_softc *sc;
543 struct ifnet *ifp = NULL;
544 int error = 0, len, mode;
548 sc = device_get_softc(dev);
550 lockinit(&sc->ndis_lock, "network driver", 0, LK_CANRECURSE);
551 KeInitializeSpinLock(&sc->ndis_rxlock);
552 KeInitializeSpinLock(&sc->ndisusb_tasklock);
553 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
554 InitializeListHead(&sc->ndis_shlist);
555 InitializeListHead(&sc->ndisusb_tasklist);
556 InitializeListHead(&sc->ndisusb_xferdonelist);
557 callout_init_mp(&sc->ndis_stat_callout);
559 if (sc->ndis_iftype == PCMCIABus) {
560 error = ndis_alloc_amem(sc);
562 device_printf(dev, "failed to allocate "
563 "attribute memory\n");
568 /* Create sysctl registry nodes */
569 ndis_create_sysctls(sc);
571 /* Find the PDO for this device instance. */
573 if (sc->ndis_iftype == PCIBus)
574 pdrv = windrv_lookup(0, "PCI Bus");
575 else if (sc->ndis_iftype == PCMCIABus)
576 pdrv = windrv_lookup(0, "PCCARD Bus");
578 pdrv = windrv_lookup(0, "USB Bus");
579 pdo = windrv_find_pdo(pdrv, dev);
582 * Create a new functional device object for this
583 * device. This is what creates the miniport block
584 * for this device instance.
587 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
588 device_printf(dev, "failed to create FDO!\n");
593 /* Tell the user what version of the API the driver is using. */
594 device_printf(dev, "NDIS API version: %d.%d\n",
595 sc->ndis_chars->nmc_version_major,
596 sc->ndis_chars->nmc_version_minor);
598 /* Do resource conversion. */
599 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
600 ndis_convert_res(sc);
602 sc->ndis_block->nmb_rlist = NULL;
604 /* Install our RX and TX interrupt handlers. */
605 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
606 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
607 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
608 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
609 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
611 /* Override the status handler so we can detect link changes. */
612 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
613 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
615 /* Set up work item handlers. */
616 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
617 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
618 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
619 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
620 sc->ndisusb_xferdoneitem =
621 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
622 sc->ndisusb_taskitem =
623 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
626 /* Call driver's init routine. */
627 if (ndis_init_nic(sc)) {
628 device_printf(dev, "init handler failed\n");
634 * Get station address from the driver.
637 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
640 * Figure out how big to make the TX buffer pool.
643 len = sizeof(sc->ndis_maxpkts);
644 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
645 &sc->ndis_maxpkts, &len)) {
646 device_printf(dev, "failed to get max TX packets\n");
652 * If this is a deserialized miniport, we don't have
653 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
655 if (!NDIS_SERIALIZED(sc->ndis_block))
656 sc->ndis_maxpkts = NDIS_TXPKTS;
658 /* Enforce some sanity, just in case. */
660 if (sc->ndis_maxpkts == 0)
661 sc->ndis_maxpkts = 10;
663 sc->ndis_txarray = kmalloc(sizeof(ndis_packet *) *
664 sc->ndis_maxpkts, M_DEVBUF, M_WAITOK|M_ZERO);
666 /* Allocate a pool of ndis_packets for TX encapsulation. */
668 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
669 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
671 if (i != NDIS_STATUS_SUCCESS) {
672 sc->ndis_txpool = NULL;
673 device_printf(dev, "failed to allocate TX packet pool");
678 sc->ndis_txpending = sc->ndis_maxpkts;
681 /* Get supported oid list. */
682 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
684 /* If the NDIS module requested scatter/gather, init maps. */
689 * See if the OID_802_11_CONFIGURATION OID is
690 * supported by this driver. If it is, then this an 802.11
691 * wireless driver, and we should set up media for wireless.
693 for (i = 0; i < sc->ndis_oidcnt; i++)
694 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
700 ifp = if_alloc(IFT_IEEE80211);
702 ifp = if_alloc(IFT_ETHER);
710 /* Check for task offload support. */
711 ndis_probe_offload(sc);
713 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
714 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
716 if (sc->ndis_iftype == PNPBus)
717 ifp->if_flags |= IFF_NEEDSGIANT;
719 ifp->if_ioctl = ndis_ioctl;
720 ifp->if_start = ndis_start;
721 ifp->if_init = ndis_init;
722 ifp->if_baudrate = 10000000;
723 ifq_set_maxlen(&ifp->if_snd, 50);
725 ifq_set_ready(&ifp->if_snd);
727 ifp->if_capenable = ifp->if_capabilities;
728 ifp->if_hwassist = sc->ndis_hwassist;
731 if (sc->ndis_80211) {
732 struct ieee80211com *ic = ifp->if_l2com;
733 ndis_80211_rates_ex rates;
734 struct ndis_80211_nettype_list *ntl;
738 callout_init_mp(&sc->ndis_scan_callout);
740 ifp->if_ioctl = ndis_ioctl_80211;
742 ic->ic_opmode = IEEE80211_M_STA;
743 ic->ic_phytype = IEEE80211_T_DS;
744 ic->ic_caps = IEEE80211_C_8023ENCAP |
745 IEEE80211_C_STA | IEEE80211_C_IBSS;
746 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
748 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
752 ntl = kmalloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
753 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
756 kfree(ntl, M_DEVBUF);
760 for (i = 0; i < ntl->ntl_items; i++) {
761 mode = ndis_nettype_mode(ntl->ntl_type[i]);
763 setbit(ic->ic_modecaps, mode);
764 setbit(&bands, mode);
766 device_printf(dev, "Unknown nettype %d\n",
769 kfree(ntl, M_DEVBUF);
771 /* Default to 11b channels if the card did not supply any */
773 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
774 setbit(&bands, IEEE80211_MODE_11B);
777 bzero((char *)&rates, len);
778 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
779 (void *)rates, &len);
781 device_printf(dev, "get rates failed: 0x%x\n", r);
783 * Since the supported rates only up to 8 can be supported,
784 * if this is not 802.11b we're just going to be faking it
788 #define TESTSETRATE(x, y) \
791 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
792 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
795 if (i == ic->ic_sup_rates[x].rs_nrates) { \
796 ic->ic_sup_rates[x].rs_rates[i] = (y); \
797 ic->ic_sup_rates[x].rs_nrates++; \
801 #define SETRATE(x, y) \
802 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
804 ic->ic_sup_rates[x].rs_nrates++
806 ic->ic_curmode = IEEE80211_MODE_AUTO;
807 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
808 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
809 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
810 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
811 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
812 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
813 for (i = 0; i < len; i++) {
814 switch (rates[i] & IEEE80211_RATE_VAL) {
820 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
821 /* Lazy-init 802.11b. */
822 setbit(ic->ic_modecaps,
824 ic->ic_sup_rates[IEEE80211_MODE_11B].
827 SETRATE(IEEE80211_MODE_11B, rates[i]);
828 INCRATE(IEEE80211_MODE_11B);
831 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
832 SETRATE(IEEE80211_MODE_11A, rates[i]);
833 INCRATE(IEEE80211_MODE_11A);
835 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
836 SETRATE(IEEE80211_MODE_11G, rates[i]);
837 INCRATE(IEEE80211_MODE_11G);
844 * If the hardware supports 802.11g, it most
845 * likely supports 802.11b and all of the
846 * 802.11b and 802.11g speeds, so maybe we can
847 * just cheat here. Just how in the heck do
848 * we detect turbo modes, though?
850 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
851 TESTSETRATE(IEEE80211_MODE_11B,
852 IEEE80211_RATE_BASIC|2);
853 TESTSETRATE(IEEE80211_MODE_11B,
854 IEEE80211_RATE_BASIC|4);
855 TESTSETRATE(IEEE80211_MODE_11B,
856 IEEE80211_RATE_BASIC|11);
857 TESTSETRATE(IEEE80211_MODE_11B,
858 IEEE80211_RATE_BASIC|22);
860 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
861 TESTSETRATE(IEEE80211_MODE_11G, 48);
862 TESTSETRATE(IEEE80211_MODE_11G, 72);
863 TESTSETRATE(IEEE80211_MODE_11G, 96);
864 TESTSETRATE(IEEE80211_MODE_11G, 108);
866 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
867 TESTSETRATE(IEEE80211_MODE_11A, 48);
868 TESTSETRATE(IEEE80211_MODE_11A, 72);
869 TESTSETRATE(IEEE80211_MODE_11A, 96);
870 TESTSETRATE(IEEE80211_MODE_11A, 108);
874 ieee80211_init_channels(ic, NULL, &bands);
877 * To test for WPA support, we need to see if we can
878 * set AUTHENTICATION_MODE to WPA and read it back
882 arg = NDIS_80211_AUTHMODE_WPA;
883 r = ndis_set_info(sc,
884 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
886 r = ndis_get_info(sc,
887 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
888 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
889 ic->ic_caps |= IEEE80211_C_WPA;
893 * To test for supported ciphers, we set each
894 * available encryption type in descending order.
895 * If ENC3 works, then we have WEP, TKIP and AES.
896 * If only ENC2 works, then we have WEP and TKIP.
897 * If only ENC1 works, then we have just WEP.
900 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
901 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
903 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
904 | IEEE80211_CRYPTO_TKIP
905 | IEEE80211_CRYPTO_AES_CCM;
908 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
909 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
911 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
912 | IEEE80211_CRYPTO_TKIP;
915 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
916 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
918 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
921 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
923 ic->ic_caps |= IEEE80211_C_PMGT;
925 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
927 ic->ic_caps |= IEEE80211_C_TXPMGT;
929 /* ieee80211_ifattach() assumes that WLAN serializer is held */
930 wlan_serialize_enter();
931 ieee80211_ifattach(ic, eaddr);
932 wlan_serialize_exit();
933 ic->ic_raw_xmit = ndis_raw_xmit;
934 ic->ic_scan_start = ndis_scan_start;
935 ic->ic_scan_end = ndis_scan_end;
936 ic->ic_set_channel = ndis_set_channel;
937 ic->ic_scan_curchan = ndis_scan_curchan;
938 ic->ic_scan_mindwell = ndis_scan_mindwell;
939 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
940 //ic->ic_bss->ni_chan = ic->ic_bsschan;
941 ic->ic_vap_create = ndis_vap_create;
942 ic->ic_vap_delete = ndis_vap_delete;
943 ic->ic_update_mcast = ndis_update_mcast;
944 ic->ic_update_promisc = ndis_update_promisc;
947 ieee80211_announce(ic);
950 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
952 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
953 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
954 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
955 ifmedia_add(&sc->ifmedia,
956 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
957 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
958 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
959 ether_ifattach(ifp, eaddr, NULL);
968 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
971 DPRINTF(("attach done.\n"));
972 /* We're done talking to the NIC for now; halt it. */
974 DPRINTF(("halting done.\n"));
979 static struct ieee80211vap *
980 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
981 enum ieee80211_opmode opmode, int flags,
982 const uint8_t bssid[IEEE80211_ADDR_LEN],
983 const uint8_t mac[IEEE80211_ADDR_LEN])
985 struct ndis_vap *nvp;
986 struct ieee80211vap *vap;
988 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
990 nvp = (struct ndis_vap *) kmalloc(sizeof(struct ndis_vap),
991 M_80211_VAP, M_NOWAIT | M_ZERO);
995 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
996 /* override with driver methods */
997 nvp->newstate = vap->iv_newstate;
998 vap->iv_newstate = ndis_newstate;
1000 /* complete setup */
1001 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
1002 ic->ic_opmode = opmode;
1003 /* install key handing routines */
1004 vap->iv_key_set = ndis_add_key;
1005 vap->iv_key_delete = ndis_del_key;
1010 ndis_vap_delete(struct ieee80211vap *vap)
1012 struct ndis_vap *nvp = NDIS_VAP(vap);
1013 struct ieee80211com *ic = vap->iv_ic;
1014 struct ifnet *ifp = ic->ic_ifp;
1015 struct ndis_softc *sc = ifp->if_softc;
1018 callout_stop_sync(&sc->ndis_scan_callout);
1019 ieee80211_vap_detach(vap);
1020 kfree(nvp, M_80211_VAP);
1024 * Shutdown hardware and free up resources. This can be called any
1025 * time after the mutex has been initialized. It is called in both
1026 * the error case in attach and the normal detach case so it needs
1027 * to be careful about only freeing resources that have actually been
1031 ndis_detach(device_t dev)
1033 struct ndis_softc *sc;
1037 sc = device_get_softc(dev);
1040 ifp->if_flags &= ~IFF_UP;
1042 if (device_is_attached(dev)) {
1046 ieee80211_ifdetach(ifp->if_l2com);
1048 ether_ifdetach(ifp);
1052 if (sc->ndis_tickitem != NULL)
1053 IoFreeWorkItem(sc->ndis_tickitem);
1054 if (sc->ndis_startitem != NULL)
1055 IoFreeWorkItem(sc->ndis_startitem);
1056 if (sc->ndis_resetitem != NULL)
1057 IoFreeWorkItem(sc->ndis_resetitem);
1058 if (sc->ndis_inputitem != NULL)
1059 IoFreeWorkItem(sc->ndis_inputitem);
1060 if (sc->ndisusb_xferdoneitem != NULL)
1061 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1062 if (sc->ndisusb_taskitem != NULL)
1063 IoFreeWorkItem(sc->ndisusb_taskitem);
1065 bus_generic_detach(dev);
1066 ndis_unload_driver(sc);
1069 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1070 if (sc->ndis_res_io)
1071 bus_release_resource(dev, SYS_RES_IOPORT,
1072 sc->ndis_io_rid, sc->ndis_res_io);
1073 if (sc->ndis_res_mem)
1074 bus_release_resource(dev, SYS_RES_MEMORY,
1075 sc->ndis_mem_rid, sc->ndis_res_mem);
1076 if (sc->ndis_res_altmem)
1077 bus_release_resource(dev, SYS_RES_MEMORY,
1078 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1083 if (sc->ndis_iftype == PCMCIABus)
1087 ndis_destroy_dma(sc);
1089 if (sc->ndis_txarray)
1090 kfree(sc->ndis_txarray, M_DEVBUF);
1092 if (!sc->ndis_80211)
1093 ifmedia_removeall(&sc->ifmedia);
1095 if (sc->ndis_txpool != NULL)
1096 NdisFreePacketPool(sc->ndis_txpool);
1098 /* Destroy the PDO for this device. */
1100 if (sc->ndis_iftype == PCIBus)
1101 drv = windrv_lookup(0, "PCI Bus");
1102 else if (sc->ndis_iftype == PCMCIABus)
1103 drv = windrv_lookup(0, "PCCARD Bus");
1105 drv = windrv_lookup(0, "USB Bus");
1107 panic("couldn't find driver object");
1108 windrv_destroy_pdo(drv, dev);
1110 if (sc->ndis_iftype == PCIBus)
1111 bus_dma_tag_destroy(sc->ndis_parent_tag);
1117 ndis_suspend(device_t dev)
1120 struct ndis_softc *sc;
1122 wlan_serialize_enter();
1123 sc = device_get_softc(dev);
1125 if (NDIS_INITIALIZED(sc))
1128 wlan_serialize_exit();
1134 ndis_resume(device_t dev)
1136 struct ndis_softc *sc;
1138 wlan_serialize_enter();
1139 sc = device_get_softc(dev);
1141 if (NDIS_INITIALIZED(sc))
1144 wlan_serialize_exit();
1149 * The following bunch of routines are here to support drivers that
1150 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1151 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1152 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1156 ndis_rxeof_eth(ndis_handle adapter, ndis_handle ctx, char *addr, void *hdr,
1157 uint32_t hdrlen, void *lookahead, uint32_t lookaheadlen, uint32_t pktlen)
1159 ndis_miniport_block *block;
1169 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1173 /* Save the data provided to us so far. */
1175 m->m_len = lookaheadlen + hdrlen;
1176 m->m_pkthdr.len = pktlen + hdrlen;
1178 m_copyback(m, 0, hdrlen, hdr);
1179 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1181 /* Now create a fake NDIS_PACKET to hold the data */
1183 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1185 if (status != NDIS_STATUS_SUCCESS) {
1192 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1200 p->np_private.npp_head = p->np_private.npp_tail = b;
1201 p->np_private.npp_totlen = m->m_pkthdr.len;
1203 /* Save the packet RX context somewhere. */
1204 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1205 priv->nep_ctx = ctx;
1207 if (!NDIS_SERIALIZED(block))
1208 KeAcquireSpinLock(&block->nmb_lock, &irql);
1210 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1212 if (!NDIS_SERIALIZED(block))
1213 KeReleaseSpinLock(&block->nmb_lock, irql);
1217 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1218 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1222 ndis_rxeof_done(ndis_handle adapter)
1224 struct ndis_softc *sc;
1225 ndis_miniport_block *block;
1229 /* Schedule transfer/RX of queued packets. */
1231 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1233 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1237 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1240 ndis_rxeof_xfr(kdpc *dpc, ndis_handle adapter, void *sysarg1, void *sysarg2)
1242 ndis_miniport_block *block;
1243 struct ndis_softc *sc;
1252 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1255 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1257 l = block->nmb_packetlist.nle_flink;
1258 while(!IsListEmpty(&block->nmb_packetlist)) {
1259 l = RemoveHeadList((&block->nmb_packetlist));
1260 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1261 InitializeListHead((&p->np_list));
1263 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1268 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1270 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1271 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1272 m->m_len, m->m_pkthdr.len - m->m_len);
1274 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1277 * If status is NDIS_STATUS_PENDING, do nothing and
1278 * wait for a callback to the ndis_rxeof_xfr_done()
1282 m->m_len = m->m_pkthdr.len;
1283 m->m_pkthdr.rcvif = ifp;
1285 if (status == NDIS_STATUS_SUCCESS) {
1286 IoFreeMdl(p->np_private.npp_head);
1288 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1289 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1290 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1291 IoQueueWorkItem(sc->ndis_inputitem,
1292 (io_workitem_func)ndis_inputtask_wrap,
1293 WORKQUEUE_CRITICAL, ifp);
1296 if (status == NDIS_STATUS_FAILURE)
1299 /* Advance to next packet */
1300 l = block->nmb_packetlist.nle_flink;
1303 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1307 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1310 ndis_rxeof_xfr_done(ndis_handle adapter, ndis_packet *packet, uint32_t status,
1313 ndis_miniport_block *block;
1314 struct ndis_softc *sc;
1319 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1323 IoFreeMdl(packet->np_private.npp_head);
1324 NdisFreePacket(packet);
1326 if (status != NDIS_STATUS_SUCCESS) {
1331 m->m_len = m->m_pkthdr.len;
1332 m->m_pkthdr.rcvif = ifp;
1333 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1334 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1335 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1336 IoQueueWorkItem(sc->ndis_inputitem,
1337 (io_workitem_func)ndis_inputtask_wrap,
1338 WORKQUEUE_CRITICAL, ifp);
1341 * A frame has been uploaded: pass the resulting mbuf chain up to
1342 * the higher level protocols.
1344 * When handling received NDIS packets, the 'status' field in the
1345 * out-of-band portion of the ndis_packet has special meaning. In the
1346 * most common case, the underlying NDIS driver will set this field
1347 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1348 * take posession of it. We then change the status field to
1349 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1350 * and that we will return it at some point in the future via the
1351 * return packet handler.
1353 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1354 * this means the driver is running out of packet/buffer resources and
1355 * wants to maintain ownership of the packet. In this case, we have to
1356 * copy the packet data into local storage and let the driver keep the
1360 ndis_rxeof(ndis_handle adapter, ndis_packet **packets, uint32_t pktcnt)
1362 struct ndis_softc *sc;
1363 ndis_miniport_block *block;
1366 ndis_tcpip_csum *csum;
1368 struct mbuf *m0, *m;
1371 block = (ndis_miniport_block *)adapter;
1372 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1376 * There's a slim chance the driver may indicate some packets
1377 * before we're completely ready to handle them. If we detect this,
1378 * we need to return them to the miniport and ignore them.
1380 if (!(ifp->if_flags & IFF_RUNNING)) {
1381 for (i = 0; i < pktcnt; i++) {
1383 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1385 ndis_return_packet(p);
1391 for (i = 0; i < pktcnt; i++) {
1393 /* Stash the softc here so ptom can use it. */
1395 if (ndis_ptom(&m0, p)) {
1396 device_printf(sc->ndis_dev, "ptom failed\n");
1397 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1398 ndis_return_packet(p);
1401 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1402 m = m_dup(m0, M_NOWAIT);
1404 * NOTE: we want to destroy the mbuf here, but
1405 * we don't actually want to return it to the
1406 * driver via the return packet handler. By
1407 * bumping np_refcnt, we can prevent the
1408 * ndis_return_packet() routine from actually
1418 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1420 m = m_dup(m0, M_NOWAIT);
1421 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1424 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1427 IFNET_STAT_INC(ifp, ierrors, 1);
1431 m0->m_pkthdr.rcvif = ifp;
1433 /* Deal with checksum offload. */
1435 if (ifp->if_capenable & IFCAP_RXCSUM &&
1436 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1438 p->np_ext.npe_info[ndis_tcpipcsum_info];
1439 csum = (ndis_tcpip_csum *)&s;
1440 if (csum->u.ntc_rxflags &
1441 NDIS_RXCSUM_IP_PASSED)
1442 m0->m_pkthdr.csum_flags |=
1443 CSUM_IP_CHECKED|CSUM_IP_VALID;
1444 if (csum->u.ntc_rxflags &
1445 (NDIS_RXCSUM_TCP_PASSED |
1446 NDIS_RXCSUM_UDP_PASSED)) {
1447 m0->m_pkthdr.csum_flags |=
1448 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1449 m0->m_pkthdr.csum_data = 0xFFFF;
1453 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1454 IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1455 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1456 IoQueueWorkItem(sc->ndis_inputitem,
1457 (io_workitem_func)ndis_inputtask_wrap,
1458 WORKQUEUE_CRITICAL, ifp);
1464 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1465 * packets into the stack in order to avoid calling ifp->if_input()
1466 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1467 * 'dispatch level' per-cpu sleep lock).
1470 ndis_inputtask(device_object *dobj, void *arg)
1473 struct ndis_softc *sc;
1475 struct ieee80211com *ic;
1476 struct ieee80211vap *vap;
1482 vap = TAILQ_FIRST(&ic->ic_vaps);
1484 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1486 IF_DEQUEUE(&sc->ndis_rxqueue, m);
1489 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1490 if ((sc->ndis_80211 != 0) && (vap != NULL))
1491 vap->iv_deliver_data(vap, vap->iv_bss, m);
1493 ifp->if_input(ifp, m, NULL, -1);
1494 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1496 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1500 * A frame was downloaded to the chip. It's safe for us to clean up
1504 ndis_txeof(ndis_handle adapter, ndis_packet *packet, ndis_status status)
1506 struct ndis_softc *sc;
1507 ndis_miniport_block *block;
1512 block = (ndis_miniport_block *)adapter;
1513 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1517 idx = packet->np_txidx;
1519 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1521 ndis_free_packet(packet);
1525 sc->ndis_txarray[idx] = NULL;
1526 sc->ndis_txpending++;
1528 if (status == NDIS_STATUS_SUCCESS)
1529 IFNET_STAT_INC(ifp, opackets, 1);
1531 IFNET_STAT_INC(ifp, oerrors, 1);
1533 sc->ndis_tx_timer = 0;
1534 ifq_clr_oactive(&ifp->if_snd);
1538 IoQueueWorkItem(sc->ndis_startitem,
1539 (io_workitem_func)ndis_starttask_wrap,
1540 WORKQUEUE_CRITICAL, ifp);
1544 ndis_linksts(ndis_handle adapter, ndis_status status, void *sbuf,
1547 ndis_miniport_block *block;
1548 struct ndis_softc *sc;
1551 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1552 sc->ndis_sts = status;
1554 /* Event list is all full up, drop this one. */
1557 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1562 /* Cache the event. */
1565 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = kmalloc(slen,
1567 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1572 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1574 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1575 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1576 NDIS_EVTINC(sc->ndis_evtpidx);
1581 ndis_linksts_done(ndis_handle adapter)
1583 ndis_miniport_block *block;
1584 struct ndis_softc *sc;
1588 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1591 if (!NDIS_INITIALIZED(sc))
1594 switch (sc->ndis_sts) {
1595 case NDIS_STATUS_MEDIA_CONNECT:
1596 IoQueueWorkItem(sc->ndis_tickitem,
1597 (io_workitem_func)ndis_ticktask_wrap,
1598 WORKQUEUE_CRITICAL, sc);
1599 IoQueueWorkItem(sc->ndis_startitem,
1600 (io_workitem_func)ndis_starttask_wrap,
1601 WORKQUEUE_CRITICAL, ifp);
1603 case NDIS_STATUS_MEDIA_DISCONNECT:
1605 IoQueueWorkItem(sc->ndis_tickitem,
1606 (io_workitem_func)ndis_ticktask_wrap,
1607 WORKQUEUE_CRITICAL, sc);
1615 ndis_tick(void *xsc)
1617 struct ndis_softc *sc;
1621 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1622 IoQueueWorkItem(sc->ndis_tickitem,
1623 (io_workitem_func)ndis_ticktask_wrap,
1624 WORKQUEUE_CRITICAL, sc);
1625 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1628 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1629 IFNET_STAT_INC(sc->ifp, oerrors, 1);
1630 device_printf(sc->ndis_dev, "watchdog timeout\n");
1632 IoQueueWorkItem(sc->ndis_resetitem,
1633 (io_workitem_func)ndis_resettask_wrap,
1634 WORKQUEUE_CRITICAL, sc);
1635 IoQueueWorkItem(sc->ndis_startitem,
1636 (io_workitem_func)ndis_starttask_wrap,
1637 WORKQUEUE_CRITICAL, sc->ifp);
1640 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1644 ndis_ticktask(device_object *d, void *xsc)
1646 struct ndis_softc *sc;
1647 struct ieee80211com *ic;
1648 struct ieee80211vap *vap;
1649 ndis_checkforhang_handler hangfunc;
1653 ic = sc->ifp->if_l2com;
1654 vap = TAILQ_FIRST(&ic->ic_vaps);
1657 if (!NDIS_INITIALIZED(sc)) {
1663 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1665 if (hangfunc != NULL) {
1666 rval = MSCALL1(hangfunc,
1667 sc->ndis_block->nmb_miniportadapterctx);
1675 if (sc->ndis_link == 0 &&
1676 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1679 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1680 ndis_getstate_80211(sc);
1681 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1684 sc->ifp->if_link_state = LINK_STATE_UP;
1685 if_link_state_change(sc->ifp);
1688 if (sc->ndis_link == 1 &&
1689 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1692 if ((sc->ndis_80211 != 0) && (vap != NULL))
1693 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1695 sc->ifp->if_link_state = LINK_STATE_DOWN;
1696 if_link_state_change(sc->ifp);
1703 ndis_map_sclist(void *arg, bus_dma_segment_t *segs, int nseg,
1704 bus_size_t mapsize, int error)
1706 struct ndis_sc_list *sclist;
1709 if (error || arg == NULL)
1714 sclist->nsl_frags = nseg;
1716 for (i = 0; i < nseg; i++) {
1717 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1718 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1723 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1724 const struct ieee80211_bpf_params *params)
1726 /* no support; just discard */
1728 ieee80211_free_node(ni);
1733 ndis_update_mcast(struct ifnet *ifp)
1735 struct ndis_softc *sc = ifp->if_softc;
1741 ndis_update_promisc(struct ifnet *ifp)
1747 ndis_starttask(device_object *d, void *arg)
1753 lwkt_serialize_enter(ifp->if_serializer);
1754 if (!ifq_is_empty(&ifp->if_snd))
1756 lwkt_serialize_exit(ifp->if_serializer);
1760 * Main transmit routine. To make NDIS drivers happy, we need to
1761 * transform mbuf chains into NDIS packets and feed them to the
1762 * send packet routines. Most drivers allow you to send several
1763 * packets at once (up to the maxpkts limit). Unfortunately, rather
1764 * that accepting them in the form of a linked list, they expect
1765 * a contiguous array of pointers to packets.
1767 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1768 * we need to perform busdma work here. Those that use map registers
1769 * will do the mapping themselves on a buffer by buffer basis.
1772 ndis_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
1774 struct ndis_softc *sc;
1775 struct mbuf *m = NULL;
1776 ndis_packet **p0 = NULL, *p = NULL;
1777 ndis_tcpip_csum *csum;
1778 int pcnt = 0, status;
1780 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
1785 if (!sc->ndis_link) {
1786 ifq_purge(&ifp->if_snd);
1791 if (ifq_is_oactive(&ifp->if_snd)) {
1796 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1798 while(sc->ndis_txpending) {
1799 m = ifq_dequeue(&ifp->if_snd);
1803 NdisAllocatePacket(&status,
1804 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1806 if (status != NDIS_STATUS_SUCCESS)
1809 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1810 ifq_prepend(&ifp->if_snd, m);
1816 * Save pointer to original mbuf
1817 * so we can free it later.
1820 p = sc->ndis_txarray[sc->ndis_txidx];
1821 p->np_txidx = sc->ndis_txidx;
1823 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1826 * Do scatter/gather processing, if driver requested it.
1829 bus_dmamap_load_mbuf(sc->ndis_ttag,
1830 sc->ndis_tmaps[sc->ndis_txidx], m,
1831 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1832 bus_dmamap_sync(sc->ndis_ttag,
1833 sc->ndis_tmaps[sc->ndis_txidx],
1834 BUS_DMASYNC_PREREAD);
1835 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1838 /* Handle checksum offload. */
1840 if (ifp->if_capenable & IFCAP_TXCSUM &&
1841 m->m_pkthdr.csum_flags) {
1842 csum = (ndis_tcpip_csum *)
1843 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1844 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1845 if (m->m_pkthdr.csum_flags & CSUM_IP)
1846 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1847 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1848 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1849 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1850 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1851 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1855 sc->ndis_txpending--;
1860 * If there's a BPF listener, bounce a copy of this frame
1863 if (!sc->ndis_80211) /* XXX handle 80211 */
1867 * The array that p0 points to must appear contiguous,
1868 * so we must not wrap past the end of sc->ndis_txarray[].
1869 * If it looks like we're about to wrap, break out here
1870 * so the this batch of packets can be transmitted, then
1871 * wait for txeof to ask us to send the rest.
1873 if (sc->ndis_txidx == 0)
1882 if (sc->ndis_txpending == 0)
1883 ifq_set_oactive(&ifp->if_snd);
1886 * Set a timeout in case the chip goes out to lunch.
1888 sc->ndis_tx_timer = 5;
1893 * According to NDIS documentation, if a driver exports
1894 * a MiniportSendPackets() routine, we prefer that over
1895 * a MiniportSend() routine (which sends just a single
1898 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1899 ndis_send_packets(sc, p0, pcnt);
1901 ndis_send_packet(sc, p);
1907 ndis_init(void *xsc)
1909 struct ndis_softc *sc = xsc;
1910 struct ifnet *ifp = sc->ifp;
1911 struct ieee80211com *ic = ifp->if_l2com;
1915 * Avoid reintializing the link unnecessarily.
1916 * This should be dealt with in a better way by
1917 * fixing the upper layer modules so they don't
1918 * call ifp->if_init() quite as often.
1924 * Cancel pending I/O and free all RX/TX buffers.
1928 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1929 error = ndis_init_nic(sc);
1931 device_printf(sc->ndis_dev,
1932 "failed to initialize the device: %d\n", error);
1937 /* Init our MAC address */
1939 /* Program the packet filter */
1941 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1943 if (ifp->if_flags & IFF_BROADCAST)
1944 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1946 if (ifp->if_flags & IFF_PROMISC)
1947 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1949 len = sizeof(sc->ndis_filter);
1951 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1952 &sc->ndis_filter, &len);
1955 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1962 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1965 * Program the multicast filter, if necessary.
1969 /* Setup task offload. */
1970 ndis_set_offload(sc);
1975 sc->ndis_txpending = sc->ndis_maxpkts;
1978 sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
1979 if_link_state_change(sc->ifp);
1981 ifp->if_flags |= IFF_RUNNING;
1982 ifq_clr_oactive(&ifp->if_snd);
1983 sc->ndis_tx_timer = 0;
1986 * Some drivers don't set this value. The NDIS spec says
1987 * the default checkforhang timeout is "approximately 2
1988 * seconds." We use 3 seconds, because it seems for some
1989 * drivers, exactly 2 seconds is too fast.
1991 if (sc->ndis_block->nmb_checkforhangsecs == 0)
1992 sc->ndis_block->nmb_checkforhangsecs = 3;
1994 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1995 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1998 /* XXX force handling */
2000 ieee80211_start_all(ic); /* start all vap's */
2004 * Set media options.
2007 ndis_ifmedia_upd(struct ifnet *ifp)
2009 struct ndis_softc *sc;
2013 if (NDIS_INITIALIZED(sc))
2020 * Report current media status.
2023 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2025 struct ndis_softc *sc;
2026 uint32_t media_info;
2027 ndis_media_state linkstate;
2030 ifmr->ifm_status = IFM_AVALID;
2031 ifmr->ifm_active = IFM_ETHER;
2034 if (!NDIS_INITIALIZED(sc))
2037 len = sizeof(linkstate);
2038 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2039 (void *)&linkstate, &len);
2041 len = sizeof(media_info);
2042 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2043 (void *)&media_info, &len);
2045 if (linkstate == nmc_connected)
2046 ifmr->ifm_status |= IFM_ACTIVE;
2048 switch (media_info) {
2050 ifmr->ifm_active |= IFM_10_T;
2053 ifmr->ifm_active |= IFM_100_TX;
2056 ifmr->ifm_active |= IFM_1000_T;
2059 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2065 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2067 struct ieee80211com *ic;
2071 ic = sc->ifp->if_l2com;
2075 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2076 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2078 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2081 if (cipher == WPA_CSE_TKIP) {
2082 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2084 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2087 if (cipher == WPA_CSE_CCMP) {
2088 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2090 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2093 DPRINTF(("Setting cipher to %d\n", arg));
2095 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2100 /* Check that the cipher was set correctly. */
2103 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2105 if (rval != 0 || arg != save)
2112 * WPA is hairy to set up. Do the work in a separate routine
2113 * so we don't clutter the setstate function too much.
2114 * Important yet undocumented fact: first we have to set the
2115 * authentication mode, _then_ we enable the ciphers. If one
2116 * of the WPA authentication modes isn't enabled, the driver
2117 * might not permit the TKIP or AES ciphers to be selected.
2120 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2122 struct ieee80211_ie_wpa *w;
2129 * Apparently, the only way for us to know what ciphers
2130 * and key management/authentication mode to use is for
2131 * us to inspect the optional information element (IE)
2132 * stored in the 802.11 state machine. This IE should be
2133 * supplied by the WPA supplicant.
2136 w = (struct ieee80211_ie_wpa *)ie;
2138 /* Check for the right kind of IE. */
2139 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2140 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2144 /* Skip over the ucast cipher OIDs. */
2145 pos = (char *)&w->wpa_uciphers[0];
2146 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2148 /* Skip over the authmode count. */
2149 pos += sizeof(u_int16_t);
2152 * Check for the authentication modes. I'm
2153 * pretty sure there's only supposed to be one.
2156 n = (struct ndis_ie *)pos;
2157 if (n->ni_val == WPA_ASE_NONE)
2158 arg = NDIS_80211_AUTHMODE_WPANONE;
2160 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2161 arg = NDIS_80211_AUTHMODE_WPA;
2163 if (n->ni_val == WPA_ASE_8021X_PSK)
2164 arg = NDIS_80211_AUTHMODE_WPAPSK;
2166 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2168 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2171 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2173 /* Now configure the desired ciphers. */
2175 /* First, set up the multicast group cipher. */
2176 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2178 if (ndis_set_cipher(sc, n->ni_val))
2181 /* Now start looking around for the unicast ciphers. */
2182 pos = (char *)&w->wpa_uciphers[0];
2183 n = (struct ndis_ie *)pos;
2185 for (i = 0; i < w->wpa_uciphercnt; i++) {
2186 if (ndis_set_cipher(sc, n->ni_val))
2195 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2197 struct ieee80211vap *vap = ifp->if_softc;
2198 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2202 if (!NDIS_INITIALIZED(sc))
2205 len = sizeof(txrate);
2206 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2207 vap->iv_bss->ni_txrate = txrate / 5000;
2208 ieee80211_media_status(ifp, imr);
2212 ndis_setstate_80211(struct ndis_softc *sc)
2214 struct ieee80211com *ic;
2215 struct ieee80211vap *vap;
2216 ndis_80211_macaddr bssid;
2217 ndis_80211_config config;
2221 char ethstr[ETHER_ADDRSTRLEN + 1];
2225 vap = TAILQ_FIRST(&ic->ic_vaps);
2227 if (!NDIS_INITIALIZED(sc)) {
2228 DPRINTF(("%s: NDIS not initialized\n", __func__));
2232 /* Disassociate and turn off radio. */
2235 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2237 /* Set network infrastructure mode. */
2240 if (ic->ic_opmode == IEEE80211_M_IBSS)
2241 arg = NDIS_80211_NET_INFRA_IBSS;
2243 arg = NDIS_80211_NET_INFRA_BSS;
2245 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2248 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2250 /* Set power management */
2252 if (vap->iv_flags & IEEE80211_F_PMGTON)
2253 arg = NDIS_80211_POWERMODE_FAST_PSP;
2255 arg = NDIS_80211_POWERMODE_CAM;
2256 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2259 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2260 ic->ic_txpowlimit < NELEM(dBm2mW)) {
2261 arg = dBm2mW[ic->ic_txpowlimit];
2263 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2267 * Default encryption mode to off, authentication
2268 * to open and privacy to 'accept everything.'
2271 arg = NDIS_80211_WEPSTAT_DISABLED;
2272 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2275 arg = NDIS_80211_AUTHMODE_OPEN;
2276 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2279 * Note that OID_802_11_PRIVACY_FILTER is optional:
2280 * not all drivers implement it.
2283 arg = NDIS_80211_PRIVFILT_8021XWEP;
2284 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2286 len = sizeof(config);
2287 bzero((char *)&config, len);
2288 config.nc_length = len;
2289 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2290 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2293 * Some drivers expect us to initialize these values, so
2294 * provide some defaults.
2297 if (config.nc_beaconperiod == 0)
2298 config.nc_beaconperiod = 100;
2299 if (config.nc_atimwin == 0)
2300 config.nc_atimwin = 100;
2301 if (config.nc_fhconfig.ncf_dwelltime == 0)
2302 config.nc_fhconfig.ncf_dwelltime = 200;
2303 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2306 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2307 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2308 config.nc_dsconfig =
2309 ic->ic_bsschan->ic_freq * 1000;
2310 len = sizeof(config);
2311 config.nc_length = len;
2312 config.nc_fhconfig.ncf_length =
2313 sizeof(ndis_80211_config_fh);
2314 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2315 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2318 device_printf(sc->ndis_dev, "couldn't change "
2319 "DS config to %ukHz: %d\n",
2320 config.nc_dsconfig, rval);
2323 device_printf(sc->ndis_dev, "couldn't retrieve "
2324 "channel info: %d\n", rval);
2326 /* Set the BSSID to our value so the driver doesn't associate */
2327 len = IEEE80211_ADDR_LEN;
2328 bcopy(IF_LLADDR(ifp), bssid, len);
2329 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2330 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2332 device_printf(sc->ndis_dev,
2333 "setting BSSID failed: %d\n", rval);
2337 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2339 struct ieee80211_node *ni;
2340 ndis_80211_ssid ssid;
2341 ndis_80211_macaddr bssid;
2343 int i, rval = 0, len, error;
2346 char ethstr[ETHER_ADDRSTRLEN + 1];
2351 if (!NDIS_INITIALIZED(sc)) {
2352 DPRINTF(("%s: NDIS not initialized\n", __func__));
2357 ndis_setstate_80211(sc);
2359 /* Set network infrastructure mode. */
2362 if (vap->iv_opmode == IEEE80211_M_IBSS)
2363 arg = NDIS_80211_NET_INFRA_IBSS;
2365 arg = NDIS_80211_NET_INFRA_BSS;
2367 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2370 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2372 /* Set RTS threshold */
2375 arg = vap->iv_rtsthreshold;
2376 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2378 /* Set fragmentation threshold */
2381 arg = vap->iv_fragthreshold;
2382 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2386 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2387 !(vap->iv_flags & IEEE80211_F_WPA)) {
2390 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2392 arg = NDIS_80211_AUTHMODE_SHARED;
2393 DPRINTF(("Setting shared auth\n"));
2394 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2397 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2398 if (vap->iv_nw_keys[i].wk_keylen) {
2399 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2400 IEEE80211_CIPHER_WEP)
2402 bzero((char *)&wep, sizeof(wep));
2403 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2406 * 5, 13 and 16 are the only valid
2407 * key lengths. Anything in between
2408 * will be zero padded out to the
2409 * next highest boundary.
2411 if (vap->iv_nw_keys[i].wk_keylen < 5)
2413 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2414 vap->iv_nw_keys[i].wk_keylen < 13)
2416 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2417 vap->iv_nw_keys[i].wk_keylen < 16)
2421 wep.nw_length = (sizeof(uint32_t) * 3)
2423 if (i == vap->iv_def_txkey)
2424 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2425 bcopy(vap->iv_nw_keys[i].wk_key,
2426 wep.nw_keydata, wep.nw_length);
2428 DPRINTF(("Setting WEP key %d\n", i));
2429 rval = ndis_set_info(sc,
2430 OID_802_11_ADD_WEP, &wep, &len);
2432 device_printf(sc->ndis_dev,
2433 "set wepkey failed: %d\n", rval);
2438 DPRINTF(("Setting WEP on\n"));
2439 arg = NDIS_80211_WEPSTAT_ENABLED;
2441 rval = ndis_set_info(sc,
2442 OID_802_11_WEP_STATUS, &arg, &len);
2444 device_printf(sc->ndis_dev,
2445 "enable WEP failed: %d\n", rval);
2446 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2447 arg = NDIS_80211_PRIVFILT_8021XWEP;
2449 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2453 OID_802_11_PRIVACY_FILTER, &arg, &len);
2458 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2459 vap->iv_appie_assocreq != NULL) {
2460 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2461 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2463 device_printf(sc->ndis_dev, "WPA setup failed\n");
2467 /* Set network type. */
2471 switch (vap->iv_curmode) {
2472 case IEEE80211_MODE_11A:
2473 arg = NDIS_80211_NETTYPE_11OFDM5;
2475 case IEEE80211_MODE_11B:
2476 arg = NDIS_80211_NETTYPE_11DS;
2478 case IEEE80211_MODE_11G:
2479 arg = NDIS_80211_NETTYPE_11OFDM24;
2482 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2487 DPRINTF(("Setting network type to %d\n", arg));
2489 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2492 device_printf(sc->ndis_dev,
2493 "set nettype failed: %d\n", rval);
2498 * If the user selected a specific BSSID, try
2499 * to use that one. This is useful in the case where
2500 * there are several APs in range with the same network
2501 * name. To delete the BSSID, we use the broadcast
2502 * address as the BSSID.
2503 * Note that some drivers seem to allow setting a BSSID
2504 * in ad-hoc mode, which has the effect of forcing the
2505 * NIC to create an ad-hoc cell with a specific BSSID,
2506 * instead of a randomly chosen one. However, the net80211
2507 * code makes the assumtion that the BSSID setting is invalid
2508 * when you're in ad-hoc mode, so we don't allow that here.
2511 len = IEEE80211_ADDR_LEN;
2512 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2513 vap->iv_opmode != IEEE80211_M_IBSS)
2514 bcopy(ni->ni_bssid, bssid, len);
2516 bcopy(ifp->if_broadcastaddr, bssid, len);
2518 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2519 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2521 device_printf(sc->ndis_dev,
2522 "setting BSSID failed: %d\n", rval);
2524 /* Set SSID -- always do this last. */
2527 if (ndis_debug > 0) {
2528 kprintf("Setting ESSID to ");
2529 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2535 bzero((char *)&ssid, len);
2536 ssid.ns_ssidlen = ni->ni_esslen;
2537 if (ssid.ns_ssidlen == 0) {
2538 ssid.ns_ssidlen = 1;
2540 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2542 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2545 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2551 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2555 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2556 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2560 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2561 if (error == ENOSPC) {
2562 kfree(*bl, M_DEVBUF);
2563 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2567 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2570 DPRINTF(("%s: failed to read\n", __func__));
2571 kfree(*bl, M_DEVBUF);
2579 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2581 struct ifnet *ifp = sc->ifp;
2582 struct ieee80211com *ic = ifp->if_l2com;
2583 struct ieee80211vap *vap;
2584 struct ieee80211_node *ni;
2585 ndis_80211_bssid_list_ex *bl;
2586 ndis_wlan_bssid_ex *bs;
2587 ndis_80211_macaddr bssid;
2593 len = sizeof(bssid);
2594 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2596 device_printf(sc->ndis_dev, "failed to get bssid\n");
2600 vap = TAILQ_FIRST(&ic->ic_vaps);
2603 error = ndis_get_bssid_list(sc, &bl);
2607 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2608 for (i = 0; i < bl->nblx_items; i++) {
2609 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2610 *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2611 if (*assoc == NULL) {
2615 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2617 if (ic->ic_opmode == IEEE80211_M_STA)
2618 ni->ni_associd = 1 | 0xc000; /* fake associd */
2621 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2629 ndis_getstate_80211(struct ndis_softc *sc)
2631 struct ieee80211com *ic;
2632 struct ieee80211vap *vap;
2633 struct ieee80211_node *ni;
2634 ndis_wlan_bssid_ex *bs;
2635 int rval, len, i = 0;
2642 vap = TAILQ_FIRST(&ic->ic_vaps);
2645 if (!NDIS_INITIALIZED(sc))
2648 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2651 /* We're associated, retrieve info on the current bssid. */
2652 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2653 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2654 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2656 /* Get SSID from current association info. */
2657 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2658 bs->nwbx_ssid.ns_ssidlen);
2659 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2661 if (ic->ic_caps & IEEE80211_C_PMGT) {
2663 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2666 device_printf(sc->ndis_dev,
2667 "get power mode failed: %d\n", rval);
2668 if (arg == NDIS_80211_POWERMODE_CAM)
2669 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2671 vap->iv_flags |= IEEE80211_F_PMGTON;
2675 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2677 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2678 for (i = 0; i < NELEM(dBm2mW); i++)
2679 if (dBm2mW[i] >= arg)
2681 ic->ic_txpowlimit = i;
2685 * Use the current association information to reflect
2686 * what channel we're on.
2688 ic->ic_curchan = ieee80211_find_channel(ic,
2689 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2690 if (ic->ic_curchan == NULL)
2691 ic->ic_curchan = &ic->ic_channels[0];
2692 ni->ni_chan = ic->ic_curchan;
2693 ic->ic_bsschan = ic->ic_curchan;
2698 * Determine current authentication mode.
2701 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2703 device_printf(sc->ndis_dev,
2704 "get authmode status failed: %d\n", rval);
2706 vap->iv_flags &= ~IEEE80211_F_WPA;
2708 case NDIS_80211_AUTHMODE_OPEN:
2709 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2711 case NDIS_80211_AUTHMODE_SHARED:
2712 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2714 case NDIS_80211_AUTHMODE_AUTO:
2715 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2717 case NDIS_80211_AUTHMODE_WPA:
2718 case NDIS_80211_AUTHMODE_WPAPSK:
2719 case NDIS_80211_AUTHMODE_WPANONE:
2720 ni->ni_authmode = IEEE80211_AUTH_WPA;
2721 vap->iv_flags |= IEEE80211_F_WPA1;
2723 case NDIS_80211_AUTHMODE_WPA2:
2724 case NDIS_80211_AUTHMODE_WPA2PSK:
2725 ni->ni_authmode = IEEE80211_AUTH_WPA;
2726 vap->iv_flags |= IEEE80211_F_WPA2;
2729 ni->ni_authmode = IEEE80211_AUTH_NONE;
2735 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2738 device_printf(sc->ndis_dev,
2739 "get wep status failed: %d\n", rval);
2741 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2742 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2744 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2748 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2750 struct ndis_softc *sc = ifp->if_softc;
2751 struct ifreq *ifr = (struct ifreq *) data;
2758 if (ifp->if_flags & IFF_UP) {
2759 if (ifp->if_flags & IFF_RUNNING &&
2760 ifp->if_flags & IFF_PROMISC &&
2761 !(sc->ndis_if_flags & IFF_PROMISC)) {
2763 NDIS_PACKET_TYPE_PROMISCUOUS;
2764 i = sizeof(sc->ndis_filter);
2765 error = ndis_set_info(sc,
2766 OID_GEN_CURRENT_PACKET_FILTER,
2767 &sc->ndis_filter, &i);
2768 } else if (ifp->if_flags & IFF_RUNNING &&
2769 !(ifp->if_flags & IFF_PROMISC) &&
2770 sc->ndis_if_flags & IFF_PROMISC) {
2772 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2773 i = sizeof(sc->ndis_filter);
2774 error = ndis_set_info(sc,
2775 OID_GEN_CURRENT_PACKET_FILTER,
2776 &sc->ndis_filter, &i);
2780 if (ifp->if_flags & IFF_RUNNING)
2783 sc->ndis_if_flags = ifp->if_flags;
2793 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2796 ifp->if_capenable = ifr->ifr_reqcap;
2797 if (ifp->if_capenable & IFCAP_TXCSUM)
2798 ifp->if_hwassist = sc->ndis_hwassist;
2800 ifp->if_hwassist = 0;
2801 ndis_set_offload(sc);
2804 error = ether_ioctl(ifp, command, data);
2808 /*NDIS_UNLOCK(sc);*/
2814 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2817 struct ndis_softc *sc = ifp->if_softc;
2818 struct ieee80211com *ic = ifp->if_l2com;
2819 struct ifreq *ifr = (struct ifreq *) data;
2820 struct ndis_oid_data oid;
2821 struct ndis_evt evt;
2828 if (ifp->if_flags & IFF_UP) {
2829 if (!(ifp->if_flags & IFF_RUNNING))
2832 if (ifp->if_flags & IFF_RUNNING)
2835 sc->ndis_if_flags = ifp->if_flags;
2837 /*NDIS_UNLOCK(sc);*/
2840 if ((error = priv_check(curthread, PRIV_DRIVER)))
2842 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2845 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2846 if (oidbuf == NULL) {
2850 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2852 kfree(oidbuf, M_TEMP);
2855 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2857 kfree(oidbuf, M_TEMP);
2860 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2862 kfree(oidbuf, M_TEMP);
2865 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2866 kfree(oidbuf, M_TEMP);
2869 if ((error = priv_check(curthread, PRIV_DRIVER)))
2871 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2874 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2875 if (oidbuf == NULL) {
2879 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2881 kfree(oidbuf, M_TEMP);
2884 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2886 kfree(oidbuf, M_TEMP);
2889 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2891 kfree(oidbuf, M_TEMP);
2894 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2895 kfree(oidbuf, M_TEMP);
2897 case SIOCGPRIVATE_0:
2898 if ((error = priv_check(curthread, PRIV_DRIVER)))
2901 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2906 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2911 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2916 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2917 ifr->ifr_data, sizeof(uint32_t) * 2);
2922 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2923 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2924 (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2925 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2930 kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2931 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2933 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2934 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2935 NDIS_EVTINC(sc->ndis_evtcidx);
2939 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2942 error = ether_ioctl(ifp, command, data);
2952 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2954 struct ndis_softc *sc;
2955 ndis_80211_key rkey;
2958 sc = vap->iv_ic->ic_ifp->if_softc;
2960 bzero((char *)&rkey, sizeof(rkey));
2964 rkey.nk_keyidx = key->wk_keyix;
2966 bcopy(vap->iv_ifp->if_broadcastaddr,
2967 rkey.nk_bssid, IEEE80211_ADDR_LEN);
2969 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
2978 * In theory this could be called for any key, but we'll
2979 * only use it for WPA TKIP or AES keys. These need to be
2980 * set after initial authentication with the AP.
2983 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
2984 const uint8_t mac[IEEE80211_ADDR_LEN])
2986 struct ndis_softc *sc;
2988 ndis_80211_key rkey;
2991 ifp = vap->iv_ic->ic_ifp;
2994 switch (key->wk_cipher->ic_cipher) {
2995 case IEEE80211_CIPHER_TKIP:
2997 len = sizeof(ndis_80211_key);
2998 bzero((char *)&rkey, sizeof(rkey));
3001 rkey.nk_keylen = key->wk_keylen;
3003 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3004 rkey.nk_keylen += 16;
3006 /* key index - gets weird in NDIS */
3008 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3009 rkey.nk_keyidx = key->wk_keyix;
3013 if (key->wk_flags & IEEE80211_KEY_XMIT)
3014 rkey.nk_keyidx |= 1 << 31;
3016 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3017 bcopy(ifp->if_broadcastaddr,
3018 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3020 bcopy(vap->iv_bss->ni_bssid,
3021 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3023 rkey.nk_keyidx |= 1 << 30;
3026 /* need to set bit 29 based on keyrsc */
3027 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3030 rkey.nk_keyidx |= 1 << 29;
3032 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3033 bcopy(key->wk_key, rkey.nk_keydata, 16);
3034 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3035 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3037 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3039 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3041 case IEEE80211_CIPHER_WEP:
3045 * I don't know how to set up keys for the AES
3046 * cipher yet. Is it the same as TKIP?
3048 case IEEE80211_CIPHER_AES_CCM:
3054 /* We need to return 1 for success, 0 for failure. */
3063 ndis_resettask(device_object *d, void *arg)
3065 struct ndis_softc *sc;
3072 * Stop the adapter and free any mbufs allocated to the
3076 ndis_stop(struct ndis_softc *sc)
3082 callout_stop_sync(&sc->ndis_stat_callout);
3085 sc->ndis_tx_timer = 0;
3087 ifp->if_flags &= ~IFF_RUNNING;
3088 ifq_clr_oactive(&ifp->if_snd);
3091 if (sc->ndis_iftype != PNPBus ||
3092 (sc->ndis_iftype == PNPBus &&
3093 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3098 for (i = 0; i < NDIS_EVENTS; i++) {
3099 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3100 kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3101 sc->ndis_evt[i].ne_buf = NULL;
3103 sc->ndis_evt[i].ne_sts = 0;
3104 sc->ndis_evt[i].ne_len = 0;
3106 sc->ndis_evtcidx = 0;
3107 sc->ndis_evtpidx = 0;
3112 * Stop all chip I/O so that the kernel's probe routines don't
3113 * get confused by errant DMAs when rebooting.
3116 ndis_shutdown(device_t dev)
3118 struct ndis_softc *sc;
3120 wlan_serialize_enter();
3121 sc = device_get_softc(dev);
3123 wlan_serialize_exit();
3127 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3129 struct ndis_vap *nvp = NDIS_VAP(vap);
3130 struct ieee80211com *ic = vap->iv_ic;
3131 struct ifnet *ifp = ic->ic_ifp;
3132 struct ndis_softc *sc = ifp->if_softc;
3133 enum ieee80211_state ostate;
3135 DPRINTF(("%s: %s -> %s\n", __func__,
3136 ieee80211_state_name[vap->iv_state],
3137 ieee80211_state_name[nstate]));
3139 ostate = vap->iv_state;
3140 vap->iv_state = nstate;
3143 /* pass on to net80211 */
3144 case IEEE80211_S_INIT:
3145 case IEEE80211_S_SCAN:
3146 return nvp->newstate(vap, nstate, arg);
3147 case IEEE80211_S_ASSOC:
3148 if (ostate != IEEE80211_S_AUTH) {
3149 wlan_serialize_exit();
3150 ndis_auth_and_assoc(sc, vap);
3151 wlan_serialize_enter();
3154 case IEEE80211_S_AUTH:
3155 wlan_serialize_exit();
3156 ndis_auth_and_assoc(sc, vap);
3157 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3158 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3159 wlan_serialize_enter();
3168 ndis_scan(void *arg)
3170 struct ieee80211vap *vap = arg;
3172 ieee80211_scan_done(vap);
3176 ndis_scan_results(struct ndis_softc *sc)
3178 struct ieee80211com *ic;
3179 struct ieee80211vap *vap;
3180 ndis_80211_bssid_list_ex *bl;
3181 ndis_wlan_bssid_ex *wb;
3182 struct ieee80211_scanparams sp;
3183 struct ieee80211_frame wh;
3184 struct ieee80211_channel *saved_chan;
3186 int rssi, noise, freq, chanflag;
3187 uint8_t ssid[2+IEEE80211_NWID_LEN];
3188 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3189 uint8_t *frm, *efrm;
3190 char ethstr[ETHER_ADDRSTRLEN + 1];
3192 ic = sc->ifp->if_l2com;
3193 vap = TAILQ_FIRST(&ic->ic_vaps);
3194 saved_chan = ic->ic_curchan;
3197 if (ndis_get_bssid_list(sc, &bl))
3200 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3201 wb = &bl->nblx_bssid[0];
3202 for (i = 0; i < bl->nblx_items; i++) {
3203 memset(&sp, 0, sizeof(sp));
3205 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3206 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3207 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3208 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3209 if (wb->nwbx_privacy)
3210 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3211 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3212 switch (wb->nwbx_netinfra) {
3213 case NDIS_80211_NET_INFRA_IBSS:
3214 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3216 case NDIS_80211_NET_INFRA_BSS:
3217 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3220 sp.rates = &rates[0];
3221 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3222 /* XXX - check units */
3223 if (wb->nwbx_supportedrates[j] == 0)
3226 wb->nwbx_supportedrates[j] & 0x7f;
3230 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3231 wb->nwbx_ssid.ns_ssidlen);
3232 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3234 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3235 freq = wb->nwbx_config.nc_dsconfig / 1000;
3236 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3237 /* Hack ic->ic_curchan to be in sync with the scan result */
3238 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3239 if (ic->ic_curchan == NULL)
3240 ic->ic_curchan = &ic->ic_channels[0];
3242 /* Process extended info from AP */
3243 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3244 frm = (uint8_t *)&wb->nwbx_ies;
3245 efrm = frm + wb->nwbx_ielen;
3246 if (efrm - frm < 12)
3248 sp.tstamp = frm; frm += 8;
3249 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3250 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3252 sp.ies_len = efrm - frm;
3255 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3256 kether_ntoa(wb->nwbx_macaddr, ethstr), freq, sp.bchan, chanflag,
3258 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3259 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3261 kfree(bl, M_DEVBUF);
3262 /* Restore the channel after messing with it */
3263 ic->ic_curchan = saved_chan;
3267 ndis_scan_start(struct ieee80211com *ic)
3269 struct ifnet *ifp = ic->ic_ifp;
3270 struct ndis_softc *sc = ifp->if_softc;
3271 struct ieee80211vap *vap;
3272 struct ieee80211_scan_state *ss;
3273 ndis_80211_ssid ssid;
3277 vap = TAILQ_FIRST(&ic->ic_vaps);
3279 if (!NDIS_INITIALIZED(sc)) {
3280 DPRINTF(("%s: scan aborted\n", __func__));
3281 ieee80211_cancel_scan(vap);
3286 bzero((char *)&ssid, len);
3287 if (ss->ss_nssid == 0)
3288 ssid.ns_ssidlen = 1;
3290 /* Perform a directed scan */
3291 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3292 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3295 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3297 DPRINTF(("%s: set ESSID failed\n", __func__));
3300 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3302 DPRINTF(("%s: scan command failed\n", __func__));
3303 ieee80211_cancel_scan(vap);
3306 /* Set a timer to collect the results */
3307 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3311 ndis_set_channel(struct ieee80211com *ic)
3317 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3323 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3325 /* NB: don't try to abort scan; wait for firmware to finish */
3329 ndis_scan_end(struct ieee80211com *ic)
3331 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3333 ndis_scan_results(sc);