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>
55 #include <net/if_arp.h>
56 #include <net/ethernet.h>
57 #include <net/if_dl.h>
58 #include <net/if_media.h>
59 #include <net/if_types.h>
60 #include <net/route.h>
64 #include <machine/bus.h>
65 #include <machine/resource.h>
69 #include <net80211/ieee80211_var.h>
70 #include <net80211/ieee80211_ioctl.h>
71 #include <net80211/ieee80211_regdomain.h>
73 #include <dev/pci/pcireg.h>
74 #include <dev/pci/pcivar.h>
75 #include <dev/usb/usb.h>
76 #include <dev/usb/usbdi.h>
78 #include <compat/ndis/pe_var.h>
79 #include <compat/ndis/cfg_var.h>
80 #include <compat/ndis/resource_var.h>
81 #include <compat/ndis/ntoskrnl_var.h>
82 #include <compat/ndis/hal_var.h>
83 #include <compat/ndis/ndis_var.h>
84 #include <compat/ndis/usbd_var.h>
85 #include <dev/if_ndis/if_ndisvar.h>
89 #define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
91 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
92 "if_ndis debug level");
97 SYSCTL_DECL(_hw_ndisusb);
99 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
100 "Halt NDIS USB driver when it's attached");
102 /* 0 - 30 dBm to mW conversion table */
103 static const uint16_t dBm2mW[] = {
104 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
105 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
106 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
107 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
108 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
109 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
113 MODULE_DEPEND(ndis, ether, 1, 1, 1);
114 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
115 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
117 MODULE_VERSION(ndis, 1);
119 int ndis_attach (device_t);
120 int ndis_detach (device_t);
121 int ndis_suspend (device_t);
122 int ndis_resume (device_t);
123 void ndis_shutdown (device_t);
125 int ndisdrv_modevent (module_t, int, void *);
127 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
128 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
129 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
130 uint32_t, void *, uint32_t, uint32_t);
131 static void ndis_rxeof_done (ndis_handle);
132 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
133 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
135 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
136 static void ndis_linksts_done (ndis_handle);
138 /* We need to wrap these functions for amd64. */
139 static funcptr ndis_txeof_wrap;
140 static funcptr ndis_rxeof_wrap;
141 static funcptr ndis_rxeof_eth_wrap;
142 static funcptr ndis_rxeof_done_wrap;
143 static funcptr ndis_rxeof_xfr_wrap;
144 static funcptr ndis_rxeof_xfr_done_wrap;
145 static funcptr ndis_linksts_wrap;
146 static funcptr ndis_linksts_done_wrap;
147 static funcptr ndis_ticktask_wrap;
148 static funcptr ndis_starttask_wrap;
149 static funcptr ndis_resettask_wrap;
150 static funcptr ndis_inputtask_wrap;
152 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
153 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
154 const uint8_t [IEEE80211_ADDR_LEN],
155 const uint8_t [IEEE80211_ADDR_LEN]);
156 static void ndis_vap_delete (struct ieee80211vap *);
157 static void ndis_tick (void *);
158 static void ndis_ticktask (device_object *, void *);
159 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
160 const struct ieee80211_bpf_params *);
161 static void ndis_update_mcast (struct ifnet *ifp);
162 static void ndis_update_promisc (struct ifnet *ifp);
163 static void ndis_start (struct ifnet *);
164 static void ndis_starttask (device_object *, void *);
165 static void ndis_resettask (device_object *, void *);
166 static void ndis_inputtask (device_object *, void *);
167 static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
168 static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t);
169 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
171 static int ndis_nettype_chan (uint32_t);
172 static int ndis_nettype_mode (uint32_t);
173 static void ndis_scan (void *);
174 static void ndis_scan_results (struct ndis_softc *);
175 static void ndis_scan_start (struct ieee80211com *);
176 static void ndis_scan_end (struct ieee80211com *);
177 static void ndis_set_channel (struct ieee80211com *);
178 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
179 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
180 static void ndis_init (void *);
181 static void ndis_stop (struct ndis_softc *);
182 static int ndis_ifmedia_upd (struct ifnet *);
183 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
184 static int ndis_get_bssid_list (struct ndis_softc *,
185 ndis_80211_bssid_list_ex **);
186 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
187 static int ndis_probe_offload (struct ndis_softc *);
188 static int ndis_set_offload (struct ndis_softc *);
189 static void ndis_getstate_80211 (struct ndis_softc *);
190 static void ndis_setstate_80211 (struct ndis_softc *);
191 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
192 static void ndis_media_status (struct ifnet *, struct ifmediareq *);
193 static int ndis_set_cipher (struct ndis_softc *, int);
194 static int ndis_set_wpa (struct ndis_softc *, void *, int);
195 static int ndis_add_key (struct ieee80211vap *,
196 const struct ieee80211_key *, const u_int8_t []);
197 static int ndis_del_key (struct ieee80211vap *,
198 const struct ieee80211_key *);
200 static void ndis_setmulti (struct ndis_softc *);
201 static void ndis_map_sclist (void *, bus_dma_segment_t *,
202 int, bus_size_t, int);
204 static int ndisdrv_loaded = 0;
207 * This routine should call windrv_load() once for each driver
208 * image. This will do the relocation and dynalinking for the
209 * image, and create a Windows driver object which will be
210 * saved in our driver database.
213 ndisdrv_modevent(mod, cmd, arg)
223 if (ndisdrv_loaded > 1)
225 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
226 3, WINDRV_WRAP_STDCALL);
227 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
228 8, WINDRV_WRAP_STDCALL);
229 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
230 1, WINDRV_WRAP_STDCALL);
231 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
232 4, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
234 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
236 3, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
238 4, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_linksts_done,
240 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
242 2, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
244 2, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
246 2, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
248 2, WINDRV_WRAP_STDCALL);
252 if (ndisdrv_loaded > 0)
256 windrv_unwrap(ndis_rxeof_wrap);
257 windrv_unwrap(ndis_rxeof_eth_wrap);
258 windrv_unwrap(ndis_rxeof_done_wrap);
259 windrv_unwrap(ndis_rxeof_xfr_wrap);
260 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
261 windrv_unwrap(ndis_txeof_wrap);
262 windrv_unwrap(ndis_linksts_wrap);
263 windrv_unwrap(ndis_linksts_done_wrap);
264 windrv_unwrap(ndis_ticktask_wrap);
265 windrv_unwrap(ndis_starttask_wrap);
266 windrv_unwrap(ndis_resettask_wrap);
267 windrv_unwrap(ndis_inputtask_wrap);
278 * Program the 64-bit multicast hash filter.
282 struct ndis_softc *sc;
285 struct ifmultiaddr *ifma;
286 int len, mclistsz, error;
291 if (!NDIS_INITIALIZED(sc))
294 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
295 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
296 len = sizeof(sc->ndis_filter);
297 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
298 &sc->ndis_filter, &len);
300 device_printf(sc->ndis_dev,
301 "set allmulti failed: %d\n", error);
305 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
308 len = sizeof(mclistsz);
309 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
311 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
313 if (mclist == NULL) {
314 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
318 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
322 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
323 if (ifma->ifma_addr->sa_family != AF_LINK)
325 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
326 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
328 if (len > mclistsz) {
329 if_maddr_runlock(ifp);
330 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
331 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
335 if_maddr_runlock(ifp);
337 len = len * ETHER_ADDR_LEN;
338 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
340 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
341 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
342 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
346 free(mclist, M_TEMP);
348 len = sizeof(sc->ndis_filter);
349 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
350 &sc->ndis_filter, &len);
352 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
357 struct ndis_softc *sc;
359 ndis_task_offload *nto;
360 ndis_task_offload_hdr *ntoh;
361 ndis_task_tcpip_csum *nttc;
367 if (!NDIS_INITIALIZED(sc))
370 /* See if there's anything to set. */
372 error = ndis_probe_offload(sc);
376 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
379 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
380 sizeof(ndis_task_tcpip_csum);
382 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
387 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
388 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
389 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
390 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
391 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
392 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
394 nto = (ndis_task_offload *)((char *)ntoh +
395 ntoh->ntoh_offset_firsttask);
397 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
398 nto->nto_len = sizeof(ndis_task_offload);
399 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
400 nto->nto_offset_nexttask = 0;
401 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
403 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
405 if (ifp->if_capenable & IFCAP_TXCSUM)
406 nttc->nttc_v4tx = sc->ndis_v4tx;
408 if (ifp->if_capenable & IFCAP_RXCSUM)
409 nttc->nttc_v4rx = sc->ndis_v4rx;
411 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418 ndis_probe_offload(sc)
419 struct ndis_softc *sc;
421 ndis_task_offload *nto;
422 ndis_task_offload_hdr *ntoh;
423 ndis_task_tcpip_csum *nttc = NULL;
425 int len, error, dummy;
430 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
435 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
440 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
441 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
442 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
443 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
444 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
446 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
453 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
458 nto = (ndis_task_offload *)((char *)ntoh +
459 ntoh->ntoh_offset_firsttask);
462 switch (nto->nto_task) {
463 case NDIS_TASK_TCPIP_CSUM:
464 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
466 /* Don't handle these yet. */
467 case NDIS_TASK_IPSEC:
468 case NDIS_TASK_TCP_LARGESEND:
472 if (nto->nto_offset_nexttask == 0)
474 nto = (ndis_task_offload *)((char *)nto +
475 nto->nto_offset_nexttask);
483 sc->ndis_v4tx = nttc->nttc_v4tx;
484 sc->ndis_v4rx = nttc->nttc_v4rx;
486 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
487 sc->ndis_hwassist |= CSUM_IP;
488 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
489 sc->ndis_hwassist |= CSUM_TCP;
490 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
491 sc->ndis_hwassist |= CSUM_UDP;
493 if (sc->ndis_hwassist)
494 ifp->if_capabilities |= IFCAP_TXCSUM;
496 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
497 ifp->if_capabilities |= IFCAP_RXCSUM;
498 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
499 ifp->if_capabilities |= IFCAP_RXCSUM;
500 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
501 ifp->if_capabilities |= IFCAP_RXCSUM;
508 ndis_nettype_chan(uint32_t type)
511 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
512 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
513 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
514 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
516 DPRINTF(("unknown channel nettype %d\n", type));
517 return (IEEE80211_CHAN_B); /* Default to 11B chan */
521 ndis_nettype_mode(uint32_t type)
524 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
525 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
526 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
527 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
529 DPRINTF(("unknown mode nettype %d\n", type));
530 return (IEEE80211_MODE_AUTO);
534 * Attach the interface. Allocate softc structures, do ifmedia
535 * setup and ethernet/BPF attach.
541 u_char eaddr[ETHER_ADDR_LEN];
542 struct ndis_softc *sc;
545 struct ifnet *ifp = NULL;
546 int error = 0, len, mode;
550 sc = device_get_softc(dev);
552 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
554 KeInitializeSpinLock(&sc->ndis_rxlock);
555 KeInitializeSpinLock(&sc->ndisusb_tasklock);
556 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
557 InitializeListHead(&sc->ndis_shlist);
558 InitializeListHead(&sc->ndisusb_tasklist);
559 InitializeListHead(&sc->ndisusb_xferdonelist);
560 callout_init(&sc->ndis_stat_callout, 1);
562 /* Create sysctl registry nodes */
563 ndis_create_sysctls(sc);
565 /* Find the PDO for this device instance. */
567 if (sc->ndis_iftype == PCIBus)
568 pdrv = windrv_lookup(0, "PCI Bus");
569 else if (sc->ndis_iftype == PCMCIABus)
570 pdrv = windrv_lookup(0, "PCCARD Bus");
572 pdrv = windrv_lookup(0, "USB Bus");
573 pdo = windrv_find_pdo(pdrv, dev);
576 * Create a new functional device object for this
577 * device. This is what creates the miniport block
578 * for this device instance.
581 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
582 device_printf(dev, "failed to create FDO!\n");
587 /* Tell the user what version of the API the driver is using. */
588 device_printf(dev, "NDIS API version: %d.%d\n",
589 sc->ndis_chars->nmc_version_major,
590 sc->ndis_chars->nmc_version_minor);
592 /* Do resource conversion. */
593 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
594 ndis_convert_res(sc);
596 sc->ndis_block->nmb_rlist = NULL;
598 /* Install our RX and TX interrupt handlers. */
599 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
600 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
601 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
602 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
603 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
605 /* Override the status handler so we can detect link changes. */
606 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
607 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
609 /* Set up work item handlers. */
610 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
611 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
612 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
613 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
614 sc->ndisusb_xferdoneitem =
615 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
616 sc->ndisusb_taskitem =
617 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
618 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
620 /* Call driver's init routine. */
621 if (ndis_init_nic(sc)) {
622 device_printf(dev, "init handler failed\n");
628 * Get station address from the driver.
631 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
634 * Figure out how big to make the TX buffer pool.
637 len = sizeof(sc->ndis_maxpkts);
638 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
639 &sc->ndis_maxpkts, &len)) {
640 device_printf(dev, "failed to get max TX packets\n");
646 * If this is a deserialized miniport, we don't have
647 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
649 if (!NDIS_SERIALIZED(sc->ndis_block))
650 sc->ndis_maxpkts = NDIS_TXPKTS;
652 /* Enforce some sanity, just in case. */
654 if (sc->ndis_maxpkts == 0)
655 sc->ndis_maxpkts = 10;
657 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
658 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
660 /* Allocate a pool of ndis_packets for TX encapsulation. */
662 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
663 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
665 if (i != NDIS_STATUS_SUCCESS) {
666 sc->ndis_txpool = NULL;
667 device_printf(dev, "failed to allocate TX packet pool");
672 sc->ndis_txpending = sc->ndis_maxpkts;
675 /* Get supported oid list. */
676 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
678 /* If the NDIS module requested scatter/gather, init maps. */
683 * See if the OID_802_11_CONFIGURATION OID is
684 * supported by this driver. If it is, then this an 802.11
685 * wireless driver, and we should set up media for wireless.
687 for (i = 0; i < sc->ndis_oidcnt; i++)
688 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
694 ifp = if_alloc(IFT_IEEE80211);
696 ifp = if_alloc(IFT_ETHER);
704 /* Check for task offload support. */
705 ndis_probe_offload(sc);
707 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
708 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
709 ifp->if_ioctl = ndis_ioctl;
710 ifp->if_start = ndis_start;
711 ifp->if_init = ndis_init;
712 ifp->if_baudrate = 10000000;
713 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
714 ifp->if_snd.ifq_drv_maxlen = 25;
715 IFQ_SET_READY(&ifp->if_snd);
716 ifp->if_capenable = ifp->if_capabilities;
717 ifp->if_hwassist = sc->ndis_hwassist;
720 if (sc->ndis_80211) {
721 struct ieee80211com *ic = ifp->if_l2com;
722 ndis_80211_rates_ex rates;
723 struct ndis_80211_nettype_list *ntl;
727 callout_init(&sc->ndis_scan_callout, 1);
729 ifp->if_ioctl = ndis_ioctl_80211;
731 ic->ic_opmode = IEEE80211_M_STA;
732 ic->ic_phytype = IEEE80211_T_DS;
733 ic->ic_caps = IEEE80211_C_8023ENCAP |
734 IEEE80211_C_STA | IEEE80211_C_IBSS;
735 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
737 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
741 ntl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
742 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
749 for (i = 0; i < ntl->ntl_items; i++) {
750 mode = ndis_nettype_mode(ntl->ntl_type[i]);
752 setbit(ic->ic_modecaps, mode);
753 setbit(&bands, mode);
755 device_printf(dev, "Unknown nettype %d\n",
760 /* Default to 11b channels if the card did not supply any */
762 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
763 setbit(&bands, IEEE80211_MODE_11B);
766 bzero((char *)&rates, len);
767 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
768 (void *)rates, &len);
770 device_printf(dev, "get rates failed: 0x%x\n", r);
772 * Since the supported rates only up to 8 can be supported,
773 * if this is not 802.11b we're just going to be faking it
777 #define TESTSETRATE(x, y) \
780 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
781 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
784 if (i == ic->ic_sup_rates[x].rs_nrates) { \
785 ic->ic_sup_rates[x].rs_rates[i] = (y); \
786 ic->ic_sup_rates[x].rs_nrates++; \
790 #define SETRATE(x, y) \
791 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
793 ic->ic_sup_rates[x].rs_nrates++
795 ic->ic_curmode = IEEE80211_MODE_AUTO;
796 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
797 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
798 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
799 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
800 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
801 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
802 for (i = 0; i < len; i++) {
803 switch (rates[i] & IEEE80211_RATE_VAL) {
809 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
810 /* Lazy-init 802.11b. */
811 setbit(ic->ic_modecaps,
813 ic->ic_sup_rates[IEEE80211_MODE_11B].
816 SETRATE(IEEE80211_MODE_11B, rates[i]);
817 INCRATE(IEEE80211_MODE_11B);
820 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
821 SETRATE(IEEE80211_MODE_11A, rates[i]);
822 INCRATE(IEEE80211_MODE_11A);
824 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
825 SETRATE(IEEE80211_MODE_11G, rates[i]);
826 INCRATE(IEEE80211_MODE_11G);
833 * If the hardware supports 802.11g, it most
834 * likely supports 802.11b and all of the
835 * 802.11b and 802.11g speeds, so maybe we can
836 * just cheat here. Just how in the heck do
837 * we detect turbo modes, though?
839 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
840 TESTSETRATE(IEEE80211_MODE_11B,
841 IEEE80211_RATE_BASIC|2);
842 TESTSETRATE(IEEE80211_MODE_11B,
843 IEEE80211_RATE_BASIC|4);
844 TESTSETRATE(IEEE80211_MODE_11B,
845 IEEE80211_RATE_BASIC|11);
846 TESTSETRATE(IEEE80211_MODE_11B,
847 IEEE80211_RATE_BASIC|22);
849 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
850 TESTSETRATE(IEEE80211_MODE_11G, 48);
851 TESTSETRATE(IEEE80211_MODE_11G, 72);
852 TESTSETRATE(IEEE80211_MODE_11G, 96);
853 TESTSETRATE(IEEE80211_MODE_11G, 108);
855 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
856 TESTSETRATE(IEEE80211_MODE_11A, 48);
857 TESTSETRATE(IEEE80211_MODE_11A, 72);
858 TESTSETRATE(IEEE80211_MODE_11A, 96);
859 TESTSETRATE(IEEE80211_MODE_11A, 108);
863 ieee80211_init_channels(ic, NULL, &bands);
866 * To test for WPA support, we need to see if we can
867 * set AUTHENTICATION_MODE to WPA and read it back
871 arg = NDIS_80211_AUTHMODE_WPA;
872 r = ndis_set_info(sc,
873 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
875 r = ndis_get_info(sc,
876 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
877 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
878 ic->ic_caps |= IEEE80211_C_WPA;
882 * To test for supported ciphers, we set each
883 * available encryption type in descending order.
884 * If ENC3 works, then we have WEP, TKIP and AES.
885 * If only ENC2 works, then we have WEP and TKIP.
886 * If only ENC1 works, then we have just WEP.
889 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
890 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
892 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
893 | IEEE80211_CRYPTO_TKIP
894 | IEEE80211_CRYPTO_AES_CCM;
897 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
898 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
900 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
901 | IEEE80211_CRYPTO_TKIP;
904 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
905 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
907 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
910 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
912 ic->ic_caps |= IEEE80211_C_PMGT;
914 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
916 ic->ic_caps |= IEEE80211_C_TXPMGT;
918 ieee80211_ifattach(ic, eaddr);
919 ic->ic_raw_xmit = ndis_raw_xmit;
920 ic->ic_scan_start = ndis_scan_start;
921 ic->ic_scan_end = ndis_scan_end;
922 ic->ic_set_channel = ndis_set_channel;
923 ic->ic_scan_curchan = ndis_scan_curchan;
924 ic->ic_scan_mindwell = ndis_scan_mindwell;
925 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
926 //ic->ic_bss->ni_chan = ic->ic_bsschan;
927 ic->ic_vap_create = ndis_vap_create;
928 ic->ic_vap_delete = ndis_vap_delete;
929 ic->ic_update_mcast = ndis_update_mcast;
930 ic->ic_update_promisc = ndis_update_promisc;
933 ieee80211_announce(ic);
936 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
938 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
939 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
940 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
941 ifmedia_add(&sc->ifmedia,
942 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
943 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
944 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
945 ether_ifattach(ifp, eaddr);
954 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
957 DPRINTF(("attach done.\n"));
958 /* We're done talking to the NIC for now; halt it. */
960 DPRINTF(("halting done.\n"));
965 static struct ieee80211vap *
966 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
967 enum ieee80211_opmode opmode, int flags,
968 const uint8_t bssid[IEEE80211_ADDR_LEN],
969 const uint8_t mac[IEEE80211_ADDR_LEN])
971 struct ndis_vap *nvp;
972 struct ieee80211vap *vap;
974 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
976 nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap),
977 M_80211_VAP, M_NOWAIT | M_ZERO);
981 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
982 /* override with driver methods */
983 nvp->newstate = vap->iv_newstate;
984 vap->iv_newstate = ndis_newstate;
987 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
988 ic->ic_opmode = opmode;
989 /* install key handing routines */
990 vap->iv_key_set = ndis_add_key;
991 vap->iv_key_delete = ndis_del_key;
996 ndis_vap_delete(struct ieee80211vap *vap)
998 struct ndis_vap *nvp = NDIS_VAP(vap);
999 struct ieee80211com *ic = vap->iv_ic;
1000 struct ifnet *ifp = ic->ic_ifp;
1001 struct ndis_softc *sc = ifp->if_softc;
1004 callout_drain(&sc->ndis_scan_callout);
1005 ieee80211_vap_detach(vap);
1006 free(nvp, M_80211_VAP);
1010 * Shutdown hardware and free up resources. This can be called any
1011 * time after the mutex has been initialized. It is called in both
1012 * the error case in attach and the normal detach case so it needs
1013 * to be careful about only freeing resources that have actually been
1020 struct ndis_softc *sc;
1024 sc = device_get_softc(dev);
1028 ifp->if_flags &= ~IFF_UP;
1030 if (device_is_attached(dev)) {
1035 ieee80211_ifdetach(ifp->if_l2com);
1037 ether_ifdetach(ifp);
1042 if (sc->ndis_tickitem != NULL)
1043 IoFreeWorkItem(sc->ndis_tickitem);
1044 if (sc->ndis_startitem != NULL)
1045 IoFreeWorkItem(sc->ndis_startitem);
1046 if (sc->ndis_resetitem != NULL)
1047 IoFreeWorkItem(sc->ndis_resetitem);
1048 if (sc->ndis_inputitem != NULL)
1049 IoFreeWorkItem(sc->ndis_inputitem);
1050 if (sc->ndisusb_xferdoneitem != NULL)
1051 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1052 if (sc->ndisusb_taskitem != NULL)
1053 IoFreeWorkItem(sc->ndisusb_taskitem);
1055 bus_generic_detach(dev);
1056 ndis_unload_driver(sc);
1059 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1060 if (sc->ndis_res_io)
1061 bus_release_resource(dev, SYS_RES_IOPORT,
1062 sc->ndis_io_rid, sc->ndis_res_io);
1063 if (sc->ndis_res_mem)
1064 bus_release_resource(dev, SYS_RES_MEMORY,
1065 sc->ndis_mem_rid, sc->ndis_res_mem);
1066 if (sc->ndis_res_altmem)
1067 bus_release_resource(dev, SYS_RES_MEMORY,
1068 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1074 ndis_destroy_dma(sc);
1076 if (sc->ndis_txarray)
1077 free(sc->ndis_txarray, M_DEVBUF);
1079 if (!sc->ndis_80211)
1080 ifmedia_removeall(&sc->ifmedia);
1082 if (sc->ndis_txpool != NULL)
1083 NdisFreePacketPool(sc->ndis_txpool);
1085 /* Destroy the PDO for this device. */
1087 if (sc->ndis_iftype == PCIBus)
1088 drv = windrv_lookup(0, "PCI Bus");
1089 else if (sc->ndis_iftype == PCMCIABus)
1090 drv = windrv_lookup(0, "PCCARD Bus");
1092 drv = windrv_lookup(0, "USB Bus");
1094 panic("couldn't find driver object");
1095 windrv_destroy_pdo(drv, dev);
1097 if (sc->ndis_iftype == PCIBus)
1098 bus_dma_tag_destroy(sc->ndis_parent_tag);
1107 struct ndis_softc *sc;
1110 sc = device_get_softc(dev);
1114 if (NDIS_INITIALIZED(sc))
1125 struct ndis_softc *sc;
1128 sc = device_get_softc(dev);
1131 if (NDIS_INITIALIZED(sc))
1138 * The following bunch of routines are here to support drivers that
1139 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1140 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1141 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1145 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1146 ndis_handle adapter;
1152 uint32_t lookaheadlen;
1155 ndis_miniport_block *block;
1165 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1169 /* Save the data provided to us so far. */
1171 m->m_len = lookaheadlen + hdrlen;
1172 m->m_pkthdr.len = pktlen + hdrlen;
1174 m_copyback(m, 0, hdrlen, hdr);
1175 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1177 /* Now create a fake NDIS_PACKET to hold the data */
1179 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1181 if (status != NDIS_STATUS_SUCCESS) {
1188 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1196 p->np_private.npp_head = p->np_private.npp_tail = b;
1197 p->np_private.npp_totlen = m->m_pkthdr.len;
1199 /* Save the packet RX context somewhere. */
1200 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1201 priv->nep_ctx = ctx;
1203 if (!NDIS_SERIALIZED(block))
1204 KeAcquireSpinLock(&block->nmb_lock, &irql);
1206 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1208 if (!NDIS_SERIALIZED(block))
1209 KeReleaseSpinLock(&block->nmb_lock, irql);
1213 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1214 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1218 ndis_rxeof_done(adapter)
1219 ndis_handle adapter;
1221 struct ndis_softc *sc;
1222 ndis_miniport_block *block;
1226 /* Schedule transfer/RX of queued packets. */
1228 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1230 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1234 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1237 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1239 ndis_handle adapter;
1243 ndis_miniport_block *block;
1244 struct ndis_softc *sc;
1253 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1256 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1258 l = block->nmb_packetlist.nle_flink;
1259 while(!IsListEmpty(&block->nmb_packetlist)) {
1260 l = RemoveHeadList((&block->nmb_packetlist));
1261 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1262 InitializeListHead((&p->np_list));
1264 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1269 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1271 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1272 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1273 m->m_len, m->m_pkthdr.len - m->m_len);
1275 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1278 * If status is NDIS_STATUS_PENDING, do nothing and
1279 * wait for a callback to the ndis_rxeof_xfr_done()
1283 m->m_len = m->m_pkthdr.len;
1284 m->m_pkthdr.rcvif = ifp;
1286 if (status == NDIS_STATUS_SUCCESS) {
1287 IoFreeMdl(p->np_private.npp_head);
1289 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1290 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1291 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1292 IoQueueWorkItem(sc->ndis_inputitem,
1293 (io_workitem_func)ndis_inputtask_wrap,
1294 WORKQUEUE_CRITICAL, ifp);
1297 if (status == NDIS_STATUS_FAILURE)
1300 /* Advance to next packet */
1301 l = block->nmb_packetlist.nle_flink;
1304 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1308 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1311 ndis_rxeof_xfr_done(adapter, packet, status, len)
1312 ndis_handle adapter;
1313 ndis_packet *packet;
1317 ndis_miniport_block *block;
1318 struct ndis_softc *sc;
1323 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1327 IoFreeMdl(packet->np_private.npp_head);
1328 NdisFreePacket(packet);
1330 if (status != NDIS_STATUS_SUCCESS) {
1335 m->m_len = m->m_pkthdr.len;
1336 m->m_pkthdr.rcvif = ifp;
1337 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1338 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1339 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1340 IoQueueWorkItem(sc->ndis_inputitem,
1341 (io_workitem_func)ndis_inputtask_wrap,
1342 WORKQUEUE_CRITICAL, ifp);
1345 * A frame has been uploaded: pass the resulting mbuf chain up to
1346 * the higher level protocols.
1348 * When handling received NDIS packets, the 'status' field in the
1349 * out-of-band portion of the ndis_packet has special meaning. In the
1350 * most common case, the underlying NDIS driver will set this field
1351 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1352 * take posession of it. We then change the status field to
1353 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1354 * and that we will return it at some point in the future via the
1355 * return packet handler.
1357 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1358 * this means the driver is running out of packet/buffer resources and
1359 * wants to maintain ownership of the packet. In this case, we have to
1360 * copy the packet data into local storage and let the driver keep the
1364 ndis_rxeof(adapter, packets, pktcnt)
1365 ndis_handle adapter;
1366 ndis_packet **packets;
1369 struct ndis_softc *sc;
1370 ndis_miniport_block *block;
1373 ndis_tcpip_csum *csum;
1375 struct mbuf *m0, *m;
1378 block = (ndis_miniport_block *)adapter;
1379 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1383 * There's a slim chance the driver may indicate some packets
1384 * before we're completely ready to handle them. If we detect this,
1385 * we need to return them to the miniport and ignore them.
1387 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1388 for (i = 0; i < pktcnt; i++) {
1390 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1392 (void)ndis_return_packet(NULL ,p, block);
1398 for (i = 0; i < pktcnt; i++) {
1400 /* Stash the softc here so ptom can use it. */
1402 if (ndis_ptom(&m0, p)) {
1403 device_printf(sc->ndis_dev, "ptom failed\n");
1404 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1405 (void)ndis_return_packet(NULL, p, block);
1408 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1409 m = m_dup(m0, M_NOWAIT);
1411 * NOTE: we want to destroy the mbuf here, but
1412 * we don't actually want to return it to the
1413 * driver via the return packet handler. By
1414 * bumping np_refcnt, we can prevent the
1415 * ndis_return_packet() routine from actually
1425 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1427 m = m_dup(m0, M_NOWAIT);
1428 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1431 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1438 m0->m_pkthdr.rcvif = ifp;
1440 /* Deal with checksum offload. */
1442 if (ifp->if_capenable & IFCAP_RXCSUM &&
1443 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1445 p->np_ext.npe_info[ndis_tcpipcsum_info];
1446 csum = (ndis_tcpip_csum *)&s;
1447 if (csum->u.ntc_rxflags &
1448 NDIS_RXCSUM_IP_PASSED)
1449 m0->m_pkthdr.csum_flags |=
1450 CSUM_IP_CHECKED|CSUM_IP_VALID;
1451 if (csum->u.ntc_rxflags &
1452 (NDIS_RXCSUM_TCP_PASSED |
1453 NDIS_RXCSUM_UDP_PASSED)) {
1454 m0->m_pkthdr.csum_flags |=
1455 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1456 m0->m_pkthdr.csum_data = 0xFFFF;
1460 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1461 _IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1462 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1463 IoQueueWorkItem(sc->ndis_inputitem,
1464 (io_workitem_func)ndis_inputtask_wrap,
1465 WORKQUEUE_CRITICAL, ifp);
1471 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1472 * packets into the stack in order to avoid calling (*ifp->if_input)()
1473 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1474 * 'dispatch level' per-cpu sleep lock).
1477 ndis_inputtask(dobj, arg)
1478 device_object *dobj;
1481 ndis_miniport_block *block;
1483 struct ndis_softc *sc;
1485 struct ieee80211com *ic;
1486 struct ieee80211vap *vap;
1492 vap = TAILQ_FIRST(&ic->ic_vaps);
1493 block = dobj->do_devext;
1495 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1497 _IF_DEQUEUE(&sc->ndis_rxqueue, m);
1500 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1501 if ((sc->ndis_80211 != 0) && (vap != NULL))
1502 vap->iv_deliver_data(vap, vap->iv_bss, m);
1504 (*ifp->if_input)(ifp, m);
1505 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1507 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1511 * A frame was downloaded to the chip. It's safe for us to clean up
1515 ndis_txeof(adapter, packet, status)
1516 ndis_handle adapter;
1517 ndis_packet *packet;
1521 struct ndis_softc *sc;
1522 ndis_miniport_block *block;
1527 block = (ndis_miniport_block *)adapter;
1528 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1532 idx = packet->np_txidx;
1534 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1536 ndis_free_packet(packet);
1540 sc->ndis_txarray[idx] = NULL;
1541 sc->ndis_txpending++;
1543 if (status == NDIS_STATUS_SUCCESS)
1548 sc->ndis_tx_timer = 0;
1549 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1553 IoQueueWorkItem(sc->ndis_startitem,
1554 (io_workitem_func)ndis_starttask_wrap,
1555 WORKQUEUE_CRITICAL, ifp);
1559 ndis_linksts(adapter, status, sbuf, slen)
1560 ndis_handle adapter;
1565 ndis_miniport_block *block;
1566 struct ndis_softc *sc;
1569 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1570 sc->ndis_sts = status;
1572 /* Event list is all full up, drop this one. */
1575 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1580 /* Cache the event. */
1583 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1585 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1590 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1592 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1593 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1594 NDIS_EVTINC(sc->ndis_evtpidx);
1599 ndis_linksts_done(adapter)
1600 ndis_handle adapter;
1602 ndis_miniport_block *block;
1603 struct ndis_softc *sc;
1607 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1610 if (!NDIS_INITIALIZED(sc))
1613 switch (sc->ndis_sts) {
1614 case NDIS_STATUS_MEDIA_CONNECT:
1615 IoQueueWorkItem(sc->ndis_tickitem,
1616 (io_workitem_func)ndis_ticktask_wrap,
1617 WORKQUEUE_CRITICAL, sc);
1618 IoQueueWorkItem(sc->ndis_startitem,
1619 (io_workitem_func)ndis_starttask_wrap,
1620 WORKQUEUE_CRITICAL, ifp);
1622 case NDIS_STATUS_MEDIA_DISCONNECT:
1624 IoQueueWorkItem(sc->ndis_tickitem,
1625 (io_workitem_func)ndis_ticktask_wrap,
1626 WORKQUEUE_CRITICAL, sc);
1637 struct ndis_softc *sc;
1641 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1642 IoQueueWorkItem(sc->ndis_tickitem,
1643 (io_workitem_func)ndis_ticktask_wrap,
1644 WORKQUEUE_CRITICAL, sc);
1645 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1648 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1649 sc->ifp->if_oerrors++;
1650 device_printf(sc->ndis_dev, "watchdog timeout\n");
1652 IoQueueWorkItem(sc->ndis_resetitem,
1653 (io_workitem_func)ndis_resettask_wrap,
1654 WORKQUEUE_CRITICAL, sc);
1655 IoQueueWorkItem(sc->ndis_startitem,
1656 (io_workitem_func)ndis_starttask_wrap,
1657 WORKQUEUE_CRITICAL, sc->ifp);
1660 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1664 ndis_ticktask(d, xsc)
1668 struct ndis_softc *sc;
1669 struct ieee80211com *ic;
1670 struct ieee80211vap *vap;
1671 ndis_checkforhang_handler hangfunc;
1675 ic = sc->ifp->if_l2com;
1676 vap = TAILQ_FIRST(&ic->ic_vaps);
1679 if (!NDIS_INITIALIZED(sc)) {
1685 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1687 if (hangfunc != NULL) {
1688 rval = MSCALL1(hangfunc,
1689 sc->ndis_block->nmb_miniportadapterctx);
1697 if (sc->ndis_link == 0 &&
1698 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1700 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1702 ndis_getstate_80211(sc);
1703 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1705 if_link_state_change(vap->iv_ifp, LINK_STATE_UP);
1707 if_link_state_change(sc->ifp, LINK_STATE_UP);
1710 if (sc->ndis_link == 1 &&
1711 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1713 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1715 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1717 if_link_state_change(vap->iv_ifp, LINK_STATE_DOWN);
1719 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1726 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1728 bus_dma_segment_t *segs;
1734 struct ndis_sc_list *sclist;
1737 if (error || arg == NULL)
1742 sclist->nsl_frags = nseg;
1744 for (i = 0; i < nseg; i++) {
1745 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1746 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1751 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1752 const struct ieee80211_bpf_params *params)
1754 /* no support; just discard */
1756 ieee80211_free_node(ni);
1761 ndis_update_mcast(struct ifnet *ifp)
1763 struct ndis_softc *sc = ifp->if_softc;
1769 ndis_update_promisc(struct ifnet *ifp)
1775 ndis_starttask(d, arg)
1783 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1788 * Main transmit routine. To make NDIS drivers happy, we need to
1789 * transform mbuf chains into NDIS packets and feed them to the
1790 * send packet routines. Most drivers allow you to send several
1791 * packets at once (up to the maxpkts limit). Unfortunately, rather
1792 * that accepting them in the form of a linked list, they expect
1793 * a contiguous array of pointers to packets.
1795 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1796 * we need to perform busdma work here. Those that use map registers
1797 * will do the mapping themselves on a buffer by buffer basis.
1803 struct ndis_softc *sc;
1804 struct mbuf *m = NULL;
1805 ndis_packet **p0 = NULL, *p = NULL;
1806 ndis_tcpip_csum *csum;
1807 int pcnt = 0, status;
1812 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1817 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1819 while(sc->ndis_txpending) {
1820 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1824 NdisAllocatePacket(&status,
1825 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1827 if (status != NDIS_STATUS_SUCCESS)
1830 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1831 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1837 * Save pointer to original mbuf
1838 * so we can free it later.
1841 p = sc->ndis_txarray[sc->ndis_txidx];
1842 p->np_txidx = sc->ndis_txidx;
1844 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1847 * Do scatter/gather processing, if driver requested it.
1850 bus_dmamap_load_mbuf(sc->ndis_ttag,
1851 sc->ndis_tmaps[sc->ndis_txidx], m,
1852 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1853 bus_dmamap_sync(sc->ndis_ttag,
1854 sc->ndis_tmaps[sc->ndis_txidx],
1855 BUS_DMASYNC_PREREAD);
1856 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1859 /* Handle checksum offload. */
1861 if (ifp->if_capenable & IFCAP_TXCSUM &&
1862 m->m_pkthdr.csum_flags) {
1863 csum = (ndis_tcpip_csum *)
1864 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1865 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1866 if (m->m_pkthdr.csum_flags & CSUM_IP)
1867 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1868 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1869 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1870 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1871 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1872 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1876 sc->ndis_txpending--;
1881 * If there's a BPF listener, bounce a copy of this frame
1884 if (!sc->ndis_80211) /* XXX handle 80211 */
1888 * The array that p0 points to must appear contiguous,
1889 * so we must not wrap past the end of sc->ndis_txarray[].
1890 * If it looks like we're about to wrap, break out here
1891 * so the this batch of packets can be transmitted, then
1892 * wait for txeof to ask us to send the rest.
1894 if (sc->ndis_txidx == 0)
1903 if (sc->ndis_txpending == 0)
1904 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1907 * Set a timeout in case the chip goes out to lunch.
1909 sc->ndis_tx_timer = 5;
1914 * According to NDIS documentation, if a driver exports
1915 * a MiniportSendPackets() routine, we prefer that over
1916 * a MiniportSend() routine (which sends just a single
1919 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1920 ndis_send_packets(sc, p0, pcnt);
1922 ndis_send_packet(sc, p);
1931 struct ndis_softc *sc = xsc;
1932 struct ifnet *ifp = sc->ifp;
1933 struct ieee80211com *ic = ifp->if_l2com;
1937 * Avoid reintializing the link unnecessarily.
1938 * This should be dealt with in a better way by
1939 * fixing the upper layer modules so they don't
1940 * call ifp->if_init() quite as often.
1946 * Cancel pending I/O and free all RX/TX buffers.
1950 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1951 error = ndis_init_nic(sc);
1953 device_printf(sc->ndis_dev,
1954 "failed to initialize the device: %d\n", error);
1959 /* Init our MAC address */
1961 /* Program the packet filter */
1963 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1965 if (ifp->if_flags & IFF_BROADCAST)
1966 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1968 if (ifp->if_flags & IFF_PROMISC)
1969 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1971 len = sizeof(sc->ndis_filter);
1973 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1974 &sc->ndis_filter, &len);
1977 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1984 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1987 * Program the multicast filter, if necessary.
1991 /* Setup task offload. */
1992 ndis_set_offload(sc);
1997 sc->ndis_txpending = sc->ndis_maxpkts;
2000 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2002 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2003 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2004 sc->ndis_tx_timer = 0;
2007 * Some drivers don't set this value. The NDIS spec says
2008 * the default checkforhang timeout is "approximately 2
2009 * seconds." We use 3 seconds, because it seems for some
2010 * drivers, exactly 2 seconds is too fast.
2012 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2013 sc->ndis_block->nmb_checkforhangsecs = 3;
2015 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2016 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2019 /* XXX force handling */
2021 ieee80211_start_all(ic); /* start all vap's */
2025 * Set media options.
2028 ndis_ifmedia_upd(ifp)
2031 struct ndis_softc *sc;
2035 if (NDIS_INITIALIZED(sc))
2042 * Report current media status.
2045 ndis_ifmedia_sts(ifp, ifmr)
2047 struct ifmediareq *ifmr;
2049 struct ndis_softc *sc;
2050 uint32_t media_info;
2051 ndis_media_state linkstate;
2054 ifmr->ifm_status = IFM_AVALID;
2055 ifmr->ifm_active = IFM_ETHER;
2058 if (!NDIS_INITIALIZED(sc))
2061 len = sizeof(linkstate);
2062 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2063 (void *)&linkstate, &len);
2065 len = sizeof(media_info);
2066 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2067 (void *)&media_info, &len);
2069 if (linkstate == nmc_connected)
2070 ifmr->ifm_status |= IFM_ACTIVE;
2072 switch (media_info) {
2074 ifmr->ifm_active |= IFM_10_T;
2077 ifmr->ifm_active |= IFM_100_TX;
2080 ifmr->ifm_active |= IFM_1000_T;
2083 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2089 ndis_set_cipher(sc, cipher)
2090 struct ndis_softc *sc;
2093 struct ieee80211com *ic;
2097 ic = sc->ifp->if_l2com;
2101 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2102 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2104 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2107 if (cipher == WPA_CSE_TKIP) {
2108 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2110 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2113 if (cipher == WPA_CSE_CCMP) {
2114 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2116 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2119 DPRINTF(("Setting cipher to %d\n", arg));
2121 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2126 /* Check that the cipher was set correctly. */
2129 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2131 if (rval != 0 || arg != save)
2138 * WPA is hairy to set up. Do the work in a separate routine
2139 * so we don't clutter the setstate function too much.
2140 * Important yet undocumented fact: first we have to set the
2141 * authentication mode, _then_ we enable the ciphers. If one
2142 * of the WPA authentication modes isn't enabled, the driver
2143 * might not permit the TKIP or AES ciphers to be selected.
2146 ndis_set_wpa(sc, ie, ielen)
2147 struct ndis_softc *sc;
2151 struct ieee80211_ie_wpa *w;
2158 * Apparently, the only way for us to know what ciphers
2159 * and key management/authentication mode to use is for
2160 * us to inspect the optional information element (IE)
2161 * stored in the 802.11 state machine. This IE should be
2162 * supplied by the WPA supplicant.
2165 w = (struct ieee80211_ie_wpa *)ie;
2167 /* Check for the right kind of IE. */
2168 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2169 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2173 /* Skip over the ucast cipher OIDs. */
2174 pos = (char *)&w->wpa_uciphers[0];
2175 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2177 /* Skip over the authmode count. */
2178 pos += sizeof(u_int16_t);
2181 * Check for the authentication modes. I'm
2182 * pretty sure there's only supposed to be one.
2185 n = (struct ndis_ie *)pos;
2186 if (n->ni_val == WPA_ASE_NONE)
2187 arg = NDIS_80211_AUTHMODE_WPANONE;
2189 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2190 arg = NDIS_80211_AUTHMODE_WPA;
2192 if (n->ni_val == WPA_ASE_8021X_PSK)
2193 arg = NDIS_80211_AUTHMODE_WPAPSK;
2195 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2197 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2200 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2202 /* Now configure the desired ciphers. */
2204 /* First, set up the multicast group cipher. */
2205 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2207 if (ndis_set_cipher(sc, n->ni_val))
2210 /* Now start looking around for the unicast ciphers. */
2211 pos = (char *)&w->wpa_uciphers[0];
2212 n = (struct ndis_ie *)pos;
2214 for (i = 0; i < w->wpa_uciphercnt; i++) {
2215 if (ndis_set_cipher(sc, n->ni_val))
2224 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2226 struct ieee80211vap *vap = ifp->if_softc;
2227 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2231 if (!NDIS_INITIALIZED(sc))
2234 len = sizeof(txrate);
2235 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2236 vap->iv_bss->ni_txrate = txrate / 5000;
2237 ieee80211_media_status(ifp, imr);
2241 ndis_setstate_80211(sc)
2242 struct ndis_softc *sc;
2244 struct ieee80211com *ic;
2245 struct ieee80211vap *vap;
2246 ndis_80211_macaddr bssid;
2247 ndis_80211_config config;
2254 vap = TAILQ_FIRST(&ic->ic_vaps);
2256 if (!NDIS_INITIALIZED(sc)) {
2257 DPRINTF(("%s: NDIS not initialized\n", __func__));
2261 /* Disassociate and turn off radio. */
2264 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2266 /* Set network infrastructure mode. */
2269 if (ic->ic_opmode == IEEE80211_M_IBSS)
2270 arg = NDIS_80211_NET_INFRA_IBSS;
2272 arg = NDIS_80211_NET_INFRA_BSS;
2274 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2277 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2279 /* Set power management */
2281 if (vap->iv_flags & IEEE80211_F_PMGTON)
2282 arg = NDIS_80211_POWERMODE_FAST_PSP;
2284 arg = NDIS_80211_POWERMODE_CAM;
2285 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2288 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2289 ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2290 arg = dBm2mW[ic->ic_txpowlimit];
2292 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2296 * Default encryption mode to off, authentication
2297 * to open and privacy to 'accept everything.'
2300 arg = NDIS_80211_WEPSTAT_DISABLED;
2301 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2304 arg = NDIS_80211_AUTHMODE_OPEN;
2305 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2308 * Note that OID_802_11_PRIVACY_FILTER is optional:
2309 * not all drivers implement it.
2312 arg = NDIS_80211_PRIVFILT_8021XWEP;
2313 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2315 len = sizeof(config);
2316 bzero((char *)&config, len);
2317 config.nc_length = len;
2318 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2319 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2322 * Some drivers expect us to initialize these values, so
2323 * provide some defaults.
2326 if (config.nc_beaconperiod == 0)
2327 config.nc_beaconperiod = 100;
2328 if (config.nc_atimwin == 0)
2329 config.nc_atimwin = 100;
2330 if (config.nc_fhconfig.ncf_dwelltime == 0)
2331 config.nc_fhconfig.ncf_dwelltime = 200;
2332 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2335 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2336 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2337 IEEE80211_CHAN_5GHZ;
2338 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2339 config.nc_dsconfig =
2340 ic->ic_bsschan->ic_freq * 1000;
2341 len = sizeof(config);
2342 config.nc_length = len;
2343 config.nc_fhconfig.ncf_length =
2344 sizeof(ndis_80211_config_fh);
2345 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2346 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2349 device_printf(sc->ndis_dev, "couldn't change "
2350 "DS config to %ukHz: %d\n",
2351 config.nc_dsconfig, rval);
2354 device_printf(sc->ndis_dev, "couldn't retrieve "
2355 "channel info: %d\n", rval);
2357 /* Set the BSSID to our value so the driver doesn't associate */
2358 len = IEEE80211_ADDR_LEN;
2359 bcopy(IF_LLADDR(ifp), bssid, len);
2360 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2361 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2363 device_printf(sc->ndis_dev,
2364 "setting BSSID failed: %d\n", rval);
2368 ndis_auth_and_assoc(sc, vap)
2369 struct ndis_softc *sc;
2370 struct ieee80211vap *vap;
2372 struct ieee80211com *ic;
2373 struct ieee80211_node *ni;
2374 ndis_80211_ssid ssid;
2375 ndis_80211_macaddr bssid;
2377 int i, rval = 0, len, error;
2385 if (!NDIS_INITIALIZED(sc)) {
2386 DPRINTF(("%s: NDIS not initialized\n", __func__));
2391 ndis_setstate_80211(sc);
2393 /* Set network infrastructure mode. */
2396 if (vap->iv_opmode == IEEE80211_M_IBSS)
2397 arg = NDIS_80211_NET_INFRA_IBSS;
2399 arg = NDIS_80211_NET_INFRA_BSS;
2401 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2404 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2406 /* Set RTS threshold */
2409 arg = vap->iv_rtsthreshold;
2410 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2412 /* Set fragmentation threshold */
2415 arg = vap->iv_fragthreshold;
2416 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2420 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2421 !(vap->iv_flags & IEEE80211_F_WPA)) {
2424 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2426 arg = NDIS_80211_AUTHMODE_SHARED;
2427 DPRINTF(("Setting shared auth\n"));
2428 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2431 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2432 if (vap->iv_nw_keys[i].wk_keylen) {
2433 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2434 IEEE80211_CIPHER_WEP)
2436 bzero((char *)&wep, sizeof(wep));
2437 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2440 * 5, 13 and 16 are the only valid
2441 * key lengths. Anything in between
2442 * will be zero padded out to the
2443 * next highest boundary.
2445 if (vap->iv_nw_keys[i].wk_keylen < 5)
2447 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2448 vap->iv_nw_keys[i].wk_keylen < 13)
2450 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2451 vap->iv_nw_keys[i].wk_keylen < 16)
2455 wep.nw_length = (sizeof(uint32_t) * 3)
2457 if (i == vap->iv_def_txkey)
2458 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2459 bcopy(vap->iv_nw_keys[i].wk_key,
2460 wep.nw_keydata, wep.nw_length);
2462 DPRINTF(("Setting WEP key %d\n", i));
2463 rval = ndis_set_info(sc,
2464 OID_802_11_ADD_WEP, &wep, &len);
2466 device_printf(sc->ndis_dev,
2467 "set wepkey failed: %d\n", rval);
2472 DPRINTF(("Setting WEP on\n"));
2473 arg = NDIS_80211_WEPSTAT_ENABLED;
2475 rval = ndis_set_info(sc,
2476 OID_802_11_WEP_STATUS, &arg, &len);
2478 device_printf(sc->ndis_dev,
2479 "enable WEP failed: %d\n", rval);
2480 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2481 arg = NDIS_80211_PRIVFILT_8021XWEP;
2483 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2487 OID_802_11_PRIVACY_FILTER, &arg, &len);
2492 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2493 vap->iv_appie_assocreq != NULL) {
2494 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2495 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2497 device_printf(sc->ndis_dev, "WPA setup failed\n");
2501 /* Set network type. */
2505 switch (vap->iv_curmode) {
2506 case IEEE80211_MODE_11A:
2507 arg = NDIS_80211_NETTYPE_11OFDM5;
2509 case IEEE80211_MODE_11B:
2510 arg = NDIS_80211_NETTYPE_11DS;
2512 case IEEE80211_MODE_11G:
2513 arg = NDIS_80211_NETTYPE_11OFDM24;
2516 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2521 DPRINTF(("Setting network type to %d\n", arg));
2523 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2526 device_printf(sc->ndis_dev,
2527 "set nettype failed: %d\n", rval);
2532 * If the user selected a specific BSSID, try
2533 * to use that one. This is useful in the case where
2534 * there are several APs in range with the same network
2535 * name. To delete the BSSID, we use the broadcast
2536 * address as the BSSID.
2537 * Note that some drivers seem to allow setting a BSSID
2538 * in ad-hoc mode, which has the effect of forcing the
2539 * NIC to create an ad-hoc cell with a specific BSSID,
2540 * instead of a randomly chosen one. However, the net80211
2541 * code makes the assumtion that the BSSID setting is invalid
2542 * when you're in ad-hoc mode, so we don't allow that here.
2545 len = IEEE80211_ADDR_LEN;
2546 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2547 vap->iv_opmode != IEEE80211_M_IBSS)
2548 bcopy(ni->ni_bssid, bssid, len);
2550 bcopy(ifp->if_broadcastaddr, bssid, len);
2552 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2553 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2555 device_printf(sc->ndis_dev,
2556 "setting BSSID failed: %d\n", rval);
2558 /* Set SSID -- always do this last. */
2561 if (ndis_debug > 0) {
2562 printf("Setting ESSID to ");
2563 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2569 bzero((char *)&ssid, len);
2570 ssid.ns_ssidlen = ni->ni_esslen;
2571 if (ssid.ns_ssidlen == 0) {
2572 ssid.ns_ssidlen = 1;
2574 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2576 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2579 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2585 ndis_get_bssid_list(sc, bl)
2586 struct ndis_softc *sc;
2587 ndis_80211_bssid_list_ex **bl;
2591 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2592 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2596 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2597 if (error == ENOSPC) {
2598 free(*bl, M_DEVBUF);
2599 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2603 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2606 DPRINTF(("%s: failed to read\n", __func__));
2607 free(*bl, M_DEVBUF);
2615 ndis_get_assoc(sc, assoc)
2616 struct ndis_softc *sc;
2617 ndis_wlan_bssid_ex **assoc;
2619 struct ifnet *ifp = sc->ifp;
2620 struct ieee80211com *ic = ifp->if_l2com;
2621 struct ieee80211vap *vap;
2622 struct ieee80211_node *ni;
2623 ndis_80211_bssid_list_ex *bl;
2624 ndis_wlan_bssid_ex *bs;
2625 ndis_80211_macaddr bssid;
2631 len = sizeof(bssid);
2632 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2634 device_printf(sc->ndis_dev, "failed to get bssid\n");
2638 vap = TAILQ_FIRST(&ic->ic_vaps);
2641 error = ndis_get_bssid_list(sc, &bl);
2645 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2646 for (i = 0; i < bl->nblx_items; i++) {
2647 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2648 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2649 if (*assoc == NULL) {
2653 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2655 if (ic->ic_opmode == IEEE80211_M_STA)
2656 ni->ni_associd = 1 | 0xc000; /* fake associd */
2659 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2667 ndis_getstate_80211(sc)
2668 struct ndis_softc *sc;
2670 struct ieee80211com *ic;
2671 struct ieee80211vap *vap;
2672 struct ieee80211_node *ni;
2673 ndis_wlan_bssid_ex *bs;
2674 int rval, len, i = 0;
2681 vap = TAILQ_FIRST(&ic->ic_vaps);
2684 if (!NDIS_INITIALIZED(sc))
2687 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2690 /* We're associated, retrieve info on the current bssid. */
2691 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2692 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2693 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2695 /* Get SSID from current association info. */
2696 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2697 bs->nwbx_ssid.ns_ssidlen);
2698 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2700 if (ic->ic_caps & IEEE80211_C_PMGT) {
2702 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2705 device_printf(sc->ndis_dev,
2706 "get power mode failed: %d\n", rval);
2707 if (arg == NDIS_80211_POWERMODE_CAM)
2708 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2710 vap->iv_flags |= IEEE80211_F_PMGTON;
2714 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2716 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2717 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2718 if (dBm2mW[i] >= arg)
2720 ic->ic_txpowlimit = i;
2724 * Use the current association information to reflect
2725 * what channel we're on.
2727 ic->ic_curchan = ieee80211_find_channel(ic,
2728 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2729 if (ic->ic_curchan == NULL)
2730 ic->ic_curchan = &ic->ic_channels[0];
2731 ni->ni_chan = ic->ic_curchan;
2732 ic->ic_bsschan = ic->ic_curchan;
2737 * Determine current authentication mode.
2740 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2742 device_printf(sc->ndis_dev,
2743 "get authmode status failed: %d\n", rval);
2745 vap->iv_flags &= ~IEEE80211_F_WPA;
2747 case NDIS_80211_AUTHMODE_OPEN:
2748 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2750 case NDIS_80211_AUTHMODE_SHARED:
2751 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2753 case NDIS_80211_AUTHMODE_AUTO:
2754 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2756 case NDIS_80211_AUTHMODE_WPA:
2757 case NDIS_80211_AUTHMODE_WPAPSK:
2758 case NDIS_80211_AUTHMODE_WPANONE:
2759 ni->ni_authmode = IEEE80211_AUTH_WPA;
2760 vap->iv_flags |= IEEE80211_F_WPA1;
2762 case NDIS_80211_AUTHMODE_WPA2:
2763 case NDIS_80211_AUTHMODE_WPA2PSK:
2764 ni->ni_authmode = IEEE80211_AUTH_WPA;
2765 vap->iv_flags |= IEEE80211_F_WPA2;
2768 ni->ni_authmode = IEEE80211_AUTH_NONE;
2774 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2777 device_printf(sc->ndis_dev,
2778 "get wep status failed: %d\n", rval);
2780 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2781 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2783 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2787 ndis_ioctl(ifp, command, data)
2792 struct ndis_softc *sc = ifp->if_softc;
2793 struct ifreq *ifr = (struct ifreq *) data;
2800 if (ifp->if_flags & IFF_UP) {
2801 if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2802 ifp->if_flags & IFF_PROMISC &&
2803 !(sc->ndis_if_flags & IFF_PROMISC)) {
2805 NDIS_PACKET_TYPE_PROMISCUOUS;
2806 i = sizeof(sc->ndis_filter);
2807 error = ndis_set_info(sc,
2808 OID_GEN_CURRENT_PACKET_FILTER,
2809 &sc->ndis_filter, &i);
2810 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2811 !(ifp->if_flags & IFF_PROMISC) &&
2812 sc->ndis_if_flags & IFF_PROMISC) {
2814 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2815 i = sizeof(sc->ndis_filter);
2816 error = ndis_set_info(sc,
2817 OID_GEN_CURRENT_PACKET_FILTER,
2818 &sc->ndis_filter, &i);
2822 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2825 sc->ndis_if_flags = ifp->if_flags;
2835 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2838 ifp->if_capenable = ifr->ifr_reqcap;
2839 if (ifp->if_capenable & IFCAP_TXCSUM)
2840 ifp->if_hwassist = sc->ndis_hwassist;
2842 ifp->if_hwassist = 0;
2843 ndis_set_offload(sc);
2846 error = ether_ioctl(ifp, command, data);
2850 /*NDIS_UNLOCK(sc);*/
2856 ndis_ioctl_80211(ifp, command, data)
2861 struct ndis_softc *sc = ifp->if_softc;
2862 struct ieee80211com *ic = ifp->if_l2com;
2863 struct ifreq *ifr = (struct ifreq *) data;
2864 struct ndis_oid_data oid;
2865 struct ndis_evt evt;
2872 if (ifp->if_flags & IFF_UP) {
2873 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
2876 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2879 sc->ndis_if_flags = ifp->if_flags;
2881 /*NDIS_UNLOCK(sc);*/
2884 if ((error = priv_check(curthread, PRIV_DRIVER)))
2886 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2889 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2890 if (oidbuf == NULL) {
2894 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2896 free(oidbuf, M_TEMP);
2899 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2901 free(oidbuf, M_TEMP);
2904 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2906 free(oidbuf, M_TEMP);
2909 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2910 free(oidbuf, M_TEMP);
2913 if ((error = priv_check(curthread, PRIV_DRIVER)))
2915 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2918 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2919 if (oidbuf == NULL) {
2923 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2925 free(oidbuf, M_TEMP);
2928 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2930 free(oidbuf, M_TEMP);
2933 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2935 free(oidbuf, M_TEMP);
2938 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2939 free(oidbuf, M_TEMP);
2941 case SIOCGPRIVATE_0:
2942 if ((error = priv_check(curthread, PRIV_DRIVER)))
2945 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2950 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2955 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2960 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2961 ifr->ifr_data, sizeof(uint32_t) * 2);
2966 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2967 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2968 ifr->ifr_data + (sizeof(uint32_t) * 2),
2969 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2974 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2975 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2977 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2978 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2979 NDIS_EVTINC(sc->ndis_evtcidx);
2983 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2986 error = ether_ioctl(ifp, command, data);
2996 ndis_del_key(vap, key)
2997 struct ieee80211vap *vap;
2998 const struct ieee80211_key *key;
3000 struct ndis_softc *sc;
3001 ndis_80211_key rkey;
3004 sc = vap->iv_ic->ic_ifp->if_softc;
3006 bzero((char *)&rkey, sizeof(rkey));
3010 rkey.nk_keyidx = key->wk_keyix;
3012 bcopy(vap->iv_ifp->if_broadcastaddr,
3013 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3015 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3024 * In theory this could be called for any key, but we'll
3025 * only use it for WPA TKIP or AES keys. These need to be
3026 * set after initial authentication with the AP.
3029 ndis_add_key(vap, key, mac)
3030 struct ieee80211vap *vap;
3031 const struct ieee80211_key *key;
3032 const uint8_t mac[IEEE80211_ADDR_LEN];
3034 struct ndis_softc *sc;
3036 ndis_80211_key rkey;
3039 ifp = vap->iv_ic->ic_ifp;
3042 switch (key->wk_cipher->ic_cipher) {
3043 case IEEE80211_CIPHER_TKIP:
3045 len = sizeof(ndis_80211_key);
3046 bzero((char *)&rkey, sizeof(rkey));
3049 rkey.nk_keylen = key->wk_keylen;
3051 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3052 rkey.nk_keylen += 16;
3054 /* key index - gets weird in NDIS */
3056 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3057 rkey.nk_keyidx = key->wk_keyix;
3061 if (key->wk_flags & IEEE80211_KEY_XMIT)
3062 rkey.nk_keyidx |= 1 << 31;
3064 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3065 bcopy(ifp->if_broadcastaddr,
3066 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3068 bcopy(vap->iv_bss->ni_bssid,
3069 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3071 rkey.nk_keyidx |= 1 << 30;
3074 /* need to set bit 29 based on keyrsc */
3075 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3078 rkey.nk_keyidx |= 1 << 29;
3080 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3081 bcopy(key->wk_key, rkey.nk_keydata, 16);
3082 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3083 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3085 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3087 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3089 case IEEE80211_CIPHER_WEP:
3093 * I don't know how to set up keys for the AES
3094 * cipher yet. Is it the same as TKIP?
3096 case IEEE80211_CIPHER_AES_CCM:
3102 /* We need to return 1 for success, 0 for failure. */
3111 ndis_resettask(d, arg)
3115 struct ndis_softc *sc;
3122 * Stop the adapter and free any mbufs allocated to the
3127 struct ndis_softc *sc;
3133 callout_drain(&sc->ndis_stat_callout);
3136 sc->ndis_tx_timer = 0;
3138 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3141 if (sc->ndis_iftype != PNPBus ||
3142 (sc->ndis_iftype == PNPBus &&
3143 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3148 for (i = 0; i < NDIS_EVENTS; i++) {
3149 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3150 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3151 sc->ndis_evt[i].ne_buf = NULL;
3153 sc->ndis_evt[i].ne_sts = 0;
3154 sc->ndis_evt[i].ne_len = 0;
3156 sc->ndis_evtcidx = 0;
3157 sc->ndis_evtpidx = 0;
3162 * Stop all chip I/O so that the kernel's probe routines don't
3163 * get confused by errant DMAs when rebooting.
3169 struct ndis_softc *sc;
3171 sc = device_get_softc(dev);
3176 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3178 struct ndis_vap *nvp = NDIS_VAP(vap);
3179 struct ieee80211com *ic = vap->iv_ic;
3180 struct ifnet *ifp = ic->ic_ifp;
3181 struct ndis_softc *sc = ifp->if_softc;
3182 enum ieee80211_state ostate;
3184 DPRINTF(("%s: %s -> %s\n", __func__,
3185 ieee80211_state_name[vap->iv_state],
3186 ieee80211_state_name[nstate]));
3188 ostate = vap->iv_state;
3189 vap->iv_state = nstate;
3192 /* pass on to net80211 */
3193 case IEEE80211_S_INIT:
3194 case IEEE80211_S_SCAN:
3195 return nvp->newstate(vap, nstate, arg);
3196 case IEEE80211_S_ASSOC:
3197 if (ostate != IEEE80211_S_AUTH) {
3198 IEEE80211_UNLOCK(ic);
3199 ndis_auth_and_assoc(sc, vap);
3203 case IEEE80211_S_AUTH:
3204 IEEE80211_UNLOCK(ic);
3205 ndis_auth_and_assoc(sc, vap);
3206 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3207 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3217 ndis_scan(void *arg)
3219 struct ieee80211vap *vap = arg;
3221 ieee80211_scan_done(vap);
3225 ndis_scan_results(struct ndis_softc *sc)
3227 struct ieee80211com *ic;
3228 struct ieee80211vap *vap;
3229 ndis_80211_bssid_list_ex *bl;
3230 ndis_wlan_bssid_ex *wb;
3231 struct ieee80211_scanparams sp;
3232 struct ieee80211_frame wh;
3233 struct ieee80211_channel *saved_chan;
3235 int rssi, noise, freq, chanflag;
3236 uint8_t ssid[2+IEEE80211_NWID_LEN];
3237 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3238 uint8_t *frm, *efrm;
3240 ic = sc->ifp->if_l2com;
3241 vap = TAILQ_FIRST(&ic->ic_vaps);
3242 saved_chan = ic->ic_curchan;
3245 if (ndis_get_bssid_list(sc, &bl))
3248 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3249 wb = &bl->nblx_bssid[0];
3250 for (i = 0; i < bl->nblx_items; i++) {
3251 memset(&sp, 0, sizeof(sp));
3253 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3254 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3255 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3256 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3257 if (wb->nwbx_privacy)
3258 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3259 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3260 switch (wb->nwbx_netinfra) {
3261 case NDIS_80211_NET_INFRA_IBSS:
3262 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3264 case NDIS_80211_NET_INFRA_BSS:
3265 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3268 sp.rates = &rates[0];
3269 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3270 /* XXX - check units */
3271 if (wb->nwbx_supportedrates[j] == 0)
3274 wb->nwbx_supportedrates[j] & 0x7f;
3277 sp.ssid = (uint8_t *)&ssid[0];
3278 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3279 wb->nwbx_ssid.ns_ssidlen);
3280 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3282 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3283 freq = wb->nwbx_config.nc_dsconfig / 1000;
3284 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3285 /* Hack ic->ic_curchan to be in sync with the scan result */
3286 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3287 if (ic->ic_curchan == NULL)
3288 ic->ic_curchan = &ic->ic_channels[0];
3290 /* Process extended info from AP */
3291 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3292 frm = (uint8_t *)&wb->nwbx_ies;
3293 efrm = frm + wb->nwbx_ielen;
3294 if (efrm - frm < 12)
3296 sp.tstamp = frm; frm += 8;
3297 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3298 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3300 sp.ies_len = efrm - frm;
3303 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3304 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3306 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3307 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3310 /* Restore the channel after messing with it */
3311 ic->ic_curchan = saved_chan;
3315 ndis_scan_start(struct ieee80211com *ic)
3317 struct ifnet *ifp = ic->ic_ifp;
3318 struct ndis_softc *sc = ifp->if_softc;
3319 struct ieee80211vap *vap;
3320 struct ieee80211_scan_state *ss;
3321 ndis_80211_ssid ssid;
3325 vap = TAILQ_FIRST(&ic->ic_vaps);
3327 if (!NDIS_INITIALIZED(sc)) {
3328 DPRINTF(("%s: scan aborted\n", __func__));
3329 ieee80211_cancel_scan(vap);
3334 bzero((char *)&ssid, len);
3335 if (ss->ss_nssid == 0)
3336 ssid.ns_ssidlen = 1;
3338 /* Perform a directed scan */
3339 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3340 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3343 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3345 DPRINTF(("%s: set ESSID failed\n", __func__));
3348 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3350 DPRINTF(("%s: scan command failed\n", __func__));
3351 ieee80211_cancel_scan(vap);
3354 /* Set a timer to collect the results */
3355 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3359 ndis_set_channel(struct ieee80211com *ic)
3365 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3371 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3373 /* NB: don't try to abort scan; wait for firmware to finish */
3377 ndis_scan_end(struct ieee80211com *ic)
3379 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3381 ndis_scan_results(sc);