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.178 2011/01/07 18:41:59 bschmidt 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/usb/usb.h>
75 #include <bus/usb/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/usbd_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 name[IFNAMSIZ], int unit, int opmode,
153 int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
154 const uint8_t mac[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 *);
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_xferlock);
553 InitializeListHead(&sc->ndis_shlist);
554 InitializeListHead(&sc->ndisusb_xferlist);
555 callout_init_mp(&sc->ndis_stat_callout);
557 if (sc->ndis_iftype == PCMCIABus) {
558 error = ndis_alloc_amem(sc);
560 device_printf(dev, "failed to allocate "
561 "attribute memory\n");
566 /* Create sysctl registry nodes */
567 ndis_create_sysctls(sc);
569 /* Find the PDO for this device instance. */
571 if (sc->ndis_iftype == PCIBus)
572 pdrv = windrv_lookup(0, "PCI Bus");
573 else if (sc->ndis_iftype == PCMCIABus)
574 pdrv = windrv_lookup(0, "PCCARD Bus");
576 pdrv = windrv_lookup(0, "USB Bus");
577 pdo = windrv_find_pdo(pdrv, dev);
580 * Create a new functional device object for this
581 * device. This is what creates the miniport block
582 * for this device instance.
585 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
586 device_printf(dev, "failed to create FDO!\n");
591 /* Tell the user what version of the API the driver is using. */
592 device_printf(dev, "NDIS API version: %d.%d\n",
593 sc->ndis_chars->nmc_version_major,
594 sc->ndis_chars->nmc_version_minor);
596 /* Do resource conversion. */
597 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
598 ndis_convert_res(sc);
600 sc->ndis_block->nmb_rlist = NULL;
602 /* Install our RX and TX interrupt handlers. */
603 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
604 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
605 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
606 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
607 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
609 /* Override the status handler so we can detect link changes. */
610 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
611 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
613 /* Set up work item handlers. */
614 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
615 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
616 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
617 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
618 sc->ndisusb_xferitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
619 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
621 /* Call driver's init routine. */
622 if (ndis_init_nic(sc)) {
623 device_printf(dev, "init handler failed\n");
629 * Get station address from the driver.
632 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
635 * Figure out how big to make the TX buffer pool.
638 len = sizeof(sc->ndis_maxpkts);
639 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
640 &sc->ndis_maxpkts, &len)) {
641 device_printf(dev, "failed to get max TX packets\n");
647 * If this is a deserialized miniport, we don't have
648 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
650 if (!NDIS_SERIALIZED(sc->ndis_block))
651 sc->ndis_maxpkts = NDIS_TXPKTS;
653 /* Enforce some sanity, just in case. */
655 if (sc->ndis_maxpkts == 0)
656 sc->ndis_maxpkts = 10;
658 sc->ndis_txarray = kmalloc(sizeof(ndis_packet *) *
659 sc->ndis_maxpkts, M_DEVBUF, M_WAITOK|M_ZERO);
661 /* Allocate a pool of ndis_packets for TX encapsulation. */
663 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
664 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
666 if (i != NDIS_STATUS_SUCCESS) {
667 sc->ndis_txpool = NULL;
668 device_printf(dev, "failed to allocate TX packet pool");
673 sc->ndis_txpending = sc->ndis_maxpkts;
676 /* Get supported oid list. */
677 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
679 /* If the NDIS module requested scatter/gather, init maps. */
684 * See if the OID_802_11_CONFIGURATION OID is
685 * supported by this driver. If it is, then this an 802.11
686 * wireless driver, and we should set up media for wireless.
688 for (i = 0; i < sc->ndis_oidcnt; i++)
689 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
695 ifp = if_alloc(IFT_IEEE80211);
697 ifp = if_alloc(IFT_ETHER);
705 /* Check for task offload support. */
706 ndis_probe_offload(sc);
708 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
709 ifp->if_mtu = ETHERMTU;
710 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
712 if (sc->ndis_iftype == PNPBus)
713 ifp->if_flags |= IFF_NEEDSGIANT;
715 ifp->if_ioctl = ndis_ioctl;
716 ifp->if_start = ndis_start;
717 ifp->if_init = ndis_init;
718 ifp->if_baudrate = 10000000;
719 ifq_set_maxlen(&ifp->if_snd, 50);
720 #if 0 /* XXX swildner */
721 ifp->if_snd.ifq_drv_maxlen = 25;
723 ifq_set_ready(&ifp->if_snd);
724 ifp->if_capenable = ifp->if_capabilities;
725 ifp->if_hwassist = sc->ndis_hwassist;
728 if (sc->ndis_80211) {
729 struct ieee80211com *ic = ifp->if_l2com;
730 ndis_80211_rates_ex rates;
731 struct ndis_80211_nettype_list *ntl;
735 callout_init_mp(&sc->ndis_scan_callout);
737 ifp->if_ioctl = ndis_ioctl_80211;
739 ic->ic_opmode = IEEE80211_M_STA;
740 ic->ic_phytype = IEEE80211_T_DS;
741 ic->ic_caps = IEEE80211_C_8023ENCAP |
742 IEEE80211_C_STA | IEEE80211_C_IBSS;
743 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
745 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
749 ntl = kmalloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
750 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
753 kfree(ntl, M_DEVBUF);
757 for (i = 0; i < ntl->ntl_items; i++) {
758 mode = ndis_nettype_mode(ntl->ntl_type[i]);
760 setbit(ic->ic_modecaps, mode);
761 setbit(&bands, mode);
763 device_printf(dev, "Unknown nettype %d\n",
766 kfree(ntl, M_DEVBUF);
768 /* Default to 11b channels if the card did not supply any */
770 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
771 setbit(&bands, IEEE80211_MODE_11B);
774 bzero((char *)&rates, len);
775 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
776 (void *)rates, &len);
778 device_printf(dev, "get rates failed: 0x%x\n", r);
780 * Since the supported rates only up to 8 can be supported,
781 * if this is not 802.11b we're just going to be faking it
785 #define TESTSETRATE(x, y) \
788 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
789 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
792 if (i == ic->ic_sup_rates[x].rs_nrates) { \
793 ic->ic_sup_rates[x].rs_rates[i] = (y); \
794 ic->ic_sup_rates[x].rs_nrates++; \
798 #define SETRATE(x, y) \
799 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
801 ic->ic_sup_rates[x].rs_nrates++
803 ic->ic_curmode = IEEE80211_MODE_AUTO;
804 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
805 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
806 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
807 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
808 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
809 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
810 for (i = 0; i < len; i++) {
811 switch (rates[i] & IEEE80211_RATE_VAL) {
817 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
818 /* Lazy-init 802.11b. */
819 setbit(ic->ic_modecaps,
821 ic->ic_sup_rates[IEEE80211_MODE_11B].
824 SETRATE(IEEE80211_MODE_11B, rates[i]);
825 INCRATE(IEEE80211_MODE_11B);
828 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
829 SETRATE(IEEE80211_MODE_11A, rates[i]);
830 INCRATE(IEEE80211_MODE_11A);
832 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
833 SETRATE(IEEE80211_MODE_11G, rates[i]);
834 INCRATE(IEEE80211_MODE_11G);
841 * If the hardware supports 802.11g, it most
842 * likely supports 802.11b and all of the
843 * 802.11b and 802.11g speeds, so maybe we can
844 * just cheat here. Just how in the heck do
845 * we detect turbo modes, though?
847 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
848 TESTSETRATE(IEEE80211_MODE_11B,
849 IEEE80211_RATE_BASIC|2);
850 TESTSETRATE(IEEE80211_MODE_11B,
851 IEEE80211_RATE_BASIC|4);
852 TESTSETRATE(IEEE80211_MODE_11B,
853 IEEE80211_RATE_BASIC|11);
854 TESTSETRATE(IEEE80211_MODE_11B,
855 IEEE80211_RATE_BASIC|22);
857 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
858 TESTSETRATE(IEEE80211_MODE_11G, 48);
859 TESTSETRATE(IEEE80211_MODE_11G, 72);
860 TESTSETRATE(IEEE80211_MODE_11G, 96);
861 TESTSETRATE(IEEE80211_MODE_11G, 108);
863 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
864 TESTSETRATE(IEEE80211_MODE_11A, 48);
865 TESTSETRATE(IEEE80211_MODE_11A, 72);
866 TESTSETRATE(IEEE80211_MODE_11A, 96);
867 TESTSETRATE(IEEE80211_MODE_11A, 108);
871 ieee80211_init_channels(ic, NULL, &bands);
874 * To test for WPA support, we need to see if we can
875 * set AUTHENTICATION_MODE to WPA and read it back
879 arg = NDIS_80211_AUTHMODE_WPA;
880 r = ndis_set_info(sc,
881 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
883 r = ndis_get_info(sc,
884 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
885 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
886 ic->ic_caps |= IEEE80211_C_WPA;
890 * To test for supported ciphers, we set each
891 * available encryption type in descending order.
892 * If ENC3 works, then we have WEP, TKIP and AES.
893 * If only ENC2 works, then we have WEP and TKIP.
894 * If only ENC1 works, then we have just WEP.
897 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
898 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
900 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
901 | IEEE80211_CRYPTO_TKIP
902 | IEEE80211_CRYPTO_AES_CCM;
905 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
906 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
908 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
909 | IEEE80211_CRYPTO_TKIP;
912 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
913 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
915 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
918 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
920 ic->ic_caps |= IEEE80211_C_PMGT;
922 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
924 ic->ic_caps |= IEEE80211_C_TXPMGT;
926 ieee80211_ifattach(ic, eaddr);
927 ic->ic_raw_xmit = ndis_raw_xmit;
928 ic->ic_scan_start = ndis_scan_start;
929 ic->ic_scan_end = ndis_scan_end;
930 ic->ic_set_channel = ndis_set_channel;
931 ic->ic_scan_curchan = ndis_scan_curchan;
932 ic->ic_scan_mindwell = ndis_scan_mindwell;
933 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
934 //ic->ic_bss->ni_chan = ic->ic_bsschan;
935 ic->ic_vap_create = ndis_vap_create;
936 ic->ic_vap_delete = ndis_vap_delete;
937 ic->ic_update_mcast = ndis_update_mcast;
938 ic->ic_update_promisc = ndis_update_promisc;
941 ieee80211_announce(ic);
944 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
946 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
947 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
948 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
949 ifmedia_add(&sc->ifmedia,
950 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
951 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
952 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
953 ether_ifattach(ifp, eaddr, NULL);
962 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
965 DPRINTF(("attach done.\n"));
966 /* We're done talking to the NIC for now; halt it. */
968 DPRINTF(("halting done.\n"));
973 static struct ieee80211vap *
974 ndis_vap_create(struct ieee80211com *ic,
975 const char name[IFNAMSIZ], int unit, int opmode, int flags,
976 const uint8_t bssid[IEEE80211_ADDR_LEN],
977 const uint8_t mac[IEEE80211_ADDR_LEN])
979 struct ndis_vap *nvp;
980 struct ieee80211vap *vap;
982 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
984 nvp = (struct ndis_vap *) kmalloc(sizeof(struct ndis_vap),
985 M_80211_VAP, M_NOWAIT | M_ZERO);
989 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
990 /* override with driver methods */
991 nvp->newstate = vap->iv_newstate;
992 vap->iv_newstate = ndis_newstate;
995 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
996 ic->ic_opmode = opmode;
997 /* install key handing routines */
998 vap->iv_key_set = ndis_add_key;
999 vap->iv_key_delete = ndis_del_key;
1004 ndis_vap_delete(struct ieee80211vap *vap)
1006 struct ndis_vap *nvp = NDIS_VAP(vap);
1007 struct ieee80211com *ic = vap->iv_ic;
1008 struct ifnet *ifp = ic->ic_ifp;
1009 struct ndis_softc *sc = ifp->if_softc;
1012 callout_stop(&sc->ndis_scan_callout); /* XXX swildner callout_drain() */
1013 ieee80211_vap_detach(vap);
1014 kfree(nvp, M_80211_VAP);
1018 * Shutdown hardware and free up resources. This can be called any
1019 * time after the mutex has been initialized. It is called in both
1020 * the error case in attach and the normal detach case so it needs
1021 * to be careful about only freeing resources that have actually been
1025 ndis_detach(device_t dev)
1027 struct ndis_softc *sc;
1031 sc = device_get_softc(dev);
1034 ifp->if_flags &= ~IFF_UP;
1036 if (device_is_attached(dev)) {
1040 ieee80211_ifdetach(ifp->if_l2com);
1042 ether_ifdetach(ifp);
1046 if (sc->ndis_tickitem != NULL)
1047 IoFreeWorkItem(sc->ndis_tickitem);
1048 if (sc->ndis_startitem != NULL)
1049 IoFreeWorkItem(sc->ndis_startitem);
1050 if (sc->ndis_resetitem != NULL)
1051 IoFreeWorkItem(sc->ndis_resetitem);
1052 if (sc->ndis_inputitem != NULL)
1053 IoFreeWorkItem(sc->ndis_inputitem);
1054 if (sc->ndisusb_xferitem != NULL)
1055 IoFreeWorkItem(sc->ndisusb_xferitem);
1057 bus_generic_detach(dev);
1058 ndis_unload_driver(sc);
1061 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1062 if (sc->ndis_res_io)
1063 bus_release_resource(dev, SYS_RES_IOPORT,
1064 sc->ndis_io_rid, sc->ndis_res_io);
1065 if (sc->ndis_res_mem)
1066 bus_release_resource(dev, SYS_RES_MEMORY,
1067 sc->ndis_mem_rid, sc->ndis_res_mem);
1068 if (sc->ndis_res_altmem)
1069 bus_release_resource(dev, SYS_RES_MEMORY,
1070 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1075 if (sc->ndis_iftype == PCMCIABus)
1079 ndis_destroy_dma(sc);
1081 if (sc->ndis_txarray)
1082 kfree(sc->ndis_txarray, M_DEVBUF);
1084 if (!sc->ndis_80211)
1085 ifmedia_removeall(&sc->ifmedia);
1087 if (sc->ndis_txpool != NULL)
1088 NdisFreePacketPool(sc->ndis_txpool);
1090 /* Destroy the PDO for this device. */
1092 if (sc->ndis_iftype == PCIBus)
1093 drv = windrv_lookup(0, "PCI Bus");
1094 else if (sc->ndis_iftype == PCMCIABus)
1095 drv = windrv_lookup(0, "PCCARD Bus");
1097 drv = windrv_lookup(0, "USB Bus");
1099 panic("couldn't find driver object");
1100 windrv_destroy_pdo(drv, dev);
1102 if (sc->ndis_iftype == PCIBus)
1103 bus_dma_tag_destroy(sc->ndis_parent_tag);
1109 ndis_suspend(device_t dev)
1111 struct ndis_softc *sc;
1114 wlan_serialize_enter();
1115 sc = device_get_softc(dev);
1119 if (NDIS_INITIALIZED(sc))
1123 wlan_serialize_exit();
1128 ndis_resume(device_t dev)
1130 struct ndis_softc *sc;
1133 wlan_serialize_enter();
1134 sc = device_get_softc(dev);
1137 if (NDIS_INITIALIZED(sc))
1140 wlan_serialize_exit();
1145 * The following bunch of routines are here to support drivers that
1146 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1147 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1148 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1152 ndis_rxeof_eth(ndis_handle adapter, ndis_handle ctx, char *addr, void *hdr,
1153 uint32_t hdrlen, void *lookahead, uint32_t lookaheadlen, uint32_t pktlen)
1155 ndis_miniport_block *block;
1165 m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
1169 /* Save the data provided to us so far. */
1171 m->m_len = lookaheadlen + hdrlen;
1172 m->m_pkthdr.len = pktlen + hdrlen;
1174 m_copyback(m, 0, hdrlen, hdr);
1175 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1177 /* Now create a fake NDIS_PACKET to hold the data */
1179 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1181 if (status != NDIS_STATUS_SUCCESS) {
1188 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1196 p->np_private.npp_head = p->np_private.npp_tail = b;
1197 p->np_private.npp_totlen = m->m_pkthdr.len;
1199 /* Save the packet RX context somewhere. */
1200 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1201 priv->nep_ctx = ctx;
1203 if (!NDIS_SERIALIZED(block))
1204 KeAcquireSpinLock(&block->nmb_lock, &irql);
1206 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1208 if (!NDIS_SERIALIZED(block))
1209 KeReleaseSpinLock(&block->nmb_lock, irql);
1213 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1214 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1218 ndis_rxeof_done(ndis_handle adapter)
1220 struct ndis_softc *sc;
1221 ndis_miniport_block *block;
1225 /* Schedule transfer/RX of queued packets. */
1227 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1229 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1233 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1236 ndis_rxeof_xfr(kdpc *dpc, ndis_handle adapter, void *sysarg1, void *sysarg2)
1238 ndis_miniport_block *block;
1239 struct ndis_softc *sc;
1248 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1251 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1253 l = block->nmb_packetlist.nle_flink;
1254 while(!IsListEmpty(&block->nmb_packetlist)) {
1255 l = RemoveHeadList((&block->nmb_packetlist));
1256 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1257 InitializeListHead((&p->np_list));
1259 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1264 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1266 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1267 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1268 m->m_len, m->m_pkthdr.len - m->m_len);
1270 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1273 * If status is NDIS_STATUS_PENDING, do nothing and
1274 * wait for a callback to the ndis_rxeof_xfr_done()
1278 m->m_len = m->m_pkthdr.len;
1279 m->m_pkthdr.rcvif = ifp;
1281 if (status == NDIS_STATUS_SUCCESS) {
1282 IoFreeMdl(p->np_private.npp_head);
1284 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1285 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1286 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1287 IoQueueWorkItem(sc->ndis_inputitem,
1288 (io_workitem_func)ndis_inputtask_wrap,
1289 WORKQUEUE_CRITICAL, ifp);
1292 if (status == NDIS_STATUS_FAILURE)
1295 /* Advance to next packet */
1296 l = block->nmb_packetlist.nle_flink;
1299 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1303 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1306 ndis_rxeof_xfr_done(ndis_handle adapter, ndis_packet *packet, uint32_t status,
1309 ndis_miniport_block *block;
1310 struct ndis_softc *sc;
1315 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1319 IoFreeMdl(packet->np_private.npp_head);
1320 NdisFreePacket(packet);
1322 if (status != NDIS_STATUS_SUCCESS) {
1327 m->m_len = m->m_pkthdr.len;
1328 m->m_pkthdr.rcvif = ifp;
1329 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1330 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1331 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1332 IoQueueWorkItem(sc->ndis_inputitem,
1333 (io_workitem_func)ndis_inputtask_wrap,
1334 WORKQUEUE_CRITICAL, ifp);
1337 * A frame has been uploaded: pass the resulting mbuf chain up to
1338 * the higher level protocols.
1340 * When handling received NDIS packets, the 'status' field in the
1341 * out-of-band portion of the ndis_packet has special meaning. In the
1342 * most common case, the underlying NDIS driver will set this field
1343 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1344 * take posession of it. We then change the status field to
1345 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1346 * and that we will return it at some point in the future via the
1347 * return packet handler.
1349 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1350 * this means the driver is running out of packet/buffer resources and
1351 * wants to maintain ownership of the packet. In this case, we have to
1352 * copy the packet data into local storage and let the driver keep the
1356 ndis_rxeof(ndis_handle adapter, ndis_packet **packets, uint32_t pktcnt)
1358 struct ndis_softc *sc;
1359 ndis_miniport_block *block;
1362 ndis_tcpip_csum *csum;
1364 struct mbuf *m0, *m;
1367 block = (ndis_miniport_block *)adapter;
1368 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1372 * There's a slim chance the driver may indicate some packets
1373 * before we're completely ready to handle them. If we detect this,
1374 * we need to return them to the miniport and ignore them.
1376 if (!(ifp->if_flags & IFF_RUNNING)) {
1377 for (i = 0; i < pktcnt; i++) {
1379 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1381 ndis_return_packet(p);
1387 for (i = 0; i < pktcnt; i++) {
1389 /* Stash the softc here so ptom can use it. */
1391 if (ndis_ptom(&m0, p)) {
1392 device_printf(sc->ndis_dev, "ptom failed\n");
1393 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1394 ndis_return_packet(p);
1397 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1398 m = m_dup(m0, MB_DONTWAIT);
1400 * NOTE: we want to destroy the mbuf here, but
1401 * we don't actually want to return it to the
1402 * driver via the return packet handler. By
1403 * bumping np_refcnt, we can prevent the
1404 * ndis_return_packet() routine from actually
1414 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1416 m = m_dup(m0, MB_DONTWAIT);
1417 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1420 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1427 m0->m_pkthdr.rcvif = ifp;
1429 /* Deal with checksum offload. */
1431 if (ifp->if_capenable & IFCAP_RXCSUM &&
1432 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1434 p->np_ext.npe_info[ndis_tcpipcsum_info];
1435 csum = (ndis_tcpip_csum *)&s;
1436 if (csum->u.ntc_rxflags &
1437 NDIS_RXCSUM_IP_PASSED)
1438 m0->m_pkthdr.csum_flags |=
1439 CSUM_IP_CHECKED|CSUM_IP_VALID;
1440 if (csum->u.ntc_rxflags &
1441 (NDIS_RXCSUM_TCP_PASSED |
1442 NDIS_RXCSUM_UDP_PASSED)) {
1443 m0->m_pkthdr.csum_flags |=
1444 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1445 m0->m_pkthdr.csum_data = 0xFFFF;
1449 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1450 IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1451 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1452 IoQueueWorkItem(sc->ndis_inputitem,
1453 (io_workitem_func)ndis_inputtask_wrap,
1454 WORKQUEUE_CRITICAL, ifp);
1460 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1461 * packets into the stack in order to avoid calling (*ifp->if_input)()
1462 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1463 * 'dispatch level' per-cpu sleep lock).
1466 ndis_inputtask(device_object *dobj, void *arg)
1468 ndis_miniport_block *block;
1470 struct ndis_softc *sc;
1472 struct ieee80211com *ic;
1473 struct ieee80211vap *vap;
1479 vap = TAILQ_FIRST(&ic->ic_vaps);
1480 block = dobj->do_devext;
1482 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1484 IF_DEQUEUE(&sc->ndis_rxqueue, m);
1487 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1488 if ((sc->ndis_80211 != 0) && (vap != NULL))
1489 vap->iv_deliver_data(vap, vap->iv_bss, m);
1491 (*ifp->if_input)(ifp, m);
1492 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1494 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1498 * A frame was downloaded to the chip. It's safe for us to clean up
1502 ndis_txeof(ndis_handle adapter, ndis_packet *packet, ndis_status status)
1504 struct ndis_softc *sc;
1505 ndis_miniport_block *block;
1510 block = (ndis_miniport_block *)adapter;
1511 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1515 idx = packet->np_txidx;
1517 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1519 ndis_free_packet(packet);
1523 sc->ndis_txarray[idx] = NULL;
1524 sc->ndis_txpending++;
1526 if (status == NDIS_STATUS_SUCCESS)
1531 sc->ndis_tx_timer = 0;
1532 ifp->if_flags &= ~IFF_OACTIVE;
1536 IoQueueWorkItem(sc->ndis_startitem,
1537 (io_workitem_func)ndis_starttask_wrap,
1538 WORKQUEUE_CRITICAL, ifp);
1542 ndis_linksts(ndis_handle adapter, ndis_status status, void *sbuf,
1545 ndis_miniport_block *block;
1546 struct ndis_softc *sc;
1549 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1550 sc->ndis_sts = status;
1552 /* Event list is all full up, drop this one. */
1555 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1560 /* Cache the event. */
1563 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = kmalloc(slen,
1565 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1570 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1572 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1573 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1574 NDIS_EVTINC(sc->ndis_evtpidx);
1579 ndis_linksts_done(ndis_handle adapter)
1581 ndis_miniport_block *block;
1582 struct ndis_softc *sc;
1586 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1589 if (!NDIS_INITIALIZED(sc))
1592 switch (sc->ndis_sts) {
1593 case NDIS_STATUS_MEDIA_CONNECT:
1594 IoQueueWorkItem(sc->ndis_tickitem,
1595 (io_workitem_func)ndis_ticktask_wrap,
1596 WORKQUEUE_CRITICAL, sc);
1597 IoQueueWorkItem(sc->ndis_startitem,
1598 (io_workitem_func)ndis_starttask_wrap,
1599 WORKQUEUE_CRITICAL, ifp);
1601 case NDIS_STATUS_MEDIA_DISCONNECT:
1603 IoQueueWorkItem(sc->ndis_tickitem,
1604 (io_workitem_func)ndis_ticktask_wrap,
1605 WORKQUEUE_CRITICAL, sc);
1613 ndis_tick(void *xsc)
1615 struct ndis_softc *sc;
1619 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1620 IoQueueWorkItem(sc->ndis_tickitem,
1621 (io_workitem_func)ndis_ticktask_wrap,
1622 WORKQUEUE_CRITICAL, sc);
1623 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1626 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1627 sc->ifp->if_oerrors++;
1628 device_printf(sc->ndis_dev, "watchdog timeout\n");
1630 IoQueueWorkItem(sc->ndis_resetitem,
1631 (io_workitem_func)ndis_resettask_wrap,
1632 WORKQUEUE_CRITICAL, sc);
1633 IoQueueWorkItem(sc->ndis_startitem,
1634 (io_workitem_func)ndis_starttask_wrap,
1635 WORKQUEUE_CRITICAL, sc->ifp);
1638 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1642 ndis_ticktask(device_object *d, void *xsc)
1644 struct ndis_softc *sc;
1645 struct ieee80211com *ic;
1646 struct ieee80211vap *vap;
1647 ndis_checkforhang_handler hangfunc;
1651 ic = sc->ifp->if_l2com;
1652 vap = TAILQ_FIRST(&ic->ic_vaps);
1655 if (!NDIS_INITIALIZED(sc)) {
1661 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1663 if (hangfunc != NULL) {
1664 rval = MSCALL1(hangfunc,
1665 sc->ndis_block->nmb_miniportadapterctx);
1673 if (sc->ndis_link == 0 &&
1674 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1677 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1678 ndis_getstate_80211(sc);
1679 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1682 sc->ifp->if_link_state = LINK_STATE_UP;
1683 if_link_state_change(sc->ifp);
1686 if (sc->ndis_link == 1 &&
1687 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1690 if ((sc->ndis_80211 != 0) && (vap != NULL))
1691 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1693 sc->ifp->if_link_state = LINK_STATE_DOWN;
1694 if_link_state_change(sc->ifp);
1701 ndis_map_sclist(void *arg, bus_dma_segment_t *segs, int nseg,
1702 bus_size_t mapsize, int error)
1704 struct ndis_sc_list *sclist;
1707 if (error || arg == NULL)
1712 sclist->nsl_frags = nseg;
1714 for (i = 0; i < nseg; i++) {
1715 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1716 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1721 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1722 const struct ieee80211_bpf_params *params)
1724 /* no support; just discard */
1726 ieee80211_free_node(ni);
1731 ndis_update_mcast(struct ifnet *ifp)
1733 struct ndis_softc *sc = ifp->if_softc;
1739 ndis_update_promisc(struct ifnet *ifp)
1745 ndis_starttask(device_object *d, void *arg)
1751 if (!ifq_is_empty(&ifp->if_snd))
1756 * Main transmit routine. To make NDIS drivers happy, we need to
1757 * transform mbuf chains into NDIS packets and feed them to the
1758 * send packet routines. Most drivers allow you to send several
1759 * packets at once (up to the maxpkts limit). Unfortunately, rather
1760 * that accepting them in the form of a linked list, they expect
1761 * a contiguous array of pointers to packets.
1763 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1764 * we need to perform busdma work here. Those that use map registers
1765 * will do the mapping themselves on a buffer by buffer basis.
1768 ndis_start(struct ifnet *ifp)
1770 struct ndis_softc *sc;
1771 struct mbuf *m = NULL;
1772 ndis_packet **p0 = NULL, *p = NULL;
1773 ndis_tcpip_csum *csum;
1774 int pcnt = 0, status;
1779 if (!sc->ndis_link || ifp->if_flags & IFF_OACTIVE) {
1784 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1786 while(sc->ndis_txpending) {
1787 m = ifq_dequeue(&ifp->if_snd, NULL);
1791 NdisAllocatePacket(&status,
1792 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1794 if (status != NDIS_STATUS_SUCCESS)
1797 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1798 ifq_prepend(&ifp->if_snd, m);
1804 * Save pointer to original mbuf
1805 * so we can free it later.
1808 p = sc->ndis_txarray[sc->ndis_txidx];
1809 p->np_txidx = sc->ndis_txidx;
1811 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1814 * Do scatter/gather processing, if driver requested it.
1817 bus_dmamap_load_mbuf(sc->ndis_ttag,
1818 sc->ndis_tmaps[sc->ndis_txidx], m,
1819 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1820 bus_dmamap_sync(sc->ndis_ttag,
1821 sc->ndis_tmaps[sc->ndis_txidx],
1822 BUS_DMASYNC_PREREAD);
1823 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1826 /* Handle checksum offload. */
1828 if (ifp->if_capenable & IFCAP_TXCSUM &&
1829 m->m_pkthdr.csum_flags) {
1830 csum = (ndis_tcpip_csum *)
1831 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1832 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1833 if (m->m_pkthdr.csum_flags & CSUM_IP)
1834 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1835 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1836 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1837 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1838 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1839 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1843 sc->ndis_txpending--;
1848 * If there's a BPF listener, bounce a copy of this frame
1851 if (!sc->ndis_80211) /* XXX handle 80211 */
1855 * The array that p0 points to must appear contiguous,
1856 * so we must not wrap past the end of sc->ndis_txarray[].
1857 * If it looks like we're about to wrap, break out here
1858 * so the this batch of packets can be transmitted, then
1859 * wait for txeof to ask us to send the rest.
1861 if (sc->ndis_txidx == 0)
1870 if (sc->ndis_txpending == 0)
1871 ifp->if_flags |= IFF_OACTIVE;
1874 * Set a timeout in case the chip goes out to lunch.
1876 sc->ndis_tx_timer = 5;
1881 * According to NDIS documentation, if a driver exports
1882 * a MiniportSendPackets() routine, we prefer that over
1883 * a MiniportSend() routine (which sends just a single
1886 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1887 ndis_send_packets(sc, p0, pcnt);
1889 ndis_send_packet(sc, p);
1895 ndis_init(void *xsc)
1897 struct ndis_softc *sc = xsc;
1898 struct ifnet *ifp = sc->ifp;
1899 struct ieee80211com *ic = ifp->if_l2com;
1903 * Avoid reintializing the link unnecessarily.
1904 * This should be dealt with in a better way by
1905 * fixing the upper layer modules so they don't
1906 * call ifp->if_init() quite as often.
1912 * Cancel pending I/O and free all RX/TX buffers.
1916 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1917 error = ndis_init_nic(sc);
1919 device_printf(sc->ndis_dev,
1920 "failed to initialize the device: %d\n", error);
1925 /* Init our MAC address */
1927 /* Program the packet filter */
1929 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1931 if (ifp->if_flags & IFF_BROADCAST)
1932 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1934 if (ifp->if_flags & IFF_PROMISC)
1935 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1937 len = sizeof(sc->ndis_filter);
1939 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1940 &sc->ndis_filter, &len);
1943 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1950 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1953 * Program the multicast filter, if necessary.
1957 /* Setup task offload. */
1958 ndis_set_offload(sc);
1963 sc->ndis_txpending = sc->ndis_maxpkts;
1966 sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
1967 if_link_state_change(sc->ifp);
1969 ifp->if_flags |= IFF_RUNNING;
1970 ifp->if_flags &= ~IFF_OACTIVE;
1971 sc->ndis_tx_timer = 0;
1974 * Some drivers don't set this value. The NDIS spec says
1975 * the default checkforhang timeout is "approximately 2
1976 * seconds." We use 3 seconds, because it seems for some
1977 * drivers, exactly 2 seconds is too fast.
1979 if (sc->ndis_block->nmb_checkforhangsecs == 0)
1980 sc->ndis_block->nmb_checkforhangsecs = 3;
1982 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1983 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1986 /* XXX force handling */
1988 ieee80211_start_all(ic); /* start all vap's */
1992 * Set media options.
1995 ndis_ifmedia_upd(struct ifnet *ifp)
1997 struct ndis_softc *sc;
2001 if (NDIS_INITIALIZED(sc))
2008 * Report current media status.
2011 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2013 struct ndis_softc *sc;
2014 uint32_t media_info;
2015 ndis_media_state linkstate;
2018 ifmr->ifm_status = IFM_AVALID;
2019 ifmr->ifm_active = IFM_ETHER;
2022 if (!NDIS_INITIALIZED(sc))
2025 len = sizeof(linkstate);
2026 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2027 (void *)&linkstate, &len);
2029 len = sizeof(media_info);
2030 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2031 (void *)&media_info, &len);
2033 if (linkstate == nmc_connected)
2034 ifmr->ifm_status |= IFM_ACTIVE;
2036 switch (media_info) {
2038 ifmr->ifm_active |= IFM_10_T;
2041 ifmr->ifm_active |= IFM_100_TX;
2044 ifmr->ifm_active |= IFM_1000_T;
2047 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2053 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2055 struct ieee80211com *ic;
2059 ic = sc->ifp->if_l2com;
2063 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2064 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2066 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2069 if (cipher == WPA_CSE_TKIP) {
2070 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2072 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2075 if (cipher == WPA_CSE_CCMP) {
2076 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2078 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2081 DPRINTF(("Setting cipher to %d\n", arg));
2083 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2088 /* Check that the cipher was set correctly. */
2091 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2093 if (rval != 0 || arg != save)
2100 * WPA is hairy to set up. Do the work in a separate routine
2101 * so we don't clutter the setstate function too much.
2102 * Important yet undocumented fact: first we have to set the
2103 * authentication mode, _then_ we enable the ciphers. If one
2104 * of the WPA authentication modes isn't enabled, the driver
2105 * might not permit the TKIP or AES ciphers to be selected.
2108 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2110 struct ieee80211_ie_wpa *w;
2117 * Apparently, the only way for us to know what ciphers
2118 * and key management/authentication mode to use is for
2119 * us to inspect the optional information element (IE)
2120 * stored in the 802.11 state machine. This IE should be
2121 * supplied by the WPA supplicant.
2124 w = (struct ieee80211_ie_wpa *)ie;
2126 /* Check for the right kind of IE. */
2127 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2128 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2132 /* Skip over the ucast cipher OIDs. */
2133 pos = (char *)&w->wpa_uciphers[0];
2134 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2136 /* Skip over the authmode count. */
2137 pos += sizeof(u_int16_t);
2140 * Check for the authentication modes. I'm
2141 * pretty sure there's only supposed to be one.
2144 n = (struct ndis_ie *)pos;
2145 if (n->ni_val == WPA_ASE_NONE)
2146 arg = NDIS_80211_AUTHMODE_WPANONE;
2148 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2149 arg = NDIS_80211_AUTHMODE_WPA;
2151 if (n->ni_val == WPA_ASE_8021X_PSK)
2152 arg = NDIS_80211_AUTHMODE_WPAPSK;
2154 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2156 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2159 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2161 /* Now configure the desired ciphers. */
2163 /* First, set up the multicast group cipher. */
2164 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2166 if (ndis_set_cipher(sc, n->ni_val))
2169 /* Now start looking around for the unicast ciphers. */
2170 pos = (char *)&w->wpa_uciphers[0];
2171 n = (struct ndis_ie *)pos;
2173 for (i = 0; i < w->wpa_uciphercnt; i++) {
2174 if (ndis_set_cipher(sc, n->ni_val))
2183 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2185 struct ieee80211vap *vap = ifp->if_softc;
2186 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2190 if (!NDIS_INITIALIZED(sc))
2193 len = sizeof(txrate);
2194 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2195 vap->iv_bss->ni_txrate = txrate / 5000;
2196 ieee80211_media_status(ifp, imr);
2200 ndis_setstate_80211(struct ndis_softc *sc)
2202 struct ieee80211com *ic;
2203 struct ieee80211vap *vap;
2204 ndis_80211_macaddr bssid;
2205 ndis_80211_config config;
2212 vap = TAILQ_FIRST(&ic->ic_vaps);
2214 if (!NDIS_INITIALIZED(sc)) {
2215 DPRINTF(("%s: NDIS not initialized\n", __func__));
2219 /* Disassociate and turn off radio. */
2222 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2224 /* Set network infrastructure mode. */
2227 if (ic->ic_opmode == IEEE80211_M_IBSS)
2228 arg = NDIS_80211_NET_INFRA_IBSS;
2230 arg = NDIS_80211_NET_INFRA_BSS;
2232 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2235 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2237 /* Set power management */
2239 if (vap->iv_flags & IEEE80211_F_PMGTON)
2240 arg = NDIS_80211_POWERMODE_FAST_PSP;
2242 arg = NDIS_80211_POWERMODE_CAM;
2243 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2246 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2247 ic->ic_txpowlimit < NELEM(dBm2mW)) {
2248 arg = dBm2mW[ic->ic_txpowlimit];
2250 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2254 * Default encryption mode to off, authentication
2255 * to open and privacy to 'accept everything.'
2258 arg = NDIS_80211_WEPSTAT_DISABLED;
2259 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2262 arg = NDIS_80211_AUTHMODE_OPEN;
2263 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2266 * Note that OID_802_11_PRIVACY_FILTER is optional:
2267 * not all drivers implement it.
2270 arg = NDIS_80211_PRIVFILT_8021XWEP;
2271 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2273 len = sizeof(config);
2274 bzero((char *)&config, len);
2275 config.nc_length = len;
2276 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2277 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2280 * Some drivers expect us to initialize these values, so
2281 * provide some defaults.
2284 if (config.nc_beaconperiod == 0)
2285 config.nc_beaconperiod = 100;
2286 if (config.nc_atimwin == 0)
2287 config.nc_atimwin = 100;
2288 if (config.nc_fhconfig.ncf_dwelltime == 0)
2289 config.nc_fhconfig.ncf_dwelltime = 200;
2290 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2293 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2294 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2295 IEEE80211_CHAN_5GHZ;
2296 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2297 config.nc_dsconfig =
2298 ic->ic_bsschan->ic_freq * 1000;
2299 len = sizeof(config);
2300 config.nc_length = len;
2301 config.nc_fhconfig.ncf_length =
2302 sizeof(ndis_80211_config_fh);
2303 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2304 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2307 device_printf(sc->ndis_dev, "couldn't change "
2308 "DS config to %ukHz: %d\n",
2309 config.nc_dsconfig, rval);
2312 device_printf(sc->ndis_dev, "couldn't retrieve "
2313 "channel info: %d\n", rval);
2315 /* Set the BSSID to our value so the driver doesn't associate */
2316 len = IEEE80211_ADDR_LEN;
2317 bcopy(IF_LLADDR(ifp), bssid, len);
2318 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2319 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2321 device_printf(sc->ndis_dev,
2322 "setting BSSID failed: %d\n", rval);
2326 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2328 struct ieee80211com *ic;
2329 struct ieee80211_node *ni;
2330 ndis_80211_ssid ssid;
2331 ndis_80211_macaddr bssid;
2333 int i, rval = 0, len, error;
2341 if (!NDIS_INITIALIZED(sc)) {
2342 DPRINTF(("%s: NDIS not initialized\n", __func__));
2347 ndis_setstate_80211(sc);
2349 /* Set network infrastructure mode. */
2352 if (vap->iv_opmode == IEEE80211_M_IBSS)
2353 arg = NDIS_80211_NET_INFRA_IBSS;
2355 arg = NDIS_80211_NET_INFRA_BSS;
2357 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2360 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2362 /* Set RTS threshold */
2365 arg = vap->iv_rtsthreshold;
2366 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2368 /* Set fragmentation threshold */
2371 arg = vap->iv_fragthreshold;
2372 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2376 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2377 !(vap->iv_flags & IEEE80211_F_WPA)) {
2380 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2382 arg = NDIS_80211_AUTHMODE_SHARED;
2383 DPRINTF(("Setting shared auth\n"));
2384 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2387 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2388 if (vap->iv_nw_keys[i].wk_keylen) {
2389 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2390 IEEE80211_CIPHER_WEP)
2392 bzero((char *)&wep, sizeof(wep));
2393 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2396 * 5, 13 and 16 are the only valid
2397 * key lengths. Anything in between
2398 * will be zero padded out to the
2399 * next highest boundary.
2401 if (vap->iv_nw_keys[i].wk_keylen < 5)
2403 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2404 vap->iv_nw_keys[i].wk_keylen < 13)
2406 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2407 vap->iv_nw_keys[i].wk_keylen < 16)
2411 wep.nw_length = (sizeof(uint32_t) * 3)
2413 if (i == vap->iv_def_txkey)
2414 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2415 bcopy(vap->iv_nw_keys[i].wk_key,
2416 wep.nw_keydata, wep.nw_length);
2418 DPRINTF(("Setting WEP key %d\n", i));
2419 rval = ndis_set_info(sc,
2420 OID_802_11_ADD_WEP, &wep, &len);
2422 device_printf(sc->ndis_dev,
2423 "set wepkey failed: %d\n", rval);
2428 DPRINTF(("Setting WEP on\n"));
2429 arg = NDIS_80211_WEPSTAT_ENABLED;
2431 rval = ndis_set_info(sc,
2432 OID_802_11_WEP_STATUS, &arg, &len);
2434 device_printf(sc->ndis_dev,
2435 "enable WEP failed: %d\n", rval);
2436 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2437 arg = NDIS_80211_PRIVFILT_8021XWEP;
2439 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2443 OID_802_11_PRIVACY_FILTER, &arg, &len);
2448 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2449 vap->iv_appie_assocreq != NULL) {
2450 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2451 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2453 device_printf(sc->ndis_dev, "WPA setup failed\n");
2457 /* Set network type. */
2461 switch (vap->iv_curmode) {
2462 case IEEE80211_MODE_11A:
2463 arg = NDIS_80211_NETTYPE_11OFDM5;
2465 case IEEE80211_MODE_11B:
2466 arg = NDIS_80211_NETTYPE_11DS;
2468 case IEEE80211_MODE_11G:
2469 arg = NDIS_80211_NETTYPE_11OFDM24;
2472 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2477 DPRINTF(("Setting network type to %d\n", arg));
2479 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2482 device_printf(sc->ndis_dev,
2483 "set nettype failed: %d\n", rval);
2488 * If the user selected a specific BSSID, try
2489 * to use that one. This is useful in the case where
2490 * there are several APs in range with the same network
2491 * name. To delete the BSSID, we use the broadcast
2492 * address as the BSSID.
2493 * Note that some drivers seem to allow setting a BSSID
2494 * in ad-hoc mode, which has the effect of forcing the
2495 * NIC to create an ad-hoc cell with a specific BSSID,
2496 * instead of a randomly chosen one. However, the net80211
2497 * code makes the assumtion that the BSSID setting is invalid
2498 * when you're in ad-hoc mode, so we don't allow that here.
2501 len = IEEE80211_ADDR_LEN;
2502 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2503 vap->iv_opmode != IEEE80211_M_IBSS)
2504 bcopy(ni->ni_bssid, bssid, len);
2506 bcopy(ifp->if_broadcastaddr, bssid, len);
2508 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2509 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2511 device_printf(sc->ndis_dev,
2512 "setting BSSID failed: %d\n", rval);
2514 /* Set SSID -- always do this last. */
2517 if (ndis_debug > 0) {
2518 kprintf("Setting ESSID to ");
2519 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2525 bzero((char *)&ssid, len);
2526 ssid.ns_ssidlen = ni->ni_esslen;
2527 if (ssid.ns_ssidlen == 0) {
2528 ssid.ns_ssidlen = 1;
2530 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2532 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2535 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2541 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2545 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2546 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2550 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2551 if (error == ENOSPC) {
2552 kfree(*bl, M_DEVBUF);
2553 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2557 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2560 DPRINTF(("%s: failed to read\n", __func__));
2561 kfree(*bl, M_DEVBUF);
2569 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2571 struct ifnet *ifp = sc->ifp;
2572 struct ieee80211com *ic = ifp->if_l2com;
2573 struct ieee80211vap *vap;
2574 struct ieee80211_node *ni;
2575 ndis_80211_bssid_list_ex *bl;
2576 ndis_wlan_bssid_ex *bs;
2577 ndis_80211_macaddr bssid;
2583 len = sizeof(bssid);
2584 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2586 device_printf(sc->ndis_dev, "failed to get bssid\n");
2590 vap = TAILQ_FIRST(&ic->ic_vaps);
2593 error = ndis_get_bssid_list(sc, &bl);
2597 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2598 for (i = 0; i < bl->nblx_items; i++) {
2599 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2600 *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2601 if (*assoc == NULL) {
2605 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2607 if (ic->ic_opmode == IEEE80211_M_STA)
2608 ni->ni_associd = 1 | 0xc000; /* fake associd */
2611 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2619 ndis_getstate_80211(struct ndis_softc *sc)
2621 struct ieee80211com *ic;
2622 struct ieee80211vap *vap;
2623 struct ieee80211_node *ni;
2624 ndis_wlan_bssid_ex *bs;
2625 int rval, len, i = 0;
2632 vap = TAILQ_FIRST(&ic->ic_vaps);
2635 if (!NDIS_INITIALIZED(sc))
2638 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2641 /* We're associated, retrieve info on the current bssid. */
2642 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2643 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2644 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2646 /* Get SSID from current association info. */
2647 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2648 bs->nwbx_ssid.ns_ssidlen);
2649 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2651 if (ic->ic_caps & IEEE80211_C_PMGT) {
2653 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2656 device_printf(sc->ndis_dev,
2657 "get power mode failed: %d\n", rval);
2658 if (arg == NDIS_80211_POWERMODE_CAM)
2659 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2661 vap->iv_flags |= IEEE80211_F_PMGTON;
2665 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2667 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2668 for (i = 0; i < NELEM(dBm2mW); i++)
2669 if (dBm2mW[i] >= arg)
2671 ic->ic_txpowlimit = i;
2675 * Use the current association information to reflect
2676 * what channel we're on.
2678 ic->ic_curchan = ieee80211_find_channel(ic,
2679 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2680 if (ic->ic_curchan == NULL)
2681 ic->ic_curchan = &ic->ic_channels[0];
2682 ni->ni_chan = ic->ic_curchan;
2683 ic->ic_bsschan = ic->ic_curchan;
2688 * Determine current authentication mode.
2691 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2693 device_printf(sc->ndis_dev,
2694 "get authmode status failed: %d\n", rval);
2696 vap->iv_flags &= ~IEEE80211_F_WPA;
2698 case NDIS_80211_AUTHMODE_OPEN:
2699 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2701 case NDIS_80211_AUTHMODE_SHARED:
2702 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2704 case NDIS_80211_AUTHMODE_AUTO:
2705 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2707 case NDIS_80211_AUTHMODE_WPA:
2708 case NDIS_80211_AUTHMODE_WPAPSK:
2709 case NDIS_80211_AUTHMODE_WPANONE:
2710 ni->ni_authmode = IEEE80211_AUTH_WPA;
2711 vap->iv_flags |= IEEE80211_F_WPA1;
2713 case NDIS_80211_AUTHMODE_WPA2:
2714 case NDIS_80211_AUTHMODE_WPA2PSK:
2715 ni->ni_authmode = IEEE80211_AUTH_WPA;
2716 vap->iv_flags |= IEEE80211_F_WPA2;
2719 ni->ni_authmode = IEEE80211_AUTH_NONE;
2725 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2728 device_printf(sc->ndis_dev,
2729 "get wep status failed: %d\n", rval);
2731 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2732 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2734 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2738 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2740 struct ndis_softc *sc = ifp->if_softc;
2741 struct ifreq *ifr = (struct ifreq *) data;
2748 if (ifp->if_flags & IFF_UP) {
2749 if (ifp->if_flags & IFF_RUNNING &&
2750 ifp->if_flags & IFF_PROMISC &&
2751 !(sc->ndis_if_flags & IFF_PROMISC)) {
2753 NDIS_PACKET_TYPE_PROMISCUOUS;
2754 i = sizeof(sc->ndis_filter);
2755 error = ndis_set_info(sc,
2756 OID_GEN_CURRENT_PACKET_FILTER,
2757 &sc->ndis_filter, &i);
2758 } else if (ifp->if_flags & IFF_RUNNING &&
2759 !(ifp->if_flags & IFF_PROMISC) &&
2760 sc->ndis_if_flags & IFF_PROMISC) {
2762 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2763 i = sizeof(sc->ndis_filter);
2764 error = ndis_set_info(sc,
2765 OID_GEN_CURRENT_PACKET_FILTER,
2766 &sc->ndis_filter, &i);
2770 if (ifp->if_flags & IFF_RUNNING)
2773 sc->ndis_if_flags = ifp->if_flags;
2783 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2786 ifp->if_capenable = ifr->ifr_reqcap;
2787 if (ifp->if_capenable & IFCAP_TXCSUM)
2788 ifp->if_hwassist = sc->ndis_hwassist;
2790 ifp->if_hwassist = 0;
2791 ndis_set_offload(sc);
2794 error = ether_ioctl(ifp, command, data);
2798 /*NDIS_UNLOCK(sc);*/
2804 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2807 struct ndis_softc *sc = ifp->if_softc;
2808 struct ieee80211com *ic = ifp->if_l2com;
2809 struct ifreq *ifr = (struct ifreq *) data;
2810 struct ndis_oid_data oid;
2811 struct ndis_evt evt;
2818 if (ifp->if_flags & IFF_UP) {
2819 if (!(ifp->if_flags & IFF_RUNNING))
2822 if (ifp->if_flags & IFF_RUNNING)
2825 sc->ndis_if_flags = ifp->if_flags;
2827 /*NDIS_UNLOCK(sc);*/
2830 if ((error = priv_check(curthread, PRIV_DRIVER)))
2832 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2835 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2836 if (oidbuf == NULL) {
2840 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2842 kfree(oidbuf, M_TEMP);
2845 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2847 kfree(oidbuf, M_TEMP);
2850 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2852 kfree(oidbuf, M_TEMP);
2855 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2856 kfree(oidbuf, M_TEMP);
2859 if ((error = priv_check(curthread, PRIV_DRIVER)))
2861 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2864 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2865 if (oidbuf == NULL) {
2869 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2871 kfree(oidbuf, M_TEMP);
2874 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2876 kfree(oidbuf, M_TEMP);
2879 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2881 kfree(oidbuf, M_TEMP);
2884 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2885 kfree(oidbuf, M_TEMP);
2887 case SIOCGPRIVATE_0:
2888 if ((error = priv_check(curthread, PRIV_DRIVER)))
2891 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2896 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2901 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2906 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2907 ifr->ifr_data, sizeof(uint32_t) * 2);
2912 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2913 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2914 (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2915 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2920 kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2921 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2923 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2924 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2925 NDIS_EVTINC(sc->ndis_evtcidx);
2929 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2932 error = ether_ioctl(ifp, command, data);
2942 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2944 struct ndis_softc *sc;
2945 ndis_80211_key rkey;
2948 sc = vap->iv_ic->ic_ifp->if_softc;
2950 bzero((char *)&rkey, sizeof(rkey));
2954 rkey.nk_keyidx = key->wk_keyix;
2956 bcopy(vap->iv_ifp->if_broadcastaddr,
2957 rkey.nk_bssid, IEEE80211_ADDR_LEN);
2959 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
2968 * In theory this could be called for any key, but we'll
2969 * only use it for WPA TKIP or AES keys. These need to be
2970 * set after initial authentication with the AP.
2973 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
2974 const uint8_t mac[IEEE80211_ADDR_LEN])
2976 struct ndis_softc *sc;
2978 ndis_80211_key rkey;
2981 ifp = vap->iv_ic->ic_ifp;
2984 switch (key->wk_cipher->ic_cipher) {
2985 case IEEE80211_CIPHER_TKIP:
2987 len = sizeof(ndis_80211_key);
2988 bzero((char *)&rkey, sizeof(rkey));
2991 rkey.nk_keylen = key->wk_keylen;
2993 if (key->wk_flags & IEEE80211_KEY_SWMIC)
2994 rkey.nk_keylen += 16;
2996 /* key index - gets weird in NDIS */
2998 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
2999 rkey.nk_keyidx = key->wk_keyix;
3003 if (key->wk_flags & IEEE80211_KEY_XMIT)
3004 rkey.nk_keyidx |= 1 << 31;
3006 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3007 bcopy(ifp->if_broadcastaddr,
3008 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3010 bcopy(vap->iv_bss->ni_bssid,
3011 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3013 rkey.nk_keyidx |= 1 << 30;
3016 /* need to set bit 29 based on keyrsc */
3017 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3020 rkey.nk_keyidx |= 1 << 29;
3022 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3023 bcopy(key->wk_key, rkey.nk_keydata, 16);
3024 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3025 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3027 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3029 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3031 case IEEE80211_CIPHER_WEP:
3035 * I don't know how to set up keys for the AES
3036 * cipher yet. Is it the same as TKIP?
3038 case IEEE80211_CIPHER_AES_CCM:
3044 /* We need to return 1 for success, 0 for failure. */
3053 ndis_resettask(device_object *d, void *arg)
3055 struct ndis_softc *sc;
3062 * Stop the adapter and free any mbufs allocated to the
3066 ndis_stop(struct ndis_softc *sc)
3072 callout_stop(&sc->ndis_stat_callout); /* XXX swildner callout_drain() */
3075 sc->ndis_tx_timer = 0;
3077 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3080 if (sc->ndis_iftype != PNPBus ||
3081 (sc->ndis_iftype == PNPBus &&
3082 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3087 for (i = 0; i < NDIS_EVENTS; i++) {
3088 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3089 kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3090 sc->ndis_evt[i].ne_buf = NULL;
3092 sc->ndis_evt[i].ne_sts = 0;
3093 sc->ndis_evt[i].ne_len = 0;
3095 sc->ndis_evtcidx = 0;
3096 sc->ndis_evtpidx = 0;
3101 * Stop all chip I/O so that the kernel's probe routines don't
3102 * get confused by errant DMAs when rebooting.
3105 ndis_shutdown(device_t dev)
3107 struct ndis_softc *sc;
3109 wlan_serialize_enter();
3110 sc = device_get_softc(dev);
3112 wlan_serialize_exit();
3116 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3118 struct ndis_vap *nvp = NDIS_VAP(vap);
3119 struct ieee80211com *ic = vap->iv_ic;
3120 struct ifnet *ifp = ic->ic_ifp;
3121 struct ndis_softc *sc = ifp->if_softc;
3122 enum ieee80211_state ostate;
3124 DPRINTF(("%s: %s -> %s\n", __func__,
3125 ieee80211_state_name[vap->iv_state],
3126 ieee80211_state_name[nstate]));
3128 ostate = vap->iv_state;
3129 vap->iv_state = nstate;
3132 /* pass on to net80211 */
3133 case IEEE80211_S_INIT:
3134 case IEEE80211_S_SCAN:
3135 return nvp->newstate(vap, nstate, arg);
3136 case IEEE80211_S_ASSOC:
3137 if (ostate != IEEE80211_S_AUTH) {
3138 wlan_serialize_exit();
3139 ndis_auth_and_assoc(sc, vap);
3140 wlan_serialize_enter();
3143 case IEEE80211_S_AUTH:
3144 wlan_serialize_exit();
3145 ndis_auth_and_assoc(sc, vap);
3146 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3147 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3148 wlan_serialize_enter();
3157 ndis_scan(void *arg)
3159 struct ieee80211vap *vap = arg;
3161 ieee80211_scan_done(vap);
3165 ndis_scan_results(struct ndis_softc *sc)
3167 struct ieee80211com *ic;
3168 struct ieee80211vap *vap;
3169 ndis_80211_bssid_list_ex *bl;
3170 ndis_wlan_bssid_ex *wb;
3171 struct ieee80211_scanparams sp;
3172 struct ieee80211_frame wh;
3173 struct ieee80211_channel *saved_chan;
3175 int rssi, noise, freq, chanflag;
3176 uint8_t ssid[2+IEEE80211_NWID_LEN];
3177 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3178 uint8_t *frm, *efrm;
3180 ic = sc->ifp->if_l2com;
3181 vap = TAILQ_FIRST(&ic->ic_vaps);
3182 saved_chan = ic->ic_curchan;
3185 if (ndis_get_bssid_list(sc, &bl))
3188 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3189 wb = &bl->nblx_bssid[0];
3190 for (i = 0; i < bl->nblx_items; i++) {
3191 memset(&sp, 0, sizeof(sp));
3193 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3194 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3195 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3196 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3197 if (wb->nwbx_privacy)
3198 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3199 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3200 switch (wb->nwbx_netinfra) {
3201 case NDIS_80211_NET_INFRA_IBSS:
3202 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3204 case NDIS_80211_NET_INFRA_BSS:
3205 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3208 sp.rates = &rates[0];
3209 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3210 /* XXX - check units */
3211 if (wb->nwbx_supportedrates[j] == 0)
3214 wb->nwbx_supportedrates[j] & 0x7f;
3217 sp.ssid = (uint8_t *)&ssid[0];
3218 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3219 wb->nwbx_ssid.ns_ssidlen);
3220 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3222 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3223 freq = wb->nwbx_config.nc_dsconfig / 1000;
3224 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3225 /* Hack ic->ic_curchan to be in sync with the scan result */
3226 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3227 if (ic->ic_curchan == NULL)
3228 ic->ic_curchan = &ic->ic_channels[0];
3230 /* Process extended info from AP */
3231 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3232 frm = (uint8_t *)&wb->nwbx_ies;
3233 efrm = frm + wb->nwbx_ielen;
3234 if (efrm - frm < 12)
3236 sp.tstamp = frm; frm += 8;
3237 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3238 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3240 sp.ies_len = efrm - frm;
3243 DPRINTF(("scan: bssid %6D chan %dMHz (%d/%d) rssi %d\n",
3244 wb->nwbx_macaddr, ":", freq, sp.bchan, chanflag,
3246 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3247 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3249 kfree(bl, M_DEVBUF);
3250 /* Restore the channel after messing with it */
3251 ic->ic_curchan = saved_chan;
3255 ndis_scan_start(struct ieee80211com *ic)
3257 struct ifnet *ifp = ic->ic_ifp;
3258 struct ndis_softc *sc = ifp->if_softc;
3259 struct ieee80211vap *vap;
3260 struct ieee80211_scan_state *ss;
3261 ndis_80211_ssid ssid;
3265 vap = TAILQ_FIRST(&ic->ic_vaps);
3267 if (!NDIS_INITIALIZED(sc)) {
3268 DPRINTF(("%s: scan aborted\n", __func__));
3269 ieee80211_cancel_scan(vap);
3274 bzero((char *)&ssid, len);
3275 if (ss->ss_nssid == 0)
3276 ssid.ns_ssidlen = 1;
3278 /* Perform a directed scan */
3279 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3280 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3283 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3285 DPRINTF(("%s: set ESSID failed\n", __func__));
3288 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3290 DPRINTF(("%s: scan command failed\n", __func__));
3291 ieee80211_cancel_scan(vap);
3294 /* Set a timer to collect the results */
3295 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3299 ndis_set_channel(struct ieee80211com *ic)
3305 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3311 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3313 /* NB: don't try to abort scan; wait for firmware to finish */
3317 ndis_scan_end(struct ieee80211com *ic)
3319 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3321 ndis_scan_results(sc);