2 * SPDX-License-Identifier: BSD-4-Clause
5 * Bill Paul <wpaul@windriver.com>. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
34 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
35 * then hacked upon mercilessly by my.
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/sockio.h>
45 #include <sys/malloc.h>
46 #include <sys/endian.h>
48 #include <sys/kernel.h>
49 #include <sys/socket.h>
50 #include <sys/queue.h>
51 #include <sys/module.h>
53 #include <sys/sysctl.h>
54 #include <sys/kthread.h>
55 #include <sys/limits.h>
58 #include <net/if_var.h>
59 #include <net/if_arp.h>
60 #include <net/ethernet.h>
61 #include <net/if_dl.h>
62 #include <net/if_media.h>
63 #include <net/if_types.h>
64 #include <net/route.h>
68 #include <machine/bus.h>
69 #include <machine/resource.h>
73 #include <net80211/ieee80211_var.h>
74 #include <net80211/ieee80211_ioctl.h>
75 #include <net80211/ieee80211_regdomain.h>
77 #include <dev/pci/pcireg.h>
78 #include <dev/pci/pcivar.h>
79 #include <dev/usb/usb.h>
80 #include <dev/usb/usbdi.h>
82 #include <compat/ndis/pe_var.h>
83 #include <compat/ndis/cfg_var.h>
84 #include <compat/ndis/resource_var.h>
85 #include <compat/ndis/ntoskrnl_var.h>
86 #include <compat/ndis/hal_var.h>
87 #include <compat/ndis/ndis_var.h>
88 #include <compat/ndis/usbd_var.h>
89 #include <dev/if_ndis/if_ndisvar.h>
93 #define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
95 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
96 "if_ndis debug level");
101 SYSCTL_DECL(_hw_ndisusb);
102 int ndisusb_halt = 1;
103 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
104 "Halt NDIS USB driver when it's attached");
106 /* 0 - 30 dBm to mW conversion table */
107 static const uint16_t dBm2mW[] = {
108 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
109 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
110 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
111 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
112 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
113 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
117 MODULE_DEPEND(ndis, ether, 1, 1, 1);
118 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
119 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
121 MODULE_VERSION(ndis, 1);
123 int ndis_attach (device_t);
124 int ndis_detach (device_t);
125 int ndis_suspend (device_t);
126 int ndis_resume (device_t);
127 void ndis_shutdown (device_t);
129 int ndisdrv_modevent (module_t, int, void *);
131 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
132 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
133 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
134 uint32_t, void *, uint32_t, uint32_t);
135 static void ndis_rxeof_done (ndis_handle);
136 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
137 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
139 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
140 static void ndis_linksts_done (ndis_handle);
142 /* We need to wrap these functions for amd64. */
143 static funcptr ndis_txeof_wrap;
144 static funcptr ndis_rxeof_wrap;
145 static funcptr ndis_rxeof_eth_wrap;
146 static funcptr ndis_rxeof_done_wrap;
147 static funcptr ndis_rxeof_xfr_wrap;
148 static funcptr ndis_rxeof_xfr_done_wrap;
149 static funcptr ndis_linksts_wrap;
150 static funcptr ndis_linksts_done_wrap;
151 static funcptr ndis_ticktask_wrap;
152 static funcptr ndis_ifstarttask_wrap;
153 static funcptr ndis_resettask_wrap;
154 static funcptr ndis_inputtask_wrap;
156 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
157 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
158 const uint8_t [IEEE80211_ADDR_LEN],
159 const uint8_t [IEEE80211_ADDR_LEN]);
160 static void ndis_vap_delete (struct ieee80211vap *);
161 static void ndis_tick (void *);
162 static void ndis_ticktask (device_object *, void *);
163 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
164 const struct ieee80211_bpf_params *);
165 static void ndis_update_mcast (struct ieee80211com *);
166 static void ndis_update_promisc (struct ieee80211com *);
167 static void ndis_ifstart (struct ifnet *);
168 static void ndis_ifstarttask (device_object *, void *);
169 static void ndis_resettask (device_object *, void *);
170 static void ndis_inputtask (device_object *, void *);
171 static int ndis_ifioctl (struct ifnet *, u_long, caddr_t);
172 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
174 static int ndis_nettype_chan (uint32_t);
175 static int ndis_nettype_mode (uint32_t);
176 static void ndis_scan (void *);
177 static void ndis_scan_results (struct ndis_softc *);
178 static void ndis_scan_start (struct ieee80211com *);
179 static void ndis_scan_end (struct ieee80211com *);
180 static void ndis_set_channel (struct ieee80211com *);
181 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
182 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
183 static void ndis_init (void *);
184 static void ndis_stop (struct ndis_softc *);
185 static int ndis_ifmedia_upd (struct ifnet *);
186 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
187 static int ndis_get_bssid_list (struct ndis_softc *,
188 ndis_80211_bssid_list_ex **);
189 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
190 static int ndis_probe_offload (struct ndis_softc *);
191 static int ndis_set_offload (struct ndis_softc *);
192 static void ndis_getstate_80211 (struct ndis_softc *);
193 static void ndis_setstate_80211 (struct ndis_softc *);
194 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
195 static void ndis_media_status (struct ifnet *, struct ifmediareq *);
196 static int ndis_set_cipher (struct ndis_softc *, int);
197 static int ndis_set_wpa (struct ndis_softc *, void *, int);
198 static int ndis_add_key (struct ieee80211vap *,
199 const struct ieee80211_key *);
200 static int ndis_del_key (struct ieee80211vap *,
201 const struct ieee80211_key *);
202 static void ndis_setmulti (struct ndis_softc *);
203 static void ndis_map_sclist (void *, bus_dma_segment_t *,
204 int, bus_size_t, int);
205 static int ndis_ifattach(struct ndis_softc *);
207 static int ndis_80211attach(struct ndis_softc *);
208 static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
209 static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
210 static void ndis_80211parent(struct ieee80211com *);
212 static int ndisdrv_loaded = 0;
215 * This routine should call windrv_load() once for each driver
216 * image. This will do the relocation and dynalinking for the
217 * image, and create a Windows driver object which will be
218 * saved in our driver database.
221 ndisdrv_modevent(mod, cmd, arg)
231 if (ndisdrv_loaded > 1)
233 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
234 3, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
236 8, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
238 1, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
240 4, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
242 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
244 3, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
246 4, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_linksts_done,
248 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
249 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
250 2, WINDRV_WRAP_STDCALL);
251 windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap,
252 2, WINDRV_WRAP_STDCALL);
253 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
254 2, WINDRV_WRAP_STDCALL);
255 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
256 2, WINDRV_WRAP_STDCALL);
260 if (ndisdrv_loaded > 0)
264 windrv_unwrap(ndis_rxeof_wrap);
265 windrv_unwrap(ndis_rxeof_eth_wrap);
266 windrv_unwrap(ndis_rxeof_done_wrap);
267 windrv_unwrap(ndis_rxeof_xfr_wrap);
268 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
269 windrv_unwrap(ndis_txeof_wrap);
270 windrv_unwrap(ndis_linksts_wrap);
271 windrv_unwrap(ndis_linksts_done_wrap);
272 windrv_unwrap(ndis_ticktask_wrap);
273 windrv_unwrap(ndis_ifstarttask_wrap);
274 windrv_unwrap(ndis_resettask_wrap);
275 windrv_unwrap(ndis_inputtask_wrap);
291 ndis_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
293 struct mclist_ctx *ctx = arg;
295 if (cnt < ctx->mclistsz)
296 bcopy(LLADDR(sdl), ctx->mclist + (ETHER_ADDR_LEN * cnt),
302 * Program the 64-bit multicast hash filter.
306 struct ndis_softc *sc;
309 struct mclist_ctx ctx;
313 if (!NDIS_INITIALIZED(sc))
320 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
321 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
322 len = sizeof(sc->ndis_filter);
323 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
324 &sc->ndis_filter, &len);
326 device_printf(sc->ndis_dev,
327 "set allmulti failed: %d\n", error);
331 if (if_llmaddr_count(ifp) == 0)
334 len = sizeof(ctx.mclistsz);
335 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &ctx.mclistsz, &len);
337 ctx.mclist = malloc(ETHER_ADDR_LEN * ctx.mclistsz, M_TEMP,
340 if (ctx.mclist == NULL) {
341 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
345 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
347 len = if_foreach_llmaddr(ifp, ndis_copy_maddr, &ctx);
348 if (len > ctx.mclistsz) {
349 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
350 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
354 len = len * ETHER_ADDR_LEN;
355 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, ctx.mclist, &len);
357 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
358 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
359 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
363 free(ctx.mclist, M_TEMP);
365 len = sizeof(sc->ndis_filter);
366 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
367 &sc->ndis_filter, &len);
369 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
374 struct ndis_softc *sc;
376 ndis_task_offload *nto;
377 ndis_task_offload_hdr *ntoh;
378 ndis_task_tcpip_csum *nttc;
382 if (!NDIS_INITIALIZED(sc))
387 /* See if there's anything to set. */
390 error = ndis_probe_offload(sc);
394 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
397 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
398 sizeof(ndis_task_tcpip_csum);
400 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
405 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
406 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
407 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
408 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
409 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
410 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
412 nto = (ndis_task_offload *)((char *)ntoh +
413 ntoh->ntoh_offset_firsttask);
415 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
416 nto->nto_len = sizeof(ndis_task_offload);
417 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
418 nto->nto_offset_nexttask = 0;
419 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
421 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
423 if (ifp->if_capenable & IFCAP_TXCSUM)
424 nttc->nttc_v4tx = sc->ndis_v4tx;
426 if (ifp->if_capenable & IFCAP_RXCSUM)
427 nttc->nttc_v4rx = sc->ndis_v4rx;
429 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
436 ndis_probe_offload(sc)
437 struct ndis_softc *sc;
439 ndis_task_offload *nto;
440 ndis_task_offload_hdr *ntoh;
441 ndis_task_tcpip_csum *nttc = NULL;
443 int len, error, dummy;
448 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
453 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
458 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
459 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
460 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
461 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
462 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
464 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
471 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
476 nto = (ndis_task_offload *)((char *)ntoh +
477 ntoh->ntoh_offset_firsttask);
480 switch (nto->nto_task) {
481 case NDIS_TASK_TCPIP_CSUM:
482 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
484 /* Don't handle these yet. */
485 case NDIS_TASK_IPSEC:
486 case NDIS_TASK_TCP_LARGESEND:
490 if (nto->nto_offset_nexttask == 0)
492 nto = (ndis_task_offload *)((char *)nto +
493 nto->nto_offset_nexttask);
501 sc->ndis_v4tx = nttc->nttc_v4tx;
502 sc->ndis_v4rx = nttc->nttc_v4rx;
504 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
505 sc->ndis_hwassist |= CSUM_IP;
506 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
507 sc->ndis_hwassist |= CSUM_TCP;
508 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
509 sc->ndis_hwassist |= CSUM_UDP;
511 if (sc->ndis_hwassist)
512 ifp->if_capabilities |= IFCAP_TXCSUM;
514 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
515 ifp->if_capabilities |= IFCAP_RXCSUM;
516 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
517 ifp->if_capabilities |= IFCAP_RXCSUM;
518 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
519 ifp->if_capabilities |= IFCAP_RXCSUM;
526 ndis_nettype_chan(uint32_t type)
529 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
530 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
531 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
532 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
534 DPRINTF(("unknown channel nettype %d\n", type));
535 return (IEEE80211_CHAN_B); /* Default to 11B chan */
539 ndis_nettype_mode(uint32_t type)
542 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
543 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
544 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
545 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
547 DPRINTF(("unknown mode nettype %d\n", type));
548 return (IEEE80211_MODE_AUTO);
552 * Attach the interface. Allocate softc structures, do ifmedia
553 * setup and ethernet/BPF attach.
556 ndis_attach(device_t dev)
558 struct ndis_softc *sc;
564 sc = device_get_softc(dev);
566 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
568 KeInitializeSpinLock(&sc->ndis_rxlock);
569 KeInitializeSpinLock(&sc->ndisusb_tasklock);
570 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
571 InitializeListHead(&sc->ndis_shlist);
572 InitializeListHead(&sc->ndisusb_tasklist);
573 InitializeListHead(&sc->ndisusb_xferdonelist);
574 callout_init(&sc->ndis_stat_callout, 1);
575 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
577 /* Create sysctl registry nodes */
578 ndis_create_sysctls(sc);
580 /* Find the PDO for this device instance. */
582 if (sc->ndis_iftype == PCIBus)
583 pdrv = windrv_lookup(0, "PCI Bus");
584 else if (sc->ndis_iftype == PCMCIABus)
585 pdrv = windrv_lookup(0, "PCCARD Bus");
587 pdrv = windrv_lookup(0, "USB Bus");
588 pdo = windrv_find_pdo(pdrv, dev);
591 * Create a new functional device object for this
592 * device. This is what creates the miniport block
593 * for this device instance.
596 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
597 device_printf(dev, "failed to create FDO!\n");
602 /* Tell the user what version of the API the driver is using. */
603 device_printf(dev, "NDIS API version: %d.%d\n",
604 sc->ndis_chars->nmc_version_major,
605 sc->ndis_chars->nmc_version_minor);
607 /* Do resource conversion. */
608 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
609 ndis_convert_res(sc);
611 sc->ndis_block->nmb_rlist = NULL;
613 /* Install our RX and TX interrupt handlers. */
614 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
615 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
616 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
617 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
618 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
620 /* Override the status handler so we can detect link changes. */
621 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
622 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
624 /* Set up work item handlers. */
625 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
627 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
628 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
629 sc->ndisusb_xferdoneitem =
630 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
631 sc->ndisusb_taskitem =
632 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
633 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
635 /* Call driver's init routine. */
636 if (ndis_init_nic(sc)) {
637 device_printf(dev, "init handler failed\n");
643 * Figure out how big to make the TX buffer pool.
645 len = sizeof(sc->ndis_maxpkts);
646 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
647 &sc->ndis_maxpkts, &len)) {
648 device_printf(dev, "failed to get max TX packets\n");
654 * If this is a deserialized miniport, we don't have
655 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
657 if (!NDIS_SERIALIZED(sc->ndis_block))
658 sc->ndis_maxpkts = NDIS_TXPKTS;
660 /* Enforce some sanity, just in case. */
662 if (sc->ndis_maxpkts == 0)
663 sc->ndis_maxpkts = 10;
665 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
666 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
668 /* Allocate a pool of ndis_packets for TX encapsulation. */
670 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
671 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
673 if (i != NDIS_STATUS_SUCCESS) {
674 sc->ndis_txpool = NULL;
675 device_printf(dev, "failed to allocate TX packet pool");
680 sc->ndis_txpending = sc->ndis_maxpkts;
683 /* Get supported oid list. */
684 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
686 /* If the NDIS module requested scatter/gather, init maps. */
691 * See if the OID_802_11_CONFIGURATION OID is
692 * supported by this driver. If it is, then this an 802.11
693 * wireless driver, and we should set up media for wireless.
695 for (i = 0; i < sc->ndis_oidcnt; i++)
696 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
702 error = ndis_80211attach(sc);
704 error = ndis_ifattach(sc);
712 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
715 DPRINTF(("attach done.\n"));
716 /* We're done talking to the NIC for now; halt it. */
718 DPRINTF(("halting done.\n"));
724 ndis_80211attach(struct ndis_softc *sc)
726 struct ieee80211com *ic = &sc->ndis_ic;
727 ndis_80211_rates_ex rates;
728 struct ndis_80211_nettype_list *ntl;
730 int mode, i, r, len, nonettypes = 1;
731 uint8_t bands[IEEE80211_MODE_BYTES] = { 0 };
733 callout_init(&sc->ndis_scan_callout, 1);
736 ic->ic_ioctl = ndis_80211ioctl;
737 ic->ic_name = device_get_nameunit(sc->ndis_dev);
738 ic->ic_opmode = IEEE80211_M_STA;
739 ic->ic_phytype = IEEE80211_T_DS;
740 ic->ic_caps = IEEE80211_C_8023ENCAP |
741 IEEE80211_C_STA | IEEE80211_C_IBSS;
742 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
744 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
747 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
748 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
754 for (i = 0; i < ntl->ntl_items; i++) {
755 mode = ndis_nettype_mode(ntl->ntl_type[i]);
758 setbit(ic->ic_modecaps, mode);
761 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
766 /* Default to 11b channels if the card did not supply any */
768 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
769 setbit(bands, IEEE80211_MODE_11B);
772 bzero((char *)&rates, len);
773 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
775 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
777 * Since the supported rates only up to 8 can be supported,
778 * if this is not 802.11b we're just going to be faking it
782 #define TESTSETRATE(x, y) \
785 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
786 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
789 if (i == ic->ic_sup_rates[x].rs_nrates) { \
790 ic->ic_sup_rates[x].rs_rates[i] = (y); \
791 ic->ic_sup_rates[x].rs_nrates++; \
795 #define SETRATE(x, y) \
796 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
798 ic->ic_sup_rates[x].rs_nrates++
800 ic->ic_curmode = IEEE80211_MODE_AUTO;
801 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
802 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
803 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
804 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
805 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
806 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
807 for (i = 0; i < len; i++) {
808 switch (rates[i] & IEEE80211_RATE_VAL) {
814 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
815 /* Lazy-init 802.11b. */
816 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
817 ic->ic_sup_rates[IEEE80211_MODE_11B].
820 SETRATE(IEEE80211_MODE_11B, rates[i]);
821 INCRATE(IEEE80211_MODE_11B);
824 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
825 SETRATE(IEEE80211_MODE_11A, rates[i]);
826 INCRATE(IEEE80211_MODE_11A);
828 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
829 SETRATE(IEEE80211_MODE_11G, rates[i]);
830 INCRATE(IEEE80211_MODE_11G);
837 * If the hardware supports 802.11g, it most
838 * likely supports 802.11b and all of the
839 * 802.11b and 802.11g speeds, so maybe we can
840 * just cheat here. Just how in the heck do
841 * we detect turbo modes, though?
843 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
844 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
845 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
846 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
847 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
849 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
850 TESTSETRATE(IEEE80211_MODE_11G, 48);
851 TESTSETRATE(IEEE80211_MODE_11G, 72);
852 TESTSETRATE(IEEE80211_MODE_11G, 96);
853 TESTSETRATE(IEEE80211_MODE_11G, 108);
855 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
856 TESTSETRATE(IEEE80211_MODE_11A, 48);
857 TESTSETRATE(IEEE80211_MODE_11A, 72);
858 TESTSETRATE(IEEE80211_MODE_11A, 96);
859 TESTSETRATE(IEEE80211_MODE_11A, 108);
866 ieee80211_init_channels(ic, NULL, bands);
869 * To test for WPA support, we need to see if we can
870 * set AUTHENTICATION_MODE to WPA and read it back
874 arg = NDIS_80211_AUTHMODE_WPA;
875 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
877 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
878 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
879 ic->ic_caps |= IEEE80211_C_WPA;
883 * To test for supported ciphers, we set each
884 * available encryption type in descending order.
885 * If ENC3 works, then we have WEP, TKIP and AES.
886 * If only ENC2 works, then we have WEP and TKIP.
887 * If only ENC1 works, then we have just WEP.
890 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
891 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
893 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
894 | IEEE80211_CRYPTO_TKIP
895 | IEEE80211_CRYPTO_AES_CCM;
898 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
899 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
901 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
902 | IEEE80211_CRYPTO_TKIP;
905 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
906 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
908 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
911 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
913 ic->ic_caps |= IEEE80211_C_PMGT;
915 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
917 ic->ic_caps |= IEEE80211_C_TXPMGT;
920 * Get station address from the driver.
922 len = sizeof(ic->ic_macaddr);
923 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
925 ieee80211_ifattach(ic);
926 ic->ic_raw_xmit = ndis_raw_xmit;
927 ic->ic_scan_start = ndis_scan_start;
928 ic->ic_scan_end = ndis_scan_end;
929 ic->ic_set_channel = ndis_set_channel;
930 ic->ic_scan_curchan = ndis_scan_curchan;
931 ic->ic_scan_mindwell = ndis_scan_mindwell;
932 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
933 ic->ic_vap_create = ndis_vap_create;
934 ic->ic_vap_delete = ndis_vap_delete;
935 ic->ic_update_mcast = ndis_update_mcast;
936 ic->ic_update_promisc = ndis_update_promisc;
937 ic->ic_transmit = ndis_80211transmit;
938 ic->ic_parent = ndis_80211parent;
941 ieee80211_announce(ic);
947 ndis_ifattach(struct ndis_softc *sc)
950 u_char eaddr[ETHER_ADDR_LEN];
953 ifp = if_alloc(IFT_ETHER);
959 /* Check for task offload support. */
960 ndis_probe_offload(sc);
963 * Get station address from the driver.
966 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
968 if_initname(ifp, device_get_name(sc->ndis_dev),
969 device_get_unit(sc->ndis_dev));
970 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
971 ifp->if_ioctl = ndis_ifioctl;
972 ifp->if_start = ndis_ifstart;
973 ifp->if_init = ndis_init;
974 ifp->if_baudrate = 10000000;
975 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
976 ifp->if_snd.ifq_drv_maxlen = 25;
977 IFQ_SET_READY(&ifp->if_snd);
978 ifp->if_capenable = ifp->if_capabilities;
979 ifp->if_hwassist = sc->ndis_hwassist;
981 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
983 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
984 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
985 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
986 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
987 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
988 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
989 ether_ifattach(ifp, eaddr);
994 static struct ieee80211vap *
995 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
996 enum ieee80211_opmode opmode, int flags,
997 const uint8_t bssid[IEEE80211_ADDR_LEN],
998 const uint8_t mac[IEEE80211_ADDR_LEN])
1000 struct ndis_vap *nvp;
1001 struct ieee80211vap *vap;
1003 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1005 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1007 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1008 /* override with driver methods */
1009 nvp->newstate = vap->iv_newstate;
1010 vap->iv_newstate = ndis_newstate;
1012 /* complete setup */
1013 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1015 ic->ic_opmode = opmode;
1016 /* install key handing routines */
1017 vap->iv_key_set = ndis_add_key;
1018 vap->iv_key_delete = ndis_del_key;
1023 ndis_vap_delete(struct ieee80211vap *vap)
1025 struct ndis_vap *nvp = NDIS_VAP(vap);
1026 struct ieee80211com *ic = vap->iv_ic;
1027 struct ndis_softc *sc = ic->ic_softc;
1030 callout_drain(&sc->ndis_scan_callout);
1031 ieee80211_vap_detach(vap);
1032 free(nvp, M_80211_VAP);
1036 * Shutdown hardware and free up resources. This can be called any
1037 * time after the mutex has been initialized. It is called in both
1038 * the error case in attach and the normal detach case so it needs
1039 * to be careful about only freeing resources that have actually been
1043 ndis_detach(device_t dev)
1046 struct ndis_softc *sc;
1049 sc = device_get_softc(dev);
1051 if (!sc->ndis_80211)
1056 ifp->if_flags &= ~IFF_UP;
1057 if (device_is_attached(dev)) {
1061 ieee80211_ifdetach(&sc->ndis_ic);
1062 else if (ifp != NULL)
1063 ether_ifdetach(ifp);
1067 if (sc->ndis_tickitem != NULL)
1068 IoFreeWorkItem(sc->ndis_tickitem);
1069 if (sc->ndis_startitem != NULL)
1070 IoFreeWorkItem(sc->ndis_startitem);
1071 if (sc->ndis_resetitem != NULL)
1072 IoFreeWorkItem(sc->ndis_resetitem);
1073 if (sc->ndis_inputitem != NULL)
1074 IoFreeWorkItem(sc->ndis_inputitem);
1075 if (sc->ndisusb_xferdoneitem != NULL)
1076 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1077 if (sc->ndisusb_taskitem != NULL)
1078 IoFreeWorkItem(sc->ndisusb_taskitem);
1080 bus_generic_detach(dev);
1081 ndis_unload_driver(sc);
1084 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1085 if (sc->ndis_res_io)
1086 bus_release_resource(dev, SYS_RES_IOPORT,
1087 sc->ndis_io_rid, sc->ndis_res_io);
1088 if (sc->ndis_res_mem)
1089 bus_release_resource(dev, SYS_RES_MEMORY,
1090 sc->ndis_mem_rid, sc->ndis_res_mem);
1091 if (sc->ndis_res_altmem)
1092 bus_release_resource(dev, SYS_RES_MEMORY,
1093 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1099 ndis_destroy_dma(sc);
1101 if (sc->ndis_txarray)
1102 free(sc->ndis_txarray, M_DEVBUF);
1104 if (!sc->ndis_80211)
1105 ifmedia_removeall(&sc->ifmedia);
1107 if (sc->ndis_txpool != NULL)
1108 NdisFreePacketPool(sc->ndis_txpool);
1110 /* Destroy the PDO for this device. */
1112 if (sc->ndis_iftype == PCIBus)
1113 drv = windrv_lookup(0, "PCI Bus");
1114 else if (sc->ndis_iftype == PCMCIABus)
1115 drv = windrv_lookup(0, "PCCARD Bus");
1117 drv = windrv_lookup(0, "USB Bus");
1119 panic("couldn't find driver object");
1120 windrv_destroy_pdo(drv, dev);
1122 if (sc->ndis_iftype == PCIBus)
1123 bus_dma_tag_destroy(sc->ndis_parent_tag);
1132 struct ndis_softc *sc;
1135 sc = device_get_softc(dev);
1139 if (NDIS_INITIALIZED(sc))
1150 struct ndis_softc *sc;
1153 sc = device_get_softc(dev);
1156 if (NDIS_INITIALIZED(sc))
1163 * The following bunch of routines are here to support drivers that
1164 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1165 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1166 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1170 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1171 ndis_handle adapter;
1177 uint32_t lookaheadlen;
1180 ndis_miniport_block *block;
1190 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1194 /* Save the data provided to us so far. */
1196 m->m_len = lookaheadlen + hdrlen;
1197 m->m_pkthdr.len = pktlen + hdrlen;
1199 m_copyback(m, 0, hdrlen, hdr);
1200 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1202 /* Now create a fake NDIS_PACKET to hold the data */
1204 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1206 if (status != NDIS_STATUS_SUCCESS) {
1213 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1221 p->np_private.npp_head = p->np_private.npp_tail = b;
1222 p->np_private.npp_totlen = m->m_pkthdr.len;
1224 /* Save the packet RX context somewhere. */
1225 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1226 priv->nep_ctx = ctx;
1228 if (!NDIS_SERIALIZED(block))
1229 KeAcquireSpinLock(&block->nmb_lock, &irql);
1231 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1233 if (!NDIS_SERIALIZED(block))
1234 KeReleaseSpinLock(&block->nmb_lock, irql);
1238 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1243 ndis_rxeof_done(adapter)
1244 ndis_handle adapter;
1246 struct ndis_softc *sc;
1247 ndis_miniport_block *block;
1251 /* Schedule transfer/RX of queued packets. */
1253 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1255 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1259 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1262 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1264 ndis_handle adapter;
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 mbufq_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, sc);
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(adapter, packet, status, len)
1337 ndis_handle adapter;
1338 ndis_packet *packet;
1342 ndis_miniport_block *block;
1343 struct ndis_softc *sc;
1348 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1352 IoFreeMdl(packet->np_private.npp_head);
1353 NdisFreePacket(packet);
1355 if (status != NDIS_STATUS_SUCCESS) {
1360 m->m_len = m->m_pkthdr.len;
1361 m->m_pkthdr.rcvif = ifp;
1362 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1363 mbufq_enqueue(&sc->ndis_rxqueue, m);
1364 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1365 IoQueueWorkItem(sc->ndis_inputitem,
1366 (io_workitem_func)ndis_inputtask_wrap,
1367 WORKQUEUE_CRITICAL, sc);
1370 * A frame has been uploaded: pass the resulting mbuf chain up to
1371 * the higher level protocols.
1373 * When handling received NDIS packets, the 'status' field in the
1374 * out-of-band portion of the ndis_packet has special meaning. In the
1375 * most common case, the underlying NDIS driver will set this field
1376 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1377 * take possession of it. We then change the status field to
1378 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1379 * and that we will return it at some point in the future via the
1380 * return packet handler.
1382 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1383 * this means the driver is running out of packet/buffer resources and
1384 * wants to maintain ownership of the packet. In this case, we have to
1385 * copy the packet data into local storage and let the driver keep the
1389 ndis_rxeof(adapter, packets, pktcnt)
1390 ndis_handle adapter;
1391 ndis_packet **packets;
1394 struct ndis_softc *sc;
1395 ndis_miniport_block *block;
1398 ndis_tcpip_csum *csum;
1400 struct mbuf *m0, *m;
1403 block = (ndis_miniport_block *)adapter;
1404 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1408 * There's a slim chance the driver may indicate some packets
1409 * before we're completely ready to handle them. If we detect this,
1410 * we need to return them to the miniport and ignore them.
1412 if (!sc->ndis_running) {
1413 for (i = 0; i < pktcnt; i++) {
1415 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1417 ndis_return_packet(p);
1423 for (i = 0; i < pktcnt; i++) {
1425 /* Stash the softc here so ptom can use it. */
1427 if (ndis_ptom(&m0, p)) {
1428 device_printf(sc->ndis_dev, "ptom failed\n");
1429 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1430 ndis_return_packet(p);
1433 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1434 m = m_dup(m0, M_NOWAIT);
1436 * NOTE: we want to destroy the mbuf here, but
1437 * we don't actually want to return it to the
1438 * driver via the return packet handler. By
1439 * bumping np_refcnt, we can prevent the
1440 * ndis_return_packet() routine from actually
1446 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1452 m = m_dup(m0, M_NOWAIT);
1453 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1456 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1459 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1463 m0->m_pkthdr.rcvif = ifp;
1465 /* Deal with checksum offload. */
1467 if (ifp->if_capenable & IFCAP_RXCSUM &&
1468 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1470 p->np_ext.npe_info[ndis_tcpipcsum_info];
1471 csum = (ndis_tcpip_csum *)&s;
1472 if (csum->u.ntc_rxflags &
1473 NDIS_RXCSUM_IP_PASSED)
1474 m0->m_pkthdr.csum_flags |=
1475 CSUM_IP_CHECKED|CSUM_IP_VALID;
1476 if (csum->u.ntc_rxflags &
1477 (NDIS_RXCSUM_TCP_PASSED |
1478 NDIS_RXCSUM_UDP_PASSED)) {
1479 m0->m_pkthdr.csum_flags |=
1480 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1481 m0->m_pkthdr.csum_data = 0xFFFF;
1485 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1486 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1487 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1488 IoQueueWorkItem(sc->ndis_inputitem,
1489 (io_workitem_func)ndis_inputtask_wrap,
1490 WORKQUEUE_CRITICAL, sc);
1496 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1497 * packets into the stack in order to avoid calling (*ifp->if_input)()
1498 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1499 * 'dispatch level' per-cpu sleep lock).
1502 ndis_inputtask(device_object *dobj, void *arg)
1504 ndis_miniport_block *block;
1505 struct ndis_softc *sc = arg;
1509 block = dobj->do_devext;
1511 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1512 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1513 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1514 if ((sc->ndis_80211 != 0)) {
1515 struct ieee80211com *ic = &sc->ndis_ic;
1516 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1519 vap->iv_deliver_data(vap, vap->iv_bss, m);
1521 struct ifnet *ifp = sc->ifp;
1523 (*ifp->if_input)(ifp, m);
1525 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1527 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1531 * A frame was downloaded to the chip. It's safe for us to clean up
1535 ndis_txeof(adapter, packet, status)
1536 ndis_handle adapter;
1537 ndis_packet *packet;
1541 struct ndis_softc *sc;
1542 ndis_miniport_block *block;
1547 block = (ndis_miniport_block *)adapter;
1548 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1552 idx = packet->np_txidx;
1554 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1556 ndis_free_packet(packet);
1560 sc->ndis_txarray[idx] = NULL;
1561 sc->ndis_txpending++;
1563 if (!sc->ndis_80211) {
1564 struct ifnet *ifp = sc->ifp;
1565 if (status == NDIS_STATUS_SUCCESS)
1566 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1568 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1569 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1571 sc->ndis_tx_timer = 0;
1575 if (!sc->ndis_80211)
1576 IoQueueWorkItem(sc->ndis_startitem,
1577 (io_workitem_func)ndis_ifstarttask_wrap,
1578 WORKQUEUE_CRITICAL, sc);
1579 DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1583 ndis_linksts(adapter, status, sbuf, slen)
1584 ndis_handle adapter;
1589 ndis_miniport_block *block;
1590 struct ndis_softc *sc;
1593 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1594 sc->ndis_sts = status;
1596 /* Event list is all full up, drop this one. */
1599 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1604 /* Cache the event. */
1607 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1609 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1614 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1616 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1617 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1618 NDIS_EVTINC(sc->ndis_evtpidx);
1623 ndis_linksts_done(adapter)
1624 ndis_handle adapter;
1626 ndis_miniport_block *block;
1627 struct ndis_softc *sc;
1631 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1634 if (!NDIS_INITIALIZED(sc))
1637 switch (sc->ndis_sts) {
1638 case NDIS_STATUS_MEDIA_CONNECT:
1639 IoQueueWorkItem(sc->ndis_tickitem,
1640 (io_workitem_func)ndis_ticktask_wrap,
1641 WORKQUEUE_CRITICAL, sc);
1642 if (!sc->ndis_80211)
1643 IoQueueWorkItem(sc->ndis_startitem,
1644 (io_workitem_func)ndis_ifstarttask_wrap,
1645 WORKQUEUE_CRITICAL, sc);
1647 case NDIS_STATUS_MEDIA_DISCONNECT:
1649 IoQueueWorkItem(sc->ndis_tickitem,
1650 (io_workitem_func)ndis_ticktask_wrap,
1651 WORKQUEUE_CRITICAL, sc);
1662 struct ndis_softc *sc;
1666 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1667 IoQueueWorkItem(sc->ndis_tickitem,
1668 (io_workitem_func)ndis_ticktask_wrap,
1669 WORKQUEUE_CRITICAL, sc);
1670 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1673 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1674 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1675 device_printf(sc->ndis_dev, "watchdog timeout\n");
1677 IoQueueWorkItem(sc->ndis_resetitem,
1678 (io_workitem_func)ndis_resettask_wrap,
1679 WORKQUEUE_CRITICAL, sc);
1680 if (!sc->ndis_80211)
1681 IoQueueWorkItem(sc->ndis_startitem,
1682 (io_workitem_func)ndis_ifstarttask_wrap,
1683 WORKQUEUE_CRITICAL, sc);
1686 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1690 ndis_ticktask(device_object *d, void *xsc)
1692 struct ndis_softc *sc = xsc;
1693 ndis_checkforhang_handler hangfunc;
1697 if (!NDIS_INITIALIZED(sc)) {
1703 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1705 if (hangfunc != NULL) {
1706 rval = MSCALL1(hangfunc,
1707 sc->ndis_block->nmb_miniportadapterctx);
1715 if (sc->ndis_link == 0 &&
1716 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1718 if (sc->ndis_80211 != 0) {
1719 struct ieee80211com *ic = &sc->ndis_ic;
1720 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1724 ndis_getstate_80211(sc);
1725 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1727 if_link_state_change(vap->iv_ifp,
1731 if_link_state_change(sc->ifp, LINK_STATE_UP);
1734 if (sc->ndis_link == 1 &&
1735 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1737 if (sc->ndis_80211 != 0) {
1738 struct ieee80211com *ic = &sc->ndis_ic;
1739 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1743 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1745 if_link_state_change(vap->iv_ifp,
1749 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1756 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1758 bus_dma_segment_t *segs;
1764 struct ndis_sc_list *sclist;
1767 if (error || arg == NULL)
1772 sclist->nsl_frags = nseg;
1774 for (i = 0; i < nseg; i++) {
1775 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1776 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1781 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1782 const struct ieee80211_bpf_params *params)
1784 /* no support; just discard */
1786 ieee80211_free_node(ni);
1791 ndis_update_mcast(struct ieee80211com *ic)
1793 struct ndis_softc *sc = ic->ic_softc;
1799 ndis_update_promisc(struct ieee80211com *ic)
1805 ndis_ifstarttask(device_object *d, void *arg)
1807 struct ndis_softc *sc = arg;
1808 DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1812 struct ifnet *ifp = sc->ifp;
1813 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1818 * Main transmit routine. To make NDIS drivers happy, we need to
1819 * transform mbuf chains into NDIS packets and feed them to the
1820 * send packet routines. Most drivers allow you to send several
1821 * packets at once (up to the maxpkts limit). Unfortunately, rather
1822 * that accepting them in the form of a linked list, they expect
1823 * a contiguous array of pointers to packets.
1825 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1826 * we need to perform busdma work here. Those that use map registers
1827 * will do the mapping themselves on a buffer by buffer basis.
1830 ndis_ifstart(struct ifnet *ifp)
1832 struct ndis_softc *sc;
1833 struct mbuf *m = NULL;
1834 ndis_packet **p0 = NULL, *p = NULL;
1835 ndis_tcpip_csum *csum;
1836 int pcnt = 0, status;
1841 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1846 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1848 while(sc->ndis_txpending) {
1849 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1853 NdisAllocatePacket(&status,
1854 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1856 if (status != NDIS_STATUS_SUCCESS)
1859 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1860 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1866 * Save pointer to original mbuf
1867 * so we can free it later.
1870 p = sc->ndis_txarray[sc->ndis_txidx];
1871 p->np_txidx = sc->ndis_txidx;
1873 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1876 * Do scatter/gather processing, if driver requested it.
1879 bus_dmamap_load_mbuf(sc->ndis_ttag,
1880 sc->ndis_tmaps[sc->ndis_txidx], m,
1881 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1882 bus_dmamap_sync(sc->ndis_ttag,
1883 sc->ndis_tmaps[sc->ndis_txidx],
1884 BUS_DMASYNC_PREREAD);
1885 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1888 /* Handle checksum offload. */
1890 if (ifp->if_capenable & IFCAP_TXCSUM &&
1891 m->m_pkthdr.csum_flags) {
1892 csum = (ndis_tcpip_csum *)
1893 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1894 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1895 if (m->m_pkthdr.csum_flags & CSUM_IP)
1896 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1897 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1898 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1899 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1900 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1901 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1905 sc->ndis_txpending--;
1910 * If there's a BPF listener, bounce a copy of this frame
1913 if (!sc->ndis_80211) /* XXX handle 80211 */
1917 * The array that p0 points to must appear contiguous,
1918 * so we must not wrap past the end of sc->ndis_txarray[].
1919 * If it looks like we're about to wrap, break out here
1920 * so the this batch of packets can be transmitted, then
1921 * wait for txeof to ask us to send the rest.
1923 if (sc->ndis_txidx == 0)
1932 if (sc->ndis_txpending == 0)
1933 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1936 * Set a timeout in case the chip goes out to lunch.
1938 sc->ndis_tx_timer = 5;
1943 * According to NDIS documentation, if a driver exports
1944 * a MiniportSendPackets() routine, we prefer that over
1945 * a MiniportSend() routine (which sends just a single
1948 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1949 ndis_send_packets(sc, p0, pcnt);
1951 ndis_send_packet(sc, p);
1957 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1959 struct ndis_softc *sc = ic->ic_softc;
1960 ndis_packet **p0 = NULL, *p = NULL;
1964 if (!sc->ndis_link || !sc->ndis_running) {
1969 if (sc->ndis_txpending == 0) {
1974 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1976 NdisAllocatePacket(&status,
1977 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1979 if (status != NDIS_STATUS_SUCCESS) {
1984 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1990 * Save pointer to original mbuf
1991 * so we can free it later.
1994 p = sc->ndis_txarray[sc->ndis_txidx];
1995 p->np_txidx = sc->ndis_txidx;
1997 p->np_oob.npo_status = NDIS_STATUS_PENDING;
2000 * Do scatter/gather processing, if driver requested it.
2003 bus_dmamap_load_mbuf(sc->ndis_ttag,
2004 sc->ndis_tmaps[sc->ndis_txidx], m,
2005 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2006 bus_dmamap_sync(sc->ndis_ttag,
2007 sc->ndis_tmaps[sc->ndis_txidx],
2008 BUS_DMASYNC_PREREAD);
2009 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2013 sc->ndis_txpending--;
2016 * Set a timeout in case the chip goes out to lunch.
2018 sc->ndis_tx_timer = 5;
2022 * According to NDIS documentation, if a driver exports
2023 * a MiniportSendPackets() routine, we prefer that over
2024 * a MiniportSend() routine (which sends just a single
2027 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2028 ndis_send_packets(sc, p0, 1);
2030 ndis_send_packet(sc, p);
2036 ndis_80211parent(struct ieee80211com *ic)
2038 struct ndis_softc *sc = ic->ic_softc;
2041 if (ic->ic_nrunning > 0) {
2042 if (!sc->ndis_running)
2044 } else if (sc->ndis_running)
2046 /*NDIS_UNLOCK(sc);*/
2050 ndis_init(void *xsc)
2052 struct ndis_softc *sc = xsc;
2056 * Avoid reintializing the link unnecessarily.
2057 * This should be dealt with in a better way by
2058 * fixing the upper layer modules so they don't
2059 * call ifp->if_init() quite as often.
2065 * Cancel pending I/O and free all RX/TX buffers.
2069 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2070 error = ndis_init_nic(sc);
2072 device_printf(sc->ndis_dev,
2073 "failed to initialize the device: %d\n", error);
2078 /* Program the packet filter */
2079 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2080 NDIS_PACKET_TYPE_BROADCAST;
2082 if (sc->ndis_80211) {
2083 struct ieee80211com *ic = &sc->ndis_ic;
2085 if (ic->ic_promisc > 0)
2086 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2088 struct ifnet *ifp = sc->ifp;
2090 if (ifp->if_flags & IFF_PROMISC)
2091 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2094 len = sizeof(sc->ndis_filter);
2096 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2097 &sc->ndis_filter, &len);
2100 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2108 i = sc->ifp->if_mtu;
2110 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2113 * Program the multicast filter, if necessary.
2117 /* Setup task offload. */
2118 ndis_set_offload(sc);
2123 sc->ndis_txpending = sc->ndis_maxpkts;
2126 if (!sc->ndis_80211) {
2127 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2128 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2129 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2132 sc->ndis_tx_timer = 0;
2135 * Some drivers don't set this value. The NDIS spec says
2136 * the default checkforhang timeout is "approximately 2
2137 * seconds." We use 3 seconds, because it seems for some
2138 * drivers, exactly 2 seconds is too fast.
2140 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2141 sc->ndis_block->nmb_checkforhangsecs = 3;
2143 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2144 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2145 sc->ndis_running = 1;
2148 /* XXX force handling */
2150 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2154 * Set media options.
2157 ndis_ifmedia_upd(ifp)
2160 struct ndis_softc *sc;
2164 if (NDIS_INITIALIZED(sc))
2171 * Report current media status.
2174 ndis_ifmedia_sts(ifp, ifmr)
2176 struct ifmediareq *ifmr;
2178 struct ndis_softc *sc;
2179 uint32_t media_info;
2180 ndis_media_state linkstate;
2183 ifmr->ifm_status = IFM_AVALID;
2184 ifmr->ifm_active = IFM_ETHER;
2187 if (!NDIS_INITIALIZED(sc))
2190 len = sizeof(linkstate);
2191 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2192 (void *)&linkstate, &len);
2194 len = sizeof(media_info);
2195 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2196 (void *)&media_info, &len);
2198 if (linkstate == nmc_connected)
2199 ifmr->ifm_status |= IFM_ACTIVE;
2201 switch (media_info) {
2203 ifmr->ifm_active |= IFM_10_T;
2206 ifmr->ifm_active |= IFM_100_TX;
2209 ifmr->ifm_active |= IFM_1000_T;
2212 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2218 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2220 struct ieee80211com *ic = &sc->ndis_ic;
2226 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2227 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2229 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2232 if (cipher == WPA_CSE_TKIP) {
2233 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2235 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2238 if (cipher == WPA_CSE_CCMP) {
2239 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2241 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2244 DPRINTF(("Setting cipher to %d\n", arg));
2246 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2251 /* Check that the cipher was set correctly. */
2254 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2256 if (rval != 0 || arg != save)
2263 * WPA is hairy to set up. Do the work in a separate routine
2264 * so we don't clutter the setstate function too much.
2265 * Important yet undocumented fact: first we have to set the
2266 * authentication mode, _then_ we enable the ciphers. If one
2267 * of the WPA authentication modes isn't enabled, the driver
2268 * might not permit the TKIP or AES ciphers to be selected.
2271 ndis_set_wpa(sc, ie, ielen)
2272 struct ndis_softc *sc;
2276 struct ieee80211_ie_wpa *w;
2283 * Apparently, the only way for us to know what ciphers
2284 * and key management/authentication mode to use is for
2285 * us to inspect the optional information element (IE)
2286 * stored in the 802.11 state machine. This IE should be
2287 * supplied by the WPA supplicant.
2290 w = (struct ieee80211_ie_wpa *)ie;
2292 /* Check for the right kind of IE. */
2293 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2294 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2298 /* Skip over the ucast cipher OIDs. */
2299 pos = (char *)&w->wpa_uciphers[0];
2300 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2302 /* Skip over the authmode count. */
2303 pos += sizeof(u_int16_t);
2306 * Check for the authentication modes. I'm
2307 * pretty sure there's only supposed to be one.
2310 n = (struct ndis_ie *)pos;
2311 if (n->ni_val == WPA_ASE_NONE)
2312 arg = NDIS_80211_AUTHMODE_WPANONE;
2314 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2315 arg = NDIS_80211_AUTHMODE_WPA;
2317 if (n->ni_val == WPA_ASE_8021X_PSK)
2318 arg = NDIS_80211_AUTHMODE_WPAPSK;
2320 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2322 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2325 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2327 /* Now configure the desired ciphers. */
2329 /* First, set up the multicast group cipher. */
2330 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2332 if (ndis_set_cipher(sc, n->ni_val))
2335 /* Now start looking around for the unicast ciphers. */
2336 pos = (char *)&w->wpa_uciphers[0];
2337 n = (struct ndis_ie *)pos;
2339 for (i = 0; i < w->wpa_uciphercnt; i++) {
2340 if (ndis_set_cipher(sc, n->ni_val))
2349 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2351 struct ieee80211vap *vap = ifp->if_softc;
2352 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2356 if (!NDIS_INITIALIZED(sc))
2359 len = sizeof(txrate);
2360 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2361 vap->iv_bss->ni_txrate = txrate / 5000;
2362 ieee80211_media_status(ifp, imr);
2366 ndis_setstate_80211(struct ndis_softc *sc)
2368 struct ieee80211com *ic = &sc->ndis_ic;
2369 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2370 ndis_80211_macaddr bssid;
2371 ndis_80211_config config;
2375 if (!NDIS_INITIALIZED(sc)) {
2376 DPRINTF(("%s: NDIS not initialized\n", __func__));
2380 /* Disassociate and turn off radio. */
2383 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2385 /* Set network infrastructure mode. */
2388 if (ic->ic_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 power management */
2400 if (vap->iv_flags & IEEE80211_F_PMGTON)
2401 arg = NDIS_80211_POWERMODE_FAST_PSP;
2403 arg = NDIS_80211_POWERMODE_CAM;
2404 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2407 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2408 ic->ic_txpowlimit < nitems(dBm2mW)) {
2409 arg = dBm2mW[ic->ic_txpowlimit];
2411 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2415 * Default encryption mode to off, authentication
2416 * to open and privacy to 'accept everything.'
2419 arg = NDIS_80211_WEPSTAT_DISABLED;
2420 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2423 arg = NDIS_80211_AUTHMODE_OPEN;
2424 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2427 * Note that OID_802_11_PRIVACY_FILTER is optional:
2428 * not all drivers implement it.
2431 arg = NDIS_80211_PRIVFILT_8021XWEP;
2432 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2434 len = sizeof(config);
2435 bzero((char *)&config, len);
2436 config.nc_length = len;
2437 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2438 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2441 * Some drivers expect us to initialize these values, so
2442 * provide some defaults.
2445 if (config.nc_beaconperiod == 0)
2446 config.nc_beaconperiod = 100;
2447 if (config.nc_atimwin == 0)
2448 config.nc_atimwin = 100;
2449 if (config.nc_fhconfig.ncf_dwelltime == 0)
2450 config.nc_fhconfig.ncf_dwelltime = 200;
2451 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2454 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2455 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2456 IEEE80211_CHAN_5GHZ;
2457 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2458 config.nc_dsconfig =
2459 ic->ic_bsschan->ic_freq * 1000;
2460 len = sizeof(config);
2461 config.nc_length = len;
2462 config.nc_fhconfig.ncf_length =
2463 sizeof(ndis_80211_config_fh);
2464 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2465 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2468 device_printf(sc->ndis_dev, "couldn't change "
2469 "DS config to %ukHz: %d\n",
2470 config.nc_dsconfig, rval);
2473 device_printf(sc->ndis_dev, "couldn't retrieve "
2474 "channel info: %d\n", rval);
2476 /* Set the BSSID to our value so the driver doesn't associate */
2477 len = IEEE80211_ADDR_LEN;
2478 bcopy(vap->iv_myaddr, bssid, len);
2479 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2480 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2482 device_printf(sc->ndis_dev,
2483 "setting BSSID failed: %d\n", rval);
2487 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2489 struct ieee80211_node *ni = vap->iv_bss;
2490 ndis_80211_ssid ssid;
2491 ndis_80211_macaddr bssid;
2493 int i, rval = 0, len, error;
2496 if (!NDIS_INITIALIZED(sc)) {
2497 DPRINTF(("%s: NDIS not initialized\n", __func__));
2502 ndis_setstate_80211(sc);
2504 /* Set network infrastructure mode. */
2507 if (vap->iv_opmode == IEEE80211_M_IBSS)
2508 arg = NDIS_80211_NET_INFRA_IBSS;
2510 arg = NDIS_80211_NET_INFRA_BSS;
2512 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2515 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2517 /* Set RTS threshold */
2520 arg = vap->iv_rtsthreshold;
2521 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2523 /* Set fragmentation threshold */
2526 arg = vap->iv_fragthreshold;
2527 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2531 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2532 !(vap->iv_flags & IEEE80211_F_WPA)) {
2535 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2537 arg = NDIS_80211_AUTHMODE_SHARED;
2538 DPRINTF(("Setting shared auth\n"));
2539 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2542 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2543 if (vap->iv_nw_keys[i].wk_keylen) {
2544 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2545 IEEE80211_CIPHER_WEP)
2547 bzero((char *)&wep, sizeof(wep));
2548 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2551 * 5, 13 and 16 are the only valid
2552 * key lengths. Anything in between
2553 * will be zero padded out to the
2554 * next highest boundary.
2556 if (vap->iv_nw_keys[i].wk_keylen < 5)
2558 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2559 vap->iv_nw_keys[i].wk_keylen < 13)
2561 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2562 vap->iv_nw_keys[i].wk_keylen < 16)
2566 wep.nw_length = (sizeof(uint32_t) * 3)
2568 if (i == vap->iv_def_txkey)
2569 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2570 bcopy(vap->iv_nw_keys[i].wk_key,
2571 wep.nw_keydata, wep.nw_length);
2573 DPRINTF(("Setting WEP key %d\n", i));
2574 rval = ndis_set_info(sc,
2575 OID_802_11_ADD_WEP, &wep, &len);
2577 device_printf(sc->ndis_dev,
2578 "set wepkey failed: %d\n", rval);
2583 DPRINTF(("Setting WEP on\n"));
2584 arg = NDIS_80211_WEPSTAT_ENABLED;
2586 rval = ndis_set_info(sc,
2587 OID_802_11_WEP_STATUS, &arg, &len);
2589 device_printf(sc->ndis_dev,
2590 "enable WEP failed: %d\n", rval);
2591 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2592 arg = NDIS_80211_PRIVFILT_8021XWEP;
2594 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2598 OID_802_11_PRIVACY_FILTER, &arg, &len);
2603 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2604 vap->iv_appie_assocreq != NULL) {
2605 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2606 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2608 device_printf(sc->ndis_dev, "WPA setup failed\n");
2612 /* Set network type. */
2616 switch (vap->iv_curmode) {
2617 case IEEE80211_MODE_11A:
2618 arg = NDIS_80211_NETTYPE_11OFDM5;
2620 case IEEE80211_MODE_11B:
2621 arg = NDIS_80211_NETTYPE_11DS;
2623 case IEEE80211_MODE_11G:
2624 arg = NDIS_80211_NETTYPE_11OFDM24;
2627 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2632 DPRINTF(("Setting network type to %d\n", arg));
2634 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2637 device_printf(sc->ndis_dev,
2638 "set nettype failed: %d\n", rval);
2643 * If the user selected a specific BSSID, try
2644 * to use that one. This is useful in the case where
2645 * there are several APs in range with the same network
2646 * name. To delete the BSSID, we use the broadcast
2647 * address as the BSSID.
2648 * Note that some drivers seem to allow setting a BSSID
2649 * in ad-hoc mode, which has the effect of forcing the
2650 * NIC to create an ad-hoc cell with a specific BSSID,
2651 * instead of a randomly chosen one. However, the net80211
2652 * code makes the assumtion that the BSSID setting is invalid
2653 * when you're in ad-hoc mode, so we don't allow that here.
2656 len = IEEE80211_ADDR_LEN;
2657 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2658 vap->iv_opmode != IEEE80211_M_IBSS)
2659 bcopy(ni->ni_bssid, bssid, len);
2661 bcopy(ieee80211broadcastaddr, bssid, len);
2663 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2664 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2666 device_printf(sc->ndis_dev,
2667 "setting BSSID failed: %d\n", rval);
2669 /* Set SSID -- always do this last. */
2672 if (ndis_debug > 0) {
2673 printf("Setting ESSID to ");
2674 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2680 bzero((char *)&ssid, len);
2681 ssid.ns_ssidlen = ni->ni_esslen;
2682 if (ssid.ns_ssidlen == 0) {
2683 ssid.ns_ssidlen = 1;
2685 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2687 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2690 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2696 ndis_get_bssid_list(sc, bl)
2697 struct ndis_softc *sc;
2698 ndis_80211_bssid_list_ex **bl;
2702 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2703 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2707 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2708 if (error == ENOSPC) {
2709 free(*bl, M_DEVBUF);
2710 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2714 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2717 DPRINTF(("%s: failed to read\n", __func__));
2718 free(*bl, M_DEVBUF);
2726 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2728 struct ieee80211com *ic = &sc->ndis_ic;
2729 struct ieee80211vap *vap;
2730 struct ieee80211_node *ni;
2731 ndis_80211_bssid_list_ex *bl;
2732 ndis_wlan_bssid_ex *bs;
2733 ndis_80211_macaddr bssid;
2739 len = sizeof(bssid);
2740 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2742 device_printf(sc->ndis_dev, "failed to get bssid\n");
2746 vap = TAILQ_FIRST(&ic->ic_vaps);
2749 error = ndis_get_bssid_list(sc, &bl);
2753 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2754 for (i = 0; i < bl->nblx_items; i++) {
2755 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2756 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2757 if (*assoc == NULL) {
2761 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2763 if (ic->ic_opmode == IEEE80211_M_STA)
2764 ni->ni_associd = 1 | 0xc000; /* fake associd */
2767 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2775 ndis_getstate_80211(struct ndis_softc *sc)
2777 struct ieee80211com *ic = &sc->ndis_ic;
2778 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2779 struct ieee80211_node *ni = vap->iv_bss;
2780 ndis_wlan_bssid_ex *bs;
2781 int rval, len, i = 0;
2785 if (!NDIS_INITIALIZED(sc))
2788 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2791 /* We're associated, retrieve info on the current bssid. */
2792 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2793 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2794 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2796 /* Get SSID from current association info. */
2797 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2798 bs->nwbx_ssid.ns_ssidlen);
2799 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2801 if (ic->ic_caps & IEEE80211_C_PMGT) {
2803 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2806 device_printf(sc->ndis_dev,
2807 "get power mode failed: %d\n", rval);
2808 if (arg == NDIS_80211_POWERMODE_CAM)
2809 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2811 vap->iv_flags |= IEEE80211_F_PMGTON;
2815 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2817 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2818 for (i = 0; i < nitems(dBm2mW); i++)
2819 if (dBm2mW[i] >= arg)
2821 ic->ic_txpowlimit = i;
2825 * Use the current association information to reflect
2826 * what channel we're on.
2828 ic->ic_curchan = ieee80211_find_channel(ic,
2829 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2830 if (ic->ic_curchan == NULL)
2831 ic->ic_curchan = &ic->ic_channels[0];
2832 ni->ni_chan = ic->ic_curchan;
2833 ic->ic_bsschan = ic->ic_curchan;
2838 * Determine current authentication mode.
2841 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2843 device_printf(sc->ndis_dev,
2844 "get authmode status failed: %d\n", rval);
2846 vap->iv_flags &= ~IEEE80211_F_WPA;
2848 case NDIS_80211_AUTHMODE_OPEN:
2849 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2851 case NDIS_80211_AUTHMODE_SHARED:
2852 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2854 case NDIS_80211_AUTHMODE_AUTO:
2855 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2857 case NDIS_80211_AUTHMODE_WPA:
2858 case NDIS_80211_AUTHMODE_WPAPSK:
2859 case NDIS_80211_AUTHMODE_WPANONE:
2860 ni->ni_authmode = IEEE80211_AUTH_WPA;
2861 vap->iv_flags |= IEEE80211_F_WPA1;
2863 case NDIS_80211_AUTHMODE_WPA2:
2864 case NDIS_80211_AUTHMODE_WPA2PSK:
2865 ni->ni_authmode = IEEE80211_AUTH_WPA;
2866 vap->iv_flags |= IEEE80211_F_WPA2;
2869 ni->ni_authmode = IEEE80211_AUTH_NONE;
2875 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2878 device_printf(sc->ndis_dev,
2879 "get wep status failed: %d\n", rval);
2881 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2882 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2884 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2888 ndis_ifioctl(ifp, command, data)
2893 struct ndis_softc *sc = ifp->if_softc;
2894 struct ifreq *ifr = (struct ifreq *) data;
2901 if (ifp->if_flags & IFF_UP) {
2902 if (sc->ndis_running &&
2903 ifp->if_flags & IFF_PROMISC &&
2904 !(sc->ndis_if_flags & IFF_PROMISC)) {
2906 NDIS_PACKET_TYPE_PROMISCUOUS;
2907 i = sizeof(sc->ndis_filter);
2908 error = ndis_set_info(sc,
2909 OID_GEN_CURRENT_PACKET_FILTER,
2910 &sc->ndis_filter, &i);
2911 } else if (sc->ndis_running &&
2912 !(ifp->if_flags & IFF_PROMISC) &&
2913 sc->ndis_if_flags & IFF_PROMISC) {
2915 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2916 i = sizeof(sc->ndis_filter);
2917 error = ndis_set_info(sc,
2918 OID_GEN_CURRENT_PACKET_FILTER,
2919 &sc->ndis_filter, &i);
2923 if (sc->ndis_running)
2926 sc->ndis_if_flags = ifp->if_flags;
2936 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2939 ifp->if_capenable = ifr->ifr_reqcap;
2940 if (ifp->if_capenable & IFCAP_TXCSUM)
2941 ifp->if_hwassist = sc->ndis_hwassist;
2943 ifp->if_hwassist = 0;
2944 ndis_set_offload(sc);
2947 error = ether_ioctl(ifp, command, data);
2951 /*NDIS_UNLOCK(sc);*/
2957 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2959 struct ndis_softc *sc = ic->ic_softc;
2960 struct ifreq *ifr = data;
2961 struct ndis_oid_data oid;
2962 struct ndis_evt evt;
2963 void *oidbuf = NULL;
2966 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2972 error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid));
2975 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2976 error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid),
2981 free(oidbuf, M_TEMP);
2987 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2990 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2992 case SIOCGPRIVATE_0:
2994 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2999 error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt));
3004 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3009 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3010 ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2);
3015 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3016 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3017 (caddr_t)ifr_data_get_ptr(ifr) +
3018 (sizeof(uint32_t) * 2),
3019 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3024 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3025 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3027 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3028 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3029 NDIS_EVTINC(sc->ndis_evtcidx);
3040 error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid));
3043 error = copyout(oidbuf,
3044 (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len);
3047 free(oidbuf, M_TEMP);
3053 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3055 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3056 ndis_80211_key rkey;
3059 bzero((char *)&rkey, sizeof(rkey));
3063 rkey.nk_keyidx = key->wk_keyix;
3065 bcopy(vap->iv_ifp->if_broadcastaddr,
3066 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3068 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3077 * In theory this could be called for any key, but we'll
3078 * only use it for WPA TKIP or AES keys. These need to be
3079 * set after initial authentication with the AP.
3082 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3084 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3085 ndis_80211_key rkey;
3088 switch (key->wk_cipher->ic_cipher) {
3089 case IEEE80211_CIPHER_TKIP:
3091 len = sizeof(ndis_80211_key);
3092 bzero((char *)&rkey, sizeof(rkey));
3095 rkey.nk_keylen = key->wk_keylen;
3097 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3098 rkey.nk_keylen += 16;
3100 /* key index - gets weird in NDIS */
3102 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3103 rkey.nk_keyidx = key->wk_keyix;
3107 if (key->wk_flags & IEEE80211_KEY_XMIT)
3108 rkey.nk_keyidx |= 1 << 31;
3110 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3111 bcopy(ieee80211broadcastaddr,
3112 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3114 bcopy(vap->iv_bss->ni_bssid,
3115 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3117 rkey.nk_keyidx |= 1 << 30;
3120 /* need to set bit 29 based on keyrsc */
3121 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3124 rkey.nk_keyidx |= 1 << 29;
3126 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3127 bcopy(key->wk_key, rkey.nk_keydata, 16);
3128 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3129 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3131 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3133 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3135 case IEEE80211_CIPHER_WEP:
3139 * I don't know how to set up keys for the AES
3140 * cipher yet. Is it the same as TKIP?
3142 case IEEE80211_CIPHER_AES_CCM:
3148 /* We need to return 1 for success, 0 for failure. */
3157 ndis_resettask(d, arg)
3161 struct ndis_softc *sc;
3168 * Stop the adapter and free any mbufs allocated to the
3172 ndis_stop(struct ndis_softc *sc)
3176 callout_drain(&sc->ndis_stat_callout);
3179 sc->ndis_tx_timer = 0;
3181 if (!sc->ndis_80211)
3182 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3183 sc->ndis_running = 0;
3186 if (sc->ndis_iftype != PNPBus ||
3187 (sc->ndis_iftype == PNPBus &&
3188 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3193 for (i = 0; i < NDIS_EVENTS; i++) {
3194 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3195 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3196 sc->ndis_evt[i].ne_buf = NULL;
3198 sc->ndis_evt[i].ne_sts = 0;
3199 sc->ndis_evt[i].ne_len = 0;
3201 sc->ndis_evtcidx = 0;
3202 sc->ndis_evtpidx = 0;
3207 * Stop all chip I/O so that the kernel's probe routines don't
3208 * get confused by errant DMAs when rebooting.
3214 struct ndis_softc *sc;
3216 sc = device_get_softc(dev);
3221 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3223 struct ndis_vap *nvp = NDIS_VAP(vap);
3224 struct ieee80211com *ic = vap->iv_ic;
3225 struct ndis_softc *sc = ic->ic_softc;
3226 enum ieee80211_state ostate;
3228 DPRINTF(("%s: %s -> %s\n", __func__,
3229 ieee80211_state_name[vap->iv_state],
3230 ieee80211_state_name[nstate]));
3232 ostate = vap->iv_state;
3233 vap->iv_state = nstate;
3236 /* pass on to net80211 */
3237 case IEEE80211_S_INIT:
3238 case IEEE80211_S_SCAN:
3239 return nvp->newstate(vap, nstate, arg);
3240 case IEEE80211_S_ASSOC:
3241 if (ostate != IEEE80211_S_AUTH) {
3242 IEEE80211_UNLOCK(ic);
3243 ndis_auth_and_assoc(sc, vap);
3247 case IEEE80211_S_AUTH:
3248 IEEE80211_UNLOCK(ic);
3249 ndis_auth_and_assoc(sc, vap);
3250 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3251 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3261 ndis_scan(void *arg)
3263 struct ieee80211vap *vap = arg;
3265 ieee80211_scan_done(vap);
3269 ndis_scan_results(struct ndis_softc *sc)
3271 struct ieee80211com *ic = &sc->ndis_ic;
3272 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3273 ndis_80211_bssid_list_ex *bl;
3274 ndis_wlan_bssid_ex *wb;
3275 struct ieee80211_scanparams sp;
3276 struct ieee80211_frame wh;
3277 struct ieee80211_channel *saved_chan;
3279 int rssi, noise, freq, chanflag;
3280 uint8_t ssid[2+IEEE80211_NWID_LEN];
3281 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3282 uint8_t *frm, *efrm;
3284 saved_chan = ic->ic_curchan;
3287 if (ndis_get_bssid_list(sc, &bl))
3290 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3291 wb = &bl->nblx_bssid[0];
3292 for (i = 0; i < bl->nblx_items; i++) {
3293 memset(&sp, 0, sizeof(sp));
3295 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3296 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3297 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3298 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3299 if (wb->nwbx_privacy)
3300 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3301 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3302 switch (wb->nwbx_netinfra) {
3303 case NDIS_80211_NET_INFRA_IBSS:
3304 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3306 case NDIS_80211_NET_INFRA_BSS:
3307 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3310 sp.rates = &rates[0];
3311 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3312 /* XXX - check units */
3313 if (wb->nwbx_supportedrates[j] == 0)
3316 wb->nwbx_supportedrates[j] & 0x7f;
3319 sp.ssid = (uint8_t *)&ssid[0];
3320 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3321 wb->nwbx_ssid.ns_ssidlen);
3322 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3324 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3325 freq = wb->nwbx_config.nc_dsconfig / 1000;
3326 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3327 /* Hack ic->ic_curchan to be in sync with the scan result */
3328 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3329 if (ic->ic_curchan == NULL)
3330 ic->ic_curchan = &ic->ic_channels[0];
3332 /* Process extended info from AP */
3333 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3334 frm = (uint8_t *)&wb->nwbx_ies;
3335 efrm = frm + wb->nwbx_ielen;
3336 if (efrm - frm < 12)
3338 sp.tstamp = frm; frm += 8;
3339 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3340 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3342 sp.ies_len = efrm - frm;
3345 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3346 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3348 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3349 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3352 /* Restore the channel after messing with it */
3353 ic->ic_curchan = saved_chan;
3357 ndis_scan_start(struct ieee80211com *ic)
3359 struct ndis_softc *sc = ic->ic_softc;
3360 struct ieee80211vap *vap;
3361 struct ieee80211_scan_state *ss;
3362 ndis_80211_ssid ssid;
3366 vap = TAILQ_FIRST(&ic->ic_vaps);
3368 if (!NDIS_INITIALIZED(sc)) {
3369 DPRINTF(("%s: scan aborted\n", __func__));
3370 ieee80211_cancel_scan(vap);
3375 bzero((char *)&ssid, len);
3376 if (ss->ss_nssid == 0)
3377 ssid.ns_ssidlen = 1;
3379 /* Perform a directed scan */
3380 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3381 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3384 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3386 DPRINTF(("%s: set ESSID failed\n", __func__));
3389 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3391 DPRINTF(("%s: scan command failed\n", __func__));
3392 ieee80211_cancel_scan(vap);
3395 /* Set a timer to collect the results */
3396 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3400 ndis_set_channel(struct ieee80211com *ic)
3406 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3412 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3414 /* NB: don't try to abort scan; wait for firmware to finish */
3418 ndis_scan_end(struct ieee80211com *ic)
3420 struct ndis_softc *sc = ic->ic_softc;
3422 ndis_scan_results(sc);