3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
33 * then hacked upon mercilessly by my.
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sockio.h>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
46 #include <sys/kernel.h>
47 #include <sys/socket.h>
48 #include <sys/queue.h>
49 #include <sys/module.h>
51 #include <sys/sysctl.h>
52 #include <sys/kthread.h>
56 #include <net/if_arp.h>
57 #include <net/ethernet.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/route.h>
65 #include <machine/bus.h>
66 #include <machine/resource.h>
70 #include <net80211/ieee80211_var.h>
71 #include <net80211/ieee80211_ioctl.h>
72 #include <net80211/ieee80211_regdomain.h>
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcivar.h>
76 #include <dev/usb/usb.h>
77 #include <dev/usb/usbdi.h>
79 #include <compat/ndis/pe_var.h>
80 #include <compat/ndis/cfg_var.h>
81 #include <compat/ndis/resource_var.h>
82 #include <compat/ndis/ntoskrnl_var.h>
83 #include <compat/ndis/hal_var.h>
84 #include <compat/ndis/ndis_var.h>
85 #include <compat/ndis/usbd_var.h>
86 #include <dev/if_ndis/if_ndisvar.h>
90 #define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
92 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
93 "if_ndis debug level");
98 SYSCTL_DECL(_hw_ndisusb);
100 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
101 "Halt NDIS USB driver when it's attached");
103 /* 0 - 30 dBm to mW conversion table */
104 static const uint16_t dBm2mW[] = {
105 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
106 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
107 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
108 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
109 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
110 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
114 MODULE_DEPEND(ndis, ether, 1, 1, 1);
115 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
116 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
118 MODULE_VERSION(ndis, 1);
120 int ndis_attach (device_t);
121 int ndis_detach (device_t);
122 int ndis_suspend (device_t);
123 int ndis_resume (device_t);
124 void ndis_shutdown (device_t);
126 int ndisdrv_modevent (module_t, int, void *);
128 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
129 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
130 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
131 uint32_t, void *, uint32_t, uint32_t);
132 static void ndis_rxeof_done (ndis_handle);
133 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
134 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
136 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
137 static void ndis_linksts_done (ndis_handle);
139 /* We need to wrap these functions for amd64. */
141 static funcptr ndis_txeof_wrap;
142 static funcptr ndis_rxeof_wrap;
143 static funcptr ndis_rxeof_eth_wrap;
144 static funcptr ndis_rxeof_done_wrap;
145 static funcptr ndis_rxeof_xfr_wrap;
146 static funcptr ndis_rxeof_xfr_done_wrap;
147 static funcptr ndis_linksts_wrap;
148 static funcptr ndis_linksts_done_wrap;
149 static funcptr ndis_ticktask_wrap;
150 static funcptr ndis_starttask_wrap;
151 static funcptr ndis_resettask_wrap;
152 static funcptr ndis_inputtask_wrap;
154 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
155 const char name[IFNAMSIZ], int unit, int opmode,
156 int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
157 const uint8_t mac[IEEE80211_ADDR_LEN]);
158 static void ndis_vap_delete (struct ieee80211vap *);
159 static void ndis_tick (void *);
160 static void ndis_ticktask (device_object *, void *);
161 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
162 const struct ieee80211_bpf_params *);
163 static void ndis_update_mcast (struct ifnet *ifp);
164 static void ndis_update_promisc (struct ifnet *ifp);
165 static void ndis_start (struct ifnet *);
166 static void ndis_starttask (device_object *, void *);
167 static void ndis_resettask (device_object *, void *);
168 static void ndis_inputtask (device_object *, void *);
169 static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
170 static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t);
171 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
173 static int ndis_nettype_chan (uint32_t);
174 static int ndis_nettype_mode (uint32_t);
175 static void ndis_scan (void *);
176 static void ndis_scan_results (struct ndis_softc *);
177 static void ndis_scan_start (struct ieee80211com *);
178 static void ndis_scan_end (struct ieee80211com *);
179 static void ndis_set_channel (struct ieee80211com *);
180 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
181 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
182 static void ndis_init (void *);
183 static void ndis_stop (struct ndis_softc *);
184 static int ndis_ifmedia_upd (struct ifnet *);
185 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
186 static int ndis_get_bssid_list (struct ndis_softc *,
187 ndis_80211_bssid_list_ex **);
188 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
189 static int ndis_probe_offload (struct ndis_softc *);
190 static int ndis_set_offload (struct ndis_softc *);
191 static void ndis_getstate_80211 (struct ndis_softc *);
192 static void ndis_setstate_80211 (struct ndis_softc *);
193 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
194 static int ndis_set_cipher (struct ndis_softc *, int);
195 static int ndis_set_wpa (struct ndis_softc *, void *, int);
196 static int ndis_add_key (struct ieee80211vap *,
197 const struct ieee80211_key *, const u_int8_t []);
198 static int ndis_del_key (struct ieee80211vap *,
199 const struct ieee80211_key *);
201 static void ndis_setmulti (struct ndis_softc *);
202 static void ndis_map_sclist (void *, bus_dma_segment_t *,
203 int, bus_size_t, int);
205 static int ndisdrv_loaded = 0;
208 * This routine should call windrv_load() once for each driver
209 * image. This will do the relocation and dynalinking for the
210 * image, and create a Windows driver object which will be
211 * saved in our driver database.
215 ndisdrv_modevent(mod, cmd, arg)
225 if (ndisdrv_loaded > 1)
227 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
228 3, WINDRV_WRAP_STDCALL);
229 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
230 8, WINDRV_WRAP_STDCALL);
231 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
232 1, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
234 4, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
236 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
238 3, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
240 4, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_linksts_done,
242 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
244 2, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
246 2, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
248 2, WINDRV_WRAP_STDCALL);
249 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
250 2, WINDRV_WRAP_STDCALL);
254 if (ndisdrv_loaded > 0)
258 windrv_unwrap(ndis_rxeof_wrap);
259 windrv_unwrap(ndis_rxeof_eth_wrap);
260 windrv_unwrap(ndis_rxeof_done_wrap);
261 windrv_unwrap(ndis_rxeof_xfr_wrap);
262 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
263 windrv_unwrap(ndis_txeof_wrap);
264 windrv_unwrap(ndis_linksts_wrap);
265 windrv_unwrap(ndis_linksts_done_wrap);
266 windrv_unwrap(ndis_ticktask_wrap);
267 windrv_unwrap(ndis_starttask_wrap);
268 windrv_unwrap(ndis_resettask_wrap);
269 windrv_unwrap(ndis_inputtask_wrap);
280 * Program the 64-bit multicast hash filter.
284 struct ndis_softc *sc;
287 struct ifmultiaddr *ifma;
288 int len, mclistsz, error;
293 if (!NDIS_INITIALIZED(sc))
296 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
297 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
298 len = sizeof(sc->ndis_filter);
299 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
300 &sc->ndis_filter, &len);
302 device_printf (sc->ndis_dev,
303 "set allmulti failed: %d\n", error);
307 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
310 len = sizeof(mclistsz);
311 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
313 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
315 if (mclist == NULL) {
316 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
320 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
324 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
325 if (ifma->ifma_addr->sa_family != AF_LINK)
327 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
328 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
330 if (len > mclistsz) {
331 if_maddr_runlock(ifp);
332 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
333 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
337 if_maddr_runlock(ifp);
339 len = len * ETHER_ADDR_LEN;
340 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
342 device_printf (sc->ndis_dev, "set mclist failed: %d\n", error);
343 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
344 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
348 free(mclist, M_TEMP);
350 len = sizeof(sc->ndis_filter);
351 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
352 &sc->ndis_filter, &len);
354 device_printf (sc->ndis_dev, "set multi failed: %d\n", error);
361 struct ndis_softc *sc;
363 ndis_task_offload *nto;
364 ndis_task_offload_hdr *ntoh;
365 ndis_task_tcpip_csum *nttc;
371 if (!NDIS_INITIALIZED(sc))
374 /* See if there's anything to set. */
376 error = ndis_probe_offload(sc);
380 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
383 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
384 sizeof(ndis_task_tcpip_csum);
386 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
391 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
392 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
393 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
394 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
395 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
396 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
398 nto = (ndis_task_offload *)((char *)ntoh +
399 ntoh->ntoh_offset_firsttask);
401 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
402 nto->nto_len = sizeof(ndis_task_offload);
403 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
404 nto->nto_offset_nexttask = 0;
405 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
407 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
409 if (ifp->if_capenable & IFCAP_TXCSUM)
410 nttc->nttc_v4tx = sc->ndis_v4tx;
412 if (ifp->if_capenable & IFCAP_RXCSUM)
413 nttc->nttc_v4rx = sc->ndis_v4rx;
415 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
422 ndis_probe_offload(sc)
423 struct ndis_softc *sc;
425 ndis_task_offload *nto;
426 ndis_task_offload_hdr *ntoh;
427 ndis_task_tcpip_csum *nttc = NULL;
429 int len, error, dummy;
434 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
439 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
444 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
445 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
446 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
447 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
448 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
450 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
457 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
462 nto = (ndis_task_offload *)((char *)ntoh +
463 ntoh->ntoh_offset_firsttask);
466 switch (nto->nto_task) {
467 case NDIS_TASK_TCPIP_CSUM:
468 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
470 /* Don't handle these yet. */
471 case NDIS_TASK_IPSEC:
472 case NDIS_TASK_TCP_LARGESEND:
476 if (nto->nto_offset_nexttask == 0)
478 nto = (ndis_task_offload *)((char *)nto +
479 nto->nto_offset_nexttask);
487 sc->ndis_v4tx = nttc->nttc_v4tx;
488 sc->ndis_v4rx = nttc->nttc_v4rx;
490 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
491 sc->ndis_hwassist |= CSUM_IP;
492 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
493 sc->ndis_hwassist |= CSUM_TCP;
494 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
495 sc->ndis_hwassist |= CSUM_UDP;
497 if (sc->ndis_hwassist)
498 ifp->if_capabilities |= IFCAP_TXCSUM;
500 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
501 ifp->if_capabilities |= IFCAP_RXCSUM;
502 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
503 ifp->if_capabilities |= IFCAP_RXCSUM;
504 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
505 ifp->if_capabilities |= IFCAP_RXCSUM;
512 ndis_nettype_chan(uint32_t type)
515 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
516 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
517 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
518 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
520 DPRINTF(("unknown channel nettype %d\n", type));
521 return (IEEE80211_CHAN_B); /* Default to 11B chan */
525 ndis_nettype_mode(uint32_t type)
528 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
529 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
530 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
531 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
533 DPRINTF(("unknown mode nettype %d\n", type));
534 return (IEEE80211_MODE_AUTO);
538 * Attach the interface. Allocate softc structures, do ifmedia
539 * setup and ethernet/BPF attach.
545 u_char eaddr[ETHER_ADDR_LEN];
546 struct ndis_softc *sc;
549 struct ifnet *ifp = NULL;
550 int error = 0, len, mode;
554 sc = device_get_softc(dev);
556 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
558 KeInitializeSpinLock(&sc->ndis_rxlock);
559 KeInitializeSpinLock(&sc->ndisusb_tasklock);
560 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
561 InitializeListHead(&sc->ndis_shlist);
562 InitializeListHead(&sc->ndisusb_tasklist);
563 InitializeListHead(&sc->ndisusb_xferdonelist);
564 callout_init(&sc->ndis_stat_callout, CALLOUT_MPSAFE);
566 if (sc->ndis_iftype == PCMCIABus) {
567 error = ndis_alloc_amem(sc);
569 device_printf(dev, "failed to allocate "
570 "attribute memory\n");
575 /* Create sysctl registry nodes */
576 ndis_create_sysctls(sc);
578 /* Find the PDO for this device instance. */
580 if (sc->ndis_iftype == PCIBus)
581 pdrv = windrv_lookup(0, "PCI Bus");
582 else if (sc->ndis_iftype == PCMCIABus)
583 pdrv = windrv_lookup(0, "PCCARD Bus");
585 pdrv = windrv_lookup(0, "USB Bus");
586 pdo = windrv_find_pdo(pdrv, dev);
589 * Create a new functional device object for this
590 * device. This is what creates the miniport block
591 * for this device instance.
594 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
595 device_printf(dev, "failed to create FDO!\n");
600 /* Tell the user what version of the API the driver is using. */
601 device_printf(dev, "NDIS API version: %d.%d\n",
602 sc->ndis_chars->nmc_version_major,
603 sc->ndis_chars->nmc_version_minor);
605 /* Do resource conversion. */
606 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
607 ndis_convert_res(sc);
609 sc->ndis_block->nmb_rlist = NULL;
611 /* Install our RX and TX interrupt handlers. */
612 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
613 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
614 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
615 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
616 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
618 /* Override the status handler so we can detect link changes. */
619 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
620 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
622 /* Set up work item handlers. */
623 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
627 sc->ndisusb_xferdoneitem =
628 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
629 sc->ndisusb_taskitem =
630 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
631 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
633 /* Call driver's init routine. */
634 if (ndis_init_nic(sc)) {
635 device_printf (dev, "init handler failed\n");
641 * Get station address from the driver.
644 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
647 * Figure out how big to make the TX buffer pool.
650 len = sizeof(sc->ndis_maxpkts);
651 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
652 &sc->ndis_maxpkts, &len)) {
653 device_printf (dev, "failed to get max TX packets\n");
659 * If this is a deserialized miniport, we don't have
660 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
663 if (!NDIS_SERIALIZED(sc->ndis_block))
664 sc->ndis_maxpkts = NDIS_TXPKTS;
666 /* Enforce some sanity, just in case. */
668 if (sc->ndis_maxpkts == 0)
669 sc->ndis_maxpkts = 10;
671 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
672 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
674 /* Allocate a pool of ndis_packets for TX encapsulation. */
676 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
677 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
679 if (i != NDIS_STATUS_SUCCESS) {
680 sc->ndis_txpool = NULL;
681 device_printf(dev, "failed to allocate TX packet pool");
686 sc->ndis_txpending = sc->ndis_maxpkts;
689 /* Get supported oid list. */
690 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
692 /* If the NDIS module requested scatter/gather, init maps. */
697 * See if the OID_802_11_CONFIGURATION OID is
698 * supported by this driver. If it is, then this an 802.11
699 * wireless driver, and we should set up media for wireless.
701 for (i = 0; i < sc->ndis_oidcnt; i++) {
702 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
709 ifp = if_alloc(IFT_IEEE80211);
711 ifp = if_alloc(IFT_ETHER);
719 /* Check for task offload support. */
720 ndis_probe_offload(sc);
722 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
723 ifp->if_mtu = ETHERMTU;
724 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
725 ifp->if_ioctl = ndis_ioctl;
726 ifp->if_start = ndis_start;
727 ifp->if_init = ndis_init;
728 ifp->if_baudrate = 10000000;
729 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
730 ifp->if_snd.ifq_drv_maxlen = 25;
731 IFQ_SET_READY(&ifp->if_snd);
732 ifp->if_capenable = ifp->if_capabilities;
733 ifp->if_hwassist = sc->ndis_hwassist;
736 if (sc->ndis_80211) {
737 struct ieee80211com *ic = ifp->if_l2com;
738 ndis_80211_rates_ex rates;
739 struct ndis_80211_nettype_list *ntl;
743 callout_init(&sc->ndis_scan_callout, CALLOUT_MPSAFE);
745 ifp->if_ioctl = ndis_ioctl_80211;
747 ic->ic_opmode = IEEE80211_M_STA;
748 ic->ic_phytype = IEEE80211_T_DS;
749 ic->ic_caps = IEEE80211_C_8023ENCAP |
750 IEEE80211_C_STA | IEEE80211_C_IBSS;
751 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
753 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
757 ntl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
758 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
765 for (i = 0; i < ntl->ntl_items; i++) {
766 mode = ndis_nettype_mode(ntl->ntl_type[i]);
768 setbit(ic->ic_modecaps, mode);
769 setbit(&bands, mode);
771 device_printf(dev, "Unknown nettype %d\n",
776 /* Default to 11b channels if the card did not supply any */
778 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
779 setbit(&bands, IEEE80211_MODE_11B);
782 bzero((char *)&rates, len);
783 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
784 (void *)rates, &len);
786 device_printf (dev, "get rates failed: 0x%x\n", r);
788 * Since the supported rates only up to 8 can be supported,
789 * if this is not 802.11b we're just going to be faking it
793 #define TESTSETRATE(x, y) \
796 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
797 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
800 if (i == ic->ic_sup_rates[x].rs_nrates) { \
801 ic->ic_sup_rates[x].rs_rates[i] = (y); \
802 ic->ic_sup_rates[x].rs_nrates++; \
806 #define SETRATE(x, y) \
807 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
809 ic->ic_sup_rates[x].rs_nrates++
811 ic->ic_curmode = IEEE80211_MODE_AUTO;
812 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
813 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
814 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
815 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
816 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
817 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
818 for (i = 0; i < len; i++) {
819 switch (rates[i] & IEEE80211_RATE_VAL) {
825 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
826 /* Lazy-init 802.11b. */
827 setbit(ic->ic_modecaps,
829 ic->ic_sup_rates[IEEE80211_MODE_11B].
832 SETRATE(IEEE80211_MODE_11B, rates[i]);
833 INCRATE(IEEE80211_MODE_11B);
836 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
837 SETRATE(IEEE80211_MODE_11A, rates[i]);
838 INCRATE(IEEE80211_MODE_11A);
840 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
841 SETRATE(IEEE80211_MODE_11G, rates[i]);
842 INCRATE(IEEE80211_MODE_11G);
849 * If the hardware supports 802.11g, it most
850 * likely supports 802.11b and all of the
851 * 802.11b and 802.11g speeds, so maybe we can
852 * just cheat here. Just how in the heck do
853 * we detect turbo modes, though?
855 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
856 TESTSETRATE(IEEE80211_MODE_11B,
857 IEEE80211_RATE_BASIC|2);
858 TESTSETRATE(IEEE80211_MODE_11B,
859 IEEE80211_RATE_BASIC|4);
860 TESTSETRATE(IEEE80211_MODE_11B,
861 IEEE80211_RATE_BASIC|11);
862 TESTSETRATE(IEEE80211_MODE_11B,
863 IEEE80211_RATE_BASIC|22);
865 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
866 TESTSETRATE(IEEE80211_MODE_11G, 48);
867 TESTSETRATE(IEEE80211_MODE_11G, 72);
868 TESTSETRATE(IEEE80211_MODE_11G, 96);
869 TESTSETRATE(IEEE80211_MODE_11G, 108);
871 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
872 TESTSETRATE(IEEE80211_MODE_11A, 48);
873 TESTSETRATE(IEEE80211_MODE_11A, 72);
874 TESTSETRATE(IEEE80211_MODE_11A, 96);
875 TESTSETRATE(IEEE80211_MODE_11A, 108);
879 ieee80211_init_channels(ic, NULL, &bands);
882 * To test for WPA support, we need to see if we can
883 * set AUTHENTICATION_MODE to WPA and read it back
887 arg = NDIS_80211_AUTHMODE_WPA;
888 r = ndis_set_info(sc,
889 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
891 r = ndis_get_info(sc,
892 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
893 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
894 ic->ic_caps |= IEEE80211_C_WPA;
898 * To test for supported ciphers, we set each
899 * available encryption type in descending order.
900 * If ENC3 works, then we have WEP, TKIP and AES.
901 * If only ENC2 works, then we have WEP and TKIP.
902 * If only ENC1 works, then we have just WEP.
905 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
906 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
908 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
909 | IEEE80211_CRYPTO_TKIP
910 | IEEE80211_CRYPTO_AES_CCM;
913 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
914 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
916 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
917 | IEEE80211_CRYPTO_TKIP;
920 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
921 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
923 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
926 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
928 ic->ic_caps |= IEEE80211_C_PMGT;
930 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
932 ic->ic_caps |= IEEE80211_C_TXPMGT;
934 ieee80211_ifattach(ic, eaddr);
935 ic->ic_raw_xmit = ndis_raw_xmit;
936 ic->ic_scan_start = ndis_scan_start;
937 ic->ic_scan_end = ndis_scan_end;
938 ic->ic_set_channel = ndis_set_channel;
939 ic->ic_scan_curchan = ndis_scan_curchan;
940 ic->ic_scan_mindwell = ndis_scan_mindwell;
941 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
942 //ic->ic_bss->ni_chan = ic->ic_bsschan;
943 ic->ic_vap_create = ndis_vap_create;
944 ic->ic_vap_delete = ndis_vap_delete;
945 ic->ic_update_mcast = ndis_update_mcast;
946 ic->ic_update_promisc = ndis_update_promisc;
949 ieee80211_announce(ic);
952 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
954 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
955 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
956 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
957 ifmedia_add(&sc->ifmedia,
958 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
959 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
960 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
961 ether_ifattach(ifp, eaddr);
970 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
973 DPRINTF(("attach done.\n"));
974 /* We're done talking to the NIC for now; halt it. */
976 DPRINTF(("halting done.\n"));
981 static struct ieee80211vap *
982 ndis_vap_create(struct ieee80211com *ic,
983 const char name[IFNAMSIZ], int unit, int opmode, int flags,
984 const uint8_t bssid[IEEE80211_ADDR_LEN],
985 const uint8_t mac[IEEE80211_ADDR_LEN])
987 struct ndis_vap *nvp;
988 struct ieee80211vap *vap;
990 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
992 nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap),
993 M_80211_VAP, M_NOWAIT | M_ZERO);
997 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
998 /* override with driver methods */
999 nvp->newstate = vap->iv_newstate;
1000 vap->iv_newstate = ndis_newstate;
1002 /* complete setup */
1003 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
1004 ic->ic_opmode = opmode;
1005 /* install key handing routines */
1006 vap->iv_key_set = ndis_add_key;
1007 vap->iv_key_delete = ndis_del_key;
1012 ndis_vap_delete(struct ieee80211vap *vap)
1014 struct ndis_vap *nvp = NDIS_VAP(vap);
1015 struct ieee80211com *ic = vap->iv_ic;
1016 struct ifnet *ifp = ic->ic_ifp;
1017 struct ndis_softc *sc = ifp->if_softc;
1020 callout_drain(&sc->ndis_scan_callout);
1021 ieee80211_vap_detach(vap);
1022 free(nvp, M_80211_VAP);
1026 * Shutdown hardware and free up resources. This can be called any
1027 * time after the mutex has been initialized. It is called in both
1028 * the error case in attach and the normal detach case so it needs
1029 * to be careful about only freeing resources that have actually been
1036 struct ndis_softc *sc;
1040 sc = device_get_softc(dev);
1044 ifp->if_flags &= ~IFF_UP;
1046 if (device_is_attached(dev)) {
1051 ieee80211_ifdetach(ifp->if_l2com);
1053 ether_ifdetach(ifp);
1058 if (sc->ndis_tickitem != NULL)
1059 IoFreeWorkItem(sc->ndis_tickitem);
1060 if (sc->ndis_startitem != NULL)
1061 IoFreeWorkItem(sc->ndis_startitem);
1062 if (sc->ndis_resetitem != NULL)
1063 IoFreeWorkItem(sc->ndis_resetitem);
1064 if (sc->ndis_inputitem != NULL)
1065 IoFreeWorkItem(sc->ndis_inputitem);
1066 if (sc->ndisusb_xferdoneitem != NULL)
1067 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1068 if (sc->ndisusb_taskitem != NULL)
1069 IoFreeWorkItem(sc->ndisusb_taskitem);
1071 bus_generic_detach(dev);
1072 ndis_unload_driver(sc);
1075 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1076 if (sc->ndis_res_io)
1077 bus_release_resource(dev, SYS_RES_IOPORT,
1078 sc->ndis_io_rid, sc->ndis_res_io);
1079 if (sc->ndis_res_mem)
1080 bus_release_resource(dev, SYS_RES_MEMORY,
1081 sc->ndis_mem_rid, sc->ndis_res_mem);
1082 if (sc->ndis_res_altmem)
1083 bus_release_resource(dev, SYS_RES_MEMORY,
1084 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1089 if (sc->ndis_iftype == PCMCIABus)
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
1165 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1166 ndis_handle adapter;
1172 uint32_t lookaheadlen;
1175 ndis_miniport_block *block;
1185 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1192 /* Save the data provided to us so far. */
1194 m->m_len = lookaheadlen + hdrlen;
1195 m->m_pkthdr.len = pktlen + hdrlen;
1197 m_copyback(m, 0, hdrlen, hdr);
1198 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1200 /* Now create a fake NDIS_PACKET to hold the data */
1202 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1204 if (status != NDIS_STATUS_SUCCESS) {
1211 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1219 p->np_private.npp_head = p->np_private.npp_tail = b;
1220 p->np_private.npp_totlen = m->m_pkthdr.len;
1222 /* Save the packet RX context somewhere. */
1223 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1224 priv->nep_ctx = ctx;
1226 if (!NDIS_SERIALIZED(block))
1227 KeAcquireSpinLock(&block->nmb_lock, &irql);
1229 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1231 if (!NDIS_SERIALIZED(block))
1232 KeReleaseSpinLock(&block->nmb_lock, irql);
1238 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1244 ndis_rxeof_done(adapter)
1245 ndis_handle adapter;
1247 struct ndis_softc *sc;
1248 ndis_miniport_block *block;
1252 /* Schedule transfer/RX of queued packets. */
1254 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1256 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1262 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1265 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1267 ndis_handle adapter;
1271 ndis_miniport_block *block;
1272 struct ndis_softc *sc;
1281 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1284 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1286 l = block->nmb_packetlist.nle_flink;
1287 while(!IsListEmpty(&block->nmb_packetlist)) {
1288 l = RemoveHeadList((&block->nmb_packetlist));
1289 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1290 InitializeListHead((&p->np_list));
1292 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1297 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1299 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1300 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1301 m->m_len, m->m_pkthdr.len - m->m_len);
1303 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1306 * If status is NDIS_STATUS_PENDING, do nothing and
1307 * wait for a callback to the ndis_rxeof_xfr_done()
1311 m->m_len = m->m_pkthdr.len;
1312 m->m_pkthdr.rcvif = ifp;
1314 if (status == NDIS_STATUS_SUCCESS) {
1315 IoFreeMdl(p->np_private.npp_head);
1317 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1318 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1319 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1320 IoQueueWorkItem(sc->ndis_inputitem,
1321 (io_workitem_func)ndis_inputtask_wrap,
1322 WORKQUEUE_CRITICAL, ifp);
1325 if (status == NDIS_STATUS_FAILURE)
1328 /* Advance to next packet */
1329 l = block->nmb_packetlist.nle_flink;
1332 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1338 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1341 ndis_rxeof_xfr_done(adapter, packet, status, len)
1342 ndis_handle adapter;
1343 ndis_packet *packet;
1347 ndis_miniport_block *block;
1348 struct ndis_softc *sc;
1353 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1357 IoFreeMdl(packet->np_private.npp_head);
1358 NdisFreePacket(packet);
1360 if (status != NDIS_STATUS_SUCCESS) {
1365 m->m_len = m->m_pkthdr.len;
1366 m->m_pkthdr.rcvif = ifp;
1367 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1368 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1369 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1370 IoQueueWorkItem(sc->ndis_inputitem,
1371 (io_workitem_func)ndis_inputtask_wrap,
1372 WORKQUEUE_CRITICAL, ifp);
1377 * A frame has been uploaded: pass the resulting mbuf chain up to
1378 * the higher level protocols.
1380 * When handling received NDIS packets, the 'status' field in the
1381 * out-of-band portion of the ndis_packet has special meaning. In the
1382 * most common case, the underlying NDIS driver will set this field
1383 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1384 * take posession of it. We then change the status field to
1385 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1386 * and that we will return it at some point in the future via the
1387 * return packet handler.
1389 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1390 * this means the driver is running out of packet/buffer resources and
1391 * wants to maintain ownership of the packet. In this case, we have to
1392 * copy the packet data into local storage and let the driver keep the
1396 ndis_rxeof(adapter, packets, pktcnt)
1397 ndis_handle adapter;
1398 ndis_packet **packets;
1401 struct ndis_softc *sc;
1402 ndis_miniport_block *block;
1405 ndis_tcpip_csum *csum;
1407 struct mbuf *m0, *m;
1410 block = (ndis_miniport_block *)adapter;
1411 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1415 * There's a slim chance the driver may indicate some packets
1416 * before we're completely ready to handle them. If we detect this,
1417 * we need to return them to the miniport and ignore them.
1420 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1421 for (i = 0; i < pktcnt; i++) {
1423 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1425 ndis_return_packet(p, block);
1431 for (i = 0; i < pktcnt; i++) {
1433 /* Stash the softc here so ptom can use it. */
1435 if (ndis_ptom(&m0, p)) {
1436 device_printf (sc->ndis_dev, "ptom failed\n");
1437 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1438 ndis_return_packet(p, block);
1441 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1442 m = m_dup(m0, M_DONTWAIT);
1444 * NOTE: we want to destroy the mbuf here, but
1445 * we don't actually want to return it to the
1446 * driver via the return packet handler. By
1447 * bumping np_refcnt, we can prevent the
1448 * ndis_return_packet() routine from actually
1458 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1460 m = m_dup(m0, M_DONTWAIT);
1461 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1464 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1471 m0->m_pkthdr.rcvif = ifp;
1473 /* Deal with checksum offload. */
1475 if (ifp->if_capenable & IFCAP_RXCSUM &&
1476 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1478 p->np_ext.npe_info[ndis_tcpipcsum_info];
1479 csum = (ndis_tcpip_csum *)&s;
1480 if (csum->u.ntc_rxflags &
1481 NDIS_RXCSUM_IP_PASSED)
1482 m0->m_pkthdr.csum_flags |=
1483 CSUM_IP_CHECKED|CSUM_IP_VALID;
1484 if (csum->u.ntc_rxflags &
1485 (NDIS_RXCSUM_TCP_PASSED |
1486 NDIS_RXCSUM_UDP_PASSED)) {
1487 m0->m_pkthdr.csum_flags |=
1488 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1489 m0->m_pkthdr.csum_data = 0xFFFF;
1493 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1494 _IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1495 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1496 IoQueueWorkItem(sc->ndis_inputitem,
1497 (io_workitem_func)ndis_inputtask_wrap,
1498 WORKQUEUE_CRITICAL, ifp);
1506 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1507 * packets into the stack in order to avoid calling (*ifp->if_input)()
1508 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1509 * 'dispatch level' per-cpu sleep lock).
1513 ndis_inputtask(dobj, arg)
1514 device_object *dobj;
1517 ndis_miniport_block *block;
1519 struct ndis_softc *sc;
1521 struct ieee80211com *ic;
1522 struct ieee80211vap *vap;
1528 vap = TAILQ_FIRST(&ic->ic_vaps);
1529 block = dobj->do_devext;
1531 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1533 _IF_DEQUEUE(&sc->ndis_rxqueue, m);
1536 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1537 if ((sc->ndis_80211 != 0) && (vap != NULL))
1538 vap->iv_deliver_data(vap, vap->iv_bss, m);
1540 (*ifp->if_input)(ifp, m);
1541 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1543 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1549 * A frame was downloaded to the chip. It's safe for us to clean up
1553 ndis_txeof(adapter, packet, status)
1554 ndis_handle adapter;
1555 ndis_packet *packet;
1559 struct ndis_softc *sc;
1560 ndis_miniport_block *block;
1565 block = (ndis_miniport_block *)adapter;
1566 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1570 idx = packet->np_txidx;
1572 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1574 ndis_free_packet(packet);
1578 sc->ndis_txarray[idx] = NULL;
1579 sc->ndis_txpending++;
1581 if (status == NDIS_STATUS_SUCCESS)
1586 sc->ndis_tx_timer = 0;
1587 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1591 IoQueueWorkItem(sc->ndis_startitem,
1592 (io_workitem_func)ndis_starttask_wrap,
1593 WORKQUEUE_CRITICAL, ifp);
1599 ndis_linksts(adapter, status, sbuf, slen)
1600 ndis_handle adapter;
1605 ndis_miniport_block *block;
1606 struct ndis_softc *sc;
1609 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1610 sc->ndis_sts = status;
1612 /* Event list is all full up, drop this one. */
1615 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1620 /* Cache the event. */
1623 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1625 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1630 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1632 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1633 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1634 NDIS_EVTINC(sc->ndis_evtpidx);
1641 ndis_linksts_done(adapter)
1642 ndis_handle adapter;
1644 ndis_miniport_block *block;
1645 struct ndis_softc *sc;
1649 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1652 if (!NDIS_INITIALIZED(sc))
1655 switch (sc->ndis_sts) {
1656 case NDIS_STATUS_MEDIA_CONNECT:
1657 IoQueueWorkItem(sc->ndis_tickitem,
1658 (io_workitem_func)ndis_ticktask_wrap,
1659 WORKQUEUE_CRITICAL, sc);
1660 IoQueueWorkItem(sc->ndis_startitem,
1661 (io_workitem_func)ndis_starttask_wrap,
1662 WORKQUEUE_CRITICAL, ifp);
1664 case NDIS_STATUS_MEDIA_DISCONNECT:
1666 IoQueueWorkItem(sc->ndis_tickitem,
1667 (io_workitem_func)ndis_ticktask_wrap,
1668 WORKQUEUE_CRITICAL, sc);
1674 /* Notify possible listners of interface change. */
1685 struct ndis_softc *sc;
1689 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1690 IoQueueWorkItem(sc->ndis_tickitem,
1691 (io_workitem_func)ndis_ticktask_wrap,
1692 WORKQUEUE_CRITICAL, sc);
1693 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1696 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1697 sc->ifp->if_oerrors++;
1698 device_printf(sc->ndis_dev, "watchdog timeout\n");
1700 IoQueueWorkItem(sc->ndis_resetitem,
1701 (io_workitem_func)ndis_resettask_wrap,
1702 WORKQUEUE_CRITICAL, sc);
1703 IoQueueWorkItem(sc->ndis_startitem,
1704 (io_workitem_func)ndis_starttask_wrap,
1705 WORKQUEUE_CRITICAL, sc->ifp);
1708 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1712 ndis_ticktask(d, xsc)
1716 struct ndis_softc *sc;
1717 struct ieee80211com *ic;
1718 struct ieee80211vap *vap;
1719 ndis_checkforhang_handler hangfunc;
1723 ic = sc->ifp->if_l2com;
1724 vap = TAILQ_FIRST(&ic->ic_vaps);
1727 if (!NDIS_INITIALIZED(sc)) {
1733 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1735 if (hangfunc != NULL) {
1736 rval = MSCALL1(hangfunc,
1737 sc->ndis_block->nmb_miniportadapterctx);
1745 if (sc->ndis_link == 0 &&
1746 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1749 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1750 ndis_getstate_80211(sc);
1751 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1754 if_link_state_change(sc->ifp, LINK_STATE_UP);
1757 if (sc->ndis_link == 1 &&
1758 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1761 if ((sc->ndis_80211 != 0) && (vap != NULL))
1762 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1764 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1773 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1775 bus_dma_segment_t *segs;
1781 struct ndis_sc_list *sclist;
1784 if (error || arg == NULL)
1789 sclist->nsl_frags = nseg;
1791 for (i = 0; i < nseg; i++) {
1792 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1793 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1800 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1801 const struct ieee80211_bpf_params *params)
1803 /* no support; just discard */
1805 ieee80211_free_node(ni);
1810 ndis_update_mcast(struct ifnet *ifp)
1812 struct ndis_softc *sc = ifp->if_softc;
1818 ndis_update_promisc(struct ifnet *ifp)
1824 ndis_starttask(d, arg)
1832 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1838 * Main transmit routine. To make NDIS drivers happy, we need to
1839 * transform mbuf chains into NDIS packets and feed them to the
1840 * send packet routines. Most drivers allow you to send several
1841 * packets at once (up to the maxpkts limit). Unfortunately, rather
1842 * that accepting them in the form of a linked list, they expect
1843 * a contiguous array of pointers to packets.
1845 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1846 * we need to perform busdma work here. Those that use map registers
1847 * will do the mapping themselves on a buffer by buffer basis.
1854 struct ndis_softc *sc;
1855 struct mbuf *m = NULL;
1856 ndis_packet **p0 = NULL, *p = NULL;
1857 ndis_tcpip_csum *csum;
1858 int pcnt = 0, status;
1864 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1869 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1871 while(sc->ndis_txpending) {
1872 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1876 NdisAllocatePacket(&status,
1877 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1879 if (status != NDIS_STATUS_SUCCESS)
1882 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1883 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1889 * Save pointer to original mbuf
1890 * so we can free it later.
1893 p = sc->ndis_txarray[sc->ndis_txidx];
1894 p->np_txidx = sc->ndis_txidx;
1896 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1899 * Do scatter/gather processing, if driver requested it.
1902 bus_dmamap_load_mbuf(sc->ndis_ttag,
1903 sc->ndis_tmaps[sc->ndis_txidx], m,
1904 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1905 bus_dmamap_sync(sc->ndis_ttag,
1906 sc->ndis_tmaps[sc->ndis_txidx],
1907 BUS_DMASYNC_PREREAD);
1908 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1911 /* Handle checksum offload. */
1913 if (ifp->if_capenable & IFCAP_TXCSUM &&
1914 m->m_pkthdr.csum_flags) {
1915 csum = (ndis_tcpip_csum *)
1916 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1917 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1918 if (m->m_pkthdr.csum_flags & CSUM_IP)
1919 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1920 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1921 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1922 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1923 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1924 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1928 sc->ndis_txpending--;
1933 * If there's a BPF listener, bounce a copy of this frame
1937 if (!sc->ndis_80211) /* XXX handle 80211 */
1941 * The array that p0 points to must appear contiguous,
1942 * so we must not wrap past the end of sc->ndis_txarray[].
1943 * If it looks like we're about to wrap, break out here
1944 * so the this batch of packets can be transmitted, then
1945 * wait for txeof to ask us to send the rest.
1948 if (sc->ndis_txidx == 0)
1957 if (sc->ndis_txpending == 0)
1958 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1961 * Set a timeout in case the chip goes out to lunch.
1963 sc->ndis_tx_timer = 5;
1968 * According to NDIS documentation, if a driver exports
1969 * a MiniportSendPackets() routine, we prefer that over
1970 * a MiniportSend() routine (which sends just a single
1974 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1975 ndis_send_packets(sc, p0, pcnt);
1977 ndis_send_packet(sc, p);
1986 struct ndis_softc *sc = xsc;
1987 struct ifnet *ifp = sc->ifp;
1988 struct ieee80211com *ic = ifp->if_l2com;
1992 * Avoid reintializing the link unnecessarily.
1993 * This should be dealt with in a better way by
1994 * fixing the upper layer modules so they don't
1995 * call ifp->if_init() quite as often.
2001 * Cancel pending I/O and free all RX/TX buffers.
2005 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2006 error = ndis_init_nic(sc);
2008 device_printf(sc->ndis_dev,
2009 "failed to initialize the device: %d\n", error);
2014 /* Init our MAC address */
2016 /* Program the packet filter */
2018 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
2020 if (ifp->if_flags & IFF_BROADCAST)
2021 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
2023 if (ifp->if_flags & IFF_PROMISC)
2024 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2026 len = sizeof(sc->ndis_filter);
2028 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2029 &sc->ndis_filter, &len);
2032 device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
2040 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2043 * Program the multicast filter, if necessary.
2047 /* Setup task offload. */
2048 ndis_set_offload(sc);
2053 sc->ndis_txpending = sc->ndis_maxpkts;
2056 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2058 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2059 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2060 sc->ndis_tx_timer = 0;
2063 * Some drivers don't set this value. The NDIS spec says
2064 * the default checkforhang timeout is "approximately 2
2065 * seconds." We use 3 seconds, because it seems for some
2066 * drivers, exactly 2 seconds is too fast.
2068 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2069 sc->ndis_block->nmb_checkforhangsecs = 3;
2071 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2072 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2075 /* XXX force handling */
2077 ieee80211_start_all(ic); /* start all vap's */
2081 * Set media options.
2084 ndis_ifmedia_upd(ifp)
2087 struct ndis_softc *sc;
2091 if (NDIS_INITIALIZED(sc))
2098 * Report current media status.
2101 ndis_ifmedia_sts(ifp, ifmr)
2103 struct ifmediareq *ifmr;
2105 struct ndis_softc *sc;
2106 uint32_t media_info;
2107 ndis_media_state linkstate;
2110 ifmr->ifm_status = IFM_AVALID;
2111 ifmr->ifm_active = IFM_ETHER;
2114 if (!NDIS_INITIALIZED(sc))
2117 len = sizeof(linkstate);
2118 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2119 (void *)&linkstate, &len);
2121 len = sizeof(media_info);
2122 error = ndis_get_info(sc, OID_GEN_LINK_SPEED,
2123 (void *)&media_info, &len);
2125 if (linkstate == nmc_connected)
2126 ifmr->ifm_status |= IFM_ACTIVE;
2128 switch(media_info) {
2130 ifmr->ifm_active |= IFM_10_T;
2133 ifmr->ifm_active |= IFM_100_TX;
2136 ifmr->ifm_active |= IFM_1000_T;
2139 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2147 ndis_set_cipher(sc, cipher)
2148 struct ndis_softc *sc;
2151 struct ieee80211com *ic;
2155 ic = sc->ifp->if_l2com;
2159 if (cipher == WPA_CSE_WEP40 || WPA_CSE_WEP104) {
2160 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2162 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2165 if (cipher == WPA_CSE_TKIP) {
2166 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2168 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2171 if (cipher == WPA_CSE_CCMP) {
2172 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2174 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2177 DPRINTF(("Setting cipher to %d\n", arg));
2179 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2184 /* Check that the cipher was set correctly. */
2187 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2189 if (rval != 0 || arg != save)
2196 * WPA is hairy to set up. Do the work in a separate routine
2197 * so we don't clutter the setstate function too much.
2198 * Important yet undocumented fact: first we have to set the
2199 * authentication mode, _then_ we enable the ciphers. If one
2200 * of the WPA authentication modes isn't enabled, the driver
2201 * might not permit the TKIP or AES ciphers to be selected.
2205 ndis_set_wpa(sc, ie, ielen)
2206 struct ndis_softc *sc;
2210 struct ieee80211_ie_wpa *w;
2217 * Apparently, the only way for us to know what ciphers
2218 * and key management/authentication mode to use is for
2219 * us to inspect the optional information element (IE)
2220 * stored in the 802.11 state machine. This IE should be
2221 * supplied by the WPA supplicant.
2224 w = (struct ieee80211_ie_wpa *)ie;
2226 /* Check for the right kind of IE. */
2227 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2228 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2232 /* Skip over the ucast cipher OIDs. */
2233 pos = (char *)&w->wpa_uciphers[0];
2234 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2236 /* Skip over the authmode count. */
2237 pos += sizeof(u_int16_t);
2240 * Check for the authentication modes. I'm
2241 * pretty sure there's only supposed to be one.
2244 n = (struct ndis_ie *)pos;
2245 if (n->ni_val == WPA_ASE_NONE)
2246 arg = NDIS_80211_AUTHMODE_WPANONE;
2248 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2249 arg = NDIS_80211_AUTHMODE_WPA;
2251 if (n->ni_val == WPA_ASE_8021X_PSK)
2252 arg = NDIS_80211_AUTHMODE_WPAPSK;
2254 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2256 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2259 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2261 /* Now configure the desired ciphers. */
2263 /* First, set up the multicast group cipher. */
2264 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2266 if (ndis_set_cipher(sc, n->ni_val))
2269 /* Now start looking around for the unicast ciphers. */
2270 pos = (char *)&w->wpa_uciphers[0];
2271 n = (struct ndis_ie *)pos;
2273 for (i = 0; i < w->wpa_uciphercnt; i++) {
2274 if (ndis_set_cipher(sc, n->ni_val))
2283 ndis_setstate_80211(sc)
2284 struct ndis_softc *sc;
2286 struct ieee80211com *ic;
2287 struct ieee80211vap *vap;
2288 ndis_80211_macaddr bssid;
2289 ndis_80211_config config;
2296 vap = TAILQ_FIRST(&ic->ic_vaps);
2298 if (!NDIS_INITIALIZED(sc)) {
2299 DPRINTF(("%s: NDIS not initialized\n", __func__));
2303 /* Disassociate and turn off radio. */
2307 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2309 /* Set network infrastructure mode. */
2312 if (ic->ic_opmode == IEEE80211_M_IBSS)
2313 arg = NDIS_80211_NET_INFRA_IBSS;
2315 arg = NDIS_80211_NET_INFRA_BSS;
2317 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2320 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2322 /* Set power management */
2325 if (vap->iv_flags & IEEE80211_F_PMGTON)
2326 arg = NDIS_80211_POWERMODE_FAST_PSP;
2328 arg = NDIS_80211_POWERMODE_CAM;
2329 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2332 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2333 ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2334 arg = dBm2mW[ic->ic_txpowlimit];
2336 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2340 * Default encryption mode to off, authentication
2341 * to open and privacy to 'accept everything.'
2345 arg = NDIS_80211_WEPSTAT_DISABLED;
2346 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2349 arg = NDIS_80211_AUTHMODE_OPEN;
2350 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2353 * Note that OID_80211_PRIVACY_FILTER is optional:
2354 * not all drivers implement it.
2357 arg = NDIS_80211_PRIVFILT_8021XWEP;
2358 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2360 len = sizeof(config);
2361 bzero((char *)&config, len);
2362 config.nc_length = len;
2363 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2364 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2367 * Some drivers expect us to initialize these values, so
2368 * provide some defaults.
2371 if (config.nc_beaconperiod == 0)
2372 config.nc_beaconperiod = 100;
2373 if (config.nc_atimwin == 0)
2374 config.nc_atimwin = 100;
2375 if (config.nc_fhconfig.ncf_dwelltime == 0)
2376 config.nc_fhconfig.ncf_dwelltime = 200;
2377 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2380 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2381 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2382 IEEE80211_CHAN_5GHZ;
2383 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2384 config.nc_dsconfig =
2385 ic->ic_bsschan->ic_freq * 1000;
2386 len = sizeof(config);
2387 config.nc_length = len;
2388 config.nc_fhconfig.ncf_length =
2389 sizeof(ndis_80211_config_fh);
2390 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2391 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2394 device_printf(sc->ndis_dev, "couldn't change "
2395 "DS config to %ukHz: %d\n",
2396 config.nc_dsconfig, rval);
2399 device_printf(sc->ndis_dev, "couldn't retrieve "
2400 "channel info: %d\n", rval);
2402 /* Set the BSSID to our value so the driver doesn't associate */
2403 len = IEEE80211_ADDR_LEN;
2404 bcopy(IF_LLADDR(ifp), bssid, len);
2405 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2406 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2408 device_printf(sc->ndis_dev,
2409 "setting BSSID failed: %d\n", rval);
2414 ndis_auth_and_assoc(sc, vap)
2415 struct ndis_softc *sc;
2416 struct ieee80211vap *vap;
2418 struct ieee80211com *ic;
2419 struct ieee80211_node *ni;
2420 ndis_80211_ssid ssid;
2421 ndis_80211_macaddr bssid;
2423 int i, rval = 0, len, error;
2431 if (!NDIS_INITIALIZED(sc)) {
2432 DPRINTF(("%s: NDIS not initialized\n", __func__));
2437 ndis_setstate_80211(sc);
2439 /* Set network infrastructure mode. */
2442 if (vap->iv_opmode == IEEE80211_M_IBSS)
2443 arg = NDIS_80211_NET_INFRA_IBSS;
2445 arg = NDIS_80211_NET_INFRA_BSS;
2447 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2450 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2452 /* Set RTS threshold */
2455 arg = vap->iv_rtsthreshold;
2456 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2458 /* Set fragmentation threshold */
2461 arg = vap->iv_fragthreshold;
2462 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2466 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2467 !(vap->iv_flags & IEEE80211_F_WPA)) {
2470 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2472 arg = NDIS_80211_AUTHMODE_SHARED;
2473 DPRINTF(("Setting shared auth\n"));
2474 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2477 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2478 if (vap->iv_nw_keys[i].wk_keylen) {
2479 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2480 IEEE80211_CIPHER_WEP)
2482 bzero((char *)&wep, sizeof(wep));
2483 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2486 * 5, 13 and 16 are the only valid
2487 * only valid key lengths. Anything
2488 * in between will be zero padded out to
2489 * the next highest boundary.
2491 if (vap->iv_nw_keys[i].wk_keylen < 5)
2493 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2494 vap->iv_nw_keys[i].wk_keylen < 13)
2496 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2497 vap->iv_nw_keys[i].wk_keylen < 16)
2501 wep.nw_length = (sizeof(uint32_t) * 3)
2503 if (i == vap->iv_def_txkey)
2504 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2505 bcopy(vap->iv_nw_keys[i].wk_key,
2506 wep.nw_keydata, wep.nw_length);
2508 DPRINTF(("Setting WEP key %d\n", i));
2509 rval = ndis_set_info(sc,
2510 OID_802_11_ADD_WEP, &wep, &len);
2512 device_printf(sc->ndis_dev,
2513 "set wepkey failed: %d\n", rval);
2518 DPRINTF(("Setting WEP on\n"));
2519 arg = NDIS_80211_WEPSTAT_ENABLED;
2521 rval = ndis_set_info(sc,
2522 OID_802_11_WEP_STATUS, &arg, &len);
2524 device_printf(sc->ndis_dev,
2525 "enable WEP failed: %d\n", rval);
2526 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2527 arg = NDIS_80211_PRIVFILT_8021XWEP;
2529 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2533 OID_802_11_PRIVACY_FILTER, &arg, &len);
2538 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2539 vap->iv_appie_assocreq != NULL) {
2540 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2541 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2543 device_printf(sc->ndis_dev, "WPA setup failed\n");
2547 /* Set network type. */
2551 switch (vap->iv_curmode) {
2552 case IEEE80211_MODE_11A:
2553 arg = NDIS_80211_NETTYPE_11OFDM5;
2555 case IEEE80211_MODE_11B:
2556 arg = NDIS_80211_NETTYPE_11DS;
2558 case IEEE80211_MODE_11G:
2559 arg = NDIS_80211_NETTYPE_11OFDM24;
2562 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2567 DPRINTF(("Setting network type to %d\n", arg));
2569 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2572 device_printf (sc->ndis_dev,
2573 "set nettype failed: %d\n", rval);
2578 * If the user selected a specific BSSID, try
2579 * to use that one. This is useful in the case where
2580 * there are several APs in range with the same network
2581 * name. To delete the BSSID, we use the broadcast
2582 * address as the BSSID.
2583 * Note that some drivers seem to allow setting a BSSID
2584 * in ad-hoc mode, which has the effect of forcing the
2585 * NIC to create an ad-hoc cell with a specific BSSID,
2586 * instead of a randomly chosen one. However, the net80211
2587 * code makes the assumtion that the BSSID setting is invalid
2588 * when you're in ad-hoc mode, so we don't allow that here.
2591 len = IEEE80211_ADDR_LEN;
2592 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2593 vap->iv_opmode != IEEE80211_M_IBSS)
2594 bcopy(ni->ni_bssid, bssid, len);
2596 bcopy(ifp->if_broadcastaddr, bssid, len);
2598 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2599 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2601 device_printf(sc->ndis_dev,
2602 "setting BSSID failed: %d\n", rval);
2604 /* Set SSID -- always do this last. */
2607 if (ndis_debug > 0) {
2608 printf("Setting ESSID to ");
2609 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2615 bzero((char *)&ssid, len);
2616 ssid.ns_ssidlen = ni->ni_esslen;
2617 if (ssid.ns_ssidlen == 0) {
2618 ssid.ns_ssidlen = 1;
2620 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2622 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2625 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2631 ndis_get_bssid_list(sc, bl)
2632 struct ndis_softc *sc;
2633 ndis_80211_bssid_list_ex **bl;
2637 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2638 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2642 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2643 if (error == ENOSPC) {
2644 free(*bl, M_DEVBUF);
2645 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2649 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2652 DPRINTF(("%s: failed to read\n", __func__));
2653 free(*bl, M_DEVBUF);
2661 ndis_get_assoc(sc, assoc)
2662 struct ndis_softc *sc;
2663 ndis_wlan_bssid_ex **assoc;
2665 struct ifnet *ifp = sc->ifp;
2666 struct ieee80211com *ic = ifp->if_l2com;
2667 struct ieee80211vap *vap;
2668 struct ieee80211_node *ni;
2669 ndis_80211_bssid_list_ex *bl;
2670 ndis_wlan_bssid_ex *bs;
2671 ndis_80211_macaddr bssid;
2677 len = sizeof(bssid);
2678 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2680 device_printf(sc->ndis_dev, "failed to get bssid\n");
2684 vap = TAILQ_FIRST(&ic->ic_vaps);
2687 error = ndis_get_bssid_list(sc, &bl);
2691 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2692 for (i = 0; i < bl->nblx_items; i++) {
2693 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2694 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2695 if (*assoc == NULL) {
2699 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2701 if (ic->ic_opmode == IEEE80211_M_STA)
2702 ni->ni_associd = 1 | 0xc000; /* fake associd */
2705 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2713 ndis_getstate_80211(sc)
2714 struct ndis_softc *sc;
2716 struct ieee80211com *ic;
2717 struct ieee80211vap *vap;
2718 struct ieee80211_node *ni;
2719 ndis_wlan_bssid_ex *bs;
2720 int rval, len, i = 0;
2727 vap = TAILQ_FIRST(&ic->ic_vaps);
2730 if (!NDIS_INITIALIZED(sc))
2733 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2736 /* We're associated, retrieve info on the current bssid. */
2737 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2738 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2739 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2741 /* Get SSID from current association info. */
2742 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2743 bs->nwbx_ssid.ns_ssidlen);
2744 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2747 rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
2749 device_printf (sc->ndis_dev, "get link speed failed: %d\n",
2751 ni->ni_txrate = arg / 5000;
2753 if (ic->ic_caps & IEEE80211_C_PMGT) {
2755 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2758 device_printf(sc->ndis_dev,
2759 "get power mode failed: %d\n", rval);
2760 if (arg == NDIS_80211_POWERMODE_CAM)
2761 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2763 vap->iv_flags |= IEEE80211_F_PMGTON;
2767 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2769 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2770 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2771 if (dBm2mW[i] >= arg)
2773 ic->ic_txpowlimit = i;
2777 * Use the current association information to reflect
2778 * what channel we're on.
2780 ic->ic_curchan = ieee80211_find_channel(ic,
2781 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2782 if (ic->ic_curchan == NULL)
2783 ic->ic_curchan = &ic->ic_channels[0];
2784 ni->ni_chan = ic->ic_curchan;
2785 ic->ic_bsschan = ic->ic_curchan;
2790 * Determine current authentication mode. Note: authmode
2791 * reporting isn't supported prior to FreeBSD 6.x.
2795 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2797 device_printf (sc->ndis_dev,
2798 "get authmode status failed: %d\n", rval);
2800 vap->iv_flags &= ~IEEE80211_F_WPA;
2802 case NDIS_80211_AUTHMODE_OPEN:
2803 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2805 case NDIS_80211_AUTHMODE_SHARED:
2806 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2808 case NDIS_80211_AUTHMODE_AUTO:
2809 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2811 case NDIS_80211_AUTHMODE_WPA:
2812 case NDIS_80211_AUTHMODE_WPAPSK:
2813 case NDIS_80211_AUTHMODE_WPANONE:
2814 ni->ni_authmode = IEEE80211_AUTH_WPA;
2815 vap->iv_flags |= IEEE80211_F_WPA1;
2817 case NDIS_80211_AUTHMODE_WPA2:
2818 case NDIS_80211_AUTHMODE_WPA2PSK:
2819 ni->ni_authmode = IEEE80211_AUTH_WPA;
2820 vap->iv_flags |= IEEE80211_F_WPA2;
2823 ni->ni_authmode = IEEE80211_AUTH_NONE;
2829 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2832 device_printf (sc->ndis_dev,
2833 "get wep status failed: %d\n", rval);
2835 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2836 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2838 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2843 ndis_ioctl(ifp, command, data)
2848 struct ndis_softc *sc = ifp->if_softc;
2849 struct ifreq *ifr = (struct ifreq *) data;
2856 if (ifp->if_flags & IFF_UP) {
2857 if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2858 ifp->if_flags & IFF_PROMISC &&
2859 !(sc->ndis_if_flags & IFF_PROMISC)) {
2861 NDIS_PACKET_TYPE_PROMISCUOUS;
2862 i = sizeof(sc->ndis_filter);
2863 error = ndis_set_info(sc,
2864 OID_GEN_CURRENT_PACKET_FILTER,
2865 &sc->ndis_filter, &i);
2866 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2867 !(ifp->if_flags & IFF_PROMISC) &&
2868 sc->ndis_if_flags & IFF_PROMISC) {
2870 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2871 i = sizeof(sc->ndis_filter);
2872 error = ndis_set_info(sc,
2873 OID_GEN_CURRENT_PACKET_FILTER,
2874 &sc->ndis_filter, &i);
2878 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2881 sc->ndis_if_flags = ifp->if_flags;
2891 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2894 ifp->if_capenable = ifr->ifr_reqcap;
2895 if (ifp->if_capenable & IFCAP_TXCSUM)
2896 ifp->if_hwassist = sc->ndis_hwassist;
2898 ifp->if_hwassist = 0;
2899 ndis_set_offload(sc);
2902 error = ether_ioctl(ifp, command, data);
2906 /*NDIS_UNLOCK(sc);*/
2912 ndis_ioctl_80211(ifp, command, data)
2917 struct ndis_softc *sc = ifp->if_softc;
2918 struct ieee80211com *ic = ifp->if_l2com;
2919 struct ifreq *ifr = (struct ifreq *) data;
2920 struct ndis_oid_data oid;
2921 struct ndis_evt evt;
2928 if (ifp->if_flags & IFF_UP) {
2929 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
2932 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2935 sc->ndis_if_flags = ifp->if_flags;
2937 /*NDIS_UNLOCK(sc);*/
2940 if ((error = priv_check(curthread, PRIV_DRIVER)))
2942 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2945 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2946 if (oidbuf == NULL) {
2950 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2952 free(oidbuf, M_TEMP);
2955 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2957 free(oidbuf, M_TEMP);
2960 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2962 free(oidbuf, M_TEMP);
2965 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2966 free(oidbuf, M_TEMP);
2969 if ((error = priv_check(curthread, PRIV_DRIVER)))
2971 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2974 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2975 if (oidbuf == NULL) {
2979 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2981 free(oidbuf, M_TEMP);
2984 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2986 free(oidbuf, M_TEMP);
2989 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2991 free(oidbuf, M_TEMP);
2994 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2995 free(oidbuf, M_TEMP);
2997 case SIOCGPRIVATE_0:
2998 if ((error = priv_check(curthread, PRIV_DRIVER)))
3001 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3006 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
3011 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3016 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3017 ifr->ifr_data, sizeof(uint32_t) * 2);
3022 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3023 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3024 ifr->ifr_data + (sizeof(uint32_t) * 2),
3025 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3030 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3031 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3033 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3034 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3035 NDIS_EVTINC(sc->ndis_evtcidx);
3039 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
3042 error = ether_ioctl(ifp, command, data);
3052 ndis_del_key(vap, key)
3053 struct ieee80211vap *vap;
3054 const struct ieee80211_key *key;
3056 struct ndis_softc *sc;
3057 ndis_80211_key rkey;
3060 sc = vap->iv_ic->ic_ifp->if_softc;
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.
3086 ndis_add_key(vap, key, mac)
3087 struct ieee80211vap *vap;
3088 const struct ieee80211_key *key;
3089 const uint8_t mac[IEEE80211_ADDR_LEN];
3091 struct ndis_softc *sc;
3093 ndis_80211_key rkey;
3096 ifp = vap->iv_ic->ic_ifp;
3099 switch (key->wk_cipher->ic_cipher) {
3100 case IEEE80211_CIPHER_TKIP:
3102 len = sizeof(ndis_80211_key);
3103 bzero((char *)&rkey, sizeof(rkey));
3106 rkey.nk_keylen = key->wk_keylen;
3108 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3109 rkey.nk_keylen += 16;
3111 /* key index - gets weird in NDIS */
3113 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3114 rkey.nk_keyidx = key->wk_keyix;
3118 if (key->wk_flags & IEEE80211_KEY_XMIT)
3119 rkey.nk_keyidx |= 1 << 31;
3121 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3122 bcopy(ifp->if_broadcastaddr,
3123 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3125 bcopy(vap->iv_bss->ni_bssid,
3126 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3128 rkey.nk_keyidx |= 1 << 30;
3131 /* need to set bit 29 based on keyrsc */
3132 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3135 rkey.nk_keyidx |= 1 << 29;
3137 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3138 bcopy(key->wk_key, rkey.nk_keydata, 16);
3139 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3140 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3142 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3144 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3146 case IEEE80211_CIPHER_WEP:
3150 * I don't know how to set up keys for the AES
3151 * cipher yet. Is it the same as TKIP?
3153 case IEEE80211_CIPHER_AES_CCM:
3159 /* We need to return 1 for success, 0 for failure. */
3168 ndis_resettask(d, arg)
3172 struct ndis_softc *sc;
3180 * Stop the adapter and free any mbufs allocated to the
3185 struct ndis_softc *sc;
3191 callout_drain(&sc->ndis_stat_callout);
3194 sc->ndis_tx_timer = 0;
3196 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3199 if (sc->ndis_iftype != PNPBus ||
3200 (sc->ndis_iftype == PNPBus &&
3201 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3206 for (i = 0; i < NDIS_EVENTS; i++) {
3207 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3208 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3209 sc->ndis_evt[i].ne_buf = NULL;
3211 sc->ndis_evt[i].ne_sts = 0;
3212 sc->ndis_evt[i].ne_len = 0;
3214 sc->ndis_evtcidx = 0;
3215 sc->ndis_evtpidx = 0;
3222 * Stop all chip I/O so that the kernel's probe routines don't
3223 * get confused by errant DMAs when rebooting.
3229 struct ndis_softc *sc;
3231 sc = device_get_softc(dev);
3238 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3240 struct ndis_vap *nvp = NDIS_VAP(vap);
3241 struct ieee80211com *ic = vap->iv_ic;
3242 struct ifnet *ifp = ic->ic_ifp;
3243 struct ndis_softc *sc = ifp->if_softc;
3244 enum ieee80211_state ostate;
3246 DPRINTF(("%s: %s -> %s\n", __func__,
3247 ieee80211_state_name[vap->iv_state],
3248 ieee80211_state_name[nstate]));
3250 ostate = vap->iv_state;
3251 vap->iv_state = nstate;
3254 /* pass on to net80211 */
3255 case IEEE80211_S_INIT:
3256 case IEEE80211_S_SCAN:
3257 return nvp->newstate(vap, nstate, arg);
3258 case IEEE80211_S_ASSOC:
3259 if (ostate != IEEE80211_S_AUTH) {
3260 IEEE80211_UNLOCK(ic);
3261 ndis_auth_and_assoc(sc, vap);
3265 case IEEE80211_S_AUTH:
3266 IEEE80211_UNLOCK(ic);
3267 ndis_auth_and_assoc(sc, vap);
3268 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3269 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3279 ndis_scan(void *arg)
3281 struct ieee80211vap *vap = arg;
3283 ieee80211_scan_done(vap);
3287 ndis_scan_results(struct ndis_softc *sc)
3289 struct ieee80211com *ic;
3290 struct ieee80211vap *vap;
3291 ndis_80211_bssid_list_ex *bl;
3292 ndis_wlan_bssid_ex *wb;
3293 struct ieee80211_scanparams sp;
3294 struct ieee80211_frame wh;
3295 struct ieee80211_channel *saved_chan;
3297 int rssi, noise, freq, chanflag;
3298 uint8_t ssid[2+IEEE80211_NWID_LEN];
3299 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3300 uint8_t *frm, *efrm;
3302 ic = sc->ifp->if_l2com;
3303 vap = TAILQ_FIRST(&ic->ic_vaps);
3304 saved_chan = ic->ic_curchan;
3307 if (ndis_get_bssid_list(sc, &bl))
3310 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3311 wb = &bl->nblx_bssid[0];
3312 for (i = 0; i < bl->nblx_items; i++) {
3313 memset(&sp, 0, sizeof(sp));
3315 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3316 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3317 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3318 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3319 if (wb->nwbx_privacy)
3320 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3321 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3322 switch (wb->nwbx_netinfra) {
3323 case NDIS_80211_NET_INFRA_IBSS:
3324 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3326 case NDIS_80211_NET_INFRA_BSS:
3327 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3330 sp.rates = &rates[0];
3331 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3332 /* XXX - check units */
3333 if (wb->nwbx_supportedrates[j] == 0)
3336 wb->nwbx_supportedrates[j] & 0x7f;
3339 sp.ssid = (uint8_t *)&ssid[0];
3340 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3341 wb->nwbx_ssid.ns_ssidlen);
3342 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3344 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3345 freq = wb->nwbx_config.nc_dsconfig / 1000;
3346 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3347 /* Hack ic->ic_curchan to be in sync with the scan result */
3348 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3349 if (ic->ic_curchan == NULL)
3350 ic->ic_curchan = &ic->ic_channels[0];
3352 /* Process extended info from AP */
3353 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3354 frm = (uint8_t *)&wb->nwbx_ies;
3355 efrm = frm + wb->nwbx_ielen;
3356 if (efrm - frm < 12)
3358 sp.tstamp = frm; frm += 8;
3359 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3360 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3362 sp.ies_len = efrm - frm;
3365 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3366 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3368 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3369 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3372 /* Restore the channel after messing with it */
3373 ic->ic_curchan = saved_chan;
3377 ndis_scan_start(struct ieee80211com *ic)
3379 struct ifnet *ifp = ic->ic_ifp;
3380 struct ndis_softc *sc = ifp->if_softc;
3381 struct ieee80211vap *vap;
3382 struct ieee80211_scan_state *ss;
3383 ndis_80211_ssid ssid;
3387 vap = TAILQ_FIRST(&ic->ic_vaps);
3389 if (!NDIS_INITIALIZED(sc)) {
3390 DPRINTF(("%s: scan aborted\n", __func__));
3391 ieee80211_cancel_scan(vap);
3396 bzero((char *)&ssid, len);
3397 if (ss->ss_nssid == 0)
3398 ssid.ns_ssidlen = 1;
3400 /* Perform a directed scan */
3401 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3402 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3405 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3407 DPRINTF(("%s: set ESSID failed\n", __func__));
3410 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
3413 DPRINTF(("%s: scan command failed\n", __func__));
3414 ieee80211_cancel_scan(vap);
3417 /* Set a timer to collect the results */
3418 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3422 ndis_set_channel(struct ieee80211com *ic)
3428 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3434 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3436 /* NB: don't try to abort scan; wait for firmware to finish */
3440 ndis_scan_end(struct ieee80211com *ic)
3442 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3444 ndis_scan_results(sc);