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>
53 #include <sys/limits.h>
56 #include <net/if_var.h>
57 #include <net/if_arp.h>
58 #include <net/ethernet.h>
59 #include <net/if_dl.h>
60 #include <net/if_media.h>
61 #include <net/if_types.h>
62 #include <net/route.h>
66 #include <machine/bus.h>
67 #include <machine/resource.h>
71 #include <net80211/ieee80211_var.h>
72 #include <net80211/ieee80211_ioctl.h>
73 #include <net80211/ieee80211_regdomain.h>
75 #include <dev/pci/pcireg.h>
76 #include <dev/pci/pcivar.h>
77 #include <dev/usb/usb.h>
78 #include <dev/usb/usbdi.h>
80 #include <compat/ndis/pe_var.h>
81 #include <compat/ndis/cfg_var.h>
82 #include <compat/ndis/resource_var.h>
83 #include <compat/ndis/ntoskrnl_var.h>
84 #include <compat/ndis/hal_var.h>
85 #include <compat/ndis/ndis_var.h>
86 #include <compat/ndis/usbd_var.h>
87 #include <dev/if_ndis/if_ndisvar.h>
91 #define DPRINTF(x) do { if (ndis_debug > 0) printf x; } while (0)
93 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
94 "if_ndis debug level");
99 SYSCTL_DECL(_hw_ndisusb);
100 int ndisusb_halt = 1;
101 SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
102 "Halt NDIS USB driver when it's attached");
104 /* 0 - 30 dBm to mW conversion table */
105 static const uint16_t dBm2mW[] = {
106 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
107 3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
108 10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
109 32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
110 100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
111 316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
115 MODULE_DEPEND(ndis, ether, 1, 1, 1);
116 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
117 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
119 MODULE_VERSION(ndis, 1);
121 int ndis_attach (device_t);
122 int ndis_detach (device_t);
123 int ndis_suspend (device_t);
124 int ndis_resume (device_t);
125 void ndis_shutdown (device_t);
127 int ndisdrv_modevent (module_t, int, void *);
129 static void ndis_txeof (ndis_handle, ndis_packet *, ndis_status);
130 static void ndis_rxeof (ndis_handle, ndis_packet **, uint32_t);
131 static void ndis_rxeof_eth (ndis_handle, ndis_handle, char *, void *,
132 uint32_t, void *, uint32_t, uint32_t);
133 static void ndis_rxeof_done (ndis_handle);
134 static void ndis_rxeof_xfr (kdpc *, ndis_handle, void *, void *);
135 static void ndis_rxeof_xfr_done (ndis_handle, ndis_packet *,
137 static void ndis_linksts (ndis_handle, ndis_status, void *, uint32_t);
138 static void ndis_linksts_done (ndis_handle);
140 /* We need to wrap these functions for amd64. */
141 static funcptr ndis_txeof_wrap;
142 static funcptr ndis_rxeof_wrap;
143 static funcptr ndis_rxeof_eth_wrap;
144 static funcptr ndis_rxeof_done_wrap;
145 static funcptr ndis_rxeof_xfr_wrap;
146 static funcptr ndis_rxeof_xfr_done_wrap;
147 static funcptr ndis_linksts_wrap;
148 static funcptr ndis_linksts_done_wrap;
149 static funcptr ndis_ticktask_wrap;
150 static funcptr ndis_starttask_wrap;
151 static funcptr ndis_resettask_wrap;
152 static funcptr ndis_inputtask_wrap;
154 static struct ieee80211vap *ndis_vap_create(struct ieee80211com *,
155 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
156 const uint8_t [IEEE80211_ADDR_LEN],
157 const uint8_t [IEEE80211_ADDR_LEN]);
158 static void ndis_vap_delete (struct ieee80211vap *);
159 static void ndis_tick (void *);
160 static void ndis_ticktask (device_object *, void *);
161 static int ndis_raw_xmit (struct ieee80211_node *, struct mbuf *,
162 const struct ieee80211_bpf_params *);
163 static void ndis_update_mcast (struct ieee80211com *);
164 static void ndis_update_promisc (struct ieee80211com *);
165 static void ndis_start (struct ifnet *);
166 static void ndis_starttask (device_object *, void *);
167 static void ndis_resettask (device_object *, void *);
168 static void ndis_inputtask (device_object *, void *);
169 static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
170 static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
172 static int ndis_nettype_chan (uint32_t);
173 static int ndis_nettype_mode (uint32_t);
174 static void ndis_scan (void *);
175 static void ndis_scan_results (struct ndis_softc *);
176 static void ndis_scan_start (struct ieee80211com *);
177 static void ndis_scan_end (struct ieee80211com *);
178 static void ndis_set_channel (struct ieee80211com *);
179 static void ndis_scan_curchan (struct ieee80211_scan_state *, unsigned long);
180 static void ndis_scan_mindwell (struct ieee80211_scan_state *);
181 static void ndis_init (void *);
182 static void ndis_stop (struct ndis_softc *);
183 static int ndis_ifmedia_upd (struct ifnet *);
184 static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
185 static int ndis_get_bssid_list (struct ndis_softc *,
186 ndis_80211_bssid_list_ex **);
187 static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
188 static int ndis_probe_offload (struct ndis_softc *);
189 static int ndis_set_offload (struct ndis_softc *);
190 static void ndis_getstate_80211 (struct ndis_softc *);
191 static void ndis_setstate_80211 (struct ndis_softc *);
192 static void ndis_auth_and_assoc (struct ndis_softc *, struct ieee80211vap *);
193 static void ndis_media_status (struct ifnet *, struct ifmediareq *);
194 static int ndis_set_cipher (struct ndis_softc *, int);
195 static int ndis_set_wpa (struct ndis_softc *, void *, int);
196 static int ndis_add_key (struct ieee80211vap *,
197 const struct ieee80211_key *);
198 static int ndis_del_key (struct ieee80211vap *,
199 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);
203 static int ndis_ifattach(struct ndis_softc *);
205 static int ndis_80211attach(struct ndis_softc *);
206 static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
207 static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
208 static void ndis_80211parent(struct ieee80211com *);
210 static int ndisdrv_loaded = 0;
213 * This routine should call windrv_load() once for each driver
214 * image. This will do the relocation and dynalinking for the
215 * image, and create a Windows driver object which will be
216 * saved in our driver database.
219 ndisdrv_modevent(mod, cmd, arg)
229 if (ndisdrv_loaded > 1)
231 windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
232 3, WINDRV_WRAP_STDCALL);
233 windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
234 8, WINDRV_WRAP_STDCALL);
235 windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
236 1, WINDRV_WRAP_STDCALL);
237 windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
238 4, WINDRV_WRAP_STDCALL);
239 windrv_wrap((funcptr)ndis_rxeof_xfr_done,
240 &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
241 windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
242 3, WINDRV_WRAP_STDCALL);
243 windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
244 4, WINDRV_WRAP_STDCALL);
245 windrv_wrap((funcptr)ndis_linksts_done,
246 &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
247 windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
248 2, WINDRV_WRAP_STDCALL);
249 windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
250 2, WINDRV_WRAP_STDCALL);
251 windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
252 2, WINDRV_WRAP_STDCALL);
253 windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
254 2, WINDRV_WRAP_STDCALL);
258 if (ndisdrv_loaded > 0)
262 windrv_unwrap(ndis_rxeof_wrap);
263 windrv_unwrap(ndis_rxeof_eth_wrap);
264 windrv_unwrap(ndis_rxeof_done_wrap);
265 windrv_unwrap(ndis_rxeof_xfr_wrap);
266 windrv_unwrap(ndis_rxeof_xfr_done_wrap);
267 windrv_unwrap(ndis_txeof_wrap);
268 windrv_unwrap(ndis_linksts_wrap);
269 windrv_unwrap(ndis_linksts_done_wrap);
270 windrv_unwrap(ndis_ticktask_wrap);
271 windrv_unwrap(ndis_starttask_wrap);
272 windrv_unwrap(ndis_resettask_wrap);
273 windrv_unwrap(ndis_inputtask_wrap);
284 * Program the 64-bit multicast hash filter.
288 struct ndis_softc *sc;
291 struct ifmultiaddr *ifma;
292 int len, mclistsz, error;
297 if (!NDIS_INITIALIZED(sc))
300 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
301 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
302 len = sizeof(sc->ndis_filter);
303 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
304 &sc->ndis_filter, &len);
306 device_printf(sc->ndis_dev,
307 "set allmulti failed: %d\n", error);
311 if (TAILQ_EMPTY(&ifp->if_multiaddrs))
314 len = sizeof(mclistsz);
315 ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
317 mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
319 if (mclist == NULL) {
320 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
324 sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
328 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
329 if (ifma->ifma_addr->sa_family != AF_LINK)
331 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
332 mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
334 if (len > mclistsz) {
335 if_maddr_runlock(ifp);
336 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
337 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
341 if_maddr_runlock(ifp);
343 len = len * ETHER_ADDR_LEN;
344 error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
346 device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
347 sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
348 sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
352 free(mclist, M_TEMP);
354 len = sizeof(sc->ndis_filter);
355 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
356 &sc->ndis_filter, &len);
358 device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
363 struct ndis_softc *sc;
365 ndis_task_offload *nto;
366 ndis_task_offload_hdr *ntoh;
367 ndis_task_tcpip_csum *nttc;
373 if (!NDIS_INITIALIZED(sc))
376 /* See if there's anything to set. */
378 error = ndis_probe_offload(sc);
382 if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
385 len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
386 sizeof(ndis_task_tcpip_csum);
388 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
393 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
394 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
395 ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
396 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
397 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
398 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
400 nto = (ndis_task_offload *)((char *)ntoh +
401 ntoh->ntoh_offset_firsttask);
403 nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
404 nto->nto_len = sizeof(ndis_task_offload);
405 nto->nto_task = NDIS_TASK_TCPIP_CSUM;
406 nto->nto_offset_nexttask = 0;
407 nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
409 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
411 if (ifp->if_capenable & IFCAP_TXCSUM)
412 nttc->nttc_v4tx = sc->ndis_v4tx;
414 if (ifp->if_capenable & IFCAP_RXCSUM)
415 nttc->nttc_v4rx = sc->ndis_v4rx;
417 error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
424 ndis_probe_offload(sc)
425 struct ndis_softc *sc;
427 ndis_task_offload *nto;
428 ndis_task_offload_hdr *ntoh;
429 ndis_task_tcpip_csum *nttc = NULL;
431 int len, error, dummy;
436 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
441 ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
446 ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
447 ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
448 ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
449 ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
450 ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
452 error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
459 if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
464 nto = (ndis_task_offload *)((char *)ntoh +
465 ntoh->ntoh_offset_firsttask);
468 switch (nto->nto_task) {
469 case NDIS_TASK_TCPIP_CSUM:
470 nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
472 /* Don't handle these yet. */
473 case NDIS_TASK_IPSEC:
474 case NDIS_TASK_TCP_LARGESEND:
478 if (nto->nto_offset_nexttask == 0)
480 nto = (ndis_task_offload *)((char *)nto +
481 nto->nto_offset_nexttask);
489 sc->ndis_v4tx = nttc->nttc_v4tx;
490 sc->ndis_v4rx = nttc->nttc_v4rx;
492 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
493 sc->ndis_hwassist |= CSUM_IP;
494 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
495 sc->ndis_hwassist |= CSUM_TCP;
496 if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
497 sc->ndis_hwassist |= CSUM_UDP;
499 if (sc->ndis_hwassist)
500 ifp->if_capabilities |= IFCAP_TXCSUM;
502 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
503 ifp->if_capabilities |= IFCAP_RXCSUM;
504 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
505 ifp->if_capabilities |= IFCAP_RXCSUM;
506 if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
507 ifp->if_capabilities |= IFCAP_RXCSUM;
514 ndis_nettype_chan(uint32_t type)
517 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_CHAN_FHSS);
518 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_CHAN_B);
519 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_CHAN_A);
520 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_CHAN_G);
522 DPRINTF(("unknown channel nettype %d\n", type));
523 return (IEEE80211_CHAN_B); /* Default to 11B chan */
527 ndis_nettype_mode(uint32_t type)
530 case NDIS_80211_NETTYPE_11FH: return (IEEE80211_MODE_FH);
531 case NDIS_80211_NETTYPE_11DS: return (IEEE80211_MODE_11B);
532 case NDIS_80211_NETTYPE_11OFDM5: return (IEEE80211_MODE_11A);
533 case NDIS_80211_NETTYPE_11OFDM24: return (IEEE80211_MODE_11G);
535 DPRINTF(("unknown mode nettype %d\n", type));
536 return (IEEE80211_MODE_AUTO);
540 * Attach the interface. Allocate softc structures, do ifmedia
541 * setup and ethernet/BPF attach.
544 ndis_attach(device_t dev)
546 struct ndis_softc *sc;
552 sc = device_get_softc(dev);
554 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
556 KeInitializeSpinLock(&sc->ndis_rxlock);
557 KeInitializeSpinLock(&sc->ndisusb_tasklock);
558 KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
559 InitializeListHead(&sc->ndis_shlist);
560 InitializeListHead(&sc->ndisusb_tasklist);
561 InitializeListHead(&sc->ndisusb_xferdonelist);
562 callout_init(&sc->ndis_stat_callout, 1);
563 mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
565 if (sc->ndis_iftype == PCMCIABus) {
566 error = ndis_alloc_amem(sc);
568 device_printf(dev, "failed to allocate "
569 "attribute memory\n");
574 /* Create sysctl registry nodes */
575 ndis_create_sysctls(sc);
577 /* Find the PDO for this device instance. */
579 if (sc->ndis_iftype == PCIBus)
580 pdrv = windrv_lookup(0, "PCI Bus");
581 else if (sc->ndis_iftype == PCMCIABus)
582 pdrv = windrv_lookup(0, "PCCARD Bus");
584 pdrv = windrv_lookup(0, "USB Bus");
585 pdo = windrv_find_pdo(pdrv, dev);
588 * Create a new functional device object for this
589 * device. This is what creates the miniport block
590 * for this device instance.
593 if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
594 device_printf(dev, "failed to create FDO!\n");
599 /* Tell the user what version of the API the driver is using. */
600 device_printf(dev, "NDIS API version: %d.%d\n",
601 sc->ndis_chars->nmc_version_major,
602 sc->ndis_chars->nmc_version_minor);
604 /* Do resource conversion. */
605 if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
606 ndis_convert_res(sc);
608 sc->ndis_block->nmb_rlist = NULL;
610 /* Install our RX and TX interrupt handlers. */
611 sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
612 sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
613 sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
614 sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
615 sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
617 /* Override the status handler so we can detect link changes. */
618 sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
619 sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
621 /* Set up work item handlers. */
622 sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
623 sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
624 sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
625 sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
626 sc->ndisusb_xferdoneitem =
627 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
628 sc->ndisusb_taskitem =
629 IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630 KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
632 /* Call driver's init routine. */
633 if (ndis_init_nic(sc)) {
634 device_printf(dev, "init handler failed\n");
640 * Figure out how big to make the TX buffer pool.
642 len = sizeof(sc->ndis_maxpkts);
643 if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
644 &sc->ndis_maxpkts, &len)) {
645 device_printf(dev, "failed to get max TX packets\n");
651 * If this is a deserialized miniport, we don't have
652 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
654 if (!NDIS_SERIALIZED(sc->ndis_block))
655 sc->ndis_maxpkts = NDIS_TXPKTS;
657 /* Enforce some sanity, just in case. */
659 if (sc->ndis_maxpkts == 0)
660 sc->ndis_maxpkts = 10;
662 sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
663 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
665 /* Allocate a pool of ndis_packets for TX encapsulation. */
667 NdisAllocatePacketPool(&i, &sc->ndis_txpool,
668 sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
670 if (i != NDIS_STATUS_SUCCESS) {
671 sc->ndis_txpool = NULL;
672 device_printf(dev, "failed to allocate TX packet pool");
677 sc->ndis_txpending = sc->ndis_maxpkts;
680 /* Get supported oid list. */
681 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
683 /* If the NDIS module requested scatter/gather, init maps. */
688 * See if the OID_802_11_CONFIGURATION OID is
689 * supported by this driver. If it is, then this an 802.11
690 * wireless driver, and we should set up media for wireless.
692 for (i = 0; i < sc->ndis_oidcnt; i++)
693 if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
699 error = ndis_80211attach(sc);
701 error = ndis_ifattach(sc);
709 if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
712 DPRINTF(("attach done.\n"));
713 /* We're done talking to the NIC for now; halt it. */
715 DPRINTF(("halting done.\n"));
721 ndis_80211attach(struct ndis_softc *sc)
723 struct ieee80211com *ic = &sc->ndis_ic;
724 ndis_80211_rates_ex rates;
725 struct ndis_80211_nettype_list *ntl;
730 callout_init(&sc->ndis_scan_callout, 1);
733 ic->ic_ioctl = ndis_80211ioctl;
734 ic->ic_name = device_get_nameunit(sc->ndis_dev);
735 ic->ic_opmode = IEEE80211_M_STA;
736 ic->ic_phytype = IEEE80211_T_DS;
737 ic->ic_caps = IEEE80211_C_8023ENCAP |
738 IEEE80211_C_STA | IEEE80211_C_IBSS;
739 setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
741 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
744 ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
745 r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
751 for (i = 0; i < ntl->ntl_items; i++) {
752 mode = ndis_nettype_mode(ntl->ntl_type[i]);
754 setbit(ic->ic_modecaps, mode);
755 setbit(&bands, mode);
757 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
762 /* Default to 11b channels if the card did not supply any */
764 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
765 setbit(&bands, IEEE80211_MODE_11B);
768 bzero((char *)&rates, len);
769 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
771 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
773 * Since the supported rates only up to 8 can be supported,
774 * if this is not 802.11b we're just going to be faking it
778 #define TESTSETRATE(x, y) \
781 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
782 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
785 if (i == ic->ic_sup_rates[x].rs_nrates) { \
786 ic->ic_sup_rates[x].rs_rates[i] = (y); \
787 ic->ic_sup_rates[x].rs_nrates++; \
791 #define SETRATE(x, y) \
792 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
794 ic->ic_sup_rates[x].rs_nrates++
796 ic->ic_curmode = IEEE80211_MODE_AUTO;
797 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
798 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
799 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
800 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
801 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
802 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
803 for (i = 0; i < len; i++) {
804 switch (rates[i] & IEEE80211_RATE_VAL) {
810 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
811 /* Lazy-init 802.11b. */
812 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
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, IEEE80211_RATE_BASIC|2);
841 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
842 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
843 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
845 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
846 TESTSETRATE(IEEE80211_MODE_11G, 48);
847 TESTSETRATE(IEEE80211_MODE_11G, 72);
848 TESTSETRATE(IEEE80211_MODE_11G, 96);
849 TESTSETRATE(IEEE80211_MODE_11G, 108);
851 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
852 TESTSETRATE(IEEE80211_MODE_11A, 48);
853 TESTSETRATE(IEEE80211_MODE_11A, 72);
854 TESTSETRATE(IEEE80211_MODE_11A, 96);
855 TESTSETRATE(IEEE80211_MODE_11A, 108);
862 ieee80211_init_channels(ic, NULL, &bands);
865 * To test for WPA support, we need to see if we can
866 * set AUTHENTICATION_MODE to WPA and read it back
870 arg = NDIS_80211_AUTHMODE_WPA;
871 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
873 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
874 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
875 ic->ic_caps |= IEEE80211_C_WPA;
879 * To test for supported ciphers, we set each
880 * available encryption type in descending order.
881 * If ENC3 works, then we have WEP, TKIP and AES.
882 * If only ENC2 works, then we have WEP and TKIP.
883 * If only ENC1 works, then we have just WEP.
886 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
887 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
889 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
890 | IEEE80211_CRYPTO_TKIP
891 | IEEE80211_CRYPTO_AES_CCM;
894 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
895 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
897 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
898 | IEEE80211_CRYPTO_TKIP;
901 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
902 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
904 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
907 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
909 ic->ic_caps |= IEEE80211_C_PMGT;
911 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
913 ic->ic_caps |= IEEE80211_C_TXPMGT;
916 * Get station address from the driver.
918 len = sizeof(ic->ic_macaddr);
919 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
921 ieee80211_ifattach(ic);
922 ic->ic_raw_xmit = ndis_raw_xmit;
923 ic->ic_scan_start = ndis_scan_start;
924 ic->ic_scan_end = ndis_scan_end;
925 ic->ic_set_channel = ndis_set_channel;
926 ic->ic_scan_curchan = ndis_scan_curchan;
927 ic->ic_scan_mindwell = ndis_scan_mindwell;
928 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
929 ic->ic_vap_create = ndis_vap_create;
930 ic->ic_vap_delete = ndis_vap_delete;
931 ic->ic_update_mcast = ndis_update_mcast;
932 ic->ic_update_promisc = ndis_update_promisc;
933 ic->ic_transmit = ndis_80211transmit;
934 ic->ic_parent = ndis_80211parent;
937 ieee80211_announce(ic);
943 ndis_ifattach(struct ndis_softc *sc)
946 u_char eaddr[ETHER_ADDR_LEN];
949 ifp = if_alloc(IFT_ETHER);
955 /* Check for task offload support. */
956 ndis_probe_offload(sc);
959 * Get station address from the driver.
962 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
964 if_initname(ifp, device_get_name(sc->ndis_dev),
965 device_get_unit(sc->ndis_dev));
966 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
967 ifp->if_ioctl = ndis_ioctl;
968 ifp->if_start = ndis_start;
969 ifp->if_init = ndis_init;
970 ifp->if_baudrate = 10000000;
971 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
972 ifp->if_snd.ifq_drv_maxlen = 25;
973 IFQ_SET_READY(&ifp->if_snd);
974 ifp->if_capenable = ifp->if_capabilities;
975 ifp->if_hwassist = sc->ndis_hwassist;
977 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
979 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
980 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
981 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
982 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
983 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
984 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
985 ether_ifattach(ifp, eaddr);
990 static struct ieee80211vap *
991 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
992 enum ieee80211_opmode opmode, int flags,
993 const uint8_t bssid[IEEE80211_ADDR_LEN],
994 const uint8_t mac[IEEE80211_ADDR_LEN])
996 struct ndis_vap *nvp;
997 struct ieee80211vap *vap;
999 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1001 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1003 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1004 /* override with driver methods */
1005 nvp->newstate = vap->iv_newstate;
1006 vap->iv_newstate = ndis_newstate;
1008 /* complete setup */
1009 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1011 ic->ic_opmode = opmode;
1012 /* install key handing routines */
1013 vap->iv_key_set = ndis_add_key;
1014 vap->iv_key_delete = ndis_del_key;
1019 ndis_vap_delete(struct ieee80211vap *vap)
1021 struct ndis_vap *nvp = NDIS_VAP(vap);
1022 struct ieee80211com *ic = vap->iv_ic;
1023 struct ndis_softc *sc = ic->ic_softc;
1026 callout_drain(&sc->ndis_scan_callout);
1027 ieee80211_vap_detach(vap);
1028 free(nvp, M_80211_VAP);
1032 * Shutdown hardware and free up resources. This can be called any
1033 * time after the mutex has been initialized. It is called in both
1034 * the error case in attach and the normal detach case so it needs
1035 * to be careful about only freeing resources that have actually been
1039 ndis_detach(device_t dev)
1042 struct ndis_softc *sc;
1045 sc = device_get_softc(dev);
1047 if (!sc->ndis_80211)
1052 ifp->if_flags &= ~IFF_UP;
1053 if (device_is_attached(dev)) {
1057 ieee80211_ifdetach(&sc->ndis_ic);
1058 else if (ifp != NULL)
1059 ether_ifdetach(ifp);
1063 if (sc->ndis_tickitem != NULL)
1064 IoFreeWorkItem(sc->ndis_tickitem);
1065 if (sc->ndis_startitem != NULL)
1066 IoFreeWorkItem(sc->ndis_startitem);
1067 if (sc->ndis_resetitem != NULL)
1068 IoFreeWorkItem(sc->ndis_resetitem);
1069 if (sc->ndis_inputitem != NULL)
1070 IoFreeWorkItem(sc->ndis_inputitem);
1071 if (sc->ndisusb_xferdoneitem != NULL)
1072 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1073 if (sc->ndisusb_taskitem != NULL)
1074 IoFreeWorkItem(sc->ndisusb_taskitem);
1076 bus_generic_detach(dev);
1077 ndis_unload_driver(sc);
1080 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1081 if (sc->ndis_res_io)
1082 bus_release_resource(dev, SYS_RES_IOPORT,
1083 sc->ndis_io_rid, sc->ndis_res_io);
1084 if (sc->ndis_res_mem)
1085 bus_release_resource(dev, SYS_RES_MEMORY,
1086 sc->ndis_mem_rid, sc->ndis_res_mem);
1087 if (sc->ndis_res_altmem)
1088 bus_release_resource(dev, SYS_RES_MEMORY,
1089 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1094 if (sc->ndis_iftype == PCMCIABus)
1098 ndis_destroy_dma(sc);
1100 if (sc->ndis_txarray)
1101 free(sc->ndis_txarray, M_DEVBUF);
1103 if (!sc->ndis_80211)
1104 ifmedia_removeall(&sc->ifmedia);
1106 if (sc->ndis_txpool != NULL)
1107 NdisFreePacketPool(sc->ndis_txpool);
1109 /* Destroy the PDO for this device. */
1111 if (sc->ndis_iftype == PCIBus)
1112 drv = windrv_lookup(0, "PCI Bus");
1113 else if (sc->ndis_iftype == PCMCIABus)
1114 drv = windrv_lookup(0, "PCCARD Bus");
1116 drv = windrv_lookup(0, "USB Bus");
1118 panic("couldn't find driver object");
1119 windrv_destroy_pdo(drv, dev);
1121 if (sc->ndis_iftype == PCIBus)
1122 bus_dma_tag_destroy(sc->ndis_parent_tag);
1131 struct ndis_softc *sc;
1134 sc = device_get_softc(dev);
1138 if (NDIS_INITIALIZED(sc))
1149 struct ndis_softc *sc;
1152 sc = device_get_softc(dev);
1155 if (NDIS_INITIALIZED(sc))
1162 * The following bunch of routines are here to support drivers that
1163 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1164 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1165 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1169 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1170 ndis_handle adapter;
1176 uint32_t lookaheadlen;
1179 ndis_miniport_block *block;
1189 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1193 /* Save the data provided to us so far. */
1195 m->m_len = lookaheadlen + hdrlen;
1196 m->m_pkthdr.len = pktlen + hdrlen;
1198 m_copyback(m, 0, hdrlen, hdr);
1199 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1201 /* Now create a fake NDIS_PACKET to hold the data */
1203 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1205 if (status != NDIS_STATUS_SUCCESS) {
1212 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1220 p->np_private.npp_head = p->np_private.npp_tail = b;
1221 p->np_private.npp_totlen = m->m_pkthdr.len;
1223 /* Save the packet RX context somewhere. */
1224 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1225 priv->nep_ctx = ctx;
1227 if (!NDIS_SERIALIZED(block))
1228 KeAcquireSpinLock(&block->nmb_lock, &irql);
1230 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1232 if (!NDIS_SERIALIZED(block))
1233 KeReleaseSpinLock(&block->nmb_lock, irql);
1237 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1238 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1242 ndis_rxeof_done(adapter)
1243 ndis_handle adapter;
1245 struct ndis_softc *sc;
1246 ndis_miniport_block *block;
1250 /* Schedule transfer/RX of queued packets. */
1252 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1254 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1258 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1261 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1263 ndis_handle adapter;
1267 ndis_miniport_block *block;
1268 struct ndis_softc *sc;
1277 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1280 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1282 l = block->nmb_packetlist.nle_flink;
1283 while(!IsListEmpty(&block->nmb_packetlist)) {
1284 l = RemoveHeadList((&block->nmb_packetlist));
1285 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1286 InitializeListHead((&p->np_list));
1288 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1293 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1295 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1296 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1297 m->m_len, m->m_pkthdr.len - m->m_len);
1299 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1302 * If status is NDIS_STATUS_PENDING, do nothing and
1303 * wait for a callback to the ndis_rxeof_xfr_done()
1307 m->m_len = m->m_pkthdr.len;
1308 m->m_pkthdr.rcvif = ifp;
1310 if (status == NDIS_STATUS_SUCCESS) {
1311 IoFreeMdl(p->np_private.npp_head);
1313 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1314 mbufq_enqueue(&sc->ndis_rxqueue, m);
1315 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1316 IoQueueWorkItem(sc->ndis_inputitem,
1317 (io_workitem_func)ndis_inputtask_wrap,
1318 WORKQUEUE_CRITICAL, sc);
1321 if (status == NDIS_STATUS_FAILURE)
1324 /* Advance to next packet */
1325 l = block->nmb_packetlist.nle_flink;
1328 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1332 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1335 ndis_rxeof_xfr_done(adapter, packet, status, len)
1336 ndis_handle adapter;
1337 ndis_packet *packet;
1341 ndis_miniport_block *block;
1342 struct ndis_softc *sc;
1347 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1351 IoFreeMdl(packet->np_private.npp_head);
1352 NdisFreePacket(packet);
1354 if (status != NDIS_STATUS_SUCCESS) {
1359 m->m_len = m->m_pkthdr.len;
1360 m->m_pkthdr.rcvif = ifp;
1361 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1362 mbufq_enqueue(&sc->ndis_rxqueue, m);
1363 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1364 IoQueueWorkItem(sc->ndis_inputitem,
1365 (io_workitem_func)ndis_inputtask_wrap,
1366 WORKQUEUE_CRITICAL, sc);
1369 * A frame has been uploaded: pass the resulting mbuf chain up to
1370 * the higher level protocols.
1372 * When handling received NDIS packets, the 'status' field in the
1373 * out-of-band portion of the ndis_packet has special meaning. In the
1374 * most common case, the underlying NDIS driver will set this field
1375 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1376 * take posession of it. We then change the status field to
1377 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1378 * and that we will return it at some point in the future via the
1379 * return packet handler.
1381 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1382 * this means the driver is running out of packet/buffer resources and
1383 * wants to maintain ownership of the packet. In this case, we have to
1384 * copy the packet data into local storage and let the driver keep the
1388 ndis_rxeof(adapter, packets, pktcnt)
1389 ndis_handle adapter;
1390 ndis_packet **packets;
1393 struct ndis_softc *sc;
1394 ndis_miniport_block *block;
1397 ndis_tcpip_csum *csum;
1399 struct mbuf *m0, *m;
1402 block = (ndis_miniport_block *)adapter;
1403 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1407 * There's a slim chance the driver may indicate some packets
1408 * before we're completely ready to handle them. If we detect this,
1409 * we need to return them to the miniport and ignore them.
1411 if (!sc->ndis_running) {
1412 for (i = 0; i < pktcnt; i++) {
1414 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1416 (void)ndis_return_packet(NULL ,p, block);
1422 for (i = 0; i < pktcnt; i++) {
1424 /* Stash the softc here so ptom can use it. */
1426 if (ndis_ptom(&m0, p)) {
1427 device_printf(sc->ndis_dev, "ptom failed\n");
1428 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1429 (void)ndis_return_packet(NULL, p, block);
1432 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1433 m = m_dup(m0, M_NOWAIT);
1435 * NOTE: we want to destroy the mbuf here, but
1436 * we don't actually want to return it to the
1437 * driver via the return packet handler. By
1438 * bumping np_refcnt, we can prevent the
1439 * ndis_return_packet() routine from actually
1445 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1449 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1451 m = m_dup(m0, M_NOWAIT);
1452 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1455 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1458 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1462 m0->m_pkthdr.rcvif = ifp;
1464 /* Deal with checksum offload. */
1466 if (ifp->if_capenable & IFCAP_RXCSUM &&
1467 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1469 p->np_ext.npe_info[ndis_tcpipcsum_info];
1470 csum = (ndis_tcpip_csum *)&s;
1471 if (csum->u.ntc_rxflags &
1472 NDIS_RXCSUM_IP_PASSED)
1473 m0->m_pkthdr.csum_flags |=
1474 CSUM_IP_CHECKED|CSUM_IP_VALID;
1475 if (csum->u.ntc_rxflags &
1476 (NDIS_RXCSUM_TCP_PASSED |
1477 NDIS_RXCSUM_UDP_PASSED)) {
1478 m0->m_pkthdr.csum_flags |=
1479 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1480 m0->m_pkthdr.csum_data = 0xFFFF;
1484 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1485 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1486 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1487 IoQueueWorkItem(sc->ndis_inputitem,
1488 (io_workitem_func)ndis_inputtask_wrap,
1489 WORKQUEUE_CRITICAL, sc);
1495 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1496 * packets into the stack in order to avoid calling (*ifp->if_input)()
1497 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1498 * 'dispatch level' per-cpu sleep lock).
1501 ndis_inputtask(device_object *dobj, void *arg)
1503 ndis_miniport_block *block;
1504 struct ndis_softc *sc = arg;
1508 block = dobj->do_devext;
1510 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1511 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1512 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1513 if ((sc->ndis_80211 != 0)) {
1514 struct ieee80211com *ic = &sc->ndis_ic;
1515 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1518 vap->iv_deliver_data(vap, vap->iv_bss, m);
1520 struct ifnet *ifp = sc->ifp;
1522 (*ifp->if_input)(ifp, m);
1524 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1526 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1530 * A frame was downloaded to the chip. It's safe for us to clean up
1534 ndis_txeof(adapter, packet, status)
1535 ndis_handle adapter;
1536 ndis_packet *packet;
1540 struct ndis_softc *sc;
1541 ndis_miniport_block *block;
1546 block = (ndis_miniport_block *)adapter;
1547 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1551 idx = packet->np_txidx;
1553 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1555 ndis_free_packet(packet);
1559 sc->ndis_txarray[idx] = NULL;
1560 sc->ndis_txpending++;
1562 if (status == NDIS_STATUS_SUCCESS)
1563 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1565 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1567 sc->ndis_tx_timer = 0;
1568 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1572 IoQueueWorkItem(sc->ndis_startitem,
1573 (io_workitem_func)ndis_starttask_wrap,
1574 WORKQUEUE_CRITICAL, ifp);
1578 ndis_linksts(adapter, status, sbuf, slen)
1579 ndis_handle adapter;
1584 ndis_miniport_block *block;
1585 struct ndis_softc *sc;
1588 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1589 sc->ndis_sts = status;
1591 /* Event list is all full up, drop this one. */
1594 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1599 /* Cache the event. */
1602 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1604 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1609 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1611 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1612 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1613 NDIS_EVTINC(sc->ndis_evtpidx);
1618 ndis_linksts_done(adapter)
1619 ndis_handle adapter;
1621 ndis_miniport_block *block;
1622 struct ndis_softc *sc;
1626 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1629 if (!NDIS_INITIALIZED(sc))
1632 switch (sc->ndis_sts) {
1633 case NDIS_STATUS_MEDIA_CONNECT:
1634 IoQueueWorkItem(sc->ndis_tickitem,
1635 (io_workitem_func)ndis_ticktask_wrap,
1636 WORKQUEUE_CRITICAL, sc);
1637 IoQueueWorkItem(sc->ndis_startitem,
1638 (io_workitem_func)ndis_starttask_wrap,
1639 WORKQUEUE_CRITICAL, ifp);
1641 case NDIS_STATUS_MEDIA_DISCONNECT:
1643 IoQueueWorkItem(sc->ndis_tickitem,
1644 (io_workitem_func)ndis_ticktask_wrap,
1645 WORKQUEUE_CRITICAL, sc);
1656 struct ndis_softc *sc;
1660 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1661 IoQueueWorkItem(sc->ndis_tickitem,
1662 (io_workitem_func)ndis_ticktask_wrap,
1663 WORKQUEUE_CRITICAL, sc);
1664 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1667 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1668 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1669 device_printf(sc->ndis_dev, "watchdog timeout\n");
1671 IoQueueWorkItem(sc->ndis_resetitem,
1672 (io_workitem_func)ndis_resettask_wrap,
1673 WORKQUEUE_CRITICAL, sc);
1674 IoQueueWorkItem(sc->ndis_startitem,
1675 (io_workitem_func)ndis_starttask_wrap,
1676 WORKQUEUE_CRITICAL, sc->ifp);
1679 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1683 ndis_ticktask(device_object *d, void *xsc)
1685 struct ndis_softc *sc = xsc;
1686 ndis_checkforhang_handler hangfunc;
1690 if (!NDIS_INITIALIZED(sc)) {
1696 hangfunc = sc->ndis_chars->nmc_checkhang_func;
1698 if (hangfunc != NULL) {
1699 rval = MSCALL1(hangfunc,
1700 sc->ndis_block->nmb_miniportadapterctx);
1708 if (sc->ndis_link == 0 &&
1709 sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1711 if (sc->ndis_80211 != 0) {
1712 struct ieee80211com *ic = &sc->ndis_ic;
1713 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1717 ndis_getstate_80211(sc);
1718 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1720 if_link_state_change(vap->iv_ifp,
1724 if_link_state_change(sc->ifp, LINK_STATE_UP);
1727 if (sc->ndis_link == 1 &&
1728 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1730 if (sc->ndis_80211 != 0) {
1731 struct ieee80211com *ic = &sc->ndis_ic;
1732 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1736 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1738 if_link_state_change(vap->iv_ifp,
1742 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1749 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1751 bus_dma_segment_t *segs;
1757 struct ndis_sc_list *sclist;
1760 if (error || arg == NULL)
1765 sclist->nsl_frags = nseg;
1767 for (i = 0; i < nseg; i++) {
1768 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1769 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1774 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1775 const struct ieee80211_bpf_params *params)
1777 /* no support; just discard */
1779 ieee80211_free_node(ni);
1784 ndis_update_mcast(struct ieee80211com *ic)
1786 struct ndis_softc *sc = ic->ic_softc;
1792 ndis_update_promisc(struct ieee80211com *ic)
1798 ndis_starttask(d, arg)
1806 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1811 * Main transmit routine. To make NDIS drivers happy, we need to
1812 * transform mbuf chains into NDIS packets and feed them to the
1813 * send packet routines. Most drivers allow you to send several
1814 * packets at once (up to the maxpkts limit). Unfortunately, rather
1815 * that accepting them in the form of a linked list, they expect
1816 * a contiguous array of pointers to packets.
1818 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1819 * we need to perform busdma work here. Those that use map registers
1820 * will do the mapping themselves on a buffer by buffer basis.
1826 struct ndis_softc *sc;
1827 struct mbuf *m = NULL;
1828 ndis_packet **p0 = NULL, *p = NULL;
1829 ndis_tcpip_csum *csum;
1830 int pcnt = 0, status;
1835 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1840 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1842 while(sc->ndis_txpending) {
1843 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1847 NdisAllocatePacket(&status,
1848 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1850 if (status != NDIS_STATUS_SUCCESS)
1853 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1854 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1860 * Save pointer to original mbuf
1861 * so we can free it later.
1864 p = sc->ndis_txarray[sc->ndis_txidx];
1865 p->np_txidx = sc->ndis_txidx;
1867 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1870 * Do scatter/gather processing, if driver requested it.
1873 bus_dmamap_load_mbuf(sc->ndis_ttag,
1874 sc->ndis_tmaps[sc->ndis_txidx], m,
1875 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1876 bus_dmamap_sync(sc->ndis_ttag,
1877 sc->ndis_tmaps[sc->ndis_txidx],
1878 BUS_DMASYNC_PREREAD);
1879 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1882 /* Handle checksum offload. */
1884 if (ifp->if_capenable & IFCAP_TXCSUM &&
1885 m->m_pkthdr.csum_flags) {
1886 csum = (ndis_tcpip_csum *)
1887 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1888 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1889 if (m->m_pkthdr.csum_flags & CSUM_IP)
1890 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1891 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1892 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1893 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1894 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1895 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1899 sc->ndis_txpending--;
1904 * If there's a BPF listener, bounce a copy of this frame
1907 if (!sc->ndis_80211) /* XXX handle 80211 */
1911 * The array that p0 points to must appear contiguous,
1912 * so we must not wrap past the end of sc->ndis_txarray[].
1913 * If it looks like we're about to wrap, break out here
1914 * so the this batch of packets can be transmitted, then
1915 * wait for txeof to ask us to send the rest.
1917 if (sc->ndis_txidx == 0)
1926 if (sc->ndis_txpending == 0)
1927 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1930 * Set a timeout in case the chip goes out to lunch.
1932 sc->ndis_tx_timer = 5;
1937 * According to NDIS documentation, if a driver exports
1938 * a MiniportSendPackets() routine, we prefer that over
1939 * a MiniportSend() routine (which sends just a single
1942 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1943 ndis_send_packets(sc, p0, pcnt);
1945 ndis_send_packet(sc, p);
1951 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1953 struct ndis_softc *sc = ic->ic_softc;
1954 ndis_packet **p0 = NULL, *p = NULL;
1958 if (!sc->ndis_link || !sc->ndis_running) {
1963 if (sc->ndis_txpending == 0) {
1968 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1970 NdisAllocatePacket(&status,
1971 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1973 if (status != NDIS_STATUS_SUCCESS) {
1978 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1984 * Save pointer to original mbuf
1985 * so we can free it later.
1988 p = sc->ndis_txarray[sc->ndis_txidx];
1989 p->np_txidx = sc->ndis_txidx;
1991 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1994 * Do scatter/gather processing, if driver requested it.
1997 bus_dmamap_load_mbuf(sc->ndis_ttag,
1998 sc->ndis_tmaps[sc->ndis_txidx], m,
1999 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2000 bus_dmamap_sync(sc->ndis_ttag,
2001 sc->ndis_tmaps[sc->ndis_txidx],
2002 BUS_DMASYNC_PREREAD);
2003 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2007 sc->ndis_txpending--;
2010 * Set a timeout in case the chip goes out to lunch.
2012 sc->ndis_tx_timer = 5;
2016 * According to NDIS documentation, if a driver exports
2017 * a MiniportSendPackets() routine, we prefer that over
2018 * a MiniportSend() routine (which sends just a single
2021 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2022 ndis_send_packets(sc, p0, 1);
2024 ndis_send_packet(sc, p);
2030 ndis_80211parent(struct ieee80211com *ic)
2032 struct ndis_softc *sc = ic->ic_softc;
2035 if (ic->ic_nrunning > 0) {
2036 if (!sc->ndis_running)
2038 } else if (sc->ndis_running)
2040 /*NDIS_UNLOCK(sc);*/
2044 ndis_init(void *xsc)
2046 struct ndis_softc *sc = xsc;
2050 * Avoid reintializing the link unnecessarily.
2051 * This should be dealt with in a better way by
2052 * fixing the upper layer modules so they don't
2053 * call ifp->if_init() quite as often.
2059 * Cancel pending I/O and free all RX/TX buffers.
2063 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2064 error = ndis_init_nic(sc);
2066 device_printf(sc->ndis_dev,
2067 "failed to initialize the device: %d\n", error);
2072 /* Program the packet filter */
2073 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2074 NDIS_PACKET_TYPE_BROADCAST;
2076 if (sc->ndis_80211) {
2077 struct ieee80211com *ic = &sc->ndis_ic;
2079 if (ic->ic_promisc > 0)
2080 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2082 struct ifnet *ifp = sc->ifp;
2084 if (ifp->if_flags & IFF_PROMISC)
2085 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2088 len = sizeof(sc->ndis_filter);
2090 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2091 &sc->ndis_filter, &len);
2094 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2102 i = sc->ifp->if_mtu;
2104 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2107 * Program the multicast filter, if necessary.
2111 /* Setup task offload. */
2112 ndis_set_offload(sc);
2117 sc->ndis_txpending = sc->ndis_maxpkts;
2120 if (!sc->ndis_80211) {
2121 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2122 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2123 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2126 sc->ndis_tx_timer = 0;
2129 * Some drivers don't set this value. The NDIS spec says
2130 * the default checkforhang timeout is "approximately 2
2131 * seconds." We use 3 seconds, because it seems for some
2132 * drivers, exactly 2 seconds is too fast.
2134 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2135 sc->ndis_block->nmb_checkforhangsecs = 3;
2137 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2138 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2139 sc->ndis_running = 1;
2142 /* XXX force handling */
2144 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2148 * Set media options.
2151 ndis_ifmedia_upd(ifp)
2154 struct ndis_softc *sc;
2158 if (NDIS_INITIALIZED(sc))
2165 * Report current media status.
2168 ndis_ifmedia_sts(ifp, ifmr)
2170 struct ifmediareq *ifmr;
2172 struct ndis_softc *sc;
2173 uint32_t media_info;
2174 ndis_media_state linkstate;
2177 ifmr->ifm_status = IFM_AVALID;
2178 ifmr->ifm_active = IFM_ETHER;
2181 if (!NDIS_INITIALIZED(sc))
2184 len = sizeof(linkstate);
2185 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2186 (void *)&linkstate, &len);
2188 len = sizeof(media_info);
2189 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2190 (void *)&media_info, &len);
2192 if (linkstate == nmc_connected)
2193 ifmr->ifm_status |= IFM_ACTIVE;
2195 switch (media_info) {
2197 ifmr->ifm_active |= IFM_10_T;
2200 ifmr->ifm_active |= IFM_100_TX;
2203 ifmr->ifm_active |= IFM_1000_T;
2206 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2212 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2214 struct ieee80211com *ic = &sc->ndis_ic;
2220 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2221 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2223 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2226 if (cipher == WPA_CSE_TKIP) {
2227 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2229 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2232 if (cipher == WPA_CSE_CCMP) {
2233 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2235 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2238 DPRINTF(("Setting cipher to %d\n", arg));
2240 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2245 /* Check that the cipher was set correctly. */
2248 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2250 if (rval != 0 || arg != save)
2257 * WPA is hairy to set up. Do the work in a separate routine
2258 * so we don't clutter the setstate function too much.
2259 * Important yet undocumented fact: first we have to set the
2260 * authentication mode, _then_ we enable the ciphers. If one
2261 * of the WPA authentication modes isn't enabled, the driver
2262 * might not permit the TKIP or AES ciphers to be selected.
2265 ndis_set_wpa(sc, ie, ielen)
2266 struct ndis_softc *sc;
2270 struct ieee80211_ie_wpa *w;
2277 * Apparently, the only way for us to know what ciphers
2278 * and key management/authentication mode to use is for
2279 * us to inspect the optional information element (IE)
2280 * stored in the 802.11 state machine. This IE should be
2281 * supplied by the WPA supplicant.
2284 w = (struct ieee80211_ie_wpa *)ie;
2286 /* Check for the right kind of IE. */
2287 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2288 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2292 /* Skip over the ucast cipher OIDs. */
2293 pos = (char *)&w->wpa_uciphers[0];
2294 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2296 /* Skip over the authmode count. */
2297 pos += sizeof(u_int16_t);
2300 * Check for the authentication modes. I'm
2301 * pretty sure there's only supposed to be one.
2304 n = (struct ndis_ie *)pos;
2305 if (n->ni_val == WPA_ASE_NONE)
2306 arg = NDIS_80211_AUTHMODE_WPANONE;
2308 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2309 arg = NDIS_80211_AUTHMODE_WPA;
2311 if (n->ni_val == WPA_ASE_8021X_PSK)
2312 arg = NDIS_80211_AUTHMODE_WPAPSK;
2314 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2316 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2319 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2321 /* Now configure the desired ciphers. */
2323 /* First, set up the multicast group cipher. */
2324 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2326 if (ndis_set_cipher(sc, n->ni_val))
2329 /* Now start looking around for the unicast ciphers. */
2330 pos = (char *)&w->wpa_uciphers[0];
2331 n = (struct ndis_ie *)pos;
2333 for (i = 0; i < w->wpa_uciphercnt; i++) {
2334 if (ndis_set_cipher(sc, n->ni_val))
2343 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2345 struct ieee80211vap *vap = ifp->if_softc;
2346 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2350 if (!NDIS_INITIALIZED(sc))
2353 len = sizeof(txrate);
2354 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2355 vap->iv_bss->ni_txrate = txrate / 5000;
2356 ieee80211_media_status(ifp, imr);
2360 ndis_setstate_80211(struct ndis_softc *sc)
2362 struct ieee80211com *ic = &sc->ndis_ic;
2363 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2364 ndis_80211_macaddr bssid;
2365 ndis_80211_config config;
2369 if (!NDIS_INITIALIZED(sc)) {
2370 DPRINTF(("%s: NDIS not initialized\n", __func__));
2374 /* Disassociate and turn off radio. */
2377 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2379 /* Set network infrastructure mode. */
2382 if (ic->ic_opmode == IEEE80211_M_IBSS)
2383 arg = NDIS_80211_NET_INFRA_IBSS;
2385 arg = NDIS_80211_NET_INFRA_BSS;
2387 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2390 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392 /* Set power management */
2394 if (vap->iv_flags & IEEE80211_F_PMGTON)
2395 arg = NDIS_80211_POWERMODE_FAST_PSP;
2397 arg = NDIS_80211_POWERMODE_CAM;
2398 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2401 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2402 ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2403 arg = dBm2mW[ic->ic_txpowlimit];
2405 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2409 * Default encryption mode to off, authentication
2410 * to open and privacy to 'accept everything.'
2413 arg = NDIS_80211_WEPSTAT_DISABLED;
2414 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2417 arg = NDIS_80211_AUTHMODE_OPEN;
2418 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2421 * Note that OID_802_11_PRIVACY_FILTER is optional:
2422 * not all drivers implement it.
2425 arg = NDIS_80211_PRIVFILT_8021XWEP;
2426 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2428 len = sizeof(config);
2429 bzero((char *)&config, len);
2430 config.nc_length = len;
2431 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2432 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2435 * Some drivers expect us to initialize these values, so
2436 * provide some defaults.
2439 if (config.nc_beaconperiod == 0)
2440 config.nc_beaconperiod = 100;
2441 if (config.nc_atimwin == 0)
2442 config.nc_atimwin = 100;
2443 if (config.nc_fhconfig.ncf_dwelltime == 0)
2444 config.nc_fhconfig.ncf_dwelltime = 200;
2445 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2448 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2449 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2450 IEEE80211_CHAN_5GHZ;
2451 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2452 config.nc_dsconfig =
2453 ic->ic_bsschan->ic_freq * 1000;
2454 len = sizeof(config);
2455 config.nc_length = len;
2456 config.nc_fhconfig.ncf_length =
2457 sizeof(ndis_80211_config_fh);
2458 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2459 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2462 device_printf(sc->ndis_dev, "couldn't change "
2463 "DS config to %ukHz: %d\n",
2464 config.nc_dsconfig, rval);
2467 device_printf(sc->ndis_dev, "couldn't retrieve "
2468 "channel info: %d\n", rval);
2470 /* Set the BSSID to our value so the driver doesn't associate */
2471 len = IEEE80211_ADDR_LEN;
2472 bcopy(vap->iv_myaddr, bssid, len);
2473 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2474 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2476 device_printf(sc->ndis_dev,
2477 "setting BSSID failed: %d\n", rval);
2481 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2483 struct ieee80211_node *ni = vap->iv_bss;
2484 ndis_80211_ssid ssid;
2485 ndis_80211_macaddr bssid;
2487 int i, rval = 0, len, error;
2490 if (!NDIS_INITIALIZED(sc)) {
2491 DPRINTF(("%s: NDIS not initialized\n", __func__));
2496 ndis_setstate_80211(sc);
2498 /* Set network infrastructure mode. */
2501 if (vap->iv_opmode == IEEE80211_M_IBSS)
2502 arg = NDIS_80211_NET_INFRA_IBSS;
2504 arg = NDIS_80211_NET_INFRA_BSS;
2506 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2509 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2511 /* Set RTS threshold */
2514 arg = vap->iv_rtsthreshold;
2515 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2517 /* Set fragmentation threshold */
2520 arg = vap->iv_fragthreshold;
2521 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2525 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2526 !(vap->iv_flags & IEEE80211_F_WPA)) {
2529 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2531 arg = NDIS_80211_AUTHMODE_SHARED;
2532 DPRINTF(("Setting shared auth\n"));
2533 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2536 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2537 if (vap->iv_nw_keys[i].wk_keylen) {
2538 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2539 IEEE80211_CIPHER_WEP)
2541 bzero((char *)&wep, sizeof(wep));
2542 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2545 * 5, 13 and 16 are the only valid
2546 * key lengths. Anything in between
2547 * will be zero padded out to the
2548 * next highest boundary.
2550 if (vap->iv_nw_keys[i].wk_keylen < 5)
2552 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2553 vap->iv_nw_keys[i].wk_keylen < 13)
2555 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2556 vap->iv_nw_keys[i].wk_keylen < 16)
2560 wep.nw_length = (sizeof(uint32_t) * 3)
2562 if (i == vap->iv_def_txkey)
2563 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2564 bcopy(vap->iv_nw_keys[i].wk_key,
2565 wep.nw_keydata, wep.nw_length);
2567 DPRINTF(("Setting WEP key %d\n", i));
2568 rval = ndis_set_info(sc,
2569 OID_802_11_ADD_WEP, &wep, &len);
2571 device_printf(sc->ndis_dev,
2572 "set wepkey failed: %d\n", rval);
2577 DPRINTF(("Setting WEP on\n"));
2578 arg = NDIS_80211_WEPSTAT_ENABLED;
2580 rval = ndis_set_info(sc,
2581 OID_802_11_WEP_STATUS, &arg, &len);
2583 device_printf(sc->ndis_dev,
2584 "enable WEP failed: %d\n", rval);
2585 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2586 arg = NDIS_80211_PRIVFILT_8021XWEP;
2588 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2592 OID_802_11_PRIVACY_FILTER, &arg, &len);
2597 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2598 vap->iv_appie_assocreq != NULL) {
2599 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2600 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2602 device_printf(sc->ndis_dev, "WPA setup failed\n");
2606 /* Set network type. */
2610 switch (vap->iv_curmode) {
2611 case IEEE80211_MODE_11A:
2612 arg = NDIS_80211_NETTYPE_11OFDM5;
2614 case IEEE80211_MODE_11B:
2615 arg = NDIS_80211_NETTYPE_11DS;
2617 case IEEE80211_MODE_11G:
2618 arg = NDIS_80211_NETTYPE_11OFDM24;
2621 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2626 DPRINTF(("Setting network type to %d\n", arg));
2628 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2631 device_printf(sc->ndis_dev,
2632 "set nettype failed: %d\n", rval);
2637 * If the user selected a specific BSSID, try
2638 * to use that one. This is useful in the case where
2639 * there are several APs in range with the same network
2640 * name. To delete the BSSID, we use the broadcast
2641 * address as the BSSID.
2642 * Note that some drivers seem to allow setting a BSSID
2643 * in ad-hoc mode, which has the effect of forcing the
2644 * NIC to create an ad-hoc cell with a specific BSSID,
2645 * instead of a randomly chosen one. However, the net80211
2646 * code makes the assumtion that the BSSID setting is invalid
2647 * when you're in ad-hoc mode, so we don't allow that here.
2650 len = IEEE80211_ADDR_LEN;
2651 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2652 vap->iv_opmode != IEEE80211_M_IBSS)
2653 bcopy(ni->ni_bssid, bssid, len);
2655 bcopy(ieee80211broadcastaddr, bssid, len);
2657 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2658 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2660 device_printf(sc->ndis_dev,
2661 "setting BSSID failed: %d\n", rval);
2663 /* Set SSID -- always do this last. */
2666 if (ndis_debug > 0) {
2667 printf("Setting ESSID to ");
2668 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2674 bzero((char *)&ssid, len);
2675 ssid.ns_ssidlen = ni->ni_esslen;
2676 if (ssid.ns_ssidlen == 0) {
2677 ssid.ns_ssidlen = 1;
2679 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2681 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2684 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2690 ndis_get_bssid_list(sc, bl)
2691 struct ndis_softc *sc;
2692 ndis_80211_bssid_list_ex **bl;
2696 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2697 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2701 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2702 if (error == ENOSPC) {
2703 free(*bl, M_DEVBUF);
2704 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2708 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2711 DPRINTF(("%s: failed to read\n", __func__));
2712 free(*bl, M_DEVBUF);
2720 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2722 struct ieee80211com *ic = &sc->ndis_ic;
2723 struct ieee80211vap *vap;
2724 struct ieee80211_node *ni;
2725 ndis_80211_bssid_list_ex *bl;
2726 ndis_wlan_bssid_ex *bs;
2727 ndis_80211_macaddr bssid;
2733 len = sizeof(bssid);
2734 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2736 device_printf(sc->ndis_dev, "failed to get bssid\n");
2740 vap = TAILQ_FIRST(&ic->ic_vaps);
2743 error = ndis_get_bssid_list(sc, &bl);
2747 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2748 for (i = 0; i < bl->nblx_items; i++) {
2749 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2750 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2751 if (*assoc == NULL) {
2755 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2757 if (ic->ic_opmode == IEEE80211_M_STA)
2758 ni->ni_associd = 1 | 0xc000; /* fake associd */
2761 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2769 ndis_getstate_80211(struct ndis_softc *sc)
2771 struct ieee80211com *ic = &sc->ndis_ic;
2772 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2773 struct ieee80211_node *ni = vap->iv_bss;
2774 ndis_wlan_bssid_ex *bs;
2775 int rval, len, i = 0;
2779 if (!NDIS_INITIALIZED(sc))
2782 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2785 /* We're associated, retrieve info on the current bssid. */
2786 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2787 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2788 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2790 /* Get SSID from current association info. */
2791 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2792 bs->nwbx_ssid.ns_ssidlen);
2793 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2795 if (ic->ic_caps & IEEE80211_C_PMGT) {
2797 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2800 device_printf(sc->ndis_dev,
2801 "get power mode failed: %d\n", rval);
2802 if (arg == NDIS_80211_POWERMODE_CAM)
2803 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2805 vap->iv_flags |= IEEE80211_F_PMGTON;
2809 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2811 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2812 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2813 if (dBm2mW[i] >= arg)
2815 ic->ic_txpowlimit = i;
2819 * Use the current association information to reflect
2820 * what channel we're on.
2822 ic->ic_curchan = ieee80211_find_channel(ic,
2823 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2824 if (ic->ic_curchan == NULL)
2825 ic->ic_curchan = &ic->ic_channels[0];
2826 ni->ni_chan = ic->ic_curchan;
2827 ic->ic_bsschan = ic->ic_curchan;
2832 * Determine current authentication mode.
2835 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2837 device_printf(sc->ndis_dev,
2838 "get authmode status failed: %d\n", rval);
2840 vap->iv_flags &= ~IEEE80211_F_WPA;
2842 case NDIS_80211_AUTHMODE_OPEN:
2843 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2845 case NDIS_80211_AUTHMODE_SHARED:
2846 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2848 case NDIS_80211_AUTHMODE_AUTO:
2849 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2851 case NDIS_80211_AUTHMODE_WPA:
2852 case NDIS_80211_AUTHMODE_WPAPSK:
2853 case NDIS_80211_AUTHMODE_WPANONE:
2854 ni->ni_authmode = IEEE80211_AUTH_WPA;
2855 vap->iv_flags |= IEEE80211_F_WPA1;
2857 case NDIS_80211_AUTHMODE_WPA2:
2858 case NDIS_80211_AUTHMODE_WPA2PSK:
2859 ni->ni_authmode = IEEE80211_AUTH_WPA;
2860 vap->iv_flags |= IEEE80211_F_WPA2;
2863 ni->ni_authmode = IEEE80211_AUTH_NONE;
2869 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2872 device_printf(sc->ndis_dev,
2873 "get wep status failed: %d\n", rval);
2875 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2876 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2878 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2882 ndis_ioctl(ifp, command, data)
2887 struct ndis_softc *sc = ifp->if_softc;
2888 struct ifreq *ifr = (struct ifreq *) data;
2895 if (ifp->if_flags & IFF_UP) {
2896 if (sc->ndis_running &&
2897 ifp->if_flags & IFF_PROMISC &&
2898 !(sc->ndis_if_flags & IFF_PROMISC)) {
2900 NDIS_PACKET_TYPE_PROMISCUOUS;
2901 i = sizeof(sc->ndis_filter);
2902 error = ndis_set_info(sc,
2903 OID_GEN_CURRENT_PACKET_FILTER,
2904 &sc->ndis_filter, &i);
2905 } else if (sc->ndis_running &&
2906 !(ifp->if_flags & IFF_PROMISC) &&
2907 sc->ndis_if_flags & IFF_PROMISC) {
2909 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2910 i = sizeof(sc->ndis_filter);
2911 error = ndis_set_info(sc,
2912 OID_GEN_CURRENT_PACKET_FILTER,
2913 &sc->ndis_filter, &i);
2917 if (sc->ndis_running)
2920 sc->ndis_if_flags = ifp->if_flags;
2930 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2933 ifp->if_capenable = ifr->ifr_reqcap;
2934 if (ifp->if_capenable & IFCAP_TXCSUM)
2935 ifp->if_hwassist = sc->ndis_hwassist;
2937 ifp->if_hwassist = 0;
2938 ndis_set_offload(sc);
2941 error = ether_ioctl(ifp, command, data);
2945 /*NDIS_UNLOCK(sc);*/
2951 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2953 struct ndis_softc *sc = ic->ic_softc;
2954 struct ifreq *ifr = data;
2955 struct ndis_oid_data oid;
2956 struct ndis_evt evt;
2957 void *oidbuf = NULL;
2960 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2966 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2969 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2970 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2974 free(oidbuf, M_TEMP);
2980 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2983 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2985 case SIOCGPRIVATE_0:
2987 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2992 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2997 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3002 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3003 ifr->ifr_data, sizeof(uint32_t) * 2);
3008 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3009 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3010 ifr->ifr_data + (sizeof(uint32_t) * 2),
3011 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3016 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3017 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3019 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3020 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3021 NDIS_EVTINC(sc->ndis_evtcidx);
3032 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3035 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3038 free(oidbuf, M_TEMP);
3044 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3046 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3047 ndis_80211_key rkey;
3050 bzero((char *)&rkey, sizeof(rkey));
3054 rkey.nk_keyidx = key->wk_keyix;
3056 bcopy(vap->iv_ifp->if_broadcastaddr,
3057 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3059 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3068 * In theory this could be called for any key, but we'll
3069 * only use it for WPA TKIP or AES keys. These need to be
3070 * set after initial authentication with the AP.
3073 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3075 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3076 ndis_80211_key rkey;
3079 switch (key->wk_cipher->ic_cipher) {
3080 case IEEE80211_CIPHER_TKIP:
3082 len = sizeof(ndis_80211_key);
3083 bzero((char *)&rkey, sizeof(rkey));
3086 rkey.nk_keylen = key->wk_keylen;
3088 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3089 rkey.nk_keylen += 16;
3091 /* key index - gets weird in NDIS */
3093 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3094 rkey.nk_keyidx = key->wk_keyix;
3098 if (key->wk_flags & IEEE80211_KEY_XMIT)
3099 rkey.nk_keyidx |= 1 << 31;
3101 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3102 bcopy(ieee80211broadcastaddr,
3103 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3105 bcopy(vap->iv_bss->ni_bssid,
3106 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3108 rkey.nk_keyidx |= 1 << 30;
3111 /* need to set bit 29 based on keyrsc */
3112 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3115 rkey.nk_keyidx |= 1 << 29;
3117 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3118 bcopy(key->wk_key, rkey.nk_keydata, 16);
3119 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3120 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3122 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3124 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3126 case IEEE80211_CIPHER_WEP:
3130 * I don't know how to set up keys for the AES
3131 * cipher yet. Is it the same as TKIP?
3133 case IEEE80211_CIPHER_AES_CCM:
3139 /* We need to return 1 for success, 0 for failure. */
3148 ndis_resettask(d, arg)
3152 struct ndis_softc *sc;
3159 * Stop the adapter and free any mbufs allocated to the
3163 ndis_stop(struct ndis_softc *sc)
3167 callout_drain(&sc->ndis_stat_callout);
3170 sc->ndis_tx_timer = 0;
3172 if (!sc->ndis_80211)
3173 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3174 sc->ndis_running = 0;
3177 if (sc->ndis_iftype != PNPBus ||
3178 (sc->ndis_iftype == PNPBus &&
3179 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3184 for (i = 0; i < NDIS_EVENTS; i++) {
3185 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3186 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3187 sc->ndis_evt[i].ne_buf = NULL;
3189 sc->ndis_evt[i].ne_sts = 0;
3190 sc->ndis_evt[i].ne_len = 0;
3192 sc->ndis_evtcidx = 0;
3193 sc->ndis_evtpidx = 0;
3198 * Stop all chip I/O so that the kernel's probe routines don't
3199 * get confused by errant DMAs when rebooting.
3205 struct ndis_softc *sc;
3207 sc = device_get_softc(dev);
3212 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3214 struct ndis_vap *nvp = NDIS_VAP(vap);
3215 struct ieee80211com *ic = vap->iv_ic;
3216 struct ndis_softc *sc = ic->ic_softc;
3217 enum ieee80211_state ostate;
3219 DPRINTF(("%s: %s -> %s\n", __func__,
3220 ieee80211_state_name[vap->iv_state],
3221 ieee80211_state_name[nstate]));
3223 ostate = vap->iv_state;
3224 vap->iv_state = nstate;
3227 /* pass on to net80211 */
3228 case IEEE80211_S_INIT:
3229 case IEEE80211_S_SCAN:
3230 return nvp->newstate(vap, nstate, arg);
3231 case IEEE80211_S_ASSOC:
3232 if (ostate != IEEE80211_S_AUTH) {
3233 IEEE80211_UNLOCK(ic);
3234 ndis_auth_and_assoc(sc, vap);
3238 case IEEE80211_S_AUTH:
3239 IEEE80211_UNLOCK(ic);
3240 ndis_auth_and_assoc(sc, vap);
3241 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3242 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3252 ndis_scan(void *arg)
3254 struct ieee80211vap *vap = arg;
3256 ieee80211_scan_done(vap);
3260 ndis_scan_results(struct ndis_softc *sc)
3262 struct ieee80211com *ic = &sc->ndis_ic;
3263 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3264 ndis_80211_bssid_list_ex *bl;
3265 ndis_wlan_bssid_ex *wb;
3266 struct ieee80211_scanparams sp;
3267 struct ieee80211_frame wh;
3268 struct ieee80211_channel *saved_chan;
3270 int rssi, noise, freq, chanflag;
3271 uint8_t ssid[2+IEEE80211_NWID_LEN];
3272 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3273 uint8_t *frm, *efrm;
3275 saved_chan = ic->ic_curchan;
3278 if (ndis_get_bssid_list(sc, &bl))
3281 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3282 wb = &bl->nblx_bssid[0];
3283 for (i = 0; i < bl->nblx_items; i++) {
3284 memset(&sp, 0, sizeof(sp));
3286 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3287 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3288 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3289 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3290 if (wb->nwbx_privacy)
3291 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3292 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3293 switch (wb->nwbx_netinfra) {
3294 case NDIS_80211_NET_INFRA_IBSS:
3295 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3297 case NDIS_80211_NET_INFRA_BSS:
3298 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3301 sp.rates = &rates[0];
3302 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3303 /* XXX - check units */
3304 if (wb->nwbx_supportedrates[j] == 0)
3307 wb->nwbx_supportedrates[j] & 0x7f;
3310 sp.ssid = (uint8_t *)&ssid[0];
3311 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3312 wb->nwbx_ssid.ns_ssidlen);
3313 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3315 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3316 freq = wb->nwbx_config.nc_dsconfig / 1000;
3317 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3318 /* Hack ic->ic_curchan to be in sync with the scan result */
3319 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3320 if (ic->ic_curchan == NULL)
3321 ic->ic_curchan = &ic->ic_channels[0];
3323 /* Process extended info from AP */
3324 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3325 frm = (uint8_t *)&wb->nwbx_ies;
3326 efrm = frm + wb->nwbx_ielen;
3327 if (efrm - frm < 12)
3329 sp.tstamp = frm; frm += 8;
3330 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3331 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3333 sp.ies_len = efrm - frm;
3336 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3337 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3339 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3340 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3343 /* Restore the channel after messing with it */
3344 ic->ic_curchan = saved_chan;
3348 ndis_scan_start(struct ieee80211com *ic)
3350 struct ndis_softc *sc = ic->ic_softc;
3351 struct ieee80211vap *vap;
3352 struct ieee80211_scan_state *ss;
3353 ndis_80211_ssid ssid;
3357 vap = TAILQ_FIRST(&ic->ic_vaps);
3359 if (!NDIS_INITIALIZED(sc)) {
3360 DPRINTF(("%s: scan aborted\n", __func__));
3361 ieee80211_cancel_scan(vap);
3366 bzero((char *)&ssid, len);
3367 if (ss->ss_nssid == 0)
3368 ssid.ns_ssidlen = 1;
3370 /* Perform a directed scan */
3371 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3372 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3375 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3377 DPRINTF(("%s: set ESSID failed\n", __func__));
3380 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3382 DPRINTF(("%s: scan command failed\n", __func__));
3383 ieee80211_cancel_scan(vap);
3386 /* Set a timer to collect the results */
3387 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3391 ndis_set_channel(struct ieee80211com *ic)
3397 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3403 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3405 /* NB: don't try to abort scan; wait for firmware to finish */
3409 ndis_scan_end(struct ieee80211com *ic)
3411 struct ndis_softc *sc = ic->ic_softc;
3413 ndis_scan_results(sc);