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 *, struct ifaltq_subque *);
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;
1453 IFNET_STAT_INC(ifp, ierrors, 1);
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)
1555 IFNET_STAT_INC(ifp, opackets, 1);
1557 IFNET_STAT_INC(ifp, oerrors, 1);
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 IFNET_STAT_INC(sc->ifp, oerrors, 1);
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, struct ifaltq_subque *ifsq)
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;
1804 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
1809 if (!sc->ndis_link) {
1810 ifq_purge(&ifp->if_snd);
1815 if (ifq_is_oactive(&ifp->if_snd)) {
1820 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1822 while(sc->ndis_txpending) {
1823 m = ifq_dequeue(&ifp->if_snd, NULL);
1827 NdisAllocatePacket(&status,
1828 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1830 if (status != NDIS_STATUS_SUCCESS)
1833 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1834 ifq_prepend(&ifp->if_snd, m);
1840 * Save pointer to original mbuf
1841 * so we can free it later.
1844 p = sc->ndis_txarray[sc->ndis_txidx];
1845 p->np_txidx = sc->ndis_txidx;
1847 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1850 * Do scatter/gather processing, if driver requested it.
1853 bus_dmamap_load_mbuf(sc->ndis_ttag,
1854 sc->ndis_tmaps[sc->ndis_txidx], m,
1855 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1856 bus_dmamap_sync(sc->ndis_ttag,
1857 sc->ndis_tmaps[sc->ndis_txidx],
1858 BUS_DMASYNC_PREREAD);
1859 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1862 /* Handle checksum offload. */
1864 if (ifp->if_capenable & IFCAP_TXCSUM &&
1865 m->m_pkthdr.csum_flags) {
1866 csum = (ndis_tcpip_csum *)
1867 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1868 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1869 if (m->m_pkthdr.csum_flags & CSUM_IP)
1870 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1871 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1872 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1873 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1874 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1875 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1879 sc->ndis_txpending--;
1884 * If there's a BPF listener, bounce a copy of this frame
1887 if (!sc->ndis_80211) /* XXX handle 80211 */
1891 * The array that p0 points to must appear contiguous,
1892 * so we must not wrap past the end of sc->ndis_txarray[].
1893 * If it looks like we're about to wrap, break out here
1894 * so the this batch of packets can be transmitted, then
1895 * wait for txeof to ask us to send the rest.
1897 if (sc->ndis_txidx == 0)
1906 if (sc->ndis_txpending == 0)
1907 ifq_set_oactive(&ifp->if_snd);
1910 * Set a timeout in case the chip goes out to lunch.
1912 sc->ndis_tx_timer = 5;
1917 * According to NDIS documentation, if a driver exports
1918 * a MiniportSendPackets() routine, we prefer that over
1919 * a MiniportSend() routine (which sends just a single
1922 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1923 ndis_send_packets(sc, p0, pcnt);
1925 ndis_send_packet(sc, p);
1931 ndis_init(void *xsc)
1933 struct ndis_softc *sc = xsc;
1934 struct ifnet *ifp = sc->ifp;
1935 struct ieee80211com *ic = ifp->if_l2com;
1939 * Avoid reintializing the link unnecessarily.
1940 * This should be dealt with in a better way by
1941 * fixing the upper layer modules so they don't
1942 * call ifp->if_init() quite as often.
1948 * Cancel pending I/O and free all RX/TX buffers.
1952 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1953 error = ndis_init_nic(sc);
1955 device_printf(sc->ndis_dev,
1956 "failed to initialize the device: %d\n", error);
1961 /* Init our MAC address */
1963 /* Program the packet filter */
1965 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1967 if (ifp->if_flags & IFF_BROADCAST)
1968 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1970 if (ifp->if_flags & IFF_PROMISC)
1971 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1973 len = sizeof(sc->ndis_filter);
1975 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1976 &sc->ndis_filter, &len);
1979 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1986 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1989 * Program the multicast filter, if necessary.
1993 /* Setup task offload. */
1994 ndis_set_offload(sc);
1999 sc->ndis_txpending = sc->ndis_maxpkts;
2002 sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
2003 if_link_state_change(sc->ifp);
2005 ifp->if_flags |= IFF_RUNNING;
2006 ifq_clr_oactive(&ifp->if_snd);
2007 sc->ndis_tx_timer = 0;
2010 * Some drivers don't set this value. The NDIS spec says
2011 * the default checkforhang timeout is "approximately 2
2012 * seconds." We use 3 seconds, because it seems for some
2013 * drivers, exactly 2 seconds is too fast.
2015 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2016 sc->ndis_block->nmb_checkforhangsecs = 3;
2018 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2019 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2022 /* XXX force handling */
2024 ieee80211_start_all(ic); /* start all vap's */
2028 * Set media options.
2031 ndis_ifmedia_upd(struct ifnet *ifp)
2033 struct ndis_softc *sc;
2037 if (NDIS_INITIALIZED(sc))
2044 * Report current media status.
2047 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2049 struct ndis_softc *sc;
2050 uint32_t media_info;
2051 ndis_media_state linkstate;
2054 ifmr->ifm_status = IFM_AVALID;
2055 ifmr->ifm_active = IFM_ETHER;
2058 if (!NDIS_INITIALIZED(sc))
2061 len = sizeof(linkstate);
2062 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2063 (void *)&linkstate, &len);
2065 len = sizeof(media_info);
2066 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2067 (void *)&media_info, &len);
2069 if (linkstate == nmc_connected)
2070 ifmr->ifm_status |= IFM_ACTIVE;
2072 switch (media_info) {
2074 ifmr->ifm_active |= IFM_10_T;
2077 ifmr->ifm_active |= IFM_100_TX;
2080 ifmr->ifm_active |= IFM_1000_T;
2083 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2089 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2091 struct ieee80211com *ic;
2095 ic = sc->ifp->if_l2com;
2099 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2100 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2102 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2105 if (cipher == WPA_CSE_TKIP) {
2106 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2108 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2111 if (cipher == WPA_CSE_CCMP) {
2112 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2114 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2117 DPRINTF(("Setting cipher to %d\n", arg));
2119 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2124 /* Check that the cipher was set correctly. */
2127 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2129 if (rval != 0 || arg != save)
2136 * WPA is hairy to set up. Do the work in a separate routine
2137 * so we don't clutter the setstate function too much.
2138 * Important yet undocumented fact: first we have to set the
2139 * authentication mode, _then_ we enable the ciphers. If one
2140 * of the WPA authentication modes isn't enabled, the driver
2141 * might not permit the TKIP or AES ciphers to be selected.
2144 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2146 struct ieee80211_ie_wpa *w;
2153 * Apparently, the only way for us to know what ciphers
2154 * and key management/authentication mode to use is for
2155 * us to inspect the optional information element (IE)
2156 * stored in the 802.11 state machine. This IE should be
2157 * supplied by the WPA supplicant.
2160 w = (struct ieee80211_ie_wpa *)ie;
2162 /* Check for the right kind of IE. */
2163 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2164 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2168 /* Skip over the ucast cipher OIDs. */
2169 pos = (char *)&w->wpa_uciphers[0];
2170 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2172 /* Skip over the authmode count. */
2173 pos += sizeof(u_int16_t);
2176 * Check for the authentication modes. I'm
2177 * pretty sure there's only supposed to be one.
2180 n = (struct ndis_ie *)pos;
2181 if (n->ni_val == WPA_ASE_NONE)
2182 arg = NDIS_80211_AUTHMODE_WPANONE;
2184 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2185 arg = NDIS_80211_AUTHMODE_WPA;
2187 if (n->ni_val == WPA_ASE_8021X_PSK)
2188 arg = NDIS_80211_AUTHMODE_WPAPSK;
2190 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2192 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2195 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2197 /* Now configure the desired ciphers. */
2199 /* First, set up the multicast group cipher. */
2200 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2202 if (ndis_set_cipher(sc, n->ni_val))
2205 /* Now start looking around for the unicast ciphers. */
2206 pos = (char *)&w->wpa_uciphers[0];
2207 n = (struct ndis_ie *)pos;
2209 for (i = 0; i < w->wpa_uciphercnt; i++) {
2210 if (ndis_set_cipher(sc, n->ni_val))
2219 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2221 struct ieee80211vap *vap = ifp->if_softc;
2222 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2226 if (!NDIS_INITIALIZED(sc))
2229 len = sizeof(txrate);
2230 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2231 vap->iv_bss->ni_txrate = txrate / 5000;
2232 ieee80211_media_status(ifp, imr);
2236 ndis_setstate_80211(struct ndis_softc *sc)
2238 struct ieee80211com *ic;
2239 struct ieee80211vap *vap;
2240 ndis_80211_macaddr bssid;
2241 ndis_80211_config config;
2245 char ethstr[ETHER_ADDRSTRLEN + 1];
2249 vap = TAILQ_FIRST(&ic->ic_vaps);
2251 if (!NDIS_INITIALIZED(sc)) {
2252 DPRINTF(("%s: NDIS not initialized\n", __func__));
2256 /* Disassociate and turn off radio. */
2259 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2261 /* Set network infrastructure mode. */
2264 if (ic->ic_opmode == IEEE80211_M_IBSS)
2265 arg = NDIS_80211_NET_INFRA_IBSS;
2267 arg = NDIS_80211_NET_INFRA_BSS;
2269 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2272 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2274 /* Set power management */
2276 if (vap->iv_flags & IEEE80211_F_PMGTON)
2277 arg = NDIS_80211_POWERMODE_FAST_PSP;
2279 arg = NDIS_80211_POWERMODE_CAM;
2280 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2283 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2284 ic->ic_txpowlimit < NELEM(dBm2mW)) {
2285 arg = dBm2mW[ic->ic_txpowlimit];
2287 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2291 * Default encryption mode to off, authentication
2292 * to open and privacy to 'accept everything.'
2295 arg = NDIS_80211_WEPSTAT_DISABLED;
2296 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2299 arg = NDIS_80211_AUTHMODE_OPEN;
2300 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2303 * Note that OID_802_11_PRIVACY_FILTER is optional:
2304 * not all drivers implement it.
2307 arg = NDIS_80211_PRIVFILT_8021XWEP;
2308 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2310 len = sizeof(config);
2311 bzero((char *)&config, len);
2312 config.nc_length = len;
2313 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2314 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2317 * Some drivers expect us to initialize these values, so
2318 * provide some defaults.
2321 if (config.nc_beaconperiod == 0)
2322 config.nc_beaconperiod = 100;
2323 if (config.nc_atimwin == 0)
2324 config.nc_atimwin = 100;
2325 if (config.nc_fhconfig.ncf_dwelltime == 0)
2326 config.nc_fhconfig.ncf_dwelltime = 200;
2327 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2330 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2331 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2332 config.nc_dsconfig =
2333 ic->ic_bsschan->ic_freq * 1000;
2334 len = sizeof(config);
2335 config.nc_length = len;
2336 config.nc_fhconfig.ncf_length =
2337 sizeof(ndis_80211_config_fh);
2338 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2339 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2342 device_printf(sc->ndis_dev, "couldn't change "
2343 "DS config to %ukHz: %d\n",
2344 config.nc_dsconfig, rval);
2347 device_printf(sc->ndis_dev, "couldn't retrieve "
2348 "channel info: %d\n", rval);
2350 /* Set the BSSID to our value so the driver doesn't associate */
2351 len = IEEE80211_ADDR_LEN;
2352 bcopy(IF_LLADDR(ifp), bssid, len);
2353 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2354 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2356 device_printf(sc->ndis_dev,
2357 "setting BSSID failed: %d\n", rval);
2361 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2363 struct ieee80211_node *ni;
2364 ndis_80211_ssid ssid;
2365 ndis_80211_macaddr bssid;
2367 int i, rval = 0, len, error;
2370 char ethstr[ETHER_ADDRSTRLEN + 1];
2375 if (!NDIS_INITIALIZED(sc)) {
2376 DPRINTF(("%s: NDIS not initialized\n", __func__));
2381 ndis_setstate_80211(sc);
2383 /* Set network infrastructure mode. */
2386 if (vap->iv_opmode == IEEE80211_M_IBSS)
2387 arg = NDIS_80211_NET_INFRA_IBSS;
2389 arg = NDIS_80211_NET_INFRA_BSS;
2391 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2394 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2396 /* Set RTS threshold */
2399 arg = vap->iv_rtsthreshold;
2400 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2402 /* Set fragmentation threshold */
2405 arg = vap->iv_fragthreshold;
2406 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2410 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2411 !(vap->iv_flags & IEEE80211_F_WPA)) {
2414 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2416 arg = NDIS_80211_AUTHMODE_SHARED;
2417 DPRINTF(("Setting shared auth\n"));
2418 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2421 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2422 if (vap->iv_nw_keys[i].wk_keylen) {
2423 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2424 IEEE80211_CIPHER_WEP)
2426 bzero((char *)&wep, sizeof(wep));
2427 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2430 * 5, 13 and 16 are the only valid
2431 * key lengths. Anything in between
2432 * will be zero padded out to the
2433 * next highest boundary.
2435 if (vap->iv_nw_keys[i].wk_keylen < 5)
2437 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2438 vap->iv_nw_keys[i].wk_keylen < 13)
2440 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2441 vap->iv_nw_keys[i].wk_keylen < 16)
2445 wep.nw_length = (sizeof(uint32_t) * 3)
2447 if (i == vap->iv_def_txkey)
2448 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2449 bcopy(vap->iv_nw_keys[i].wk_key,
2450 wep.nw_keydata, wep.nw_length);
2452 DPRINTF(("Setting WEP key %d\n", i));
2453 rval = ndis_set_info(sc,
2454 OID_802_11_ADD_WEP, &wep, &len);
2456 device_printf(sc->ndis_dev,
2457 "set wepkey failed: %d\n", rval);
2462 DPRINTF(("Setting WEP on\n"));
2463 arg = NDIS_80211_WEPSTAT_ENABLED;
2465 rval = ndis_set_info(sc,
2466 OID_802_11_WEP_STATUS, &arg, &len);
2468 device_printf(sc->ndis_dev,
2469 "enable WEP failed: %d\n", rval);
2470 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2471 arg = NDIS_80211_PRIVFILT_8021XWEP;
2473 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2477 OID_802_11_PRIVACY_FILTER, &arg, &len);
2482 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2483 vap->iv_appie_assocreq != NULL) {
2484 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2485 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2487 device_printf(sc->ndis_dev, "WPA setup failed\n");
2491 /* Set network type. */
2495 switch (vap->iv_curmode) {
2496 case IEEE80211_MODE_11A:
2497 arg = NDIS_80211_NETTYPE_11OFDM5;
2499 case IEEE80211_MODE_11B:
2500 arg = NDIS_80211_NETTYPE_11DS;
2502 case IEEE80211_MODE_11G:
2503 arg = NDIS_80211_NETTYPE_11OFDM24;
2506 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2511 DPRINTF(("Setting network type to %d\n", arg));
2513 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2516 device_printf(sc->ndis_dev,
2517 "set nettype failed: %d\n", rval);
2522 * If the user selected a specific BSSID, try
2523 * to use that one. This is useful in the case where
2524 * there are several APs in range with the same network
2525 * name. To delete the BSSID, we use the broadcast
2526 * address as the BSSID.
2527 * Note that some drivers seem to allow setting a BSSID
2528 * in ad-hoc mode, which has the effect of forcing the
2529 * NIC to create an ad-hoc cell with a specific BSSID,
2530 * instead of a randomly chosen one. However, the net80211
2531 * code makes the assumtion that the BSSID setting is invalid
2532 * when you're in ad-hoc mode, so we don't allow that here.
2535 len = IEEE80211_ADDR_LEN;
2536 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2537 vap->iv_opmode != IEEE80211_M_IBSS)
2538 bcopy(ni->ni_bssid, bssid, len);
2540 bcopy(ifp->if_broadcastaddr, bssid, len);
2542 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2543 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2545 device_printf(sc->ndis_dev,
2546 "setting BSSID failed: %d\n", rval);
2548 /* Set SSID -- always do this last. */
2551 if (ndis_debug > 0) {
2552 kprintf("Setting ESSID to ");
2553 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2559 bzero((char *)&ssid, len);
2560 ssid.ns_ssidlen = ni->ni_esslen;
2561 if (ssid.ns_ssidlen == 0) {
2562 ssid.ns_ssidlen = 1;
2564 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2566 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2569 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2575 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2579 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2580 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2584 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2585 if (error == ENOSPC) {
2586 kfree(*bl, M_DEVBUF);
2587 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2591 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2594 DPRINTF(("%s: failed to read\n", __func__));
2595 kfree(*bl, M_DEVBUF);
2603 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2605 struct ifnet *ifp = sc->ifp;
2606 struct ieee80211com *ic = ifp->if_l2com;
2607 struct ieee80211vap *vap;
2608 struct ieee80211_node *ni;
2609 ndis_80211_bssid_list_ex *bl;
2610 ndis_wlan_bssid_ex *bs;
2611 ndis_80211_macaddr bssid;
2617 len = sizeof(bssid);
2618 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2620 device_printf(sc->ndis_dev, "failed to get bssid\n");
2624 vap = TAILQ_FIRST(&ic->ic_vaps);
2627 error = ndis_get_bssid_list(sc, &bl);
2631 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2632 for (i = 0; i < bl->nblx_items; i++) {
2633 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2634 *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2635 if (*assoc == NULL) {
2639 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2641 if (ic->ic_opmode == IEEE80211_M_STA)
2642 ni->ni_associd = 1 | 0xc000; /* fake associd */
2645 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2653 ndis_getstate_80211(struct ndis_softc *sc)
2655 struct ieee80211com *ic;
2656 struct ieee80211vap *vap;
2657 struct ieee80211_node *ni;
2658 ndis_wlan_bssid_ex *bs;
2659 int rval, len, i = 0;
2666 vap = TAILQ_FIRST(&ic->ic_vaps);
2669 if (!NDIS_INITIALIZED(sc))
2672 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2675 /* We're associated, retrieve info on the current bssid. */
2676 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2677 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2678 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2680 /* Get SSID from current association info. */
2681 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2682 bs->nwbx_ssid.ns_ssidlen);
2683 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2685 if (ic->ic_caps & IEEE80211_C_PMGT) {
2687 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2690 device_printf(sc->ndis_dev,
2691 "get power mode failed: %d\n", rval);
2692 if (arg == NDIS_80211_POWERMODE_CAM)
2693 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2695 vap->iv_flags |= IEEE80211_F_PMGTON;
2699 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2701 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2702 for (i = 0; i < NELEM(dBm2mW); i++)
2703 if (dBm2mW[i] >= arg)
2705 ic->ic_txpowlimit = i;
2709 * Use the current association information to reflect
2710 * what channel we're on.
2712 ic->ic_curchan = ieee80211_find_channel(ic,
2713 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2714 if (ic->ic_curchan == NULL)
2715 ic->ic_curchan = &ic->ic_channels[0];
2716 ni->ni_chan = ic->ic_curchan;
2717 ic->ic_bsschan = ic->ic_curchan;
2722 * Determine current authentication mode.
2725 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2727 device_printf(sc->ndis_dev,
2728 "get authmode status failed: %d\n", rval);
2730 vap->iv_flags &= ~IEEE80211_F_WPA;
2732 case NDIS_80211_AUTHMODE_OPEN:
2733 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2735 case NDIS_80211_AUTHMODE_SHARED:
2736 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2738 case NDIS_80211_AUTHMODE_AUTO:
2739 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2741 case NDIS_80211_AUTHMODE_WPA:
2742 case NDIS_80211_AUTHMODE_WPAPSK:
2743 case NDIS_80211_AUTHMODE_WPANONE:
2744 ni->ni_authmode = IEEE80211_AUTH_WPA;
2745 vap->iv_flags |= IEEE80211_F_WPA1;
2747 case NDIS_80211_AUTHMODE_WPA2:
2748 case NDIS_80211_AUTHMODE_WPA2PSK:
2749 ni->ni_authmode = IEEE80211_AUTH_WPA;
2750 vap->iv_flags |= IEEE80211_F_WPA2;
2753 ni->ni_authmode = IEEE80211_AUTH_NONE;
2759 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2762 device_printf(sc->ndis_dev,
2763 "get wep status failed: %d\n", rval);
2765 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2766 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2768 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2772 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2774 struct ndis_softc *sc = ifp->if_softc;
2775 struct ifreq *ifr = (struct ifreq *) data;
2782 if (ifp->if_flags & IFF_UP) {
2783 if (ifp->if_flags & IFF_RUNNING &&
2784 ifp->if_flags & IFF_PROMISC &&
2785 !(sc->ndis_if_flags & IFF_PROMISC)) {
2787 NDIS_PACKET_TYPE_PROMISCUOUS;
2788 i = sizeof(sc->ndis_filter);
2789 error = ndis_set_info(sc,
2790 OID_GEN_CURRENT_PACKET_FILTER,
2791 &sc->ndis_filter, &i);
2792 } else if (ifp->if_flags & IFF_RUNNING &&
2793 !(ifp->if_flags & IFF_PROMISC) &&
2794 sc->ndis_if_flags & IFF_PROMISC) {
2796 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2797 i = sizeof(sc->ndis_filter);
2798 error = ndis_set_info(sc,
2799 OID_GEN_CURRENT_PACKET_FILTER,
2800 &sc->ndis_filter, &i);
2804 if (ifp->if_flags & IFF_RUNNING)
2807 sc->ndis_if_flags = ifp->if_flags;
2817 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2820 ifp->if_capenable = ifr->ifr_reqcap;
2821 if (ifp->if_capenable & IFCAP_TXCSUM)
2822 ifp->if_hwassist = sc->ndis_hwassist;
2824 ifp->if_hwassist = 0;
2825 ndis_set_offload(sc);
2828 error = ether_ioctl(ifp, command, data);
2832 /*NDIS_UNLOCK(sc);*/
2838 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2841 struct ndis_softc *sc = ifp->if_softc;
2842 struct ieee80211com *ic = ifp->if_l2com;
2843 struct ifreq *ifr = (struct ifreq *) data;
2844 struct ndis_oid_data oid;
2845 struct ndis_evt evt;
2852 if (ifp->if_flags & IFF_UP) {
2853 if (!(ifp->if_flags & IFF_RUNNING))
2856 if (ifp->if_flags & IFF_RUNNING)
2859 sc->ndis_if_flags = ifp->if_flags;
2861 /*NDIS_UNLOCK(sc);*/
2864 if ((error = priv_check(curthread, PRIV_DRIVER)))
2866 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2869 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2870 if (oidbuf == NULL) {
2874 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2876 kfree(oidbuf, M_TEMP);
2879 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2881 kfree(oidbuf, M_TEMP);
2884 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2886 kfree(oidbuf, M_TEMP);
2889 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2890 kfree(oidbuf, M_TEMP);
2893 if ((error = priv_check(curthread, PRIV_DRIVER)))
2895 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2898 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2899 if (oidbuf == NULL) {
2903 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2905 kfree(oidbuf, M_TEMP);
2908 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2910 kfree(oidbuf, M_TEMP);
2913 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2915 kfree(oidbuf, M_TEMP);
2918 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2919 kfree(oidbuf, M_TEMP);
2921 case SIOCGPRIVATE_0:
2922 if ((error = priv_check(curthread, PRIV_DRIVER)))
2925 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2930 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2935 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2940 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2941 ifr->ifr_data, sizeof(uint32_t) * 2);
2946 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2947 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2948 (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2949 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2954 kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2955 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2957 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2958 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2959 NDIS_EVTINC(sc->ndis_evtcidx);
2963 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2966 error = ether_ioctl(ifp, command, data);
2976 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2978 struct ndis_softc *sc;
2979 ndis_80211_key rkey;
2982 sc = vap->iv_ic->ic_ifp->if_softc;
2984 bzero((char *)&rkey, sizeof(rkey));
2988 rkey.nk_keyidx = key->wk_keyix;
2990 bcopy(vap->iv_ifp->if_broadcastaddr,
2991 rkey.nk_bssid, IEEE80211_ADDR_LEN);
2993 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3002 * In theory this could be called for any key, but we'll
3003 * only use it for WPA TKIP or AES keys. These need to be
3004 * set after initial authentication with the AP.
3007 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
3008 const uint8_t mac[IEEE80211_ADDR_LEN])
3010 struct ndis_softc *sc;
3012 ndis_80211_key rkey;
3015 ifp = vap->iv_ic->ic_ifp;
3018 switch (key->wk_cipher->ic_cipher) {
3019 case IEEE80211_CIPHER_TKIP:
3021 len = sizeof(ndis_80211_key);
3022 bzero((char *)&rkey, sizeof(rkey));
3025 rkey.nk_keylen = key->wk_keylen;
3027 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3028 rkey.nk_keylen += 16;
3030 /* key index - gets weird in NDIS */
3032 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3033 rkey.nk_keyidx = key->wk_keyix;
3037 if (key->wk_flags & IEEE80211_KEY_XMIT)
3038 rkey.nk_keyidx |= 1 << 31;
3040 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3041 bcopy(ifp->if_broadcastaddr,
3042 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3044 bcopy(vap->iv_bss->ni_bssid,
3045 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3047 rkey.nk_keyidx |= 1 << 30;
3050 /* need to set bit 29 based on keyrsc */
3051 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3054 rkey.nk_keyidx |= 1 << 29;
3056 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3057 bcopy(key->wk_key, rkey.nk_keydata, 16);
3058 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3059 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3061 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3063 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3065 case IEEE80211_CIPHER_WEP:
3069 * I don't know how to set up keys for the AES
3070 * cipher yet. Is it the same as TKIP?
3072 case IEEE80211_CIPHER_AES_CCM:
3078 /* We need to return 1 for success, 0 for failure. */
3087 ndis_resettask(device_object *d, void *arg)
3089 struct ndis_softc *sc;
3096 * Stop the adapter and free any mbufs allocated to the
3100 ndis_stop(struct ndis_softc *sc)
3106 callout_stop(&sc->ndis_stat_callout); /* XXX swildner callout_drain() */
3109 sc->ndis_tx_timer = 0;
3111 ifp->if_flags &= ~IFF_RUNNING;
3112 ifq_clr_oactive(&ifp->if_snd);
3115 if (sc->ndis_iftype != PNPBus ||
3116 (sc->ndis_iftype == PNPBus &&
3117 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3122 for (i = 0; i < NDIS_EVENTS; i++) {
3123 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3124 kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3125 sc->ndis_evt[i].ne_buf = NULL;
3127 sc->ndis_evt[i].ne_sts = 0;
3128 sc->ndis_evt[i].ne_len = 0;
3130 sc->ndis_evtcidx = 0;
3131 sc->ndis_evtpidx = 0;
3136 * Stop all chip I/O so that the kernel's probe routines don't
3137 * get confused by errant DMAs when rebooting.
3140 ndis_shutdown(device_t dev)
3142 struct ndis_softc *sc;
3144 wlan_serialize_enter();
3145 sc = device_get_softc(dev);
3147 wlan_serialize_exit();
3151 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3153 struct ndis_vap *nvp = NDIS_VAP(vap);
3154 struct ieee80211com *ic = vap->iv_ic;
3155 struct ifnet *ifp = ic->ic_ifp;
3156 struct ndis_softc *sc = ifp->if_softc;
3157 enum ieee80211_state ostate;
3159 DPRINTF(("%s: %s -> %s\n", __func__,
3160 ieee80211_state_name[vap->iv_state],
3161 ieee80211_state_name[nstate]));
3163 ostate = vap->iv_state;
3164 vap->iv_state = nstate;
3167 /* pass on to net80211 */
3168 case IEEE80211_S_INIT:
3169 case IEEE80211_S_SCAN:
3170 return nvp->newstate(vap, nstate, arg);
3171 case IEEE80211_S_ASSOC:
3172 if (ostate != IEEE80211_S_AUTH) {
3173 wlan_serialize_exit();
3174 ndis_auth_and_assoc(sc, vap);
3175 wlan_serialize_enter();
3178 case IEEE80211_S_AUTH:
3179 wlan_serialize_exit();
3180 ndis_auth_and_assoc(sc, vap);
3181 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3182 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3183 wlan_serialize_enter();
3192 ndis_scan(void *arg)
3194 struct ieee80211vap *vap = arg;
3196 ieee80211_scan_done(vap);
3200 ndis_scan_results(struct ndis_softc *sc)
3202 struct ieee80211com *ic;
3203 struct ieee80211vap *vap;
3204 ndis_80211_bssid_list_ex *bl;
3205 ndis_wlan_bssid_ex *wb;
3206 struct ieee80211_scanparams sp;
3207 struct ieee80211_frame wh;
3208 struct ieee80211_channel *saved_chan;
3210 int rssi, noise, freq, chanflag;
3211 uint8_t ssid[2+IEEE80211_NWID_LEN];
3212 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3213 uint8_t *frm, *efrm;
3214 char ethstr[ETHER_ADDRSTRLEN + 1];
3216 ic = sc->ifp->if_l2com;
3217 vap = TAILQ_FIRST(&ic->ic_vaps);
3218 saved_chan = ic->ic_curchan;
3221 if (ndis_get_bssid_list(sc, &bl))
3224 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3225 wb = &bl->nblx_bssid[0];
3226 for (i = 0; i < bl->nblx_items; i++) {
3227 memset(&sp, 0, sizeof(sp));
3229 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3230 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3231 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3232 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3233 if (wb->nwbx_privacy)
3234 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3235 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3236 switch (wb->nwbx_netinfra) {
3237 case NDIS_80211_NET_INFRA_IBSS:
3238 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3240 case NDIS_80211_NET_INFRA_BSS:
3241 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3244 sp.rates = &rates[0];
3245 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3246 /* XXX - check units */
3247 if (wb->nwbx_supportedrates[j] == 0)
3250 wb->nwbx_supportedrates[j] & 0x7f;
3254 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3255 wb->nwbx_ssid.ns_ssidlen);
3256 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3258 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3259 freq = wb->nwbx_config.nc_dsconfig / 1000;
3260 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3261 /* Hack ic->ic_curchan to be in sync with the scan result */
3262 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3263 if (ic->ic_curchan == NULL)
3264 ic->ic_curchan = &ic->ic_channels[0];
3266 /* Process extended info from AP */
3267 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3268 frm = (uint8_t *)&wb->nwbx_ies;
3269 efrm = frm + wb->nwbx_ielen;
3270 if (efrm - frm < 12)
3272 sp.tstamp = frm; frm += 8;
3273 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3274 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3276 sp.ies_len = efrm - frm;
3279 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3280 kether_ntoa(wb->nwbx_macaddr, ethstr), freq, sp.bchan, chanflag,
3282 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3283 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3285 kfree(bl, M_DEVBUF);
3286 /* Restore the channel after messing with it */
3287 ic->ic_curchan = saved_chan;
3291 ndis_scan_start(struct ieee80211com *ic)
3293 struct ifnet *ifp = ic->ic_ifp;
3294 struct ndis_softc *sc = ifp->if_softc;
3295 struct ieee80211vap *vap;
3296 struct ieee80211_scan_state *ss;
3297 ndis_80211_ssid ssid;
3301 vap = TAILQ_FIRST(&ic->ic_vaps);
3303 if (!NDIS_INITIALIZED(sc)) {
3304 DPRINTF(("%s: scan aborted\n", __func__));
3305 ieee80211_cancel_scan(vap);
3310 bzero((char *)&ssid, len);
3311 if (ss->ss_nssid == 0)
3312 ssid.ns_ssidlen = 1;
3314 /* Perform a directed scan */
3315 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3316 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3319 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3321 DPRINTF(("%s: set ESSID failed\n", __func__));
3324 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3326 DPRINTF(("%s: scan command failed\n", __func__));
3327 ieee80211_cancel_scan(vap);
3330 /* Set a timer to collect the results */
3331 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3335 ndis_set_channel(struct ieee80211com *ic)
3341 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3347 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3349 /* NB: don't try to abort scan; wait for firmware to finish */
3353 ndis_scan_end(struct ieee80211com *ic)
3355 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3357 ndis_scan_results(sc);