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);
1016 ieee80211_vap_detach(vap);
1017 free(nvp, M_80211_VAP);
1021 * Shutdown hardware and free up resources. This can be called any
1022 * time after the mutex has been initialized. It is called in both
1023 * the error case in attach and the normal detach case so it needs
1024 * to be careful about only freeing resources that have actually been
1031 struct ndis_softc *sc;
1035 sc = device_get_softc(dev);
1039 ifp->if_flags &= ~IFF_UP;
1041 if (device_is_attached(dev)) {
1046 ieee80211_ifdetach(ifp->if_l2com);
1048 ether_ifdetach(ifp);
1053 if (sc->ndis_tickitem != NULL)
1054 IoFreeWorkItem(sc->ndis_tickitem);
1055 if (sc->ndis_startitem != NULL)
1056 IoFreeWorkItem(sc->ndis_startitem);
1057 if (sc->ndis_resetitem != NULL)
1058 IoFreeWorkItem(sc->ndis_resetitem);
1059 if (sc->ndis_inputitem != NULL)
1060 IoFreeWorkItem(sc->ndis_inputitem);
1061 if (sc->ndisusb_xferdoneitem != NULL)
1062 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1063 if (sc->ndisusb_taskitem != NULL)
1064 IoFreeWorkItem(sc->ndisusb_taskitem);
1066 bus_generic_detach(dev);
1067 ndis_unload_driver(sc);
1070 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1071 if (sc->ndis_res_io)
1072 bus_release_resource(dev, SYS_RES_IOPORT,
1073 sc->ndis_io_rid, sc->ndis_res_io);
1074 if (sc->ndis_res_mem)
1075 bus_release_resource(dev, SYS_RES_MEMORY,
1076 sc->ndis_mem_rid, sc->ndis_res_mem);
1077 if (sc->ndis_res_altmem)
1078 bus_release_resource(dev, SYS_RES_MEMORY,
1079 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1084 if (sc->ndis_iftype == PCMCIABus)
1088 ndis_destroy_dma(sc);
1090 if (sc->ndis_txarray)
1091 free(sc->ndis_txarray, M_DEVBUF);
1093 if (!sc->ndis_80211)
1094 ifmedia_removeall(&sc->ifmedia);
1096 if (sc->ndis_txpool != NULL)
1097 NdisFreePacketPool(sc->ndis_txpool);
1099 /* Destroy the PDO for this device. */
1101 if (sc->ndis_iftype == PCIBus)
1102 drv = windrv_lookup(0, "PCI Bus");
1103 else if (sc->ndis_iftype == PCMCIABus)
1104 drv = windrv_lookup(0, "PCCARD Bus");
1106 drv = windrv_lookup(0, "USB Bus");
1108 panic("couldn't find driver object");
1109 windrv_destroy_pdo(drv, dev);
1111 if (sc->ndis_iftype == PCIBus)
1112 bus_dma_tag_destroy(sc->ndis_parent_tag);
1121 struct ndis_softc *sc;
1124 sc = device_get_softc(dev);
1128 if (NDIS_INITIALIZED(sc))
1139 struct ndis_softc *sc;
1142 sc = device_get_softc(dev);
1145 if (NDIS_INITIALIZED(sc))
1152 * The following bunch of routines are here to support drivers that
1153 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1154 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1155 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1160 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1161 ndis_handle adapter;
1167 uint32_t lookaheadlen;
1170 ndis_miniport_block *block;
1180 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1187 /* Save the data provided to us so far. */
1189 m->m_len = lookaheadlen + hdrlen;
1190 m->m_pkthdr.len = pktlen + hdrlen;
1192 m_copyback(m, 0, hdrlen, hdr);
1193 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1195 /* Now create a fake NDIS_PACKET to hold the data */
1197 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1199 if (status != NDIS_STATUS_SUCCESS) {
1206 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1214 p->np_private.npp_head = p->np_private.npp_tail = b;
1215 p->np_private.npp_totlen = m->m_pkthdr.len;
1217 /* Save the packet RX context somewhere. */
1218 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1219 priv->nep_ctx = ctx;
1221 if (!NDIS_SERIALIZED(block))
1222 KeAcquireSpinLock(&block->nmb_lock, &irql);
1224 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1226 if (!NDIS_SERIALIZED(block))
1227 KeReleaseSpinLock(&block->nmb_lock, irql);
1233 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1234 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1239 ndis_rxeof_done(adapter)
1240 ndis_handle adapter;
1242 struct ndis_softc *sc;
1243 ndis_miniport_block *block;
1247 /* Schedule transfer/RX of queued packets. */
1249 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1251 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1257 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1260 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1262 ndis_handle adapter;
1266 ndis_miniport_block *block;
1267 struct ndis_softc *sc;
1276 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1279 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1281 l = block->nmb_packetlist.nle_flink;
1282 while(!IsListEmpty(&block->nmb_packetlist)) {
1283 l = RemoveHeadList((&block->nmb_packetlist));
1284 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1285 InitializeListHead((&p->np_list));
1287 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1292 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1294 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1295 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1296 m->m_len, m->m_pkthdr.len - m->m_len);
1298 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1301 * If status is NDIS_STATUS_PENDING, do nothing and
1302 * wait for a callback to the ndis_rxeof_xfr_done()
1306 m->m_len = m->m_pkthdr.len;
1307 m->m_pkthdr.rcvif = ifp;
1309 if (status == NDIS_STATUS_SUCCESS) {
1310 IoFreeMdl(p->np_private.npp_head);
1312 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1313 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1314 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1315 IoQueueWorkItem(sc->ndis_inputitem,
1316 (io_workitem_func)ndis_inputtask_wrap,
1317 WORKQUEUE_CRITICAL, ifp);
1320 if (status == NDIS_STATUS_FAILURE)
1323 /* Advance to next packet */
1324 l = block->nmb_packetlist.nle_flink;
1327 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1333 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1336 ndis_rxeof_xfr_done(adapter, packet, status, len)
1337 ndis_handle adapter;
1338 ndis_packet *packet;
1342 ndis_miniport_block *block;
1343 struct ndis_softc *sc;
1348 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1352 IoFreeMdl(packet->np_private.npp_head);
1353 NdisFreePacket(packet);
1355 if (status != NDIS_STATUS_SUCCESS) {
1360 m->m_len = m->m_pkthdr.len;
1361 m->m_pkthdr.rcvif = ifp;
1362 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1363 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1364 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1365 IoQueueWorkItem(sc->ndis_inputitem,
1366 (io_workitem_func)ndis_inputtask_wrap,
1367 WORKQUEUE_CRITICAL, ifp);
1372 * A frame has been uploaded: pass the resulting mbuf chain up to
1373 * the higher level protocols.
1375 * When handling received NDIS packets, the 'status' field in the
1376 * out-of-band portion of the ndis_packet has special meaning. In the
1377 * most common case, the underlying NDIS driver will set this field
1378 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1379 * take posession of it. We then change the status field to
1380 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1381 * and that we will return it at some point in the future via the
1382 * return packet handler.
1384 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1385 * this means the driver is running out of packet/buffer resources and
1386 * wants to maintain ownership of the packet. In this case, we have to
1387 * copy the packet data into local storage and let the driver keep the
1391 ndis_rxeof(adapter, packets, pktcnt)
1392 ndis_handle adapter;
1393 ndis_packet **packets;
1396 struct ndis_softc *sc;
1397 ndis_miniport_block *block;
1400 ndis_tcpip_csum *csum;
1402 struct mbuf *m0, *m;
1405 block = (ndis_miniport_block *)adapter;
1406 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1410 * There's a slim chance the driver may indicate some packets
1411 * before we're completely ready to handle them. If we detect this,
1412 * we need to return them to the miniport and ignore them.
1415 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1416 for (i = 0; i < pktcnt; i++) {
1418 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1420 ndis_return_packet(p, block);
1426 for (i = 0; i < pktcnt; i++) {
1428 /* Stash the softc here so ptom can use it. */
1430 if (ndis_ptom(&m0, p)) {
1431 device_printf (sc->ndis_dev, "ptom failed\n");
1432 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1433 ndis_return_packet(p, block);
1436 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1437 m = m_dup(m0, M_DONTWAIT);
1439 * NOTE: we want to destroy the mbuf here, but
1440 * we don't actually want to return it to the
1441 * driver via the return packet handler. By
1442 * bumping np_refcnt, we can prevent the
1443 * ndis_return_packet() routine from actually
1453 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1455 m = m_dup(m0, M_DONTWAIT);
1456 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1459 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1466 m0->m_pkthdr.rcvif = ifp;
1468 /* Deal with checksum offload. */
1470 if (ifp->if_capenable & IFCAP_RXCSUM &&
1471 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1473 p->np_ext.npe_info[ndis_tcpipcsum_info];
1474 csum = (ndis_tcpip_csum *)&s;
1475 if (csum->u.ntc_rxflags &
1476 NDIS_RXCSUM_IP_PASSED)
1477 m0->m_pkthdr.csum_flags |=
1478 CSUM_IP_CHECKED|CSUM_IP_VALID;
1479 if (csum->u.ntc_rxflags &
1480 (NDIS_RXCSUM_TCP_PASSED |
1481 NDIS_RXCSUM_UDP_PASSED)) {
1482 m0->m_pkthdr.csum_flags |=
1483 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1484 m0->m_pkthdr.csum_data = 0xFFFF;
1488 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1489 _IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1490 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1491 IoQueueWorkItem(sc->ndis_inputitem,
1492 (io_workitem_func)ndis_inputtask_wrap,
1493 WORKQUEUE_CRITICAL, ifp);
1501 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1502 * packets into the stack in order to avoid calling (*ifp->if_input)()
1503 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1504 * 'dispatch level' per-cpu sleep lock).
1508 ndis_inputtask(dobj, arg)
1509 device_object *dobj;
1512 ndis_miniport_block *block;
1514 struct ndis_softc *sc;
1516 struct ieee80211com *ic;
1517 struct ieee80211vap *vap;
1523 vap = TAILQ_FIRST(&ic->ic_vaps);
1524 block = dobj->do_devext;
1526 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1528 _IF_DEQUEUE(&sc->ndis_rxqueue, m);
1531 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1533 vap->iv_deliver_data(vap, vap->iv_bss, m);
1535 (*ifp->if_input)(ifp, m);
1536 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1538 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1544 * A frame was downloaded to the chip. It's safe for us to clean up
1548 ndis_txeof(adapter, packet, status)
1549 ndis_handle adapter;
1550 ndis_packet *packet;
1554 struct ndis_softc *sc;
1555 ndis_miniport_block *block;
1560 block = (ndis_miniport_block *)adapter;
1561 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1565 idx = packet->np_txidx;
1567 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1569 ndis_free_packet(packet);
1573 sc->ndis_txarray[idx] = NULL;
1574 sc->ndis_txpending++;
1576 if (status == NDIS_STATUS_SUCCESS)
1581 sc->ndis_tx_timer = 0;
1582 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1586 IoQueueWorkItem(sc->ndis_startitem,
1587 (io_workitem_func)ndis_starttask_wrap,
1588 WORKQUEUE_CRITICAL, ifp);
1594 ndis_linksts(adapter, status, sbuf, slen)
1595 ndis_handle adapter;
1600 ndis_miniport_block *block;
1601 struct ndis_softc *sc;
1604 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1605 sc->ndis_sts = status;
1607 /* Event list is all full up, drop this one. */
1610 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1615 /* Cache the event. */
1618 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1620 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1625 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1627 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1628 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1629 NDIS_EVTINC(sc->ndis_evtpidx);
1636 ndis_linksts_done(adapter)
1637 ndis_handle adapter;
1639 ndis_miniport_block *block;
1640 struct ndis_softc *sc;
1644 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1647 if (!NDIS_INITIALIZED(sc))
1650 switch (sc->ndis_sts) {
1651 case NDIS_STATUS_MEDIA_CONNECT:
1652 IoQueueWorkItem(sc->ndis_tickitem,
1653 (io_workitem_func)ndis_ticktask_wrap,
1654 WORKQUEUE_CRITICAL, sc);
1655 IoQueueWorkItem(sc->ndis_startitem,
1656 (io_workitem_func)ndis_starttask_wrap,
1657 WORKQUEUE_CRITICAL, ifp);
1659 case NDIS_STATUS_MEDIA_DISCONNECT:
1661 IoQueueWorkItem(sc->ndis_tickitem,
1662 (io_workitem_func)ndis_ticktask_wrap,
1663 WORKQUEUE_CRITICAL, sc);
1669 /* Notify possible listners of interface change. */
1680 struct ndis_softc *sc;
1684 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1685 IoQueueWorkItem(sc->ndis_tickitem,
1686 (io_workitem_func)ndis_ticktask_wrap,
1687 WORKQUEUE_CRITICAL, sc);
1688 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1691 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1692 sc->ifp->if_oerrors++;
1693 device_printf(sc->ndis_dev, "watchdog timeout\n");
1695 IoQueueWorkItem(sc->ndis_resetitem,
1696 (io_workitem_func)ndis_resettask_wrap,
1697 WORKQUEUE_CRITICAL, sc);
1698 IoQueueWorkItem(sc->ndis_startitem,
1699 (io_workitem_func)ndis_starttask_wrap,
1700 WORKQUEUE_CRITICAL, sc->ifp);
1703 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1707 ndis_ticktask(d, xsc)
1711 struct ndis_softc *sc;
1712 struct ieee80211com *ic;
1713 struct ieee80211vap *vap;
1714 ndis_checkforhang_handler hangfunc;
1718 ic = sc->ifp->if_l2com;
1719 vap = TAILQ_FIRST(&ic->ic_vaps);
1722 if (!NDIS_INITIALIZED(sc)) {
1728 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1730 if (hangfunc != NULL) {
1731 rval = MSCALL1(hangfunc,
1732 sc->ndis_block->nmb_miniportadapterctx);
1740 if (sc->ndis_link == 0 &&
1741 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1744 if (sc->ndis_80211) {
1745 ndis_getstate_80211(sc);
1746 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1749 if_link_state_change(sc->ifp, LINK_STATE_UP);
1752 if (sc->ndis_link == 1 &&
1753 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1757 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1759 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1768 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1770 bus_dma_segment_t *segs;
1776 struct ndis_sc_list *sclist;
1779 if (error || arg == NULL)
1784 sclist->nsl_frags = nseg;
1786 for (i = 0; i < nseg; i++) {
1787 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1788 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1795 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1796 const struct ieee80211_bpf_params *params)
1798 /* no support; just discard */
1800 ieee80211_free_node(ni);
1805 ndis_update_mcast(struct ifnet *ifp)
1807 struct ndis_softc *sc = ifp->if_softc;
1813 ndis_update_promisc(struct ifnet *ifp)
1819 ndis_starttask(d, arg)
1827 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1833 * Main transmit routine. To make NDIS drivers happy, we need to
1834 * transform mbuf chains into NDIS packets and feed them to the
1835 * send packet routines. Most drivers allow you to send several
1836 * packets at once (up to the maxpkts limit). Unfortunately, rather
1837 * that accepting them in the form of a linked list, they expect
1838 * a contiguous array of pointers to packets.
1840 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1841 * we need to perform busdma work here. Those that use map registers
1842 * will do the mapping themselves on a buffer by buffer basis.
1849 struct ndis_softc *sc;
1850 struct mbuf *m = NULL;
1851 ndis_packet **p0 = NULL, *p = NULL;
1852 ndis_tcpip_csum *csum;
1853 int pcnt = 0, status;
1859 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1864 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1866 while(sc->ndis_txpending) {
1867 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1871 NdisAllocatePacket(&status,
1872 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1874 if (status != NDIS_STATUS_SUCCESS)
1877 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1878 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1884 * Save pointer to original mbuf
1885 * so we can free it later.
1888 p = sc->ndis_txarray[sc->ndis_txidx];
1889 p->np_txidx = sc->ndis_txidx;
1891 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1894 * Do scatter/gather processing, if driver requested it.
1897 bus_dmamap_load_mbuf(sc->ndis_ttag,
1898 sc->ndis_tmaps[sc->ndis_txidx], m,
1899 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1900 bus_dmamap_sync(sc->ndis_ttag,
1901 sc->ndis_tmaps[sc->ndis_txidx],
1902 BUS_DMASYNC_PREREAD);
1903 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1906 /* Handle checksum offload. */
1908 if (ifp->if_capenable & IFCAP_TXCSUM &&
1909 m->m_pkthdr.csum_flags) {
1910 csum = (ndis_tcpip_csum *)
1911 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1912 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1913 if (m->m_pkthdr.csum_flags & CSUM_IP)
1914 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1915 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1916 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1917 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1918 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1919 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1923 sc->ndis_txpending--;
1928 * If there's a BPF listener, bounce a copy of this frame
1932 if (!sc->ndis_80211) /* XXX handle 80211 */
1936 * The array that p0 points to must appear contiguous,
1937 * so we must not wrap past the end of sc->ndis_txarray[].
1938 * If it looks like we're about to wrap, break out here
1939 * so the this batch of packets can be transmitted, then
1940 * wait for txeof to ask us to send the rest.
1943 if (sc->ndis_txidx == 0)
1952 if (sc->ndis_txpending == 0)
1953 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1956 * Set a timeout in case the chip goes out to lunch.
1958 sc->ndis_tx_timer = 5;
1963 * According to NDIS documentation, if a driver exports
1964 * a MiniportSendPackets() routine, we prefer that over
1965 * a MiniportSend() routine (which sends just a single
1969 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1970 ndis_send_packets(sc, p0, pcnt);
1972 ndis_send_packet(sc, p);
1981 struct ndis_softc *sc = xsc;
1982 struct ifnet *ifp = sc->ifp;
1983 struct ieee80211com *ic = ifp->if_l2com;
1987 * Avoid reintializing the link unnecessarily.
1988 * This should be dealt with in a better way by
1989 * fixing the upper layer modules so they don't
1990 * call ifp->if_init() quite as often.
1996 * Cancel pending I/O and free all RX/TX buffers.
2000 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2001 error = ndis_init_nic(sc);
2003 device_printf(sc->ndis_dev,
2004 "failed to initialize the device: %d\n", error);
2009 /* Init our MAC address */
2011 /* Program the packet filter */
2013 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
2015 if (ifp->if_flags & IFF_BROADCAST)
2016 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
2018 if (ifp->if_flags & IFF_PROMISC)
2019 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2021 len = sizeof(sc->ndis_filter);
2023 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2024 &sc->ndis_filter, &len);
2027 device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
2035 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2038 * Program the multicast filter, if necessary.
2042 /* Setup task offload. */
2043 ndis_set_offload(sc);
2046 ndis_setstate_80211(sc);
2051 sc->ndis_txpending = sc->ndis_maxpkts;
2054 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2056 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2057 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2058 sc->ndis_tx_timer = 0;
2061 * Some drivers don't set this value. The NDIS spec says
2062 * the default checkforhang timeout is "approximately 2
2063 * seconds." We use 3 seconds, because it seems for some
2064 * drivers, exactly 2 seconds is too fast.
2066 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2067 sc->ndis_block->nmb_checkforhangsecs = 3;
2069 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2070 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2073 /* XXX force handling */
2075 ieee80211_start_all(ic); /* start all vap's */
2079 * Set media options.
2082 ndis_ifmedia_upd(ifp)
2085 struct ndis_softc *sc;
2089 if (NDIS_INITIALIZED(sc))
2096 * Report current media status.
2099 ndis_ifmedia_sts(ifp, ifmr)
2101 struct ifmediareq *ifmr;
2103 struct ndis_softc *sc;
2104 uint32_t media_info;
2105 ndis_media_state linkstate;
2108 ifmr->ifm_status = IFM_AVALID;
2109 ifmr->ifm_active = IFM_ETHER;
2112 if (!NDIS_INITIALIZED(sc))
2115 len = sizeof(linkstate);
2116 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2117 (void *)&linkstate, &len);
2119 len = sizeof(media_info);
2120 error = ndis_get_info(sc, OID_GEN_LINK_SPEED,
2121 (void *)&media_info, &len);
2123 if (linkstate == nmc_connected)
2124 ifmr->ifm_status |= IFM_ACTIVE;
2126 switch(media_info) {
2128 ifmr->ifm_active |= IFM_10_T;
2131 ifmr->ifm_active |= IFM_100_TX;
2134 ifmr->ifm_active |= IFM_1000_T;
2137 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2145 ndis_set_cipher(sc, cipher)
2146 struct ndis_softc *sc;
2149 struct ieee80211com *ic;
2153 ic = sc->ifp->if_l2com;
2157 if (cipher == WPA_CSE_WEP40 || WPA_CSE_WEP104) {
2158 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2160 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2163 if (cipher == WPA_CSE_TKIP) {
2164 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2166 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2169 if (cipher == WPA_CSE_CCMP) {
2170 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2172 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2175 DPRINTF(("Setting cipher to %d\n", arg));
2177 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2182 /* Check that the cipher was set correctly. */
2185 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2187 if (rval != 0 || arg != save)
2194 * WPA is hairy to set up. Do the work in a separate routine
2195 * so we don't clutter the setstate function too much.
2196 * Important yet undocumented fact: first we have to set the
2197 * authentication mode, _then_ we enable the ciphers. If one
2198 * of the WPA authentication modes isn't enabled, the driver
2199 * might not permit the TKIP or AES ciphers to be selected.
2203 ndis_set_wpa(sc, ie, ielen)
2204 struct ndis_softc *sc;
2208 struct ieee80211_ie_wpa *w;
2215 * Apparently, the only way for us to know what ciphers
2216 * and key management/authentication mode to use is for
2217 * us to inspect the optional information element (IE)
2218 * stored in the 802.11 state machine. This IE should be
2219 * supplied by the WPA supplicant.
2222 w = (struct ieee80211_ie_wpa *)ie;
2224 /* Check for the right kind of IE. */
2225 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2226 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2230 /* Skip over the ucast cipher OIDs. */
2231 pos = (char *)&w->wpa_uciphers[0];
2232 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2234 /* Skip over the authmode count. */
2235 pos += sizeof(u_int16_t);
2238 * Check for the authentication modes. I'm
2239 * pretty sure there's only supposed to be one.
2242 n = (struct ndis_ie *)pos;
2243 if (n->ni_val == WPA_ASE_NONE)
2244 arg = NDIS_80211_AUTHMODE_WPANONE;
2246 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2247 arg = NDIS_80211_AUTHMODE_WPA;
2249 if (n->ni_val == WPA_ASE_8021X_PSK)
2250 arg = NDIS_80211_AUTHMODE_WPAPSK;
2252 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2254 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2257 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2259 /* Now configure the desired ciphers. */
2261 /* First, set up the multicast group cipher. */
2262 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2264 if (ndis_set_cipher(sc, n->ni_val))
2267 /* Now start looking around for the unicast ciphers. */
2268 pos = (char *)&w->wpa_uciphers[0];
2269 n = (struct ndis_ie *)pos;
2271 for (i = 0; i < w->wpa_uciphercnt; i++) {
2272 if (ndis_set_cipher(sc, n->ni_val))
2281 ndis_setstate_80211(sc)
2282 struct ndis_softc *sc;
2284 struct ieee80211com *ic;
2285 struct ieee80211vap *vap;
2286 ndis_80211_macaddr bssid;
2287 ndis_80211_config config;
2294 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);
2732 if (!NDIS_INITIALIZED(sc))
2735 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2738 /* We're associated, retrieve info on the current bssid. */
2739 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2740 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2741 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2743 /* Get SSID from current association info. */
2744 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2745 bs->nwbx_ssid.ns_ssidlen);
2746 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2749 rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
2751 device_printf (sc->ndis_dev, "get link speed failed: %d\n",
2753 ni->ni_txrate = arg / 5000;
2755 if (ic->ic_caps & IEEE80211_C_PMGT) {
2757 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2760 device_printf(sc->ndis_dev,
2761 "get power mode failed: %d\n", rval);
2762 if (arg == NDIS_80211_POWERMODE_CAM)
2763 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2765 vap->iv_flags |= IEEE80211_F_PMGTON;
2769 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2771 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2772 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2773 if (dBm2mW[i] >= arg)
2775 ic->ic_txpowlimit = i;
2779 * Use the current association information to reflect
2780 * what channel we're on.
2782 ic->ic_curchan = ieee80211_find_channel(ic,
2783 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2784 if (ic->ic_curchan == NULL)
2785 ic->ic_curchan = &ic->ic_channels[0];
2786 ni->ni_chan = ic->ic_curchan;
2787 ic->ic_bsschan = ic->ic_curchan;
2792 * Determine current authentication mode. Note: authmode
2793 * reporting isn't supported prior to FreeBSD 6.x.
2797 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2799 device_printf (sc->ndis_dev,
2800 "get authmode status failed: %d\n", rval);
2802 vap->iv_flags &= ~IEEE80211_F_WPA;
2804 case NDIS_80211_AUTHMODE_OPEN:
2805 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2807 case NDIS_80211_AUTHMODE_SHARED:
2808 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2810 case NDIS_80211_AUTHMODE_AUTO:
2811 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2813 case NDIS_80211_AUTHMODE_WPA:
2814 case NDIS_80211_AUTHMODE_WPAPSK:
2815 case NDIS_80211_AUTHMODE_WPANONE:
2816 ni->ni_authmode = IEEE80211_AUTH_WPA;
2817 vap->iv_flags |= IEEE80211_F_WPA1;
2819 case NDIS_80211_AUTHMODE_WPA2:
2820 case NDIS_80211_AUTHMODE_WPA2PSK:
2821 ni->ni_authmode = IEEE80211_AUTH_WPA;
2822 vap->iv_flags |= IEEE80211_F_WPA2;
2825 ni->ni_authmode = IEEE80211_AUTH_NONE;
2831 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2834 device_printf (sc->ndis_dev,
2835 "get wep status failed: %d\n", rval);
2837 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2838 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2840 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2845 ndis_ioctl(ifp, command, data)
2850 struct ndis_softc *sc = ifp->if_softc;
2851 struct ifreq *ifr = (struct ifreq *) data;
2858 if (ifp->if_flags & IFF_UP) {
2859 if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2860 ifp->if_flags & IFF_PROMISC &&
2861 !(sc->ndis_if_flags & IFF_PROMISC)) {
2863 NDIS_PACKET_TYPE_PROMISCUOUS;
2864 i = sizeof(sc->ndis_filter);
2865 error = ndis_set_info(sc,
2866 OID_GEN_CURRENT_PACKET_FILTER,
2867 &sc->ndis_filter, &i);
2868 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2869 !(ifp->if_flags & IFF_PROMISC) &&
2870 sc->ndis_if_flags & IFF_PROMISC) {
2872 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2873 i = sizeof(sc->ndis_filter);
2874 error = ndis_set_info(sc,
2875 OID_GEN_CURRENT_PACKET_FILTER,
2876 &sc->ndis_filter, &i);
2880 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2883 sc->ndis_if_flags = ifp->if_flags;
2893 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2896 ifp->if_capenable = ifr->ifr_reqcap;
2897 if (ifp->if_capenable & IFCAP_TXCSUM)
2898 ifp->if_hwassist = sc->ndis_hwassist;
2900 ifp->if_hwassist = 0;
2901 ndis_set_offload(sc);
2904 error = ether_ioctl(ifp, command, data);
2908 /*NDIS_UNLOCK(sc);*/
2914 ndis_ioctl_80211(ifp, command, data)
2919 struct ndis_softc *sc = ifp->if_softc;
2920 struct ieee80211com *ic = ifp->if_l2com;
2921 struct ifreq *ifr = (struct ifreq *) data;
2922 struct ndis_oid_data oid;
2923 struct ndis_evt evt;
2930 if (ifp->if_flags & IFF_UP) {
2931 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
2934 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2937 sc->ndis_if_flags = ifp->if_flags;
2939 /*NDIS_UNLOCK(sc);*/
2942 if ((error = priv_check(curthread, PRIV_DRIVER)))
2944 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2947 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2948 if (oidbuf == NULL) {
2952 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2954 free(oidbuf, M_TEMP);
2957 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2959 free(oidbuf, M_TEMP);
2962 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2964 free(oidbuf, M_TEMP);
2967 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2968 free(oidbuf, M_TEMP);
2971 if ((error = priv_check(curthread, PRIV_DRIVER)))
2973 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2976 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2977 if (oidbuf == NULL) {
2981 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2983 free(oidbuf, M_TEMP);
2986 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2988 free(oidbuf, M_TEMP);
2991 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2993 free(oidbuf, M_TEMP);
2996 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2997 free(oidbuf, M_TEMP);
2999 case SIOCGPRIVATE_0:
3000 if ((error = priv_check(curthread, PRIV_DRIVER)))
3003 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3008 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
3013 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3018 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3019 ifr->ifr_data, sizeof(uint32_t) * 2);
3024 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3025 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3026 ifr->ifr_data + (sizeof(uint32_t) * 2),
3027 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3032 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3033 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3035 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3036 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3037 NDIS_EVTINC(sc->ndis_evtcidx);
3041 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
3044 error = ether_ioctl(ifp, command, data);
3054 ndis_del_key(vap, key)
3055 struct ieee80211vap *vap;
3056 const struct ieee80211_key *key;
3058 struct ndis_softc *sc;
3059 ndis_80211_key rkey;
3062 sc = vap->iv_ic->ic_ifp->if_softc;
3064 bzero((char *)&rkey, sizeof(rkey));
3068 rkey.nk_keyidx = key->wk_keyix;
3070 bcopy(vap->iv_ifp->if_broadcastaddr,
3071 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3073 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3082 * In theory this could be called for any key, but we'll
3083 * only use it for WPA TKIP or AES keys. These need to be
3084 * set after initial authentication with the AP.
3088 ndis_add_key(vap, key, mac)
3089 struct ieee80211vap *vap;
3090 const struct ieee80211_key *key;
3091 const uint8_t mac[IEEE80211_ADDR_LEN];
3093 struct ndis_softc *sc;
3095 ndis_80211_key rkey;
3098 ifp = vap->iv_ic->ic_ifp;
3101 switch (key->wk_cipher->ic_cipher) {
3102 case IEEE80211_CIPHER_TKIP:
3104 len = sizeof(ndis_80211_key);
3105 bzero((char *)&rkey, sizeof(rkey));
3108 rkey.nk_keylen = key->wk_keylen;
3110 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3111 rkey.nk_keylen += 16;
3113 /* key index - gets weird in NDIS */
3115 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3116 rkey.nk_keyidx = key->wk_keyix;
3120 if (key->wk_flags & IEEE80211_KEY_XMIT)
3121 rkey.nk_keyidx |= 1 << 31;
3123 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3124 bcopy(ifp->if_broadcastaddr,
3125 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3127 bcopy(vap->iv_bss->ni_bssid,
3128 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3130 rkey.nk_keyidx |= 1 << 30;
3133 /* need to set bit 29 based on keyrsc */
3134 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3137 rkey.nk_keyidx |= 1 << 29;
3139 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3140 bcopy(key->wk_key, rkey.nk_keydata, 16);
3141 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3142 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3144 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3146 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3148 case IEEE80211_CIPHER_WEP:
3152 * I don't know how to set up keys for the AES
3153 * cipher yet. Is it the same as TKIP?
3155 case IEEE80211_CIPHER_AES_CCM:
3161 /* We need to return 1 for success, 0 for failure. */
3170 ndis_resettask(d, arg)
3174 struct ndis_softc *sc;
3182 * Stop the adapter and free any mbufs allocated to the
3187 struct ndis_softc *sc;
3193 callout_drain(&sc->ndis_stat_callout);
3196 sc->ndis_tx_timer = 0;
3198 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3201 if (sc->ndis_iftype != PNPBus ||
3202 (sc->ndis_iftype == PNPBus &&
3203 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3208 for (i = 0; i < NDIS_EVENTS; i++) {
3209 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3210 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3211 sc->ndis_evt[i].ne_buf = NULL;
3213 sc->ndis_evt[i].ne_sts = 0;
3214 sc->ndis_evt[i].ne_len = 0;
3216 sc->ndis_evtcidx = 0;
3217 sc->ndis_evtpidx = 0;
3224 * Stop all chip I/O so that the kernel's probe routines don't
3225 * get confused by errant DMAs when rebooting.
3231 struct ndis_softc *sc;
3233 sc = device_get_softc(dev);
3240 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3242 struct ndis_vap *nvp = NDIS_VAP(vap);
3243 struct ieee80211com *ic = vap->iv_ic;
3244 struct ifnet *ifp = ic->ic_ifp;
3245 struct ndis_softc *sc = ifp->if_softc;
3246 enum ieee80211_state ostate;
3248 DPRINTF(("%s: %s -> %s\n", __func__,
3249 ieee80211_state_name[vap->iv_state],
3250 ieee80211_state_name[nstate]));
3252 ostate = vap->iv_state;
3253 vap->iv_state = nstate;
3256 /* pass on to net80211 */
3257 case IEEE80211_S_INIT:
3258 case IEEE80211_S_SCAN:
3259 return nvp->newstate(vap, nstate, arg);
3260 case IEEE80211_S_ASSOC:
3261 if (ostate != IEEE80211_S_AUTH) {
3262 IEEE80211_UNLOCK(ic);
3263 ndis_auth_and_assoc(sc, vap);
3267 case IEEE80211_S_AUTH:
3268 IEEE80211_UNLOCK(ic);
3269 ndis_auth_and_assoc(sc, vap);
3270 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3271 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3281 ndis_scan(void *arg)
3283 struct ndis_softc *sc = arg;
3284 struct ieee80211com *ic;
3285 struct ieee80211vap *vap;
3287 ic = sc->ifp->if_l2com;
3288 vap = TAILQ_FIRST(&ic->ic_vaps);
3290 ndis_scan_results(sc);
3291 ieee80211_scan_done(vap);
3295 ndis_scan_results(struct ndis_softc *sc)
3297 struct ieee80211com *ic;
3298 struct ieee80211vap *vap;
3299 ndis_80211_bssid_list_ex *bl;
3300 ndis_wlan_bssid_ex *wb;
3301 struct ieee80211_scanparams sp;
3302 struct ieee80211_frame wh;
3303 struct ieee80211_channel *saved_chan;
3305 int rssi, noise, freq, chanflag;
3306 uint8_t ssid[2+IEEE80211_NWID_LEN];
3307 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3308 uint8_t *frm, *efrm;
3310 ic = sc->ifp->if_l2com;
3311 vap = TAILQ_FIRST(&ic->ic_vaps);
3312 saved_chan = ic->ic_curchan;
3315 if (ndis_get_bssid_list(sc, &bl))
3318 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3319 wb = &bl->nblx_bssid[0];
3320 for (i = 0; i < bl->nblx_items; i++) {
3321 memset(&sp, 0, sizeof(sp));
3323 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3324 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3325 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3326 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3327 if (wb->nwbx_privacy)
3328 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3329 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3330 switch (wb->nwbx_netinfra) {
3331 case NDIS_80211_NET_INFRA_IBSS:
3332 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3334 case NDIS_80211_NET_INFRA_BSS:
3335 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3338 sp.rates = &rates[0];
3339 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3340 /* XXX - check units */
3341 if (wb->nwbx_supportedrates[j] == 0)
3344 wb->nwbx_supportedrates[j] & 0x7f;
3347 sp.ssid = (uint8_t *)&ssid[0];
3348 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3349 wb->nwbx_ssid.ns_ssidlen);
3350 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3352 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3353 freq = wb->nwbx_config.nc_dsconfig / 1000;
3354 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3355 /* Hack ic->ic_curchan to be in sync with the scan result */
3356 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3357 if (ic->ic_curchan == NULL)
3358 ic->ic_curchan = &ic->ic_channels[0];
3360 /* Process extended info from AP */
3361 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3362 frm = (uint8_t *)&wb->nwbx_ies;
3363 efrm = frm + wb->nwbx_ielen;
3364 if (efrm - frm < 12)
3368 sp.bintval = le16toh(*(uint16_t *)frm);
3370 sp.capinfo = le16toh(*(uint16_t *)frm);
3373 /* Grab variable length ies */
3374 while (efrm - frm > 1) {
3375 if (efrm - frm < frm[1] + 2)
3378 case IEEE80211_ELEMID_RSN:
3386 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3387 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3389 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3390 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3393 /* Restore the channel after messing with it */
3394 ic->ic_curchan = saved_chan;
3398 ndis_scan_start(struct ieee80211com *ic)
3400 struct ifnet *ifp = ic->ic_ifp;
3401 struct ndis_softc *sc = ifp->if_softc;
3402 struct ieee80211vap *vap;
3403 struct ieee80211_scan_state *ss;
3404 ndis_80211_ssid ssid;
3408 vap = TAILQ_FIRST(&ic->ic_vaps);
3410 if (!NDIS_INITIALIZED(sc)) {
3411 DPRINTF(("%s: scan aborted\n", __func__));
3412 ieee80211_cancel_scan(vap);
3417 bzero((char *)&ssid, len);
3418 if (ss->ss_nssid == 0)
3419 ssid.ns_ssidlen = 1;
3421 /* Perform a directed scan */
3422 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3423 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3426 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3428 DPRINTF(("%s: set ESSID failed\n", __func__));
3431 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
3434 DPRINTF(("%s: scan command failed\n", __func__));
3435 ieee80211_cancel_scan(vap);
3438 /* Set a timer to collect the results */
3439 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, sc);
3443 ndis_set_channel(struct ieee80211com *ic)
3449 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3455 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3457 /* NB: don't try to abort scan; wait for firmware to finish */
3461 ndis_scan_end(struct ieee80211com *ic)