xref: /NextBSD/sys/dev/if_ndis/if_ndis.c (revision ea41b2069698db5cfd8b1d3888556269b4fdc668)
1 /*-
2  * Copyright (c) 2003
3  *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
19  *
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.
31  *
32  * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
33  * then hacked upon mercilessly by my.
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sockio.h>
42 #include <sys/mbuf.h>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
45 #include <sys/priv.h>
46 #include <sys/kernel.h>
47 #include <sys/socket.h>
48 #include <sys/queue.h>
49 #include <sys/module.h>
50 #include <sys/proc.h>
51 #include <sys/sysctl.h>
52 #include <sys/kthread.h>
53 #include <sys/limits.h>
54 
55 #include <net/if.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>
63 
64 #include <net/bpf.h>
65 
66 #include <machine/bus.h>
67 #include <machine/resource.h>
68 #include <sys/bus.h>
69 #include <sys/rman.h>
70 
71 #include <net80211/ieee80211_var.h>
72 #include <net80211/ieee80211_ioctl.h>
73 #include <net80211/ieee80211_regdomain.h>
74 
75 #include <dev/pci/pcireg.h>
76 #include <dev/pci/pcivar.h>
77 #include <dev/usb/usb.h>
78 #include <dev/usb/usbdi.h>
79 
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>
88 
89 #define NDIS_DEBUG
90 #ifdef NDIS_DEBUG
91 #define DPRINTF(x)	do { if (ndis_debug > 0) printf x; } while (0)
92 int ndis_debug = 0;
93 SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
94     "if_ndis debug level");
95 #else
96 #define DPRINTF(x)
97 #endif
98 
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");
103 
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,
112 	1000
113 };
114 
115 MODULE_DEPEND(ndis, ether, 1, 1, 1);
116 MODULE_DEPEND(ndis, wlan, 1, 1, 1);
117 MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
118 
119 MODULE_VERSION(ndis, 1);
120 
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);
126 
127 int ndisdrv_modevent		(module_t, int, void *);
128 
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 *,
136 				 uint32_t, uint32_t);
137 static void ndis_linksts	(ndis_handle, ndis_status, void *, uint32_t);
138 static void ndis_linksts_done	(ndis_handle);
139 
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;
153 
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,
171 	int);
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 *);
204 
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 *);
209 
210 static int ndisdrv_loaded = 0;
211 
212 /*
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.
217  */
218 int
ndisdrv_modevent(mod,cmd,arg)219 ndisdrv_modevent(mod, cmd, arg)
220 	module_t		mod;
221 	int			cmd;
222 	void			*arg;
223 {
224 	int			error = 0;
225 
226 	switch (cmd) {
227 	case MOD_LOAD:
228 		ndisdrv_loaded++;
229                 if (ndisdrv_loaded > 1)
230 			break;
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);
255 		break;
256 	case MOD_UNLOAD:
257 		ndisdrv_loaded--;
258 		if (ndisdrv_loaded > 0)
259 			break;
260 		/* fallthrough */
261 	case MOD_SHUTDOWN:
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);
274 		break;
275 	default:
276 		error = EINVAL;
277 		break;
278 	}
279 
280 	return (error);
281 }
282 
283 /*
284  * Program the 64-bit multicast hash filter.
285  */
286 static void
ndis_setmulti(sc)287 ndis_setmulti(sc)
288 	struct ndis_softc	*sc;
289 {
290 	struct ifnet		*ifp;
291 	struct ifmultiaddr	*ifma;
292 	int			len, mclistsz, error;
293 	uint8_t			*mclist;
294 
295 	ifp = sc->ifp;
296 
297 	if (!NDIS_INITIALIZED(sc))
298 		return;
299 
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);
305 		if (error)
306 			device_printf(sc->ndis_dev,
307 			    "set allmulti failed: %d\n", error);
308 		return;
309 	}
310 
311 	if (TAILQ_EMPTY(&ifp->if_multiaddrs))
312 		return;
313 
314 	len = sizeof(mclistsz);
315 	ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
316 
317 	mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
318 
319 	if (mclist == NULL) {
320 		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
321 		goto out;
322 	}
323 
324 	sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
325 
326 	len = 0;
327 	if_maddr_rlock(ifp);
328 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
329 		if (ifma->ifma_addr->sa_family != AF_LINK)
330 			continue;
331 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
332 		    mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
333 		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;
338 			goto out;
339 		}
340 	}
341 	if_maddr_runlock(ifp);
342 
343 	len = len * ETHER_ADDR_LEN;
344 	error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
345 	if (error) {
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;
349 	}
350 
351 out:
352 	free(mclist, M_TEMP);
353 
354 	len = sizeof(sc->ndis_filter);
355 	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
356 	    &sc->ndis_filter, &len);
357 	if (error)
358 		device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
359 }
360 
361 static int
ndis_set_offload(sc)362 ndis_set_offload(sc)
363 	struct ndis_softc	*sc;
364 {
365 	ndis_task_offload	*nto;
366 	ndis_task_offload_hdr	*ntoh;
367 	ndis_task_tcpip_csum	*nttc;
368 	struct ifnet		*ifp;
369 	int			len, error;
370 
371 	ifp = sc->ifp;
372 
373 	if (!NDIS_INITIALIZED(sc))
374 		return (EINVAL);
375 
376 	/* See if there's anything to set. */
377 
378 	error = ndis_probe_offload(sc);
379 	if (error)
380 		return (error);
381 
382 	if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
383 		return (0);
384 
385 	len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
386 	    sizeof(ndis_task_tcpip_csum);
387 
388 	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
389 
390 	if (ntoh == NULL)
391 		return (ENOMEM);
392 
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;
399 
400 	nto = (ndis_task_offload *)((char *)ntoh +
401 	    ntoh->ntoh_offset_firsttask);
402 
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);
408 
409 	nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
410 
411 	if (ifp->if_capenable & IFCAP_TXCSUM)
412 		nttc->nttc_v4tx = sc->ndis_v4tx;
413 
414 	if (ifp->if_capenable & IFCAP_RXCSUM)
415 		nttc->nttc_v4rx = sc->ndis_v4rx;
416 
417 	error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
418 	free(ntoh, M_TEMP);
419 
420 	return (error);
421 }
422 
423 static int
ndis_probe_offload(sc)424 ndis_probe_offload(sc)
425 	struct ndis_softc	*sc;
426 {
427 	ndis_task_offload	*nto;
428 	ndis_task_offload_hdr	*ntoh;
429 	ndis_task_tcpip_csum	*nttc = NULL;
430 	struct ifnet		*ifp;
431 	int			len, error, dummy;
432 
433 	ifp = sc->ifp;
434 
435 	len = sizeof(dummy);
436 	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
437 
438 	if (error != ENOSPC)
439 		return (error);
440 
441 	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
442 
443 	if (ntoh == NULL)
444 		return (ENOMEM);
445 
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;
451 
452 	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
453 
454 	if (error) {
455 		free(ntoh, M_TEMP);
456 		return (error);
457 	}
458 
459 	if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
460 		free(ntoh, M_TEMP);
461 		return (EINVAL);
462 	}
463 
464 	nto = (ndis_task_offload *)((char *)ntoh +
465 	    ntoh->ntoh_offset_firsttask);
466 
467 	while (1) {
468 		switch (nto->nto_task) {
469 		case NDIS_TASK_TCPIP_CSUM:
470 			nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
471 			break;
472 		/* Don't handle these yet. */
473 		case NDIS_TASK_IPSEC:
474 		case NDIS_TASK_TCP_LARGESEND:
475 		default:
476 			break;
477 		}
478 		if (nto->nto_offset_nexttask == 0)
479 			break;
480 		nto = (ndis_task_offload *)((char *)nto +
481 		    nto->nto_offset_nexttask);
482 	}
483 
484 	if (nttc == NULL) {
485 		free(ntoh, M_TEMP);
486 		return (ENOENT);
487 	}
488 
489 	sc->ndis_v4tx = nttc->nttc_v4tx;
490 	sc->ndis_v4rx = nttc->nttc_v4rx;
491 
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;
498 
499 	if (sc->ndis_hwassist)
500 		ifp->if_capabilities |= IFCAP_TXCSUM;
501 
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;
508 
509 	free(ntoh, M_TEMP);
510 	return (0);
511 }
512 
513 static int
ndis_nettype_chan(uint32_t type)514 ndis_nettype_chan(uint32_t type)
515 {
516 	switch (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);
521 	}
522 	DPRINTF(("unknown channel nettype %d\n", type));
523 	return (IEEE80211_CHAN_B);	/* Default to 11B chan */
524 }
525 
526 static int
ndis_nettype_mode(uint32_t type)527 ndis_nettype_mode(uint32_t type)
528 {
529 	switch (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);
534 	}
535 	DPRINTF(("unknown mode nettype %d\n", type));
536 	return (IEEE80211_MODE_AUTO);
537 }
538 
539 /*
540  * Attach the interface. Allocate softc structures, do ifmedia
541  * setup and ethernet/BPF attach.
542  */
543 int
ndis_attach(device_t dev)544 ndis_attach(device_t dev)
545 {
546 	struct ndis_softc	*sc;
547 	driver_object		*pdrv;
548 	device_object		*pdo;
549 	int			error = 0, len;
550 	int			i;
551 
552 	sc = device_get_softc(dev);
553 
554 	mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
555 	    MTX_DEF);
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 */
564 
565 	if (sc->ndis_iftype == PCMCIABus) {
566 		error = ndis_alloc_amem(sc);
567 		if (error) {
568 			device_printf(dev, "failed to allocate "
569 			    "attribute memory\n");
570 			goto fail;
571 		}
572 	}
573 
574 	/* Create sysctl registry nodes */
575 	ndis_create_sysctls(sc);
576 
577 	/* Find the PDO for this device instance. */
578 
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");
583 	else
584 		pdrv = windrv_lookup(0, "USB Bus");
585 	pdo = windrv_find_pdo(pdrv, dev);
586 
587 	/*
588 	 * Create a new functional device object for this
589 	 * device. This is what creates the miniport block
590 	 * for this device instance.
591 	 */
592 
593 	if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
594 		device_printf(dev, "failed to create FDO!\n");
595 		error = ENXIO;
596 		goto fail;
597 	}
598 
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);
603 
604 	/* Do resource conversion. */
605 	if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
606 		ndis_convert_res(sc);
607 	else
608 		sc->ndis_block->nmb_rlist = NULL;
609 
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;
616 
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;
620 
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);
631 
632 	/* Call driver's init routine. */
633 	if (ndis_init_nic(sc)) {
634 		device_printf(dev, "init handler failed\n");
635 		error = ENXIO;
636 		goto fail;
637 	}
638 
639 	/*
640 	 * Figure out how big to make the TX buffer pool.
641 	 */
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");
646 		error = ENXIO;
647 		goto fail;
648 	}
649 
650 	/*
651 	 * If this is a deserialized miniport, we don't have
652 	 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
653 	 */
654 	if (!NDIS_SERIALIZED(sc->ndis_block))
655 		sc->ndis_maxpkts = NDIS_TXPKTS;
656 
657 	/* Enforce some sanity, just in case. */
658 
659 	if (sc->ndis_maxpkts == 0)
660 		sc->ndis_maxpkts = 10;
661 
662 	sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
663 	    sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
664 
665 	/* Allocate a pool of ndis_packets for TX encapsulation. */
666 
667 	NdisAllocatePacketPool(&i, &sc->ndis_txpool,
668 	    sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
669 
670 	if (i != NDIS_STATUS_SUCCESS) {
671 		sc->ndis_txpool = NULL;
672 		device_printf(dev, "failed to allocate TX packet pool");
673 		error = ENOMEM;
674 		goto fail;
675 	}
676 
677 	sc->ndis_txpending = sc->ndis_maxpkts;
678 
679 	sc->ndis_oidcnt = 0;
680 	/* Get supported oid list. */
681 	ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
682 
683 	/* If the NDIS module requested scatter/gather, init maps. */
684 	if (sc->ndis_sc)
685 		ndis_init_dma(sc);
686 
687 	/*
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.
691 	 */
692 	for (i = 0; i < sc->ndis_oidcnt; i++)
693 		if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
694 			sc->ndis_80211 = 1;
695 			break;
696 		}
697 
698 	if (sc->ndis_80211)
699 		error = ndis_80211attach(sc);
700 	else
701 		error = ndis_ifattach(sc);
702 
703 fail:
704 	if (error) {
705 		ndis_detach(dev);
706 		return (error);
707 	}
708 
709 	if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
710 		return (error);
711 
712 	DPRINTF(("attach done.\n"));
713 	/* We're done talking to the NIC for now; halt it. */
714 	ndis_halt_nic(sc);
715 	DPRINTF(("halting done.\n"));
716 
717 	return (error);
718 }
719 
720 static int
ndis_80211attach(struct ndis_softc * sc)721 ndis_80211attach(struct ndis_softc *sc)
722 {
723 	struct ieee80211com	*ic = &sc->ndis_ic;
724 	ndis_80211_rates_ex	rates;
725 	struct ndis_80211_nettype_list *ntl;
726 	uint32_t		arg;
727 	int			mode, i, r, len, nonettypes = 1;
728 	uint8_t			bands[howmany(IEEE80211_MODE_MAX, 8)] = { 0 };
729 
730 	callout_init(&sc->ndis_scan_callout, 1);
731 
732 	ic->ic_softc = sc;
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);
740 	len = 0;
741 	r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
742 	if (r != ENOSPC)
743 		goto nonettypes;
744 	ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
745 	r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
746 	if (r != 0) {
747 		free(ntl, M_DEVBUF);
748 		goto nonettypes;
749 	}
750 
751 	for (i = 0; i < ntl->ntl_items; i++) {
752 		mode = ndis_nettype_mode(ntl->ntl_type[i]);
753 		if (mode) {
754 			nonettypes = 0;
755 			setbit(ic->ic_modecaps, mode);
756 			setbit(bands, mode);
757 		} else
758 			device_printf(sc->ndis_dev, "Unknown nettype %d\n",
759 			    ntl->ntl_type[i]);
760 	}
761 	free(ntl, M_DEVBUF);
762 nonettypes:
763 	/* Default to 11b channels if the card did not supply any */
764 	if (nonettypes) {
765 		setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
766 		setbit(bands, IEEE80211_MODE_11B);
767 	}
768 	len = sizeof(rates);
769 	bzero((char *)&rates, len);
770 	r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
771 	if (r != 0)
772 		device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
773 	/*
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
776 	 * all up to heck.
777 	 */
778 
779 #define TESTSETRATE(x, y)						\
780 	do {								\
781 		int			i;				\
782 		for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) {	\
783 			if (ic->ic_sup_rates[x].rs_rates[i] == (y))	\
784 				break;					\
785 		}							\
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++;		\
789 		}							\
790 	} while (0)
791 
792 #define SETRATE(x, y)	\
793 	ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
794 #define INCRATE(x)	\
795 	ic->ic_sup_rates[x].rs_nrates++
796 
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) {
806 		case 2:
807 		case 4:
808 		case 11:
809 		case 10:
810 		case 22:
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].
815 				    rs_nrates = 0;
816 			}
817 			SETRATE(IEEE80211_MODE_11B, rates[i]);
818 			INCRATE(IEEE80211_MODE_11B);
819 			break;
820 		default:
821 			if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
822 				SETRATE(IEEE80211_MODE_11A, rates[i]);
823 				INCRATE(IEEE80211_MODE_11A);
824 			}
825 			if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
826 				SETRATE(IEEE80211_MODE_11G, rates[i]);
827 				INCRATE(IEEE80211_MODE_11G);
828 			}
829 			break;
830 		}
831 	}
832 
833 	/*
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?
839 	 */
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);
845 	}
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);
851 	}
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);
857 	}
858 
859 #undef SETRATE
860 #undef INCRATE
861 #undef TESTSETRATE
862 
863 	ieee80211_init_channels(ic, NULL, bands);
864 
865 	/*
866 	 * To test for WPA support, we need to see if we can
867 	 * set AUTHENTICATION_MODE to WPA and read it back
868 	 * successfully.
869 	 */
870 	i = sizeof(arg);
871 	arg = NDIS_80211_AUTHMODE_WPA;
872 	r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
873 	if (r == 0) {
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;
877 	}
878 
879 	/*
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.
885 	 */
886 	i = sizeof(arg);
887 	arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
888 	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
889 	if (r == 0) {
890 		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
891 				  |  IEEE80211_CRYPTO_TKIP
892 				  |  IEEE80211_CRYPTO_AES_CCM;
893 		goto got_crypto;
894 	}
895 	arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
896 	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
897 	if (r == 0) {
898 		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
899 				  |  IEEE80211_CRYPTO_TKIP;
900 		goto got_crypto;
901 	}
902 	arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
903 	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
904 	if (r == 0)
905 		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
906 got_crypto:
907 	i = sizeof(arg);
908 	r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
909 	if (r == 0)
910 		ic->ic_caps |= IEEE80211_C_PMGT;
911 
912 	r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
913 	if (r == 0)
914 		ic->ic_caps |= IEEE80211_C_TXPMGT;
915 
916 	/*
917 	 * Get station address from the driver.
918 	 */
919 	len = sizeof(ic->ic_macaddr);
920 	ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
921 
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;
936 
937 	if (bootverbose)
938 		ieee80211_announce(ic);
939 
940 	return (0);
941 }
942 
943 static int
ndis_ifattach(struct ndis_softc * sc)944 ndis_ifattach(struct ndis_softc *sc)
945 {
946 	struct ifnet *ifp;
947 	u_char eaddr[ETHER_ADDR_LEN];
948 	int len;
949 
950 	ifp = if_alloc(IFT_ETHER);
951 	if (ifp == NULL)
952 		return (ENOSPC);
953 	sc->ifp = ifp;
954 	ifp->if_softc = sc;
955 
956 	/* Check for task offload support. */
957 	ndis_probe_offload(sc);
958 
959 	/*
960 	 * Get station address from the driver.
961 	 */
962 	len = sizeof(eaddr);
963 	ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
964 
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;
977 
978 	ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
979 	    ndis_ifmedia_sts);
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);
987 
988 	return (0);
989 }
990 
991 static struct ieee80211vap *
ndis_vap_create(struct ieee80211com * ic,const char name[IFNAMSIZ],int unit,enum ieee80211_opmode opmode,int flags,const uint8_t bssid[IEEE80211_ADDR_LEN],const uint8_t mac[IEEE80211_ADDR_LEN])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])
996 {
997 	struct ndis_vap *nvp;
998 	struct ieee80211vap *vap;
999 
1000 	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
1001 		return NULL;
1002 	nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1003 	vap = &nvp->vap;
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;
1008 
1009 	/* complete setup */
1010 	ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1011 	    mac);
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;
1016 	return vap;
1017 }
1018 
1019 static void
ndis_vap_delete(struct ieee80211vap * vap)1020 ndis_vap_delete(struct ieee80211vap *vap)
1021 {
1022 	struct ndis_vap *nvp = NDIS_VAP(vap);
1023 	struct ieee80211com *ic = vap->iv_ic;
1024 	struct ndis_softc *sc = ic->ic_softc;
1025 
1026 	ndis_stop(sc);
1027 	callout_drain(&sc->ndis_scan_callout);
1028 	ieee80211_vap_detach(vap);
1029 	free(nvp, M_80211_VAP);
1030 }
1031 
1032 /*
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
1037  * allocated.
1038  */
1039 int
ndis_detach(device_t dev)1040 ndis_detach(device_t dev)
1041 {
1042 	struct ifnet		*ifp;
1043 	struct ndis_softc	*sc;
1044 	driver_object		*drv;
1045 
1046 	sc = device_get_softc(dev);
1047 	NDIS_LOCK(sc);
1048 	if (!sc->ndis_80211)
1049 		ifp = sc->ifp;
1050 	else
1051 		ifp = NULL;
1052 	if (ifp != NULL)
1053 		ifp->if_flags &= ~IFF_UP;
1054 	if (device_is_attached(dev)) {
1055 		NDIS_UNLOCK(sc);
1056 		ndis_stop(sc);
1057 		if (sc->ndis_80211)
1058 			ieee80211_ifdetach(&sc->ndis_ic);
1059 		else if (ifp != NULL)
1060 			ether_ifdetach(ifp);
1061 	} else
1062 		NDIS_UNLOCK(sc);
1063 
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);
1076 
1077 	bus_generic_detach(dev);
1078 	ndis_unload_driver(sc);
1079 
1080 	if (sc->ndis_irq)
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);
1091 
1092 	if (ifp != NULL)
1093 		if_free(ifp);
1094 
1095 	if (sc->ndis_iftype == PCMCIABus)
1096 		ndis_free_amem(sc);
1097 
1098 	if (sc->ndis_sc)
1099 		ndis_destroy_dma(sc);
1100 
1101 	if (sc->ndis_txarray)
1102 		free(sc->ndis_txarray, M_DEVBUF);
1103 
1104 	if (!sc->ndis_80211)
1105 		ifmedia_removeall(&sc->ifmedia);
1106 
1107 	if (sc->ndis_txpool != NULL)
1108 		NdisFreePacketPool(sc->ndis_txpool);
1109 
1110 	/* Destroy the PDO for this device. */
1111 
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");
1116 	else
1117 		drv = windrv_lookup(0, "USB Bus");
1118 	if (drv == NULL)
1119 		panic("couldn't find driver object");
1120 	windrv_destroy_pdo(drv, dev);
1121 
1122 	if (sc->ndis_iftype == PCIBus)
1123 		bus_dma_tag_destroy(sc->ndis_parent_tag);
1124 
1125 	return (0);
1126 }
1127 
1128 int
ndis_suspend(dev)1129 ndis_suspend(dev)
1130 	device_t		dev;
1131 {
1132 	struct ndis_softc	*sc;
1133 	struct ifnet		*ifp;
1134 
1135 	sc = device_get_softc(dev);
1136 	ifp = sc->ifp;
1137 
1138 #ifdef notdef
1139 	if (NDIS_INITIALIZED(sc))
1140         	ndis_stop(sc);
1141 #endif
1142 
1143 	return (0);
1144 }
1145 
1146 int
ndis_resume(dev)1147 ndis_resume(dev)
1148 	device_t		dev;
1149 {
1150 	struct ndis_softc	*sc;
1151 	struct ifnet		*ifp;
1152 
1153 	sc = device_get_softc(dev);
1154 	ifp = sc->ifp;
1155 
1156 	if (NDIS_INITIALIZED(sc))
1157         	ndis_init(sc);
1158 
1159 	return (0);
1160 }
1161 
1162 /*
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
1167  * miniports.
1168  */
1169 static void
ndis_rxeof_eth(adapter,ctx,addr,hdr,hdrlen,lookahead,lookaheadlen,pktlen)1170 ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1171 	ndis_handle		adapter;
1172 	ndis_handle		ctx;
1173 	char			*addr;
1174 	void			*hdr;
1175 	uint32_t		hdrlen;
1176 	void			*lookahead;
1177 	uint32_t		lookaheadlen;
1178 	uint32_t		pktlen;
1179 {
1180 	ndis_miniport_block	*block;
1181 	uint8_t			irql = 0;
1182 	uint32_t		status;
1183 	ndis_buffer		*b;
1184 	ndis_packet		*p;
1185 	struct mbuf		*m;
1186 	ndis_ethpriv		*priv;
1187 
1188 	block = adapter;
1189 
1190 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1191 	if (m == NULL)
1192 		return;
1193 
1194 	/* Save the data provided to us so far. */
1195 
1196 	m->m_len = lookaheadlen + hdrlen;
1197 	m->m_pkthdr.len = pktlen + hdrlen;
1198 	m->m_next = NULL;
1199 	m_copyback(m, 0, hdrlen, hdr);
1200 	m_copyback(m, hdrlen, lookaheadlen, lookahead);
1201 
1202 	/* Now create a fake NDIS_PACKET to hold the data */
1203 
1204 	NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1205 
1206 	if (status != NDIS_STATUS_SUCCESS) {
1207 		m_freem(m);
1208 		return;
1209 	}
1210 
1211 	p->np_m0 = m;
1212 
1213 	b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1214 
1215 	if (b == NULL) {
1216 		NdisFreePacket(p);
1217 		m_freem(m);
1218 		return;
1219 	}
1220 
1221 	p->np_private.npp_head = p->np_private.npp_tail = b;
1222 	p->np_private.npp_totlen = m->m_pkthdr.len;
1223 
1224 	/* Save the packet RX context somewhere. */
1225 	priv = (ndis_ethpriv *)&p->np_protocolreserved;
1226 	priv->nep_ctx = ctx;
1227 
1228 	if (!NDIS_SERIALIZED(block))
1229 		KeAcquireSpinLock(&block->nmb_lock, &irql);
1230 
1231 	InsertTailList((&block->nmb_packetlist), (&p->np_list));
1232 
1233 	if (!NDIS_SERIALIZED(block))
1234 		KeReleaseSpinLock(&block->nmb_lock, irql);
1235 }
1236 
1237 /*
1238  * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1239  * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1240  * miniports.
1241  */
1242 static void
ndis_rxeof_done(adapter)1243 ndis_rxeof_done(adapter)
1244 	ndis_handle		adapter;
1245 {
1246 	struct ndis_softc	*sc;
1247 	ndis_miniport_block	*block;
1248 
1249 	block = adapter;
1250 
1251 	/* Schedule transfer/RX of queued packets. */
1252 
1253 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1254 
1255 	KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1256 }
1257 
1258 /*
1259  * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1260  */
1261 static void
ndis_rxeof_xfr(dpc,adapter,sysarg1,sysarg2)1262 ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1263 	kdpc			*dpc;
1264 	ndis_handle		adapter;
1265 	void			*sysarg1;
1266 	void			*sysarg2;
1267 {
1268 	ndis_miniport_block	*block;
1269 	struct ndis_softc	*sc;
1270 	ndis_packet		*p;
1271 	list_entry		*l;
1272 	uint32_t		status;
1273 	ndis_ethpriv		*priv;
1274 	struct ifnet		*ifp;
1275 	struct mbuf		*m;
1276 
1277 	block = adapter;
1278 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1279 	ifp = sc->ifp;
1280 
1281 	KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1282 
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));
1288 
1289 		priv = (ndis_ethpriv *)&p->np_protocolreserved;
1290 		m = p->np_m0;
1291 		p->np_softc = sc;
1292 		p->np_m0 = NULL;
1293 
1294 		KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1295 
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);
1299 
1300 		KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1301 
1302 		/*
1303 		 * If status is NDIS_STATUS_PENDING, do nothing and
1304 		 * wait for a callback to the ndis_rxeof_xfr_done()
1305 		 * handler.
1306 	 	 */
1307 
1308 		m->m_len = m->m_pkthdr.len;
1309 		m->m_pkthdr.rcvif = ifp;
1310 
1311 		if (status == NDIS_STATUS_SUCCESS) {
1312 			IoFreeMdl(p->np_private.npp_head);
1313 			NdisFreePacket(p);
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);
1320 		}
1321 
1322 		if (status == NDIS_STATUS_FAILURE)
1323 			m_freem(m);
1324 
1325 		/* Advance to next packet */
1326 		l = block->nmb_packetlist.nle_flink;
1327 	}
1328 
1329 	KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1330 }
1331 
1332 /*
1333  * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1334  */
1335 static void
ndis_rxeof_xfr_done(adapter,packet,status,len)1336 ndis_rxeof_xfr_done(adapter, packet, status, len)
1337 	ndis_handle		adapter;
1338 	ndis_packet		*packet;
1339 	uint32_t		status;
1340 	uint32_t		len;
1341 {
1342 	ndis_miniport_block	*block;
1343 	struct ndis_softc	*sc;
1344 	struct ifnet		*ifp;
1345 	struct mbuf		*m;
1346 
1347 	block = adapter;
1348 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1349 	ifp = sc->ifp;
1350 
1351 	m = packet->np_m0;
1352 	IoFreeMdl(packet->np_private.npp_head);
1353 	NdisFreePacket(packet);
1354 
1355 	if (status != NDIS_STATUS_SUCCESS) {
1356 		m_freem(m);
1357 		return;
1358 	}
1359 
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);
1368 }
1369 /*
1370  * A frame has been uploaded: pass the resulting mbuf chain up to
1371  * the higher level protocols.
1372  *
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.
1381  *
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
1386  * packet.
1387  */
1388 static void
ndis_rxeof(adapter,packets,pktcnt)1389 ndis_rxeof(adapter, packets, pktcnt)
1390 	ndis_handle		adapter;
1391 	ndis_packet		**packets;
1392 	uint32_t		pktcnt;
1393 {
1394 	struct ndis_softc	*sc;
1395 	ndis_miniport_block	*block;
1396 	ndis_packet		*p;
1397 	uint32_t		s;
1398 	ndis_tcpip_csum		*csum;
1399 	struct ifnet		*ifp;
1400 	struct mbuf		*m0, *m;
1401 	int			i;
1402 
1403 	block = (ndis_miniport_block *)adapter;
1404 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1405 	ifp = sc->ifp;
1406 
1407 	/*
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.
1411 	 */
1412         if (!sc->ndis_running) {
1413 		for (i = 0; i < pktcnt; i++) {
1414 			p = packets[i];
1415 			if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1416 				p->np_refcnt++;
1417 				(void)ndis_return_packet(NULL ,p, block);
1418 			}
1419 		}
1420 		return;
1421         }
1422 
1423 	for (i = 0; i < pktcnt; i++) {
1424 		p = packets[i];
1425 		/* Stash the softc here so ptom can use it. */
1426 		p->np_softc = sc;
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);
1431 		} else {
1432 #ifdef notdef
1433 			if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1434 				m = m_dup(m0, M_NOWAIT);
1435 				/*
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
1441 				 * doing anything.
1442 				 */
1443 				p->np_refcnt++;
1444 				m_freem(m0);
1445 				if (m == NULL)
1446 					if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1447 				else
1448 					m0 = m;
1449 			} else
1450 				p->np_oob.npo_status = NDIS_STATUS_PENDING;
1451 #endif
1452 			m = m_dup(m0, M_NOWAIT);
1453 			if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1454 				p->np_refcnt++;
1455 			else
1456 				p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457 			m_freem(m0);
1458 			if (m == NULL) {
1459 				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1460 				continue;
1461 			}
1462 			m0 = m;
1463 			m0->m_pkthdr.rcvif = ifp;
1464 
1465 			/* Deal with checksum offload. */
1466 
1467 			if (ifp->if_capenable & IFCAP_RXCSUM &&
1468 			    p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1469 				s = (uintptr_t)
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;
1482 				}
1483 			}
1484 
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);
1491 		}
1492 	}
1493 }
1494 
1495 /*
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).
1500  */
1501 static void
ndis_inputtask(device_object * dobj,void * arg)1502 ndis_inputtask(device_object *dobj, void *arg)
1503 {
1504 	ndis_miniport_block	*block;
1505 	struct ndis_softc	*sc = arg;
1506 	struct mbuf		*m;
1507 	uint8_t			irql;
1508 
1509 	block = dobj->do_devext;
1510 
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);
1517 
1518 			if (vap != NULL)
1519 				vap->iv_deliver_data(vap, vap->iv_bss, m);
1520 		} else {
1521 			struct ifnet *ifp = sc->ifp;
1522 
1523 			(*ifp->if_input)(ifp, m);
1524 		}
1525 		KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1526 	}
1527 	KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1528 }
1529 
1530 /*
1531  * A frame was downloaded to the chip. It's safe for us to clean up
1532  * the list buffers.
1533  */
1534 static void
ndis_txeof(adapter,packet,status)1535 ndis_txeof(adapter, packet, status)
1536 	ndis_handle		adapter;
1537 	ndis_packet		*packet;
1538 	ndis_status		status;
1539 
1540 {
1541 	struct ndis_softc	*sc;
1542 	ndis_miniport_block	*block;
1543 	struct ifnet		*ifp;
1544 	int			idx;
1545 	struct mbuf		*m;
1546 
1547 	block = (ndis_miniport_block *)adapter;
1548 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1549 	ifp = sc->ifp;
1550 
1551 	m = packet->np_m0;
1552 	idx = packet->np_txidx;
1553 	if (sc->ndis_sc)
1554 		bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1555 
1556 	ndis_free_packet(packet);
1557 	m_freem(m);
1558 
1559 	NDIS_LOCK(sc);
1560 	sc->ndis_txarray[idx] = NULL;
1561 	sc->ndis_txpending++;
1562 
1563 	if (status == NDIS_STATUS_SUCCESS)
1564 		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1565 	else
1566 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1567 
1568 	sc->ndis_tx_timer = 0;
1569 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1570 
1571 	NDIS_UNLOCK(sc);
1572 
1573 	IoQueueWorkItem(sc->ndis_startitem,
1574 	    (io_workitem_func)ndis_starttask_wrap,
1575 	    WORKQUEUE_CRITICAL, ifp);
1576 }
1577 
1578 static void
ndis_linksts(adapter,status,sbuf,slen)1579 ndis_linksts(adapter, status, sbuf, slen)
1580 	ndis_handle		adapter;
1581 	ndis_status		status;
1582 	void			*sbuf;
1583 	uint32_t		slen;
1584 {
1585 	ndis_miniport_block	*block;
1586 	struct ndis_softc	*sc;
1587 
1588 	block = adapter;
1589 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1590 	sc->ndis_sts = status;
1591 
1592 	/* Event list is all full up, drop this one. */
1593 
1594 	NDIS_LOCK(sc);
1595 	if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1596 		NDIS_UNLOCK(sc);
1597 		return;
1598 	}
1599 
1600 	/* Cache the event. */
1601 
1602 	if (slen) {
1603 		sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1604 		    M_TEMP, M_NOWAIT);
1605 		if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1606 			NDIS_UNLOCK(sc);
1607 			return;
1608 		}
1609 		bcopy((char *)sbuf,
1610 		    sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1611 	}
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);
1615 	NDIS_UNLOCK(sc);
1616 }
1617 
1618 static void
ndis_linksts_done(adapter)1619 ndis_linksts_done(adapter)
1620 	ndis_handle		adapter;
1621 {
1622 	ndis_miniport_block	*block;
1623 	struct ndis_softc	*sc;
1624 	struct ifnet		*ifp;
1625 
1626 	block = adapter;
1627 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1628 	ifp = sc->ifp;
1629 
1630 	if (!NDIS_INITIALIZED(sc))
1631 		return;
1632 
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);
1641 		break;
1642 	case NDIS_STATUS_MEDIA_DISCONNECT:
1643 		if (sc->ndis_link)
1644 			IoQueueWorkItem(sc->ndis_tickitem,
1645 		    	    (io_workitem_func)ndis_ticktask_wrap,
1646 			    WORKQUEUE_CRITICAL, sc);
1647 		break;
1648 	default:
1649 		break;
1650 	}
1651 }
1652 
1653 static void
ndis_tick(xsc)1654 ndis_tick(xsc)
1655 	void			*xsc;
1656 {
1657 	struct ndis_softc	*sc;
1658 
1659 	sc = xsc;
1660 
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;
1666 	}
1667 
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");
1671 
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);
1678 	}
1679 
1680 	callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1681 }
1682 
1683 static void
ndis_ticktask(device_object * d,void * xsc)1684 ndis_ticktask(device_object *d, void *xsc)
1685 {
1686 	struct ndis_softc	*sc = xsc;
1687 	ndis_checkforhang_handler hangfunc;
1688 	uint8_t			rval;
1689 
1690 	NDIS_LOCK(sc);
1691 	if (!NDIS_INITIALIZED(sc)) {
1692 		NDIS_UNLOCK(sc);
1693 		return;
1694 	}
1695 	NDIS_UNLOCK(sc);
1696 
1697 	hangfunc = sc->ndis_chars->nmc_checkhang_func;
1698 
1699 	if (hangfunc != NULL) {
1700 		rval = MSCALL1(hangfunc,
1701 		    sc->ndis_block->nmb_miniportadapterctx);
1702 		if (rval == TRUE) {
1703 			ndis_reset_nic(sc);
1704 			return;
1705 		}
1706 	}
1707 
1708 	NDIS_LOCK(sc);
1709 	if (sc->ndis_link == 0 &&
1710 	    sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1711 		sc->ndis_link = 1;
1712 		if (sc->ndis_80211 != 0) {
1713 			struct ieee80211com *ic = &sc->ndis_ic;
1714 			struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1715 
1716 			if (vap != NULL) {
1717 				NDIS_UNLOCK(sc);
1718 				ndis_getstate_80211(sc);
1719 				ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1720 				NDIS_LOCK(sc);
1721 				if_link_state_change(vap->iv_ifp,
1722 				    LINK_STATE_UP);
1723 			}
1724 		} else
1725 			if_link_state_change(sc->ifp, LINK_STATE_UP);
1726 	}
1727 
1728 	if (sc->ndis_link == 1 &&
1729 	    sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1730 		sc->ndis_link = 0;
1731 		if (sc->ndis_80211 != 0) {
1732 			struct ieee80211com *ic = &sc->ndis_ic;
1733 			struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1734 
1735 			if (vap != NULL) {
1736 				NDIS_UNLOCK(sc);
1737 				ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1738 				NDIS_LOCK(sc);
1739 				if_link_state_change(vap->iv_ifp,
1740 				    LINK_STATE_DOWN);
1741 			}
1742 		} else
1743 			if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1744 	}
1745 
1746 	NDIS_UNLOCK(sc);
1747 }
1748 
1749 static void
ndis_map_sclist(arg,segs,nseg,mapsize,error)1750 ndis_map_sclist(arg, segs, nseg, mapsize, error)
1751 	void			*arg;
1752 	bus_dma_segment_t	*segs;
1753 	int			nseg;
1754 	bus_size_t		mapsize;
1755 	int			error;
1756 
1757 {
1758 	struct ndis_sc_list	*sclist;
1759 	int			i;
1760 
1761 	if (error || arg == NULL)
1762 		return;
1763 
1764 	sclist = arg;
1765 
1766 	sclist->nsl_frags = nseg;
1767 
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;
1771 	}
1772 }
1773 
1774 static int
ndis_raw_xmit(struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_bpf_params * params)1775 ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1776 	const struct ieee80211_bpf_params *params)
1777 {
1778 	/* no support; just discard */
1779 	m_freem(m);
1780 	ieee80211_free_node(ni);
1781 	return (0);
1782 }
1783 
1784 static void
ndis_update_mcast(struct ieee80211com * ic)1785 ndis_update_mcast(struct ieee80211com *ic)
1786 {
1787        struct ndis_softc *sc = ic->ic_softc;
1788 
1789        ndis_setmulti(sc);
1790 }
1791 
1792 static void
ndis_update_promisc(struct ieee80211com * ic)1793 ndis_update_promisc(struct ieee80211com *ic)
1794 {
1795        /* not supported */
1796 }
1797 
1798 static void
ndis_starttask(d,arg)1799 ndis_starttask(d, arg)
1800 	device_object		*d;
1801 	void			*arg;
1802 {
1803 	struct ifnet		*ifp;
1804 
1805 	ifp = arg;
1806 
1807 	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1808 		ndis_start(ifp);
1809 }
1810 
1811 /*
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.
1818  *
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.
1822  */
1823 static void
ndis_start(ifp)1824 ndis_start(ifp)
1825 	struct ifnet		*ifp;
1826 {
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;
1832 
1833 	sc = ifp->if_softc;
1834 
1835 	NDIS_LOCK(sc);
1836 	if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1837 		NDIS_UNLOCK(sc);
1838 		return;
1839 	}
1840 
1841 	p0 = &sc->ndis_txarray[sc->ndis_txidx];
1842 
1843 	while(sc->ndis_txpending) {
1844 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1845 		if (m == NULL)
1846 			break;
1847 
1848 		NdisAllocatePacket(&status,
1849 		    &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1850 
1851 		if (status != NDIS_STATUS_SUCCESS)
1852 			break;
1853 
1854 		if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1855 			IFQ_DRV_PREPEND(&ifp->if_snd, m);
1856 			NDIS_UNLOCK(sc);
1857 			return;
1858 		}
1859 
1860 		/*
1861 		 * Save pointer to original mbuf
1862 		 * so we can free it later.
1863 		 */
1864 
1865 		p = sc->ndis_txarray[sc->ndis_txidx];
1866 		p->np_txidx = sc->ndis_txidx;
1867 		p->np_m0 = m;
1868 		p->np_oob.npo_status = NDIS_STATUS_PENDING;
1869 
1870 		/*
1871 		 * Do scatter/gather processing, if driver requested it.
1872 		 */
1873 		if (sc->ndis_sc) {
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;
1881 		}
1882 
1883 		/* Handle checksum offload. */
1884 
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;
1897 		}
1898 
1899 		NDIS_INC(sc);
1900 		sc->ndis_txpending--;
1901 
1902 		pcnt++;
1903 
1904 		/*
1905 		 * If there's a BPF listener, bounce a copy of this frame
1906 		 * to him.
1907 		 */
1908 		if (!sc->ndis_80211)	/* XXX handle 80211 */
1909 			BPF_MTAP(ifp, m);
1910 
1911 		/*
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.
1917 		 */
1918 		if (sc->ndis_txidx == 0)
1919 			break;
1920 	}
1921 
1922 	if (pcnt == 0) {
1923 		NDIS_UNLOCK(sc);
1924 		return;
1925 	}
1926 
1927 	if (sc->ndis_txpending == 0)
1928 		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1929 
1930 	/*
1931 	 * Set a timeout in case the chip goes out to lunch.
1932 	 */
1933 	sc->ndis_tx_timer = 5;
1934 
1935 	NDIS_UNLOCK(sc);
1936 
1937 	/*
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
1941 	 * packet).
1942 	 */
1943 	if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1944 		ndis_send_packets(sc, p0, pcnt);
1945 	else
1946 		ndis_send_packet(sc, p);
1947 
1948 	return;
1949 }
1950 
1951 static int
ndis_80211transmit(struct ieee80211com * ic,struct mbuf * m)1952 ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1953 {
1954 	struct ndis_softc *sc = ic->ic_softc;
1955 	ndis_packet **p0 = NULL, *p = NULL;
1956 	int status;
1957 
1958 	NDIS_LOCK(sc);
1959 	if (!sc->ndis_link || !sc->ndis_running) {
1960 		NDIS_UNLOCK(sc);
1961 		return (ENXIO);
1962 	}
1963 
1964 	if (sc->ndis_txpending == 0) {
1965 		NDIS_UNLOCK(sc);
1966 		return (ENOBUFS);
1967 	}
1968 
1969 	p0 = &sc->ndis_txarray[sc->ndis_txidx];
1970 
1971 	NdisAllocatePacket(&status,
1972 	    &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1973 
1974 	if (status != NDIS_STATUS_SUCCESS) {
1975 		NDIS_UNLOCK(sc);
1976 		return (ENOBUFS);
1977 	}
1978 
1979 	if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1980 		NDIS_UNLOCK(sc);
1981 		return (ENOBUFS);
1982 	}
1983 
1984 	/*
1985 	 * Save pointer to original mbuf
1986 	 * so we can free it later.
1987 	 */
1988 
1989 	p = sc->ndis_txarray[sc->ndis_txidx];
1990 	p->np_txidx = sc->ndis_txidx;
1991 	p->np_m0 = m;
1992 	p->np_oob.npo_status = NDIS_STATUS_PENDING;
1993 
1994 	/*
1995 	 * Do scatter/gather processing, if driver requested it.
1996 	 */
1997 	if (sc->ndis_sc) {
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;
2005 	}
2006 
2007 	NDIS_INC(sc);
2008 	sc->ndis_txpending--;
2009 
2010 	/*
2011 	 * Set a timeout in case the chip goes out to lunch.
2012 	 */
2013 	sc->ndis_tx_timer = 5;
2014 	NDIS_UNLOCK(sc);
2015 
2016 	/*
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
2020 	 * packet).
2021 	 */
2022 	if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2023 		ndis_send_packets(sc, p0, 1);
2024 	else
2025 		ndis_send_packet(sc, p);
2026 
2027 	return (0);
2028 }
2029 
2030 static void
ndis_80211parent(struct ieee80211com * ic)2031 ndis_80211parent(struct ieee80211com *ic)
2032 {
2033 	struct ndis_softc *sc = ic->ic_softc;
2034 
2035 	/*NDIS_LOCK(sc);*/
2036 	if (ic->ic_nrunning > 0) {
2037 		if (!sc->ndis_running)
2038 			ndis_init(sc);
2039 	} else if (sc->ndis_running)
2040 		ndis_stop(sc);
2041 	/*NDIS_UNLOCK(sc);*/
2042 }
2043 
2044 static void
ndis_init(void * xsc)2045 ndis_init(void *xsc)
2046 {
2047 	struct ndis_softc	*sc = xsc;
2048 	int			i, len, error;
2049 
2050 	/*
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.
2055 	 */
2056 	if (sc->ndis_link)
2057 		return;
2058 
2059 	/*
2060 	 * Cancel pending I/O and free all RX/TX buffers.
2061 	 */
2062 	ndis_stop(sc);
2063 
2064 	if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2065 		error = ndis_init_nic(sc);
2066 		if (error != 0) {
2067 			device_printf(sc->ndis_dev,
2068 			    "failed to initialize the device: %d\n", error);
2069 			return;
2070 		}
2071 	}
2072 
2073 	/* Program the packet filter */
2074 	sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2075 	    NDIS_PACKET_TYPE_BROADCAST;
2076 
2077 	if (sc->ndis_80211) {
2078 		struct ieee80211com *ic = &sc->ndis_ic;
2079 
2080 		if (ic->ic_promisc > 0)
2081 			sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2082 	} else {
2083 		struct ifnet *ifp = sc->ifp;
2084 
2085 		if (ifp->if_flags & IFF_PROMISC)
2086 			sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2087 	}
2088 
2089 	len = sizeof(sc->ndis_filter);
2090 
2091 	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2092 	    &sc->ndis_filter, &len);
2093 
2094 	if (error)
2095 		device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2096 
2097 	/*
2098 	 * Set lookahead.
2099  	 */
2100 	if (sc->ndis_80211)
2101 		i = ETHERMTU;
2102 	else
2103 		i = sc->ifp->if_mtu;
2104 	len = sizeof(i);
2105 	ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2106 
2107 	/*
2108 	 * Program the multicast filter, if necessary.
2109 	 */
2110 	ndis_setmulti(sc);
2111 
2112 	/* Setup task offload. */
2113 	ndis_set_offload(sc);
2114 
2115 	NDIS_LOCK(sc);
2116 
2117 	sc->ndis_txidx = 0;
2118 	sc->ndis_txpending = sc->ndis_maxpkts;
2119 	sc->ndis_link = 0;
2120 
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;
2125 	}
2126 
2127 	sc->ndis_tx_timer = 0;
2128 
2129 	/*
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.
2134 	 */
2135 	if (sc->ndis_block->nmb_checkforhangsecs == 0)
2136 		sc->ndis_block->nmb_checkforhangsecs = 3;
2137 
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;
2141 	NDIS_UNLOCK(sc);
2142 
2143 	/* XXX force handling */
2144 	if (sc->ndis_80211)
2145 		ieee80211_start_all(&sc->ndis_ic);	/* start all vap's */
2146 }
2147 
2148 /*
2149  * Set media options.
2150  */
2151 static int
ndis_ifmedia_upd(ifp)2152 ndis_ifmedia_upd(ifp)
2153 	struct ifnet		*ifp;
2154 {
2155 	struct ndis_softc		*sc;
2156 
2157 	sc = ifp->if_softc;
2158 
2159 	if (NDIS_INITIALIZED(sc))
2160 		ndis_init(sc);
2161 
2162 	return (0);
2163 }
2164 
2165 /*
2166  * Report current media status.
2167  */
2168 static void
ndis_ifmedia_sts(ifp,ifmr)2169 ndis_ifmedia_sts(ifp, ifmr)
2170 	struct ifnet		*ifp;
2171 	struct ifmediareq	*ifmr;
2172 {
2173 	struct ndis_softc	*sc;
2174 	uint32_t		media_info;
2175 	ndis_media_state	linkstate;
2176 	int			len;
2177 
2178 	ifmr->ifm_status = IFM_AVALID;
2179 	ifmr->ifm_active = IFM_ETHER;
2180 	sc = ifp->if_softc;
2181 
2182 	if (!NDIS_INITIALIZED(sc))
2183 		return;
2184 
2185 	len = sizeof(linkstate);
2186 	ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2187 	    (void *)&linkstate, &len);
2188 
2189 	len = sizeof(media_info);
2190 	ndis_get_info(sc, OID_GEN_LINK_SPEED,
2191 	    (void *)&media_info, &len);
2192 
2193 	if (linkstate == nmc_connected)
2194 		ifmr->ifm_status |= IFM_ACTIVE;
2195 
2196 	switch (media_info) {
2197 	case 100000:
2198 		ifmr->ifm_active |= IFM_10_T;
2199 		break;
2200 	case 1000000:
2201 		ifmr->ifm_active |= IFM_100_TX;
2202 		break;
2203 	case 10000000:
2204 		ifmr->ifm_active |= IFM_1000_T;
2205 		break;
2206 	default:
2207 		device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2208 		break;
2209 	}
2210 }
2211 
2212 static int
ndis_set_cipher(struct ndis_softc * sc,int cipher)2213 ndis_set_cipher(struct ndis_softc *sc, int cipher)
2214 {
2215 	struct ieee80211com	*ic = &sc->ndis_ic;
2216 	int			rval = 0, len;
2217 	uint32_t		arg, save;
2218 
2219 	len = sizeof(arg);
2220 
2221 	if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2222 		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2223 			return (ENOTSUP);
2224 		arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2225 	}
2226 
2227 	if (cipher == WPA_CSE_TKIP) {
2228 		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2229 			return (ENOTSUP);
2230 		arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2231 	}
2232 
2233 	if (cipher == WPA_CSE_CCMP) {
2234 		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2235 			return (ENOTSUP);
2236 		arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2237 	}
2238 
2239 	DPRINTF(("Setting cipher to %d\n", arg));
2240 	save = arg;
2241 	rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2242 
2243 	if (rval)
2244 		return (rval);
2245 
2246 	/* Check that the cipher was set correctly. */
2247 
2248 	len = sizeof(save);
2249 	rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2250 
2251 	if (rval != 0 || arg != save)
2252 		return (ENODEV);
2253 
2254 	return (0);
2255 }
2256 
2257 /*
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.
2264  */
2265 static int
ndis_set_wpa(sc,ie,ielen)2266 ndis_set_wpa(sc, ie, ielen)
2267 	struct ndis_softc	*sc;
2268 	void			*ie;
2269 	int			ielen;
2270 {
2271 	struct ieee80211_ie_wpa	*w;
2272 	struct ndis_ie		*n;
2273 	char			*pos;
2274 	uint32_t		arg;
2275 	int			i;
2276 
2277 	/*
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.
2283 	 */
2284 
2285 	w = (struct ieee80211_ie_wpa *)ie;
2286 
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));
2290 		return (EINVAL);
2291 	}
2292 
2293 	/* Skip over the ucast cipher OIDs. */
2294 	pos = (char *)&w->wpa_uciphers[0];
2295 	pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2296 
2297 	/* Skip over the authmode count. */
2298 	pos += sizeof(u_int16_t);
2299 
2300 	/*
2301 	 * Check for the authentication modes. I'm
2302 	 * pretty sure there's only supposed to be one.
2303 	 */
2304 
2305 	n = (struct ndis_ie *)pos;
2306 	if (n->ni_val == WPA_ASE_NONE)
2307 		arg = NDIS_80211_AUTHMODE_WPANONE;
2308 
2309 	if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2310 		arg = NDIS_80211_AUTHMODE_WPA;
2311 
2312 	if (n->ni_val == WPA_ASE_8021X_PSK)
2313 		arg = NDIS_80211_AUTHMODE_WPAPSK;
2314 
2315 	DPRINTF(("Setting WPA auth mode to %d\n", arg));
2316 	i = sizeof(arg);
2317 	if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2318 		return (ENOTSUP);
2319 	i = sizeof(arg);
2320 	ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2321 
2322 	/* Now configure the desired ciphers. */
2323 
2324 	/* First, set up the multicast group cipher. */
2325 	n = (struct ndis_ie *)&w->wpa_mcipher[0];
2326 
2327 	if (ndis_set_cipher(sc, n->ni_val))
2328 		return (ENOTSUP);
2329 
2330 	/* Now start looking around for the unicast ciphers. */
2331 	pos = (char *)&w->wpa_uciphers[0];
2332 	n = (struct ndis_ie *)pos;
2333 
2334 	for (i = 0; i < w->wpa_uciphercnt; i++) {
2335 		if (ndis_set_cipher(sc, n->ni_val))
2336 			return (ENOTSUP);
2337 		n++;
2338 	}
2339 
2340 	return (0);
2341 }
2342 
2343 static void
ndis_media_status(struct ifnet * ifp,struct ifmediareq * imr)2344 ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2345 {
2346 	struct ieee80211vap *vap = ifp->if_softc;
2347 	struct ndis_softc *sc = vap->iv_ic->ic_softc;
2348 	uint32_t txrate;
2349 	int len;
2350 
2351 	if (!NDIS_INITIALIZED(sc))
2352 		return;
2353 
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);
2358 }
2359 
2360 static void
ndis_setstate_80211(struct ndis_softc * sc)2361 ndis_setstate_80211(struct ndis_softc *sc)
2362 {
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;
2367 	int			rval = 0, len;
2368 	uint32_t		arg;
2369 
2370 	if (!NDIS_INITIALIZED(sc)) {
2371 		DPRINTF(("%s: NDIS not initialized\n", __func__));
2372 		return;
2373 	}
2374 
2375 	/* Disassociate and turn off radio. */
2376 	len = sizeof(arg);
2377 	arg = 1;
2378 	ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2379 
2380 	/* Set network infrastructure mode. */
2381 
2382 	len = sizeof(arg);
2383 	if (ic->ic_opmode == IEEE80211_M_IBSS)
2384 		arg = NDIS_80211_NET_INFRA_IBSS;
2385 	else
2386 		arg = NDIS_80211_NET_INFRA_BSS;
2387 
2388 	rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2389 
2390 	if (rval)
2391 		device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2392 
2393 	/* Set power management */
2394 	len = sizeof(arg);
2395 	if (vap->iv_flags & IEEE80211_F_PMGTON)
2396 		arg = NDIS_80211_POWERMODE_FAST_PSP;
2397 	else
2398 		arg = NDIS_80211_POWERMODE_CAM;
2399 	ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2400 
2401 	/* Set TX power */
2402 	if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2403 	    ic->ic_txpowlimit < (sizeof(dBm2mW) / sizeof(dBm2mW[0]))) {
2404 		arg = dBm2mW[ic->ic_txpowlimit];
2405 		len = sizeof(arg);
2406 		ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2407 	}
2408 
2409 	/*
2410 	 * Default encryption mode to off, authentication
2411 	 * to open and privacy to 'accept everything.'
2412 	 */
2413 	len = sizeof(arg);
2414 	arg = NDIS_80211_WEPSTAT_DISABLED;
2415 	ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2416 
2417 	len = sizeof(arg);
2418 	arg = NDIS_80211_AUTHMODE_OPEN;
2419 	ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2420 
2421 	/*
2422 	 * Note that OID_802_11_PRIVACY_FILTER is optional:
2423 	 * not all drivers implement it.
2424 	 */
2425 	len = sizeof(arg);
2426 	arg = NDIS_80211_PRIVFILT_8021XWEP;
2427 	ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2428 
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);
2434 
2435 	/*
2436 	 * Some drivers expect us to initialize these values, so
2437 	 * provide some defaults.
2438 	 */
2439 
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) {
2447 		int chan, chanflag;
2448 
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,
2461 			    &config, &len);
2462 			if (rval)
2463 				device_printf(sc->ndis_dev, "couldn't change "
2464 				    "DS config to %ukHz: %d\n",
2465 				    config.nc_dsconfig, rval);
2466 		}
2467 	} else if (rval)
2468 		device_printf(sc->ndis_dev, "couldn't retrieve "
2469 		    "channel info: %d\n", rval);
2470 
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);
2476 	if (rval)
2477 		device_printf(sc->ndis_dev,
2478 		    "setting BSSID failed: %d\n", rval);
2479 }
2480 
2481 static void
ndis_auth_and_assoc(struct ndis_softc * sc,struct ieee80211vap * vap)2482 ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2483 {
2484 	struct ieee80211_node	*ni = vap->iv_bss;
2485 	ndis_80211_ssid		ssid;
2486 	ndis_80211_macaddr	bssid;
2487 	ndis_80211_wep		wep;
2488 	int			i, rval = 0, len, error;
2489 	uint32_t		arg;
2490 
2491 	if (!NDIS_INITIALIZED(sc)) {
2492 		DPRINTF(("%s: NDIS not initialized\n", __func__));
2493 		return;
2494 	}
2495 
2496 	/* Initial setup */
2497 	ndis_setstate_80211(sc);
2498 
2499 	/* Set network infrastructure mode. */
2500 
2501 	len = sizeof(arg);
2502 	if (vap->iv_opmode == IEEE80211_M_IBSS)
2503 		arg = NDIS_80211_NET_INFRA_IBSS;
2504 	else
2505 		arg = NDIS_80211_NET_INFRA_BSS;
2506 
2507 	rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2508 
2509 	if (rval)
2510 		device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2511 
2512 	/* Set RTS threshold */
2513 
2514 	len = sizeof(arg);
2515 	arg = vap->iv_rtsthreshold;
2516 	ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2517 
2518 	/* Set fragmentation threshold */
2519 
2520 	len = sizeof(arg);
2521 	arg = vap->iv_fragthreshold;
2522 	ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2523 
2524 	/* Set WEP */
2525 
2526 	if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2527 	    !(vap->iv_flags & IEEE80211_F_WPA)) {
2528 		int keys_set = 0;
2529 
2530 		if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2531 			len = sizeof(arg);
2532 			arg = NDIS_80211_AUTHMODE_SHARED;
2533 			DPRINTF(("Setting shared auth\n"));
2534 			ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2535 			    &arg, &len);
2536 		}
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)
2541 					continue;
2542 				bzero((char *)&wep, sizeof(wep));
2543 				wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2544 
2545 				/*
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.
2550 				 */
2551 				if (vap->iv_nw_keys[i].wk_keylen < 5)
2552 					wep.nw_keylen = 5;
2553 				else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2554 				     vap->iv_nw_keys[i].wk_keylen < 13)
2555 					wep.nw_keylen = 13;
2556 				else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2557 				     vap->iv_nw_keys[i].wk_keylen < 16)
2558 					wep.nw_keylen = 16;
2559 
2560 				wep.nw_keyidx = i;
2561 				wep.nw_length = (sizeof(uint32_t) * 3)
2562 				    + wep.nw_keylen;
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);
2567 				len = sizeof(wep);
2568 				DPRINTF(("Setting WEP key %d\n", i));
2569 				rval = ndis_set_info(sc,
2570 				    OID_802_11_ADD_WEP, &wep, &len);
2571 				if (rval)
2572 					device_printf(sc->ndis_dev,
2573 					    "set wepkey failed: %d\n", rval);
2574 				keys_set++;
2575 			}
2576 		}
2577 		if (keys_set) {
2578 			DPRINTF(("Setting WEP on\n"));
2579 			arg = NDIS_80211_WEPSTAT_ENABLED;
2580 			len = sizeof(arg);
2581 			rval = ndis_set_info(sc,
2582 			    OID_802_11_WEP_STATUS, &arg, &len);
2583 			if (rval)
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;
2588 			else
2589 				arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2590 
2591 			len = sizeof(arg);
2592 			ndis_set_info(sc,
2593 			    OID_802_11_PRIVACY_FILTER, &arg, &len);
2594 		}
2595 	}
2596 
2597 	/* Set up WPA. */
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);
2602 		if (error != 0)
2603 			device_printf(sc->ndis_dev, "WPA setup failed\n");
2604 	}
2605 
2606 #ifdef notyet
2607 	/* Set network type. */
2608 
2609 	arg = 0;
2610 
2611 	switch (vap->iv_curmode) {
2612 	case IEEE80211_MODE_11A:
2613 		arg = NDIS_80211_NETTYPE_11OFDM5;
2614 		break;
2615 	case IEEE80211_MODE_11B:
2616 		arg = NDIS_80211_NETTYPE_11DS;
2617 		break;
2618 	case IEEE80211_MODE_11G:
2619 		arg = NDIS_80211_NETTYPE_11OFDM24;
2620 		break;
2621 	default:
2622 		device_printf(sc->ndis_dev, "unknown mode: %d\n",
2623 		    vap->iv_curmode);
2624 	}
2625 
2626 	if (arg) {
2627 		DPRINTF(("Setting network type to %d\n", arg));
2628 		len = sizeof(arg);
2629 		rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2630 		    &arg, &len);
2631 		if (rval)
2632 			device_printf(sc->ndis_dev,
2633 			    "set nettype failed: %d\n", rval);
2634 	}
2635 #endif
2636 
2637 	/*
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.
2649 	 */
2650 
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);
2655 	else
2656 		bcopy(ieee80211broadcastaddr, bssid, len);
2657 
2658 	DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2659 	rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2660 	if (rval)
2661 		device_printf(sc->ndis_dev,
2662 		    "setting BSSID failed: %d\n", rval);
2663 
2664 	/* Set SSID -- always do this last. */
2665 
2666 #ifdef NDIS_DEBUG
2667 	if (ndis_debug > 0) {
2668 		printf("Setting ESSID to ");
2669 		ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2670 		printf("\n");
2671 	}
2672 #endif
2673 
2674 	len = sizeof(ssid);
2675 	bzero((char *)&ssid, len);
2676 	ssid.ns_ssidlen = ni->ni_esslen;
2677 	if (ssid.ns_ssidlen == 0) {
2678 		ssid.ns_ssidlen = 1;
2679 	} else
2680 		bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2681 
2682 	rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2683 
2684 	if (rval)
2685 		device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2686 
2687 	return;
2688 }
2689 
2690 static int
ndis_get_bssid_list(sc,bl)2691 ndis_get_bssid_list(sc, bl)
2692 	struct ndis_softc	*sc;
2693 	ndis_80211_bssid_list_ex	**bl;
2694 {
2695 	int	len, error;
2696 
2697 	len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2698 	*bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2699 	if (*bl == NULL)
2700 		return (ENOMEM);
2701 
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);
2706 		if (*bl == NULL)
2707 			return (ENOMEM);
2708 
2709 		error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2710 	}
2711 	if (error) {
2712 		DPRINTF(("%s: failed to read\n", __func__));
2713 		free(*bl, M_DEVBUF);
2714 		return (error);
2715 	}
2716 
2717 	return (0);
2718 }
2719 
2720 static int
ndis_get_assoc(struct ndis_softc * sc,ndis_wlan_bssid_ex ** assoc)2721 ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2722 {
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;
2729 	int			i, len, error;
2730 
2731 	if (!sc->ndis_link)
2732 		return (ENOENT);
2733 
2734 	len = sizeof(bssid);
2735 	error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2736 	if (error) {
2737 		device_printf(sc->ndis_dev, "failed to get bssid\n");
2738 		return (ENOENT);
2739 	}
2740 
2741 	vap = TAILQ_FIRST(&ic->ic_vaps);
2742 	ni = vap->iv_bss;
2743 
2744 	error = ndis_get_bssid_list(sc, &bl);
2745 	if (error)
2746 		return (error);
2747 
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) {
2753 				free(bl, M_TEMP);
2754 				return (ENOMEM);
2755 			}
2756 			bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2757 			free(bl, M_TEMP);
2758 			if (ic->ic_opmode == IEEE80211_M_STA)
2759 				ni->ni_associd = 1 | 0xc000; /* fake associd */
2760 			return (0);
2761 		}
2762 		bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2763 	}
2764 
2765 	free(bl, M_TEMP);
2766 	return (ENOENT);
2767 }
2768 
2769 static void
ndis_getstate_80211(struct ndis_softc * sc)2770 ndis_getstate_80211(struct ndis_softc *sc)
2771 {
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;
2777 	int			chanflag;
2778 	uint32_t		arg;
2779 
2780 	if (!NDIS_INITIALIZED(sc))
2781 		return;
2782 
2783 	if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2784 		return;
2785 
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);
2790 
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;
2795 
2796 	if (ic->ic_caps & IEEE80211_C_PMGT) {
2797 		len = sizeof(arg);
2798 		rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2799 
2800 		if (rval)
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;
2805 		else
2806 			vap->iv_flags |= IEEE80211_F_PMGTON;
2807 	}
2808 
2809 	/* Get TX power */
2810 	if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2811 		len = sizeof(arg);
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)
2815 				break;
2816 		ic->ic_txpowlimit = i;
2817 	}
2818 
2819 	/*
2820 	 * Use the current association information to reflect
2821 	 * what channel we're on.
2822 	 */
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;
2829 
2830 	free(bs, M_TEMP);
2831 
2832 	/*
2833 	 * Determine current authentication mode.
2834 	 */
2835 	len = sizeof(arg);
2836 	rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2837 	if (rval)
2838 		device_printf(sc->ndis_dev,
2839 		    "get authmode status failed: %d\n", rval);
2840 	else {
2841 		vap->iv_flags &= ~IEEE80211_F_WPA;
2842 		switch (arg) {
2843 		case NDIS_80211_AUTHMODE_OPEN:
2844 			ni->ni_authmode = IEEE80211_AUTH_OPEN;
2845 			break;
2846 		case NDIS_80211_AUTHMODE_SHARED:
2847 			ni->ni_authmode = IEEE80211_AUTH_SHARED;
2848 			break;
2849 		case NDIS_80211_AUTHMODE_AUTO:
2850 			ni->ni_authmode = IEEE80211_AUTH_AUTO;
2851 			break;
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;
2857 			break;
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;
2862 			break;
2863 		default:
2864 			ni->ni_authmode = IEEE80211_AUTH_NONE;
2865 			break;
2866 		}
2867 	}
2868 
2869 	len = sizeof(arg);
2870 	rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2871 
2872 	if (rval)
2873 		device_printf(sc->ndis_dev,
2874 		    "get wep status failed: %d\n", rval);
2875 
2876 	if (arg == NDIS_80211_WEPSTAT_ENABLED)
2877 		vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2878 	else
2879 		vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2880 }
2881 
2882 static int
ndis_ioctl(ifp,command,data)2883 ndis_ioctl(ifp, command, data)
2884 	struct ifnet		*ifp;
2885 	u_long			command;
2886 	caddr_t			data;
2887 {
2888 	struct ndis_softc	*sc = ifp->if_softc;
2889 	struct ifreq		*ifr = (struct ifreq *) data;
2890 	int			i, error = 0;
2891 
2892 	/*NDIS_LOCK(sc);*/
2893 
2894 	switch (command) {
2895 	case SIOCSIFFLAGS:
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)) {
2900 				sc->ndis_filter |=
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) {
2909 				sc->ndis_filter &=
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);
2915 			} else
2916 				ndis_init(sc);
2917 		} else {
2918 			if (sc->ndis_running)
2919 				ndis_stop(sc);
2920 		}
2921 		sc->ndis_if_flags = ifp->if_flags;
2922 		error = 0;
2923 		break;
2924 	case SIOCADDMULTI:
2925 	case SIOCDELMULTI:
2926 		ndis_setmulti(sc);
2927 		error = 0;
2928 		break;
2929 	case SIOCGIFMEDIA:
2930 	case SIOCSIFMEDIA:
2931 		error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2932 		break;
2933 	case SIOCSIFCAP:
2934 		ifp->if_capenable = ifr->ifr_reqcap;
2935 		if (ifp->if_capenable & IFCAP_TXCSUM)
2936 			ifp->if_hwassist = sc->ndis_hwassist;
2937 		else
2938 			ifp->if_hwassist = 0;
2939 		ndis_set_offload(sc);
2940 		break;
2941 	default:
2942 		error = ether_ioctl(ifp, command, data);
2943 		break;
2944 	}
2945 
2946 	/*NDIS_UNLOCK(sc);*/
2947 
2948 	return(error);
2949 }
2950 
2951 static int
ndis_80211ioctl(struct ieee80211com * ic,u_long cmd,void * data)2952 ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2953 {
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;
2959 	int error = 0;
2960 
2961 	if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2962 		return (error);
2963 
2964 	switch (cmd) {
2965 	case SIOCGDRVSPEC:
2966 	case SIOCSDRVSPEC:
2967 		error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2968 		if (error)
2969 			break;
2970 		oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2971 		error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2972 	}
2973 
2974 	if (error) {
2975 		free(oidbuf, M_TEMP);
2976 		return (error);
2977 	}
2978 
2979 	switch (cmd) {
2980 	case SIOCGDRVSPEC:
2981 		error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2982 		break;
2983 	case SIOCSDRVSPEC:
2984 		error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2985 		break;
2986 	case SIOCGPRIVATE_0:
2987 		NDIS_LOCK(sc);
2988 		if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
2989 			error = ENOENT;
2990 			NDIS_UNLOCK(sc);
2991 			break;
2992 		}
2993 		error = copyin(ifr->ifr_data, &evt, sizeof(evt));
2994 		if (error) {
2995 			NDIS_UNLOCK(sc);
2996 			break;
2997 		}
2998 		if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
2999 			error = ENOSPC;
3000 			NDIS_UNLOCK(sc);
3001 			break;
3002 		}
3003 		error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3004 		    ifr->ifr_data, sizeof(uint32_t) * 2);
3005 		if (error) {
3006 			NDIS_UNLOCK(sc);
3007 			break;
3008 		}
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);
3013 			if (error) {
3014 				NDIS_UNLOCK(sc);
3015 				break;
3016 			}
3017 			free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3018 			sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3019 		}
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);
3023 		NDIS_UNLOCK(sc);
3024 		break;
3025 	default:
3026 		error = ENOTTY;
3027 		break;
3028 	}
3029 
3030 	switch (cmd) {
3031 	case SIOCGDRVSPEC:
3032 	case SIOCSDRVSPEC:
3033 		error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3034 		if (error)
3035 			break;
3036 		error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3037 	}
3038 
3039 	free(oidbuf, M_TEMP);
3040 
3041 	return (error);
3042 }
3043 
3044 int
ndis_del_key(struct ieee80211vap * vap,const struct ieee80211_key * key)3045 ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3046 {
3047 	struct ndis_softc	*sc = vap->iv_ic->ic_softc;
3048 	ndis_80211_key		rkey;
3049 	int			len, error = 0;
3050 
3051 	bzero((char *)&rkey, sizeof(rkey));
3052 	len = sizeof(rkey);
3053 
3054 	rkey.nk_len = len;
3055 	rkey.nk_keyidx = key->wk_keyix;
3056 
3057 	bcopy(vap->iv_ifp->if_broadcastaddr,
3058 	    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3059 
3060 	error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3061 
3062 	if (error)
3063 		return (0);
3064 
3065 	return (1);
3066 }
3067 
3068 /*
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.
3072  */
3073 static int
ndis_add_key(struct ieee80211vap * vap,const struct ieee80211_key * key)3074 ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3075 {
3076 	struct ndis_softc	*sc = vap->iv_ic->ic_softc;
3077 	ndis_80211_key		rkey;
3078 	int			len, error = 0;
3079 
3080 	switch (key->wk_cipher->ic_cipher) {
3081 	case IEEE80211_CIPHER_TKIP:
3082 
3083 		len = sizeof(ndis_80211_key);
3084 		bzero((char *)&rkey, sizeof(rkey));
3085 
3086 		rkey.nk_len = len;
3087 		rkey.nk_keylen = key->wk_keylen;
3088 
3089 		if (key->wk_flags & IEEE80211_KEY_SWMIC)
3090 			rkey.nk_keylen += 16;
3091 
3092 		/* key index - gets weird in NDIS */
3093 
3094 		if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3095 			rkey.nk_keyidx = key->wk_keyix;
3096 		else
3097 			rkey.nk_keyidx = 0;
3098 
3099 		if (key->wk_flags & IEEE80211_KEY_XMIT)
3100 			rkey.nk_keyidx |= 1 << 31;
3101 
3102 		if (key->wk_flags & IEEE80211_KEY_GROUP) {
3103 			bcopy(ieee80211broadcastaddr,
3104 			    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3105 		} else {
3106 			bcopy(vap->iv_bss->ni_bssid,
3107 			    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3108 			/* pairwise key */
3109 			rkey.nk_keyidx |= 1 << 30;
3110 		}
3111 
3112 		/* need to set bit 29 based on keyrsc */
3113 		rkey.nk_keyrsc = key->wk_keyrsc[0];	/* XXX need tid */
3114 
3115 		if (rkey.nk_keyrsc)
3116 			rkey.nk_keyidx |= 1 << 29;
3117 
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);
3122 		} else
3123 			bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3124 
3125 		error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3126 		break;
3127 	case IEEE80211_CIPHER_WEP:
3128 		error = 0;
3129 		break;
3130 	/*
3131 	 * I don't know how to set up keys for the AES
3132 	 * cipher yet. Is it the same as TKIP?
3133 	 */
3134 	case IEEE80211_CIPHER_AES_CCM:
3135 	default:
3136 		error = ENOTTY;
3137 		break;
3138 	}
3139 
3140 	/* We need to return 1 for success, 0 for failure. */
3141 
3142 	if (error)
3143 		return (0);
3144 
3145 	return (1);
3146 }
3147 
3148 static void
ndis_resettask(d,arg)3149 ndis_resettask(d, arg)
3150 	device_object		*d;
3151 	void			*arg;
3152 {
3153 	struct ndis_softc		*sc;
3154 
3155 	sc = arg;
3156 	ndis_reset_nic(sc);
3157 }
3158 
3159 /*
3160  * Stop the adapter and free any mbufs allocated to the
3161  * RX and TX lists.
3162  */
3163 static void
ndis_stop(struct ndis_softc * sc)3164 ndis_stop(struct ndis_softc *sc)
3165 {
3166 	int			i;
3167 
3168 	callout_drain(&sc->ndis_stat_callout);
3169 
3170 	NDIS_LOCK(sc);
3171 	sc->ndis_tx_timer = 0;
3172 	sc->ndis_link = 0;
3173 	if (!sc->ndis_80211)
3174 		sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3175 	sc->ndis_running = 0;
3176 	NDIS_UNLOCK(sc);
3177 
3178 	if (sc->ndis_iftype != PNPBus ||
3179 	    (sc->ndis_iftype == PNPBus &&
3180 	     !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3181 	     ndisusb_halt != 0))
3182 		ndis_halt_nic(sc);
3183 
3184 	NDIS_LOCK(sc);
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;
3189 		}
3190 		sc->ndis_evt[i].ne_sts = 0;
3191 		sc->ndis_evt[i].ne_len = 0;
3192 	}
3193 	sc->ndis_evtcidx = 0;
3194 	sc->ndis_evtpidx = 0;
3195 	NDIS_UNLOCK(sc);
3196 }
3197 
3198 /*
3199  * Stop all chip I/O so that the kernel's probe routines don't
3200  * get confused by errant DMAs when rebooting.
3201  */
3202 void
ndis_shutdown(dev)3203 ndis_shutdown(dev)
3204 	device_t		dev;
3205 {
3206 	struct ndis_softc		*sc;
3207 
3208 	sc = device_get_softc(dev);
3209 	ndis_stop(sc);
3210 }
3211 
3212 static int
ndis_newstate(struct ieee80211vap * vap,enum ieee80211_state nstate,int arg)3213 ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3214 {
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;
3219 
3220 	DPRINTF(("%s: %s -> %s\n", __func__,
3221 		ieee80211_state_name[vap->iv_state],
3222 		ieee80211_state_name[nstate]));
3223 
3224 	ostate = vap->iv_state;
3225 	vap->iv_state = nstate;
3226 
3227 	switch (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);
3236 			IEEE80211_LOCK(ic);
3237 		}
3238 		break;
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);
3244 		IEEE80211_LOCK(ic);
3245 		break;
3246 	default:
3247 		break;
3248 	}
3249 	return (0);
3250 }
3251 
3252 static void
ndis_scan(void * arg)3253 ndis_scan(void *arg)
3254 {
3255 	struct ieee80211vap *vap = arg;
3256 
3257 	ieee80211_scan_done(vap);
3258 }
3259 
3260 static void
ndis_scan_results(struct ndis_softc * sc)3261 ndis_scan_results(struct ndis_softc *sc)
3262 {
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;
3270 	int i, j;
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;
3275 
3276 	saved_chan = ic->ic_curchan;
3277 	noise = -96;
3278 
3279 	if (ndis_get_bssid_list(sc, &bl))
3280 		return;
3281 
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));
3286 
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;
3297 				break;
3298 			case NDIS_80211_NET_INFRA_BSS:
3299 				sp.capinfo |= IEEE80211_CAPINFO_ESS;
3300 				break;
3301 		}
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)
3306 				break;
3307 			rates[2 + j] =
3308 			wb->nwbx_supportedrates[j] & 0x7f;
3309 		}
3310 		rates[1] = j;
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;
3315 
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];
3323 
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)
3329 				goto done;
3330 			sp.tstamp = frm;			frm += 8;
3331 			sp.bintval = le16toh(*(uint16_t *)frm);	frm += 2;
3332 			sp.capinfo = le16toh(*(uint16_t *)frm);	frm += 2;
3333 			sp.ies = frm;
3334 			sp.ies_len = efrm - frm;
3335 		}
3336 done:
3337 		DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3338 		    ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3339 		    rssi));
3340 		ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3341 		wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3342 	}
3343 	free(bl, M_DEVBUF);
3344 	/* Restore the channel after messing with it */
3345 	ic->ic_curchan = saved_chan;
3346 }
3347 
3348 static void
ndis_scan_start(struct ieee80211com * ic)3349 ndis_scan_start(struct ieee80211com *ic)
3350 {
3351 	struct ndis_softc *sc = ic->ic_softc;
3352 	struct ieee80211vap *vap;
3353 	struct ieee80211_scan_state *ss;
3354 	ndis_80211_ssid ssid;
3355 	int error, len;
3356 
3357 	ss = ic->ic_scan;
3358 	vap = TAILQ_FIRST(&ic->ic_vaps);
3359 
3360 	if (!NDIS_INITIALIZED(sc)) {
3361 		DPRINTF(("%s: scan aborted\n", __func__));
3362 		ieee80211_cancel_scan(vap);
3363 		return;
3364 	}
3365 
3366 	len = sizeof(ssid);
3367 	bzero((char *)&ssid, len);
3368 	if (ss->ss_nssid == 0)
3369 		ssid.ns_ssidlen = 1;
3370 	else {
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);
3374 	}
3375 
3376 	error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3377 	if (error)
3378 		DPRINTF(("%s: set ESSID failed\n", __func__));
3379 
3380 	len = 0;
3381 	error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3382 	if (error) {
3383 		DPRINTF(("%s: scan command failed\n", __func__));
3384 		ieee80211_cancel_scan(vap);
3385 		return;
3386 	}
3387 	/* Set a timer to collect the results */
3388 	callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3389 }
3390 
3391 static void
ndis_set_channel(struct ieee80211com * ic)3392 ndis_set_channel(struct ieee80211com *ic)
3393 {
3394 	/* ignore */
3395 }
3396 
3397 static void
ndis_scan_curchan(struct ieee80211_scan_state * ss,unsigned long maxdwell)3398 ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3399 {
3400 	/* ignore */
3401 }
3402 
3403 static void
ndis_scan_mindwell(struct ieee80211_scan_state * ss)3404 ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3405 {
3406 	/* NB: don't try to abort scan; wait for firmware to finish */
3407 }
3408 
3409 static void
ndis_scan_end(struct ieee80211com * ic)3410 ndis_scan_end(struct ieee80211com *ic)
3411 {
3412 	struct ndis_softc *sc = ic->ic_softc;
3413 
3414 	ndis_scan_results(sc);
3415 }
3416