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 lwkt_serialize_enter(ifp->if_serializer);
1780 if (!ifq_is_empty(&ifp->if_snd))
1782 lwkt_serialize_exit(ifp->if_serializer);
1786 * Main transmit routine. To make NDIS drivers happy, we need to
1787 * transform mbuf chains into NDIS packets and feed them to the
1788 * send packet routines. Most drivers allow you to send several
1789 * packets at once (up to the maxpkts limit). Unfortunately, rather
1790 * that accepting them in the form of a linked list, they expect
1791 * a contiguous array of pointers to packets.
1793 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1794 * we need to perform busdma work here. Those that use map registers
1795 * will do the mapping themselves on a buffer by buffer basis.
1798 ndis_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
1800 struct ndis_softc *sc;
1801 struct mbuf *m = NULL;
1802 ndis_packet **p0 = NULL, *p = NULL;
1803 ndis_tcpip_csum *csum;
1804 int pcnt = 0, status;
1806 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
1811 if (!sc->ndis_link) {
1812 ifq_purge(&ifp->if_snd);
1817 if (ifq_is_oactive(&ifp->if_snd)) {
1822 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1824 while(sc->ndis_txpending) {
1825 m = ifq_dequeue(&ifp->if_snd);
1829 NdisAllocatePacket(&status,
1830 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1832 if (status != NDIS_STATUS_SUCCESS)
1835 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1836 ifq_prepend(&ifp->if_snd, m);
1842 * Save pointer to original mbuf
1843 * so we can free it later.
1846 p = sc->ndis_txarray[sc->ndis_txidx];
1847 p->np_txidx = sc->ndis_txidx;
1849 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1852 * Do scatter/gather processing, if driver requested it.
1855 bus_dmamap_load_mbuf(sc->ndis_ttag,
1856 sc->ndis_tmaps[sc->ndis_txidx], m,
1857 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1858 bus_dmamap_sync(sc->ndis_ttag,
1859 sc->ndis_tmaps[sc->ndis_txidx],
1860 BUS_DMASYNC_PREREAD);
1861 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1864 /* Handle checksum offload. */
1866 if (ifp->if_capenable & IFCAP_TXCSUM &&
1867 m->m_pkthdr.csum_flags) {
1868 csum = (ndis_tcpip_csum *)
1869 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1870 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1871 if (m->m_pkthdr.csum_flags & CSUM_IP)
1872 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1873 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1874 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1875 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1876 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1877 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1881 sc->ndis_txpending--;
1886 * If there's a BPF listener, bounce a copy of this frame
1889 if (!sc->ndis_80211) /* XXX handle 80211 */
1893 * The array that p0 points to must appear contiguous,
1894 * so we must not wrap past the end of sc->ndis_txarray[].
1895 * If it looks like we're about to wrap, break out here
1896 * so the this batch of packets can be transmitted, then
1897 * wait for txeof to ask us to send the rest.
1899 if (sc->ndis_txidx == 0)
1908 if (sc->ndis_txpending == 0)
1909 ifq_set_oactive(&ifp->if_snd);
1912 * Set a timeout in case the chip goes out to lunch.
1914 sc->ndis_tx_timer = 5;
1919 * According to NDIS documentation, if a driver exports
1920 * a MiniportSendPackets() routine, we prefer that over
1921 * a MiniportSend() routine (which sends just a single
1924 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1925 ndis_send_packets(sc, p0, pcnt);
1927 ndis_send_packet(sc, p);
1933 ndis_init(void *xsc)
1935 struct ndis_softc *sc = xsc;
1936 struct ifnet *ifp = sc->ifp;
1937 struct ieee80211com *ic = ifp->if_l2com;
1941 * Avoid reintializing the link unnecessarily.
1942 * This should be dealt with in a better way by
1943 * fixing the upper layer modules so they don't
1944 * call ifp->if_init() quite as often.
1950 * Cancel pending I/O and free all RX/TX buffers.
1954 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1955 error = ndis_init_nic(sc);
1957 device_printf(sc->ndis_dev,
1958 "failed to initialize the device: %d\n", error);
1963 /* Init our MAC address */
1965 /* Program the packet filter */
1967 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1969 if (ifp->if_flags & IFF_BROADCAST)
1970 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1972 if (ifp->if_flags & IFF_PROMISC)
1973 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1975 len = sizeof(sc->ndis_filter);
1977 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1978 &sc->ndis_filter, &len);
1981 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1988 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1991 * Program the multicast filter, if necessary.
1995 /* Setup task offload. */
1996 ndis_set_offload(sc);
2001 sc->ndis_txpending = sc->ndis_maxpkts;
2004 sc->ifp->if_link_state = LINK_STATE_UNKNOWN;
2005 if_link_state_change(sc->ifp);
2007 ifp->if_flags |= IFF_RUNNING;
2008 ifq_clr_oactive(&ifp->if_snd);
2009 sc->ndis_tx_timer = 0;
2012 * Some drivers don't set this value. The NDIS spec says
2013 * the default checkforhang timeout is "approximately 2
2014 * seconds." We use 3 seconds, because it seems for some
2015 * drivers, exactly 2 seconds is too fast.
2017 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2018 sc->ndis_block->nmb_checkforhangsecs = 3;
2020 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2021 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2024 /* XXX force handling */
2026 ieee80211_start_all(ic); /* start all vap's */
2030 * Set media options.
2033 ndis_ifmedia_upd(struct ifnet *ifp)
2035 struct ndis_softc *sc;
2039 if (NDIS_INITIALIZED(sc))
2046 * Report current media status.
2049 ndis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2051 struct ndis_softc *sc;
2052 uint32_t media_info;
2053 ndis_media_state linkstate;
2056 ifmr->ifm_status = IFM_AVALID;
2057 ifmr->ifm_active = IFM_ETHER;
2060 if (!NDIS_INITIALIZED(sc))
2063 len = sizeof(linkstate);
2064 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2065 (void *)&linkstate, &len);
2067 len = sizeof(media_info);
2068 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2069 (void *)&media_info, &len);
2071 if (linkstate == nmc_connected)
2072 ifmr->ifm_status |= IFM_ACTIVE;
2074 switch (media_info) {
2076 ifmr->ifm_active |= IFM_10_T;
2079 ifmr->ifm_active |= IFM_100_TX;
2082 ifmr->ifm_active |= IFM_1000_T;
2085 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2091 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2093 struct ieee80211com *ic;
2097 ic = sc->ifp->if_l2com;
2101 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2102 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2104 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2107 if (cipher == WPA_CSE_TKIP) {
2108 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2110 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2113 if (cipher == WPA_CSE_CCMP) {
2114 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2116 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2119 DPRINTF(("Setting cipher to %d\n", arg));
2121 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2126 /* Check that the cipher was set correctly. */
2129 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2131 if (rval != 0 || arg != save)
2138 * WPA is hairy to set up. Do the work in a separate routine
2139 * so we don't clutter the setstate function too much.
2140 * Important yet undocumented fact: first we have to set the
2141 * authentication mode, _then_ we enable the ciphers. If one
2142 * of the WPA authentication modes isn't enabled, the driver
2143 * might not permit the TKIP or AES ciphers to be selected.
2146 ndis_set_wpa(struct ndis_softc *sc, void *ie, int ielen)
2148 struct ieee80211_ie_wpa *w;
2155 * Apparently, the only way for us to know what ciphers
2156 * and key management/authentication mode to use is for
2157 * us to inspect the optional information element (IE)
2158 * stored in the 802.11 state machine. This IE should be
2159 * supplied by the WPA supplicant.
2162 w = (struct ieee80211_ie_wpa *)ie;
2164 /* Check for the right kind of IE. */
2165 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2166 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2170 /* Skip over the ucast cipher OIDs. */
2171 pos = (char *)&w->wpa_uciphers[0];
2172 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2174 /* Skip over the authmode count. */
2175 pos += sizeof(u_int16_t);
2178 * Check for the authentication modes. I'm
2179 * pretty sure there's only supposed to be one.
2182 n = (struct ndis_ie *)pos;
2183 if (n->ni_val == WPA_ASE_NONE)
2184 arg = NDIS_80211_AUTHMODE_WPANONE;
2186 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2187 arg = NDIS_80211_AUTHMODE_WPA;
2189 if (n->ni_val == WPA_ASE_8021X_PSK)
2190 arg = NDIS_80211_AUTHMODE_WPAPSK;
2192 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2194 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2197 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2199 /* Now configure the desired ciphers. */
2201 /* First, set up the multicast group cipher. */
2202 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2204 if (ndis_set_cipher(sc, n->ni_val))
2207 /* Now start looking around for the unicast ciphers. */
2208 pos = (char *)&w->wpa_uciphers[0];
2209 n = (struct ndis_ie *)pos;
2211 for (i = 0; i < w->wpa_uciphercnt; i++) {
2212 if (ndis_set_cipher(sc, n->ni_val))
2221 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2223 struct ieee80211vap *vap = ifp->if_softc;
2224 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2228 if (!NDIS_INITIALIZED(sc))
2231 len = sizeof(txrate);
2232 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2233 vap->iv_bss->ni_txrate = txrate / 5000;
2234 ieee80211_media_status(ifp, imr);
2238 ndis_setstate_80211(struct ndis_softc *sc)
2240 struct ieee80211com *ic;
2241 struct ieee80211vap *vap;
2242 ndis_80211_macaddr bssid;
2243 ndis_80211_config config;
2247 char ethstr[ETHER_ADDRSTRLEN + 1];
2251 vap = TAILQ_FIRST(&ic->ic_vaps);
2253 if (!NDIS_INITIALIZED(sc)) {
2254 DPRINTF(("%s: NDIS not initialized\n", __func__));
2258 /* Disassociate and turn off radio. */
2261 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2263 /* Set network infrastructure mode. */
2266 if (ic->ic_opmode == IEEE80211_M_IBSS)
2267 arg = NDIS_80211_NET_INFRA_IBSS;
2269 arg = NDIS_80211_NET_INFRA_BSS;
2271 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2274 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2276 /* Set power management */
2278 if (vap->iv_flags & IEEE80211_F_PMGTON)
2279 arg = NDIS_80211_POWERMODE_FAST_PSP;
2281 arg = NDIS_80211_POWERMODE_CAM;
2282 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2285 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2286 ic->ic_txpowlimit < NELEM(dBm2mW)) {
2287 arg = dBm2mW[ic->ic_txpowlimit];
2289 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2293 * Default encryption mode to off, authentication
2294 * to open and privacy to 'accept everything.'
2297 arg = NDIS_80211_WEPSTAT_DISABLED;
2298 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2301 arg = NDIS_80211_AUTHMODE_OPEN;
2302 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2305 * Note that OID_802_11_PRIVACY_FILTER is optional:
2306 * not all drivers implement it.
2309 arg = NDIS_80211_PRIVFILT_8021XWEP;
2310 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2312 len = sizeof(config);
2313 bzero((char *)&config, len);
2314 config.nc_length = len;
2315 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2316 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2319 * Some drivers expect us to initialize these values, so
2320 * provide some defaults.
2323 if (config.nc_beaconperiod == 0)
2324 config.nc_beaconperiod = 100;
2325 if (config.nc_atimwin == 0)
2326 config.nc_atimwin = 100;
2327 if (config.nc_fhconfig.ncf_dwelltime == 0)
2328 config.nc_fhconfig.ncf_dwelltime = 200;
2329 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2332 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2333 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2334 config.nc_dsconfig =
2335 ic->ic_bsschan->ic_freq * 1000;
2336 len = sizeof(config);
2337 config.nc_length = len;
2338 config.nc_fhconfig.ncf_length =
2339 sizeof(ndis_80211_config_fh);
2340 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2341 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2344 device_printf(sc->ndis_dev, "couldn't change "
2345 "DS config to %ukHz: %d\n",
2346 config.nc_dsconfig, rval);
2349 device_printf(sc->ndis_dev, "couldn't retrieve "
2350 "channel info: %d\n", rval);
2352 /* Set the BSSID to our value so the driver doesn't associate */
2353 len = IEEE80211_ADDR_LEN;
2354 bcopy(IF_LLADDR(ifp), bssid, len);
2355 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2356 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2358 device_printf(sc->ndis_dev,
2359 "setting BSSID failed: %d\n", rval);
2363 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2365 struct ieee80211_node *ni;
2366 ndis_80211_ssid ssid;
2367 ndis_80211_macaddr bssid;
2369 int i, rval = 0, len, error;
2372 char ethstr[ETHER_ADDRSTRLEN + 1];
2377 if (!NDIS_INITIALIZED(sc)) {
2378 DPRINTF(("%s: NDIS not initialized\n", __func__));
2383 ndis_setstate_80211(sc);
2385 /* Set network infrastructure mode. */
2388 if (vap->iv_opmode == IEEE80211_M_IBSS)
2389 arg = NDIS_80211_NET_INFRA_IBSS;
2391 arg = NDIS_80211_NET_INFRA_BSS;
2393 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2396 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2398 /* Set RTS threshold */
2401 arg = vap->iv_rtsthreshold;
2402 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2404 /* Set fragmentation threshold */
2407 arg = vap->iv_fragthreshold;
2408 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2412 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2413 !(vap->iv_flags & IEEE80211_F_WPA)) {
2416 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2418 arg = NDIS_80211_AUTHMODE_SHARED;
2419 DPRINTF(("Setting shared auth\n"));
2420 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2423 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2424 if (vap->iv_nw_keys[i].wk_keylen) {
2425 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2426 IEEE80211_CIPHER_WEP)
2428 bzero((char *)&wep, sizeof(wep));
2429 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2432 * 5, 13 and 16 are the only valid
2433 * key lengths. Anything in between
2434 * will be zero padded out to the
2435 * next highest boundary.
2437 if (vap->iv_nw_keys[i].wk_keylen < 5)
2439 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2440 vap->iv_nw_keys[i].wk_keylen < 13)
2442 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2443 vap->iv_nw_keys[i].wk_keylen < 16)
2447 wep.nw_length = (sizeof(uint32_t) * 3)
2449 if (i == vap->iv_def_txkey)
2450 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2451 bcopy(vap->iv_nw_keys[i].wk_key,
2452 wep.nw_keydata, wep.nw_length);
2454 DPRINTF(("Setting WEP key %d\n", i));
2455 rval = ndis_set_info(sc,
2456 OID_802_11_ADD_WEP, &wep, &len);
2458 device_printf(sc->ndis_dev,
2459 "set wepkey failed: %d\n", rval);
2464 DPRINTF(("Setting WEP on\n"));
2465 arg = NDIS_80211_WEPSTAT_ENABLED;
2467 rval = ndis_set_info(sc,
2468 OID_802_11_WEP_STATUS, &arg, &len);
2470 device_printf(sc->ndis_dev,
2471 "enable WEP failed: %d\n", rval);
2472 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2473 arg = NDIS_80211_PRIVFILT_8021XWEP;
2475 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2479 OID_802_11_PRIVACY_FILTER, &arg, &len);
2484 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2485 vap->iv_appie_assocreq != NULL) {
2486 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2487 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2489 device_printf(sc->ndis_dev, "WPA setup failed\n");
2493 /* Set network type. */
2497 switch (vap->iv_curmode) {
2498 case IEEE80211_MODE_11A:
2499 arg = NDIS_80211_NETTYPE_11OFDM5;
2501 case IEEE80211_MODE_11B:
2502 arg = NDIS_80211_NETTYPE_11DS;
2504 case IEEE80211_MODE_11G:
2505 arg = NDIS_80211_NETTYPE_11OFDM24;
2508 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2513 DPRINTF(("Setting network type to %d\n", arg));
2515 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2518 device_printf(sc->ndis_dev,
2519 "set nettype failed: %d\n", rval);
2524 * If the user selected a specific BSSID, try
2525 * to use that one. This is useful in the case where
2526 * there are several APs in range with the same network
2527 * name. To delete the BSSID, we use the broadcast
2528 * address as the BSSID.
2529 * Note that some drivers seem to allow setting a BSSID
2530 * in ad-hoc mode, which has the effect of forcing the
2531 * NIC to create an ad-hoc cell with a specific BSSID,
2532 * instead of a randomly chosen one. However, the net80211
2533 * code makes the assumtion that the BSSID setting is invalid
2534 * when you're in ad-hoc mode, so we don't allow that here.
2537 len = IEEE80211_ADDR_LEN;
2538 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2539 vap->iv_opmode != IEEE80211_M_IBSS)
2540 bcopy(ni->ni_bssid, bssid, len);
2542 bcopy(ifp->if_broadcastaddr, bssid, len);
2544 DPRINTF(("Setting BSSID to %s\n", kether_ntoa((uint8_t *)&bssid, ethstr)));
2545 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2547 device_printf(sc->ndis_dev,
2548 "setting BSSID failed: %d\n", rval);
2550 /* Set SSID -- always do this last. */
2553 if (ndis_debug > 0) {
2554 kprintf("Setting ESSID to ");
2555 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2561 bzero((char *)&ssid, len);
2562 ssid.ns_ssidlen = ni->ni_esslen;
2563 if (ssid.ns_ssidlen == 0) {
2564 ssid.ns_ssidlen = 1;
2566 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2568 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2571 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2577 ndis_get_bssid_list(struct ndis_softc *sc, ndis_80211_bssid_list_ex **bl)
2581 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2582 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2586 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2587 if (error == ENOSPC) {
2588 kfree(*bl, M_DEVBUF);
2589 *bl = kmalloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2593 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2596 DPRINTF(("%s: failed to read\n", __func__));
2597 kfree(*bl, M_DEVBUF);
2605 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2607 struct ifnet *ifp = sc->ifp;
2608 struct ieee80211com *ic = ifp->if_l2com;
2609 struct ieee80211vap *vap;
2610 struct ieee80211_node *ni;
2611 ndis_80211_bssid_list_ex *bl;
2612 ndis_wlan_bssid_ex *bs;
2613 ndis_80211_macaddr bssid;
2619 len = sizeof(bssid);
2620 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2622 device_printf(sc->ndis_dev, "failed to get bssid\n");
2626 vap = TAILQ_FIRST(&ic->ic_vaps);
2629 error = ndis_get_bssid_list(sc, &bl);
2633 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2634 for (i = 0; i < bl->nblx_items; i++) {
2635 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2636 *assoc = kmalloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2637 if (*assoc == NULL) {
2641 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2643 if (ic->ic_opmode == IEEE80211_M_STA)
2644 ni->ni_associd = 1 | 0xc000; /* fake associd */
2647 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2655 ndis_getstate_80211(struct ndis_softc *sc)
2657 struct ieee80211com *ic;
2658 struct ieee80211vap *vap;
2659 struct ieee80211_node *ni;
2660 ndis_wlan_bssid_ex *bs;
2661 int rval, len, i = 0;
2668 vap = TAILQ_FIRST(&ic->ic_vaps);
2671 if (!NDIS_INITIALIZED(sc))
2674 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2677 /* We're associated, retrieve info on the current bssid. */
2678 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2679 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2680 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2682 /* Get SSID from current association info. */
2683 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2684 bs->nwbx_ssid.ns_ssidlen);
2685 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2687 if (ic->ic_caps & IEEE80211_C_PMGT) {
2689 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2692 device_printf(sc->ndis_dev,
2693 "get power mode failed: %d\n", rval);
2694 if (arg == NDIS_80211_POWERMODE_CAM)
2695 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2697 vap->iv_flags |= IEEE80211_F_PMGTON;
2701 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2703 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2704 for (i = 0; i < NELEM(dBm2mW); i++)
2705 if (dBm2mW[i] >= arg)
2707 ic->ic_txpowlimit = i;
2711 * Use the current association information to reflect
2712 * what channel we're on.
2714 ic->ic_curchan = ieee80211_find_channel(ic,
2715 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2716 if (ic->ic_curchan == NULL)
2717 ic->ic_curchan = &ic->ic_channels[0];
2718 ni->ni_chan = ic->ic_curchan;
2719 ic->ic_bsschan = ic->ic_curchan;
2724 * Determine current authentication mode.
2727 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2729 device_printf(sc->ndis_dev,
2730 "get authmode status failed: %d\n", rval);
2732 vap->iv_flags &= ~IEEE80211_F_WPA;
2734 case NDIS_80211_AUTHMODE_OPEN:
2735 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2737 case NDIS_80211_AUTHMODE_SHARED:
2738 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2740 case NDIS_80211_AUTHMODE_AUTO:
2741 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2743 case NDIS_80211_AUTHMODE_WPA:
2744 case NDIS_80211_AUTHMODE_WPAPSK:
2745 case NDIS_80211_AUTHMODE_WPANONE:
2746 ni->ni_authmode = IEEE80211_AUTH_WPA;
2747 vap->iv_flags |= IEEE80211_F_WPA1;
2749 case NDIS_80211_AUTHMODE_WPA2:
2750 case NDIS_80211_AUTHMODE_WPA2PSK:
2751 ni->ni_authmode = IEEE80211_AUTH_WPA;
2752 vap->iv_flags |= IEEE80211_F_WPA2;
2755 ni->ni_authmode = IEEE80211_AUTH_NONE;
2761 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2764 device_printf(sc->ndis_dev,
2765 "get wep status failed: %d\n", rval);
2767 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2768 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2770 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2774 ndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
2776 struct ndis_softc *sc = ifp->if_softc;
2777 struct ifreq *ifr = (struct ifreq *) data;
2784 if (ifp->if_flags & IFF_UP) {
2785 if (ifp->if_flags & IFF_RUNNING &&
2786 ifp->if_flags & IFF_PROMISC &&
2787 !(sc->ndis_if_flags & IFF_PROMISC)) {
2789 NDIS_PACKET_TYPE_PROMISCUOUS;
2790 i = sizeof(sc->ndis_filter);
2791 error = ndis_set_info(sc,
2792 OID_GEN_CURRENT_PACKET_FILTER,
2793 &sc->ndis_filter, &i);
2794 } else if (ifp->if_flags & IFF_RUNNING &&
2795 !(ifp->if_flags & IFF_PROMISC) &&
2796 sc->ndis_if_flags & IFF_PROMISC) {
2798 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2799 i = sizeof(sc->ndis_filter);
2800 error = ndis_set_info(sc,
2801 OID_GEN_CURRENT_PACKET_FILTER,
2802 &sc->ndis_filter, &i);
2806 if (ifp->if_flags & IFF_RUNNING)
2809 sc->ndis_if_flags = ifp->if_flags;
2819 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2822 ifp->if_capenable = ifr->ifr_reqcap;
2823 if (ifp->if_capenable & IFCAP_TXCSUM)
2824 ifp->if_hwassist = sc->ndis_hwassist;
2826 ifp->if_hwassist = 0;
2827 ndis_set_offload(sc);
2830 error = ether_ioctl(ifp, command, data);
2834 /*NDIS_UNLOCK(sc);*/
2840 ndis_ioctl_80211(struct ifnet *ifp, u_long command, caddr_t data,
2843 struct ndis_softc *sc = ifp->if_softc;
2844 struct ieee80211com *ic = ifp->if_l2com;
2845 struct ifreq *ifr = (struct ifreq *) data;
2846 struct ndis_oid_data oid;
2847 struct ndis_evt evt;
2854 if (ifp->if_flags & IFF_UP) {
2855 if (!(ifp->if_flags & IFF_RUNNING))
2858 if (ifp->if_flags & IFF_RUNNING)
2861 sc->ndis_if_flags = ifp->if_flags;
2863 /*NDIS_UNLOCK(sc);*/
2866 if ((error = priv_check(curthread, PRIV_DRIVER)))
2868 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2871 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2872 if (oidbuf == NULL) {
2876 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2878 kfree(oidbuf, M_TEMP);
2881 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2883 kfree(oidbuf, M_TEMP);
2886 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2888 kfree(oidbuf, M_TEMP);
2891 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2892 kfree(oidbuf, M_TEMP);
2895 if ((error = priv_check(curthread, PRIV_DRIVER)))
2897 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2900 oidbuf = kmalloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2901 if (oidbuf == NULL) {
2905 error = copyin((caddr_t)ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2907 kfree(oidbuf, M_TEMP);
2910 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2912 kfree(oidbuf, M_TEMP);
2915 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2917 kfree(oidbuf, M_TEMP);
2920 error = copyout(oidbuf, (caddr_t)ifr->ifr_data + sizeof(oid), oid.len);
2921 kfree(oidbuf, M_TEMP);
2923 case SIOCGPRIVATE_0:
2924 if ((error = priv_check(curthread, PRIV_DRIVER)))
2927 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2932 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2937 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2942 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2943 ifr->ifr_data, sizeof(uint32_t) * 2);
2948 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2949 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2950 (caddr_t)ifr->ifr_data + (sizeof(uint32_t) * 2),
2951 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2956 kfree(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2957 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2959 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2960 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2961 NDIS_EVTINC(sc->ndis_evtcidx);
2965 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2968 error = ether_ioctl(ifp, command, data);
2978 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
2980 struct ndis_softc *sc;
2981 ndis_80211_key rkey;
2984 sc = vap->iv_ic->ic_ifp->if_softc;
2986 bzero((char *)&rkey, sizeof(rkey));
2990 rkey.nk_keyidx = key->wk_keyix;
2992 bcopy(vap->iv_ifp->if_broadcastaddr,
2993 rkey.nk_bssid, IEEE80211_ADDR_LEN);
2995 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3004 * In theory this could be called for any key, but we'll
3005 * only use it for WPA TKIP or AES keys. These need to be
3006 * set after initial authentication with the AP.
3009 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
3010 const uint8_t mac[IEEE80211_ADDR_LEN])
3012 struct ndis_softc *sc;
3014 ndis_80211_key rkey;
3017 ifp = vap->iv_ic->ic_ifp;
3020 switch (key->wk_cipher->ic_cipher) {
3021 case IEEE80211_CIPHER_TKIP:
3023 len = sizeof(ndis_80211_key);
3024 bzero((char *)&rkey, sizeof(rkey));
3027 rkey.nk_keylen = key->wk_keylen;
3029 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3030 rkey.nk_keylen += 16;
3032 /* key index - gets weird in NDIS */
3034 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3035 rkey.nk_keyidx = key->wk_keyix;
3039 if (key->wk_flags & IEEE80211_KEY_XMIT)
3040 rkey.nk_keyidx |= 1 << 31;
3042 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3043 bcopy(ifp->if_broadcastaddr,
3044 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3046 bcopy(vap->iv_bss->ni_bssid,
3047 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3049 rkey.nk_keyidx |= 1 << 30;
3052 /* need to set bit 29 based on keyrsc */
3053 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3056 rkey.nk_keyidx |= 1 << 29;
3058 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3059 bcopy(key->wk_key, rkey.nk_keydata, 16);
3060 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3061 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3063 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3065 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3067 case IEEE80211_CIPHER_WEP:
3071 * I don't know how to set up keys for the AES
3072 * cipher yet. Is it the same as TKIP?
3074 case IEEE80211_CIPHER_AES_CCM:
3080 /* We need to return 1 for success, 0 for failure. */
3089 ndis_resettask(device_object *d, void *arg)
3091 struct ndis_softc *sc;
3098 * Stop the adapter and free any mbufs allocated to the
3102 ndis_stop(struct ndis_softc *sc)
3108 callout_stop(&sc->ndis_stat_callout); /* XXX swildner callout_drain() */
3111 sc->ndis_tx_timer = 0;
3113 ifp->if_flags &= ~IFF_RUNNING;
3114 ifq_clr_oactive(&ifp->if_snd);
3117 if (sc->ndis_iftype != PNPBus ||
3118 (sc->ndis_iftype == PNPBus &&
3119 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3124 for (i = 0; i < NDIS_EVENTS; i++) {
3125 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3126 kfree(sc->ndis_evt[i].ne_buf, M_TEMP);
3127 sc->ndis_evt[i].ne_buf = NULL;
3129 sc->ndis_evt[i].ne_sts = 0;
3130 sc->ndis_evt[i].ne_len = 0;
3132 sc->ndis_evtcidx = 0;
3133 sc->ndis_evtpidx = 0;
3138 * Stop all chip I/O so that the kernel's probe routines don't
3139 * get confused by errant DMAs when rebooting.
3142 ndis_shutdown(device_t dev)
3144 struct ndis_softc *sc;
3146 wlan_serialize_enter();
3147 sc = device_get_softc(dev);
3149 wlan_serialize_exit();
3153 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3155 struct ndis_vap *nvp = NDIS_VAP(vap);
3156 struct ieee80211com *ic = vap->iv_ic;
3157 struct ifnet *ifp = ic->ic_ifp;
3158 struct ndis_softc *sc = ifp->if_softc;
3159 enum ieee80211_state ostate;
3161 DPRINTF(("%s: %s -> %s\n", __func__,
3162 ieee80211_state_name[vap->iv_state],
3163 ieee80211_state_name[nstate]));
3165 ostate = vap->iv_state;
3166 vap->iv_state = nstate;
3169 /* pass on to net80211 */
3170 case IEEE80211_S_INIT:
3171 case IEEE80211_S_SCAN:
3172 return nvp->newstate(vap, nstate, arg);
3173 case IEEE80211_S_ASSOC:
3174 if (ostate != IEEE80211_S_AUTH) {
3175 wlan_serialize_exit();
3176 ndis_auth_and_assoc(sc, vap);
3177 wlan_serialize_enter();
3180 case IEEE80211_S_AUTH:
3181 wlan_serialize_exit();
3182 ndis_auth_and_assoc(sc, vap);
3183 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3184 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3185 wlan_serialize_enter();
3194 ndis_scan(void *arg)
3196 struct ieee80211vap *vap = arg;
3198 ieee80211_scan_done(vap);
3202 ndis_scan_results(struct ndis_softc *sc)
3204 struct ieee80211com *ic;
3205 struct ieee80211vap *vap;
3206 ndis_80211_bssid_list_ex *bl;
3207 ndis_wlan_bssid_ex *wb;
3208 struct ieee80211_scanparams sp;
3209 struct ieee80211_frame wh;
3210 struct ieee80211_channel *saved_chan;
3212 int rssi, noise, freq, chanflag;
3213 uint8_t ssid[2+IEEE80211_NWID_LEN];
3214 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3215 uint8_t *frm, *efrm;
3216 char ethstr[ETHER_ADDRSTRLEN + 1];
3218 ic = sc->ifp->if_l2com;
3219 vap = TAILQ_FIRST(&ic->ic_vaps);
3220 saved_chan = ic->ic_curchan;
3223 if (ndis_get_bssid_list(sc, &bl))
3226 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3227 wb = &bl->nblx_bssid[0];
3228 for (i = 0; i < bl->nblx_items; i++) {
3229 memset(&sp, 0, sizeof(sp));
3231 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3232 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3233 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3234 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3235 if (wb->nwbx_privacy)
3236 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3237 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3238 switch (wb->nwbx_netinfra) {
3239 case NDIS_80211_NET_INFRA_IBSS:
3240 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3242 case NDIS_80211_NET_INFRA_BSS:
3243 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3246 sp.rates = &rates[0];
3247 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3248 /* XXX - check units */
3249 if (wb->nwbx_supportedrates[j] == 0)
3252 wb->nwbx_supportedrates[j] & 0x7f;
3256 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3257 wb->nwbx_ssid.ns_ssidlen);
3258 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3260 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3261 freq = wb->nwbx_config.nc_dsconfig / 1000;
3262 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3263 /* Hack ic->ic_curchan to be in sync with the scan result */
3264 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3265 if (ic->ic_curchan == NULL)
3266 ic->ic_curchan = &ic->ic_channels[0];
3268 /* Process extended info from AP */
3269 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3270 frm = (uint8_t *)&wb->nwbx_ies;
3271 efrm = frm + wb->nwbx_ielen;
3272 if (efrm - frm < 12)
3274 sp.tstamp = frm; frm += 8;
3275 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3276 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3278 sp.ies_len = efrm - frm;
3281 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3282 kether_ntoa(wb->nwbx_macaddr, ethstr), freq, sp.bchan, chanflag,
3284 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3285 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3287 kfree(bl, M_DEVBUF);
3288 /* Restore the channel after messing with it */
3289 ic->ic_curchan = saved_chan;
3293 ndis_scan_start(struct ieee80211com *ic)
3295 struct ifnet *ifp = ic->ic_ifp;
3296 struct ndis_softc *sc = ifp->if_softc;
3297 struct ieee80211vap *vap;
3298 struct ieee80211_scan_state *ss;
3299 ndis_80211_ssid ssid;
3303 vap = TAILQ_FIRST(&ic->ic_vaps);
3305 if (!NDIS_INITIALIZED(sc)) {
3306 DPRINTF(("%s: scan aborted\n", __func__));
3307 ieee80211_cancel_scan(vap);
3312 bzero((char *)&ssid, len);
3313 if (ss->ss_nssid == 0)
3314 ssid.ns_ssidlen = 1;
3316 /* Perform a directed scan */
3317 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3318 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3321 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3323 DPRINTF(("%s: set ESSID failed\n", __func__));
3326 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3328 DPRINTF(("%s: scan command failed\n", __func__));
3329 ieee80211_cancel_scan(vap);
3332 /* Set a timer to collect the results */
3333 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3337 ndis_set_channel(struct ieee80211com *ic)
3343 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3349 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3351 /* NB: don't try to abort scan; wait for firmware to finish */
3355 ndis_scan_end(struct ieee80211com *ic)
3357 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3359 ndis_scan_results(sc);