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, CALLOUT_MPSAFE);
562 if (sc->ndis_iftype == PCMCIABus) {
563 error = ndis_alloc_amem(sc);
565 device_printf(dev, "failed to allocate "
566 "attribute memory\n");
571 /* Create sysctl registry nodes */
572 ndis_create_sysctls(sc);
574 /* Find the PDO for this device instance. */
576 if (sc->ndis_iftype == PCIBus)
577 pdrv = windrv_lookup(0, "PCI Bus");
578 else if (sc->ndis_iftype == PCMCIABus)
579 pdrv = windrv_lookup(0, "PCCARD Bus");
581 pdrv = windrv_lookup(0, "USB Bus");
582 pdo = windrv_find_pdo(pdrv, dev);
585 * Create a new functional device object for this
586 * device. This is what creates the miniport block
587 * for this device instance.
590 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
591 device_printf(dev, "failed to create FDO!\n");
596 /* Tell the user what version of the API the driver is using. */
597 device_printf(dev, "NDIS API version: %d.%d\n",
598 sc->ndis_chars->nmc_version_major,
599 sc->ndis_chars->nmc_version_minor);
601 /* Do resource conversion. */
602 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
603 ndis_convert_res(sc);
605 sc->ndis_block->nmb_rlist = NULL;
607 /* Install our RX and TX interrupt handlers. */
608 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
609 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
610 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
611 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
612 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
614 /* Override the status handler so we can detect link changes. */
615 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
616 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
618 /* Set up work item handlers. */
619 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
620 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
621 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
622 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623 sc->ndisusb_xferdoneitem =
624 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndisusb_taskitem =
626 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
627 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
629 /* Call driver's init routine. */
630 if (ndis_init_nic(sc)) {
631 device_printf(dev, "init handler failed\n");
637 * Get station address from the driver.
640 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
643 * Figure out how big to make the TX buffer pool.
646 len = sizeof(sc->ndis_maxpkts);
647 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
648 &sc->ndis_maxpkts, &len)) {
649 device_printf(dev, "failed to get max TX packets\n");
655 * If this is a deserialized miniport, we don't have
656 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
658 if (!NDIS_SERIALIZED(sc->ndis_block))
659 sc->ndis_maxpkts = NDIS_TXPKTS;
661 /* Enforce some sanity, just in case. */
663 if (sc->ndis_maxpkts == 0)
664 sc->ndis_maxpkts = 10;
666 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
667 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
669 /* Allocate a pool of ndis_packets for TX encapsulation. */
671 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
672 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
674 if (i != NDIS_STATUS_SUCCESS) {
675 sc->ndis_txpool = NULL;
676 device_printf(dev, "failed to allocate TX packet pool");
681 sc->ndis_txpending = sc->ndis_maxpkts;
684 /* Get supported oid list. */
685 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
687 /* If the NDIS module requested scatter/gather, init maps. */
692 * See if the OID_802_11_CONFIGURATION OID is
693 * supported by this driver. If it is, then this an 802.11
694 * wireless driver, and we should set up media for wireless.
696 for (i = 0; i < sc->ndis_oidcnt; i++)
697 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
703 ifp = if_alloc(IFT_IEEE80211);
705 ifp = if_alloc(IFT_ETHER);
713 /* Check for task offload support. */
714 ndis_probe_offload(sc);
716 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
717 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
718 ifp->if_ioctl = ndis_ioctl;
719 ifp->if_start = ndis_start;
720 ifp->if_init = ndis_init;
721 ifp->if_baudrate = 10000000;
722 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
723 ifp->if_snd.ifq_drv_maxlen = 25;
724 IFQ_SET_READY(&ifp->if_snd);
725 ifp->if_capenable = ifp->if_capabilities;
726 ifp->if_hwassist = sc->ndis_hwassist;
729 if (sc->ndis_80211) {
730 struct ieee80211com *ic = ifp->if_l2com;
731 ndis_80211_rates_ex rates;
732 struct ndis_80211_nettype_list *ntl;
736 callout_init(&sc->ndis_scan_callout, CALLOUT_MPSAFE);
738 ifp->if_ioctl = ndis_ioctl_80211;
740 ic->ic_opmode = IEEE80211_M_STA;
741 ic->ic_phytype = IEEE80211_T_DS;
742 ic->ic_caps = IEEE80211_C_8023ENCAP |
743 IEEE80211_C_STA | IEEE80211_C_IBSS;
744 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
746 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
750 ntl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
751 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
758 for (i = 0; i < ntl->ntl_items; i++) {
759 mode = ndis_nettype_mode(ntl->ntl_type[i]);
761 setbit(ic->ic_modecaps, mode);
762 setbit(&bands, mode);
764 device_printf(dev, "Unknown nettype %d\n",
769 /* Default to 11b channels if the card did not supply any */
771 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
772 setbit(&bands, IEEE80211_MODE_11B);
775 bzero((char *)&rates, len);
776 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
777 (void *)rates, &len);
779 device_printf(dev, "get rates failed: 0x%x\n", r);
781 * Since the supported rates only up to 8 can be supported,
782 * if this is not 802.11b we're just going to be faking it
786 #define TESTSETRATE(x, y) \
789 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
790 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
793 if (i == ic->ic_sup_rates[x].rs_nrates) { \
794 ic->ic_sup_rates[x].rs_rates[i] = (y); \
795 ic->ic_sup_rates[x].rs_nrates++; \
799 #define SETRATE(x, y) \
800 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
802 ic->ic_sup_rates[x].rs_nrates++
804 ic->ic_curmode = IEEE80211_MODE_AUTO;
805 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
806 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
807 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
808 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
809 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
810 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
811 for (i = 0; i < len; i++) {
812 switch (rates[i] & IEEE80211_RATE_VAL) {
818 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
819 /* Lazy-init 802.11b. */
820 setbit(ic->ic_modecaps,
822 ic->ic_sup_rates[IEEE80211_MODE_11B].
825 SETRATE(IEEE80211_MODE_11B, rates[i]);
826 INCRATE(IEEE80211_MODE_11B);
829 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
830 SETRATE(IEEE80211_MODE_11A, rates[i]);
831 INCRATE(IEEE80211_MODE_11A);
833 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
834 SETRATE(IEEE80211_MODE_11G, rates[i]);
835 INCRATE(IEEE80211_MODE_11G);
842 * If the hardware supports 802.11g, it most
843 * likely supports 802.11b and all of the
844 * 802.11b and 802.11g speeds, so maybe we can
845 * just cheat here. Just how in the heck do
846 * we detect turbo modes, though?
848 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
849 TESTSETRATE(IEEE80211_MODE_11B,
850 IEEE80211_RATE_BASIC|2);
851 TESTSETRATE(IEEE80211_MODE_11B,
852 IEEE80211_RATE_BASIC|4);
853 TESTSETRATE(IEEE80211_MODE_11B,
854 IEEE80211_RATE_BASIC|11);
855 TESTSETRATE(IEEE80211_MODE_11B,
856 IEEE80211_RATE_BASIC|22);
858 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
859 TESTSETRATE(IEEE80211_MODE_11G, 48);
860 TESTSETRATE(IEEE80211_MODE_11G, 72);
861 TESTSETRATE(IEEE80211_MODE_11G, 96);
862 TESTSETRATE(IEEE80211_MODE_11G, 108);
864 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
865 TESTSETRATE(IEEE80211_MODE_11A, 48);
866 TESTSETRATE(IEEE80211_MODE_11A, 72);
867 TESTSETRATE(IEEE80211_MODE_11A, 96);
868 TESTSETRATE(IEEE80211_MODE_11A, 108);
872 ieee80211_init_channels(ic, NULL, &bands);
875 * To test for WPA support, we need to see if we can
876 * set AUTHENTICATION_MODE to WPA and read it back
880 arg = NDIS_80211_AUTHMODE_WPA;
881 r = ndis_set_info(sc,
882 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
884 r = ndis_get_info(sc,
885 OID_802_11_AUTHENTICATION_MODE, &arg, &i);
886 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
887 ic->ic_caps |= IEEE80211_C_WPA;
891 * To test for supported ciphers, we set each
892 * available encryption type in descending order.
893 * If ENC3 works, then we have WEP, TKIP and AES.
894 * If only ENC2 works, then we have WEP and TKIP.
895 * If only ENC1 works, then we have just WEP.
898 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
899 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
901 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
902 | IEEE80211_CRYPTO_TKIP
903 | IEEE80211_CRYPTO_AES_CCM;
906 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
907 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
909 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
910 | IEEE80211_CRYPTO_TKIP;
913 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
914 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
916 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
919 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
921 ic->ic_caps |= IEEE80211_C_PMGT;
923 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
925 ic->ic_caps |= IEEE80211_C_TXPMGT;
927 ieee80211_ifattach(ic, eaddr);
928 ic->ic_raw_xmit = ndis_raw_xmit;
929 ic->ic_scan_start = ndis_scan_start;
930 ic->ic_scan_end = ndis_scan_end;
931 ic->ic_set_channel = ndis_set_channel;
932 ic->ic_scan_curchan = ndis_scan_curchan;
933 ic->ic_scan_mindwell = ndis_scan_mindwell;
934 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
935 //ic->ic_bss->ni_chan = ic->ic_bsschan;
936 ic->ic_vap_create = ndis_vap_create;
937 ic->ic_vap_delete = ndis_vap_delete;
938 ic->ic_update_mcast = ndis_update_mcast;
939 ic->ic_update_promisc = ndis_update_promisc;
942 ieee80211_announce(ic);
945 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
947 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
948 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
949 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
950 ifmedia_add(&sc->ifmedia,
951 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
952 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
953 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
954 ether_ifattach(ifp, eaddr);
963 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
966 DPRINTF(("attach done.\n"));
967 /* We're done talking to the NIC for now; halt it. */
969 DPRINTF(("halting done.\n"));
974 static struct ieee80211vap *
975 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
976 enum ieee80211_opmode opmode, int flags,
977 const uint8_t bssid[IEEE80211_ADDR_LEN],
978 const uint8_t mac[IEEE80211_ADDR_LEN])
980 struct ndis_vap *nvp;
981 struct ieee80211vap *vap;
983 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
985 nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap),
986 M_80211_VAP, M_NOWAIT | M_ZERO);
990 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
991 /* override with driver methods */
992 nvp->newstate = vap->iv_newstate;
993 vap->iv_newstate = ndis_newstate;
996 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
997 ic->ic_opmode = opmode;
998 /* install key handing routines */
999 vap->iv_key_set = ndis_add_key;
1000 vap->iv_key_delete = ndis_del_key;
1005 ndis_vap_delete(struct ieee80211vap *vap)
1007 struct ndis_vap *nvp = NDIS_VAP(vap);
1008 struct ieee80211com *ic = vap->iv_ic;
1009 struct ifnet *ifp = ic->ic_ifp;
1010 struct ndis_softc *sc = ifp->if_softc;
1013 callout_drain(&sc->ndis_scan_callout);
1014 ieee80211_vap_detach(vap);
1015 free(nvp, M_80211_VAP);
1019 * Shutdown hardware and free up resources. This can be called any
1020 * time after the mutex has been initialized. It is called in both
1021 * the error case in attach and the normal detach case so it needs
1022 * to be careful about only freeing resources that have actually been
1029 struct ndis_softc *sc;
1033 sc = device_get_softc(dev);
1037 ifp->if_flags &= ~IFF_UP;
1039 if (device_is_attached(dev)) {
1044 ieee80211_ifdetach(ifp->if_l2com);
1046 ether_ifdetach(ifp);
1051 if (sc->ndis_tickitem != NULL)
1052 IoFreeWorkItem(sc->ndis_tickitem);
1053 if (sc->ndis_startitem != NULL)
1054 IoFreeWorkItem(sc->ndis_startitem);
1055 if (sc->ndis_resetitem != NULL)
1056 IoFreeWorkItem(sc->ndis_resetitem);
1057 if (sc->ndis_inputitem != NULL)
1058 IoFreeWorkItem(sc->ndis_inputitem);
1059 if (sc->ndisusb_xferdoneitem != NULL)
1060 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1061 if (sc->ndisusb_taskitem != NULL)
1062 IoFreeWorkItem(sc->ndisusb_taskitem);
1064 bus_generic_detach(dev);
1065 ndis_unload_driver(sc);
1068 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1069 if (sc->ndis_res_io)
1070 bus_release_resource(dev, SYS_RES_IOPORT,
1071 sc->ndis_io_rid, sc->ndis_res_io);
1072 if (sc->ndis_res_mem)
1073 bus_release_resource(dev, SYS_RES_MEMORY,
1074 sc->ndis_mem_rid, sc->ndis_res_mem);
1075 if (sc->ndis_res_altmem)
1076 bus_release_resource(dev, SYS_RES_MEMORY,
1077 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1082 if (sc->ndis_iftype == PCMCIABus)
1086 ndis_destroy_dma(sc);
1088 if (sc->ndis_txarray)
1089 free(sc->ndis_txarray, M_DEVBUF);
1091 if (!sc->ndis_80211)
1092 ifmedia_removeall(&sc->ifmedia);
1094 if (sc->ndis_txpool != NULL)
1095 NdisFreePacketPool(sc->ndis_txpool);
1097 /* Destroy the PDO for this device. */
1099 if (sc->ndis_iftype == PCIBus)
1100 drv = windrv_lookup(0, "PCI Bus");
1101 else if (sc->ndis_iftype == PCMCIABus)
1102 drv = windrv_lookup(0, "PCCARD Bus");
1104 drv = windrv_lookup(0, "USB Bus");
1106 panic("couldn't find driver object");
1107 windrv_destroy_pdo(drv, dev);
1109 if (sc->ndis_iftype == PCIBus)
1110 bus_dma_tag_destroy(sc->ndis_parent_tag);
1119 struct ndis_softc *sc;
1122 sc = device_get_softc(dev);
1126 if (NDIS_INITIALIZED(sc))
1137 struct ndis_softc *sc;
1140 sc = device_get_softc(dev);
1143 if (NDIS_INITIALIZED(sc))
1150 * The following bunch of routines are here to support drivers that
1151 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1152 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1153 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1157 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1158 ndis_handle adapter;
1164 uint32_t lookaheadlen;
1167 ndis_miniport_block *block;
1177 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1181 /* Save the data provided to us so far. */
1183 m->m_len = lookaheadlen + hdrlen;
1184 m->m_pkthdr.len = pktlen + hdrlen;
1186 m_copyback(m, 0, hdrlen, hdr);
1187 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1189 /* Now create a fake NDIS_PACKET to hold the data */
1191 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1193 if (status != NDIS_STATUS_SUCCESS) {
1200 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1208 p->np_private.npp_head = p->np_private.npp_tail = b;
1209 p->np_private.npp_totlen = m->m_pkthdr.len;
1211 /* Save the packet RX context somewhere. */
1212 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1213 priv->nep_ctx = ctx;
1215 if (!NDIS_SERIALIZED(block))
1216 KeAcquireSpinLock(&block->nmb_lock, &irql);
1218 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1220 if (!NDIS_SERIALIZED(block))
1221 KeReleaseSpinLock(&block->nmb_lock, irql);
1225 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1226 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1230 ndis_rxeof_done(adapter)
1231 ndis_handle adapter;
1233 struct ndis_softc *sc;
1234 ndis_miniport_block *block;
1238 /* Schedule transfer/RX of queued packets. */
1240 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1242 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1246 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1249 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1251 ndis_handle adapter;
1255 ndis_miniport_block *block;
1256 struct ndis_softc *sc;
1265 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1268 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1270 l = block->nmb_packetlist.nle_flink;
1271 while(!IsListEmpty(&block->nmb_packetlist)) {
1272 l = RemoveHeadList((&block->nmb_packetlist));
1273 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1274 InitializeListHead((&p->np_list));
1276 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1281 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1283 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1284 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1285 m->m_len, m->m_pkthdr.len - m->m_len);
1287 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1290 * If status is NDIS_STATUS_PENDING, do nothing and
1291 * wait for a callback to the ndis_rxeof_xfr_done()
1295 m->m_len = m->m_pkthdr.len;
1296 m->m_pkthdr.rcvif = ifp;
1298 if (status == NDIS_STATUS_SUCCESS) {
1299 IoFreeMdl(p->np_private.npp_head);
1301 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1302 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1303 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1304 IoQueueWorkItem(sc->ndis_inputitem,
1305 (io_workitem_func)ndis_inputtask_wrap,
1306 WORKQUEUE_CRITICAL, ifp);
1309 if (status == NDIS_STATUS_FAILURE)
1312 /* Advance to next packet */
1313 l = block->nmb_packetlist.nle_flink;
1316 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1320 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1323 ndis_rxeof_xfr_done(adapter, packet, status, len)
1324 ndis_handle adapter;
1325 ndis_packet *packet;
1329 ndis_miniport_block *block;
1330 struct ndis_softc *sc;
1335 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1339 IoFreeMdl(packet->np_private.npp_head);
1340 NdisFreePacket(packet);
1342 if (status != NDIS_STATUS_SUCCESS) {
1347 m->m_len = m->m_pkthdr.len;
1348 m->m_pkthdr.rcvif = ifp;
1349 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1350 _IF_ENQUEUE(&sc->ndis_rxqueue, m);
1351 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1352 IoQueueWorkItem(sc->ndis_inputitem,
1353 (io_workitem_func)ndis_inputtask_wrap,
1354 WORKQUEUE_CRITICAL, ifp);
1357 * A frame has been uploaded: pass the resulting mbuf chain up to
1358 * the higher level protocols.
1360 * When handling received NDIS packets, the 'status' field in the
1361 * out-of-band portion of the ndis_packet has special meaning. In the
1362 * most common case, the underlying NDIS driver will set this field
1363 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1364 * take posession of it. We then change the status field to
1365 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1366 * and that we will return it at some point in the future via the
1367 * return packet handler.
1369 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1370 * this means the driver is running out of packet/buffer resources and
1371 * wants to maintain ownership of the packet. In this case, we have to
1372 * copy the packet data into local storage and let the driver keep the
1376 ndis_rxeof(adapter, packets, pktcnt)
1377 ndis_handle adapter;
1378 ndis_packet **packets;
1381 struct ndis_softc *sc;
1382 ndis_miniport_block *block;
1385 ndis_tcpip_csum *csum;
1387 struct mbuf *m0, *m;
1390 block = (ndis_miniport_block *)adapter;
1391 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1395 * There's a slim chance the driver may indicate some packets
1396 * before we're completely ready to handle them. If we detect this,
1397 * we need to return them to the miniport and ignore them.
1399 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1400 for (i = 0; i < pktcnt; i++) {
1402 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1404 (void)ndis_return_packet(NULL ,p, block);
1410 for (i = 0; i < pktcnt; i++) {
1412 /* Stash the softc here so ptom can use it. */
1414 if (ndis_ptom(&m0, p)) {
1415 device_printf(sc->ndis_dev, "ptom failed\n");
1416 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1417 (void)ndis_return_packet(NULL, p, block);
1420 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1421 m = m_dup(m0, M_NOWAIT);
1423 * NOTE: we want to destroy the mbuf here, but
1424 * we don't actually want to return it to the
1425 * driver via the return packet handler. By
1426 * bumping np_refcnt, we can prevent the
1427 * ndis_return_packet() routine from actually
1437 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1439 m = m_dup(m0, M_NOWAIT);
1440 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1443 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1450 m0->m_pkthdr.rcvif = ifp;
1452 /* Deal with checksum offload. */
1454 if (ifp->if_capenable & IFCAP_RXCSUM &&
1455 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1457 p->np_ext.npe_info[ndis_tcpipcsum_info];
1458 csum = (ndis_tcpip_csum *)&s;
1459 if (csum->u.ntc_rxflags &
1460 NDIS_RXCSUM_IP_PASSED)
1461 m0->m_pkthdr.csum_flags |=
1462 CSUM_IP_CHECKED|CSUM_IP_VALID;
1463 if (csum->u.ntc_rxflags &
1464 (NDIS_RXCSUM_TCP_PASSED |
1465 NDIS_RXCSUM_UDP_PASSED)) {
1466 m0->m_pkthdr.csum_flags |=
1467 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1468 m0->m_pkthdr.csum_data = 0xFFFF;
1472 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1473 _IF_ENQUEUE(&sc->ndis_rxqueue, m0);
1474 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1475 IoQueueWorkItem(sc->ndis_inputitem,
1476 (io_workitem_func)ndis_inputtask_wrap,
1477 WORKQUEUE_CRITICAL, ifp);
1483 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1484 * packets into the stack in order to avoid calling (*ifp->if_input)()
1485 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1486 * 'dispatch level' per-cpu sleep lock).
1489 ndis_inputtask(dobj, arg)
1490 device_object *dobj;
1493 ndis_miniport_block *block;
1495 struct ndis_softc *sc;
1497 struct ieee80211com *ic;
1498 struct ieee80211vap *vap;
1504 vap = TAILQ_FIRST(&ic->ic_vaps);
1505 block = dobj->do_devext;
1507 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1509 _IF_DEQUEUE(&sc->ndis_rxqueue, m);
1512 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1513 if ((sc->ndis_80211 != 0) && (vap != NULL))
1514 vap->iv_deliver_data(vap, vap->iv_bss, m);
1516 (*ifp->if_input)(ifp, m);
1517 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1519 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1523 * A frame was downloaded to the chip. It's safe for us to clean up
1527 ndis_txeof(adapter, packet, status)
1528 ndis_handle adapter;
1529 ndis_packet *packet;
1533 struct ndis_softc *sc;
1534 ndis_miniport_block *block;
1539 block = (ndis_miniport_block *)adapter;
1540 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1544 idx = packet->np_txidx;
1546 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1548 ndis_free_packet(packet);
1552 sc->ndis_txarray[idx] = NULL;
1553 sc->ndis_txpending++;
1555 if (status == NDIS_STATUS_SUCCESS)
1560 sc->ndis_tx_timer = 0;
1561 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1565 IoQueueWorkItem(sc->ndis_startitem,
1566 (io_workitem_func)ndis_starttask_wrap,
1567 WORKQUEUE_CRITICAL, ifp);
1571 ndis_linksts(adapter, status, sbuf, slen)
1572 ndis_handle adapter;
1577 ndis_miniport_block *block;
1578 struct ndis_softc *sc;
1581 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1582 sc->ndis_sts = status;
1584 /* Event list is all full up, drop this one. */
1587 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1592 /* Cache the event. */
1595 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1597 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1602 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1604 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1605 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1606 NDIS_EVTINC(sc->ndis_evtpidx);
1611 ndis_linksts_done(adapter)
1612 ndis_handle adapter;
1614 ndis_miniport_block *block;
1615 struct ndis_softc *sc;
1619 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1622 if (!NDIS_INITIALIZED(sc))
1625 switch (sc->ndis_sts) {
1626 case NDIS_STATUS_MEDIA_CONNECT:
1627 IoQueueWorkItem(sc->ndis_tickitem,
1628 (io_workitem_func)ndis_ticktask_wrap,
1629 WORKQUEUE_CRITICAL, sc);
1630 IoQueueWorkItem(sc->ndis_startitem,
1631 (io_workitem_func)ndis_starttask_wrap,
1632 WORKQUEUE_CRITICAL, ifp);
1634 case NDIS_STATUS_MEDIA_DISCONNECT:
1636 IoQueueWorkItem(sc->ndis_tickitem,
1637 (io_workitem_func)ndis_ticktask_wrap,
1638 WORKQUEUE_CRITICAL, sc);
1649 struct ndis_softc *sc;
1653 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1654 IoQueueWorkItem(sc->ndis_tickitem,
1655 (io_workitem_func)ndis_ticktask_wrap,
1656 WORKQUEUE_CRITICAL, sc);
1657 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1660 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1661 sc->ifp->if_oerrors++;
1662 device_printf(sc->ndis_dev, "watchdog timeout\n");
1664 IoQueueWorkItem(sc->ndis_resetitem,
1665 (io_workitem_func)ndis_resettask_wrap,
1666 WORKQUEUE_CRITICAL, sc);
1667 IoQueueWorkItem(sc->ndis_startitem,
1668 (io_workitem_func)ndis_starttask_wrap,
1669 WORKQUEUE_CRITICAL, sc->ifp);
1672 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1676 ndis_ticktask(d, xsc)
1680 struct ndis_softc *sc;
1681 struct ieee80211com *ic;
1682 struct ieee80211vap *vap;
1683 ndis_checkforhang_handler hangfunc;
1687 ic = sc->ifp->if_l2com;
1688 vap = TAILQ_FIRST(&ic->ic_vaps);
1691 if (!NDIS_INITIALIZED(sc)) {
1697 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1699 if (hangfunc != NULL) {
1700 rval = MSCALL1(hangfunc,
1701 sc->ndis_block->nmb_miniportadapterctx);
1709 if (sc->ndis_link == 0 &&
1710 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1713 if ((sc->ndis_80211 != 0) && (vap != NULL)) {
1714 ndis_getstate_80211(sc);
1715 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1718 if_link_state_change(sc->ifp, LINK_STATE_UP);
1721 if (sc->ndis_link == 1 &&
1722 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1725 if ((sc->ndis_80211 != 0) && (vap != NULL))
1726 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1728 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1735 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1737 bus_dma_segment_t *segs;
1743 struct ndis_sc_list *sclist;
1746 if (error || arg == NULL)
1751 sclist->nsl_frags = nseg;
1753 for (i = 0; i < nseg; i++) {
1754 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1755 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1760 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1761 const struct ieee80211_bpf_params *params)
1763 /* no support; just discard */
1765 ieee80211_free_node(ni);
1770 ndis_update_mcast(struct ifnet *ifp)
1772 struct ndis_softc *sc = ifp->if_softc;
1778 ndis_update_promisc(struct ifnet *ifp)
1784 ndis_starttask(d, arg)
1792 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1797 * Main transmit routine. To make NDIS drivers happy, we need to
1798 * transform mbuf chains into NDIS packets and feed them to the
1799 * send packet routines. Most drivers allow you to send several
1800 * packets at once (up to the maxpkts limit). Unfortunately, rather
1801 * that accepting them in the form of a linked list, they expect
1802 * a contiguous array of pointers to packets.
1804 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1805 * we need to perform busdma work here. Those that use map registers
1806 * will do the mapping themselves on a buffer by buffer basis.
1812 struct ndis_softc *sc;
1813 struct mbuf *m = NULL;
1814 ndis_packet **p0 = NULL, *p = NULL;
1815 ndis_tcpip_csum *csum;
1816 int pcnt = 0, status;
1821 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1826 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1828 while(sc->ndis_txpending) {
1829 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1833 NdisAllocatePacket(&status,
1834 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1836 if (status != NDIS_STATUS_SUCCESS)
1839 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1840 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1846 * Save pointer to original mbuf
1847 * so we can free it later.
1850 p = sc->ndis_txarray[sc->ndis_txidx];
1851 p->np_txidx = sc->ndis_txidx;
1853 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1856 * Do scatter/gather processing, if driver requested it.
1859 bus_dmamap_load_mbuf(sc->ndis_ttag,
1860 sc->ndis_tmaps[sc->ndis_txidx], m,
1861 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1862 bus_dmamap_sync(sc->ndis_ttag,
1863 sc->ndis_tmaps[sc->ndis_txidx],
1864 BUS_DMASYNC_PREREAD);
1865 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1868 /* Handle checksum offload. */
1870 if (ifp->if_capenable & IFCAP_TXCSUM &&
1871 m->m_pkthdr.csum_flags) {
1872 csum = (ndis_tcpip_csum *)
1873 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1874 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1875 if (m->m_pkthdr.csum_flags & CSUM_IP)
1876 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1877 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1878 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1879 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1880 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1881 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1885 sc->ndis_txpending--;
1890 * If there's a BPF listener, bounce a copy of this frame
1893 if (!sc->ndis_80211) /* XXX handle 80211 */
1897 * The array that p0 points to must appear contiguous,
1898 * so we must not wrap past the end of sc->ndis_txarray[].
1899 * If it looks like we're about to wrap, break out here
1900 * so the this batch of packets can be transmitted, then
1901 * wait for txeof to ask us to send the rest.
1903 if (sc->ndis_txidx == 0)
1912 if (sc->ndis_txpending == 0)
1913 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1916 * Set a timeout in case the chip goes out to lunch.
1918 sc->ndis_tx_timer = 5;
1923 * According to NDIS documentation, if a driver exports
1924 * a MiniportSendPackets() routine, we prefer that over
1925 * a MiniportSend() routine (which sends just a single
1928 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1929 ndis_send_packets(sc, p0, pcnt);
1931 ndis_send_packet(sc, p);
1940 struct ndis_softc *sc = xsc;
1941 struct ifnet *ifp = sc->ifp;
1942 struct ieee80211com *ic = ifp->if_l2com;
1946 * Avoid reintializing the link unnecessarily.
1947 * This should be dealt with in a better way by
1948 * fixing the upper layer modules so they don't
1949 * call ifp->if_init() quite as often.
1955 * Cancel pending I/O and free all RX/TX buffers.
1959 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
1960 error = ndis_init_nic(sc);
1962 device_printf(sc->ndis_dev,
1963 "failed to initialize the device: %d\n", error);
1968 /* Init our MAC address */
1970 /* Program the packet filter */
1972 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1974 if (ifp->if_flags & IFF_BROADCAST)
1975 sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1977 if (ifp->if_flags & IFF_PROMISC)
1978 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1980 len = sizeof(sc->ndis_filter);
1982 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1983 &sc->ndis_filter, &len);
1986 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
1993 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
1996 * Program the multicast filter, if necessary.
2000 /* Setup task offload. */
2001 ndis_set_offload(sc);
2006 sc->ndis_txpending = sc->ndis_maxpkts;
2009 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2011 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2012 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2013 sc->ndis_tx_timer = 0;
2016 * Some drivers don't set this value. The NDIS spec says
2017 * the default checkforhang timeout is "approximately 2
2018 * seconds." We use 3 seconds, because it seems for some
2019 * drivers, exactly 2 seconds is too fast.
2021 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2022 sc->ndis_block->nmb_checkforhangsecs = 3;
2024 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2025 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2028 /* XXX force handling */
2030 ieee80211_start_all(ic); /* start all vap's */
2034 * Set media options.
2037 ndis_ifmedia_upd(ifp)
2040 struct ndis_softc *sc;
2044 if (NDIS_INITIALIZED(sc))
2051 * Report current media status.
2054 ndis_ifmedia_sts(ifp, ifmr)
2056 struct ifmediareq *ifmr;
2058 struct ndis_softc *sc;
2059 uint32_t media_info;
2060 ndis_media_state linkstate;
2063 ifmr->ifm_status = IFM_AVALID;
2064 ifmr->ifm_active = IFM_ETHER;
2067 if (!NDIS_INITIALIZED(sc))
2070 len = sizeof(linkstate);
2071 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2072 (void *)&linkstate, &len);
2074 len = sizeof(media_info);
2075 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2076 (void *)&media_info, &len);
2078 if (linkstate == nmc_connected)
2079 ifmr->ifm_status |= IFM_ACTIVE;
2081 switch (media_info) {
2083 ifmr->ifm_active |= IFM_10_T;
2086 ifmr->ifm_active |= IFM_100_TX;
2089 ifmr->ifm_active |= IFM_1000_T;
2092 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2098 ndis_set_cipher(sc, cipher)
2099 struct ndis_softc *sc;
2102 struct ieee80211com *ic;
2106 ic = sc->ifp->if_l2com;
2110 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2111 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2113 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2116 if (cipher == WPA_CSE_TKIP) {
2117 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2119 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2122 if (cipher == WPA_CSE_CCMP) {
2123 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2125 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2128 DPRINTF(("Setting cipher to %d\n", arg));
2130 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2135 /* Check that the cipher was set correctly. */
2138 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2140 if (rval != 0 || arg != save)
2147 * WPA is hairy to set up. Do the work in a separate routine
2148 * so we don't clutter the setstate function too much.
2149 * Important yet undocumented fact: first we have to set the
2150 * authentication mode, _then_ we enable the ciphers. If one
2151 * of the WPA authentication modes isn't enabled, the driver
2152 * might not permit the TKIP or AES ciphers to be selected.
2155 ndis_set_wpa(sc, ie, ielen)
2156 struct ndis_softc *sc;
2160 struct ieee80211_ie_wpa *w;
2167 * Apparently, the only way for us to know what ciphers
2168 * and key management/authentication mode to use is for
2169 * us to inspect the optional information element (IE)
2170 * stored in the 802.11 state machine. This IE should be
2171 * supplied by the WPA supplicant.
2174 w = (struct ieee80211_ie_wpa *)ie;
2176 /* Check for the right kind of IE. */
2177 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2178 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2182 /* Skip over the ucast cipher OIDs. */
2183 pos = (char *)&w->wpa_uciphers[0];
2184 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2186 /* Skip over the authmode count. */
2187 pos += sizeof(u_int16_t);
2190 * Check for the authentication modes. I'm
2191 * pretty sure there's only supposed to be one.
2194 n = (struct ndis_ie *)pos;
2195 if (n->ni_val == WPA_ASE_NONE)
2196 arg = NDIS_80211_AUTHMODE_WPANONE;
2198 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2199 arg = NDIS_80211_AUTHMODE_WPA;
2201 if (n->ni_val == WPA_ASE_8021X_PSK)
2202 arg = NDIS_80211_AUTHMODE_WPAPSK;
2204 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2206 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2209 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2211 /* Now configure the desired ciphers. */
2213 /* First, set up the multicast group cipher. */
2214 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2216 if (ndis_set_cipher(sc, n->ni_val))
2219 /* Now start looking around for the unicast ciphers. */
2220 pos = (char *)&w->wpa_uciphers[0];
2221 n = (struct ndis_ie *)pos;
2223 for (i = 0; i < w->wpa_uciphercnt; i++) {
2224 if (ndis_set_cipher(sc, n->ni_val))
2233 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2235 struct ieee80211vap *vap = ifp->if_softc;
2236 struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2240 if (!NDIS_INITIALIZED(sc))
2243 len = sizeof(txrate);
2244 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2245 vap->iv_bss->ni_txrate = txrate / 5000;
2246 ieee80211_media_status(ifp, imr);
2250 ndis_setstate_80211(sc)
2251 struct ndis_softc *sc;
2253 struct ieee80211com *ic;
2254 struct ieee80211vap *vap;
2255 ndis_80211_macaddr bssid;
2256 ndis_80211_config config;
2263 vap = TAILQ_FIRST(&ic->ic_vaps);
2265 if (!NDIS_INITIALIZED(sc)) {
2266 DPRINTF(("%s: NDIS not initialized\n", __func__));
2270 /* Disassociate and turn off radio. */
2273 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2275 /* Set network infrastructure mode. */
2278 if (ic->ic_opmode == IEEE80211_M_IBSS)
2279 arg = NDIS_80211_NET_INFRA_IBSS;
2281 arg = NDIS_80211_NET_INFRA_BSS;
2283 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2286 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2288 /* Set power management */
2290 if (vap->iv_flags & IEEE80211_F_PMGTON)
2291 arg = NDIS_80211_POWERMODE_FAST_PSP;
2293 arg = NDIS_80211_POWERMODE_CAM;
2294 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2297 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2298 ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2299 arg = dBm2mW[ic->ic_txpowlimit];
2301 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2305 * Default encryption mode to off, authentication
2306 * to open and privacy to 'accept everything.'
2309 arg = NDIS_80211_WEPSTAT_DISABLED;
2310 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2313 arg = NDIS_80211_AUTHMODE_OPEN;
2314 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2317 * Note that OID_802_11_PRIVACY_FILTER is optional:
2318 * not all drivers implement it.
2321 arg = NDIS_80211_PRIVFILT_8021XWEP;
2322 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2324 len = sizeof(config);
2325 bzero((char *)&config, len);
2326 config.nc_length = len;
2327 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2328 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2331 * Some drivers expect us to initialize these values, so
2332 * provide some defaults.
2335 if (config.nc_beaconperiod == 0)
2336 config.nc_beaconperiod = 100;
2337 if (config.nc_atimwin == 0)
2338 config.nc_atimwin = 100;
2339 if (config.nc_fhconfig.ncf_dwelltime == 0)
2340 config.nc_fhconfig.ncf_dwelltime = 200;
2341 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2344 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2345 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2346 IEEE80211_CHAN_5GHZ;
2347 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2348 config.nc_dsconfig =
2349 ic->ic_bsschan->ic_freq * 1000;
2350 len = sizeof(config);
2351 config.nc_length = len;
2352 config.nc_fhconfig.ncf_length =
2353 sizeof(ndis_80211_config_fh);
2354 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2355 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2358 device_printf(sc->ndis_dev, "couldn't change "
2359 "DS config to %ukHz: %d\n",
2360 config.nc_dsconfig, rval);
2363 device_printf(sc->ndis_dev, "couldn't retrieve "
2364 "channel info: %d\n", rval);
2366 /* Set the BSSID to our value so the driver doesn't associate */
2367 len = IEEE80211_ADDR_LEN;
2368 bcopy(IF_LLADDR(ifp), bssid, len);
2369 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2370 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2372 device_printf(sc->ndis_dev,
2373 "setting BSSID failed: %d\n", rval);
2377 ndis_auth_and_assoc(sc, vap)
2378 struct ndis_softc *sc;
2379 struct ieee80211vap *vap;
2381 struct ieee80211com *ic;
2382 struct ieee80211_node *ni;
2383 ndis_80211_ssid ssid;
2384 ndis_80211_macaddr bssid;
2386 int i, rval = 0, len, error;
2394 if (!NDIS_INITIALIZED(sc)) {
2395 DPRINTF(("%s: NDIS not initialized\n", __func__));
2400 ndis_setstate_80211(sc);
2402 /* Set network infrastructure mode. */
2405 if (vap->iv_opmode == IEEE80211_M_IBSS)
2406 arg = NDIS_80211_NET_INFRA_IBSS;
2408 arg = NDIS_80211_NET_INFRA_BSS;
2410 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2413 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2415 /* Set RTS threshold */
2418 arg = vap->iv_rtsthreshold;
2419 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2421 /* Set fragmentation threshold */
2424 arg = vap->iv_fragthreshold;
2425 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2429 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2430 !(vap->iv_flags & IEEE80211_F_WPA)) {
2433 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2435 arg = NDIS_80211_AUTHMODE_SHARED;
2436 DPRINTF(("Setting shared auth\n"));
2437 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2440 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2441 if (vap->iv_nw_keys[i].wk_keylen) {
2442 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2443 IEEE80211_CIPHER_WEP)
2445 bzero((char *)&wep, sizeof(wep));
2446 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2449 * 5, 13 and 16 are the only valid
2450 * key lengths. Anything in between
2451 * will be zero padded out to the
2452 * next highest boundary.
2454 if (vap->iv_nw_keys[i].wk_keylen < 5)
2456 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2457 vap->iv_nw_keys[i].wk_keylen < 13)
2459 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2460 vap->iv_nw_keys[i].wk_keylen < 16)
2464 wep.nw_length = (sizeof(uint32_t) * 3)
2466 if (i == vap->iv_def_txkey)
2467 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2468 bcopy(vap->iv_nw_keys[i].wk_key,
2469 wep.nw_keydata, wep.nw_length);
2471 DPRINTF(("Setting WEP key %d\n", i));
2472 rval = ndis_set_info(sc,
2473 OID_802_11_ADD_WEP, &wep, &len);
2475 device_printf(sc->ndis_dev,
2476 "set wepkey failed: %d\n", rval);
2481 DPRINTF(("Setting WEP on\n"));
2482 arg = NDIS_80211_WEPSTAT_ENABLED;
2484 rval = ndis_set_info(sc,
2485 OID_802_11_WEP_STATUS, &arg, &len);
2487 device_printf(sc->ndis_dev,
2488 "enable WEP failed: %d\n", rval);
2489 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2490 arg = NDIS_80211_PRIVFILT_8021XWEP;
2492 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2496 OID_802_11_PRIVACY_FILTER, &arg, &len);
2501 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2502 vap->iv_appie_assocreq != NULL) {
2503 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2504 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2506 device_printf(sc->ndis_dev, "WPA setup failed\n");
2510 /* Set network type. */
2514 switch (vap->iv_curmode) {
2515 case IEEE80211_MODE_11A:
2516 arg = NDIS_80211_NETTYPE_11OFDM5;
2518 case IEEE80211_MODE_11B:
2519 arg = NDIS_80211_NETTYPE_11DS;
2521 case IEEE80211_MODE_11G:
2522 arg = NDIS_80211_NETTYPE_11OFDM24;
2525 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2530 DPRINTF(("Setting network type to %d\n", arg));
2532 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2535 device_printf(sc->ndis_dev,
2536 "set nettype failed: %d\n", rval);
2541 * If the user selected a specific BSSID, try
2542 * to use that one. This is useful in the case where
2543 * there are several APs in range with the same network
2544 * name. To delete the BSSID, we use the broadcast
2545 * address as the BSSID.
2546 * Note that some drivers seem to allow setting a BSSID
2547 * in ad-hoc mode, which has the effect of forcing the
2548 * NIC to create an ad-hoc cell with a specific BSSID,
2549 * instead of a randomly chosen one. However, the net80211
2550 * code makes the assumtion that the BSSID setting is invalid
2551 * when you're in ad-hoc mode, so we don't allow that here.
2554 len = IEEE80211_ADDR_LEN;
2555 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2556 vap->iv_opmode != IEEE80211_M_IBSS)
2557 bcopy(ni->ni_bssid, bssid, len);
2559 bcopy(ifp->if_broadcastaddr, bssid, len);
2561 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2562 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2564 device_printf(sc->ndis_dev,
2565 "setting BSSID failed: %d\n", rval);
2567 /* Set SSID -- always do this last. */
2570 if (ndis_debug > 0) {
2571 printf("Setting ESSID to ");
2572 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2578 bzero((char *)&ssid, len);
2579 ssid.ns_ssidlen = ni->ni_esslen;
2580 if (ssid.ns_ssidlen == 0) {
2581 ssid.ns_ssidlen = 1;
2583 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2585 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2588 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2594 ndis_get_bssid_list(sc, bl)
2595 struct ndis_softc *sc;
2596 ndis_80211_bssid_list_ex **bl;
2600 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2601 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2605 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2606 if (error == ENOSPC) {
2607 free(*bl, M_DEVBUF);
2608 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2612 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2615 DPRINTF(("%s: failed to read\n", __func__));
2616 free(*bl, M_DEVBUF);
2624 ndis_get_assoc(sc, assoc)
2625 struct ndis_softc *sc;
2626 ndis_wlan_bssid_ex **assoc;
2628 struct ifnet *ifp = sc->ifp;
2629 struct ieee80211com *ic = ifp->if_l2com;
2630 struct ieee80211vap *vap;
2631 struct ieee80211_node *ni;
2632 ndis_80211_bssid_list_ex *bl;
2633 ndis_wlan_bssid_ex *bs;
2634 ndis_80211_macaddr bssid;
2640 len = sizeof(bssid);
2641 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2643 device_printf(sc->ndis_dev, "failed to get bssid\n");
2647 vap = TAILQ_FIRST(&ic->ic_vaps);
2650 error = ndis_get_bssid_list(sc, &bl);
2654 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2655 for (i = 0; i < bl->nblx_items; i++) {
2656 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2657 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2658 if (*assoc == NULL) {
2662 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2664 if (ic->ic_opmode == IEEE80211_M_STA)
2665 ni->ni_associd = 1 | 0xc000; /* fake associd */
2668 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2676 ndis_getstate_80211(sc)
2677 struct ndis_softc *sc;
2679 struct ieee80211com *ic;
2680 struct ieee80211vap *vap;
2681 struct ieee80211_node *ni;
2682 ndis_wlan_bssid_ex *bs;
2683 int rval, len, i = 0;
2690 vap = TAILQ_FIRST(&ic->ic_vaps);
2693 if (!NDIS_INITIALIZED(sc))
2696 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2699 /* We're associated, retrieve info on the current bssid. */
2700 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2701 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2702 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2704 /* Get SSID from current association info. */
2705 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2706 bs->nwbx_ssid.ns_ssidlen);
2707 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2709 if (ic->ic_caps & IEEE80211_C_PMGT) {
2711 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2714 device_printf(sc->ndis_dev,
2715 "get power mode failed: %d\n", rval);
2716 if (arg == NDIS_80211_POWERMODE_CAM)
2717 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2719 vap->iv_flags |= IEEE80211_F_PMGTON;
2723 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2725 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2726 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2727 if (dBm2mW[i] >= arg)
2729 ic->ic_txpowlimit = i;
2733 * Use the current association information to reflect
2734 * what channel we're on.
2736 ic->ic_curchan = ieee80211_find_channel(ic,
2737 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2738 if (ic->ic_curchan == NULL)
2739 ic->ic_curchan = &ic->ic_channels[0];
2740 ni->ni_chan = ic->ic_curchan;
2741 ic->ic_bsschan = ic->ic_curchan;
2746 * Determine current authentication mode.
2749 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2751 device_printf(sc->ndis_dev,
2752 "get authmode status failed: %d\n", rval);
2754 vap->iv_flags &= ~IEEE80211_F_WPA;
2756 case NDIS_80211_AUTHMODE_OPEN:
2757 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2759 case NDIS_80211_AUTHMODE_SHARED:
2760 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2762 case NDIS_80211_AUTHMODE_AUTO:
2763 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2765 case NDIS_80211_AUTHMODE_WPA:
2766 case NDIS_80211_AUTHMODE_WPAPSK:
2767 case NDIS_80211_AUTHMODE_WPANONE:
2768 ni->ni_authmode = IEEE80211_AUTH_WPA;
2769 vap->iv_flags |= IEEE80211_F_WPA1;
2771 case NDIS_80211_AUTHMODE_WPA2:
2772 case NDIS_80211_AUTHMODE_WPA2PSK:
2773 ni->ni_authmode = IEEE80211_AUTH_WPA;
2774 vap->iv_flags |= IEEE80211_F_WPA2;
2777 ni->ni_authmode = IEEE80211_AUTH_NONE;
2783 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2786 device_printf(sc->ndis_dev,
2787 "get wep status failed: %d\n", rval);
2789 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2790 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2792 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2796 ndis_ioctl(ifp, command, data)
2801 struct ndis_softc *sc = ifp->if_softc;
2802 struct ifreq *ifr = (struct ifreq *) data;
2809 if (ifp->if_flags & IFF_UP) {
2810 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);
2819 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2820 !(ifp->if_flags & IFF_PROMISC) &&
2821 sc->ndis_if_flags & IFF_PROMISC) {
2823 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2824 i = sizeof(sc->ndis_filter);
2825 error = ndis_set_info(sc,
2826 OID_GEN_CURRENT_PACKET_FILTER,
2827 &sc->ndis_filter, &i);
2831 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2834 sc->ndis_if_flags = ifp->if_flags;
2844 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2847 ifp->if_capenable = ifr->ifr_reqcap;
2848 if (ifp->if_capenable & IFCAP_TXCSUM)
2849 ifp->if_hwassist = sc->ndis_hwassist;
2851 ifp->if_hwassist = 0;
2852 ndis_set_offload(sc);
2855 error = ether_ioctl(ifp, command, data);
2859 /*NDIS_UNLOCK(sc);*/
2865 ndis_ioctl_80211(ifp, command, data)
2870 struct ndis_softc *sc = ifp->if_softc;
2871 struct ieee80211com *ic = ifp->if_l2com;
2872 struct ifreq *ifr = (struct ifreq *) data;
2873 struct ndis_oid_data oid;
2874 struct ndis_evt evt;
2881 if (ifp->if_flags & IFF_UP) {
2882 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
2885 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2888 sc->ndis_if_flags = ifp->if_flags;
2890 /*NDIS_UNLOCK(sc);*/
2893 if ((error = priv_check(curthread, PRIV_DRIVER)))
2895 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2898 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2899 if (oidbuf == NULL) {
2903 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2905 free(oidbuf, M_TEMP);
2908 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2910 free(oidbuf, M_TEMP);
2913 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2915 free(oidbuf, M_TEMP);
2918 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2919 free(oidbuf, M_TEMP);
2922 if ((error = priv_check(curthread, PRIV_DRIVER)))
2924 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2927 oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
2928 if (oidbuf == NULL) {
2932 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2934 free(oidbuf, M_TEMP);
2937 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2939 free(oidbuf, M_TEMP);
2942 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
2944 free(oidbuf, M_TEMP);
2947 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
2948 free(oidbuf, M_TEMP);
2950 case SIOCGPRIVATE_0:
2951 if ((error = priv_check(curthread, PRIV_DRIVER)))
2954 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2959 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2964 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2969 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
2970 ifr->ifr_data, sizeof(uint32_t) * 2);
2975 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2976 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
2977 ifr->ifr_data + (sizeof(uint32_t) * 2),
2978 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
2983 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
2984 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
2986 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
2987 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
2988 NDIS_EVTINC(sc->ndis_evtcidx);
2992 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
2995 error = ether_ioctl(ifp, command, data);
3005 ndis_del_key(vap, key)
3006 struct ieee80211vap *vap;
3007 const struct ieee80211_key *key;
3009 struct ndis_softc *sc;
3010 ndis_80211_key rkey;
3013 sc = vap->iv_ic->ic_ifp->if_softc;
3015 bzero((char *)&rkey, sizeof(rkey));
3019 rkey.nk_keyidx = key->wk_keyix;
3021 bcopy(vap->iv_ifp->if_broadcastaddr,
3022 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3024 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3033 * In theory this could be called for any key, but we'll
3034 * only use it for WPA TKIP or AES keys. These need to be
3035 * set after initial authentication with the AP.
3038 ndis_add_key(vap, key, mac)
3039 struct ieee80211vap *vap;
3040 const struct ieee80211_key *key;
3041 const uint8_t mac[IEEE80211_ADDR_LEN];
3043 struct ndis_softc *sc;
3045 ndis_80211_key rkey;
3048 ifp = vap->iv_ic->ic_ifp;
3051 switch (key->wk_cipher->ic_cipher) {
3052 case IEEE80211_CIPHER_TKIP:
3054 len = sizeof(ndis_80211_key);
3055 bzero((char *)&rkey, sizeof(rkey));
3058 rkey.nk_keylen = key->wk_keylen;
3060 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3061 rkey.nk_keylen += 16;
3063 /* key index - gets weird in NDIS */
3065 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3066 rkey.nk_keyidx = key->wk_keyix;
3070 if (key->wk_flags & IEEE80211_KEY_XMIT)
3071 rkey.nk_keyidx |= 1 << 31;
3073 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3074 bcopy(ifp->if_broadcastaddr,
3075 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3077 bcopy(vap->iv_bss->ni_bssid,
3078 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3080 rkey.nk_keyidx |= 1 << 30;
3083 /* need to set bit 29 based on keyrsc */
3084 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3087 rkey.nk_keyidx |= 1 << 29;
3089 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3090 bcopy(key->wk_key, rkey.nk_keydata, 16);
3091 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3092 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3094 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3096 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3098 case IEEE80211_CIPHER_WEP:
3102 * I don't know how to set up keys for the AES
3103 * cipher yet. Is it the same as TKIP?
3105 case IEEE80211_CIPHER_AES_CCM:
3111 /* We need to return 1 for success, 0 for failure. */
3120 ndis_resettask(d, arg)
3124 struct ndis_softc *sc;
3131 * Stop the adapter and free any mbufs allocated to the
3136 struct ndis_softc *sc;
3142 callout_drain(&sc->ndis_stat_callout);
3145 sc->ndis_tx_timer = 0;
3147 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3150 if (sc->ndis_iftype != PNPBus ||
3151 (sc->ndis_iftype == PNPBus &&
3152 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3157 for (i = 0; i < NDIS_EVENTS; i++) {
3158 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3159 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3160 sc->ndis_evt[i].ne_buf = NULL;
3162 sc->ndis_evt[i].ne_sts = 0;
3163 sc->ndis_evt[i].ne_len = 0;
3165 sc->ndis_evtcidx = 0;
3166 sc->ndis_evtpidx = 0;
3171 * Stop all chip I/O so that the kernel's probe routines don't
3172 * get confused by errant DMAs when rebooting.
3178 struct ndis_softc *sc;
3180 sc = device_get_softc(dev);
3185 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3187 struct ndis_vap *nvp = NDIS_VAP(vap);
3188 struct ieee80211com *ic = vap->iv_ic;
3189 struct ifnet *ifp = ic->ic_ifp;
3190 struct ndis_softc *sc = ifp->if_softc;
3191 enum ieee80211_state ostate;
3193 DPRINTF(("%s: %s -> %s\n", __func__,
3194 ieee80211_state_name[vap->iv_state],
3195 ieee80211_state_name[nstate]));
3197 ostate = vap->iv_state;
3198 vap->iv_state = nstate;
3201 /* pass on to net80211 */
3202 case IEEE80211_S_INIT:
3203 case IEEE80211_S_SCAN:
3204 return nvp->newstate(vap, nstate, arg);
3205 case IEEE80211_S_ASSOC:
3206 if (ostate != IEEE80211_S_AUTH) {
3207 IEEE80211_UNLOCK(ic);
3208 ndis_auth_and_assoc(sc, vap);
3212 case IEEE80211_S_AUTH:
3213 IEEE80211_UNLOCK(ic);
3214 ndis_auth_and_assoc(sc, vap);
3215 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3216 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3226 ndis_scan(void *arg)
3228 struct ieee80211vap *vap = arg;
3230 ieee80211_scan_done(vap);
3234 ndis_scan_results(struct ndis_softc *sc)
3236 struct ieee80211com *ic;
3237 struct ieee80211vap *vap;
3238 ndis_80211_bssid_list_ex *bl;
3239 ndis_wlan_bssid_ex *wb;
3240 struct ieee80211_scanparams sp;
3241 struct ieee80211_frame wh;
3242 struct ieee80211_channel *saved_chan;
3244 int rssi, noise, freq, chanflag;
3245 uint8_t ssid[2+IEEE80211_NWID_LEN];
3246 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3247 uint8_t *frm, *efrm;
3249 ic = sc->ifp->if_l2com;
3250 vap = TAILQ_FIRST(&ic->ic_vaps);
3251 saved_chan = ic->ic_curchan;
3254 if (ndis_get_bssid_list(sc, &bl))
3257 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3258 wb = &bl->nblx_bssid[0];
3259 for (i = 0; i < bl->nblx_items; i++) {
3260 memset(&sp, 0, sizeof(sp));
3262 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3263 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3264 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3265 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3266 if (wb->nwbx_privacy)
3267 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3268 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3269 switch (wb->nwbx_netinfra) {
3270 case NDIS_80211_NET_INFRA_IBSS:
3271 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3273 case NDIS_80211_NET_INFRA_BSS:
3274 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3277 sp.rates = &rates[0];
3278 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3279 /* XXX - check units */
3280 if (wb->nwbx_supportedrates[j] == 0)
3283 wb->nwbx_supportedrates[j] & 0x7f;
3286 sp.ssid = (uint8_t *)&ssid[0];
3287 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3288 wb->nwbx_ssid.ns_ssidlen);
3289 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3291 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3292 freq = wb->nwbx_config.nc_dsconfig / 1000;
3293 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3294 /* Hack ic->ic_curchan to be in sync with the scan result */
3295 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3296 if (ic->ic_curchan == NULL)
3297 ic->ic_curchan = &ic->ic_channels[0];
3299 /* Process extended info from AP */
3300 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3301 frm = (uint8_t *)&wb->nwbx_ies;
3302 efrm = frm + wb->nwbx_ielen;
3303 if (efrm - frm < 12)
3305 sp.tstamp = frm; frm += 8;
3306 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3307 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3309 sp.ies_len = efrm - frm;
3312 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3313 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3315 ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise);
3316 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3319 /* Restore the channel after messing with it */
3320 ic->ic_curchan = saved_chan;
3324 ndis_scan_start(struct ieee80211com *ic)
3326 struct ifnet *ifp = ic->ic_ifp;
3327 struct ndis_softc *sc = ifp->if_softc;
3328 struct ieee80211vap *vap;
3329 struct ieee80211_scan_state *ss;
3330 ndis_80211_ssid ssid;
3334 vap = TAILQ_FIRST(&ic->ic_vaps);
3336 if (!NDIS_INITIALIZED(sc)) {
3337 DPRINTF(("%s: scan aborted\n", __func__));
3338 ieee80211_cancel_scan(vap);
3343 bzero((char *)&ssid, len);
3344 if (ss->ss_nssid == 0)
3345 ssid.ns_ssidlen = 1;
3347 /* Perform a directed scan */
3348 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3349 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3352 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3354 DPRINTF(("%s: set ESSID failed\n", __func__));
3357 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3359 DPRINTF(("%s: scan command failed\n", __func__));
3360 ieee80211_cancel_scan(vap);
3363 /* Set a timer to collect the results */
3364 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3368 ndis_set_channel(struct ieee80211com *ic)
3374 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3380 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3382 /* NB: don't try to abort scan; wait for firmware to finish */
3386 ndis_scan_end(struct ieee80211com *ic)
3388 struct ndis_softc *sc = ic->ic_ifp->if_softc;
3390 ndis_scan_results(sc);