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 |
972 ifp->if_ioctl = ndis_ifioctl;
973 ifp->if_start = ndis_ifstart;
974 ifp->if_init = ndis_init;
975 ifp->if_baudrate = 10000000;
976 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
977 ifp->if_snd.ifq_drv_maxlen = 25;
978 IFQ_SET_READY(&ifp->if_snd);
979 ifp->if_capenable = ifp->if_capabilities;
980 ifp->if_hwassist = sc->ndis_hwassist;
982 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
984 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
985 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
986 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
987 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
988 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
989 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
990 ether_ifattach(ifp, eaddr);
995 static struct ieee80211vap *
996 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
997 enum ieee80211_opmode opmode, int flags,
998 const uint8_t bssid[IEEE80211_ADDR_LEN],
999 const uint8_t mac[IEEE80211_ADDR_LEN])
1001 struct ndis_vap *nvp;
1002 struct ieee80211vap *vap;
1004 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1006 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1008 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1009 /* override with driver methods */
1010 nvp->newstate = vap->iv_newstate;
1011 vap->iv_newstate = ndis_newstate;
1013 /* complete setup */
1014 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1016 ic->ic_opmode = opmode;
1017 /* install key handing routines */
1018 vap->iv_key_set = ndis_add_key;
1019 vap->iv_key_delete = ndis_del_key;
1024 ndis_vap_delete(struct ieee80211vap *vap)
1026 struct ndis_vap *nvp = NDIS_VAP(vap);
1027 struct ieee80211com *ic = vap->iv_ic;
1028 struct ndis_softc *sc = ic->ic_softc;
1031 callout_drain(&sc->ndis_scan_callout);
1032 ieee80211_vap_detach(vap);
1033 free(nvp, M_80211_VAP);
1037 * Shutdown hardware and free up resources. This can be called any
1038 * time after the mutex has been initialized. It is called in both
1039 * the error case in attach and the normal detach case so it needs
1040 * to be careful about only freeing resources that have actually been
1044 ndis_detach(device_t dev)
1047 struct ndis_softc *sc;
1050 sc = device_get_softc(dev);
1052 if (!sc->ndis_80211)
1057 ifp->if_flags &= ~IFF_UP;
1058 if (device_is_attached(dev)) {
1062 ieee80211_ifdetach(&sc->ndis_ic);
1063 else if (ifp != NULL)
1064 ether_ifdetach(ifp);
1068 if (sc->ndis_tickitem != NULL)
1069 IoFreeWorkItem(sc->ndis_tickitem);
1070 if (sc->ndis_startitem != NULL)
1071 IoFreeWorkItem(sc->ndis_startitem);
1072 if (sc->ndis_resetitem != NULL)
1073 IoFreeWorkItem(sc->ndis_resetitem);
1074 if (sc->ndis_inputitem != NULL)
1075 IoFreeWorkItem(sc->ndis_inputitem);
1076 if (sc->ndisusb_xferdoneitem != NULL)
1077 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1078 if (sc->ndisusb_taskitem != NULL)
1079 IoFreeWorkItem(sc->ndisusb_taskitem);
1081 bus_generic_detach(dev);
1082 ndis_unload_driver(sc);
1085 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1086 if (sc->ndis_res_io)
1087 bus_release_resource(dev, SYS_RES_IOPORT,
1088 sc->ndis_io_rid, sc->ndis_res_io);
1089 if (sc->ndis_res_mem)
1090 bus_release_resource(dev, SYS_RES_MEMORY,
1091 sc->ndis_mem_rid, sc->ndis_res_mem);
1092 if (sc->ndis_res_altmem)
1093 bus_release_resource(dev, SYS_RES_MEMORY,
1094 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1100 ndis_destroy_dma(sc);
1102 if (sc->ndis_txarray)
1103 free(sc->ndis_txarray, M_DEVBUF);
1105 if (!sc->ndis_80211)
1106 ifmedia_removeall(&sc->ifmedia);
1108 if (sc->ndis_txpool != NULL)
1109 NdisFreePacketPool(sc->ndis_txpool);
1111 /* Destroy the PDO for this device. */
1113 if (sc->ndis_iftype == PCIBus)
1114 drv = windrv_lookup(0, "PCI Bus");
1115 else if (sc->ndis_iftype == PCMCIABus)
1116 drv = windrv_lookup(0, "PCCARD Bus");
1118 drv = windrv_lookup(0, "USB Bus");
1120 panic("couldn't find driver object");
1121 windrv_destroy_pdo(drv, dev);
1123 if (sc->ndis_iftype == PCIBus)
1124 bus_dma_tag_destroy(sc->ndis_parent_tag);
1133 struct ndis_softc *sc;
1136 sc = device_get_softc(dev);
1140 if (NDIS_INITIALIZED(sc))
1151 struct ndis_softc *sc;
1154 sc = device_get_softc(dev);
1157 if (NDIS_INITIALIZED(sc))
1164 * The following bunch of routines are here to support drivers that
1165 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1166 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1167 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1171 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1172 ndis_handle adapter;
1178 uint32_t lookaheadlen;
1181 ndis_miniport_block *block;
1191 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1195 /* Save the data provided to us so far. */
1197 m->m_len = lookaheadlen + hdrlen;
1198 m->m_pkthdr.len = pktlen + hdrlen;
1200 m_copyback(m, 0, hdrlen, hdr);
1201 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1203 /* Now create a fake NDIS_PACKET to hold the data */
1205 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1207 if (status != NDIS_STATUS_SUCCESS) {
1214 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1222 p->np_private.npp_head = p->np_private.npp_tail = b;
1223 p->np_private.npp_totlen = m->m_pkthdr.len;
1225 /* Save the packet RX context somewhere. */
1226 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1227 priv->nep_ctx = ctx;
1229 if (!NDIS_SERIALIZED(block))
1230 KeAcquireSpinLock(&block->nmb_lock, &irql);
1232 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1234 if (!NDIS_SERIALIZED(block))
1235 KeReleaseSpinLock(&block->nmb_lock, irql);
1239 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1240 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1244 ndis_rxeof_done(adapter)
1245 ndis_handle adapter;
1247 struct ndis_softc *sc;
1248 ndis_miniport_block *block;
1252 /* Schedule transfer/RX of queued packets. */
1254 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1256 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1260 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1263 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1265 ndis_handle adapter;
1269 ndis_miniport_block *block;
1270 struct ndis_softc *sc;
1279 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1282 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1284 l = block->nmb_packetlist.nle_flink;
1285 while(!IsListEmpty(&block->nmb_packetlist)) {
1286 l = RemoveHeadList((&block->nmb_packetlist));
1287 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1288 InitializeListHead((&p->np_list));
1290 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1295 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1297 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1298 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1299 m->m_len, m->m_pkthdr.len - m->m_len);
1301 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1304 * If status is NDIS_STATUS_PENDING, do nothing and
1305 * wait for a callback to the ndis_rxeof_xfr_done()
1309 m->m_len = m->m_pkthdr.len;
1310 m->m_pkthdr.rcvif = ifp;
1312 if (status == NDIS_STATUS_SUCCESS) {
1313 IoFreeMdl(p->np_private.npp_head);
1315 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1316 mbufq_enqueue(&sc->ndis_rxqueue, m);
1317 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1318 IoQueueWorkItem(sc->ndis_inputitem,
1319 (io_workitem_func)ndis_inputtask_wrap,
1320 WORKQUEUE_CRITICAL, sc);
1323 if (status == NDIS_STATUS_FAILURE)
1326 /* Advance to next packet */
1327 l = block->nmb_packetlist.nle_flink;
1330 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1334 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1337 ndis_rxeof_xfr_done(adapter, packet, status, len)
1338 ndis_handle adapter;
1339 ndis_packet *packet;
1343 ndis_miniport_block *block;
1344 struct ndis_softc *sc;
1349 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1353 IoFreeMdl(packet->np_private.npp_head);
1354 NdisFreePacket(packet);
1356 if (status != NDIS_STATUS_SUCCESS) {
1361 m->m_len = m->m_pkthdr.len;
1362 m->m_pkthdr.rcvif = ifp;
1363 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1364 mbufq_enqueue(&sc->ndis_rxqueue, m);
1365 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1366 IoQueueWorkItem(sc->ndis_inputitem,
1367 (io_workitem_func)ndis_inputtask_wrap,
1368 WORKQUEUE_CRITICAL, sc);
1371 * A frame has been uploaded: pass the resulting mbuf chain up to
1372 * the higher level protocols.
1374 * When handling received NDIS packets, the 'status' field in the
1375 * out-of-band portion of the ndis_packet has special meaning. In the
1376 * most common case, the underlying NDIS driver will set this field
1377 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1378 * take possession of it. We then change the status field to
1379 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1380 * and that we will return it at some point in the future via the
1381 * return packet handler.
1383 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1384 * this means the driver is running out of packet/buffer resources and
1385 * wants to maintain ownership of the packet. In this case, we have to
1386 * copy the packet data into local storage and let the driver keep the
1390 ndis_rxeof(adapter, packets, pktcnt)
1391 ndis_handle adapter;
1392 ndis_packet **packets;
1395 struct ndis_softc *sc;
1396 ndis_miniport_block *block;
1399 ndis_tcpip_csum *csum;
1401 struct mbuf *m0, *m;
1404 block = (ndis_miniport_block *)adapter;
1405 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1409 * There's a slim chance the driver may indicate some packets
1410 * before we're completely ready to handle them. If we detect this,
1411 * we need to return them to the miniport and ignore them.
1413 if (!sc->ndis_running) {
1414 for (i = 0; i < pktcnt; i++) {
1416 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1418 ndis_return_packet(p);
1424 for (i = 0; i < pktcnt; i++) {
1426 /* Stash the softc here so ptom can use it. */
1428 if (ndis_ptom(&m0, p)) {
1429 device_printf(sc->ndis_dev, "ptom failed\n");
1430 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1431 ndis_return_packet(p);
1434 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1435 m = m_dup(m0, M_NOWAIT);
1437 * NOTE: we want to destroy the mbuf here, but
1438 * we don't actually want to return it to the
1439 * driver via the return packet handler. By
1440 * bumping np_refcnt, we can prevent the
1441 * ndis_return_packet() routine from actually
1447 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1451 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1453 m = m_dup(m0, M_NOWAIT);
1454 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1457 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1460 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1464 m0->m_pkthdr.rcvif = ifp;
1466 /* Deal with checksum offload. */
1468 if (ifp->if_capenable & IFCAP_RXCSUM &&
1469 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1471 p->np_ext.npe_info[ndis_tcpipcsum_info];
1472 csum = (ndis_tcpip_csum *)&s;
1473 if (csum->u.ntc_rxflags &
1474 NDIS_RXCSUM_IP_PASSED)
1475 m0->m_pkthdr.csum_flags |=
1476 CSUM_IP_CHECKED|CSUM_IP_VALID;
1477 if (csum->u.ntc_rxflags &
1478 (NDIS_RXCSUM_TCP_PASSED |
1479 NDIS_RXCSUM_UDP_PASSED)) {
1480 m0->m_pkthdr.csum_flags |=
1481 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1482 m0->m_pkthdr.csum_data = 0xFFFF;
1486 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1487 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1488 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1489 IoQueueWorkItem(sc->ndis_inputitem,
1490 (io_workitem_func)ndis_inputtask_wrap,
1491 WORKQUEUE_CRITICAL, sc);
1497 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1498 * packets into the stack in order to avoid calling (*ifp->if_input)()
1499 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1500 * 'dispatch level' per-cpu sleep lock).
1503 ndis_inputtask(device_object *dobj, void *arg)
1505 ndis_miniport_block *block;
1506 struct ndis_softc *sc = arg;
1510 block = dobj->do_devext;
1512 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1513 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1514 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1515 if ((sc->ndis_80211 != 0)) {
1516 struct ieee80211com *ic = &sc->ndis_ic;
1517 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1520 vap->iv_deliver_data(vap, vap->iv_bss, m);
1522 struct ifnet *ifp = sc->ifp;
1524 (*ifp->if_input)(ifp, m);
1526 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1528 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1532 * A frame was downloaded to the chip. It's safe for us to clean up
1536 ndis_txeof(adapter, packet, status)
1537 ndis_handle adapter;
1538 ndis_packet *packet;
1542 struct ndis_softc *sc;
1543 ndis_miniport_block *block;
1548 block = (ndis_miniport_block *)adapter;
1549 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1553 idx = packet->np_txidx;
1555 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1557 ndis_free_packet(packet);
1561 sc->ndis_txarray[idx] = NULL;
1562 sc->ndis_txpending++;
1564 if (!sc->ndis_80211) {
1565 struct ifnet *ifp = sc->ifp;
1566 if (status == NDIS_STATUS_SUCCESS)
1567 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1569 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1570 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1572 sc->ndis_tx_timer = 0;
1576 if (!sc->ndis_80211)
1577 IoQueueWorkItem(sc->ndis_startitem,
1578 (io_workitem_func)ndis_ifstarttask_wrap,
1579 WORKQUEUE_CRITICAL, sc);
1580 DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1584 ndis_linksts(adapter, status, sbuf, slen)
1585 ndis_handle adapter;
1590 ndis_miniport_block *block;
1591 struct ndis_softc *sc;
1594 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1595 sc->ndis_sts = status;
1597 /* Event list is all full up, drop this one. */
1600 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1605 /* Cache the event. */
1608 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1610 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1615 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1617 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1618 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1619 NDIS_EVTINC(sc->ndis_evtpidx);
1624 ndis_linksts_done(adapter)
1625 ndis_handle adapter;
1627 ndis_miniport_block *block;
1628 struct ndis_softc *sc;
1632 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1635 if (!NDIS_INITIALIZED(sc))
1638 switch (sc->ndis_sts) {
1639 case NDIS_STATUS_MEDIA_CONNECT:
1640 IoQueueWorkItem(sc->ndis_tickitem,
1641 (io_workitem_func)ndis_ticktask_wrap,
1642 WORKQUEUE_CRITICAL, sc);
1643 if (!sc->ndis_80211)
1644 IoQueueWorkItem(sc->ndis_startitem,
1645 (io_workitem_func)ndis_ifstarttask_wrap,
1646 WORKQUEUE_CRITICAL, sc);
1648 case NDIS_STATUS_MEDIA_DISCONNECT:
1650 IoQueueWorkItem(sc->ndis_tickitem,
1651 (io_workitem_func)ndis_ticktask_wrap,
1652 WORKQUEUE_CRITICAL, sc);
1663 struct ndis_softc *sc;
1667 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1668 IoQueueWorkItem(sc->ndis_tickitem,
1669 (io_workitem_func)ndis_ticktask_wrap,
1670 WORKQUEUE_CRITICAL, sc);
1671 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1674 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1675 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1676 device_printf(sc->ndis_dev, "watchdog timeout\n");
1678 IoQueueWorkItem(sc->ndis_resetitem,
1679 (io_workitem_func)ndis_resettask_wrap,
1680 WORKQUEUE_CRITICAL, sc);
1681 if (!sc->ndis_80211)
1682 IoQueueWorkItem(sc->ndis_startitem,
1683 (io_workitem_func)ndis_ifstarttask_wrap,
1684 WORKQUEUE_CRITICAL, sc);
1687 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1691 ndis_ticktask(device_object *d, void *xsc)
1693 struct ndis_softc *sc = xsc;
1694 ndis_checkforhang_handler hangfunc;
1698 if (!NDIS_INITIALIZED(sc)) {
1704 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1706 if (hangfunc != NULL) {
1707 rval = MSCALL1(hangfunc,
1708 sc->ndis_block->nmb_miniportadapterctx);
1716 if (sc->ndis_link == 0 &&
1717 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1719 if (sc->ndis_80211 != 0) {
1720 struct ieee80211com *ic = &sc->ndis_ic;
1721 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1725 ndis_getstate_80211(sc);
1726 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1728 if_link_state_change(vap->iv_ifp,
1732 if_link_state_change(sc->ifp, LINK_STATE_UP);
1735 if (sc->ndis_link == 1 &&
1736 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1738 if (sc->ndis_80211 != 0) {
1739 struct ieee80211com *ic = &sc->ndis_ic;
1740 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1744 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1746 if_link_state_change(vap->iv_ifp,
1750 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1757 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1759 bus_dma_segment_t *segs;
1765 struct ndis_sc_list *sclist;
1768 if (error || arg == NULL)
1773 sclist->nsl_frags = nseg;
1775 for (i = 0; i < nseg; i++) {
1776 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1777 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1782 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1783 const struct ieee80211_bpf_params *params)
1785 /* no support; just discard */
1787 ieee80211_free_node(ni);
1792 ndis_update_mcast(struct ieee80211com *ic)
1794 struct ndis_softc *sc = ic->ic_softc;
1800 ndis_update_promisc(struct ieee80211com *ic)
1806 ndis_ifstarttask(device_object *d, void *arg)
1808 struct ndis_softc *sc = arg;
1809 DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1813 struct ifnet *ifp = sc->ifp;
1814 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1819 * Main transmit routine. To make NDIS drivers happy, we need to
1820 * transform mbuf chains into NDIS packets and feed them to the
1821 * send packet routines. Most drivers allow you to send several
1822 * packets at once (up to the maxpkts limit). Unfortunately, rather
1823 * that accepting them in the form of a linked list, they expect
1824 * a contiguous array of pointers to packets.
1826 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1827 * we need to perform busdma work here. Those that use map registers
1828 * will do the mapping themselves on a buffer by buffer basis.
1831 ndis_ifstart(struct ifnet *ifp)
1833 struct ndis_softc *sc;
1834 struct mbuf *m = NULL;
1835 ndis_packet **p0 = NULL, *p = NULL;
1836 ndis_tcpip_csum *csum;
1837 int pcnt = 0, status;
1842 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1847 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1849 while(sc->ndis_txpending) {
1850 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1854 NdisAllocatePacket(&status,
1855 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1857 if (status != NDIS_STATUS_SUCCESS)
1860 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1861 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1867 * Save pointer to original mbuf
1868 * so we can free it later.
1871 p = sc->ndis_txarray[sc->ndis_txidx];
1872 p->np_txidx = sc->ndis_txidx;
1874 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1877 * Do scatter/gather processing, if driver requested it.
1880 bus_dmamap_load_mbuf(sc->ndis_ttag,
1881 sc->ndis_tmaps[sc->ndis_txidx], m,
1882 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1883 bus_dmamap_sync(sc->ndis_ttag,
1884 sc->ndis_tmaps[sc->ndis_txidx],
1885 BUS_DMASYNC_PREREAD);
1886 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1889 /* Handle checksum offload. */
1891 if (ifp->if_capenable & IFCAP_TXCSUM &&
1892 m->m_pkthdr.csum_flags) {
1893 csum = (ndis_tcpip_csum *)
1894 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1895 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1896 if (m->m_pkthdr.csum_flags & CSUM_IP)
1897 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1898 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1899 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1900 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1901 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1902 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1906 sc->ndis_txpending--;
1911 * If there's a BPF listener, bounce a copy of this frame
1914 if (!sc->ndis_80211) /* XXX handle 80211 */
1918 * The array that p0 points to must appear contiguous,
1919 * so we must not wrap past the end of sc->ndis_txarray[].
1920 * If it looks like we're about to wrap, break out here
1921 * so the this batch of packets can be transmitted, then
1922 * wait for txeof to ask us to send the rest.
1924 if (sc->ndis_txidx == 0)
1933 if (sc->ndis_txpending == 0)
1934 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1937 * Set a timeout in case the chip goes out to lunch.
1939 sc->ndis_tx_timer = 5;
1944 * According to NDIS documentation, if a driver exports
1945 * a MiniportSendPackets() routine, we prefer that over
1946 * a MiniportSend() routine (which sends just a single
1949 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1950 ndis_send_packets(sc, p0, pcnt);
1952 ndis_send_packet(sc, p);
1958 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1960 struct ndis_softc *sc = ic->ic_softc;
1961 ndis_packet **p0 = NULL, *p = NULL;
1965 if (!sc->ndis_link || !sc->ndis_running) {
1970 if (sc->ndis_txpending == 0) {
1975 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1977 NdisAllocatePacket(&status,
1978 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1980 if (status != NDIS_STATUS_SUCCESS) {
1985 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1991 * Save pointer to original mbuf
1992 * so we can free it later.
1995 p = sc->ndis_txarray[sc->ndis_txidx];
1996 p->np_txidx = sc->ndis_txidx;
1998 p->np_oob.npo_status = NDIS_STATUS_PENDING;
2001 * Do scatter/gather processing, if driver requested it.
2004 bus_dmamap_load_mbuf(sc->ndis_ttag,
2005 sc->ndis_tmaps[sc->ndis_txidx], m,
2006 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2007 bus_dmamap_sync(sc->ndis_ttag,
2008 sc->ndis_tmaps[sc->ndis_txidx],
2009 BUS_DMASYNC_PREREAD);
2010 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2014 sc->ndis_txpending--;
2017 * Set a timeout in case the chip goes out to lunch.
2019 sc->ndis_tx_timer = 5;
2023 * According to NDIS documentation, if a driver exports
2024 * a MiniportSendPackets() routine, we prefer that over
2025 * a MiniportSend() routine (which sends just a single
2028 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2029 ndis_send_packets(sc, p0, 1);
2031 ndis_send_packet(sc, p);
2037 ndis_80211parent(struct ieee80211com *ic)
2039 struct ndis_softc *sc = ic->ic_softc;
2042 if (ic->ic_nrunning > 0) {
2043 if (!sc->ndis_running)
2045 } else if (sc->ndis_running)
2047 /*NDIS_UNLOCK(sc);*/
2051 ndis_init(void *xsc)
2053 struct ndis_softc *sc = xsc;
2057 * Avoid reintializing the link unnecessarily.
2058 * This should be dealt with in a better way by
2059 * fixing the upper layer modules so they don't
2060 * call ifp->if_init() quite as often.
2066 * Cancel pending I/O and free all RX/TX buffers.
2070 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2071 error = ndis_init_nic(sc);
2073 device_printf(sc->ndis_dev,
2074 "failed to initialize the device: %d\n", error);
2079 /* Program the packet filter */
2080 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2081 NDIS_PACKET_TYPE_BROADCAST;
2083 if (sc->ndis_80211) {
2084 struct ieee80211com *ic = &sc->ndis_ic;
2086 if (ic->ic_promisc > 0)
2087 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2089 struct ifnet *ifp = sc->ifp;
2091 if (ifp->if_flags & IFF_PROMISC)
2092 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2095 len = sizeof(sc->ndis_filter);
2097 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2098 &sc->ndis_filter, &len);
2101 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2109 i = sc->ifp->if_mtu;
2111 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2114 * Program the multicast filter, if necessary.
2118 /* Setup task offload. */
2119 ndis_set_offload(sc);
2124 sc->ndis_txpending = sc->ndis_maxpkts;
2127 if (!sc->ndis_80211) {
2128 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2129 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2130 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2133 sc->ndis_tx_timer = 0;
2136 * Some drivers don't set this value. The NDIS spec says
2137 * the default checkforhang timeout is "approximately 2
2138 * seconds." We use 3 seconds, because it seems for some
2139 * drivers, exactly 2 seconds is too fast.
2141 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2142 sc->ndis_block->nmb_checkforhangsecs = 3;
2144 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2145 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2146 sc->ndis_running = 1;
2149 /* XXX force handling */
2151 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2155 * Set media options.
2158 ndis_ifmedia_upd(ifp)
2161 struct ndis_softc *sc;
2165 if (NDIS_INITIALIZED(sc))
2172 * Report current media status.
2175 ndis_ifmedia_sts(ifp, ifmr)
2177 struct ifmediareq *ifmr;
2179 struct ndis_softc *sc;
2180 uint32_t media_info;
2181 ndis_media_state linkstate;
2184 ifmr->ifm_status = IFM_AVALID;
2185 ifmr->ifm_active = IFM_ETHER;
2188 if (!NDIS_INITIALIZED(sc))
2191 len = sizeof(linkstate);
2192 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2193 (void *)&linkstate, &len);
2195 len = sizeof(media_info);
2196 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2197 (void *)&media_info, &len);
2199 if (linkstate == nmc_connected)
2200 ifmr->ifm_status |= IFM_ACTIVE;
2202 switch (media_info) {
2204 ifmr->ifm_active |= IFM_10_T;
2207 ifmr->ifm_active |= IFM_100_TX;
2210 ifmr->ifm_active |= IFM_1000_T;
2213 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2219 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2221 struct ieee80211com *ic = &sc->ndis_ic;
2227 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2228 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2230 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2233 if (cipher == WPA_CSE_TKIP) {
2234 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2236 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2239 if (cipher == WPA_CSE_CCMP) {
2240 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2242 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2245 DPRINTF(("Setting cipher to %d\n", arg));
2247 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2252 /* Check that the cipher was set correctly. */
2255 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2257 if (rval != 0 || arg != save)
2264 * WPA is hairy to set up. Do the work in a separate routine
2265 * so we don't clutter the setstate function too much.
2266 * Important yet undocumented fact: first we have to set the
2267 * authentication mode, _then_ we enable the ciphers. If one
2268 * of the WPA authentication modes isn't enabled, the driver
2269 * might not permit the TKIP or AES ciphers to be selected.
2272 ndis_set_wpa(sc, ie, ielen)
2273 struct ndis_softc *sc;
2277 struct ieee80211_ie_wpa *w;
2284 * Apparently, the only way for us to know what ciphers
2285 * and key management/authentication mode to use is for
2286 * us to inspect the optional information element (IE)
2287 * stored in the 802.11 state machine. This IE should be
2288 * supplied by the WPA supplicant.
2291 w = (struct ieee80211_ie_wpa *)ie;
2293 /* Check for the right kind of IE. */
2294 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2295 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2299 /* Skip over the ucast cipher OIDs. */
2300 pos = (char *)&w->wpa_uciphers[0];
2301 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2303 /* Skip over the authmode count. */
2304 pos += sizeof(u_int16_t);
2307 * Check for the authentication modes. I'm
2308 * pretty sure there's only supposed to be one.
2311 n = (struct ndis_ie *)pos;
2312 if (n->ni_val == WPA_ASE_NONE)
2313 arg = NDIS_80211_AUTHMODE_WPANONE;
2315 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2316 arg = NDIS_80211_AUTHMODE_WPA;
2318 if (n->ni_val == WPA_ASE_8021X_PSK)
2319 arg = NDIS_80211_AUTHMODE_WPAPSK;
2321 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2323 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2326 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2328 /* Now configure the desired ciphers. */
2330 /* First, set up the multicast group cipher. */
2331 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2333 if (ndis_set_cipher(sc, n->ni_val))
2336 /* Now start looking around for the unicast ciphers. */
2337 pos = (char *)&w->wpa_uciphers[0];
2338 n = (struct ndis_ie *)pos;
2340 for (i = 0; i < w->wpa_uciphercnt; i++) {
2341 if (ndis_set_cipher(sc, n->ni_val))
2350 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2352 struct ieee80211vap *vap = ifp->if_softc;
2353 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2357 if (!NDIS_INITIALIZED(sc))
2360 len = sizeof(txrate);
2361 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2362 vap->iv_bss->ni_txrate = txrate / 5000;
2363 ieee80211_media_status(ifp, imr);
2367 ndis_setstate_80211(struct ndis_softc *sc)
2369 struct ieee80211com *ic = &sc->ndis_ic;
2370 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2371 ndis_80211_macaddr bssid;
2372 ndis_80211_config config;
2376 if (!NDIS_INITIALIZED(sc)) {
2377 DPRINTF(("%s: NDIS not initialized\n", __func__));
2381 /* Disassociate and turn off radio. */
2384 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2386 /* Set network infrastructure mode. */
2389 if (ic->ic_opmode == IEEE80211_M_IBSS)
2390 arg = NDIS_80211_NET_INFRA_IBSS;
2392 arg = NDIS_80211_NET_INFRA_BSS;
2394 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2397 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2399 /* Set power management */
2401 if (vap->iv_flags & IEEE80211_F_PMGTON)
2402 arg = NDIS_80211_POWERMODE_FAST_PSP;
2404 arg = NDIS_80211_POWERMODE_CAM;
2405 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2408 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2409 ic->ic_txpowlimit < nitems(dBm2mW)) {
2410 arg = dBm2mW[ic->ic_txpowlimit];
2412 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2416 * Default encryption mode to off, authentication
2417 * to open and privacy to 'accept everything.'
2420 arg = NDIS_80211_WEPSTAT_DISABLED;
2421 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2424 arg = NDIS_80211_AUTHMODE_OPEN;
2425 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2428 * Note that OID_802_11_PRIVACY_FILTER is optional:
2429 * not all drivers implement it.
2432 arg = NDIS_80211_PRIVFILT_8021XWEP;
2433 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2435 len = sizeof(config);
2436 bzero((char *)&config, len);
2437 config.nc_length = len;
2438 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2439 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2442 * Some drivers expect us to initialize these values, so
2443 * provide some defaults.
2446 if (config.nc_beaconperiod == 0)
2447 config.nc_beaconperiod = 100;
2448 if (config.nc_atimwin == 0)
2449 config.nc_atimwin = 100;
2450 if (config.nc_fhconfig.ncf_dwelltime == 0)
2451 config.nc_fhconfig.ncf_dwelltime = 200;
2452 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2455 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2456 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2457 IEEE80211_CHAN_5GHZ;
2458 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2459 config.nc_dsconfig =
2460 ic->ic_bsschan->ic_freq * 1000;
2461 len = sizeof(config);
2462 config.nc_length = len;
2463 config.nc_fhconfig.ncf_length =
2464 sizeof(ndis_80211_config_fh);
2465 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2466 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2469 device_printf(sc->ndis_dev, "couldn't change "
2470 "DS config to %ukHz: %d\n",
2471 config.nc_dsconfig, rval);
2474 device_printf(sc->ndis_dev, "couldn't retrieve "
2475 "channel info: %d\n", rval);
2477 /* Set the BSSID to our value so the driver doesn't associate */
2478 len = IEEE80211_ADDR_LEN;
2479 bcopy(vap->iv_myaddr, bssid, len);
2480 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2481 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2483 device_printf(sc->ndis_dev,
2484 "setting BSSID failed: %d\n", rval);
2488 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2490 struct ieee80211_node *ni = vap->iv_bss;
2491 ndis_80211_ssid ssid;
2492 ndis_80211_macaddr bssid;
2494 int i, rval = 0, len, error;
2497 if (!NDIS_INITIALIZED(sc)) {
2498 DPRINTF(("%s: NDIS not initialized\n", __func__));
2503 ndis_setstate_80211(sc);
2505 /* Set network infrastructure mode. */
2508 if (vap->iv_opmode == IEEE80211_M_IBSS)
2509 arg = NDIS_80211_NET_INFRA_IBSS;
2511 arg = NDIS_80211_NET_INFRA_BSS;
2513 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2516 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2518 /* Set RTS threshold */
2521 arg = vap->iv_rtsthreshold;
2522 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2524 /* Set fragmentation threshold */
2527 arg = vap->iv_fragthreshold;
2528 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2532 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2533 !(vap->iv_flags & IEEE80211_F_WPA)) {
2536 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2538 arg = NDIS_80211_AUTHMODE_SHARED;
2539 DPRINTF(("Setting shared auth\n"));
2540 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2543 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2544 if (vap->iv_nw_keys[i].wk_keylen) {
2545 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2546 IEEE80211_CIPHER_WEP)
2548 bzero((char *)&wep, sizeof(wep));
2549 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2552 * 5, 13 and 16 are the only valid
2553 * key lengths. Anything in between
2554 * will be zero padded out to the
2555 * next highest boundary.
2557 if (vap->iv_nw_keys[i].wk_keylen < 5)
2559 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2560 vap->iv_nw_keys[i].wk_keylen < 13)
2562 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2563 vap->iv_nw_keys[i].wk_keylen < 16)
2567 wep.nw_length = (sizeof(uint32_t) * 3)
2569 if (i == vap->iv_def_txkey)
2570 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2571 bcopy(vap->iv_nw_keys[i].wk_key,
2572 wep.nw_keydata, wep.nw_length);
2574 DPRINTF(("Setting WEP key %d\n", i));
2575 rval = ndis_set_info(sc,
2576 OID_802_11_ADD_WEP, &wep, &len);
2578 device_printf(sc->ndis_dev,
2579 "set wepkey failed: %d\n", rval);
2584 DPRINTF(("Setting WEP on\n"));
2585 arg = NDIS_80211_WEPSTAT_ENABLED;
2587 rval = ndis_set_info(sc,
2588 OID_802_11_WEP_STATUS, &arg, &len);
2590 device_printf(sc->ndis_dev,
2591 "enable WEP failed: %d\n", rval);
2592 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2593 arg = NDIS_80211_PRIVFILT_8021XWEP;
2595 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2599 OID_802_11_PRIVACY_FILTER, &arg, &len);
2604 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2605 vap->iv_appie_assocreq != NULL) {
2606 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2607 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2609 device_printf(sc->ndis_dev, "WPA setup failed\n");
2613 /* Set network type. */
2617 switch (vap->iv_curmode) {
2618 case IEEE80211_MODE_11A:
2619 arg = NDIS_80211_NETTYPE_11OFDM5;
2621 case IEEE80211_MODE_11B:
2622 arg = NDIS_80211_NETTYPE_11DS;
2624 case IEEE80211_MODE_11G:
2625 arg = NDIS_80211_NETTYPE_11OFDM24;
2628 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2633 DPRINTF(("Setting network type to %d\n", arg));
2635 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2638 device_printf(sc->ndis_dev,
2639 "set nettype failed: %d\n", rval);
2644 * If the user selected a specific BSSID, try
2645 * to use that one. This is useful in the case where
2646 * there are several APs in range with the same network
2647 * name. To delete the BSSID, we use the broadcast
2648 * address as the BSSID.
2649 * Note that some drivers seem to allow setting a BSSID
2650 * in ad-hoc mode, which has the effect of forcing the
2651 * NIC to create an ad-hoc cell with a specific BSSID,
2652 * instead of a randomly chosen one. However, the net80211
2653 * code makes the assumtion that the BSSID setting is invalid
2654 * when you're in ad-hoc mode, so we don't allow that here.
2657 len = IEEE80211_ADDR_LEN;
2658 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2659 vap->iv_opmode != IEEE80211_M_IBSS)
2660 bcopy(ni->ni_bssid, bssid, len);
2662 bcopy(ieee80211broadcastaddr, bssid, len);
2664 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2665 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2667 device_printf(sc->ndis_dev,
2668 "setting BSSID failed: %d\n", rval);
2670 /* Set SSID -- always do this last. */
2673 if (ndis_debug > 0) {
2674 printf("Setting ESSID to ");
2675 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2681 bzero((char *)&ssid, len);
2682 ssid.ns_ssidlen = ni->ni_esslen;
2683 if (ssid.ns_ssidlen == 0) {
2684 ssid.ns_ssidlen = 1;
2686 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2688 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2691 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2697 ndis_get_bssid_list(sc, bl)
2698 struct ndis_softc *sc;
2699 ndis_80211_bssid_list_ex **bl;
2703 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2704 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2708 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2709 if (error == ENOSPC) {
2710 free(*bl, M_DEVBUF);
2711 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2715 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2718 DPRINTF(("%s: failed to read\n", __func__));
2719 free(*bl, M_DEVBUF);
2727 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2729 struct ieee80211com *ic = &sc->ndis_ic;
2730 struct ieee80211vap *vap;
2731 struct ieee80211_node *ni;
2732 ndis_80211_bssid_list_ex *bl;
2733 ndis_wlan_bssid_ex *bs;
2734 ndis_80211_macaddr bssid;
2740 len = sizeof(bssid);
2741 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2743 device_printf(sc->ndis_dev, "failed to get bssid\n");
2747 vap = TAILQ_FIRST(&ic->ic_vaps);
2750 error = ndis_get_bssid_list(sc, &bl);
2754 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2755 for (i = 0; i < bl->nblx_items; i++) {
2756 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2757 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2758 if (*assoc == NULL) {
2762 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2764 if (ic->ic_opmode == IEEE80211_M_STA)
2765 ni->ni_associd = 1 | 0xc000; /* fake associd */
2768 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2776 ndis_getstate_80211(struct ndis_softc *sc)
2778 struct ieee80211com *ic = &sc->ndis_ic;
2779 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2780 struct ieee80211_node *ni = vap->iv_bss;
2781 ndis_wlan_bssid_ex *bs;
2782 int rval, len, i = 0;
2786 if (!NDIS_INITIALIZED(sc))
2789 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2792 /* We're associated, retrieve info on the current bssid. */
2793 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2794 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2795 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2797 /* Get SSID from current association info. */
2798 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2799 bs->nwbx_ssid.ns_ssidlen);
2800 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2802 if (ic->ic_caps & IEEE80211_C_PMGT) {
2804 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2807 device_printf(sc->ndis_dev,
2808 "get power mode failed: %d\n", rval);
2809 if (arg == NDIS_80211_POWERMODE_CAM)
2810 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2812 vap->iv_flags |= IEEE80211_F_PMGTON;
2816 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2818 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2819 for (i = 0; i < nitems(dBm2mW); i++)
2820 if (dBm2mW[i] >= arg)
2822 ic->ic_txpowlimit = i;
2826 * Use the current association information to reflect
2827 * what channel we're on.
2829 ic->ic_curchan = ieee80211_find_channel(ic,
2830 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2831 if (ic->ic_curchan == NULL)
2832 ic->ic_curchan = &ic->ic_channels[0];
2833 ni->ni_chan = ic->ic_curchan;
2834 ic->ic_bsschan = ic->ic_curchan;
2839 * Determine current authentication mode.
2842 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2844 device_printf(sc->ndis_dev,
2845 "get authmode status failed: %d\n", rval);
2847 vap->iv_flags &= ~IEEE80211_F_WPA;
2849 case NDIS_80211_AUTHMODE_OPEN:
2850 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2852 case NDIS_80211_AUTHMODE_SHARED:
2853 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2855 case NDIS_80211_AUTHMODE_AUTO:
2856 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2858 case NDIS_80211_AUTHMODE_WPA:
2859 case NDIS_80211_AUTHMODE_WPAPSK:
2860 case NDIS_80211_AUTHMODE_WPANONE:
2861 ni->ni_authmode = IEEE80211_AUTH_WPA;
2862 vap->iv_flags |= IEEE80211_F_WPA1;
2864 case NDIS_80211_AUTHMODE_WPA2:
2865 case NDIS_80211_AUTHMODE_WPA2PSK:
2866 ni->ni_authmode = IEEE80211_AUTH_WPA;
2867 vap->iv_flags |= IEEE80211_F_WPA2;
2870 ni->ni_authmode = IEEE80211_AUTH_NONE;
2876 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2879 device_printf(sc->ndis_dev,
2880 "get wep status failed: %d\n", rval);
2882 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2883 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2885 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2889 ndis_ifioctl(ifp, command, data)
2894 struct ndis_softc *sc = ifp->if_softc;
2895 struct ifreq *ifr = (struct ifreq *) data;
2902 if (ifp->if_flags & IFF_UP) {
2903 if (sc->ndis_running &&
2904 ifp->if_flags & IFF_PROMISC &&
2905 !(sc->ndis_if_flags & IFF_PROMISC)) {
2907 NDIS_PACKET_TYPE_PROMISCUOUS;
2908 i = sizeof(sc->ndis_filter);
2909 error = ndis_set_info(sc,
2910 OID_GEN_CURRENT_PACKET_FILTER,
2911 &sc->ndis_filter, &i);
2912 } else if (sc->ndis_running &&
2913 !(ifp->if_flags & IFF_PROMISC) &&
2914 sc->ndis_if_flags & IFF_PROMISC) {
2916 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2917 i = sizeof(sc->ndis_filter);
2918 error = ndis_set_info(sc,
2919 OID_GEN_CURRENT_PACKET_FILTER,
2920 &sc->ndis_filter, &i);
2924 if (sc->ndis_running)
2927 sc->ndis_if_flags = ifp->if_flags;
2937 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2940 ifp->if_capenable = ifr->ifr_reqcap;
2941 if (ifp->if_capenable & IFCAP_TXCSUM)
2942 ifp->if_hwassist = sc->ndis_hwassist;
2944 ifp->if_hwassist = 0;
2945 ndis_set_offload(sc);
2948 error = ether_ioctl(ifp, command, data);
2952 /*NDIS_UNLOCK(sc);*/
2958 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2960 struct ndis_softc *sc = ic->ic_softc;
2961 struct ifreq *ifr = data;
2962 struct ndis_oid_data oid;
2963 struct ndis_evt evt;
2964 void *oidbuf = NULL;
2967 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2973 error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid));
2976 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2977 error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid),
2982 free(oidbuf, M_TEMP);
2988 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2991 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2993 case SIOCGPRIVATE_0:
2995 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3000 error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt));
3005 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3011 ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2);
3016 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3017 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3018 (caddr_t)ifr_data_get_ptr(ifr) +
3019 (sizeof(uint32_t) * 2),
3020 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3025 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3026 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3028 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3029 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3030 NDIS_EVTINC(sc->ndis_evtcidx);
3041 error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid));
3044 error = copyout(oidbuf,
3045 (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len);
3048 free(oidbuf, M_TEMP);
3054 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3056 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3057 ndis_80211_key rkey;
3060 bzero((char *)&rkey, sizeof(rkey));
3064 rkey.nk_keyidx = key->wk_keyix;
3066 bcopy(vap->iv_ifp->if_broadcastaddr,
3067 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3069 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3078 * In theory this could be called for any key, but we'll
3079 * only use it for WPA TKIP or AES keys. These need to be
3080 * set after initial authentication with the AP.
3083 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3085 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3086 ndis_80211_key rkey;
3089 switch (key->wk_cipher->ic_cipher) {
3090 case IEEE80211_CIPHER_TKIP:
3092 len = sizeof(ndis_80211_key);
3093 bzero((char *)&rkey, sizeof(rkey));
3096 rkey.nk_keylen = key->wk_keylen;
3098 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3099 rkey.nk_keylen += 16;
3101 /* key index - gets weird in NDIS */
3103 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3104 rkey.nk_keyidx = key->wk_keyix;
3108 if (key->wk_flags & IEEE80211_KEY_XMIT)
3109 rkey.nk_keyidx |= 1 << 31;
3111 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3112 bcopy(ieee80211broadcastaddr,
3113 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3115 bcopy(vap->iv_bss->ni_bssid,
3116 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3118 rkey.nk_keyidx |= 1 << 30;
3121 /* need to set bit 29 based on keyrsc */
3122 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3125 rkey.nk_keyidx |= 1 << 29;
3127 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3128 bcopy(key->wk_key, rkey.nk_keydata, 16);
3129 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3130 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3132 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3134 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3136 case IEEE80211_CIPHER_WEP:
3140 * I don't know how to set up keys for the AES
3141 * cipher yet. Is it the same as TKIP?
3143 case IEEE80211_CIPHER_AES_CCM:
3149 /* We need to return 1 for success, 0 for failure. */
3158 ndis_resettask(d, arg)
3162 struct ndis_softc *sc;
3169 * Stop the adapter and free any mbufs allocated to the
3173 ndis_stop(struct ndis_softc *sc)
3177 callout_drain(&sc->ndis_stat_callout);
3180 sc->ndis_tx_timer = 0;
3182 if (!sc->ndis_80211)
3183 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3184 sc->ndis_running = 0;
3187 if (sc->ndis_iftype != PNPBus ||
3188 (sc->ndis_iftype == PNPBus &&
3189 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3194 for (i = 0; i < NDIS_EVENTS; i++) {
3195 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3196 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3197 sc->ndis_evt[i].ne_buf = NULL;
3199 sc->ndis_evt[i].ne_sts = 0;
3200 sc->ndis_evt[i].ne_len = 0;
3202 sc->ndis_evtcidx = 0;
3203 sc->ndis_evtpidx = 0;
3208 * Stop all chip I/O so that the kernel's probe routines don't
3209 * get confused by errant DMAs when rebooting.
3215 struct ndis_softc *sc;
3217 sc = device_get_softc(dev);
3222 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3224 struct ndis_vap *nvp = NDIS_VAP(vap);
3225 struct ieee80211com *ic = vap->iv_ic;
3226 struct ndis_softc *sc = ic->ic_softc;
3227 enum ieee80211_state ostate;
3229 DPRINTF(("%s: %s -> %s\n", __func__,
3230 ieee80211_state_name[vap->iv_state],
3231 ieee80211_state_name[nstate]));
3233 ostate = vap->iv_state;
3234 vap->iv_state = nstate;
3237 /* pass on to net80211 */
3238 case IEEE80211_S_INIT:
3239 case IEEE80211_S_SCAN:
3240 return nvp->newstate(vap, nstate, arg);
3241 case IEEE80211_S_ASSOC:
3242 if (ostate != IEEE80211_S_AUTH) {
3243 IEEE80211_UNLOCK(ic);
3244 ndis_auth_and_assoc(sc, vap);
3248 case IEEE80211_S_AUTH:
3249 IEEE80211_UNLOCK(ic);
3250 ndis_auth_and_assoc(sc, vap);
3251 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3252 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3262 ndis_scan(void *arg)
3264 struct ieee80211vap *vap = arg;
3266 ieee80211_scan_done(vap);
3270 ndis_scan_results(struct ndis_softc *sc)
3272 struct ieee80211com *ic = &sc->ndis_ic;
3273 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3274 ndis_80211_bssid_list_ex *bl;
3275 ndis_wlan_bssid_ex *wb;
3276 struct ieee80211_scanparams sp;
3277 struct ieee80211_frame wh;
3278 struct ieee80211_channel *saved_chan;
3280 int rssi, noise, freq, chanflag;
3281 uint8_t ssid[2+IEEE80211_NWID_LEN];
3282 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3283 uint8_t *frm, *efrm;
3285 saved_chan = ic->ic_curchan;
3288 if (ndis_get_bssid_list(sc, &bl))
3291 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3292 wb = &bl->nblx_bssid[0];
3293 for (i = 0; i < bl->nblx_items; i++) {
3294 memset(&sp, 0, sizeof(sp));
3296 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3297 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3298 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3299 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3300 if (wb->nwbx_privacy)
3301 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3302 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3303 switch (wb->nwbx_netinfra) {
3304 case NDIS_80211_NET_INFRA_IBSS:
3305 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3307 case NDIS_80211_NET_INFRA_BSS:
3308 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3311 sp.rates = &rates[0];
3312 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3313 /* XXX - check units */
3314 if (wb->nwbx_supportedrates[j] == 0)
3317 wb->nwbx_supportedrates[j] & 0x7f;
3320 sp.ssid = (uint8_t *)&ssid[0];
3321 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3322 wb->nwbx_ssid.ns_ssidlen);
3323 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3325 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3326 freq = wb->nwbx_config.nc_dsconfig / 1000;
3327 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3328 /* Hack ic->ic_curchan to be in sync with the scan result */
3329 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3330 if (ic->ic_curchan == NULL)
3331 ic->ic_curchan = &ic->ic_channels[0];
3333 /* Process extended info from AP */
3334 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3335 frm = (uint8_t *)&wb->nwbx_ies;
3336 efrm = frm + wb->nwbx_ielen;
3337 if (efrm - frm < 12)
3339 sp.tstamp = frm; frm += 8;
3340 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3341 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3343 sp.ies_len = efrm - frm;
3346 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3347 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3349 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3350 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3353 /* Restore the channel after messing with it */
3354 ic->ic_curchan = saved_chan;
3358 ndis_scan_start(struct ieee80211com *ic)
3360 struct ndis_softc *sc = ic->ic_softc;
3361 struct ieee80211vap *vap;
3362 struct ieee80211_scan_state *ss;
3363 ndis_80211_ssid ssid;
3367 vap = TAILQ_FIRST(&ic->ic_vaps);
3369 if (!NDIS_INITIALIZED(sc)) {
3370 DPRINTF(("%s: scan aborted\n", __func__));
3371 ieee80211_cancel_scan(vap);
3376 bzero((char *)&ssid, len);
3377 if (ss->ss_nssid == 0)
3378 ssid.ns_ssidlen = 1;
3380 /* Perform a directed scan */
3381 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3382 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3385 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3387 DPRINTF(("%s: set ESSID failed\n", __func__));
3390 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3392 DPRINTF(("%s: scan command failed\n", __func__));
3393 ieee80211_cancel_scan(vap);
3396 /* Set a timer to collect the results */
3397 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3401 ndis_set_channel(struct ieee80211com *ic)
3407 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3413 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3415 /* NB: don't try to abort scan; wait for firmware to finish */
3419 ndis_scan_end(struct ieee80211com *ic)
3421 struct ndis_softc *sc = ic->ic_softc;
3423 ndis_scan_results(sc);