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;
727 int mode, i, r, len, nonettypes = 1;
728 uint8_t bands[howmany(IEEE80211_MODE_MAX, 8)] = { 0 };
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]);
755 setbit(ic->ic_modecaps, mode);
758 device_printf(sc->ndis_dev, "Unknown nettype %d\n",
763 /* Default to 11b channels if the card did not supply any */
765 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
766 setbit(bands, IEEE80211_MODE_11B);
769 bzero((char *)&rates, len);
770 r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
772 device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
774 * Since the supported rates only up to 8 can be supported,
775 * if this is not 802.11b we're just going to be faking it
779 #define TESTSETRATE(x, y) \
782 for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \
783 if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \
786 if (i == ic->ic_sup_rates[x].rs_nrates) { \
787 ic->ic_sup_rates[x].rs_rates[i] = (y); \
788 ic->ic_sup_rates[x].rs_nrates++; \
792 #define SETRATE(x, y) \
793 ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
795 ic->ic_sup_rates[x].rs_nrates++
797 ic->ic_curmode = IEEE80211_MODE_AUTO;
798 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
799 ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
800 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
801 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
802 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
803 ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
804 for (i = 0; i < len; i++) {
805 switch (rates[i] & IEEE80211_RATE_VAL) {
811 if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
812 /* Lazy-init 802.11b. */
813 setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
814 ic->ic_sup_rates[IEEE80211_MODE_11B].
817 SETRATE(IEEE80211_MODE_11B, rates[i]);
818 INCRATE(IEEE80211_MODE_11B);
821 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
822 SETRATE(IEEE80211_MODE_11A, rates[i]);
823 INCRATE(IEEE80211_MODE_11A);
825 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
826 SETRATE(IEEE80211_MODE_11G, rates[i]);
827 INCRATE(IEEE80211_MODE_11G);
834 * If the hardware supports 802.11g, it most
835 * likely supports 802.11b and all of the
836 * 802.11b and 802.11g speeds, so maybe we can
837 * just cheat here. Just how in the heck do
838 * we detect turbo modes, though?
840 if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
841 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
842 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
843 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
844 TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
846 if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
847 TESTSETRATE(IEEE80211_MODE_11G, 48);
848 TESTSETRATE(IEEE80211_MODE_11G, 72);
849 TESTSETRATE(IEEE80211_MODE_11G, 96);
850 TESTSETRATE(IEEE80211_MODE_11G, 108);
852 if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
853 TESTSETRATE(IEEE80211_MODE_11A, 48);
854 TESTSETRATE(IEEE80211_MODE_11A, 72);
855 TESTSETRATE(IEEE80211_MODE_11A, 96);
856 TESTSETRATE(IEEE80211_MODE_11A, 108);
863 ieee80211_init_channels(ic, NULL, bands);
866 * To test for WPA support, we need to see if we can
867 * set AUTHENTICATION_MODE to WPA and read it back
871 arg = NDIS_80211_AUTHMODE_WPA;
872 r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
874 r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
875 if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
876 ic->ic_caps |= IEEE80211_C_WPA;
880 * To test for supported ciphers, we set each
881 * available encryption type in descending order.
882 * If ENC3 works, then we have WEP, TKIP and AES.
883 * If only ENC2 works, then we have WEP and TKIP.
884 * If only ENC1 works, then we have just WEP.
887 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
888 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
890 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
891 | IEEE80211_CRYPTO_TKIP
892 | IEEE80211_CRYPTO_AES_CCM;
895 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
896 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
898 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
899 | IEEE80211_CRYPTO_TKIP;
902 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
903 r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
905 ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
908 r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
910 ic->ic_caps |= IEEE80211_C_PMGT;
912 r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
914 ic->ic_caps |= IEEE80211_C_TXPMGT;
917 * Get station address from the driver.
919 len = sizeof(ic->ic_macaddr);
920 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
922 ieee80211_ifattach(ic);
923 ic->ic_raw_xmit = ndis_raw_xmit;
924 ic->ic_scan_start = ndis_scan_start;
925 ic->ic_scan_end = ndis_scan_end;
926 ic->ic_set_channel = ndis_set_channel;
927 ic->ic_scan_curchan = ndis_scan_curchan;
928 ic->ic_scan_mindwell = ndis_scan_mindwell;
929 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
930 ic->ic_vap_create = ndis_vap_create;
931 ic->ic_vap_delete = ndis_vap_delete;
932 ic->ic_update_mcast = ndis_update_mcast;
933 ic->ic_update_promisc = ndis_update_promisc;
934 ic->ic_transmit = ndis_80211transmit;
935 ic->ic_parent = ndis_80211parent;
938 ieee80211_announce(ic);
944 ndis_ifattach(struct ndis_softc *sc)
947 u_char eaddr[ETHER_ADDR_LEN];
950 ifp = if_alloc(IFT_ETHER);
956 /* Check for task offload support. */
957 ndis_probe_offload(sc);
960 * Get station address from the driver.
963 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
965 if_initname(ifp, device_get_name(sc->ndis_dev),
966 device_get_unit(sc->ndis_dev));
967 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
968 ifp->if_ioctl = ndis_ioctl;
969 ifp->if_start = ndis_start;
970 ifp->if_init = ndis_init;
971 ifp->if_baudrate = 10000000;
972 IFQ_SET_MAXLEN(&ifp->if_snd, 50);
973 ifp->if_snd.ifq_drv_maxlen = 25;
974 IFQ_SET_READY(&ifp->if_snd);
975 ifp->if_capenable = ifp->if_capabilities;
976 ifp->if_hwassist = sc->ndis_hwassist;
978 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
980 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
981 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
982 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
983 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
984 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
985 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
986 ether_ifattach(ifp, eaddr);
991 static struct ieee80211vap *
992 ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
993 enum ieee80211_opmode opmode, int flags,
994 const uint8_t bssid[IEEE80211_ADDR_LEN],
995 const uint8_t mac[IEEE80211_ADDR_LEN])
997 struct ndis_vap *nvp;
998 struct ieee80211vap *vap;
1000 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1002 nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1004 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1005 /* override with driver methods */
1006 nvp->newstate = vap->iv_newstate;
1007 vap->iv_newstate = ndis_newstate;
1009 /* complete setup */
1010 ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1012 ic->ic_opmode = opmode;
1013 /* install key handing routines */
1014 vap->iv_key_set = ndis_add_key;
1015 vap->iv_key_delete = ndis_del_key;
1020 ndis_vap_delete(struct ieee80211vap *vap)
1022 struct ndis_vap *nvp = NDIS_VAP(vap);
1023 struct ieee80211com *ic = vap->iv_ic;
1024 struct ndis_softc *sc = ic->ic_softc;
1027 callout_drain(&sc->ndis_scan_callout);
1028 ieee80211_vap_detach(vap);
1029 free(nvp, M_80211_VAP);
1033 * Shutdown hardware and free up resources. This can be called any
1034 * time after the mutex has been initialized. It is called in both
1035 * the error case in attach and the normal detach case so it needs
1036 * to be careful about only freeing resources that have actually been
1040 ndis_detach(device_t dev)
1043 struct ndis_softc *sc;
1046 sc = device_get_softc(dev);
1048 if (!sc->ndis_80211)
1053 ifp->if_flags &= ~IFF_UP;
1054 if (device_is_attached(dev)) {
1058 ieee80211_ifdetach(&sc->ndis_ic);
1059 else if (ifp != NULL)
1060 ether_ifdetach(ifp);
1064 if (sc->ndis_tickitem != NULL)
1065 IoFreeWorkItem(sc->ndis_tickitem);
1066 if (sc->ndis_startitem != NULL)
1067 IoFreeWorkItem(sc->ndis_startitem);
1068 if (sc->ndis_resetitem != NULL)
1069 IoFreeWorkItem(sc->ndis_resetitem);
1070 if (sc->ndis_inputitem != NULL)
1071 IoFreeWorkItem(sc->ndis_inputitem);
1072 if (sc->ndisusb_xferdoneitem != NULL)
1073 IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1074 if (sc->ndisusb_taskitem != NULL)
1075 IoFreeWorkItem(sc->ndisusb_taskitem);
1077 bus_generic_detach(dev);
1078 ndis_unload_driver(sc);
1081 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1082 if (sc->ndis_res_io)
1083 bus_release_resource(dev, SYS_RES_IOPORT,
1084 sc->ndis_io_rid, sc->ndis_res_io);
1085 if (sc->ndis_res_mem)
1086 bus_release_resource(dev, SYS_RES_MEMORY,
1087 sc->ndis_mem_rid, sc->ndis_res_mem);
1088 if (sc->ndis_res_altmem)
1089 bus_release_resource(dev, SYS_RES_MEMORY,
1090 sc->ndis_altmem_rid, sc->ndis_res_altmem);
1095 if (sc->ndis_iftype == PCMCIABus)
1099 ndis_destroy_dma(sc);
1101 if (sc->ndis_txarray)
1102 free(sc->ndis_txarray, M_DEVBUF);
1104 if (!sc->ndis_80211)
1105 ifmedia_removeall(&sc->ifmedia);
1107 if (sc->ndis_txpool != NULL)
1108 NdisFreePacketPool(sc->ndis_txpool);
1110 /* Destroy the PDO for this device. */
1112 if (sc->ndis_iftype == PCIBus)
1113 drv = windrv_lookup(0, "PCI Bus");
1114 else if (sc->ndis_iftype == PCMCIABus)
1115 drv = windrv_lookup(0, "PCCARD Bus");
1117 drv = windrv_lookup(0, "USB Bus");
1119 panic("couldn't find driver object");
1120 windrv_destroy_pdo(drv, dev);
1122 if (sc->ndis_iftype == PCIBus)
1123 bus_dma_tag_destroy(sc->ndis_parent_tag);
1132 struct ndis_softc *sc;
1135 sc = device_get_softc(dev);
1139 if (NDIS_INITIALIZED(sc))
1150 struct ndis_softc *sc;
1153 sc = device_get_softc(dev);
1156 if (NDIS_INITIALIZED(sc))
1163 * The following bunch of routines are here to support drivers that
1164 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1165 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1166 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1170 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1171 ndis_handle adapter;
1177 uint32_t lookaheadlen;
1180 ndis_miniport_block *block;
1190 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1194 /* Save the data provided to us so far. */
1196 m->m_len = lookaheadlen + hdrlen;
1197 m->m_pkthdr.len = pktlen + hdrlen;
1199 m_copyback(m, 0, hdrlen, hdr);
1200 m_copyback(m, hdrlen, lookaheadlen, lookahead);
1202 /* Now create a fake NDIS_PACKET to hold the data */
1204 NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1206 if (status != NDIS_STATUS_SUCCESS) {
1213 b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1221 p->np_private.npp_head = p->np_private.npp_tail = b;
1222 p->np_private.npp_totlen = m->m_pkthdr.len;
1224 /* Save the packet RX context somewhere. */
1225 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1226 priv->nep_ctx = ctx;
1228 if (!NDIS_SERIALIZED(block))
1229 KeAcquireSpinLock(&block->nmb_lock, &irql);
1231 InsertTailList((&block->nmb_packetlist), (&p->np_list));
1233 if (!NDIS_SERIALIZED(block))
1234 KeReleaseSpinLock(&block->nmb_lock, irql);
1238 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1243 ndis_rxeof_done(adapter)
1244 ndis_handle adapter;
1246 struct ndis_softc *sc;
1247 ndis_miniport_block *block;
1251 /* Schedule transfer/RX of queued packets. */
1253 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1255 KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1259 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1262 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1264 ndis_handle adapter;
1268 ndis_miniport_block *block;
1269 struct ndis_softc *sc;
1278 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1281 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1283 l = block->nmb_packetlist.nle_flink;
1284 while(!IsListEmpty(&block->nmb_packetlist)) {
1285 l = RemoveHeadList((&block->nmb_packetlist));
1286 p = CONTAINING_RECORD(l, ndis_packet, np_list);
1287 InitializeListHead((&p->np_list));
1289 priv = (ndis_ethpriv *)&p->np_protocolreserved;
1294 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1296 status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1297 p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1298 m->m_len, m->m_pkthdr.len - m->m_len);
1300 KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1303 * If status is NDIS_STATUS_PENDING, do nothing and
1304 * wait for a callback to the ndis_rxeof_xfr_done()
1308 m->m_len = m->m_pkthdr.len;
1309 m->m_pkthdr.rcvif = ifp;
1311 if (status == NDIS_STATUS_SUCCESS) {
1312 IoFreeMdl(p->np_private.npp_head);
1314 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1315 mbufq_enqueue(&sc->ndis_rxqueue, m);
1316 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1317 IoQueueWorkItem(sc->ndis_inputitem,
1318 (io_workitem_func)ndis_inputtask_wrap,
1319 WORKQUEUE_CRITICAL, sc);
1322 if (status == NDIS_STATUS_FAILURE)
1325 /* Advance to next packet */
1326 l = block->nmb_packetlist.nle_flink;
1329 KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1333 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1336 ndis_rxeof_xfr_done(adapter, packet, status, len)
1337 ndis_handle adapter;
1338 ndis_packet *packet;
1342 ndis_miniport_block *block;
1343 struct ndis_softc *sc;
1348 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1352 IoFreeMdl(packet->np_private.npp_head);
1353 NdisFreePacket(packet);
1355 if (status != NDIS_STATUS_SUCCESS) {
1360 m->m_len = m->m_pkthdr.len;
1361 m->m_pkthdr.rcvif = ifp;
1362 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1363 mbufq_enqueue(&sc->ndis_rxqueue, m);
1364 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1365 IoQueueWorkItem(sc->ndis_inputitem,
1366 (io_workitem_func)ndis_inputtask_wrap,
1367 WORKQUEUE_CRITICAL, sc);
1370 * A frame has been uploaded: pass the resulting mbuf chain up to
1371 * the higher level protocols.
1373 * When handling received NDIS packets, the 'status' field in the
1374 * out-of-band portion of the ndis_packet has special meaning. In the
1375 * most common case, the underlying NDIS driver will set this field
1376 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1377 * take posession of it. We then change the status field to
1378 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1379 * and that we will return it at some point in the future via the
1380 * return packet handler.
1382 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1383 * this means the driver is running out of packet/buffer resources and
1384 * wants to maintain ownership of the packet. In this case, we have to
1385 * copy the packet data into local storage and let the driver keep the
1389 ndis_rxeof(adapter, packets, pktcnt)
1390 ndis_handle adapter;
1391 ndis_packet **packets;
1394 struct ndis_softc *sc;
1395 ndis_miniport_block *block;
1398 ndis_tcpip_csum *csum;
1400 struct mbuf *m0, *m;
1403 block = (ndis_miniport_block *)adapter;
1404 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1408 * There's a slim chance the driver may indicate some packets
1409 * before we're completely ready to handle them. If we detect this,
1410 * we need to return them to the miniport and ignore them.
1412 if (!sc->ndis_running) {
1413 for (i = 0; i < pktcnt; i++) {
1415 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1417 (void)ndis_return_packet(NULL ,p, block);
1423 for (i = 0; i < pktcnt; i++) {
1425 /* Stash the softc here so ptom can use it. */
1427 if (ndis_ptom(&m0, p)) {
1428 device_printf(sc->ndis_dev, "ptom failed\n");
1429 if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1430 (void)ndis_return_packet(NULL, p, block);
1433 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1434 m = m_dup(m0, M_NOWAIT);
1436 * NOTE: we want to destroy the mbuf here, but
1437 * we don't actually want to return it to the
1438 * driver via the return packet handler. By
1439 * bumping np_refcnt, we can prevent the
1440 * ndis_return_packet() routine from actually
1446 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1450 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1452 m = m_dup(m0, M_NOWAIT);
1453 if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1456 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1459 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1463 m0->m_pkthdr.rcvif = ifp;
1465 /* Deal with checksum offload. */
1467 if (ifp->if_capenable & IFCAP_RXCSUM &&
1468 p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1470 p->np_ext.npe_info[ndis_tcpipcsum_info];
1471 csum = (ndis_tcpip_csum *)&s;
1472 if (csum->u.ntc_rxflags &
1473 NDIS_RXCSUM_IP_PASSED)
1474 m0->m_pkthdr.csum_flags |=
1475 CSUM_IP_CHECKED|CSUM_IP_VALID;
1476 if (csum->u.ntc_rxflags &
1477 (NDIS_RXCSUM_TCP_PASSED |
1478 NDIS_RXCSUM_UDP_PASSED)) {
1479 m0->m_pkthdr.csum_flags |=
1480 CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1481 m0->m_pkthdr.csum_data = 0xFFFF;
1485 KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1486 mbufq_enqueue(&sc->ndis_rxqueue, m0);
1487 KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1488 IoQueueWorkItem(sc->ndis_inputitem,
1489 (io_workitem_func)ndis_inputtask_wrap,
1490 WORKQUEUE_CRITICAL, sc);
1496 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1497 * packets into the stack in order to avoid calling (*ifp->if_input)()
1498 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1499 * 'dispatch level' per-cpu sleep lock).
1502 ndis_inputtask(device_object *dobj, void *arg)
1504 ndis_miniport_block *block;
1505 struct ndis_softc *sc = arg;
1509 block = dobj->do_devext;
1511 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1512 while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1513 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1514 if ((sc->ndis_80211 != 0)) {
1515 struct ieee80211com *ic = &sc->ndis_ic;
1516 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1519 vap->iv_deliver_data(vap, vap->iv_bss, m);
1521 struct ifnet *ifp = sc->ifp;
1523 (*ifp->if_input)(ifp, m);
1525 KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1527 KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1531 * A frame was downloaded to the chip. It's safe for us to clean up
1535 ndis_txeof(adapter, packet, status)
1536 ndis_handle adapter;
1537 ndis_packet *packet;
1541 struct ndis_softc *sc;
1542 ndis_miniport_block *block;
1547 block = (ndis_miniport_block *)adapter;
1548 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1552 idx = packet->np_txidx;
1554 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1556 ndis_free_packet(packet);
1560 sc->ndis_txarray[idx] = NULL;
1561 sc->ndis_txpending++;
1563 if (status == NDIS_STATUS_SUCCESS)
1564 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1566 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1568 sc->ndis_tx_timer = 0;
1569 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1573 IoQueueWorkItem(sc->ndis_startitem,
1574 (io_workitem_func)ndis_starttask_wrap,
1575 WORKQUEUE_CRITICAL, ifp);
1579 ndis_linksts(adapter, status, sbuf, slen)
1580 ndis_handle adapter;
1585 ndis_miniport_block *block;
1586 struct ndis_softc *sc;
1589 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1590 sc->ndis_sts = status;
1592 /* Event list is all full up, drop this one. */
1595 if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1600 /* Cache the event. */
1603 sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1605 if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1610 sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1612 sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1613 sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1614 NDIS_EVTINC(sc->ndis_evtpidx);
1619 ndis_linksts_done(adapter)
1620 ndis_handle adapter;
1622 ndis_miniport_block *block;
1623 struct ndis_softc *sc;
1627 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1630 if (!NDIS_INITIALIZED(sc))
1633 switch (sc->ndis_sts) {
1634 case NDIS_STATUS_MEDIA_CONNECT:
1635 IoQueueWorkItem(sc->ndis_tickitem,
1636 (io_workitem_func)ndis_ticktask_wrap,
1637 WORKQUEUE_CRITICAL, sc);
1638 IoQueueWorkItem(sc->ndis_startitem,
1639 (io_workitem_func)ndis_starttask_wrap,
1640 WORKQUEUE_CRITICAL, ifp);
1642 case NDIS_STATUS_MEDIA_DISCONNECT:
1644 IoQueueWorkItem(sc->ndis_tickitem,
1645 (io_workitem_func)ndis_ticktask_wrap,
1646 WORKQUEUE_CRITICAL, sc);
1657 struct ndis_softc *sc;
1661 if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1662 IoQueueWorkItem(sc->ndis_tickitem,
1663 (io_workitem_func)ndis_ticktask_wrap,
1664 WORKQUEUE_CRITICAL, sc);
1665 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1668 if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1669 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1670 device_printf(sc->ndis_dev, "watchdog timeout\n");
1672 IoQueueWorkItem(sc->ndis_resetitem,
1673 (io_workitem_func)ndis_resettask_wrap,
1674 WORKQUEUE_CRITICAL, sc);
1675 IoQueueWorkItem(sc->ndis_startitem,
1676 (io_workitem_func)ndis_starttask_wrap,
1677 WORKQUEUE_CRITICAL, sc->ifp);
1680 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1684 ndis_ticktask(device_object *d, void *xsc)
1686 struct ndis_softc *sc = xsc;
1687 ndis_checkforhang_handler hangfunc;
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) {
1712 if (sc->ndis_80211 != 0) {
1713 struct ieee80211com *ic = &sc->ndis_ic;
1714 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1718 ndis_getstate_80211(sc);
1719 ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1721 if_link_state_change(vap->iv_ifp,
1725 if_link_state_change(sc->ifp, LINK_STATE_UP);
1728 if (sc->ndis_link == 1 &&
1729 sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1731 if (sc->ndis_80211 != 0) {
1732 struct ieee80211com *ic = &sc->ndis_ic;
1733 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1737 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1739 if_link_state_change(vap->iv_ifp,
1743 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1750 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1752 bus_dma_segment_t *segs;
1758 struct ndis_sc_list *sclist;
1761 if (error || arg == NULL)
1766 sclist->nsl_frags = nseg;
1768 for (i = 0; i < nseg; i++) {
1769 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1770 sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1775 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1776 const struct ieee80211_bpf_params *params)
1778 /* no support; just discard */
1780 ieee80211_free_node(ni);
1785 ndis_update_mcast(struct ieee80211com *ic)
1787 struct ndis_softc *sc = ic->ic_softc;
1793 ndis_update_promisc(struct ieee80211com *ic)
1799 ndis_starttask(d, arg)
1807 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1812 * Main transmit routine. To make NDIS drivers happy, we need to
1813 * transform mbuf chains into NDIS packets and feed them to the
1814 * send packet routines. Most drivers allow you to send several
1815 * packets at once (up to the maxpkts limit). Unfortunately, rather
1816 * that accepting them in the form of a linked list, they expect
1817 * a contiguous array of pointers to packets.
1819 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1820 * we need to perform busdma work here. Those that use map registers
1821 * will do the mapping themselves on a buffer by buffer basis.
1827 struct ndis_softc *sc;
1828 struct mbuf *m = NULL;
1829 ndis_packet **p0 = NULL, *p = NULL;
1830 ndis_tcpip_csum *csum;
1831 int pcnt = 0, status;
1836 if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1841 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1843 while(sc->ndis_txpending) {
1844 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1848 NdisAllocatePacket(&status,
1849 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1851 if (status != NDIS_STATUS_SUCCESS)
1854 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1855 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1861 * Save pointer to original mbuf
1862 * so we can free it later.
1865 p = sc->ndis_txarray[sc->ndis_txidx];
1866 p->np_txidx = sc->ndis_txidx;
1868 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1871 * Do scatter/gather processing, if driver requested it.
1874 bus_dmamap_load_mbuf(sc->ndis_ttag,
1875 sc->ndis_tmaps[sc->ndis_txidx], m,
1876 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1877 bus_dmamap_sync(sc->ndis_ttag,
1878 sc->ndis_tmaps[sc->ndis_txidx],
1879 BUS_DMASYNC_PREREAD);
1880 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1883 /* Handle checksum offload. */
1885 if (ifp->if_capenable & IFCAP_TXCSUM &&
1886 m->m_pkthdr.csum_flags) {
1887 csum = (ndis_tcpip_csum *)
1888 &p->np_ext.npe_info[ndis_tcpipcsum_info];
1889 csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1890 if (m->m_pkthdr.csum_flags & CSUM_IP)
1891 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1892 if (m->m_pkthdr.csum_flags & CSUM_TCP)
1893 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1894 if (m->m_pkthdr.csum_flags & CSUM_UDP)
1895 csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1896 p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1900 sc->ndis_txpending--;
1905 * If there's a BPF listener, bounce a copy of this frame
1908 if (!sc->ndis_80211) /* XXX handle 80211 */
1912 * The array that p0 points to must appear contiguous,
1913 * so we must not wrap past the end of sc->ndis_txarray[].
1914 * If it looks like we're about to wrap, break out here
1915 * so the this batch of packets can be transmitted, then
1916 * wait for txeof to ask us to send the rest.
1918 if (sc->ndis_txidx == 0)
1927 if (sc->ndis_txpending == 0)
1928 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1931 * Set a timeout in case the chip goes out to lunch.
1933 sc->ndis_tx_timer = 5;
1938 * According to NDIS documentation, if a driver exports
1939 * a MiniportSendPackets() routine, we prefer that over
1940 * a MiniportSend() routine (which sends just a single
1943 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1944 ndis_send_packets(sc, p0, pcnt);
1946 ndis_send_packet(sc, p);
1952 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1954 struct ndis_softc *sc = ic->ic_softc;
1955 ndis_packet **p0 = NULL, *p = NULL;
1959 if (!sc->ndis_link || !sc->ndis_running) {
1964 if (sc->ndis_txpending == 0) {
1969 p0 = &sc->ndis_txarray[sc->ndis_txidx];
1971 NdisAllocatePacket(&status,
1972 &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1974 if (status != NDIS_STATUS_SUCCESS) {
1979 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1985 * Save pointer to original mbuf
1986 * so we can free it later.
1989 p = sc->ndis_txarray[sc->ndis_txidx];
1990 p->np_txidx = sc->ndis_txidx;
1992 p->np_oob.npo_status = NDIS_STATUS_PENDING;
1995 * Do scatter/gather processing, if driver requested it.
1998 bus_dmamap_load_mbuf(sc->ndis_ttag,
1999 sc->ndis_tmaps[sc->ndis_txidx], m,
2000 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2001 bus_dmamap_sync(sc->ndis_ttag,
2002 sc->ndis_tmaps[sc->ndis_txidx],
2003 BUS_DMASYNC_PREREAD);
2004 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2008 sc->ndis_txpending--;
2011 * Set a timeout in case the chip goes out to lunch.
2013 sc->ndis_tx_timer = 5;
2017 * According to NDIS documentation, if a driver exports
2018 * a MiniportSendPackets() routine, we prefer that over
2019 * a MiniportSend() routine (which sends just a single
2022 if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2023 ndis_send_packets(sc, p0, 1);
2025 ndis_send_packet(sc, p);
2031 ndis_80211parent(struct ieee80211com *ic)
2033 struct ndis_softc *sc = ic->ic_softc;
2036 if (ic->ic_nrunning > 0) {
2037 if (!sc->ndis_running)
2039 } else if (sc->ndis_running)
2041 /*NDIS_UNLOCK(sc);*/
2045 ndis_init(void *xsc)
2047 struct ndis_softc *sc = xsc;
2051 * Avoid reintializing the link unnecessarily.
2052 * This should be dealt with in a better way by
2053 * fixing the upper layer modules so they don't
2054 * call ifp->if_init() quite as often.
2060 * Cancel pending I/O and free all RX/TX buffers.
2064 if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2065 error = ndis_init_nic(sc);
2067 device_printf(sc->ndis_dev,
2068 "failed to initialize the device: %d\n", error);
2073 /* Program the packet filter */
2074 sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2075 NDIS_PACKET_TYPE_BROADCAST;
2077 if (sc->ndis_80211) {
2078 struct ieee80211com *ic = &sc->ndis_ic;
2080 if (ic->ic_promisc > 0)
2081 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2083 struct ifnet *ifp = sc->ifp;
2085 if (ifp->if_flags & IFF_PROMISC)
2086 sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2089 len = sizeof(sc->ndis_filter);
2091 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2092 &sc->ndis_filter, &len);
2095 device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2103 i = sc->ifp->if_mtu;
2105 ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2108 * Program the multicast filter, if necessary.
2112 /* Setup task offload. */
2113 ndis_set_offload(sc);
2118 sc->ndis_txpending = sc->ndis_maxpkts;
2121 if (!sc->ndis_80211) {
2122 if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2123 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2124 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2127 sc->ndis_tx_timer = 0;
2130 * Some drivers don't set this value. The NDIS spec says
2131 * the default checkforhang timeout is "approximately 2
2132 * seconds." We use 3 seconds, because it seems for some
2133 * drivers, exactly 2 seconds is too fast.
2135 if (sc->ndis_block->nmb_checkforhangsecs == 0)
2136 sc->ndis_block->nmb_checkforhangsecs = 3;
2138 sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2139 callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2140 sc->ndis_running = 1;
2143 /* XXX force handling */
2145 ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
2149 * Set media options.
2152 ndis_ifmedia_upd(ifp)
2155 struct ndis_softc *sc;
2159 if (NDIS_INITIALIZED(sc))
2166 * Report current media status.
2169 ndis_ifmedia_sts(ifp, ifmr)
2171 struct ifmediareq *ifmr;
2173 struct ndis_softc *sc;
2174 uint32_t media_info;
2175 ndis_media_state linkstate;
2178 ifmr->ifm_status = IFM_AVALID;
2179 ifmr->ifm_active = IFM_ETHER;
2182 if (!NDIS_INITIALIZED(sc))
2185 len = sizeof(linkstate);
2186 ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2187 (void *)&linkstate, &len);
2189 len = sizeof(media_info);
2190 ndis_get_info(sc, OID_GEN_LINK_SPEED,
2191 (void *)&media_info, &len);
2193 if (linkstate == nmc_connected)
2194 ifmr->ifm_status |= IFM_ACTIVE;
2196 switch (media_info) {
2198 ifmr->ifm_active |= IFM_10_T;
2201 ifmr->ifm_active |= IFM_100_TX;
2204 ifmr->ifm_active |= IFM_1000_T;
2207 device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2213 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2215 struct ieee80211com *ic = &sc->ndis_ic;
2221 if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2222 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2224 arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2227 if (cipher == WPA_CSE_TKIP) {
2228 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2230 arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2233 if (cipher == WPA_CSE_CCMP) {
2234 if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2236 arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2239 DPRINTF(("Setting cipher to %d\n", arg));
2241 rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2246 /* Check that the cipher was set correctly. */
2249 rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2251 if (rval != 0 || arg != save)
2258 * WPA is hairy to set up. Do the work in a separate routine
2259 * so we don't clutter the setstate function too much.
2260 * Important yet undocumented fact: first we have to set the
2261 * authentication mode, _then_ we enable the ciphers. If one
2262 * of the WPA authentication modes isn't enabled, the driver
2263 * might not permit the TKIP or AES ciphers to be selected.
2266 ndis_set_wpa(sc, ie, ielen)
2267 struct ndis_softc *sc;
2271 struct ieee80211_ie_wpa *w;
2278 * Apparently, the only way for us to know what ciphers
2279 * and key management/authentication mode to use is for
2280 * us to inspect the optional information element (IE)
2281 * stored in the 802.11 state machine. This IE should be
2282 * supplied by the WPA supplicant.
2285 w = (struct ieee80211_ie_wpa *)ie;
2287 /* Check for the right kind of IE. */
2288 if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2289 DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2293 /* Skip over the ucast cipher OIDs. */
2294 pos = (char *)&w->wpa_uciphers[0];
2295 pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2297 /* Skip over the authmode count. */
2298 pos += sizeof(u_int16_t);
2301 * Check for the authentication modes. I'm
2302 * pretty sure there's only supposed to be one.
2305 n = (struct ndis_ie *)pos;
2306 if (n->ni_val == WPA_ASE_NONE)
2307 arg = NDIS_80211_AUTHMODE_WPANONE;
2309 if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2310 arg = NDIS_80211_AUTHMODE_WPA;
2312 if (n->ni_val == WPA_ASE_8021X_PSK)
2313 arg = NDIS_80211_AUTHMODE_WPAPSK;
2315 DPRINTF(("Setting WPA auth mode to %d\n", arg));
2317 if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2320 ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2322 /* Now configure the desired ciphers. */
2324 /* First, set up the multicast group cipher. */
2325 n = (struct ndis_ie *)&w->wpa_mcipher[0];
2327 if (ndis_set_cipher(sc, n->ni_val))
2330 /* Now start looking around for the unicast ciphers. */
2331 pos = (char *)&w->wpa_uciphers[0];
2332 n = (struct ndis_ie *)pos;
2334 for (i = 0; i < w->wpa_uciphercnt; i++) {
2335 if (ndis_set_cipher(sc, n->ni_val))
2344 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2346 struct ieee80211vap *vap = ifp->if_softc;
2347 struct ndis_softc *sc = vap->iv_ic->ic_softc;
2351 if (!NDIS_INITIALIZED(sc))
2354 len = sizeof(txrate);
2355 if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2356 vap->iv_bss->ni_txrate = txrate / 5000;
2357 ieee80211_media_status(ifp, imr);
2361 ndis_setstate_80211(struct ndis_softc *sc)
2363 struct ieee80211com *ic = &sc->ndis_ic;
2364 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2365 ndis_80211_macaddr bssid;
2366 ndis_80211_config config;
2370 if (!NDIS_INITIALIZED(sc)) {
2371 DPRINTF(("%s: NDIS not initialized\n", __func__));
2375 /* Disassociate and turn off radio. */
2378 ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2380 /* Set network infrastructure mode. */
2383 if (ic->ic_opmode == IEEE80211_M_IBSS)
2384 arg = NDIS_80211_NET_INFRA_IBSS;
2386 arg = NDIS_80211_NET_INFRA_BSS;
2388 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2391 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2393 /* Set power management */
2395 if (vap->iv_flags & IEEE80211_F_PMGTON)
2396 arg = NDIS_80211_POWERMODE_FAST_PSP;
2398 arg = NDIS_80211_POWERMODE_CAM;
2399 ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2402 if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2403 ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2404 arg = dBm2mW[ic->ic_txpowlimit];
2406 ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2410 * Default encryption mode to off, authentication
2411 * to open and privacy to 'accept everything.'
2414 arg = NDIS_80211_WEPSTAT_DISABLED;
2415 ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2418 arg = NDIS_80211_AUTHMODE_OPEN;
2419 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2422 * Note that OID_802_11_PRIVACY_FILTER is optional:
2423 * not all drivers implement it.
2426 arg = NDIS_80211_PRIVFILT_8021XWEP;
2427 ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2429 len = sizeof(config);
2430 bzero((char *)&config, len);
2431 config.nc_length = len;
2432 config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2433 rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2436 * Some drivers expect us to initialize these values, so
2437 * provide some defaults.
2440 if (config.nc_beaconperiod == 0)
2441 config.nc_beaconperiod = 100;
2442 if (config.nc_atimwin == 0)
2443 config.nc_atimwin = 100;
2444 if (config.nc_fhconfig.ncf_dwelltime == 0)
2445 config.nc_fhconfig.ncf_dwelltime = 200;
2446 if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2449 chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2450 chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2451 IEEE80211_CHAN_5GHZ;
2452 if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2453 config.nc_dsconfig =
2454 ic->ic_bsschan->ic_freq * 1000;
2455 len = sizeof(config);
2456 config.nc_length = len;
2457 config.nc_fhconfig.ncf_length =
2458 sizeof(ndis_80211_config_fh);
2459 DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2460 rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2463 device_printf(sc->ndis_dev, "couldn't change "
2464 "DS config to %ukHz: %d\n",
2465 config.nc_dsconfig, rval);
2468 device_printf(sc->ndis_dev, "couldn't retrieve "
2469 "channel info: %d\n", rval);
2471 /* Set the BSSID to our value so the driver doesn't associate */
2472 len = IEEE80211_ADDR_LEN;
2473 bcopy(vap->iv_myaddr, bssid, len);
2474 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2475 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2477 device_printf(sc->ndis_dev,
2478 "setting BSSID failed: %d\n", rval);
2482 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2484 struct ieee80211_node *ni = vap->iv_bss;
2485 ndis_80211_ssid ssid;
2486 ndis_80211_macaddr bssid;
2488 int i, rval = 0, len, error;
2491 if (!NDIS_INITIALIZED(sc)) {
2492 DPRINTF(("%s: NDIS not initialized\n", __func__));
2497 ndis_setstate_80211(sc);
2499 /* Set network infrastructure mode. */
2502 if (vap->iv_opmode == IEEE80211_M_IBSS)
2503 arg = NDIS_80211_NET_INFRA_IBSS;
2505 arg = NDIS_80211_NET_INFRA_BSS;
2507 rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2510 device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2512 /* Set RTS threshold */
2515 arg = vap->iv_rtsthreshold;
2516 ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2518 /* Set fragmentation threshold */
2521 arg = vap->iv_fragthreshold;
2522 ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2526 if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2527 !(vap->iv_flags & IEEE80211_F_WPA)) {
2530 if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2532 arg = NDIS_80211_AUTHMODE_SHARED;
2533 DPRINTF(("Setting shared auth\n"));
2534 ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2537 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2538 if (vap->iv_nw_keys[i].wk_keylen) {
2539 if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2540 IEEE80211_CIPHER_WEP)
2542 bzero((char *)&wep, sizeof(wep));
2543 wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2546 * 5, 13 and 16 are the only valid
2547 * key lengths. Anything in between
2548 * will be zero padded out to the
2549 * next highest boundary.
2551 if (vap->iv_nw_keys[i].wk_keylen < 5)
2553 else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2554 vap->iv_nw_keys[i].wk_keylen < 13)
2556 else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2557 vap->iv_nw_keys[i].wk_keylen < 16)
2561 wep.nw_length = (sizeof(uint32_t) * 3)
2563 if (i == vap->iv_def_txkey)
2564 wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2565 bcopy(vap->iv_nw_keys[i].wk_key,
2566 wep.nw_keydata, wep.nw_length);
2568 DPRINTF(("Setting WEP key %d\n", i));
2569 rval = ndis_set_info(sc,
2570 OID_802_11_ADD_WEP, &wep, &len);
2572 device_printf(sc->ndis_dev,
2573 "set wepkey failed: %d\n", rval);
2578 DPRINTF(("Setting WEP on\n"));
2579 arg = NDIS_80211_WEPSTAT_ENABLED;
2581 rval = ndis_set_info(sc,
2582 OID_802_11_WEP_STATUS, &arg, &len);
2584 device_printf(sc->ndis_dev,
2585 "enable WEP failed: %d\n", rval);
2586 if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2587 arg = NDIS_80211_PRIVFILT_8021XWEP;
2589 arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2593 OID_802_11_PRIVACY_FILTER, &arg, &len);
2598 if ((vap->iv_flags & IEEE80211_F_WPA) &&
2599 vap->iv_appie_assocreq != NULL) {
2600 struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2601 error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2603 device_printf(sc->ndis_dev, "WPA setup failed\n");
2607 /* Set network type. */
2611 switch (vap->iv_curmode) {
2612 case IEEE80211_MODE_11A:
2613 arg = NDIS_80211_NETTYPE_11OFDM5;
2615 case IEEE80211_MODE_11B:
2616 arg = NDIS_80211_NETTYPE_11DS;
2618 case IEEE80211_MODE_11G:
2619 arg = NDIS_80211_NETTYPE_11OFDM24;
2622 device_printf(sc->ndis_dev, "unknown mode: %d\n",
2627 DPRINTF(("Setting network type to %d\n", arg));
2629 rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2632 device_printf(sc->ndis_dev,
2633 "set nettype failed: %d\n", rval);
2638 * If the user selected a specific BSSID, try
2639 * to use that one. This is useful in the case where
2640 * there are several APs in range with the same network
2641 * name. To delete the BSSID, we use the broadcast
2642 * address as the BSSID.
2643 * Note that some drivers seem to allow setting a BSSID
2644 * in ad-hoc mode, which has the effect of forcing the
2645 * NIC to create an ad-hoc cell with a specific BSSID,
2646 * instead of a randomly chosen one. However, the net80211
2647 * code makes the assumtion that the BSSID setting is invalid
2648 * when you're in ad-hoc mode, so we don't allow that here.
2651 len = IEEE80211_ADDR_LEN;
2652 if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2653 vap->iv_opmode != IEEE80211_M_IBSS)
2654 bcopy(ni->ni_bssid, bssid, len);
2656 bcopy(ieee80211broadcastaddr, bssid, len);
2658 DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2659 rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2661 device_printf(sc->ndis_dev,
2662 "setting BSSID failed: %d\n", rval);
2664 /* Set SSID -- always do this last. */
2667 if (ndis_debug > 0) {
2668 printf("Setting ESSID to ");
2669 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2675 bzero((char *)&ssid, len);
2676 ssid.ns_ssidlen = ni->ni_esslen;
2677 if (ssid.ns_ssidlen == 0) {
2678 ssid.ns_ssidlen = 1;
2680 bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2682 rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2685 device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2691 ndis_get_bssid_list(sc, bl)
2692 struct ndis_softc *sc;
2693 ndis_80211_bssid_list_ex **bl;
2697 len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2698 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2702 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2703 if (error == ENOSPC) {
2704 free(*bl, M_DEVBUF);
2705 *bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2709 error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2712 DPRINTF(("%s: failed to read\n", __func__));
2713 free(*bl, M_DEVBUF);
2721 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2723 struct ieee80211com *ic = &sc->ndis_ic;
2724 struct ieee80211vap *vap;
2725 struct ieee80211_node *ni;
2726 ndis_80211_bssid_list_ex *bl;
2727 ndis_wlan_bssid_ex *bs;
2728 ndis_80211_macaddr bssid;
2734 len = sizeof(bssid);
2735 error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2737 device_printf(sc->ndis_dev, "failed to get bssid\n");
2741 vap = TAILQ_FIRST(&ic->ic_vaps);
2744 error = ndis_get_bssid_list(sc, &bl);
2748 bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2749 for (i = 0; i < bl->nblx_items; i++) {
2750 if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2751 *assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2752 if (*assoc == NULL) {
2756 bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2758 if (ic->ic_opmode == IEEE80211_M_STA)
2759 ni->ni_associd = 1 | 0xc000; /* fake associd */
2762 bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2770 ndis_getstate_80211(struct ndis_softc *sc)
2772 struct ieee80211com *ic = &sc->ndis_ic;
2773 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2774 struct ieee80211_node *ni = vap->iv_bss;
2775 ndis_wlan_bssid_ex *bs;
2776 int rval, len, i = 0;
2780 if (!NDIS_INITIALIZED(sc))
2783 if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2786 /* We're associated, retrieve info on the current bssid. */
2787 ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2788 chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2789 IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2791 /* Get SSID from current association info. */
2792 bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2793 bs->nwbx_ssid.ns_ssidlen);
2794 ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2796 if (ic->ic_caps & IEEE80211_C_PMGT) {
2798 rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2801 device_printf(sc->ndis_dev,
2802 "get power mode failed: %d\n", rval);
2803 if (arg == NDIS_80211_POWERMODE_CAM)
2804 vap->iv_flags &= ~IEEE80211_F_PMGTON;
2806 vap->iv_flags |= IEEE80211_F_PMGTON;
2810 if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2812 ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2813 for (i = 0; i < (sizeof(dBm2mW) / sizeof(dBm2mW[0])); i++)
2814 if (dBm2mW[i] >= arg)
2816 ic->ic_txpowlimit = i;
2820 * Use the current association information to reflect
2821 * what channel we're on.
2823 ic->ic_curchan = ieee80211_find_channel(ic,
2824 bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2825 if (ic->ic_curchan == NULL)
2826 ic->ic_curchan = &ic->ic_channels[0];
2827 ni->ni_chan = ic->ic_curchan;
2828 ic->ic_bsschan = ic->ic_curchan;
2833 * Determine current authentication mode.
2836 rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2838 device_printf(sc->ndis_dev,
2839 "get authmode status failed: %d\n", rval);
2841 vap->iv_flags &= ~IEEE80211_F_WPA;
2843 case NDIS_80211_AUTHMODE_OPEN:
2844 ni->ni_authmode = IEEE80211_AUTH_OPEN;
2846 case NDIS_80211_AUTHMODE_SHARED:
2847 ni->ni_authmode = IEEE80211_AUTH_SHARED;
2849 case NDIS_80211_AUTHMODE_AUTO:
2850 ni->ni_authmode = IEEE80211_AUTH_AUTO;
2852 case NDIS_80211_AUTHMODE_WPA:
2853 case NDIS_80211_AUTHMODE_WPAPSK:
2854 case NDIS_80211_AUTHMODE_WPANONE:
2855 ni->ni_authmode = IEEE80211_AUTH_WPA;
2856 vap->iv_flags |= IEEE80211_F_WPA1;
2858 case NDIS_80211_AUTHMODE_WPA2:
2859 case NDIS_80211_AUTHMODE_WPA2PSK:
2860 ni->ni_authmode = IEEE80211_AUTH_WPA;
2861 vap->iv_flags |= IEEE80211_F_WPA2;
2864 ni->ni_authmode = IEEE80211_AUTH_NONE;
2870 rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2873 device_printf(sc->ndis_dev,
2874 "get wep status failed: %d\n", rval);
2876 if (arg == NDIS_80211_WEPSTAT_ENABLED)
2877 vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2879 vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2883 ndis_ioctl(ifp, command, data)
2888 struct ndis_softc *sc = ifp->if_softc;
2889 struct ifreq *ifr = (struct ifreq *) data;
2896 if (ifp->if_flags & IFF_UP) {
2897 if (sc->ndis_running &&
2898 ifp->if_flags & IFF_PROMISC &&
2899 !(sc->ndis_if_flags & IFF_PROMISC)) {
2901 NDIS_PACKET_TYPE_PROMISCUOUS;
2902 i = sizeof(sc->ndis_filter);
2903 error = ndis_set_info(sc,
2904 OID_GEN_CURRENT_PACKET_FILTER,
2905 &sc->ndis_filter, &i);
2906 } else if (sc->ndis_running &&
2907 !(ifp->if_flags & IFF_PROMISC) &&
2908 sc->ndis_if_flags & IFF_PROMISC) {
2910 ~NDIS_PACKET_TYPE_PROMISCUOUS;
2911 i = sizeof(sc->ndis_filter);
2912 error = ndis_set_info(sc,
2913 OID_GEN_CURRENT_PACKET_FILTER,
2914 &sc->ndis_filter, &i);
2918 if (sc->ndis_running)
2921 sc->ndis_if_flags = ifp->if_flags;
2931 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2934 ifp->if_capenable = ifr->ifr_reqcap;
2935 if (ifp->if_capenable & IFCAP_TXCSUM)
2936 ifp->if_hwassist = sc->ndis_hwassist;
2938 ifp->if_hwassist = 0;
2939 ndis_set_offload(sc);
2942 error = ether_ioctl(ifp, command, data);
2946 /*NDIS_UNLOCK(sc);*/
2952 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2954 struct ndis_softc *sc = ic->ic_softc;
2955 struct ifreq *ifr = data;
2956 struct ndis_oid_data oid;
2957 struct ndis_evt evt;
2958 void *oidbuf = NULL;
2961 if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2967 error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2970 oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2971 error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2975 free(oidbuf, M_TEMP);
2981 error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2984 error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2986 case SIOCGPRIVATE_0:
2988 if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2993 error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2998 if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3003 error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3004 ifr->ifr_data, sizeof(uint32_t) * 2);
3009 if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010 error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3011 ifr->ifr_data + (sizeof(uint32_t) * 2),
3012 sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3017 free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3018 sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3020 sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3021 sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3022 NDIS_EVTINC(sc->ndis_evtcidx);
3033 error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3036 error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3039 free(oidbuf, M_TEMP);
3045 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3047 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3048 ndis_80211_key rkey;
3051 bzero((char *)&rkey, sizeof(rkey));
3055 rkey.nk_keyidx = key->wk_keyix;
3057 bcopy(vap->iv_ifp->if_broadcastaddr,
3058 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3060 error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3069 * In theory this could be called for any key, but we'll
3070 * only use it for WPA TKIP or AES keys. These need to be
3071 * set after initial authentication with the AP.
3074 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3076 struct ndis_softc *sc = vap->iv_ic->ic_softc;
3077 ndis_80211_key rkey;
3080 switch (key->wk_cipher->ic_cipher) {
3081 case IEEE80211_CIPHER_TKIP:
3083 len = sizeof(ndis_80211_key);
3084 bzero((char *)&rkey, sizeof(rkey));
3087 rkey.nk_keylen = key->wk_keylen;
3089 if (key->wk_flags & IEEE80211_KEY_SWMIC)
3090 rkey.nk_keylen += 16;
3092 /* key index - gets weird in NDIS */
3094 if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3095 rkey.nk_keyidx = key->wk_keyix;
3099 if (key->wk_flags & IEEE80211_KEY_XMIT)
3100 rkey.nk_keyidx |= 1 << 31;
3102 if (key->wk_flags & IEEE80211_KEY_GROUP) {
3103 bcopy(ieee80211broadcastaddr,
3104 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3106 bcopy(vap->iv_bss->ni_bssid,
3107 rkey.nk_bssid, IEEE80211_ADDR_LEN);
3109 rkey.nk_keyidx |= 1 << 30;
3112 /* need to set bit 29 based on keyrsc */
3113 rkey.nk_keyrsc = key->wk_keyrsc[0]; /* XXX need tid */
3116 rkey.nk_keyidx |= 1 << 29;
3118 if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3119 bcopy(key->wk_key, rkey.nk_keydata, 16);
3120 bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3121 bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3123 bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3125 error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3127 case IEEE80211_CIPHER_WEP:
3131 * I don't know how to set up keys for the AES
3132 * cipher yet. Is it the same as TKIP?
3134 case IEEE80211_CIPHER_AES_CCM:
3140 /* We need to return 1 for success, 0 for failure. */
3149 ndis_resettask(d, arg)
3153 struct ndis_softc *sc;
3160 * Stop the adapter and free any mbufs allocated to the
3164 ndis_stop(struct ndis_softc *sc)
3168 callout_drain(&sc->ndis_stat_callout);
3171 sc->ndis_tx_timer = 0;
3173 if (!sc->ndis_80211)
3174 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3175 sc->ndis_running = 0;
3178 if (sc->ndis_iftype != PNPBus ||
3179 (sc->ndis_iftype == PNPBus &&
3180 !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3185 for (i = 0; i < NDIS_EVENTS; i++) {
3186 if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3187 free(sc->ndis_evt[i].ne_buf, M_TEMP);
3188 sc->ndis_evt[i].ne_buf = NULL;
3190 sc->ndis_evt[i].ne_sts = 0;
3191 sc->ndis_evt[i].ne_len = 0;
3193 sc->ndis_evtcidx = 0;
3194 sc->ndis_evtpidx = 0;
3199 * Stop all chip I/O so that the kernel's probe routines don't
3200 * get confused by errant DMAs when rebooting.
3206 struct ndis_softc *sc;
3208 sc = device_get_softc(dev);
3213 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3215 struct ndis_vap *nvp = NDIS_VAP(vap);
3216 struct ieee80211com *ic = vap->iv_ic;
3217 struct ndis_softc *sc = ic->ic_softc;
3218 enum ieee80211_state ostate;
3220 DPRINTF(("%s: %s -> %s\n", __func__,
3221 ieee80211_state_name[vap->iv_state],
3222 ieee80211_state_name[nstate]));
3224 ostate = vap->iv_state;
3225 vap->iv_state = nstate;
3228 /* pass on to net80211 */
3229 case IEEE80211_S_INIT:
3230 case IEEE80211_S_SCAN:
3231 return nvp->newstate(vap, nstate, arg);
3232 case IEEE80211_S_ASSOC:
3233 if (ostate != IEEE80211_S_AUTH) {
3234 IEEE80211_UNLOCK(ic);
3235 ndis_auth_and_assoc(sc, vap);
3239 case IEEE80211_S_AUTH:
3240 IEEE80211_UNLOCK(ic);
3241 ndis_auth_and_assoc(sc, vap);
3242 if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3243 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3253 ndis_scan(void *arg)
3255 struct ieee80211vap *vap = arg;
3257 ieee80211_scan_done(vap);
3261 ndis_scan_results(struct ndis_softc *sc)
3263 struct ieee80211com *ic = &sc->ndis_ic;
3264 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3265 ndis_80211_bssid_list_ex *bl;
3266 ndis_wlan_bssid_ex *wb;
3267 struct ieee80211_scanparams sp;
3268 struct ieee80211_frame wh;
3269 struct ieee80211_channel *saved_chan;
3271 int rssi, noise, freq, chanflag;
3272 uint8_t ssid[2+IEEE80211_NWID_LEN];
3273 uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3274 uint8_t *frm, *efrm;
3276 saved_chan = ic->ic_curchan;
3279 if (ndis_get_bssid_list(sc, &bl))
3282 DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3283 wb = &bl->nblx_bssid[0];
3284 for (i = 0; i < bl->nblx_items; i++) {
3285 memset(&sp, 0, sizeof(sp));
3287 memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3288 memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3289 rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3290 rssi = max(0, min(rssi, 100)); /* limit 0 <= rssi <= 100 */
3291 if (wb->nwbx_privacy)
3292 sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3293 sp.bintval = wb->nwbx_config.nc_beaconperiod;
3294 switch (wb->nwbx_netinfra) {
3295 case NDIS_80211_NET_INFRA_IBSS:
3296 sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3298 case NDIS_80211_NET_INFRA_BSS:
3299 sp.capinfo |= IEEE80211_CAPINFO_ESS;
3302 sp.rates = &rates[0];
3303 for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3304 /* XXX - check units */
3305 if (wb->nwbx_supportedrates[j] == 0)
3308 wb->nwbx_supportedrates[j] & 0x7f;
3311 sp.ssid = (uint8_t *)&ssid[0];
3312 memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3313 wb->nwbx_ssid.ns_ssidlen);
3314 sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3316 chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3317 freq = wb->nwbx_config.nc_dsconfig / 1000;
3318 sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3319 /* Hack ic->ic_curchan to be in sync with the scan result */
3320 ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3321 if (ic->ic_curchan == NULL)
3322 ic->ic_curchan = &ic->ic_channels[0];
3324 /* Process extended info from AP */
3325 if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3326 frm = (uint8_t *)&wb->nwbx_ies;
3327 efrm = frm + wb->nwbx_ielen;
3328 if (efrm - frm < 12)
3330 sp.tstamp = frm; frm += 8;
3331 sp.bintval = le16toh(*(uint16_t *)frm); frm += 2;
3332 sp.capinfo = le16toh(*(uint16_t *)frm); frm += 2;
3334 sp.ies_len = efrm - frm;
3337 DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3338 ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3340 ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3341 wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3344 /* Restore the channel after messing with it */
3345 ic->ic_curchan = saved_chan;
3349 ndis_scan_start(struct ieee80211com *ic)
3351 struct ndis_softc *sc = ic->ic_softc;
3352 struct ieee80211vap *vap;
3353 struct ieee80211_scan_state *ss;
3354 ndis_80211_ssid ssid;
3358 vap = TAILQ_FIRST(&ic->ic_vaps);
3360 if (!NDIS_INITIALIZED(sc)) {
3361 DPRINTF(("%s: scan aborted\n", __func__));
3362 ieee80211_cancel_scan(vap);
3367 bzero((char *)&ssid, len);
3368 if (ss->ss_nssid == 0)
3369 ssid.ns_ssidlen = 1;
3371 /* Perform a directed scan */
3372 ssid.ns_ssidlen = ss->ss_ssid[0].len;
3373 bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3376 error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3378 DPRINTF(("%s: set ESSID failed\n", __func__));
3381 error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3383 DPRINTF(("%s: scan command failed\n", __func__));
3384 ieee80211_cancel_scan(vap);
3387 /* Set a timer to collect the results */
3388 callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3392 ndis_set_channel(struct ieee80211com *ic)
3398 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3404 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3406 /* NB: don't try to abort scan; wait for firmware to finish */
3410 ndis_scan_end(struct ieee80211com *ic)
3412 struct ndis_softc *sc = ic->ic_softc;
3414 ndis_scan_results(sc);