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 "use_usb4bsd.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/sockio.h>
44 #include <sys/malloc.h>
45 #include <sys/endian.h>
47 #include <sys/kernel.h>
48 #include <sys/socket.h>
49 #include <sys/queue.h>
50 #include <sys/module.h>
52 #include <sys/sysctl.h>
53 #include <sys/kthread.h>
56 #include <net/if_arp.h>
57 #include <net/ethernet.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/route.h>
64 #include <net/ifq_var.h>
68 #include <sys/mplock2.h>
70 #include <netproto/802_11/ieee80211_var.h>
71 #include <netproto/802_11/ieee80211_ioctl.h>
72 #include <netproto/802_11/ieee80211_regdomain.h>
74 #include <bus/pci/pcireg.h>
75 #include <bus/pci/pcivar.h>
77 #include <bus/u4b/usb.h>
78 #include <bus/u4b/usbdi.h>
80 #include <bus/usb/usb.h>
81 #include <bus/usb/usbdi.h>
84 #include <emulation/ndis/pe_var.h>
85 #include <emulation/ndis/cfg_var.h>
86 #include <emulation/ndis/resource_var.h>
87 #include <emulation/ndis/ntoskrnl_var.h>
88 #include <emulation/ndis/hal_var.h>
89 #include <emulation/ndis/ndis_var.h>
91 #include <emulation/ndis/u4bd_var.h>
93 #include <emulation/ndis/usbd_var.h>
95 #include <dev/netif/ndis/if_ndisvar.h>
99 #define DPRINTF(x) do { if (ndis_debug > 0) kprintf x; } while (0)
101 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
102 "if_ndis debug level");
107 SYSCTL_DECL(_hw_ndisusb);
108 int ndisusb_halt = 1;
109 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
110 "Halt NDIS USB driver when it's attached");
112 /* 0 - 30 dBm to mW conversion table */
113 static const uint16_t dBm2mW[] = {
114 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
115 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
116 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
117 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
118 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
119 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
123 MODULE_DEPEND(if_ndis, ether, 1, 1, 1);
124 MODULE_DEPEND(if_ndis, wlan, 1, 1, 1);
125 MODULE_DEPEND(if_ndis, ndis, 1, 1, 1);
127 MODULE_VERSION(if_ndis, 1);
129 int ndis_attach (device_t);
130 int ndis_detach (device_t);
131 int ndis_suspend (device_t);
132 int ndis_resume (device_t);
133 void ndis_shutdown (device_t);
135 int ndisdrv_modevent (module_t, int, void *);
137 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
138 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
139 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
140 uint32_t, void *, uint32_t, uint32_t);
141 static void ndis_rxeof_done (ndis_handle);
142 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
143 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
145 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
146 static void ndis_linksts_done (ndis_handle);
148 /* We need to wrap these functions for amd64. */
149 static funcptr ndis_txeof_wrap;
150 static funcptr ndis_rxeof_wrap;
151 static funcptr ndis_rxeof_eth_wrap;
152 static funcptr ndis_rxeof_done_wrap;
153 static funcptr ndis_rxeof_xfr_wrap;
154 static funcptr ndis_rxeof_xfr_done_wrap;
155 static funcptr ndis_linksts_wrap;
156 static funcptr ndis_linksts_done_wrap;
157 static funcptr ndis_ticktask_wrap;
158 static funcptr ndis_starttask_wrap;
159 static funcptr ndis_resettask_wrap;
160 static funcptr ndis_inputtask_wrap;
162 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
163 const char [IFNAMSIZ], int, int, int,
164 const uint8_t [IEEE80211_ADDR_LEN],
165 const uint8_t [IEEE80211_ADDR_LEN]);
166 static void ndis_vap_delete (struct ieee80211vap *);
167 static void ndis_tick (void *);
168 static void ndis_ticktask (device_object *, void *);
169 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
170 const struct ieee80211_bpf_params *);
171 static void ndis_update_mcast (struct ifnet *ifp);
172 static void ndis_update_promisc (struct ifnet *ifp);
173 static void ndis_start (struct ifnet *);
174 static void ndis_starttask (device_object *, void *);
175 static void ndis_resettask (device_object *, void *);
176 static void ndis_inputtask (device_object *, void *);
177 static int ndis_ioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
178 static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t, struct ucred *);
179 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
181 static int ndis_nettype_chan (uint32_t);
182 static int ndis_nettype_mode (uint32_t);
183 static void ndis_scan (void *);
184 static void ndis_scan_results (struct ndis_softc *);
185 static void ndis_scan_start (struct ieee80211com *);
186 static void ndis_scan_end (struct ieee80211com *);
187 static void ndis_set_channel (struct ieee80211com *);
188 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
189 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
190 static void ndis_init (void *);
191 static void ndis_stop (struct ndis_softc *);
192 static int ndis_ifmedia_upd (struct ifnet *);
193 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
194 static int ndis_get_bssid_list (struct ndis_softc *,
195 ndis_80211_bssid_list_ex **);
196 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
197 static int ndis_probe_offload (struct ndis_softc *);
198 static int ndis_set_offload (struct ndis_softc *);
199 static void ndis_getstate_80211 (struct ndis_softc *);
200 static void ndis_setstate_80211 (struct ndis_softc *);
201 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
202 static void ndis_media_status (struct ifnet *, struct ifmediareq *);
203 static int ndis_set_cipher (struct ndis_softc *, int);
204 static int ndis_set_wpa (struct ndis_softc *, void *, int);
205 static int ndis_add_key (struct ieee80211vap *,
206 const struct ieee80211_key *, const u_int8_t []);
207 static int ndis_del_key (struct ieee80211vap *,
208 const struct ieee80211_key *);
210 static void ndis_setmulti (struct ndis_softc *);
211 static void ndis_map_sclist (void *, bus_dma_segment_t *,
212 int, bus_size_t, int);
214 static int ndisdrv_loaded = 0;
217 * This routine should call windrv_load() once for each driver
218 * image. This will do the relocation and dynalinking for the
219 * image, and create a Windows driver object which will be
220 * saved in our driver database.
223 ndisdrv_modevent(module_t mod, int cmd, void *arg)
230 if (ndisdrv_loaded > 1)
232 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
233 3, WINDRV_WRAP_STDCALL);
234 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
235 8, WINDRV_WRAP_STDCALL);
236 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
237 1, WINDRV_WRAP_STDCALL);
238 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
239 4, WINDRV_WRAP_STDCALL);
240 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
241 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
242 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
243 3, WINDRV_WRAP_STDCALL);
244 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
245 4, WINDRV_WRAP_STDCALL);
246 windrv_wrap((funcptr)ndis_linksts_done,
247 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
248 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
249 2, WINDRV_WRAP_STDCALL);
250 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
251 2, WINDRV_WRAP_STDCALL);
252 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
253 2, WINDRV_WRAP_STDCALL);
254 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
255 2, WINDRV_WRAP_STDCALL);
259 if (ndisdrv_loaded > 0)
263 windrv_unwrap(ndis_rxeof_wrap);
264 windrv_unwrap(ndis_rxeof_eth_wrap);
265 windrv_unwrap(ndis_rxeof_done_wrap);
266 windrv_unwrap(ndis_rxeof_xfr_wrap);
267 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
268 windrv_unwrap(ndis_txeof_wrap);
269 windrv_unwrap(ndis_linksts_wrap);
270 windrv_unwrap(ndis_linksts_done_wrap);
271 windrv_unwrap(ndis_ticktask_wrap);
272 windrv_unwrap(ndis_starttask_wrap);
273 windrv_unwrap(ndis_resettask_wrap);
274 windrv_unwrap(ndis_inputtask_wrap);
285 * Program the 64-bit multicast hash filter.
288 ndis_setmulti(struct ndis_softc *sc)
291 struct ifmultiaddr *ifma;
292 int len, mclistsz, error;
297 if (!NDIS_INITIALIZED(sc))
300 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
302 len = sizeof(sc->ndis_filter);
303 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
304 &sc->ndis_filter, &len);
306 device_printf(sc->ndis_dev,
307 "set allmulti failed: %d\n", error);
311 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
314 len = sizeof(mclistsz);
315 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
317 mclist = kmalloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
319 if (mclist == NULL) {
320 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
324 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
327 #if 0 /* XXX swildner */
330 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
331 if (ifma->ifma_addr->sa_family != AF_LINK)
333 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
334 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
336 if (len > mclistsz) {
337 #if 0 /* XXX swildner */
338 if_maddr_runlock(ifp);
340 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
341 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
345 #if 0 /* XXX swildner */
346 if_maddr_runlock(ifp);
349 len = len * ETHER_ADDR_LEN;
350 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
352 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
353 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
354 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
358 kfree(mclist, M_TEMP);
360 len = sizeof(sc->ndis_filter);
361 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
362 &sc->ndis_filter, &len);
364 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
368 ndis_set_offload(struct ndis_softc *sc)
370 ndis_task_offload *nto;
371 ndis_task_offload_hdr *ntoh;
372 ndis_task_tcpip_csum *nttc;
378 if (!NDIS_INITIALIZED(sc))
381 /* See if there's anything to set. */
383 error = ndis_probe_offload(sc);
387 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
390 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
391 sizeof(ndis_task_tcpip_csum);
393 ntoh = kmalloc(len, M_TEMP, M_NOWAIT|M_ZERO);
398 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
399 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
400 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
401 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
402 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
403 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
405 nto = (ndis_task_offload *)((char *)ntoh +
406 ntoh->ntoh_offset_firsttask);
408 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
409 nto->nto_len = sizeof(ndis_task_offload);
410 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
411 nto->nto_offset_nexttask = 0;
412 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
414 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
416 if (ifp->if_capenable & IFCAP_TXCSUM)
417 nttc->nttc_v4tx = sc->ndis_v4tx;
419 if (ifp->if_capenable & IFCAP_RXCSUM)
420 nttc->nttc_v4rx = sc->ndis_v4rx;
422 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
429 ndis_probe_offload(struct ndis_softc *sc)
431 ndis_task_offload *nto;
432 ndis_task_offload_hdr *ntoh;
433 ndis_task_tcpip_csum *nttc = NULL;
435 int len, error, dummy;
440 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
445 ntoh = kmalloc(len, M_TEMP, M_NOWAIT|M_ZERO);
450 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
451 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
452 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
453 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
454 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
456 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
463 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
468 nto = (ndis_task_offload *)((char *)ntoh +
469 ntoh->ntoh_offset_firsttask);
472 switch (nto->nto_task) {
473 case NDIS_TASK_TCPIP_CSUM:
474 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
476 /* Don't handle these yet. */
477 case NDIS_TASK_IPSEC:
478 case NDIS_TASK_TCP_LARGESEND:
482 if (nto->nto_offset_nexttask == 0)
484 nto = (ndis_task_offload *)((char *)nto +
485 nto->nto_offset_nexttask);
493 sc->ndis_v4tx = nttc->nttc_v4tx;
494 sc->ndis_v4rx = nttc->nttc_v4rx;
496 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
497 sc->ndis_hwassist |= CSUM_IP;
498 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
499 sc->ndis_hwassist |= CSUM_TCP;
500 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
501 sc->ndis_hwassist |= CSUM_UDP;
503 if (sc->ndis_hwassist)
504 ifp->if_capabilities |= IFCAP_TXCSUM;
506 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
507 ifp->if_capabilities |= IFCAP_RXCSUM;
508 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
509 ifp->if_capabilities |= IFCAP_RXCSUM;
510 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
511 ifp->if_capabilities |= IFCAP_RXCSUM;
518 ndis_nettype_chan(uint32_t type)
521 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
522 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
523 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
524 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
526 DPRINTF(("unknown channel nettype %d\n", type));
527 return (IEEE80211_CHAN_B); /* Default to 11B chan */
531 ndis_nettype_mode(uint32_t type)
534 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
535 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
536 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
537 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
539 DPRINTF(("unknown mode nettype %d\n", type));
540 return (IEEE80211_MODE_AUTO);
544 * Attach the interface. Allocate softc structures, do ifmedia
545 * setup and ethernet/BPF attach.
548 ndis_attach(device_t dev)
550 u_char eaddr[ETHER_ADDR_LEN];
551 struct ndis_softc *sc;
554 struct ifnet *ifp = NULL;
555 int error = 0, len, mode;
559 sc = device_get_softc(dev);
561 lockinit(&sc->ndis_lock, "network driver", 0, LK_CANRECURSE);
562 KeInitializeSpinLock(&sc->ndis_rxlock);
564 KeInitializeSpinLock(&sc->ndisusb_tasklock);
565 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
567 KeInitializeSpinLock(&sc->ndisusb_xferlock);
569 InitializeListHead(&sc->ndis_shlist);
571 InitializeListHead(&sc->ndisusb_tasklist);
572 InitializeListHead(&sc->ndisusb_xferdonelist);
574 InitializeListHead(&sc->ndisusb_xferlist);
576 callout_init_mp(&sc->ndis_stat_callout);
578 if (sc->ndis_iftype == PCMCIABus) {
579 error = ndis_alloc_amem(sc);
581 device_printf(dev, "failed to allocate "
582 "attribute memory\n");
587 /* Create sysctl registry nodes */
588 ndis_create_sysctls(sc);
590 /* Find the PDO for this device instance. */
592 if (sc->ndis_iftype == PCIBus)
593 pdrv = windrv_lookup(0, "PCI Bus");
594 else if (sc->ndis_iftype == PCMCIABus)
595 pdrv = windrv_lookup(0, "PCCARD Bus");
597 pdrv = windrv_lookup(0, "USB Bus");
598 pdo = windrv_find_pdo(pdrv, dev);
601 * Create a new functional device object for this
602 * device. This is what creates the miniport block
603 * for this device instance.
606 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
607 device_printf(dev, "failed to create FDO!\n");
612 /* Tell the user what version of the API the driver is using. */
613 device_printf(dev, "NDIS API version: %d.%d\n",
614 sc->ndis_chars->nmc_version_major,
615 sc->ndis_chars->nmc_version_minor);
617 /* Do resource conversion. */
618 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
619 ndis_convert_res(sc);
621 sc->ndis_block->nmb_rlist = NULL;
623 /* Install our RX and TX interrupt handlers. */
624 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
625 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
626 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
627 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
628 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
630 /* Override the status handler so we can detect link changes. */
631 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
632 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
634 /* Set up work item handlers. */
635 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
636 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
637 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
638 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
640 sc->ndisusb_xferdoneitem =
641 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
642 sc->ndisusb_taskitem =
643 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
645 sc->ndisusb_xferitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
647 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
649 /* Call driver's init routine. */
650 if (ndis_init_nic(sc)) {
651 device_printf(dev, "init handler failed\n");
657 * Get station address from the driver.
660 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
663 * Figure out how big to make the TX buffer pool.
666 len = sizeof(sc->ndis_maxpkts);
667 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
668 &sc->ndis_maxpkts, &len)) {
669 device_printf(dev, "failed to get max TX packets\n");
675 * If this is a deserialized miniport, we don't have
676 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
678 if (!NDIS_SERIALIZED(sc->ndis_block))
679 sc->ndis_maxpkts = NDIS_TXPKTS;
681 /* Enforce some sanity, just in case. */
683 if (sc->ndis_maxpkts == 0)
684 sc->ndis_maxpkts = 10;
686 sc->ndis_txarray = kmalloc(sizeof(ndis_packet *) *
687 sc->ndis_maxpkts, M_DEVBUF, M_WAITOK|M_ZERO);
689 /* Allocate a pool of ndis_packets for TX encapsulation. */
691 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
692 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
694 if (i != NDIS_STATUS_SUCCESS) {
695 sc->ndis_txpool = NULL;
696 device_printf(dev, "failed to allocate TX packet pool");
701 sc->ndis_txpending = sc->ndis_maxpkts;
704 /* Get supported oid list. */
705 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
707 /* If the NDIS module requested scatter/gather, init maps. */
712 * See if the OID_802_11_CONFIGURATION OID is
713 * supported by this driver. If it is, then this an 802.11
714 * wireless driver, and we should set up media for wireless.
716 for (i = 0; i < sc->ndis_oidcnt; i++)
717 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
723 ifp = if_alloc(IFT_IEEE80211);
725 ifp = if_alloc(IFT_ETHER);
733 /* Check for task offload support. */
734 ndis_probe_offload(sc);
736 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
737 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
739 if (sc->ndis_iftype == PNPBus)
740 ifp->if_flags |= IFF_NEEDSGIANT;
742 ifp->if_ioctl = ndis_ioctl;
743 ifp->if_start = ndis_start;
744 ifp->if_init = ndis_init;
745 ifp->if_baudrate = 10000000;
746 ifq_set_maxlen(&ifp->if_snd, 50);
747 #if 0 /* XXX swildner */
748 ifp->if_snd.ifq_drv_maxlen = 25;
750 ifq_set_ready(&ifp->if_snd);
751 ifp->if_capenable = ifp->if_capabilities;
752 ifp->if_hwassist = sc->ndis_hwassist;
755 if (sc->ndis_80211) {
756 struct ieee80211com *ic = ifp->if_l2com;
757 ndis_80211_rates_ex rates;
758 struct ndis_80211_nettype_list *ntl;
762 callout_init_mp(&sc->ndis_scan_callout);
764 ifp->if_ioctl = ndis_ioctl_80211;
766 ic->ic_opmode = IEEE80211_M_STA;
767 ic->ic_phytype = IEEE80211_T_DS;
768 ic->ic_caps = IEEE80211_C_8023ENCAP |
769 IEEE80211_C_STA | IEEE80211_C_IBSS;
770 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
772 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
776 ntl = kmalloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
777 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
780 kfree(ntl, M_DEVBUF);
784 for (i = 0; i < ntl->ntl_items; i++) {
785 mode = ndis_nettype_mode(ntl->ntl_type[i]);
787 setbit(ic->ic_modecaps, mode);
788 setbit(&bands, mode);
790 device_printf(dev, "Unknown nettype %d\n",
793 kfree(ntl, M_DEVBUF);
795 /* Default to 11b channels if the card did not supply any */
797 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
798 setbit(&bands, IEEE80211_MODE_11B);
801 bzero((char *)&rates, len);
802 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
803 (void *)rates, &len);
805 device_printf(dev, "get rates failed: 0x%x\n", r);
807 * Since the supported rates only up to 8 can be supported,
808 * if this is not 802.11b we're just going to be faking it
812 #define TESTSETRATE(x, y) \
815 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
816 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
819 if (i == ic->ic_sup_rates[x].rs_nrates) { \
820 ic->ic_sup_rates[x].rs_rates[i] = (y); \
821 ic->ic_sup_rates[x].rs_nrates++; \
825 #define SETRATE(x, y) \
826 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
828 ic->ic_sup_rates[x].rs_nrates++
830 ic->ic_curmode = IEEE80211_MODE_AUTO;
831 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
832 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
833 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
834 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
835 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
836 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
837 for (i = 0; i < len; i++) {
838 switch (rates[i] & IEEE80211_RATE_VAL) {
844 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
845 /* Lazy-init 802.11b. */
846 setbit(ic->ic_modecaps,
848 ic->ic_sup_rates[IEEE80211_MODE_11B].
851 SETRATE(IEEE80211_MODE_11B, rates[i]);
852 INCRATE(IEEE80211_MODE_11B);
855 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
856 SETRATE(IEEE80211_MODE_11A, rates[i]);
857 INCRATE(IEEE80211_MODE_11A);
859 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
860 SETRATE(IEEE80211_MODE_11G, rates[i]);
861 INCRATE(IEEE80211_MODE_11G);
868 * If the hardware supports 802.11g, it most
869 * likely supports 802.11b and all of the
870 * 802.11b and 802.11g speeds, so maybe we can
871 * just cheat here. Just how in the heck do
872 * we detect turbo modes, though?
874 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
875 TESTSETRATE(IEEE80211_MODE_11B,
876 IEEE80211_RATE_BASIC|2);
877 TESTSETRATE(IEEE80211_MODE_11B,
878 IEEE80211_RATE_BASIC|4);
879 TESTSETRATE(IEEE80211_MODE_11B,
880 IEEE80211_RATE_BASIC|11);
881 TESTSETRATE(IEEE80211_MODE_11B,
882 IEEE80211_RATE_BASIC|22);
884 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
885 TESTSETRATE(IEEE80211_MODE_11G, 48);
886 TESTSETRATE(IEEE80211_MODE_11G, 72);
887 TESTSETRATE(IEEE80211_MODE_11G, 96);
888 TESTSETRATE(IEEE80211_MODE_11G, 108);
890 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
891 TESTSETRATE(IEEE80211_MODE_11A, 48);
892 TESTSETRATE(IEEE80211_MODE_11A, 72);
893 TESTSETRATE(IEEE80211_MODE_11A, 96);
894 TESTSETRATE(IEEE80211_MODE_11A, 108);
898 ieee80211_init_channels(ic, NULL, &bands);
901 * To test for WPA support, we need to see if we can
902 * set AUTHENTICATION_MODE to WPA and read it back
906 arg = NDIS_80211_AUTHMODE_WPA;
907 r = ndis_set_info(sc,
908 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
910 r = ndis_get_info(sc,
911 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
912 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
913 ic->ic_caps |= IEEE80211_C_WPA;
917 * To test for supported ciphers, we set each
918 * available encryption type in descending order.
919 * If ENC3 works, then we have WEP, TKIP and AES.
920 * If only ENC2 works, then we have WEP and TKIP.
921 * If only ENC1 works, then we have just WEP.
924 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
925 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
927 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
928 | IEEE80211_CRYPTO_TKIP
929 | IEEE80211_CRYPTO_AES_CCM;
932 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
933 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
935 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
936 | IEEE80211_CRYPTO_TKIP;
939 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
940 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
942 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
945 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
947 ic->ic_caps |= IEEE80211_C_PMGT;
949 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
951 ic->ic_caps |= IEEE80211_C_TXPMGT;
953 ieee80211_ifattach(ic, eaddr);
954 ic->ic_raw_xmit = ndis_raw_xmit;
955 ic->ic_scan_start = ndis_scan_start;
956 ic->ic_scan_end = ndis_scan_end;
957 ic->ic_set_channel = ndis_set_channel;
958 ic->ic_scan_curchan = ndis_scan_curchan;
959 ic->ic_scan_mindwell = ndis_scan_mindwell;
960 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
961 //ic->ic_bss->ni_chan = ic->ic_bsschan;
962 ic->ic_vap_create = ndis_vap_create;
963 ic->ic_vap_delete = ndis_vap_delete;
964 ic->ic_update_mcast = ndis_update_mcast;
965 ic->ic_update_promisc = ndis_update_promisc;
968 ieee80211_announce(ic);
971 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
973 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
974 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
975 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
976 ifmedia_add(&sc->ifmedia,
977 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
978 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
979 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
980 ether_ifattach(ifp, eaddr, NULL);
989 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
992 DPRINTF(("attach done.\n"));
993 /* We're done talking to the NIC for now; halt it. */
995 DPRINTF(("halting done.\n"));
1000 static struct ieee80211vap *
1001 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1002 int opmode, int flags,
1003 const uint8_t bssid[IEEE80211_ADDR_LEN],
1004 const uint8_t mac[IEEE80211_ADDR_LEN])
1006 struct ndis_vap *nvp;
1007 struct ieee80211vap *vap;
1009 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1011 nvp = (struct ndis_vap *) kmalloc(sizeof(struct ndis_vap),
1012 M_80211_VAP, M_NOWAIT | M_ZERO);
1016 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
1017 /* override with driver methods */
1018 nvp->newstate = vap->iv_newstate;
1019 vap->iv_newstate = ndis_newstate;
1021 /* complete setup */
1022 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
1023 ic->ic_opmode = opmode;
1024 /* install key handing routines */
1025 vap->iv_key_set = ndis_add_key;
1026 vap->iv_key_delete = ndis_del_key;
1031 ndis_vap_delete(struct ieee80211vap *vap)
1033 struct ndis_vap *nvp = NDIS_VAP(vap);
1034 struct ieee80211com *ic = vap->iv_ic;
1035 struct ifnet *ifp = ic->ic_ifp;
1036 struct ndis_softc *sc = ifp->if_softc;
1039 callout_stop(&sc->ndis_scan_callout); /* XXX swildner callout_drain() */
1040 ieee80211_vap_detach(vap);
1041 kfree(nvp, M_80211_VAP);
1045 * Shutdown hardware and free up resources. This can be called any
1046 * time after the mutex has been initialized. It is called in both
1047 * the error case in attach and the normal detach case so it needs
1048 * to be careful about only freeing resources that have actually been
1052 ndis_detach(device_t dev)
1054 struct ndis_softc *sc;
1058 sc = device_get_softc(dev);
1061 ifp->if_flags &= ~IFF_UP;
1063 if (device_is_attached(dev)) {
1067 ieee80211_ifdetach(ifp->if_l2com);
1069 ether_ifdetach(ifp);
1073 if (sc->ndis_tickitem != NULL)
1074 IoFreeWorkItem(sc->ndis_tickitem);
1075 if (sc->ndis_startitem != NULL)
1076 IoFreeWorkItem(sc->ndis_startitem);
1077 if (sc->ndis_resetitem != NULL)
1078 IoFreeWorkItem(sc->ndis_resetitem);
1079 if (sc->ndis_inputitem != NULL)
1080 IoFreeWorkItem(sc->ndis_inputitem);
1082 if (sc->ndisusb_xferdoneitem != NULL)
1083 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1084 if (sc->ndisusb_taskitem != NULL)
1085 IoFreeWorkItem(sc->ndisusb_taskitem);
1087 if (sc->ndisusb_xferitem != NULL)
1088 IoFreeWorkItem(sc->ndisusb_xferitem);
1091 bus_generic_detach(dev);
1092 ndis_unload_driver(sc);
1095 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1096 if (sc->ndis_res_io)
1097 bus_release_resource(dev, SYS_RES_IOPORT,
1098 sc->ndis_io_rid, sc->ndis_res_io);
1099 if (sc->ndis_res_mem)
1100 bus_release_resource(dev, SYS_RES_MEMORY,
1101 sc->ndis_mem_rid, sc->ndis_res_mem);
1102 if (sc->ndis_res_altmem)
1103 bus_release_resource(dev, SYS_RES_MEMORY,
1104 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1109 if (sc->ndis_iftype == PCMCIABus)
1113 ndis_destroy_dma(sc);
1115 if (sc->ndis_txarray)
1116 kfree(sc->ndis_txarray, M_DEVBUF);
1118 if (!sc->ndis_80211)
1119 ifmedia_removeall(&sc->ifmedia);
1121 if (sc->ndis_txpool != NULL)
1122 NdisFreePacketPool(sc->ndis_txpool);
1124 /* Destroy the PDO for this device. */
1126 if (sc->ndis_iftype == PCIBus)
1127 drv = windrv_lookup(0, "PCI Bus");
1128 else if (sc->ndis_iftype == PCMCIABus)
1129 drv = windrv_lookup(0, "PCCARD Bus");
1131 drv = windrv_lookup(0, "USB Bus");
1133 panic("couldn't find driver object");
1134 windrv_destroy_pdo(drv, dev);
1136 if (sc->ndis_iftype == PCIBus)
1137 bus_dma_tag_destroy(sc->ndis_parent_tag);
1143 ndis_suspend(device_t dev)
1146 struct ndis_softc *sc;
1148 wlan_serialize_enter();
1149 sc = device_get_softc(dev);
1151 if (NDIS_INITIALIZED(sc))
1154 wlan_serialize_exit();
1160 ndis_resume(device_t dev)
1162 struct ndis_softc *sc;
1164 wlan_serialize_enter();
1165 sc = device_get_softc(dev);
1167 if (NDIS_INITIALIZED(sc))
1170 wlan_serialize_exit();
1175 * The following bunch of routines are here to support drivers that
1176 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1177 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1178 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1182 ndis_rxeof_eth(ndis_handle adapter, ndis_handle ctx, char *addr, void *hdr,
1183 uint32_t hdrlen, void *lookahead, uint32_t lookaheadlen, uint32_t pktlen)
1185 ndis_miniport_block *block;
1195 m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
1199 /* Save the data provided to us so far. */
1201 m->m_len = lookaheadlen + hdrlen;
1202 m->m_pkthdr.len = pktlen + hdrlen;
1204 m_copyback(m, 0, hdrlen, hdr);
1205 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1207 /* Now create a fake NDIS_PACKET to hold the data */
1209 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1211 if (status != NDIS_STATUS_SUCCESS) {
1218 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1226 p->np_private.npp_head = p->np_private.npp_tail = b;
1227 p->np_private.npp_totlen = m->m_pkthdr.len;
1229 /* Save the packet RX context somewhere. */
1230 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1231 priv->nep_ctx = ctx;
1233 if (!NDIS_SERIALIZED(block))
1234 KeAcquireSpinLock(&block->nmb_lock, &irql);
1236 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1238 if (!NDIS_SERIALIZED(block))
1239 KeReleaseSpinLock(&block->nmb_lock, irql);
1243 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1244 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1248 ndis_rxeof_done(ndis_handle adapter)
1250 struct ndis_softc *sc;
1251 ndis_miniport_block *block;
1255 /* Schedule transfer/RX of queued packets. */
1257 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1259 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1263 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1266 ndis_rxeof_xfr(kdpc *dpc, ndis_handle adapter, void *sysarg1, void *sysarg2)
1268 ndis_miniport_block *block;
1269 struct ndis_softc *sc;
1278 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1281 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1283 l = block->nmb_packetlist.nle_flink;
1284 while(!IsListEmpty(&block->nmb_packetlist)) {
1285 l = RemoveHeadList((&block->nmb_packetlist));
1286 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1287 InitializeListHead((&p->np_list));
1289 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1294 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1296 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1297 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1298 m->m_len, m->m_pkthdr.len - m->m_len);
1300 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1303 * If status is NDIS_STATUS_PENDING, do nothing and
1304 * wait for a callback to the ndis_rxeof_xfr_done()
1308 m->m_len = m->m_pkthdr.len;
1309 m->m_pkthdr.rcvif = ifp;
1311 if (status == NDIS_STATUS_SUCCESS) {
1312 IoFreeMdl(p->np_private.npp_head);
1314 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1315 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1316 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1317 IoQueueWorkItem(sc->ndis_inputitem,
1318 (io_workitem_func)ndis_inputtask_wrap,
1319 WORKQUEUE_CRITICAL, ifp);
1322 if (status == NDIS_STATUS_FAILURE)
1325 /* Advance to next packet */
1326 l = block->nmb_packetlist.nle_flink;
1329 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1333 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1336 ndis_rxeof_xfr_done(ndis_handle adapter, ndis_packet *packet, uint32_t status,
1339 ndis_miniport_block *block;
1340 struct ndis_softc *sc;
1345 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1349 IoFreeMdl(packet->np_private.npp_head);
1350 NdisFreePacket(packet);
1352 if (status != NDIS_STATUS_SUCCESS) {
1357 m->m_len = m->m_pkthdr.len;
1358 m->m_pkthdr.rcvif = ifp;
1359 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1360 IF_ENQUEUE(&sc->ndis_rxqueue, m);
1361 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1362 IoQueueWorkItem(sc->ndis_inputitem,
1363 (io_workitem_func)ndis_inputtask_wrap,
1364 WORKQUEUE_CRITICAL, ifp);
1367 * A frame has been uploaded: pass the resulting mbuf chain up to
1368 * the higher level protocols.
1370 * When handling received NDIS packets, the 'status' field in the
1371 * out-of-band portion of the ndis_packet has special meaning. In the
1372 * most common case, the underlying NDIS driver will set this field
1373 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1374 * take posession of it. We then change the status field to
1375 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1376 * and that we will return it at some point in the future via the
1377 * return packet handler.
1379 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1380 * this means the driver is running out of packet/buffer resources and
1381 * wants to maintain ownership of the packet. In this case, we have to
1382 * copy the packet data into local storage and let the driver keep the
1386 ndis_rxeof(ndis_handle adapter, ndis_packet **packets, uint32_t pktcnt)
1388 struct ndis_softc *sc;
1389 ndis_miniport_block *block;
1392 ndis_tcpip_csum *csum;
1394 struct mbuf *m0, *m;
1397 block = (ndis_miniport_block *)adapter;
1398 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1402 * There's a slim chance the driver may indicate some packets
1403 * before we're completely ready to handle them. If we detect this,
1404 * we need to return them to the miniport and ignore them.
1406 if (!(ifp->if_flags & IFF_RUNNING)) {
1407 for (i = 0; i < pktcnt; i++) {
1409 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1411 ndis_return_packet(p);
1417 for (i = 0; i < pktcnt; i++) {
1419 /* Stash the softc here so ptom can use it. */
1421 if (ndis_ptom(&m0, p)) {
1422 device_printf(sc->ndis_dev, "ptom failed\n");
1423 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1424 ndis_return_packet(p);
1427 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1428 m = m_dup(m0, MB_DONTWAIT);
1430 * NOTE: we want to destroy the mbuf here, but
1431 * we don't actually want to return it to the
1432 * driver via the return packet handler. By
1433 * bumping np_refcnt, we can prevent the
1434 * ndis_return_packet() routine from actually
1444 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1446 m = m_dup(m0, MB_DONTWAIT);
1447 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457 m0->m_pkthdr.rcvif = ifp;
1459 /* Deal with checksum offload. */
1461 if (ifp->if_capenable & IFCAP_RXCSUM &&
1462 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1464 p->np_ext.npe_info[ndis_tcpipcsum_info];
1465 csum = (ndis_tcpip_csum *)&s;
1466 if (csum->u.ntc_rxflags &
1467 NDIS_RXCSUM_IP_PASSED)
1468 m0->m_pkthdr.csum_flags |=
1469 CSUM_IP_CHECKED|CSUM_IP_VALID;
1470 if (csum->u.ntc_rxflags &
1471 (NDIS_RXCSUM_TCP_PASSED |
1472 NDIS_RXCSUM_UDP_PASSED)) {
1473 m0->m_pkthdr.csum_flags |=
1474 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1475 m0->m_pkthdr.csum_data = 0xFFFF;
1479 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1480 IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1481 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1482 IoQueueWorkItem(sc->ndis_inputitem,
1483 (io_workitem_func)ndis_inputtask_wrap,
1484 WORKQUEUE_CRITICAL, ifp);
1490 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1491 * packets into the stack in order to avoid calling (*ifp->if_input)()
1492 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1493 * 'dispatch level' per-cpu sleep lock).
1496 ndis_inputtask(device_object *dobj, void *arg)
1499 struct ndis_softc *sc;
1501 struct ieee80211com *ic;
1502 struct ieee80211vap *vap;
1508 vap = TAILQ_FIRST(&ic->ic_vaps);
1510 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1512 IF_DEQUEUE(&sc->ndis_rxqueue, m);
1515 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1516 if ((sc->ndis_80211 != 0) && (vap != NULL))
1517 vap->iv_deliver_data(vap, vap->iv_bss, m);
1519 (*ifp->if_input)(ifp, m);
1520 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1522 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1526 * A frame was downloaded to the chip. It's safe for us to clean up
1530 ndis_txeof(ndis_handle adapter, ndis_packet *packet, ndis_status status)
1532 struct ndis_softc *sc;
1533 ndis_miniport_block *block;
1538 block = (ndis_miniport_block *)adapter;
1539 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1543 idx = packet->np_txidx;
1545 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1547 ndis_free_packet(packet);
1551 sc->ndis_txarray[idx] = NULL;
1552 sc->ndis_txpending++;
1554 if (status == NDIS_STATUS_SUCCESS)
1559 sc->ndis_tx_timer = 0;
1560 ifq_clr_oactive(&ifp->if_snd);
1564 IoQueueWorkItem(sc->ndis_startitem,
1565 (io_workitem_func)ndis_starttask_wrap,
1566 WORKQUEUE_CRITICAL, ifp);
1570 ndis_linksts(ndis_handle adapter, ndis_status status, void *sbuf,
1573 ndis_miniport_block *block;
1574 struct ndis_softc *sc;
1577 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1578 sc->ndis_sts = status;
1580 /* Event list is all full up, drop this one. */
1583 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1588 /* Cache the event. */
1591 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = kmalloc(slen,
1593 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1598 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1600 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1601 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1602 NDIS_EVTINC(sc->ndis_evtpidx);
1607 ndis_linksts_done(ndis_handle adapter)
1609 ndis_miniport_block *block;
1610 struct ndis_softc *sc;
1614 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1617 if (!NDIS_INITIALIZED(sc))
1620 switch (sc->ndis_sts) {
1621 case NDIS_STATUS_MEDIA_CONNECT:
1622 IoQueueWorkItem(sc->ndis_tickitem,
1623 (io_workitem_func)ndis_ticktask_wrap,
1624 WORKQUEUE_CRITICAL, sc);
1625 IoQueueWorkItem(sc->ndis_startitem,
1626 (io_workitem_func)ndis_starttask_wrap,
1627 WORKQUEUE_CRITICAL, ifp);
1629 case NDIS_STATUS_MEDIA_DISCONNECT:
1631 IoQueueWorkItem(sc->ndis_tickitem,
1632 (io_workitem_func)ndis_ticktask_wrap,
1633 WORKQUEUE_CRITICAL, sc);
1641 ndis_tick(void *xsc)
1643 struct ndis_softc *sc;
1647 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1648 IoQueueWorkItem(sc->ndis_tickitem,
1649 (io_workitem_func)ndis_ticktask_wrap,
1650 WORKQUEUE_CRITICAL, sc);
1651 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1654 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1655 sc->ifp->if_oerrors++;
1656 device_printf(sc->ndis_dev, "watchdog timeout\n");
1658 IoQueueWorkItem(sc->ndis_resetitem,
1659 (io_workitem_func)ndis_resettask_wrap,
1660 WORKQUEUE_CRITICAL, sc);
1661 IoQueueWorkItem(sc->ndis_startitem,
1662 (io_workitem_func)ndis_starttask_wrap,
1663 WORKQUEUE_CRITICAL, sc->ifp);
1666 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1670 ndis_ticktask(device_object *d, void *xsc)
1672 struct ndis_softc *sc;
1673 struct ieee80211com *ic;
1674 struct ieee80211vap *vap;
1675 ndis_checkforhang_handler hangfunc;
1679 ic = sc->ifp->if_l2com;
1680 vap = TAILQ_FIRST(&ic->ic_vaps);
1683 if (!NDIS_INITIALIZED(sc)) {
1689 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1691 if (hangfunc != NULL) {
1692 rval = MSCALL1(hangfunc,
1693 sc->ndis_block->nmb_miniportadapterctx);
1701 if (sc->ndis_link == 0 &&
1702 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1705 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1706 ndis_getstate_80211(sc);
1707 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1710 sc->ifp->if_link_state = LINK_STATE_UP;
1711 if_link_state_change(sc->ifp);
1714 if (sc->ndis_link == 1 &&
1715 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1718 if ((sc->ndis_80211 != 0) && (vap != NULL))
1719 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1721 sc->ifp->if_link_state = LINK_STATE_DOWN;
1722 if_link_state_change(sc->ifp);
1729 ndis_map_sclist(void *arg, bus_dma_segment_t *segs, int nseg,
1730 bus_size_t mapsize, int error)
1732 struct ndis_sc_list *sclist;
1735 if (error || arg == NULL)
1740 sclist->nsl_frags = nseg;
1742 for (i = 0; i < nseg; i++) {
1743 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1744 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1749 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1750 const struct ieee80211_bpf_params *params)
1752 /* no support; just discard */
1754 ieee80211_free_node(ni);
1759 ndis_update_mcast(struct ifnet *ifp)
1761 struct ndis_softc *sc = ifp->if_softc;
1767 ndis_update_promisc(struct ifnet *ifp)
1773 ndis_starttask(device_object *d, void *arg)
1779 if (!ifq_is_empty(&ifp->if_snd))
1784 * Main transmit routine. To make NDIS drivers happy, we need to
1785 * transform mbuf chains into NDIS packets and feed them to the
1786 * send packet routines. Most drivers allow you to send several
1787 * packets at once (up to the maxpkts limit). Unfortunately, rather
1788 * that accepting them in the form of a linked list, they expect
1789 * a contiguous array of pointers to packets.
1791 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1792 * we need to perform busdma work here. Those that use map registers
1793 * will do the mapping themselves on a buffer by buffer basis.
1796 ndis_start(struct ifnet *ifp)
1798 struct ndis_softc *sc;
1799 struct mbuf *m = NULL;
1800 ndis_packet **p0 = NULL, *p = NULL;
1801 ndis_tcpip_csum *csum;
1802 int pcnt = 0, status;
1807 if (!sc->ndis_link) {
1808 ifq_purge(&ifp->if_snd);
1813 if (ifq_is_oactive(&ifp->if_snd)) {
1818 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1820 while(sc->ndis_txpending) {
1821 m = ifq_dequeue(&ifp->if_snd, NULL);
1825 NdisAllocatePacket(&status,
1826 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1828 if (status != NDIS_STATUS_SUCCESS)
1831 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1832 ifq_prepend(&ifp->if_snd, m);
1838 * Save pointer to original mbuf
1839 * so we can free it later.
1842 p = sc->ndis_txarray[sc->ndis_txidx];
1843 p->np_txidx = sc->ndis_txidx;
1845 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1848 * Do scatter/gather processing, if driver requested it.
1851 bus_dmamap_load_mbuf(sc->ndis_ttag,
1852 sc->ndis_tmaps[sc->ndis_txidx], m,
1853 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1854 bus_dmamap_sync(sc->ndis_ttag,
1855 sc->ndis_tmaps[sc->ndis_txidx],
1856 BUS_DMASYNC_PREREAD);
1857 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1860 /* Handle checksum offload. */
1862 if (ifp->if_capenable & IFCAP_TXCSUM &&
1863 m->m_pkthdr.csum_flags) {
1864 csum = (ndis_tcpip_csum *)
1865 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1866 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1867 if (m->m_pkthdr.csum_flags & CSUM_IP)
1868 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1869 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1870 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1871 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1872 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1873 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1877 sc->ndis_txpending--;
1882 * If there's a BPF listener, bounce a copy of this frame
1885 if (!sc->ndis_80211) /* XXX handle 80211 */
1889 * The array that p0 points to must appear contiguous,
1890 * so we must not wrap past the end of sc->ndis_txarray[].
1891 * If it looks like we're about to wrap, break out here
1892 * so the this batch of packets can be transmitted, then
1893 * wait for txeof to ask us to send the rest.
1895 if (sc->ndis_txidx == 0)
1904 if (sc->ndis_txpending == 0)
1905 ifq_set_oactive(&ifp->if_snd);
1908 * Set a timeout in case the chip goes out to lunch.
1910 sc->ndis_tx_timer = 5;
1915 * According to NDIS documentation, if a driver exports
1916 * a MiniportSendPackets() routine, we prefer that over
1917 * a MiniportSend() routine (which sends just a single
1920 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1921 ndis_send_packets(sc, p0, pcnt);
1923 ndis_send_packet(sc, p);
1929 ndis_init(void *xsc)
1931 struct ndis_softc *sc = xsc;
1932 struct ifnet *ifp = sc->ifp;
1933 struct ieee80211com *ic = ifp->if_l2com;
1937 * Avoid reintializing the link unnecessarily.
1938 * This should be dealt with in a better way by
1939 * fixing the upper layer modules so they don't
1940 * call ifp->if_init() quite as often.
1946 * Cancel pending I/O and free all RX/TX buffers.
1950 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1951 error = ndis_init_nic(sc);
1953 device_printf(sc->ndis_dev,
1954 "failed to initialize the device: %d\n", error);
1959 /* Init our MAC address */
1961 /* Program the packet filter */
1963 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1965 if (ifp->if_flags & IFF_BROADCAST)
1966 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1968 if (ifp->if_flags & IFF_PROMISC)
1969 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1971 len = sizeof(sc->ndis_filter);
1973 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1974 &sc->ndis_filter, &len);
1977 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1984 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1987 * Program the multicast filter, if necessary.
1991 /* Setup task offload. */
1992 ndis_set_offload(sc);
1997 sc->ndis_txpending = sc->ndis_maxpkts;
2000 sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
2001 if_link_state_change(sc->ifp);
2003 ifp->if_flags |= IFF_RUNNING;
2004 ifq_clr_oactive(&ifp->if_snd);
2005 sc->ndis_tx_timer = 0;
2008 * Some drivers don't set this value. The NDIS spec says
2009 * the default checkforhang timeout is "approximately 2
2010 * seconds." We use 3 seconds, because it seems for some
2011 * drivers, exactly 2 seconds is too fast.
2013 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2014 sc->ndis_block->nmb_checkforhangsecs = 3;
2016 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2017 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2020 /* XXX force handling */
2022 ieee80211_start_all(ic); /* start all vap's */
2026 * Set media options.
2029 ndis_ifmedia_upd(struct ifnet *ifp)
2031 struct ndis_softc *sc;
2035 if (NDIS_INITIALIZED(sc))
2042 * Report current media status.
2045 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2047 struct ndis_softc *sc;
2048 uint32_t media_info;
2049 ndis_media_state linkstate;
2052 ifmr->ifm_status = IFM_AVALID;
2053 ifmr->ifm_active = IFM_ETHER;
2056 if (!NDIS_INITIALIZED(sc))
2059 len = sizeof(linkstate);
2060 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2061 (void *)&linkstate, &len);
2063 len = sizeof(media_info);
2064 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2065 (void *)&media_info, &len);
2067 if (linkstate == nmc_connected)
2068 ifmr->ifm_status |= IFM_ACTIVE;
2070 switch (media_info) {
2072 ifmr->ifm_active |= IFM_10_T;
2075 ifmr->ifm_active |= IFM_100_TX;
2078 ifmr->ifm_active |= IFM_1000_T;
2081 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2087 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2089 struct ieee80211com *ic;
2093 ic = sc->ifp->if_l2com;
2097 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2098 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2100 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2103 if (cipher == WPA_CSE_TKIP) {
2104 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2106 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2109 if (cipher == WPA_CSE_CCMP) {
2110 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2112 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2115 DPRINTF(("Setting cipher to %d\n", arg));
2117 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2122 /* Check that the cipher was set correctly. */
2125 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2127 if (rval != 0 || arg != save)
2134 * WPA is hairy to set up. Do the work in a separate routine
2135 * so we don't clutter the setstate function too much.
2136 * Important yet undocumented fact: first we have to set the
2137 * authentication mode, _then_ we enable the ciphers. If one
2138 * of the WPA authentication modes isn't enabled, the driver
2139 * might not permit the TKIP or AES ciphers to be selected.
2142 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2144 struct ieee80211_ie_wpa *w;
2151 * Apparently, the only way for us to know what ciphers
2152 * and key management/authentication mode to use is for
2153 * us to inspect the optional information element (IE)
2154 * stored in the 802.11 state machine. This IE should be
2155 * supplied by the WPA supplicant.
2158 w = (struct ieee80211_ie_wpa *)ie;
2160 /* Check for the right kind of IE. */
2161 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2162 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2166 /* Skip over the ucast cipher OIDs. */
2167 pos = (char *)&w->wpa_uciphers[0];
2168 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2170 /* Skip over the authmode count. */
2171 pos += sizeof(u_int16_t);
2174 * Check for the authentication modes. I'm
2175 * pretty sure there's only supposed to be one.
2178 n = (struct ndis_ie *)pos;
2179 if (n->ni_val == WPA_ASE_NONE)
2180 arg = NDIS_80211_AUTHMODE_WPANONE;
2182 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2183 arg = NDIS_80211_AUTHMODE_WPA;
2185 if (n->ni_val == WPA_ASE_8021X_PSK)
2186 arg = NDIS_80211_AUTHMODE_WPAPSK;
2188 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2190 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2193 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2195 /* Now configure the desired ciphers. */
2197 /* First, set up the multicast group cipher. */
2198 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2200 if (ndis_set_cipher(sc, n->ni_val))
2203 /* Now start looking around for the unicast ciphers. */
2204 pos = (char *)&w->wpa_uciphers[0];
2205 n = (struct ndis_ie *)pos;
2207 for (i = 0; i < w->wpa_uciphercnt; i++) {
2208 if (ndis_set_cipher(sc, n->ni_val))
2217 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2219 struct ieee80211vap *vap = ifp->if_softc;
2220 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2224 if (!NDIS_INITIALIZED(sc))
2227 len = sizeof(txrate);
2228 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2229 vap->iv_bss->ni_txrate = txrate / 5000;
2230 ieee80211_media_status(ifp, imr);
2234 ndis_setstate_80211(struct ndis_softc *sc)
2236 struct ieee80211com *ic;
2237 struct ieee80211vap *vap;
2238 ndis_80211_macaddr bssid;
2239 ndis_80211_config config;
2246 vap = TAILQ_FIRST(&ic->ic_vaps);
2248 if (!NDIS_INITIALIZED(sc)) {
2249 DPRINTF(("%s: NDIS not initialized\n", __func__));
2253 /* Disassociate and turn off radio. */
2256 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2258 /* Set network infrastructure mode. */
2261 if (ic->ic_opmode == IEEE80211_M_IBSS)
2262 arg = NDIS_80211_NET_INFRA_IBSS;
2264 arg = NDIS_80211_NET_INFRA_BSS;
2266 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2269 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2271 /* Set power management */
2273 if (vap->iv_flags & IEEE80211_F_PMGTON)
2274 arg = NDIS_80211_POWERMODE_FAST_PSP;
2276 arg = NDIS_80211_POWERMODE_CAM;
2277 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2280 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2281 ic->ic_txpowlimit < NELEM(dBm2mW)) {
2282 arg = dBm2mW[ic->ic_txpowlimit];
2284 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2288 * Default encryption mode to off, authentication
2289 * to open and privacy to 'accept everything.'
2292 arg = NDIS_80211_WEPSTAT_DISABLED;
2293 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2296 arg = NDIS_80211_AUTHMODE_OPEN;
2297 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2300 * Note that OID_802_11_PRIVACY_FILTER is optional:
2301 * not all drivers implement it.
2304 arg = NDIS_80211_PRIVFILT_8021XWEP;
2305 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2307 len = sizeof(config);
2308 bzero((char *)&config, len);
2309 config.nc_length = len;
2310 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2311 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2314 * Some drivers expect us to initialize these values, so
2315 * provide some defaults.
2318 if (config.nc_beaconperiod == 0)
2319 config.nc_beaconperiod = 100;
2320 if (config.nc_atimwin == 0)
2321 config.nc_atimwin = 100;
2322 if (config.nc_fhconfig.ncf_dwelltime == 0)
2323 config.nc_fhconfig.ncf_dwelltime = 200;
2324 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2327 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2328 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2329 config.nc_dsconfig =
2330 ic->ic_bsschan->ic_freq * 1000;
2331 len = sizeof(config);
2332 config.nc_length = len;
2333 config.nc_fhconfig.ncf_length =
2334 sizeof(ndis_80211_config_fh);
2335 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2336 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2339 device_printf(sc->ndis_dev, "couldn't change "
2340 "DS config to %ukHz: %d\n",
2341 config.nc_dsconfig, rval);
2344 device_printf(sc->ndis_dev, "couldn't retrieve "
2345 "channel info: %d\n", rval);
2347 /* Set the BSSID to our value so the driver doesn't associate */
2348 len = IEEE80211_ADDR_LEN;
2349 bcopy(IF_LLADDR(ifp), bssid, len);
2350 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2351 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2353 device_printf(sc->ndis_dev,
2354 "setting BSSID failed: %d\n", rval);
2358 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2360 struct ieee80211_node *ni;
2361 ndis_80211_ssid ssid;
2362 ndis_80211_macaddr bssid;
2364 int i, rval = 0, len, error;
2371 if (!NDIS_INITIALIZED(sc)) {
2372 DPRINTF(("%s: NDIS not initialized\n", __func__));
2377 ndis_setstate_80211(sc);
2379 /* Set network infrastructure mode. */
2382 if (vap->iv_opmode == IEEE80211_M_IBSS)
2383 arg = NDIS_80211_NET_INFRA_IBSS;
2385 arg = NDIS_80211_NET_INFRA_BSS;
2387 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2390 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392 /* Set RTS threshold */
2395 arg = vap->iv_rtsthreshold;
2396 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2398 /* Set fragmentation threshold */
2401 arg = vap->iv_fragthreshold;
2402 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2406 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2407 !(vap->iv_flags & IEEE80211_F_WPA)) {
2410 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2412 arg = NDIS_80211_AUTHMODE_SHARED;
2413 DPRINTF(("Setting shared auth\n"));
2414 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2417 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2418 if (vap->iv_nw_keys[i].wk_keylen) {
2419 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2420 IEEE80211_CIPHER_WEP)
2422 bzero((char *)&wep, sizeof(wep));
2423 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2426 * 5, 13 and 16 are the only valid
2427 * key lengths. Anything in between
2428 * will be zero padded out to the
2429 * next highest boundary.
2431 if (vap->iv_nw_keys[i].wk_keylen < 5)
2433 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2434 vap->iv_nw_keys[i].wk_keylen < 13)
2436 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2437 vap->iv_nw_keys[i].wk_keylen < 16)
2441 wep.nw_length = (sizeof(uint32_t) * 3)
2443 if (i == vap->iv_def_txkey)
2444 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2445 bcopy(vap->iv_nw_keys[i].wk_key,
2446 wep.nw_keydata, wep.nw_length);
2448 DPRINTF(("Setting WEP key %d\n", i));
2449 rval = ndis_set_info(sc,
2450 OID_802_11_ADD_WEP, &wep, &len);
2452 device_printf(sc->ndis_dev,
2453 "set wepkey failed: %d\n", rval);
2458 DPRINTF(("Setting WEP on\n"));
2459 arg = NDIS_80211_WEPSTAT_ENABLED;
2461 rval = ndis_set_info(sc,
2462 OID_802_11_WEP_STATUS, &arg, &len);
2464 device_printf(sc->ndis_dev,
2465 "enable WEP failed: %d\n", rval);
2466 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2467 arg = NDIS_80211_PRIVFILT_8021XWEP;
2469 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2473 OID_802_11_PRIVACY_FILTER, &arg, &len);
2478 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2479 vap->iv_appie_assocreq != NULL) {
2480 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2481 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2483 device_printf(sc->ndis_dev, "WPA setup failed\n");
2487 /* Set network type. */
2491 switch (vap->iv_curmode) {
2492 case IEEE80211_MODE_11A:
2493 arg = NDIS_80211_NETTYPE_11OFDM5;
2495 case IEEE80211_MODE_11B:
2496 arg = NDIS_80211_NETTYPE_11DS;
2498 case IEEE80211_MODE_11G:
2499 arg = NDIS_80211_NETTYPE_11OFDM24;
2502 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2507 DPRINTF(("Setting network type to %d\n", arg));
2509 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2512 device_printf(sc->ndis_dev,
2513 "set nettype failed: %d\n", rval);
2518 * If the user selected a specific BSSID, try
2519 * to use that one. This is useful in the case where
2520 * there are several APs in range with the same network
2521 * name. To delete the BSSID, we use the broadcast
2522 * address as the BSSID.
2523 * Note that some drivers seem to allow setting a BSSID
2524 * in ad-hoc mode, which has the effect of forcing the
2525 * NIC to create an ad-hoc cell with a specific BSSID,
2526 * instead of a randomly chosen one. However, the net80211
2527 * code makes the assumtion that the BSSID setting is invalid
2528 * when you're in ad-hoc mode, so we don't allow that here.
2531 len = IEEE80211_ADDR_LEN;
2532 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2533 vap->iv_opmode != IEEE80211_M_IBSS)
2534 bcopy(ni->ni_bssid, bssid, len);
2536 bcopy(ifp->if_broadcastaddr, bssid, len);
2538 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2539 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2541 device_printf(sc->ndis_dev,
2542 "setting BSSID failed: %d\n", rval);
2544 /* Set SSID -- always do this last. */
2547 if (ndis_debug > 0) {
2548 kprintf("Setting ESSID to ");
2549 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2555 bzero((char *)&ssid, len);
2556 ssid.ns_ssidlen = ni->ni_esslen;
2557 if (ssid.ns_ssidlen == 0) {
2558 ssid.ns_ssidlen = 1;
2560 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2562 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2565 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2571 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2575 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2576 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2580 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2581 if (error == ENOSPC) {
2582 kfree(*bl, M_DEVBUF);
2583 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2587 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2590 DPRINTF(("%s: failed to read\n", __func__));
2591 kfree(*bl, M_DEVBUF);
2599 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2601 struct ifnet *ifp = sc->ifp;
2602 struct ieee80211com *ic = ifp->if_l2com;
2603 struct ieee80211vap *vap;
2604 struct ieee80211_node *ni;
2605 ndis_80211_bssid_list_ex *bl;
2606 ndis_wlan_bssid_ex *bs;
2607 ndis_80211_macaddr bssid;
2613 len = sizeof(bssid);
2614 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2616 device_printf(sc->ndis_dev, "failed to get bssid\n");
2620 vap = TAILQ_FIRST(&ic->ic_vaps);
2623 error = ndis_get_bssid_list(sc, &bl);
2627 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2628 for (i = 0; i < bl->nblx_items; i++) {
2629 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2630 *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2631 if (*assoc == NULL) {
2635 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2637 if (ic->ic_opmode == IEEE80211_M_STA)
2638 ni->ni_associd = 1 | 0xc000; /* fake associd */
2641 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2649 ndis_getstate_80211(struct ndis_softc *sc)
2651 struct ieee80211com *ic;
2652 struct ieee80211vap *vap;
2653 struct ieee80211_node *ni;
2654 ndis_wlan_bssid_ex *bs;
2655 int rval, len, i = 0;
2662 vap = TAILQ_FIRST(&ic->ic_vaps);
2665 if (!NDIS_INITIALIZED(sc))
2668 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2671 /* We're associated, retrieve info on the current bssid. */
2672 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2673 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2674 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2676 /* Get SSID from current association info. */
2677 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2678 bs->nwbx_ssid.ns_ssidlen);
2679 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2681 if (ic->ic_caps & IEEE80211_C_PMGT) {
2683 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2686 device_printf(sc->ndis_dev,
2687 "get power mode failed: %d\n", rval);
2688 if (arg == NDIS_80211_POWERMODE_CAM)
2689 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2691 vap->iv_flags |= IEEE80211_F_PMGTON;
2695 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2697 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2698 for (i = 0; i < NELEM(dBm2mW); i++)
2699 if (dBm2mW[i] >= arg)
2701 ic->ic_txpowlimit = i;
2705 * Use the current association information to reflect
2706 * what channel we're on.
2708 ic->ic_curchan = ieee80211_find_channel(ic,
2709 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2710 if (ic->ic_curchan == NULL)
2711 ic->ic_curchan = &ic->ic_channels[0];
2712 ni->ni_chan = ic->ic_curchan;
2713 ic->ic_bsschan = ic->ic_curchan;
2718 * Determine current authentication mode.
2721 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2723 device_printf(sc->ndis_dev,
2724 "get authmode status failed: %d\n", rval);
2726 vap->iv_flags &= ~IEEE80211_F_WPA;
2728 case NDIS_80211_AUTHMODE_OPEN:
2729 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2731 case NDIS_80211_AUTHMODE_SHARED:
2732 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2734 case NDIS_80211_AUTHMODE_AUTO:
2735 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2737 case NDIS_80211_AUTHMODE_WPA:
2738 case NDIS_80211_AUTHMODE_WPAPSK:
2739 case NDIS_80211_AUTHMODE_WPANONE:
2740 ni->ni_authmode = IEEE80211_AUTH_WPA;
2741 vap->iv_flags |= IEEE80211_F_WPA1;
2743 case NDIS_80211_AUTHMODE_WPA2:
2744 case NDIS_80211_AUTHMODE_WPA2PSK:
2745 ni->ni_authmode = IEEE80211_AUTH_WPA;
2746 vap->iv_flags |= IEEE80211_F_WPA2;
2749 ni->ni_authmode = IEEE80211_AUTH_NONE;
2755 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2758 device_printf(sc->ndis_dev,
2759 "get wep status failed: %d\n", rval);
2761 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2762 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2764 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2768 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2770 struct ndis_softc *sc = ifp->if_softc;
2771 struct ifreq *ifr = (struct ifreq *) data;
2778 if (ifp->if_flags & IFF_UP) {
2779 if (ifp->if_flags & IFF_RUNNING &&
2780 ifp->if_flags & IFF_PROMISC &&
2781 !(sc->ndis_if_flags & IFF_PROMISC)) {
2783 NDIS_PACKET_TYPE_PROMISCUOUS;
2784 i = sizeof(sc->ndis_filter);
2785 error = ndis_set_info(sc,
2786 OID_GEN_CURRENT_PACKET_FILTER,
2787 &sc->ndis_filter, &i);
2788 } else if (ifp->if_flags & IFF_RUNNING &&
2789 !(ifp->if_flags & IFF_PROMISC) &&
2790 sc->ndis_if_flags & IFF_PROMISC) {
2792 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2793 i = sizeof(sc->ndis_filter);
2794 error = ndis_set_info(sc,
2795 OID_GEN_CURRENT_PACKET_FILTER,
2796 &sc->ndis_filter, &i);
2800 if (ifp->if_flags & IFF_RUNNING)
2803 sc->ndis_if_flags = ifp->if_flags;
2813 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2816 ifp->if_capenable = ifr->ifr_reqcap;
2817 if (ifp->if_capenable & IFCAP_TXCSUM)
2818 ifp->if_hwassist = sc->ndis_hwassist;
2820 ifp->if_hwassist = 0;
2821 ndis_set_offload(sc);
2824 error = ether_ioctl(ifp, command, data);
2828 /*NDIS_UNLOCK(sc);*/
2834 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2837 struct ndis_softc *sc = ifp->if_softc;
2838 struct ieee80211com *ic = ifp->if_l2com;
2839 struct ifreq *ifr = (struct ifreq *) data;
2840 struct ndis_oid_data oid;
2841 struct ndis_evt evt;
2848 if (ifp->if_flags & IFF_UP) {
2849 if (!(ifp->if_flags & IFF_RUNNING))
2852 if (ifp->if_flags & IFF_RUNNING)
2855 sc->ndis_if_flags = ifp->if_flags;
2857 /*NDIS_UNLOCK(sc);*/
2860 if ((error = priv_check(curthread, PRIV_DRIVER)))
2862 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2865 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2866 if (oidbuf == NULL) {
2870 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2872 kfree(oidbuf, M_TEMP);
2875 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2877 kfree(oidbuf, M_TEMP);
2880 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2882 kfree(oidbuf, M_TEMP);
2885 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2886 kfree(oidbuf, M_TEMP);
2889 if ((error = priv_check(curthread, PRIV_DRIVER)))
2891 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2894 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2895 if (oidbuf == NULL) {
2899 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2901 kfree(oidbuf, M_TEMP);
2904 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2906 kfree(oidbuf, M_TEMP);
2909 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2911 kfree(oidbuf, M_TEMP);
2914 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2915 kfree(oidbuf, M_TEMP);
2917 case SIOCGPRIVATE_0:
2918 if ((error = priv_check(curthread, PRIV_DRIVER)))
2921 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2926 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2931 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2936 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2937 ifr->ifr_data, sizeof(uint32_t) * 2);
2942 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2943 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2944 (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2945 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2950 kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2951 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2953 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2954 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2955 NDIS_EVTINC(sc->ndis_evtcidx);
2959 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2962 error = ether_ioctl(ifp, command, data);
2972 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2974 struct ndis_softc *sc;
2975 ndis_80211_key rkey;
2978 sc = vap->iv_ic->ic_ifp->if_softc;
2980 bzero((char *)&rkey, sizeof(rkey));
2984 rkey.nk_keyidx = key->wk_keyix;
2986 bcopy(vap->iv_ifp->if_broadcastaddr,
2987 rkey.nk_bssid, IEEE80211_ADDR_LEN);
2989 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
2998 * In theory this could be called for any key, but we'll
2999 * only use it for WPA TKIP or AES keys. These need to be
3000 * set after initial authentication with the AP.
3003 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
3004 const uint8_t mac[IEEE80211_ADDR_LEN])
3006 struct ndis_softc *sc;
3008 ndis_80211_key rkey;
3011 ifp = vap->iv_ic->ic_ifp;
3014 switch (key->wk_cipher->ic_cipher) {
3015 case IEEE80211_CIPHER_TKIP:
3017 len = sizeof(ndis_80211_key);
3018 bzero((char *)&rkey, sizeof(rkey));
3021 rkey.nk_keylen = key->wk_keylen;
3023 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3024 rkey.nk_keylen += 16;
3026 /* key index - gets weird in NDIS */
3028 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3029 rkey.nk_keyidx = key->wk_keyix;
3033 if (key->wk_flags & IEEE80211_KEY_XMIT)
3034 rkey.nk_keyidx |= 1 << 31;
3036 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3037 bcopy(ifp->if_broadcastaddr,
3038 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3040 bcopy(vap->iv_bss->ni_bssid,
3041 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3043 rkey.nk_keyidx |= 1 << 30;
3046 /* need to set bit 29 based on keyrsc */
3047 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3050 rkey.nk_keyidx |= 1 << 29;
3052 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3053 bcopy(key->wk_key, rkey.nk_keydata, 16);
3054 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3055 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3057 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3059 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3061 case IEEE80211_CIPHER_WEP:
3065 * I don't know how to set up keys for the AES
3066 * cipher yet. Is it the same as TKIP?
3068 case IEEE80211_CIPHER_AES_CCM:
3074 /* We need to return 1 for success, 0 for failure. */
3083 ndis_resettask(device_object *d, void *arg)
3085 struct ndis_softc *sc;
3092 * Stop the adapter and free any mbufs allocated to the
3096 ndis_stop(struct ndis_softc *sc)
3102 callout_stop(&sc->ndis_stat_callout); /* XXX swildner callout_drain() */
3105 sc->ndis_tx_timer = 0;
3107 ifp->if_flags &= ~IFF_RUNNING;
3108 ifq_clr_oactive(&ifp->if_snd);
3111 if (sc->ndis_iftype != PNPBus ||
3112 (sc->ndis_iftype == PNPBus &&
3113 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3118 for (i = 0; i < NDIS_EVENTS; i++) {
3119 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3120 kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3121 sc->ndis_evt[i].ne_buf = NULL;
3123 sc->ndis_evt[i].ne_sts = 0;
3124 sc->ndis_evt[i].ne_len = 0;
3126 sc->ndis_evtcidx = 0;
3127 sc->ndis_evtpidx = 0;
3132 * Stop all chip I/O so that the kernel's probe routines don't
3133 * get confused by errant DMAs when rebooting.
3136 ndis_shutdown(device_t dev)
3138 struct ndis_softc *sc;
3140 wlan_serialize_enter();
3141 sc = device_get_softc(dev);
3143 wlan_serialize_exit();
3147 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3149 struct ndis_vap *nvp = NDIS_VAP(vap);
3150 struct ieee80211com *ic = vap->iv_ic;
3151 struct ifnet *ifp = ic->ic_ifp;
3152 struct ndis_softc *sc = ifp->if_softc;
3153 enum ieee80211_state ostate;
3155 DPRINTF(("%s: %s -> %s\n", __func__,
3156 ieee80211_state_name[vap->iv_state],
3157 ieee80211_state_name[nstate]));
3159 ostate = vap->iv_state;
3160 vap->iv_state = nstate;
3163 /* pass on to net80211 */
3164 case IEEE80211_S_INIT:
3165 case IEEE80211_S_SCAN:
3166 return nvp->newstate(vap, nstate, arg);
3167 case IEEE80211_S_ASSOC:
3168 if (ostate != IEEE80211_S_AUTH) {
3169 wlan_serialize_exit();
3170 ndis_auth_and_assoc(sc, vap);
3171 wlan_serialize_enter();
3174 case IEEE80211_S_AUTH:
3175 wlan_serialize_exit();
3176 ndis_auth_and_assoc(sc, vap);
3177 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3178 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3179 wlan_serialize_enter();
3188 ndis_scan(void *arg)
3190 struct ieee80211vap *vap = arg;
3192 ieee80211_scan_done(vap);
3196 ndis_scan_results(struct ndis_softc *sc)
3198 struct ieee80211com *ic;
3199 struct ieee80211vap *vap;
3200 ndis_80211_bssid_list_ex *bl;
3201 ndis_wlan_bssid_ex *wb;
3202 struct ieee80211_scanparams sp;
3203 struct ieee80211_frame wh;
3204 struct ieee80211_channel *saved_chan;
3206 int rssi, noise, freq, chanflag;
3207 uint8_t ssid[2+IEEE80211_NWID_LEN];
3208 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3209 uint8_t *frm, *efrm;
3211 ic = sc->ifp->if_l2com;
3212 vap = TAILQ_FIRST(&ic->ic_vaps);
3213 saved_chan = ic->ic_curchan;
3216 if (ndis_get_bssid_list(sc, &bl))
3219 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3220 wb = &bl->nblx_bssid[0];
3221 for (i = 0; i < bl->nblx_items; i++) {
3222 memset(&sp, 0, sizeof(sp));
3224 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3225 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3226 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3227 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3228 if (wb->nwbx_privacy)
3229 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3230 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3231 switch (wb->nwbx_netinfra) {
3232 case NDIS_80211_NET_INFRA_IBSS:
3233 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3235 case NDIS_80211_NET_INFRA_BSS:
3236 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3239 sp.rates = &rates[0];
3240 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3241 /* XXX - check units */
3242 if (wb->nwbx_supportedrates[j] == 0)
3245 wb->nwbx_supportedrates[j] & 0x7f;
3249 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3250 wb->nwbx_ssid.ns_ssidlen);
3251 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3253 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3254 freq = wb->nwbx_config.nc_dsconfig / 1000;
3255 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3256 /* Hack ic->ic_curchan to be in sync with the scan result */
3257 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3258 if (ic->ic_curchan == NULL)
3259 ic->ic_curchan = &ic->ic_channels[0];
3261 /* Process extended info from AP */
3262 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3263 frm = (uint8_t *)&wb->nwbx_ies;
3264 efrm = frm + wb->nwbx_ielen;
3265 if (efrm - frm < 12)
3267 sp.tstamp = frm; frm += 8;
3268 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3269 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3271 sp.ies_len = efrm - frm;
3274 DPRINTF(("scan: bssid %6D chan %dMHz (%d/%d) rssi %d\n",
3275 wb->nwbx_macaddr, ":", freq, sp.bchan, chanflag,
3277 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3278 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3280 kfree(bl, M_DEVBUF);
3281 /* Restore the channel after messing with it */
3282 ic->ic_curchan = saved_chan;
3286 ndis_scan_start(struct ieee80211com *ic)
3288 struct ifnet *ifp = ic->ic_ifp;
3289 struct ndis_softc *sc = ifp->if_softc;
3290 struct ieee80211vap *vap;
3291 struct ieee80211_scan_state *ss;
3292 ndis_80211_ssid ssid;
3296 vap = TAILQ_FIRST(&ic->ic_vaps);
3298 if (!NDIS_INITIALIZED(sc)) {
3299 DPRINTF(("%s: scan aborted\n", __func__));
3300 ieee80211_cancel_scan(vap);
3305 bzero((char *)&ssid, len);
3306 if (ss->ss_nssid == 0)
3307 ssid.ns_ssidlen = 1;
3309 /* Perform a directed scan */
3310 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3311 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3314 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3316 DPRINTF(("%s: set ESSID failed\n", __func__));
3319 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3321 DPRINTF(("%s: scan command failed\n", __func__));
3322 ieee80211_cancel_scan(vap);
3325 /* Set a timer to collect the results */
3326 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3330 ndis_set_channel(struct ieee80211com *ic)
3336 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3342 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3344 /* NB: don't try to abort scan; wait for firmware to finish */
3348 ndis_scan_end(struct ieee80211com *ic)
3350 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3352 ndis_scan_results(sc);