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);
286 * Program the 64-bit multicast hash filter.
290 struct ndis_softc *sc;
293 struct ifmultiaddr *ifma;
294 int len, mclistsz, error;
298 if (!NDIS_INITIALIZED(sc))
305 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
306 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
307 len = sizeof(sc->ndis_filter);
308 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
309 &sc->ndis_filter, &len);
311 device_printf(sc->ndis_dev,
312 "set allmulti failed: %d\n", error);
316 if (CK_STAILQ_EMPTY(&ifp->if_multiaddrs))
319 len = sizeof(mclistsz);
320 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
322 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
324 if (mclist == NULL) {
325 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
329 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
333 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
334 if (ifma->ifma_addr->sa_family != AF_LINK)
336 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
337 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
339 if (len > mclistsz) {
340 if_maddr_runlock(ifp);
341 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
342 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
346 if_maddr_runlock(ifp);
348 len = len * ETHER_ADDR_LEN;
349 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
351 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
352 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
353 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
357 free(mclist, M_TEMP);
359 len = sizeof(sc->ndis_filter);
360 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
361 &sc->ndis_filter, &len);
363 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
368 struct ndis_softc *sc;
370 ndis_task_offload *nto;
371 ndis_task_offload_hdr *ntoh;
372 ndis_task_tcpip_csum *nttc;
376 if (!NDIS_INITIALIZED(sc))
381 /* See if there's anything to set. */
384 error = ndis_probe_offload(sc);
388 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
391 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
392 sizeof(ndis_task_tcpip_csum);
394 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
399 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
400 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
401 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
402 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
403 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
404 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
406 nto = (ndis_task_offload *)((char *)ntoh +
407 ntoh->ntoh_offset_firsttask);
409 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
410 nto->nto_len = sizeof(ndis_task_offload);
411 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
412 nto->nto_offset_nexttask = 0;
413 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
415 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
417 if (ifp->if_capenable & IFCAP_TXCSUM)
418 nttc->nttc_v4tx = sc->ndis_v4tx;
420 if (ifp->if_capenable & IFCAP_RXCSUM)
421 nttc->nttc_v4rx = sc->ndis_v4rx;
423 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
430 ndis_probe_offload(sc)
431 struct ndis_softc *sc;
433 ndis_task_offload *nto;
434 ndis_task_offload_hdr *ntoh;
435 ndis_task_tcpip_csum *nttc = NULL;
437 int len, error, dummy;
442 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
447 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
452 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
453 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
454 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
455 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
456 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
458 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
465 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
470 nto = (ndis_task_offload *)((char *)ntoh +
471 ntoh->ntoh_offset_firsttask);
474 switch (nto->nto_task) {
475 case NDIS_TASK_TCPIP_CSUM:
476 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
478 /* Don't handle these yet. */
479 case NDIS_TASK_IPSEC:
480 case NDIS_TASK_TCP_LARGESEND:
484 if (nto->nto_offset_nexttask == 0)
486 nto = (ndis_task_offload *)((char *)nto +
487 nto->nto_offset_nexttask);
495 sc->ndis_v4tx = nttc->nttc_v4tx;
496 sc->ndis_v4rx = nttc->nttc_v4rx;
498 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
499 sc->ndis_hwassist |= CSUM_IP;
500 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
501 sc->ndis_hwassist |= CSUM_TCP;
502 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
503 sc->ndis_hwassist |= CSUM_UDP;
505 if (sc->ndis_hwassist)
506 ifp->if_capabilities |= IFCAP_TXCSUM;
508 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
509 ifp->if_capabilities |= IFCAP_RXCSUM;
510 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
511 ifp->if_capabilities |= IFCAP_RXCSUM;
512 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
513 ifp->if_capabilities |= IFCAP_RXCSUM;
520 ndis_nettype_chan(uint32_t type)
523 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
524 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
525 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
526 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
528 DPRINTF(("unknown channel nettype %d\n", type));
529 return (IEEE80211_CHAN_B); /* Default to 11B chan */
533 ndis_nettype_mode(uint32_t type)
536 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
537 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
538 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
539 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
541 DPRINTF(("unknown mode nettype %d\n", type));
542 return (IEEE80211_MODE_AUTO);
546 * Attach the interface. Allocate softc structures, do ifmedia
547 * setup and ethernet/BPF attach.
550 ndis_attach(device_t dev)
552 struct ndis_softc *sc;
558 sc = device_get_softc(dev);
560 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
562 KeInitializeSpinLock(&sc->ndis_rxlock);
563 KeInitializeSpinLock(&sc->ndisusb_tasklock);
564 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
565 InitializeListHead(&sc->ndis_shlist);
566 InitializeListHead(&sc->ndisusb_tasklist);
567 InitializeListHead(&sc->ndisusb_xferdonelist);
568 callout_init(&sc->ndis_stat_callout, 1);
569 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
571 /* Create sysctl registry nodes */
572 ndis_create_sysctls(sc);
574 /* Find the PDO for this device instance. */
576 if (sc->ndis_iftype == PCIBus)
577 pdrv = windrv_lookup(0, "PCI Bus");
578 else if (sc->ndis_iftype == PCMCIABus)
579 pdrv = windrv_lookup(0, "PCCARD Bus");
581 pdrv = windrv_lookup(0, "USB Bus");
582 pdo = windrv_find_pdo(pdrv, dev);
585 * Create a new functional device object for this
586 * device. This is what creates the miniport block
587 * for this device instance.
590 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
591 device_printf(dev, "failed to create FDO!\n");
596 /* Tell the user what version of the API the driver is using. */
597 device_printf(dev, "NDIS API version: %d.%d\n",
598 sc->ndis_chars->nmc_version_major,
599 sc->ndis_chars->nmc_version_minor);
601 /* Do resource conversion. */
602 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
603 ndis_convert_res(sc);
605 sc->ndis_block->nmb_rlist = NULL;
607 /* Install our RX and TX interrupt handlers. */
608 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
609 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
610 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
611 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
612 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
614 /* Override the status handler so we can detect link changes. */
615 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
616 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
618 /* Set up work item handlers. */
619 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
620 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
621 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
622 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623 sc->ndisusb_xferdoneitem =
624 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndisusb_taskitem =
626 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
627 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
629 /* Call driver's init routine. */
630 if (ndis_init_nic(sc)) {
631 device_printf(dev, "init handler failed\n");
637 * Figure out how big to make the TX buffer pool.
639 len = sizeof(sc->ndis_maxpkts);
640 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
641 &sc->ndis_maxpkts, &len)) {
642 device_printf(dev, "failed to get max TX packets\n");
648 * If this is a deserialized miniport, we don't have
649 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
651 if (!NDIS_SERIALIZED(sc->ndis_block))
652 sc->ndis_maxpkts = NDIS_TXPKTS;
654 /* Enforce some sanity, just in case. */
656 if (sc->ndis_maxpkts == 0)
657 sc->ndis_maxpkts = 10;
659 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
660 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
662 /* Allocate a pool of ndis_packets for TX encapsulation. */
664 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
665 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
667 if (i != NDIS_STATUS_SUCCESS) {
668 sc->ndis_txpool = NULL;
669 device_printf(dev, "failed to allocate TX packet pool");
674 sc->ndis_txpending = sc->ndis_maxpkts;
677 /* Get supported oid list. */
678 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
680 /* If the NDIS module requested scatter/gather, init maps. */
685 * See if the OID_802_11_CONFIGURATION OID is
686 * supported by this driver. If it is, then this an 802.11
687 * wireless driver, and we should set up media for wireless.
689 for (i = 0; i < sc->ndis_oidcnt; i++)
690 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
696 error = ndis_80211attach(sc);
698 error = ndis_ifattach(sc);
706 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
709 DPRINTF(("attach done.\n"));
710 /* We're done talking to the NIC for now; halt it. */
712 DPRINTF(("halting done.\n"));
718 ndis_80211attach(struct ndis_softc *sc)
720 struct ieee80211com *ic = &sc->ndis_ic;
721 ndis_80211_rates_ex rates;
722 struct ndis_80211_nettype_list *ntl;
724 int mode, i, r, len, nonettypes = 1;
725 uint8_t bands[IEEE80211_MODE_BYTES] = { 0 };
727 callout_init(&sc->ndis_scan_callout, 1);
730 ic->ic_ioctl = ndis_80211ioctl;
731 ic->ic_name = device_get_nameunit(sc->ndis_dev);
732 ic->ic_opmode = IEEE80211_M_STA;
733 ic->ic_phytype = IEEE80211_T_DS;
734 ic->ic_caps = IEEE80211_C_8023ENCAP |
735 IEEE80211_C_STA | IEEE80211_C_IBSS;
736 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
738 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
741 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
742 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
748 for (i = 0; i < ntl->ntl_items; i++) {
749 mode = ndis_nettype_mode(ntl->ntl_type[i]);
752 setbit(ic->ic_modecaps, mode);
755 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
760 /* Default to 11b channels if the card did not supply any */
762 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
763 setbit(bands, IEEE80211_MODE_11B);
766 bzero((char *)&rates, len);
767 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
769 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
771 * Since the supported rates only up to 8 can be supported,
772 * if this is not 802.11b we're just going to be faking it
776 #define TESTSETRATE(x, y) \
779 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
780 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
783 if (i == ic->ic_sup_rates[x].rs_nrates) { \
784 ic->ic_sup_rates[x].rs_rates[i] = (y); \
785 ic->ic_sup_rates[x].rs_nrates++; \
789 #define SETRATE(x, y) \
790 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
792 ic->ic_sup_rates[x].rs_nrates++
794 ic->ic_curmode = IEEE80211_MODE_AUTO;
795 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
796 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
797 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
798 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
799 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
800 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
801 for (i = 0; i < len; i++) {
802 switch (rates[i] & IEEE80211_RATE_VAL) {
808 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
809 /* Lazy-init 802.11b. */
810 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
811 ic->ic_sup_rates[IEEE80211_MODE_11B].
814 SETRATE(IEEE80211_MODE_11B, rates[i]);
815 INCRATE(IEEE80211_MODE_11B);
818 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
819 SETRATE(IEEE80211_MODE_11A, rates[i]);
820 INCRATE(IEEE80211_MODE_11A);
822 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
823 SETRATE(IEEE80211_MODE_11G, rates[i]);
824 INCRATE(IEEE80211_MODE_11G);
831 * If the hardware supports 802.11g, it most
832 * likely supports 802.11b and all of the
833 * 802.11b and 802.11g speeds, so maybe we can
834 * just cheat here. Just how in the heck do
835 * we detect turbo modes, though?
837 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
838 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
839 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
840 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
841 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
843 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
844 TESTSETRATE(IEEE80211_MODE_11G, 48);
845 TESTSETRATE(IEEE80211_MODE_11G, 72);
846 TESTSETRATE(IEEE80211_MODE_11G, 96);
847 TESTSETRATE(IEEE80211_MODE_11G, 108);
849 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
850 TESTSETRATE(IEEE80211_MODE_11A, 48);
851 TESTSETRATE(IEEE80211_MODE_11A, 72);
852 TESTSETRATE(IEEE80211_MODE_11A, 96);
853 TESTSETRATE(IEEE80211_MODE_11A, 108);
860 ieee80211_init_channels(ic, NULL, bands);
863 * To test for WPA support, we need to see if we can
864 * set AUTHENTICATION_MODE to WPA and read it back
868 arg = NDIS_80211_AUTHMODE_WPA;
869 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
871 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
872 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
873 ic->ic_caps |= IEEE80211_C_WPA;
877 * To test for supported ciphers, we set each
878 * available encryption type in descending order.
879 * If ENC3 works, then we have WEP, TKIP and AES.
880 * If only ENC2 works, then we have WEP and TKIP.
881 * If only ENC1 works, then we have just WEP.
884 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
885 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
887 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
888 | IEEE80211_CRYPTO_TKIP
889 | IEEE80211_CRYPTO_AES_CCM;
892 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
893 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
895 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
896 | IEEE80211_CRYPTO_TKIP;
899 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
900 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
902 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
905 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
907 ic->ic_caps |= IEEE80211_C_PMGT;
909 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
911 ic->ic_caps |= IEEE80211_C_TXPMGT;
914 * Get station address from the driver.
916 len = sizeof(ic->ic_macaddr);
917 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
919 ieee80211_ifattach(ic);
920 ic->ic_raw_xmit = ndis_raw_xmit;
921 ic->ic_scan_start = ndis_scan_start;
922 ic->ic_scan_end = ndis_scan_end;
923 ic->ic_set_channel = ndis_set_channel;
924 ic->ic_scan_curchan = ndis_scan_curchan;
925 ic->ic_scan_mindwell = ndis_scan_mindwell;
926 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
927 ic->ic_vap_create = ndis_vap_create;
928 ic->ic_vap_delete = ndis_vap_delete;
929 ic->ic_update_mcast = ndis_update_mcast;
930 ic->ic_update_promisc = ndis_update_promisc;
931 ic->ic_transmit = ndis_80211transmit;
932 ic->ic_parent = ndis_80211parent;
935 ieee80211_announce(ic);
941 ndis_ifattach(struct ndis_softc *sc)
944 u_char eaddr[ETHER_ADDR_LEN];
947 ifp = if_alloc(IFT_ETHER);
953 /* Check for task offload support. */
954 ndis_probe_offload(sc);
957 * Get station address from the driver.
960 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
962 if_initname(ifp, device_get_name(sc->ndis_dev),
963 device_get_unit(sc->ndis_dev));
964 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
965 ifp->if_ioctl = ndis_ifioctl;
966 ifp->if_start = ndis_ifstart;
967 ifp->if_init = ndis_init;
968 ifp->if_baudrate = 10000000;
969 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
970 ifp->if_snd.ifq_drv_maxlen = 25;
971 IFQ_SET_READY(&ifp->if_snd);
972 ifp->if_capenable = ifp->if_capabilities;
973 ifp->if_hwassist = sc->ndis_hwassist;
975 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
977 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
978 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
979 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
980 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
981 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
982 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
983 ether_ifattach(ifp, eaddr);
988 static struct ieee80211vap *
989 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
990 enum ieee80211_opmode opmode, int flags,
991 const uint8_t bssid[IEEE80211_ADDR_LEN],
992 const uint8_t mac[IEEE80211_ADDR_LEN])
994 struct ndis_vap *nvp;
995 struct ieee80211vap *vap;
997 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
999 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1001 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1002 /* override with driver methods */
1003 nvp->newstate = vap->iv_newstate;
1004 vap->iv_newstate = ndis_newstate;
1006 /* complete setup */
1007 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1009 ic->ic_opmode = opmode;
1010 /* install key handing routines */
1011 vap->iv_key_set = ndis_add_key;
1012 vap->iv_key_delete = ndis_del_key;
1017 ndis_vap_delete(struct ieee80211vap *vap)
1019 struct ndis_vap *nvp = NDIS_VAP(vap);
1020 struct ieee80211com *ic = vap->iv_ic;
1021 struct ndis_softc *sc = ic->ic_softc;
1024 callout_drain(&sc->ndis_scan_callout);
1025 ieee80211_vap_detach(vap);
1026 free(nvp, M_80211_VAP);
1030 * Shutdown hardware and free up resources. This can be called any
1031 * time after the mutex has been initialized. It is called in both
1032 * the error case in attach and the normal detach case so it needs
1033 * to be careful about only freeing resources that have actually been
1037 ndis_detach(device_t dev)
1040 struct ndis_softc *sc;
1043 sc = device_get_softc(dev);
1045 if (!sc->ndis_80211)
1050 ifp->if_flags &= ~IFF_UP;
1051 if (device_is_attached(dev)) {
1055 ieee80211_ifdetach(&sc->ndis_ic);
1056 else if (ifp != NULL)
1057 ether_ifdetach(ifp);
1061 if (sc->ndis_tickitem != NULL)
1062 IoFreeWorkItem(sc->ndis_tickitem);
1063 if (sc->ndis_startitem != NULL)
1064 IoFreeWorkItem(sc->ndis_startitem);
1065 if (sc->ndis_resetitem != NULL)
1066 IoFreeWorkItem(sc->ndis_resetitem);
1067 if (sc->ndis_inputitem != NULL)
1068 IoFreeWorkItem(sc->ndis_inputitem);
1069 if (sc->ndisusb_xferdoneitem != NULL)
1070 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1071 if (sc->ndisusb_taskitem != NULL)
1072 IoFreeWorkItem(sc->ndisusb_taskitem);
1074 bus_generic_detach(dev);
1075 ndis_unload_driver(sc);
1078 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1079 if (sc->ndis_res_io)
1080 bus_release_resource(dev, SYS_RES_IOPORT,
1081 sc->ndis_io_rid, sc->ndis_res_io);
1082 if (sc->ndis_res_mem)
1083 bus_release_resource(dev, SYS_RES_MEMORY,
1084 sc->ndis_mem_rid, sc->ndis_res_mem);
1085 if (sc->ndis_res_altmem)
1086 bus_release_resource(dev, SYS_RES_MEMORY,
1087 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1093 ndis_destroy_dma(sc);
1095 if (sc->ndis_txarray)
1096 free(sc->ndis_txarray, M_DEVBUF);
1098 if (!sc->ndis_80211)
1099 ifmedia_removeall(&sc->ifmedia);
1101 if (sc->ndis_txpool != NULL)
1102 NdisFreePacketPool(sc->ndis_txpool);
1104 /* Destroy the PDO for this device. */
1106 if (sc->ndis_iftype == PCIBus)
1107 drv = windrv_lookup(0, "PCI Bus");
1108 else if (sc->ndis_iftype == PCMCIABus)
1109 drv = windrv_lookup(0, "PCCARD Bus");
1111 drv = windrv_lookup(0, "USB Bus");
1113 panic("couldn't find driver object");
1114 windrv_destroy_pdo(drv, dev);
1116 if (sc->ndis_iftype == PCIBus)
1117 bus_dma_tag_destroy(sc->ndis_parent_tag);
1126 struct ndis_softc *sc;
1129 sc = device_get_softc(dev);
1133 if (NDIS_INITIALIZED(sc))
1144 struct ndis_softc *sc;
1147 sc = device_get_softc(dev);
1150 if (NDIS_INITIALIZED(sc))
1157 * The following bunch of routines are here to support drivers that
1158 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1159 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1160 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1164 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1165 ndis_handle adapter;
1171 uint32_t lookaheadlen;
1174 ndis_miniport_block *block;
1184 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1188 /* Save the data provided to us so far. */
1190 m->m_len = lookaheadlen + hdrlen;
1191 m->m_pkthdr.len = pktlen + hdrlen;
1193 m_copyback(m, 0, hdrlen, hdr);
1194 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1196 /* Now create a fake NDIS_PACKET to hold the data */
1198 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1200 if (status != NDIS_STATUS_SUCCESS) {
1207 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1215 p->np_private.npp_head = p->np_private.npp_tail = b;
1216 p->np_private.npp_totlen = m->m_pkthdr.len;
1218 /* Save the packet RX context somewhere. */
1219 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1220 priv->nep_ctx = ctx;
1222 if (!NDIS_SERIALIZED(block))
1223 KeAcquireSpinLock(&block->nmb_lock, &irql);
1225 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1227 if (!NDIS_SERIALIZED(block))
1228 KeReleaseSpinLock(&block->nmb_lock, irql);
1232 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1233 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1237 ndis_rxeof_done(adapter)
1238 ndis_handle adapter;
1240 struct ndis_softc *sc;
1241 ndis_miniport_block *block;
1245 /* Schedule transfer/RX of queued packets. */
1247 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1249 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1253 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1256 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1258 ndis_handle adapter;
1262 ndis_miniport_block *block;
1263 struct ndis_softc *sc;
1272 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1275 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1277 l = block->nmb_packetlist.nle_flink;
1278 while(!IsListEmpty(&block->nmb_packetlist)) {
1279 l = RemoveHeadList((&block->nmb_packetlist));
1280 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1281 InitializeListHead((&p->np_list));
1283 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1288 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1290 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1291 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1292 m->m_len, m->m_pkthdr.len - m->m_len);
1294 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1297 * If status is NDIS_STATUS_PENDING, do nothing and
1298 * wait for a callback to the ndis_rxeof_xfr_done()
1302 m->m_len = m->m_pkthdr.len;
1303 m->m_pkthdr.rcvif = ifp;
1305 if (status == NDIS_STATUS_SUCCESS) {
1306 IoFreeMdl(p->np_private.npp_head);
1308 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1309 mbufq_enqueue(&sc->ndis_rxqueue, m);
1310 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1311 IoQueueWorkItem(sc->ndis_inputitem,
1312 (io_workitem_func)ndis_inputtask_wrap,
1313 WORKQUEUE_CRITICAL, sc);
1316 if (status == NDIS_STATUS_FAILURE)
1319 /* Advance to next packet */
1320 l = block->nmb_packetlist.nle_flink;
1323 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1327 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1330 ndis_rxeof_xfr_done(adapter, packet, status, len)
1331 ndis_handle adapter;
1332 ndis_packet *packet;
1336 ndis_miniport_block *block;
1337 struct ndis_softc *sc;
1342 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1346 IoFreeMdl(packet->np_private.npp_head);
1347 NdisFreePacket(packet);
1349 if (status != NDIS_STATUS_SUCCESS) {
1354 m->m_len = m->m_pkthdr.len;
1355 m->m_pkthdr.rcvif = ifp;
1356 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1357 mbufq_enqueue(&sc->ndis_rxqueue, m);
1358 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1359 IoQueueWorkItem(sc->ndis_inputitem,
1360 (io_workitem_func)ndis_inputtask_wrap,
1361 WORKQUEUE_CRITICAL, sc);
1364 * A frame has been uploaded: pass the resulting mbuf chain up to
1365 * the higher level protocols.
1367 * When handling received NDIS packets, the 'status' field in the
1368 * out-of-band portion of the ndis_packet has special meaning. In the
1369 * most common case, the underlying NDIS driver will set this field
1370 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1371 * take possession of it. We then change the status field to
1372 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1373 * and that we will return it at some point in the future via the
1374 * return packet handler.
1376 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1377 * this means the driver is running out of packet/buffer resources and
1378 * wants to maintain ownership of the packet. In this case, we have to
1379 * copy the packet data into local storage and let the driver keep the
1383 ndis_rxeof(adapter, packets, pktcnt)
1384 ndis_handle adapter;
1385 ndis_packet **packets;
1388 struct ndis_softc *sc;
1389 ndis_miniport_block *block;
1392 ndis_tcpip_csum *csum;
1394 struct mbuf *m0, *m;
1397 block = (ndis_miniport_block *)adapter;
1398 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1402 * There's a slim chance the driver may indicate some packets
1403 * before we're completely ready to handle them. If we detect this,
1404 * we need to return them to the miniport and ignore them.
1406 if (!sc->ndis_running) {
1407 for (i = 0; i < pktcnt; i++) {
1409 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1411 ndis_return_packet(p);
1417 for (i = 0; i < pktcnt; i++) {
1419 /* Stash the softc here so ptom can use it. */
1421 if (ndis_ptom(&m0, p)) {
1422 device_printf(sc->ndis_dev, "ptom failed\n");
1423 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1424 ndis_return_packet(p);
1427 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1428 m = m_dup(m0, M_NOWAIT);
1430 * NOTE: we want to destroy the mbuf here, but
1431 * we don't actually want to return it to the
1432 * driver via the return packet handler. By
1433 * bumping np_refcnt, we can prevent the
1434 * ndis_return_packet() routine from actually
1440 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1444 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1446 m = m_dup(m0, M_NOWAIT);
1447 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1453 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1457 m0->m_pkthdr.rcvif = ifp;
1459 /* Deal with checksum offload. */
1461 if (ifp->if_capenable & IFCAP_RXCSUM &&
1462 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1464 p->np_ext.npe_info[ndis_tcpipcsum_info];
1465 csum = (ndis_tcpip_csum *)&s;
1466 if (csum->u.ntc_rxflags &
1467 NDIS_RXCSUM_IP_PASSED)
1468 m0->m_pkthdr.csum_flags |=
1469 CSUM_IP_CHECKED|CSUM_IP_VALID;
1470 if (csum->u.ntc_rxflags &
1471 (NDIS_RXCSUM_TCP_PASSED |
1472 NDIS_RXCSUM_UDP_PASSED)) {
1473 m0->m_pkthdr.csum_flags |=
1474 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1475 m0->m_pkthdr.csum_data = 0xFFFF;
1479 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1480 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1481 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1482 IoQueueWorkItem(sc->ndis_inputitem,
1483 (io_workitem_func)ndis_inputtask_wrap,
1484 WORKQUEUE_CRITICAL, sc);
1490 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1491 * packets into the stack in order to avoid calling (*ifp->if_input)()
1492 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1493 * 'dispatch level' per-cpu sleep lock).
1496 ndis_inputtask(device_object *dobj, void *arg)
1498 ndis_miniport_block *block;
1499 struct ndis_softc *sc = arg;
1503 block = dobj->do_devext;
1505 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1506 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1507 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1508 if ((sc->ndis_80211 != 0)) {
1509 struct ieee80211com *ic = &sc->ndis_ic;
1510 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1513 vap->iv_deliver_data(vap, vap->iv_bss, m);
1515 struct ifnet *ifp = sc->ifp;
1517 (*ifp->if_input)(ifp, m);
1519 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1521 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1525 * A frame was downloaded to the chip. It's safe for us to clean up
1529 ndis_txeof(adapter, packet, status)
1530 ndis_handle adapter;
1531 ndis_packet *packet;
1535 struct ndis_softc *sc;
1536 ndis_miniport_block *block;
1541 block = (ndis_miniport_block *)adapter;
1542 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1546 idx = packet->np_txidx;
1548 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1550 ndis_free_packet(packet);
1554 sc->ndis_txarray[idx] = NULL;
1555 sc->ndis_txpending++;
1557 if (!sc->ndis_80211) {
1558 struct ifnet *ifp = sc->ifp;
1559 if (status == NDIS_STATUS_SUCCESS)
1560 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1562 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1563 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1565 sc->ndis_tx_timer = 0;
1569 if (!sc->ndis_80211)
1570 IoQueueWorkItem(sc->ndis_startitem,
1571 (io_workitem_func)ndis_ifstarttask_wrap,
1572 WORKQUEUE_CRITICAL, sc);
1573 DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1577 ndis_linksts(adapter, status, sbuf, slen)
1578 ndis_handle adapter;
1583 ndis_miniport_block *block;
1584 struct ndis_softc *sc;
1587 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1588 sc->ndis_sts = status;
1590 /* Event list is all full up, drop this one. */
1593 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1598 /* Cache the event. */
1601 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1603 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1608 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1610 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1611 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1612 NDIS_EVTINC(sc->ndis_evtpidx);
1617 ndis_linksts_done(adapter)
1618 ndis_handle adapter;
1620 ndis_miniport_block *block;
1621 struct ndis_softc *sc;
1625 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1628 if (!NDIS_INITIALIZED(sc))
1631 switch (sc->ndis_sts) {
1632 case NDIS_STATUS_MEDIA_CONNECT:
1633 IoQueueWorkItem(sc->ndis_tickitem,
1634 (io_workitem_func)ndis_ticktask_wrap,
1635 WORKQUEUE_CRITICAL, sc);
1636 if (!sc->ndis_80211)
1637 IoQueueWorkItem(sc->ndis_startitem,
1638 (io_workitem_func)ndis_ifstarttask_wrap,
1639 WORKQUEUE_CRITICAL, sc);
1641 case NDIS_STATUS_MEDIA_DISCONNECT:
1643 IoQueueWorkItem(sc->ndis_tickitem,
1644 (io_workitem_func)ndis_ticktask_wrap,
1645 WORKQUEUE_CRITICAL, sc);
1656 struct ndis_softc *sc;
1660 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1661 IoQueueWorkItem(sc->ndis_tickitem,
1662 (io_workitem_func)ndis_ticktask_wrap,
1663 WORKQUEUE_CRITICAL, sc);
1664 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1667 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1668 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1669 device_printf(sc->ndis_dev, "watchdog timeout\n");
1671 IoQueueWorkItem(sc->ndis_resetitem,
1672 (io_workitem_func)ndis_resettask_wrap,
1673 WORKQUEUE_CRITICAL, sc);
1674 if (!sc->ndis_80211)
1675 IoQueueWorkItem(sc->ndis_startitem,
1676 (io_workitem_func)ndis_ifstarttask_wrap,
1677 WORKQUEUE_CRITICAL, sc);
1680 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1684 ndis_ticktask(device_object *d, void *xsc)
1686 struct ndis_softc *sc = xsc;
1687 ndis_checkforhang_handler hangfunc;
1691 if (!NDIS_INITIALIZED(sc)) {
1697 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1699 if (hangfunc != NULL) {
1700 rval = MSCALL1(hangfunc,
1701 sc->ndis_block->nmb_miniportadapterctx);
1709 if (sc->ndis_link == 0 &&
1710 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1712 if (sc->ndis_80211 != 0) {
1713 struct ieee80211com *ic = &sc->ndis_ic;
1714 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1718 ndis_getstate_80211(sc);
1719 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1721 if_link_state_change(vap->iv_ifp,
1725 if_link_state_change(sc->ifp, LINK_STATE_UP);
1728 if (sc->ndis_link == 1 &&
1729 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1731 if (sc->ndis_80211 != 0) {
1732 struct ieee80211com *ic = &sc->ndis_ic;
1733 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1737 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1739 if_link_state_change(vap->iv_ifp,
1743 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1750 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1752 bus_dma_segment_t *segs;
1758 struct ndis_sc_list *sclist;
1761 if (error || arg == NULL)
1766 sclist->nsl_frags = nseg;
1768 for (i = 0; i < nseg; i++) {
1769 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1770 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1775 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1776 const struct ieee80211_bpf_params *params)
1778 /* no support; just discard */
1780 ieee80211_free_node(ni);
1785 ndis_update_mcast(struct ieee80211com *ic)
1787 struct ndis_softc *sc = ic->ic_softc;
1793 ndis_update_promisc(struct ieee80211com *ic)
1799 ndis_ifstarttask(device_object *d, void *arg)
1801 struct ndis_softc *sc = arg;
1802 DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1806 struct ifnet *ifp = sc->ifp;
1807 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1812 * Main transmit routine. To make NDIS drivers happy, we need to
1813 * transform mbuf chains into NDIS packets and feed them to the
1814 * send packet routines. Most drivers allow you to send several
1815 * packets at once (up to the maxpkts limit). Unfortunately, rather
1816 * that accepting them in the form of a linked list, they expect
1817 * a contiguous array of pointers to packets.
1819 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1820 * we need to perform busdma work here. Those that use map registers
1821 * will do the mapping themselves on a buffer by buffer basis.
1824 ndis_ifstart(struct ifnet *ifp)
1826 struct ndis_softc *sc;
1827 struct mbuf *m = NULL;
1828 ndis_packet **p0 = NULL, *p = NULL;
1829 ndis_tcpip_csum *csum;
1830 int pcnt = 0, status;
1835 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1840 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1842 while(sc->ndis_txpending) {
1843 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1847 NdisAllocatePacket(&status,
1848 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1850 if (status != NDIS_STATUS_SUCCESS)
1853 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1854 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1860 * Save pointer to original mbuf
1861 * so we can free it later.
1864 p = sc->ndis_txarray[sc->ndis_txidx];
1865 p->np_txidx = sc->ndis_txidx;
1867 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1870 * Do scatter/gather processing, if driver requested it.
1873 bus_dmamap_load_mbuf(sc->ndis_ttag,
1874 sc->ndis_tmaps[sc->ndis_txidx], m,
1875 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1876 bus_dmamap_sync(sc->ndis_ttag,
1877 sc->ndis_tmaps[sc->ndis_txidx],
1878 BUS_DMASYNC_PREREAD);
1879 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1882 /* Handle checksum offload. */
1884 if (ifp->if_capenable & IFCAP_TXCSUM &&
1885 m->m_pkthdr.csum_flags) {
1886 csum = (ndis_tcpip_csum *)
1887 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1888 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1889 if (m->m_pkthdr.csum_flags & CSUM_IP)
1890 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1891 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1892 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1893 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1894 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1895 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1899 sc->ndis_txpending--;
1904 * If there's a BPF listener, bounce a copy of this frame
1907 if (!sc->ndis_80211) /* XXX handle 80211 */
1911 * The array that p0 points to must appear contiguous,
1912 * so we must not wrap past the end of sc->ndis_txarray[].
1913 * If it looks like we're about to wrap, break out here
1914 * so the this batch of packets can be transmitted, then
1915 * wait for txeof to ask us to send the rest.
1917 if (sc->ndis_txidx == 0)
1926 if (sc->ndis_txpending == 0)
1927 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1930 * Set a timeout in case the chip goes out to lunch.
1932 sc->ndis_tx_timer = 5;
1937 * According to NDIS documentation, if a driver exports
1938 * a MiniportSendPackets() routine, we prefer that over
1939 * a MiniportSend() routine (which sends just a single
1942 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1943 ndis_send_packets(sc, p0, pcnt);
1945 ndis_send_packet(sc, p);
1951 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1953 struct ndis_softc *sc = ic->ic_softc;
1954 ndis_packet **p0 = NULL, *p = NULL;
1958 if (!sc->ndis_link || !sc->ndis_running) {
1963 if (sc->ndis_txpending == 0) {
1968 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1970 NdisAllocatePacket(&status,
1971 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1973 if (status != NDIS_STATUS_SUCCESS) {
1978 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1984 * Save pointer to original mbuf
1985 * so we can free it later.
1988 p = sc->ndis_txarray[sc->ndis_txidx];
1989 p->np_txidx = sc->ndis_txidx;
1991 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1994 * Do scatter/gather processing, if driver requested it.
1997 bus_dmamap_load_mbuf(sc->ndis_ttag,
1998 sc->ndis_tmaps[sc->ndis_txidx], m,
1999 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2000 bus_dmamap_sync(sc->ndis_ttag,
2001 sc->ndis_tmaps[sc->ndis_txidx],
2002 BUS_DMASYNC_PREREAD);
2003 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2007 sc->ndis_txpending--;
2010 * Set a timeout in case the chip goes out to lunch.
2012 sc->ndis_tx_timer = 5;
2016 * According to NDIS documentation, if a driver exports
2017 * a MiniportSendPackets() routine, we prefer that over
2018 * a MiniportSend() routine (which sends just a single
2021 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2022 ndis_send_packets(sc, p0, 1);
2024 ndis_send_packet(sc, p);
2030 ndis_80211parent(struct ieee80211com *ic)
2032 struct ndis_softc *sc = ic->ic_softc;
2035 if (ic->ic_nrunning > 0) {
2036 if (!sc->ndis_running)
2038 } else if (sc->ndis_running)
2040 /*NDIS_UNLOCK(sc);*/
2044 ndis_init(void *xsc)
2046 struct ndis_softc *sc = xsc;
2050 * Avoid reintializing the link unnecessarily.
2051 * This should be dealt with in a better way by
2052 * fixing the upper layer modules so they don't
2053 * call ifp->if_init() quite as often.
2059 * Cancel pending I/O and free all RX/TX buffers.
2063 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2064 error = ndis_init_nic(sc);
2066 device_printf(sc->ndis_dev,
2067 "failed to initialize the device: %d\n", error);
2072 /* Program the packet filter */
2073 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2074 NDIS_PACKET_TYPE_BROADCAST;
2076 if (sc->ndis_80211) {
2077 struct ieee80211com *ic = &sc->ndis_ic;
2079 if (ic->ic_promisc > 0)
2080 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2082 struct ifnet *ifp = sc->ifp;
2084 if (ifp->if_flags & IFF_PROMISC)
2085 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2088 len = sizeof(sc->ndis_filter);
2090 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2091 &sc->ndis_filter, &len);
2094 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2102 i = sc->ifp->if_mtu;
2104 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2107 * Program the multicast filter, if necessary.
2111 /* Setup task offload. */
2112 ndis_set_offload(sc);
2117 sc->ndis_txpending = sc->ndis_maxpkts;
2120 if (!sc->ndis_80211) {
2121 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2122 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2123 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2126 sc->ndis_tx_timer = 0;
2129 * Some drivers don't set this value. The NDIS spec says
2130 * the default checkforhang timeout is "approximately 2
2131 * seconds." We use 3 seconds, because it seems for some
2132 * drivers, exactly 2 seconds is too fast.
2134 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2135 sc->ndis_block->nmb_checkforhangsecs = 3;
2137 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2138 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2139 sc->ndis_running = 1;
2142 /* XXX force handling */
2144 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2148 * Set media options.
2151 ndis_ifmedia_upd(ifp)
2154 struct ndis_softc *sc;
2158 if (NDIS_INITIALIZED(sc))
2165 * Report current media status.
2168 ndis_ifmedia_sts(ifp, ifmr)
2170 struct ifmediareq *ifmr;
2172 struct ndis_softc *sc;
2173 uint32_t media_info;
2174 ndis_media_state linkstate;
2177 ifmr->ifm_status = IFM_AVALID;
2178 ifmr->ifm_active = IFM_ETHER;
2181 if (!NDIS_INITIALIZED(sc))
2184 len = sizeof(linkstate);
2185 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2186 (void *)&linkstate, &len);
2188 len = sizeof(media_info);
2189 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2190 (void *)&media_info, &len);
2192 if (linkstate == nmc_connected)
2193 ifmr->ifm_status |= IFM_ACTIVE;
2195 switch (media_info) {
2197 ifmr->ifm_active |= IFM_10_T;
2200 ifmr->ifm_active |= IFM_100_TX;
2203 ifmr->ifm_active |= IFM_1000_T;
2206 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2212 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2214 struct ieee80211com *ic = &sc->ndis_ic;
2220 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2221 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2223 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2226 if (cipher == WPA_CSE_TKIP) {
2227 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2229 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2232 if (cipher == WPA_CSE_CCMP) {
2233 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2235 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2238 DPRINTF(("Setting cipher to %d\n", arg));
2240 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2245 /* Check that the cipher was set correctly. */
2248 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2250 if (rval != 0 || arg != save)
2257 * WPA is hairy to set up. Do the work in a separate routine
2258 * so we don't clutter the setstate function too much.
2259 * Important yet undocumented fact: first we have to set the
2260 * authentication mode, _then_ we enable the ciphers. If one
2261 * of the WPA authentication modes isn't enabled, the driver
2262 * might not permit the TKIP or AES ciphers to be selected.
2265 ndis_set_wpa(sc, ie, ielen)
2266 struct ndis_softc *sc;
2270 struct ieee80211_ie_wpa *w;
2277 * Apparently, the only way for us to know what ciphers
2278 * and key management/authentication mode to use is for
2279 * us to inspect the optional information element (IE)
2280 * stored in the 802.11 state machine. This IE should be
2281 * supplied by the WPA supplicant.
2284 w = (struct ieee80211_ie_wpa *)ie;
2286 /* Check for the right kind of IE. */
2287 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2288 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2292 /* Skip over the ucast cipher OIDs. */
2293 pos = (char *)&w->wpa_uciphers[0];
2294 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2296 /* Skip over the authmode count. */
2297 pos += sizeof(u_int16_t);
2300 * Check for the authentication modes. I'm
2301 * pretty sure there's only supposed to be one.
2304 n = (struct ndis_ie *)pos;
2305 if (n->ni_val == WPA_ASE_NONE)
2306 arg = NDIS_80211_AUTHMODE_WPANONE;
2308 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2309 arg = NDIS_80211_AUTHMODE_WPA;
2311 if (n->ni_val == WPA_ASE_8021X_PSK)
2312 arg = NDIS_80211_AUTHMODE_WPAPSK;
2314 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2316 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2319 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2321 /* Now configure the desired ciphers. */
2323 /* First, set up the multicast group cipher. */
2324 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2326 if (ndis_set_cipher(sc, n->ni_val))
2329 /* Now start looking around for the unicast ciphers. */
2330 pos = (char *)&w->wpa_uciphers[0];
2331 n = (struct ndis_ie *)pos;
2333 for (i = 0; i < w->wpa_uciphercnt; i++) {
2334 if (ndis_set_cipher(sc, n->ni_val))
2343 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2345 struct ieee80211vap *vap = ifp->if_softc;
2346 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2350 if (!NDIS_INITIALIZED(sc))
2353 len = sizeof(txrate);
2354 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2355 vap->iv_bss->ni_txrate = txrate / 5000;
2356 ieee80211_media_status(ifp, imr);
2360 ndis_setstate_80211(struct ndis_softc *sc)
2362 struct ieee80211com *ic = &sc->ndis_ic;
2363 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2364 ndis_80211_macaddr bssid;
2365 ndis_80211_config config;
2369 if (!NDIS_INITIALIZED(sc)) {
2370 DPRINTF(("%s: NDIS not initialized\n", __func__));
2374 /* Disassociate and turn off radio. */
2377 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2379 /* Set network infrastructure mode. */
2382 if (ic->ic_opmode == IEEE80211_M_IBSS)
2383 arg = NDIS_80211_NET_INFRA_IBSS;
2385 arg = NDIS_80211_NET_INFRA_BSS;
2387 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2390 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392 /* Set power management */
2394 if (vap->iv_flags & IEEE80211_F_PMGTON)
2395 arg = NDIS_80211_POWERMODE_FAST_PSP;
2397 arg = NDIS_80211_POWERMODE_CAM;
2398 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2401 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2402 ic->ic_txpowlimit < nitems(dBm2mW)) {
2403 arg = dBm2mW[ic->ic_txpowlimit];
2405 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2409 * Default encryption mode to off, authentication
2410 * to open and privacy to 'accept everything.'
2413 arg = NDIS_80211_WEPSTAT_DISABLED;
2414 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2417 arg = NDIS_80211_AUTHMODE_OPEN;
2418 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2421 * Note that OID_802_11_PRIVACY_FILTER is optional:
2422 * not all drivers implement it.
2425 arg = NDIS_80211_PRIVFILT_8021XWEP;
2426 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2428 len = sizeof(config);
2429 bzero((char *)&config, len);
2430 config.nc_length = len;
2431 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2432 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2435 * Some drivers expect us to initialize these values, so
2436 * provide some defaults.
2439 if (config.nc_beaconperiod == 0)
2440 config.nc_beaconperiod = 100;
2441 if (config.nc_atimwin == 0)
2442 config.nc_atimwin = 100;
2443 if (config.nc_fhconfig.ncf_dwelltime == 0)
2444 config.nc_fhconfig.ncf_dwelltime = 200;
2445 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2448 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2449 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2450 IEEE80211_CHAN_5GHZ;
2451 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2452 config.nc_dsconfig =
2453 ic->ic_bsschan->ic_freq * 1000;
2454 len = sizeof(config);
2455 config.nc_length = len;
2456 config.nc_fhconfig.ncf_length =
2457 sizeof(ndis_80211_config_fh);
2458 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2459 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2462 device_printf(sc->ndis_dev, "couldn't change "
2463 "DS config to %ukHz: %d\n",
2464 config.nc_dsconfig, rval);
2467 device_printf(sc->ndis_dev, "couldn't retrieve "
2468 "channel info: %d\n", rval);
2470 /* Set the BSSID to our value so the driver doesn't associate */
2471 len = IEEE80211_ADDR_LEN;
2472 bcopy(vap->iv_myaddr, bssid, len);
2473 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2474 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2476 device_printf(sc->ndis_dev,
2477 "setting BSSID failed: %d\n", rval);
2481 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2483 struct ieee80211_node *ni = vap->iv_bss;
2484 ndis_80211_ssid ssid;
2485 ndis_80211_macaddr bssid;
2487 int i, rval = 0, len, error;
2490 if (!NDIS_INITIALIZED(sc)) {
2491 DPRINTF(("%s: NDIS not initialized\n", __func__));
2496 ndis_setstate_80211(sc);
2498 /* Set network infrastructure mode. */
2501 if (vap->iv_opmode == IEEE80211_M_IBSS)
2502 arg = NDIS_80211_NET_INFRA_IBSS;
2504 arg = NDIS_80211_NET_INFRA_BSS;
2506 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2509 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2511 /* Set RTS threshold */
2514 arg = vap->iv_rtsthreshold;
2515 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2517 /* Set fragmentation threshold */
2520 arg = vap->iv_fragthreshold;
2521 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2525 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2526 !(vap->iv_flags & IEEE80211_F_WPA)) {
2529 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2531 arg = NDIS_80211_AUTHMODE_SHARED;
2532 DPRINTF(("Setting shared auth\n"));
2533 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2536 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2537 if (vap->iv_nw_keys[i].wk_keylen) {
2538 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2539 IEEE80211_CIPHER_WEP)
2541 bzero((char *)&wep, sizeof(wep));
2542 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2545 * 5, 13 and 16 are the only valid
2546 * key lengths. Anything in between
2547 * will be zero padded out to the
2548 * next highest boundary.
2550 if (vap->iv_nw_keys[i].wk_keylen < 5)
2552 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2553 vap->iv_nw_keys[i].wk_keylen < 13)
2555 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2556 vap->iv_nw_keys[i].wk_keylen < 16)
2560 wep.nw_length = (sizeof(uint32_t) * 3)
2562 if (i == vap->iv_def_txkey)
2563 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2564 bcopy(vap->iv_nw_keys[i].wk_key,
2565 wep.nw_keydata, wep.nw_length);
2567 DPRINTF(("Setting WEP key %d\n", i));
2568 rval = ndis_set_info(sc,
2569 OID_802_11_ADD_WEP, &wep, &len);
2571 device_printf(sc->ndis_dev,
2572 "set wepkey failed: %d\n", rval);
2577 DPRINTF(("Setting WEP on\n"));
2578 arg = NDIS_80211_WEPSTAT_ENABLED;
2580 rval = ndis_set_info(sc,
2581 OID_802_11_WEP_STATUS, &arg, &len);
2583 device_printf(sc->ndis_dev,
2584 "enable WEP failed: %d\n", rval);
2585 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2586 arg = NDIS_80211_PRIVFILT_8021XWEP;
2588 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2592 OID_802_11_PRIVACY_FILTER, &arg, &len);
2597 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2598 vap->iv_appie_assocreq != NULL) {
2599 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2600 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2602 device_printf(sc->ndis_dev, "WPA setup failed\n");
2606 /* Set network type. */
2610 switch (vap->iv_curmode) {
2611 case IEEE80211_MODE_11A:
2612 arg = NDIS_80211_NETTYPE_11OFDM5;
2614 case IEEE80211_MODE_11B:
2615 arg = NDIS_80211_NETTYPE_11DS;
2617 case IEEE80211_MODE_11G:
2618 arg = NDIS_80211_NETTYPE_11OFDM24;
2621 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2626 DPRINTF(("Setting network type to %d\n", arg));
2628 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2631 device_printf(sc->ndis_dev,
2632 "set nettype failed: %d\n", rval);
2637 * If the user selected a specific BSSID, try
2638 * to use that one. This is useful in the case where
2639 * there are several APs in range with the same network
2640 * name. To delete the BSSID, we use the broadcast
2641 * address as the BSSID.
2642 * Note that some drivers seem to allow setting a BSSID
2643 * in ad-hoc mode, which has the effect of forcing the
2644 * NIC to create an ad-hoc cell with a specific BSSID,
2645 * instead of a randomly chosen one. However, the net80211
2646 * code makes the assumtion that the BSSID setting is invalid
2647 * when you're in ad-hoc mode, so we don't allow that here.
2650 len = IEEE80211_ADDR_LEN;
2651 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2652 vap->iv_opmode != IEEE80211_M_IBSS)
2653 bcopy(ni->ni_bssid, bssid, len);
2655 bcopy(ieee80211broadcastaddr, bssid, len);
2657 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2658 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2660 device_printf(sc->ndis_dev,
2661 "setting BSSID failed: %d\n", rval);
2663 /* Set SSID -- always do this last. */
2666 if (ndis_debug > 0) {
2667 printf("Setting ESSID to ");
2668 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2674 bzero((char *)&ssid, len);
2675 ssid.ns_ssidlen = ni->ni_esslen;
2676 if (ssid.ns_ssidlen == 0) {
2677 ssid.ns_ssidlen = 1;
2679 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2681 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2684 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2690 ndis_get_bssid_list(sc, bl)
2691 struct ndis_softc *sc;
2692 ndis_80211_bssid_list_ex **bl;
2696 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2697 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2701 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2702 if (error == ENOSPC) {
2703 free(*bl, M_DEVBUF);
2704 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2708 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2711 DPRINTF(("%s: failed to read\n", __func__));
2712 free(*bl, M_DEVBUF);
2720 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2722 struct ieee80211com *ic = &sc->ndis_ic;
2723 struct ieee80211vap *vap;
2724 struct ieee80211_node *ni;
2725 ndis_80211_bssid_list_ex *bl;
2726 ndis_wlan_bssid_ex *bs;
2727 ndis_80211_macaddr bssid;
2733 len = sizeof(bssid);
2734 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2736 device_printf(sc->ndis_dev, "failed to get bssid\n");
2740 vap = TAILQ_FIRST(&ic->ic_vaps);
2743 error = ndis_get_bssid_list(sc, &bl);
2747 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2748 for (i = 0; i < bl->nblx_items; i++) {
2749 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2750 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2751 if (*assoc == NULL) {
2755 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2757 if (ic->ic_opmode == IEEE80211_M_STA)
2758 ni->ni_associd = 1 | 0xc000; /* fake associd */
2761 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2769 ndis_getstate_80211(struct ndis_softc *sc)
2771 struct ieee80211com *ic = &sc->ndis_ic;
2772 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2773 struct ieee80211_node *ni = vap->iv_bss;
2774 ndis_wlan_bssid_ex *bs;
2775 int rval, len, i = 0;
2779 if (!NDIS_INITIALIZED(sc))
2782 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2785 /* We're associated, retrieve info on the current bssid. */
2786 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2787 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2788 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2790 /* Get SSID from current association info. */
2791 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2792 bs->nwbx_ssid.ns_ssidlen);
2793 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2795 if (ic->ic_caps & IEEE80211_C_PMGT) {
2797 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2800 device_printf(sc->ndis_dev,
2801 "get power mode failed: %d\n", rval);
2802 if (arg == NDIS_80211_POWERMODE_CAM)
2803 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2805 vap->iv_flags |= IEEE80211_F_PMGTON;
2809 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2811 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2812 for (i = 0; i < nitems(dBm2mW); i++)
2813 if (dBm2mW[i] >= arg)
2815 ic->ic_txpowlimit = i;
2819 * Use the current association information to reflect
2820 * what channel we're on.
2822 ic->ic_curchan = ieee80211_find_channel(ic,
2823 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2824 if (ic->ic_curchan == NULL)
2825 ic->ic_curchan = &ic->ic_channels[0];
2826 ni->ni_chan = ic->ic_curchan;
2827 ic->ic_bsschan = ic->ic_curchan;
2832 * Determine current authentication mode.
2835 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2837 device_printf(sc->ndis_dev,
2838 "get authmode status failed: %d\n", rval);
2840 vap->iv_flags &= ~IEEE80211_F_WPA;
2842 case NDIS_80211_AUTHMODE_OPEN:
2843 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2845 case NDIS_80211_AUTHMODE_SHARED:
2846 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2848 case NDIS_80211_AUTHMODE_AUTO:
2849 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2851 case NDIS_80211_AUTHMODE_WPA:
2852 case NDIS_80211_AUTHMODE_WPAPSK:
2853 case NDIS_80211_AUTHMODE_WPANONE:
2854 ni->ni_authmode = IEEE80211_AUTH_WPA;
2855 vap->iv_flags |= IEEE80211_F_WPA1;
2857 case NDIS_80211_AUTHMODE_WPA2:
2858 case NDIS_80211_AUTHMODE_WPA2PSK:
2859 ni->ni_authmode = IEEE80211_AUTH_WPA;
2860 vap->iv_flags |= IEEE80211_F_WPA2;
2863 ni->ni_authmode = IEEE80211_AUTH_NONE;
2869 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2872 device_printf(sc->ndis_dev,
2873 "get wep status failed: %d\n", rval);
2875 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2876 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2878 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2882 ndis_ifioctl(ifp, command, data)
2887 struct ndis_softc *sc = ifp->if_softc;
2888 struct ifreq *ifr = (struct ifreq *) data;
2895 if (ifp->if_flags & IFF_UP) {
2896 if (sc->ndis_running &&
2897 ifp->if_flags & IFF_PROMISC &&
2898 !(sc->ndis_if_flags & IFF_PROMISC)) {
2900 NDIS_PACKET_TYPE_PROMISCUOUS;
2901 i = sizeof(sc->ndis_filter);
2902 error = ndis_set_info(sc,
2903 OID_GEN_CURRENT_PACKET_FILTER,
2904 &sc->ndis_filter, &i);
2905 } else if (sc->ndis_running &&
2906 !(ifp->if_flags & IFF_PROMISC) &&
2907 sc->ndis_if_flags & IFF_PROMISC) {
2909 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2910 i = sizeof(sc->ndis_filter);
2911 error = ndis_set_info(sc,
2912 OID_GEN_CURRENT_PACKET_FILTER,
2913 &sc->ndis_filter, &i);
2917 if (sc->ndis_running)
2920 sc->ndis_if_flags = ifp->if_flags;
2930 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2933 ifp->if_capenable = ifr->ifr_reqcap;
2934 if (ifp->if_capenable & IFCAP_TXCSUM)
2935 ifp->if_hwassist = sc->ndis_hwassist;
2937 ifp->if_hwassist = 0;
2938 ndis_set_offload(sc);
2941 error = ether_ioctl(ifp, command, data);
2945 /*NDIS_UNLOCK(sc);*/
2951 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2953 struct ndis_softc *sc = ic->ic_softc;
2954 struct ifreq *ifr = data;
2955 struct ndis_oid_data oid;
2956 struct ndis_evt evt;
2957 void *oidbuf = NULL;
2960 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2966 error = copyin(ifr_data_get_ptr(ifr), &oid, sizeof(oid));
2969 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2970 error = copyin((caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid),
2975 free(oidbuf, M_TEMP);
2981 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2984 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2986 case SIOCGPRIVATE_0:
2988 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2993 error = copyin(ifr_data_get_ptr(ifr), &evt, sizeof(evt));
2998 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3003 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3004 ifr_data_get_ptr(ifr), sizeof(uint32_t) * 2);
3009 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3011 (caddr_t)ifr_data_get_ptr(ifr) +
3012 (sizeof(uint32_t) * 2),
3013 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3018 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3019 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3021 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3022 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3023 NDIS_EVTINC(sc->ndis_evtcidx);
3034 error = copyout(&oid, ifr_data_get_ptr(ifr), sizeof(oid));
3037 error = copyout(oidbuf,
3038 (caddr_t)ifr_data_get_ptr(ifr) + sizeof(oid), oid.len);
3041 free(oidbuf, M_TEMP);
3047 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3049 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3050 ndis_80211_key rkey;
3053 bzero((char *)&rkey, sizeof(rkey));
3057 rkey.nk_keyidx = key->wk_keyix;
3059 bcopy(vap->iv_ifp->if_broadcastaddr,
3060 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3062 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3071 * In theory this could be called for any key, but we'll
3072 * only use it for WPA TKIP or AES keys. These need to be
3073 * set after initial authentication with the AP.
3076 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3078 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3079 ndis_80211_key rkey;
3082 switch (key->wk_cipher->ic_cipher) {
3083 case IEEE80211_CIPHER_TKIP:
3085 len = sizeof(ndis_80211_key);
3086 bzero((char *)&rkey, sizeof(rkey));
3089 rkey.nk_keylen = key->wk_keylen;
3091 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3092 rkey.nk_keylen += 16;
3094 /* key index - gets weird in NDIS */
3096 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3097 rkey.nk_keyidx = key->wk_keyix;
3101 if (key->wk_flags & IEEE80211_KEY_XMIT)
3102 rkey.nk_keyidx |= 1 << 31;
3104 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3105 bcopy(ieee80211broadcastaddr,
3106 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3108 bcopy(vap->iv_bss->ni_bssid,
3109 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3111 rkey.nk_keyidx |= 1 << 30;
3114 /* need to set bit 29 based on keyrsc */
3115 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3118 rkey.nk_keyidx |= 1 << 29;
3120 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3121 bcopy(key->wk_key, rkey.nk_keydata, 16);
3122 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3123 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3125 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3127 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3129 case IEEE80211_CIPHER_WEP:
3133 * I don't know how to set up keys for the AES
3134 * cipher yet. Is it the same as TKIP?
3136 case IEEE80211_CIPHER_AES_CCM:
3142 /* We need to return 1 for success, 0 for failure. */
3151 ndis_resettask(d, arg)
3155 struct ndis_softc *sc;
3162 * Stop the adapter and free any mbufs allocated to the
3166 ndis_stop(struct ndis_softc *sc)
3170 callout_drain(&sc->ndis_stat_callout);
3173 sc->ndis_tx_timer = 0;
3175 if (!sc->ndis_80211)
3176 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3177 sc->ndis_running = 0;
3180 if (sc->ndis_iftype != PNPBus ||
3181 (sc->ndis_iftype == PNPBus &&
3182 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3187 for (i = 0; i < NDIS_EVENTS; i++) {
3188 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3189 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3190 sc->ndis_evt[i].ne_buf = NULL;
3192 sc->ndis_evt[i].ne_sts = 0;
3193 sc->ndis_evt[i].ne_len = 0;
3195 sc->ndis_evtcidx = 0;
3196 sc->ndis_evtpidx = 0;
3201 * Stop all chip I/O so that the kernel's probe routines don't
3202 * get confused by errant DMAs when rebooting.
3208 struct ndis_softc *sc;
3210 sc = device_get_softc(dev);
3215 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3217 struct ndis_vap *nvp = NDIS_VAP(vap);
3218 struct ieee80211com *ic = vap->iv_ic;
3219 struct ndis_softc *sc = ic->ic_softc;
3220 enum ieee80211_state ostate;
3222 DPRINTF(("%s: %s -> %s\n", __func__,
3223 ieee80211_state_name[vap->iv_state],
3224 ieee80211_state_name[nstate]));
3226 ostate = vap->iv_state;
3227 vap->iv_state = nstate;
3230 /* pass on to net80211 */
3231 case IEEE80211_S_INIT:
3232 case IEEE80211_S_SCAN:
3233 return nvp->newstate(vap, nstate, arg);
3234 case IEEE80211_S_ASSOC:
3235 if (ostate != IEEE80211_S_AUTH) {
3236 IEEE80211_UNLOCK(ic);
3237 ndis_auth_and_assoc(sc, vap);
3241 case IEEE80211_S_AUTH:
3242 IEEE80211_UNLOCK(ic);
3243 ndis_auth_and_assoc(sc, vap);
3244 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3245 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3255 ndis_scan(void *arg)
3257 struct ieee80211vap *vap = arg;
3259 ieee80211_scan_done(vap);
3263 ndis_scan_results(struct ndis_softc *sc)
3265 struct ieee80211com *ic = &sc->ndis_ic;
3266 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3267 ndis_80211_bssid_list_ex *bl;
3268 ndis_wlan_bssid_ex *wb;
3269 struct ieee80211_scanparams sp;
3270 struct ieee80211_frame wh;
3271 struct ieee80211_channel *saved_chan;
3273 int rssi, noise, freq, chanflag;
3274 uint8_t ssid[2+IEEE80211_NWID_LEN];
3275 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3276 uint8_t *frm, *efrm;
3278 saved_chan = ic->ic_curchan;
3281 if (ndis_get_bssid_list(sc, &bl))
3284 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3285 wb = &bl->nblx_bssid[0];
3286 for (i = 0; i < bl->nblx_items; i++) {
3287 memset(&sp, 0, sizeof(sp));
3289 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3290 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3291 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3292 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3293 if (wb->nwbx_privacy)
3294 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3295 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3296 switch (wb->nwbx_netinfra) {
3297 case NDIS_80211_NET_INFRA_IBSS:
3298 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3300 case NDIS_80211_NET_INFRA_BSS:
3301 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3304 sp.rates = &rates[0];
3305 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3306 /* XXX - check units */
3307 if (wb->nwbx_supportedrates[j] == 0)
3310 wb->nwbx_supportedrates[j] & 0x7f;
3313 sp.ssid = (uint8_t *)&ssid[0];
3314 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3315 wb->nwbx_ssid.ns_ssidlen);
3316 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3318 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3319 freq = wb->nwbx_config.nc_dsconfig / 1000;
3320 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3321 /* Hack ic->ic_curchan to be in sync with the scan result */
3322 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3323 if (ic->ic_curchan == NULL)
3324 ic->ic_curchan = &ic->ic_channels[0];
3326 /* Process extended info from AP */
3327 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3328 frm = (uint8_t *)&wb->nwbx_ies;
3329 efrm = frm + wb->nwbx_ielen;
3330 if (efrm - frm < 12)
3332 sp.tstamp = frm; frm += 8;
3333 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3334 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3336 sp.ies_len = efrm - frm;
3339 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3340 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3342 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3343 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3346 /* Restore the channel after messing with it */
3347 ic->ic_curchan = saved_chan;
3351 ndis_scan_start(struct ieee80211com *ic)
3353 struct ndis_softc *sc = ic->ic_softc;
3354 struct ieee80211vap *vap;
3355 struct ieee80211_scan_state *ss;
3356 ndis_80211_ssid ssid;
3360 vap = TAILQ_FIRST(&ic->ic_vaps);
3362 if (!NDIS_INITIALIZED(sc)) {
3363 DPRINTF(("%s: scan aborted\n", __func__));
3364 ieee80211_cancel_scan(vap);
3369 bzero((char *)&ssid, len);
3370 if (ss->ss_nssid == 0)
3371 ssid.ns_ssidlen = 1;
3373 /* Perform a directed scan */
3374 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3375 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3378 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3380 DPRINTF(("%s: set ESSID failed\n", __func__));
3383 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3385 DPRINTF(("%s: scan command failed\n", __func__));
3386 ieee80211_cancel_scan(vap);
3389 /* Set a timer to collect the results */
3390 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3394 ndis_set_channel(struct ieee80211com *ic)
3400 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3406 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3408 /* NB: don't try to abort scan; wait for firmware to finish */
3412 ndis_scan_end(struct ieee80211com *ic)
3414 struct ndis_softc *sc = ic->ic_softc;
3416 ndis_scan_results(sc);