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 (TAILQ_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 TAILQ_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 if (sc->ndis_iftype == PCMCIABus) {
572 error = ndis_alloc_amem(sc);
574 device_printf(dev, "failed to allocate "
575 "attribute memory\n");
580 /* Create sysctl registry nodes */
581 ndis_create_sysctls(sc);
583 /* Find the PDO for this device instance. */
585 if (sc->ndis_iftype == PCIBus)
586 pdrv = windrv_lookup(0, "PCI Bus");
587 else if (sc->ndis_iftype == PCMCIABus)
588 pdrv = windrv_lookup(0, "PCCARD Bus");
590 pdrv = windrv_lookup(0, "USB Bus");
591 pdo = windrv_find_pdo(pdrv, dev);
594 * Create a new functional device object for this
595 * device. This is what creates the miniport block
596 * for this device instance.
599 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
600 device_printf(dev, "failed to create FDO!\n");
605 /* Tell the user what version of the API the driver is using. */
606 device_printf(dev, "NDIS API version: %d.%d\n",
607 sc->ndis_chars->nmc_version_major,
608 sc->ndis_chars->nmc_version_minor);
610 /* Do resource conversion. */
611 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
612 ndis_convert_res(sc);
614 sc->ndis_block->nmb_rlist = NULL;
616 /* Install our RX and TX interrupt handlers. */
617 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
618 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
619 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
620 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
621 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
623 /* Override the status handler so we can detect link changes. */
624 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
625 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
627 /* Set up work item handlers. */
628 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
629 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
631 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
632 sc->ndisusb_xferdoneitem =
633 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
634 sc->ndisusb_taskitem =
635 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
636 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
638 /* Call driver's init routine. */
639 if (ndis_init_nic(sc)) {
640 device_printf(dev, "init handler failed\n");
646 * Figure out how big to make the TX buffer pool.
648 len = sizeof(sc->ndis_maxpkts);
649 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
650 &sc->ndis_maxpkts, &len)) {
651 device_printf(dev, "failed to get max TX packets\n");
657 * If this is a deserialized miniport, we don't have
658 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
660 if (!NDIS_SERIALIZED(sc->ndis_block))
661 sc->ndis_maxpkts = NDIS_TXPKTS;
663 /* Enforce some sanity, just in case. */
665 if (sc->ndis_maxpkts == 0)
666 sc->ndis_maxpkts = 10;
668 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
669 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
671 /* Allocate a pool of ndis_packets for TX encapsulation. */
673 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
674 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
676 if (i != NDIS_STATUS_SUCCESS) {
677 sc->ndis_txpool = NULL;
678 device_printf(dev, "failed to allocate TX packet pool");
683 sc->ndis_txpending = sc->ndis_maxpkts;
686 /* Get supported oid list. */
687 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
689 /* If the NDIS module requested scatter/gather, init maps. */
694 * See if the OID_802_11_CONFIGURATION OID is
695 * supported by this driver. If it is, then this an 802.11
696 * wireless driver, and we should set up media for wireless.
698 for (i = 0; i < sc->ndis_oidcnt; i++)
699 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
705 error = ndis_80211attach(sc);
707 error = ndis_ifattach(sc);
715 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
718 DPRINTF(("attach done.\n"));
719 /* We're done talking to the NIC for now; halt it. */
721 DPRINTF(("halting done.\n"));
727 ndis_80211attach(struct ndis_softc *sc)
729 struct ieee80211com *ic = &sc->ndis_ic;
730 ndis_80211_rates_ex rates;
731 struct ndis_80211_nettype_list *ntl;
733 int mode, i, r, len, nonettypes = 1;
734 uint8_t bands[IEEE80211_MODE_BYTES] = { 0 };
736 callout_init(&sc->ndis_scan_callout, 1);
739 ic->ic_ioctl = ndis_80211ioctl;
740 ic->ic_name = device_get_nameunit(sc->ndis_dev);
741 ic->ic_opmode = IEEE80211_M_STA;
742 ic->ic_phytype = IEEE80211_T_DS;
743 ic->ic_caps = IEEE80211_C_8023ENCAP |
744 IEEE80211_C_STA | IEEE80211_C_IBSS;
745 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
747 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
750 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
751 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
757 for (i = 0; i < ntl->ntl_items; i++) {
758 mode = ndis_nettype_mode(ntl->ntl_type[i]);
761 setbit(ic->ic_modecaps, mode);
764 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
769 /* Default to 11b channels if the card did not supply any */
771 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
772 setbit(bands, IEEE80211_MODE_11B);
775 bzero((char *)&rates, len);
776 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
778 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
780 * Since the supported rates only up to 8 can be supported,
781 * if this is not 802.11b we're just going to be faking it
785 #define TESTSETRATE(x, y) \
788 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
789 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
792 if (i == ic->ic_sup_rates[x].rs_nrates) { \
793 ic->ic_sup_rates[x].rs_rates[i] = (y); \
794 ic->ic_sup_rates[x].rs_nrates++; \
798 #define SETRATE(x, y) \
799 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
801 ic->ic_sup_rates[x].rs_nrates++
803 ic->ic_curmode = IEEE80211_MODE_AUTO;
804 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
805 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
806 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
807 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
808 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
809 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
810 for (i = 0; i < len; i++) {
811 switch (rates[i] & IEEE80211_RATE_VAL) {
817 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
818 /* Lazy-init 802.11b. */
819 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
820 ic->ic_sup_rates[IEEE80211_MODE_11B].
823 SETRATE(IEEE80211_MODE_11B, rates[i]);
824 INCRATE(IEEE80211_MODE_11B);
827 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
828 SETRATE(IEEE80211_MODE_11A, rates[i]);
829 INCRATE(IEEE80211_MODE_11A);
831 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
832 SETRATE(IEEE80211_MODE_11G, rates[i]);
833 INCRATE(IEEE80211_MODE_11G);
840 * If the hardware supports 802.11g, it most
841 * likely supports 802.11b and all of the
842 * 802.11b and 802.11g speeds, so maybe we can
843 * just cheat here. Just how in the heck do
844 * we detect turbo modes, though?
846 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
847 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
848 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
849 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
850 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
852 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
853 TESTSETRATE(IEEE80211_MODE_11G, 48);
854 TESTSETRATE(IEEE80211_MODE_11G, 72);
855 TESTSETRATE(IEEE80211_MODE_11G, 96);
856 TESTSETRATE(IEEE80211_MODE_11G, 108);
858 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
859 TESTSETRATE(IEEE80211_MODE_11A, 48);
860 TESTSETRATE(IEEE80211_MODE_11A, 72);
861 TESTSETRATE(IEEE80211_MODE_11A, 96);
862 TESTSETRATE(IEEE80211_MODE_11A, 108);
869 ieee80211_init_channels(ic, NULL, bands);
872 * To test for WPA support, we need to see if we can
873 * set AUTHENTICATION_MODE to WPA and read it back
877 arg = NDIS_80211_AUTHMODE_WPA;
878 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
880 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
881 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
882 ic->ic_caps |= IEEE80211_C_WPA;
886 * To test for supported ciphers, we set each
887 * available encryption type in descending order.
888 * If ENC3 works, then we have WEP, TKIP and AES.
889 * If only ENC2 works, then we have WEP and TKIP.
890 * If only ENC1 works, then we have just WEP.
893 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
894 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
896 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
897 | IEEE80211_CRYPTO_TKIP
898 | IEEE80211_CRYPTO_AES_CCM;
901 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
902 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
904 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
905 | IEEE80211_CRYPTO_TKIP;
908 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
909 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
911 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
914 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
916 ic->ic_caps |= IEEE80211_C_PMGT;
918 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
920 ic->ic_caps |= IEEE80211_C_TXPMGT;
923 * Get station address from the driver.
925 len = sizeof(ic->ic_macaddr);
926 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
928 ieee80211_ifattach(ic);
929 ic->ic_raw_xmit = ndis_raw_xmit;
930 ic->ic_scan_start = ndis_scan_start;
931 ic->ic_scan_end = ndis_scan_end;
932 ic->ic_set_channel = ndis_set_channel;
933 ic->ic_scan_curchan = ndis_scan_curchan;
934 ic->ic_scan_mindwell = ndis_scan_mindwell;
935 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
936 ic->ic_vap_create = ndis_vap_create;
937 ic->ic_vap_delete = ndis_vap_delete;
938 ic->ic_update_mcast = ndis_update_mcast;
939 ic->ic_update_promisc = ndis_update_promisc;
940 ic->ic_transmit = ndis_80211transmit;
941 ic->ic_parent = ndis_80211parent;
944 ieee80211_announce(ic);
950 ndis_ifattach(struct ndis_softc *sc)
953 u_char eaddr[ETHER_ADDR_LEN];
956 ifp = if_alloc(IFT_ETHER);
962 /* Check for task offload support. */
963 ndis_probe_offload(sc);
966 * Get station address from the driver.
969 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
971 if_initname(ifp, device_get_name(sc->ndis_dev),
972 device_get_unit(sc->ndis_dev));
973 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
974 ifp->if_ioctl = ndis_ifioctl;
975 ifp->if_start = ndis_ifstart;
976 ifp->if_init = ndis_init;
977 ifp->if_baudrate = 10000000;
978 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
979 ifp->if_snd.ifq_drv_maxlen = 25;
980 IFQ_SET_READY(&ifp->if_snd);
981 ifp->if_capenable = ifp->if_capabilities;
982 ifp->if_hwassist = sc->ndis_hwassist;
984 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
986 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
987 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
988 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
989 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
990 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
991 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
992 ether_ifattach(ifp, eaddr);
997 static struct ieee80211vap *
998 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
999 enum ieee80211_opmode opmode, int flags,
1000 const uint8_t bssid[IEEE80211_ADDR_LEN],
1001 const uint8_t mac[IEEE80211_ADDR_LEN])
1003 struct ndis_vap *nvp;
1004 struct ieee80211vap *vap;
1006 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1008 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1010 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1011 /* override with driver methods */
1012 nvp->newstate = vap->iv_newstate;
1013 vap->iv_newstate = ndis_newstate;
1015 /* complete setup */
1016 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1018 ic->ic_opmode = opmode;
1019 /* install key handing routines */
1020 vap->iv_key_set = ndis_add_key;
1021 vap->iv_key_delete = ndis_del_key;
1026 ndis_vap_delete(struct ieee80211vap *vap)
1028 struct ndis_vap *nvp = NDIS_VAP(vap);
1029 struct ieee80211com *ic = vap->iv_ic;
1030 struct ndis_softc *sc = ic->ic_softc;
1033 callout_drain(&sc->ndis_scan_callout);
1034 ieee80211_vap_detach(vap);
1035 free(nvp, M_80211_VAP);
1039 * Shutdown hardware and free up resources. This can be called any
1040 * time after the mutex has been initialized. It is called in both
1041 * the error case in attach and the normal detach case so it needs
1042 * to be careful about only freeing resources that have actually been
1046 ndis_detach(device_t dev)
1049 struct ndis_softc *sc;
1052 sc = device_get_softc(dev);
1054 if (!sc->ndis_80211)
1059 ifp->if_flags &= ~IFF_UP;
1060 if (device_is_attached(dev)) {
1064 ieee80211_ifdetach(&sc->ndis_ic);
1065 else if (ifp != NULL)
1066 ether_ifdetach(ifp);
1070 if (sc->ndis_tickitem != NULL)
1071 IoFreeWorkItem(sc->ndis_tickitem);
1072 if (sc->ndis_startitem != NULL)
1073 IoFreeWorkItem(sc->ndis_startitem);
1074 if (sc->ndis_resetitem != NULL)
1075 IoFreeWorkItem(sc->ndis_resetitem);
1076 if (sc->ndis_inputitem != NULL)
1077 IoFreeWorkItem(sc->ndis_inputitem);
1078 if (sc->ndisusb_xferdoneitem != NULL)
1079 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1080 if (sc->ndisusb_taskitem != NULL)
1081 IoFreeWorkItem(sc->ndisusb_taskitem);
1083 bus_generic_detach(dev);
1084 ndis_unload_driver(sc);
1087 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1088 if (sc->ndis_res_io)
1089 bus_release_resource(dev, SYS_RES_IOPORT,
1090 sc->ndis_io_rid, sc->ndis_res_io);
1091 if (sc->ndis_res_mem)
1092 bus_release_resource(dev, SYS_RES_MEMORY,
1093 sc->ndis_mem_rid, sc->ndis_res_mem);
1094 if (sc->ndis_res_altmem)
1095 bus_release_resource(dev, SYS_RES_MEMORY,
1096 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1101 if (sc->ndis_iftype == PCMCIABus)
1105 ndis_destroy_dma(sc);
1107 if (sc->ndis_txarray)
1108 free(sc->ndis_txarray, M_DEVBUF);
1110 if (!sc->ndis_80211)
1111 ifmedia_removeall(&sc->ifmedia);
1113 if (sc->ndis_txpool != NULL)
1114 NdisFreePacketPool(sc->ndis_txpool);
1116 /* Destroy the PDO for this device. */
1118 if (sc->ndis_iftype == PCIBus)
1119 drv = windrv_lookup(0, "PCI Bus");
1120 else if (sc->ndis_iftype == PCMCIABus)
1121 drv = windrv_lookup(0, "PCCARD Bus");
1123 drv = windrv_lookup(0, "USB Bus");
1125 panic("couldn't find driver object");
1126 windrv_destroy_pdo(drv, dev);
1128 if (sc->ndis_iftype == PCIBus)
1129 bus_dma_tag_destroy(sc->ndis_parent_tag);
1138 struct ndis_softc *sc;
1141 sc = device_get_softc(dev);
1145 if (NDIS_INITIALIZED(sc))
1156 struct ndis_softc *sc;
1159 sc = device_get_softc(dev);
1162 if (NDIS_INITIALIZED(sc))
1169 * The following bunch of routines are here to support drivers that
1170 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1171 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1172 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1176 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1177 ndis_handle adapter;
1183 uint32_t lookaheadlen;
1186 ndis_miniport_block *block;
1196 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1200 /* Save the data provided to us so far. */
1202 m->m_len = lookaheadlen + hdrlen;
1203 m->m_pkthdr.len = pktlen + hdrlen;
1205 m_copyback(m, 0, hdrlen, hdr);
1206 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1208 /* Now create a fake NDIS_PACKET to hold the data */
1210 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1212 if (status != NDIS_STATUS_SUCCESS) {
1219 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1227 p->np_private.npp_head = p->np_private.npp_tail = b;
1228 p->np_private.npp_totlen = m->m_pkthdr.len;
1230 /* Save the packet RX context somewhere. */
1231 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1232 priv->nep_ctx = ctx;
1234 if (!NDIS_SERIALIZED(block))
1235 KeAcquireSpinLock(&block->nmb_lock, &irql);
1237 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1239 if (!NDIS_SERIALIZED(block))
1240 KeReleaseSpinLock(&block->nmb_lock, irql);
1244 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1245 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1249 ndis_rxeof_done(adapter)
1250 ndis_handle adapter;
1252 struct ndis_softc *sc;
1253 ndis_miniport_block *block;
1257 /* Schedule transfer/RX of queued packets. */
1259 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1261 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1265 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1268 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1270 ndis_handle adapter;
1274 ndis_miniport_block *block;
1275 struct ndis_softc *sc;
1284 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1287 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1289 l = block->nmb_packetlist.nle_flink;
1290 while(!IsListEmpty(&block->nmb_packetlist)) {
1291 l = RemoveHeadList((&block->nmb_packetlist));
1292 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1293 InitializeListHead((&p->np_list));
1295 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1300 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1302 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1303 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1304 m->m_len, m->m_pkthdr.len - m->m_len);
1306 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1309 * If status is NDIS_STATUS_PENDING, do nothing and
1310 * wait for a callback to the ndis_rxeof_xfr_done()
1314 m->m_len = m->m_pkthdr.len;
1315 m->m_pkthdr.rcvif = ifp;
1317 if (status == NDIS_STATUS_SUCCESS) {
1318 IoFreeMdl(p->np_private.npp_head);
1320 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1321 mbufq_enqueue(&sc->ndis_rxqueue, m);
1322 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1323 IoQueueWorkItem(sc->ndis_inputitem,
1324 (io_workitem_func)ndis_inputtask_wrap,
1325 WORKQUEUE_CRITICAL, sc);
1328 if (status == NDIS_STATUS_FAILURE)
1331 /* Advance to next packet */
1332 l = block->nmb_packetlist.nle_flink;
1335 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1339 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1342 ndis_rxeof_xfr_done(adapter, packet, status, len)
1343 ndis_handle adapter;
1344 ndis_packet *packet;
1348 ndis_miniport_block *block;
1349 struct ndis_softc *sc;
1354 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1358 IoFreeMdl(packet->np_private.npp_head);
1359 NdisFreePacket(packet);
1361 if (status != NDIS_STATUS_SUCCESS) {
1366 m->m_len = m->m_pkthdr.len;
1367 m->m_pkthdr.rcvif = ifp;
1368 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1369 mbufq_enqueue(&sc->ndis_rxqueue, m);
1370 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1371 IoQueueWorkItem(sc->ndis_inputitem,
1372 (io_workitem_func)ndis_inputtask_wrap,
1373 WORKQUEUE_CRITICAL, sc);
1376 * A frame has been uploaded: pass the resulting mbuf chain up to
1377 * the higher level protocols.
1379 * When handling received NDIS packets, the 'status' field in the
1380 * out-of-band portion of the ndis_packet has special meaning. In the
1381 * most common case, the underlying NDIS driver will set this field
1382 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1383 * take possession of it. We then change the status field to
1384 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1385 * and that we will return it at some point in the future via the
1386 * return packet handler.
1388 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1389 * this means the driver is running out of packet/buffer resources and
1390 * wants to maintain ownership of the packet. In this case, we have to
1391 * copy the packet data into local storage and let the driver keep the
1395 ndis_rxeof(adapter, packets, pktcnt)
1396 ndis_handle adapter;
1397 ndis_packet **packets;
1400 struct ndis_softc *sc;
1401 ndis_miniport_block *block;
1404 ndis_tcpip_csum *csum;
1406 struct mbuf *m0, *m;
1409 block = (ndis_miniport_block *)adapter;
1410 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1414 * There's a slim chance the driver may indicate some packets
1415 * before we're completely ready to handle them. If we detect this,
1416 * we need to return them to the miniport and ignore them.
1418 if (!sc->ndis_running) {
1419 for (i = 0; i < pktcnt; i++) {
1421 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1423 ndis_return_packet(p);
1429 for (i = 0; i < pktcnt; i++) {
1431 /* Stash the softc here so ptom can use it. */
1433 if (ndis_ptom(&m0, p)) {
1434 device_printf(sc->ndis_dev, "ptom failed\n");
1435 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1436 ndis_return_packet(p);
1439 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1440 m = m_dup(m0, M_NOWAIT);
1442 * NOTE: we want to destroy the mbuf here, but
1443 * we don't actually want to return it to the
1444 * driver via the return packet handler. By
1445 * bumping np_refcnt, we can prevent the
1446 * ndis_return_packet() routine from actually
1452 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1456 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1458 m = m_dup(m0, M_NOWAIT);
1459 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1462 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1465 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1469 m0->m_pkthdr.rcvif = ifp;
1471 /* Deal with checksum offload. */
1473 if (ifp->if_capenable & IFCAP_RXCSUM &&
1474 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1476 p->np_ext.npe_info[ndis_tcpipcsum_info];
1477 csum = (ndis_tcpip_csum *)&s;
1478 if (csum->u.ntc_rxflags &
1479 NDIS_RXCSUM_IP_PASSED)
1480 m0->m_pkthdr.csum_flags |=
1481 CSUM_IP_CHECKED|CSUM_IP_VALID;
1482 if (csum->u.ntc_rxflags &
1483 (NDIS_RXCSUM_TCP_PASSED |
1484 NDIS_RXCSUM_UDP_PASSED)) {
1485 m0->m_pkthdr.csum_flags |=
1486 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1487 m0->m_pkthdr.csum_data = 0xFFFF;
1491 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1492 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1493 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1494 IoQueueWorkItem(sc->ndis_inputitem,
1495 (io_workitem_func)ndis_inputtask_wrap,
1496 WORKQUEUE_CRITICAL, sc);
1502 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1503 * packets into the stack in order to avoid calling (*ifp->if_input)()
1504 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1505 * 'dispatch level' per-cpu sleep lock).
1508 ndis_inputtask(device_object *dobj, void *arg)
1510 ndis_miniport_block *block;
1511 struct ndis_softc *sc = arg;
1515 block = dobj->do_devext;
1517 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1518 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1519 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1520 if ((sc->ndis_80211 != 0)) {
1521 struct ieee80211com *ic = &sc->ndis_ic;
1522 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1525 vap->iv_deliver_data(vap, vap->iv_bss, m);
1527 struct ifnet *ifp = sc->ifp;
1529 (*ifp->if_input)(ifp, m);
1531 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1533 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1537 * A frame was downloaded to the chip. It's safe for us to clean up
1541 ndis_txeof(adapter, packet, status)
1542 ndis_handle adapter;
1543 ndis_packet *packet;
1547 struct ndis_softc *sc;
1548 ndis_miniport_block *block;
1553 block = (ndis_miniport_block *)adapter;
1554 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1558 idx = packet->np_txidx;
1560 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1562 ndis_free_packet(packet);
1566 sc->ndis_txarray[idx] = NULL;
1567 sc->ndis_txpending++;
1569 if (!sc->ndis_80211) {
1570 struct ifnet *ifp = sc->ifp;
1571 if (status == NDIS_STATUS_SUCCESS)
1572 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1574 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1575 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1577 sc->ndis_tx_timer = 0;
1581 if (!sc->ndis_80211)
1582 IoQueueWorkItem(sc->ndis_startitem,
1583 (io_workitem_func)ndis_ifstarttask_wrap,
1584 WORKQUEUE_CRITICAL, sc);
1585 DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1589 ndis_linksts(adapter, status, sbuf, slen)
1590 ndis_handle adapter;
1595 ndis_miniport_block *block;
1596 struct ndis_softc *sc;
1599 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1600 sc->ndis_sts = status;
1602 /* Event list is all full up, drop this one. */
1605 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1610 /* Cache the event. */
1613 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1615 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1620 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1622 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1623 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1624 NDIS_EVTINC(sc->ndis_evtpidx);
1629 ndis_linksts_done(adapter)
1630 ndis_handle adapter;
1632 ndis_miniport_block *block;
1633 struct ndis_softc *sc;
1637 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1640 if (!NDIS_INITIALIZED(sc))
1643 switch (sc->ndis_sts) {
1644 case NDIS_STATUS_MEDIA_CONNECT:
1645 IoQueueWorkItem(sc->ndis_tickitem,
1646 (io_workitem_func)ndis_ticktask_wrap,
1647 WORKQUEUE_CRITICAL, sc);
1648 if (!sc->ndis_80211)
1649 IoQueueWorkItem(sc->ndis_startitem,
1650 (io_workitem_func)ndis_ifstarttask_wrap,
1651 WORKQUEUE_CRITICAL, sc);
1653 case NDIS_STATUS_MEDIA_DISCONNECT:
1655 IoQueueWorkItem(sc->ndis_tickitem,
1656 (io_workitem_func)ndis_ticktask_wrap,
1657 WORKQUEUE_CRITICAL, sc);
1668 struct ndis_softc *sc;
1672 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1673 IoQueueWorkItem(sc->ndis_tickitem,
1674 (io_workitem_func)ndis_ticktask_wrap,
1675 WORKQUEUE_CRITICAL, sc);
1676 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1679 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1680 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1681 device_printf(sc->ndis_dev, "watchdog timeout\n");
1683 IoQueueWorkItem(sc->ndis_resetitem,
1684 (io_workitem_func)ndis_resettask_wrap,
1685 WORKQUEUE_CRITICAL, sc);
1686 if (!sc->ndis_80211)
1687 IoQueueWorkItem(sc->ndis_startitem,
1688 (io_workitem_func)ndis_ifstarttask_wrap,
1689 WORKQUEUE_CRITICAL, sc);
1692 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1696 ndis_ticktask(device_object *d, void *xsc)
1698 struct ndis_softc *sc = xsc;
1699 ndis_checkforhang_handler hangfunc;
1703 if (!NDIS_INITIALIZED(sc)) {
1709 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1711 if (hangfunc != NULL) {
1712 rval = MSCALL1(hangfunc,
1713 sc->ndis_block->nmb_miniportadapterctx);
1721 if (sc->ndis_link == 0 &&
1722 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1724 if (sc->ndis_80211 != 0) {
1725 struct ieee80211com *ic = &sc->ndis_ic;
1726 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1730 ndis_getstate_80211(sc);
1731 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1733 if_link_state_change(vap->iv_ifp,
1737 if_link_state_change(sc->ifp, LINK_STATE_UP);
1740 if (sc->ndis_link == 1 &&
1741 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1743 if (sc->ndis_80211 != 0) {
1744 struct ieee80211com *ic = &sc->ndis_ic;
1745 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1749 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1751 if_link_state_change(vap->iv_ifp,
1755 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1762 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1764 bus_dma_segment_t *segs;
1770 struct ndis_sc_list *sclist;
1773 if (error || arg == NULL)
1778 sclist->nsl_frags = nseg;
1780 for (i = 0; i < nseg; i++) {
1781 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1782 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1787 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1788 const struct ieee80211_bpf_params *params)
1790 /* no support; just discard */
1792 ieee80211_free_node(ni);
1797 ndis_update_mcast(struct ieee80211com *ic)
1799 struct ndis_softc *sc = ic->ic_softc;
1805 ndis_update_promisc(struct ieee80211com *ic)
1811 ndis_ifstarttask(device_object *d, void *arg)
1813 struct ndis_softc *sc = arg;
1814 DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1818 struct ifnet *ifp = sc->ifp;
1819 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1824 * Main transmit routine. To make NDIS drivers happy, we need to
1825 * transform mbuf chains into NDIS packets and feed them to the
1826 * send packet routines. Most drivers allow you to send several
1827 * packets at once (up to the maxpkts limit). Unfortunately, rather
1828 * that accepting them in the form of a linked list, they expect
1829 * a contiguous array of pointers to packets.
1831 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1832 * we need to perform busdma work here. Those that use map registers
1833 * will do the mapping themselves on a buffer by buffer basis.
1836 ndis_ifstart(struct ifnet *ifp)
1838 struct ndis_softc *sc;
1839 struct mbuf *m = NULL;
1840 ndis_packet **p0 = NULL, *p = NULL;
1841 ndis_tcpip_csum *csum;
1842 int pcnt = 0, status;
1847 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1852 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1854 while(sc->ndis_txpending) {
1855 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1859 NdisAllocatePacket(&status,
1860 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1862 if (status != NDIS_STATUS_SUCCESS)
1865 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1866 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1872 * Save pointer to original mbuf
1873 * so we can free it later.
1876 p = sc->ndis_txarray[sc->ndis_txidx];
1877 p->np_txidx = sc->ndis_txidx;
1879 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1882 * Do scatter/gather processing, if driver requested it.
1885 bus_dmamap_load_mbuf(sc->ndis_ttag,
1886 sc->ndis_tmaps[sc->ndis_txidx], m,
1887 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1888 bus_dmamap_sync(sc->ndis_ttag,
1889 sc->ndis_tmaps[sc->ndis_txidx],
1890 BUS_DMASYNC_PREREAD);
1891 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1894 /* Handle checksum offload. */
1896 if (ifp->if_capenable & IFCAP_TXCSUM &&
1897 m->m_pkthdr.csum_flags) {
1898 csum = (ndis_tcpip_csum *)
1899 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1900 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1901 if (m->m_pkthdr.csum_flags & CSUM_IP)
1902 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1903 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1904 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1905 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1906 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1907 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1911 sc->ndis_txpending--;
1916 * If there's a BPF listener, bounce a copy of this frame
1919 if (!sc->ndis_80211) /* XXX handle 80211 */
1923 * The array that p0 points to must appear contiguous,
1924 * so we must not wrap past the end of sc->ndis_txarray[].
1925 * If it looks like we're about to wrap, break out here
1926 * so the this batch of packets can be transmitted, then
1927 * wait for txeof to ask us to send the rest.
1929 if (sc->ndis_txidx == 0)
1938 if (sc->ndis_txpending == 0)
1939 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1942 * Set a timeout in case the chip goes out to lunch.
1944 sc->ndis_tx_timer = 5;
1949 * According to NDIS documentation, if a driver exports
1950 * a MiniportSendPackets() routine, we prefer that over
1951 * a MiniportSend() routine (which sends just a single
1954 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1955 ndis_send_packets(sc, p0, pcnt);
1957 ndis_send_packet(sc, p);
1963 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1965 struct ndis_softc *sc = ic->ic_softc;
1966 ndis_packet **p0 = NULL, *p = NULL;
1970 if (!sc->ndis_link || !sc->ndis_running) {
1975 if (sc->ndis_txpending == 0) {
1980 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1982 NdisAllocatePacket(&status,
1983 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1985 if (status != NDIS_STATUS_SUCCESS) {
1990 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1996 * Save pointer to original mbuf
1997 * so we can free it later.
2000 p = sc->ndis_txarray[sc->ndis_txidx];
2001 p->np_txidx = sc->ndis_txidx;
2003 p->np_oob.npo_status = NDIS_STATUS_PENDING;
2006 * Do scatter/gather processing, if driver requested it.
2009 bus_dmamap_load_mbuf(sc->ndis_ttag,
2010 sc->ndis_tmaps[sc->ndis_txidx], m,
2011 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2012 bus_dmamap_sync(sc->ndis_ttag,
2013 sc->ndis_tmaps[sc->ndis_txidx],
2014 BUS_DMASYNC_PREREAD);
2015 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2019 sc->ndis_txpending--;
2022 * Set a timeout in case the chip goes out to lunch.
2024 sc->ndis_tx_timer = 5;
2028 * According to NDIS documentation, if a driver exports
2029 * a MiniportSendPackets() routine, we prefer that over
2030 * a MiniportSend() routine (which sends just a single
2033 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2034 ndis_send_packets(sc, p0, 1);
2036 ndis_send_packet(sc, p);
2042 ndis_80211parent(struct ieee80211com *ic)
2044 struct ndis_softc *sc = ic->ic_softc;
2047 if (ic->ic_nrunning > 0) {
2048 if (!sc->ndis_running)
2050 } else if (sc->ndis_running)
2052 /*NDIS_UNLOCK(sc);*/
2056 ndis_init(void *xsc)
2058 struct ndis_softc *sc = xsc;
2062 * Avoid reintializing the link unnecessarily.
2063 * This should be dealt with in a better way by
2064 * fixing the upper layer modules so they don't
2065 * call ifp->if_init() quite as often.
2071 * Cancel pending I/O and free all RX/TX buffers.
2075 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2076 error = ndis_init_nic(sc);
2078 device_printf(sc->ndis_dev,
2079 "failed to initialize the device: %d\n", error);
2084 /* Program the packet filter */
2085 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2086 NDIS_PACKET_TYPE_BROADCAST;
2088 if (sc->ndis_80211) {
2089 struct ieee80211com *ic = &sc->ndis_ic;
2091 if (ic->ic_promisc > 0)
2092 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2094 struct ifnet *ifp = sc->ifp;
2096 if (ifp->if_flags & IFF_PROMISC)
2097 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2100 len = sizeof(sc->ndis_filter);
2102 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2103 &sc->ndis_filter, &len);
2106 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2114 i = sc->ifp->if_mtu;
2116 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2119 * Program the multicast filter, if necessary.
2123 /* Setup task offload. */
2124 ndis_set_offload(sc);
2129 sc->ndis_txpending = sc->ndis_maxpkts;
2132 if (!sc->ndis_80211) {
2133 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2134 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2135 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2138 sc->ndis_tx_timer = 0;
2141 * Some drivers don't set this value. The NDIS spec says
2142 * the default checkforhang timeout is "approximately 2
2143 * seconds." We use 3 seconds, because it seems for some
2144 * drivers, exactly 2 seconds is too fast.
2146 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2147 sc->ndis_block->nmb_checkforhangsecs = 3;
2149 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2150 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2151 sc->ndis_running = 1;
2154 /* XXX force handling */
2156 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2160 * Set media options.
2163 ndis_ifmedia_upd(ifp)
2166 struct ndis_softc *sc;
2170 if (NDIS_INITIALIZED(sc))
2177 * Report current media status.
2180 ndis_ifmedia_sts(ifp, ifmr)
2182 struct ifmediareq *ifmr;
2184 struct ndis_softc *sc;
2185 uint32_t media_info;
2186 ndis_media_state linkstate;
2189 ifmr->ifm_status = IFM_AVALID;
2190 ifmr->ifm_active = IFM_ETHER;
2193 if (!NDIS_INITIALIZED(sc))
2196 len = sizeof(linkstate);
2197 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2198 (void *)&linkstate, &len);
2200 len = sizeof(media_info);
2201 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2202 (void *)&media_info, &len);
2204 if (linkstate == nmc_connected)
2205 ifmr->ifm_status |= IFM_ACTIVE;
2207 switch (media_info) {
2209 ifmr->ifm_active |= IFM_10_T;
2212 ifmr->ifm_active |= IFM_100_TX;
2215 ifmr->ifm_active |= IFM_1000_T;
2218 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2224 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2226 struct ieee80211com *ic = &sc->ndis_ic;
2232 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2233 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2235 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2238 if (cipher == WPA_CSE_TKIP) {
2239 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2241 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2244 if (cipher == WPA_CSE_CCMP) {
2245 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2247 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2250 DPRINTF(("Setting cipher to %d\n", arg));
2252 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2257 /* Check that the cipher was set correctly. */
2260 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2262 if (rval != 0 || arg != save)
2269 * WPA is hairy to set up. Do the work in a separate routine
2270 * so we don't clutter the setstate function too much.
2271 * Important yet undocumented fact: first we have to set the
2272 * authentication mode, _then_ we enable the ciphers. If one
2273 * of the WPA authentication modes isn't enabled, the driver
2274 * might not permit the TKIP or AES ciphers to be selected.
2277 ndis_set_wpa(sc, ie, ielen)
2278 struct ndis_softc *sc;
2282 struct ieee80211_ie_wpa *w;
2289 * Apparently, the only way for us to know what ciphers
2290 * and key management/authentication mode to use is for
2291 * us to inspect the optional information element (IE)
2292 * stored in the 802.11 state machine. This IE should be
2293 * supplied by the WPA supplicant.
2296 w = (struct ieee80211_ie_wpa *)ie;
2298 /* Check for the right kind of IE. */
2299 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2300 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2304 /* Skip over the ucast cipher OIDs. */
2305 pos = (char *)&w->wpa_uciphers[0];
2306 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2308 /* Skip over the authmode count. */
2309 pos += sizeof(u_int16_t);
2312 * Check for the authentication modes. I'm
2313 * pretty sure there's only supposed to be one.
2316 n = (struct ndis_ie *)pos;
2317 if (n->ni_val == WPA_ASE_NONE)
2318 arg = NDIS_80211_AUTHMODE_WPANONE;
2320 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2321 arg = NDIS_80211_AUTHMODE_WPA;
2323 if (n->ni_val == WPA_ASE_8021X_PSK)
2324 arg = NDIS_80211_AUTHMODE_WPAPSK;
2326 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2328 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2331 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2333 /* Now configure the desired ciphers. */
2335 /* First, set up the multicast group cipher. */
2336 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2338 if (ndis_set_cipher(sc, n->ni_val))
2341 /* Now start looking around for the unicast ciphers. */
2342 pos = (char *)&w->wpa_uciphers[0];
2343 n = (struct ndis_ie *)pos;
2345 for (i = 0; i < w->wpa_uciphercnt; i++) {
2346 if (ndis_set_cipher(sc, n->ni_val))
2355 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2357 struct ieee80211vap *vap = ifp->if_softc;
2358 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2362 if (!NDIS_INITIALIZED(sc))
2365 len = sizeof(txrate);
2366 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2367 vap->iv_bss->ni_txrate = txrate / 5000;
2368 ieee80211_media_status(ifp, imr);
2372 ndis_setstate_80211(struct ndis_softc *sc)
2374 struct ieee80211com *ic = &sc->ndis_ic;
2375 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2376 ndis_80211_macaddr bssid;
2377 ndis_80211_config config;
2381 if (!NDIS_INITIALIZED(sc)) {
2382 DPRINTF(("%s: NDIS not initialized\n", __func__));
2386 /* Disassociate and turn off radio. */
2389 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2391 /* Set network infrastructure mode. */
2394 if (ic->ic_opmode == IEEE80211_M_IBSS)
2395 arg = NDIS_80211_NET_INFRA_IBSS;
2397 arg = NDIS_80211_NET_INFRA_BSS;
2399 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2402 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2404 /* Set power management */
2406 if (vap->iv_flags & IEEE80211_F_PMGTON)
2407 arg = NDIS_80211_POWERMODE_FAST_PSP;
2409 arg = NDIS_80211_POWERMODE_CAM;
2410 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2413 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2414 ic->ic_txpowlimit < nitems(dBm2mW)) {
2415 arg = dBm2mW[ic->ic_txpowlimit];
2417 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2421 * Default encryption mode to off, authentication
2422 * to open and privacy to 'accept everything.'
2425 arg = NDIS_80211_WEPSTAT_DISABLED;
2426 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2429 arg = NDIS_80211_AUTHMODE_OPEN;
2430 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2433 * Note that OID_802_11_PRIVACY_FILTER is optional:
2434 * not all drivers implement it.
2437 arg = NDIS_80211_PRIVFILT_8021XWEP;
2438 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2440 len = sizeof(config);
2441 bzero((char *)&config, len);
2442 config.nc_length = len;
2443 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2444 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2447 * Some drivers expect us to initialize these values, so
2448 * provide some defaults.
2451 if (config.nc_beaconperiod == 0)
2452 config.nc_beaconperiod = 100;
2453 if (config.nc_atimwin == 0)
2454 config.nc_atimwin = 100;
2455 if (config.nc_fhconfig.ncf_dwelltime == 0)
2456 config.nc_fhconfig.ncf_dwelltime = 200;
2457 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2460 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2461 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2462 IEEE80211_CHAN_5GHZ;
2463 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2464 config.nc_dsconfig =
2465 ic->ic_bsschan->ic_freq * 1000;
2466 len = sizeof(config);
2467 config.nc_length = len;
2468 config.nc_fhconfig.ncf_length =
2469 sizeof(ndis_80211_config_fh);
2470 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2471 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2474 device_printf(sc->ndis_dev, "couldn't change "
2475 "DS config to %ukHz: %d\n",
2476 config.nc_dsconfig, rval);
2479 device_printf(sc->ndis_dev, "couldn't retrieve "
2480 "channel info: %d\n", rval);
2482 /* Set the BSSID to our value so the driver doesn't associate */
2483 len = IEEE80211_ADDR_LEN;
2484 bcopy(vap->iv_myaddr, bssid, len);
2485 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2486 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2488 device_printf(sc->ndis_dev,
2489 "setting BSSID failed: %d\n", rval);
2493 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2495 struct ieee80211_node *ni = vap->iv_bss;
2496 ndis_80211_ssid ssid;
2497 ndis_80211_macaddr bssid;
2499 int i, rval = 0, len, error;
2502 if (!NDIS_INITIALIZED(sc)) {
2503 DPRINTF(("%s: NDIS not initialized\n", __func__));
2508 ndis_setstate_80211(sc);
2510 /* Set network infrastructure mode. */
2513 if (vap->iv_opmode == IEEE80211_M_IBSS)
2514 arg = NDIS_80211_NET_INFRA_IBSS;
2516 arg = NDIS_80211_NET_INFRA_BSS;
2518 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2521 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2523 /* Set RTS threshold */
2526 arg = vap->iv_rtsthreshold;
2527 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2529 /* Set fragmentation threshold */
2532 arg = vap->iv_fragthreshold;
2533 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2537 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2538 !(vap->iv_flags & IEEE80211_F_WPA)) {
2541 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2543 arg = NDIS_80211_AUTHMODE_SHARED;
2544 DPRINTF(("Setting shared auth\n"));
2545 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2548 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2549 if (vap->iv_nw_keys[i].wk_keylen) {
2550 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2551 IEEE80211_CIPHER_WEP)
2553 bzero((char *)&wep, sizeof(wep));
2554 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2557 * 5, 13 and 16 are the only valid
2558 * key lengths. Anything in between
2559 * will be zero padded out to the
2560 * next highest boundary.
2562 if (vap->iv_nw_keys[i].wk_keylen < 5)
2564 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2565 vap->iv_nw_keys[i].wk_keylen < 13)
2567 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2568 vap->iv_nw_keys[i].wk_keylen < 16)
2572 wep.nw_length = (sizeof(uint32_t) * 3)
2574 if (i == vap->iv_def_txkey)
2575 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2576 bcopy(vap->iv_nw_keys[i].wk_key,
2577 wep.nw_keydata, wep.nw_length);
2579 DPRINTF(("Setting WEP key %d\n", i));
2580 rval = ndis_set_info(sc,
2581 OID_802_11_ADD_WEP, &wep, &len);
2583 device_printf(sc->ndis_dev,
2584 "set wepkey failed: %d\n", rval);
2589 DPRINTF(("Setting WEP on\n"));
2590 arg = NDIS_80211_WEPSTAT_ENABLED;
2592 rval = ndis_set_info(sc,
2593 OID_802_11_WEP_STATUS, &arg, &len);
2595 device_printf(sc->ndis_dev,
2596 "enable WEP failed: %d\n", rval);
2597 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2598 arg = NDIS_80211_PRIVFILT_8021XWEP;
2600 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2604 OID_802_11_PRIVACY_FILTER, &arg, &len);
2609 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2610 vap->iv_appie_assocreq != NULL) {
2611 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2612 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2614 device_printf(sc->ndis_dev, "WPA setup failed\n");
2618 /* Set network type. */
2622 switch (vap->iv_curmode) {
2623 case IEEE80211_MODE_11A:
2624 arg = NDIS_80211_NETTYPE_11OFDM5;
2626 case IEEE80211_MODE_11B:
2627 arg = NDIS_80211_NETTYPE_11DS;
2629 case IEEE80211_MODE_11G:
2630 arg = NDIS_80211_NETTYPE_11OFDM24;
2633 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2638 DPRINTF(("Setting network type to %d\n", arg));
2640 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2643 device_printf(sc->ndis_dev,
2644 "set nettype failed: %d\n", rval);
2649 * If the user selected a specific BSSID, try
2650 * to use that one. This is useful in the case where
2651 * there are several APs in range with the same network
2652 * name. To delete the BSSID, we use the broadcast
2653 * address as the BSSID.
2654 * Note that some drivers seem to allow setting a BSSID
2655 * in ad-hoc mode, which has the effect of forcing the
2656 * NIC to create an ad-hoc cell with a specific BSSID,
2657 * instead of a randomly chosen one. However, the net80211
2658 * code makes the assumtion that the BSSID setting is invalid
2659 * when you're in ad-hoc mode, so we don't allow that here.
2662 len = IEEE80211_ADDR_LEN;
2663 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2664 vap->iv_opmode != IEEE80211_M_IBSS)
2665 bcopy(ni->ni_bssid, bssid, len);
2667 bcopy(ieee80211broadcastaddr, bssid, len);
2669 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2670 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2672 device_printf(sc->ndis_dev,
2673 "setting BSSID failed: %d\n", rval);
2675 /* Set SSID -- always do this last. */
2678 if (ndis_debug > 0) {
2679 printf("Setting ESSID to ");
2680 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2686 bzero((char *)&ssid, len);
2687 ssid.ns_ssidlen = ni->ni_esslen;
2688 if (ssid.ns_ssidlen == 0) {
2689 ssid.ns_ssidlen = 1;
2691 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2693 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2696 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2702 ndis_get_bssid_list(sc, bl)
2703 struct ndis_softc *sc;
2704 ndis_80211_bssid_list_ex **bl;
2708 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2709 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2713 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2714 if (error == ENOSPC) {
2715 free(*bl, M_DEVBUF);
2716 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2720 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2723 DPRINTF(("%s: failed to read\n", __func__));
2724 free(*bl, M_DEVBUF);
2732 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2734 struct ieee80211com *ic = &sc->ndis_ic;
2735 struct ieee80211vap *vap;
2736 struct ieee80211_node *ni;
2737 ndis_80211_bssid_list_ex *bl;
2738 ndis_wlan_bssid_ex *bs;
2739 ndis_80211_macaddr bssid;
2745 len = sizeof(bssid);
2746 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2748 device_printf(sc->ndis_dev, "failed to get bssid\n");
2752 vap = TAILQ_FIRST(&ic->ic_vaps);
2755 error = ndis_get_bssid_list(sc, &bl);
2759 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2760 for (i = 0; i < bl->nblx_items; i++) {
2761 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2762 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2763 if (*assoc == NULL) {
2767 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2769 if (ic->ic_opmode == IEEE80211_M_STA)
2770 ni->ni_associd = 1 | 0xc000; /* fake associd */
2773 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2781 ndis_getstate_80211(struct ndis_softc *sc)
2783 struct ieee80211com *ic = &sc->ndis_ic;
2784 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2785 struct ieee80211_node *ni = vap->iv_bss;
2786 ndis_wlan_bssid_ex *bs;
2787 int rval, len, i = 0;
2791 if (!NDIS_INITIALIZED(sc))
2794 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2797 /* We're associated, retrieve info on the current bssid. */
2798 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2799 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2800 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2802 /* Get SSID from current association info. */
2803 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2804 bs->nwbx_ssid.ns_ssidlen);
2805 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2807 if (ic->ic_caps & IEEE80211_C_PMGT) {
2809 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2812 device_printf(sc->ndis_dev,
2813 "get power mode failed: %d\n", rval);
2814 if (arg == NDIS_80211_POWERMODE_CAM)
2815 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2817 vap->iv_flags |= IEEE80211_F_PMGTON;
2821 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2823 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2824 for (i = 0; i < nitems(dBm2mW); i++)
2825 if (dBm2mW[i] >= arg)
2827 ic->ic_txpowlimit = i;
2831 * Use the current association information to reflect
2832 * what channel we're on.
2834 ic->ic_curchan = ieee80211_find_channel(ic,
2835 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2836 if (ic->ic_curchan == NULL)
2837 ic->ic_curchan = &ic->ic_channels[0];
2838 ni->ni_chan = ic->ic_curchan;
2839 ic->ic_bsschan = ic->ic_curchan;
2844 * Determine current authentication mode.
2847 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2849 device_printf(sc->ndis_dev,
2850 "get authmode status failed: %d\n", rval);
2852 vap->iv_flags &= ~IEEE80211_F_WPA;
2854 case NDIS_80211_AUTHMODE_OPEN:
2855 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2857 case NDIS_80211_AUTHMODE_SHARED:
2858 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2860 case NDIS_80211_AUTHMODE_AUTO:
2861 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2863 case NDIS_80211_AUTHMODE_WPA:
2864 case NDIS_80211_AUTHMODE_WPAPSK:
2865 case NDIS_80211_AUTHMODE_WPANONE:
2866 ni->ni_authmode = IEEE80211_AUTH_WPA;
2867 vap->iv_flags |= IEEE80211_F_WPA1;
2869 case NDIS_80211_AUTHMODE_WPA2:
2870 case NDIS_80211_AUTHMODE_WPA2PSK:
2871 ni->ni_authmode = IEEE80211_AUTH_WPA;
2872 vap->iv_flags |= IEEE80211_F_WPA2;
2875 ni->ni_authmode = IEEE80211_AUTH_NONE;
2881 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2884 device_printf(sc->ndis_dev,
2885 "get wep status failed: %d\n", rval);
2887 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2888 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2890 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2894 ndis_ifioctl(ifp, command, data)
2899 struct ndis_softc *sc = ifp->if_softc;
2900 struct ifreq *ifr = (struct ifreq *) data;
2907 if (ifp->if_flags & IFF_UP) {
2908 if (sc->ndis_running &&
2909 ifp->if_flags & IFF_PROMISC &&
2910 !(sc->ndis_if_flags & IFF_PROMISC)) {
2912 NDIS_PACKET_TYPE_PROMISCUOUS;
2913 i = sizeof(sc->ndis_filter);
2914 error = ndis_set_info(sc,
2915 OID_GEN_CURRENT_PACKET_FILTER,
2916 &sc->ndis_filter, &i);
2917 } else if (sc->ndis_running &&
2918 !(ifp->if_flags & IFF_PROMISC) &&
2919 sc->ndis_if_flags & IFF_PROMISC) {
2921 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2922 i = sizeof(sc->ndis_filter);
2923 error = ndis_set_info(sc,
2924 OID_GEN_CURRENT_PACKET_FILTER,
2925 &sc->ndis_filter, &i);
2929 if (sc->ndis_running)
2932 sc->ndis_if_flags = ifp->if_flags;
2942 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2945 ifp->if_capenable = ifr->ifr_reqcap;
2946 if (ifp->if_capenable & IFCAP_TXCSUM)
2947 ifp->if_hwassist = sc->ndis_hwassist;
2949 ifp->if_hwassist = 0;
2950 ndis_set_offload(sc);
2953 error = ether_ioctl(ifp, command, data);
2957 /*NDIS_UNLOCK(sc);*/
2963 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2965 struct ndis_softc *sc = ic->ic_softc;
2966 struct ifreq *ifr = data;
2967 struct ndis_oid_data oid;
2968 struct ndis_evt evt;
2969 void *oidbuf = NULL;
2972 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2978 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2981 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2982 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2986 free(oidbuf, M_TEMP);
2992 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2995 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2997 case SIOCGPRIVATE_0:
2999 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3004 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
3009 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3014 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3015 ifr->ifr_data, sizeof(uint32_t) * 2);
3020 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3021 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3022 ifr->ifr_data + (sizeof(uint32_t) * 2),
3023 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3028 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3029 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3031 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3032 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3033 NDIS_EVTINC(sc->ndis_evtcidx);
3044 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3047 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3050 free(oidbuf, M_TEMP);
3056 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3058 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3059 ndis_80211_key rkey;
3062 bzero((char *)&rkey, sizeof(rkey));
3066 rkey.nk_keyidx = key->wk_keyix;
3068 bcopy(vap->iv_ifp->if_broadcastaddr,
3069 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3071 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3080 * In theory this could be called for any key, but we'll
3081 * only use it for WPA TKIP or AES keys. These need to be
3082 * set after initial authentication with the AP.
3085 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3087 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3088 ndis_80211_key rkey;
3091 switch (key->wk_cipher->ic_cipher) {
3092 case IEEE80211_CIPHER_TKIP:
3094 len = sizeof(ndis_80211_key);
3095 bzero((char *)&rkey, sizeof(rkey));
3098 rkey.nk_keylen = key->wk_keylen;
3100 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3101 rkey.nk_keylen += 16;
3103 /* key index - gets weird in NDIS */
3105 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3106 rkey.nk_keyidx = key->wk_keyix;
3110 if (key->wk_flags & IEEE80211_KEY_XMIT)
3111 rkey.nk_keyidx |= 1 << 31;
3113 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3114 bcopy(ieee80211broadcastaddr,
3115 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3117 bcopy(vap->iv_bss->ni_bssid,
3118 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3120 rkey.nk_keyidx |= 1 << 30;
3123 /* need to set bit 29 based on keyrsc */
3124 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3127 rkey.nk_keyidx |= 1 << 29;
3129 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3130 bcopy(key->wk_key, rkey.nk_keydata, 16);
3131 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3132 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3134 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3136 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3138 case IEEE80211_CIPHER_WEP:
3142 * I don't know how to set up keys for the AES
3143 * cipher yet. Is it the same as TKIP?
3145 case IEEE80211_CIPHER_AES_CCM:
3151 /* We need to return 1 for success, 0 for failure. */
3160 ndis_resettask(d, arg)
3164 struct ndis_softc *sc;
3171 * Stop the adapter and free any mbufs allocated to the
3175 ndis_stop(struct ndis_softc *sc)
3179 callout_drain(&sc->ndis_stat_callout);
3182 sc->ndis_tx_timer = 0;
3184 if (!sc->ndis_80211)
3185 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3186 sc->ndis_running = 0;
3189 if (sc->ndis_iftype != PNPBus ||
3190 (sc->ndis_iftype == PNPBus &&
3191 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3196 for (i = 0; i < NDIS_EVENTS; i++) {
3197 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3198 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3199 sc->ndis_evt[i].ne_buf = NULL;
3201 sc->ndis_evt[i].ne_sts = 0;
3202 sc->ndis_evt[i].ne_len = 0;
3204 sc->ndis_evtcidx = 0;
3205 sc->ndis_evtpidx = 0;
3210 * Stop all chip I/O so that the kernel's probe routines don't
3211 * get confused by errant DMAs when rebooting.
3217 struct ndis_softc *sc;
3219 sc = device_get_softc(dev);
3224 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3226 struct ndis_vap *nvp = NDIS_VAP(vap);
3227 struct ieee80211com *ic = vap->iv_ic;
3228 struct ndis_softc *sc = ic->ic_softc;
3229 enum ieee80211_state ostate;
3231 DPRINTF(("%s: %s -> %s\n", __func__,
3232 ieee80211_state_name[vap->iv_state],
3233 ieee80211_state_name[nstate]));
3235 ostate = vap->iv_state;
3236 vap->iv_state = nstate;
3239 /* pass on to net80211 */
3240 case IEEE80211_S_INIT:
3241 case IEEE80211_S_SCAN:
3242 return nvp->newstate(vap, nstate, arg);
3243 case IEEE80211_S_ASSOC:
3244 if (ostate != IEEE80211_S_AUTH) {
3245 IEEE80211_UNLOCK(ic);
3246 ndis_auth_and_assoc(sc, vap);
3250 case IEEE80211_S_AUTH:
3251 IEEE80211_UNLOCK(ic);
3252 ndis_auth_and_assoc(sc, vap);
3253 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3254 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3264 ndis_scan(void *arg)
3266 struct ieee80211vap *vap = arg;
3268 ieee80211_scan_done(vap);
3272 ndis_scan_results(struct ndis_softc *sc)
3274 struct ieee80211com *ic = &sc->ndis_ic;
3275 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3276 ndis_80211_bssid_list_ex *bl;
3277 ndis_wlan_bssid_ex *wb;
3278 struct ieee80211_scanparams sp;
3279 struct ieee80211_frame wh;
3280 struct ieee80211_channel *saved_chan;
3282 int rssi, noise, freq, chanflag;
3283 uint8_t ssid[2+IEEE80211_NWID_LEN];
3284 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3285 uint8_t *frm, *efrm;
3287 saved_chan = ic->ic_curchan;
3290 if (ndis_get_bssid_list(sc, &bl))
3293 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3294 wb = &bl->nblx_bssid[0];
3295 for (i = 0; i < bl->nblx_items; i++) {
3296 memset(&sp, 0, sizeof(sp));
3298 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3299 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3300 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3301 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3302 if (wb->nwbx_privacy)
3303 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3304 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3305 switch (wb->nwbx_netinfra) {
3306 case NDIS_80211_NET_INFRA_IBSS:
3307 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3309 case NDIS_80211_NET_INFRA_BSS:
3310 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3313 sp.rates = &rates[0];
3314 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3315 /* XXX - check units */
3316 if (wb->nwbx_supportedrates[j] == 0)
3319 wb->nwbx_supportedrates[j] & 0x7f;
3322 sp.ssid = (uint8_t *)&ssid[0];
3323 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3324 wb->nwbx_ssid.ns_ssidlen);
3325 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3327 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3328 freq = wb->nwbx_config.nc_dsconfig / 1000;
3329 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3330 /* Hack ic->ic_curchan to be in sync with the scan result */
3331 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3332 if (ic->ic_curchan == NULL)
3333 ic->ic_curchan = &ic->ic_channels[0];
3335 /* Process extended info from AP */
3336 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3337 frm = (uint8_t *)&wb->nwbx_ies;
3338 efrm = frm + wb->nwbx_ielen;
3339 if (efrm - frm < 12)
3341 sp.tstamp = frm; frm += 8;
3342 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3343 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3345 sp.ies_len = efrm - frm;
3348 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3349 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3351 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3352 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3355 /* Restore the channel after messing with it */
3356 ic->ic_curchan = saved_chan;
3360 ndis_scan_start(struct ieee80211com *ic)
3362 struct ndis_softc *sc = ic->ic_softc;
3363 struct ieee80211vap *vap;
3364 struct ieee80211_scan_state *ss;
3365 ndis_80211_ssid ssid;
3369 vap = TAILQ_FIRST(&ic->ic_vaps);
3371 if (!NDIS_INITIALIZED(sc)) {
3372 DPRINTF(("%s: scan aborted\n", __func__));
3373 ieee80211_cancel_scan(vap);
3378 bzero((char *)&ssid, len);
3379 if (ss->ss_nssid == 0)
3380 ssid.ns_ssidlen = 1;
3382 /* Perform a directed scan */
3383 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3384 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3387 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3389 DPRINTF(("%s: set ESSID failed\n", __func__));
3392 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3394 DPRINTF(("%s: scan command failed\n", __func__));
3395 ieee80211_cancel_scan(vap);
3398 /* Set a timer to collect the results */
3399 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3403 ndis_set_channel(struct ieee80211com *ic)
3409 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3415 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3417 /* NB: don't try to abort scan; wait for firmware to finish */
3421 ndis_scan_end(struct ieee80211com *ic)
3423 struct ndis_softc *sc = ic->ic_softc;
3425 ndis_scan_results(sc);