if_ndis.c revision 330897
1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 2003
5 *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * WPA support originally contributed by Arvind Srinivasan <arvind@celar.us>
35 * then hacked upon mercilessly by my.
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: stable/11/sys/dev/if_ndis/if_ndis.c 330897 2018-03-14 03:19:51Z eadler $");
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/sockio.h>
44#include <sys/mbuf.h>
45#include <sys/malloc.h>
46#include <sys/endian.h>
47#include <sys/priv.h>
48#include <sys/kernel.h>
49#include <sys/socket.h>
50#include <sys/queue.h>
51#include <sys/module.h>
52#include <sys/proc.h>
53#include <sys/sysctl.h>
54#include <sys/kthread.h>
55#include <sys/limits.h>
56
57#include <net/if.h>
58#include <net/if_var.h>
59#include <net/if_arp.h>
60#include <net/ethernet.h>
61#include <net/if_dl.h>
62#include <net/if_media.h>
63#include <net/if_types.h>
64#include <net/route.h>
65
66#include <net/bpf.h>
67
68#include <machine/bus.h>
69#include <machine/resource.h>
70#include <sys/bus.h>
71#include <sys/rman.h>
72
73#include <net80211/ieee80211_var.h>
74#include <net80211/ieee80211_ioctl.h>
75#include <net80211/ieee80211_regdomain.h>
76
77#include <dev/pci/pcireg.h>
78#include <dev/pci/pcivar.h>
79#include <dev/usb/usb.h>
80#include <dev/usb/usbdi.h>
81
82#include <compat/ndis/pe_var.h>
83#include <compat/ndis/cfg_var.h>
84#include <compat/ndis/resource_var.h>
85#include <compat/ndis/ntoskrnl_var.h>
86#include <compat/ndis/hal_var.h>
87#include <compat/ndis/ndis_var.h>
88#include <compat/ndis/usbd_var.h>
89#include <dev/if_ndis/if_ndisvar.h>
90
91#define NDIS_DEBUG
92#ifdef NDIS_DEBUG
93#define DPRINTF(x)	do { if (ndis_debug > 0) printf x; } while (0)
94int ndis_debug = 0;
95SYSCTL_INT(_debug, OID_AUTO, ndis, CTLFLAG_RW, &ndis_debug, 0,
96    "if_ndis debug level");
97#else
98#define DPRINTF(x)
99#endif
100
101SYSCTL_DECL(_hw_ndisusb);
102int ndisusb_halt = 1;
103SYSCTL_INT(_hw_ndisusb, OID_AUTO, halt, CTLFLAG_RW, &ndisusb_halt, 0,
104    "Halt NDIS USB driver when it's attached");
105
106/* 0 - 30 dBm to mW conversion table */
107static const uint16_t dBm2mW[] = {
108	1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
109	3, 4, 4, 4, 5, 6, 6, 7, 8, 9,
110	10, 11, 13, 14, 16, 18, 20, 22, 25, 28,
111	32, 35, 40, 45, 50, 56, 63, 71, 79, 89,
112	100, 112, 126, 141, 158, 178, 200, 224, 251, 282,
113	316, 355, 398, 447, 501, 562, 631, 708, 794, 891,
114	1000
115};
116
117MODULE_DEPEND(ndis, ether, 1, 1, 1);
118MODULE_DEPEND(ndis, wlan, 1, 1, 1);
119MODULE_DEPEND(ndis, ndisapi, 1, 1, 1);
120
121MODULE_VERSION(ndis, 1);
122
123int ndis_attach			(device_t);
124int ndis_detach			(device_t);
125int ndis_suspend		(device_t);
126int ndis_resume			(device_t);
127void ndis_shutdown		(device_t);
128
129int ndisdrv_modevent		(module_t, int, void *);
130
131static void ndis_txeof		(ndis_handle, ndis_packet *, ndis_status);
132static void ndis_rxeof		(ndis_handle, ndis_packet **, uint32_t);
133static void ndis_rxeof_eth	(ndis_handle, ndis_handle, char *, void *,
134				 uint32_t, void *, uint32_t, uint32_t);
135static void ndis_rxeof_done	(ndis_handle);
136static void ndis_rxeof_xfr	(kdpc *, ndis_handle, void *, void *);
137static void ndis_rxeof_xfr_done	(ndis_handle, ndis_packet *,
138				 uint32_t, uint32_t);
139static void ndis_linksts	(ndis_handle, ndis_status, void *, uint32_t);
140static void ndis_linksts_done	(ndis_handle);
141
142/* We need to wrap these functions for amd64. */
143static funcptr ndis_txeof_wrap;
144static funcptr ndis_rxeof_wrap;
145static funcptr ndis_rxeof_eth_wrap;
146static funcptr ndis_rxeof_done_wrap;
147static funcptr ndis_rxeof_xfr_wrap;
148static funcptr ndis_rxeof_xfr_done_wrap;
149static funcptr ndis_linksts_wrap;
150static funcptr ndis_linksts_done_wrap;
151static funcptr ndis_ticktask_wrap;
152static funcptr ndis_ifstarttask_wrap;
153static funcptr ndis_resettask_wrap;
154static funcptr ndis_inputtask_wrap;
155
156static struct	ieee80211vap *ndis_vap_create(struct ieee80211com *,
157		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
158		    const uint8_t [IEEE80211_ADDR_LEN],
159		    const uint8_t [IEEE80211_ADDR_LEN]);
160static void ndis_vap_delete	(struct ieee80211vap *);
161static void ndis_tick		(void *);
162static void ndis_ticktask	(device_object *, void *);
163static int ndis_raw_xmit	(struct ieee80211_node *, struct mbuf *,
164	const struct ieee80211_bpf_params *);
165static void ndis_update_mcast	(struct ieee80211com *);
166static void ndis_update_promisc	(struct ieee80211com *);
167static void ndis_ifstart	(struct ifnet *);
168static void ndis_ifstarttask	(device_object *, void *);
169static void ndis_resettask	(device_object *, void *);
170static void ndis_inputtask	(device_object *, void *);
171static int ndis_ifioctl		(struct ifnet *, u_long, caddr_t);
172static int ndis_newstate	(struct ieee80211vap *, enum ieee80211_state,
173	int);
174static int ndis_nettype_chan	(uint32_t);
175static int ndis_nettype_mode	(uint32_t);
176static void ndis_scan		(void *);
177static void ndis_scan_results	(struct ndis_softc *);
178static void ndis_scan_start	(struct ieee80211com *);
179static void ndis_scan_end	(struct ieee80211com *);
180static void ndis_set_channel	(struct ieee80211com *);
181static void ndis_scan_curchan	(struct ieee80211_scan_state *, unsigned long);
182static void ndis_scan_mindwell	(struct ieee80211_scan_state *);
183static void ndis_init		(void *);
184static void ndis_stop		(struct ndis_softc *);
185static int ndis_ifmedia_upd	(struct ifnet *);
186static void ndis_ifmedia_sts	(struct ifnet *, struct ifmediareq *);
187static int ndis_get_bssid_list	(struct ndis_softc *,
188					ndis_80211_bssid_list_ex **);
189static int ndis_get_assoc	(struct ndis_softc *, ndis_wlan_bssid_ex **);
190static int ndis_probe_offload	(struct ndis_softc *);
191static int ndis_set_offload	(struct ndis_softc *);
192static void ndis_getstate_80211	(struct ndis_softc *);
193static void ndis_setstate_80211	(struct ndis_softc *);
194static void ndis_auth_and_assoc	(struct ndis_softc *, struct ieee80211vap *);
195static void ndis_media_status	(struct ifnet *, struct ifmediareq *);
196static int ndis_set_cipher	(struct ndis_softc *, int);
197static int ndis_set_wpa		(struct ndis_softc *, void *, int);
198static int ndis_add_key		(struct ieee80211vap *,
199	const struct ieee80211_key *);
200static int ndis_del_key		(struct ieee80211vap *,
201	const struct ieee80211_key *);
202static void ndis_setmulti	(struct ndis_softc *);
203static void ndis_map_sclist	(void *, bus_dma_segment_t *,
204	int, bus_size_t, int);
205static int ndis_ifattach(struct ndis_softc *);
206
207static int ndis_80211attach(struct ndis_softc *);
208static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
209static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
210static void ndis_80211parent(struct ieee80211com *);
211
212static int ndisdrv_loaded = 0;
213
214/*
215 * This routine should call windrv_load() once for each driver
216 * image. This will do the relocation and dynalinking for the
217 * image, and create a Windows driver object which will be
218 * saved in our driver database.
219 */
220int
221ndisdrv_modevent(mod, cmd, arg)
222	module_t		mod;
223	int			cmd;
224	void			*arg;
225{
226	int			error = 0;
227
228	switch (cmd) {
229	case MOD_LOAD:
230		ndisdrv_loaded++;
231                if (ndisdrv_loaded > 1)
232			break;
233		windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap,
234		    3, WINDRV_WRAP_STDCALL);
235		windrv_wrap((funcptr)ndis_rxeof_eth, &ndis_rxeof_eth_wrap,
236		    8, WINDRV_WRAP_STDCALL);
237		windrv_wrap((funcptr)ndis_rxeof_done, &ndis_rxeof_done_wrap,
238		    1, WINDRV_WRAP_STDCALL);
239		windrv_wrap((funcptr)ndis_rxeof_xfr, &ndis_rxeof_xfr_wrap,
240		    4, WINDRV_WRAP_STDCALL);
241		windrv_wrap((funcptr)ndis_rxeof_xfr_done,
242		    &ndis_rxeof_xfr_done_wrap, 4, WINDRV_WRAP_STDCALL);
243		windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap,
244		    3, WINDRV_WRAP_STDCALL);
245		windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap,
246		    4, WINDRV_WRAP_STDCALL);
247		windrv_wrap((funcptr)ndis_linksts_done,
248		    &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
249		windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
250		    2, WINDRV_WRAP_STDCALL);
251		windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap,
252		    2, WINDRV_WRAP_STDCALL);
253		windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
254		    2, WINDRV_WRAP_STDCALL);
255		windrv_wrap((funcptr)ndis_inputtask, &ndis_inputtask_wrap,
256		    2, WINDRV_WRAP_STDCALL);
257		break;
258	case MOD_UNLOAD:
259		ndisdrv_loaded--;
260		if (ndisdrv_loaded > 0)
261			break;
262		/* fallthrough */
263	case MOD_SHUTDOWN:
264		windrv_unwrap(ndis_rxeof_wrap);
265		windrv_unwrap(ndis_rxeof_eth_wrap);
266		windrv_unwrap(ndis_rxeof_done_wrap);
267		windrv_unwrap(ndis_rxeof_xfr_wrap);
268		windrv_unwrap(ndis_rxeof_xfr_done_wrap);
269		windrv_unwrap(ndis_txeof_wrap);
270		windrv_unwrap(ndis_linksts_wrap);
271		windrv_unwrap(ndis_linksts_done_wrap);
272		windrv_unwrap(ndis_ticktask_wrap);
273		windrv_unwrap(ndis_ifstarttask_wrap);
274		windrv_unwrap(ndis_resettask_wrap);
275		windrv_unwrap(ndis_inputtask_wrap);
276		break;
277	default:
278		error = EINVAL;
279		break;
280	}
281
282	return (error);
283}
284
285/*
286 * Program the 64-bit multicast hash filter.
287 */
288static void
289ndis_setmulti(sc)
290	struct ndis_softc	*sc;
291{
292	struct ifnet		*ifp;
293	struct ifmultiaddr	*ifma;
294	int			len, mclistsz, error;
295	uint8_t			*mclist;
296
297
298	if (!NDIS_INITIALIZED(sc))
299		return;
300
301	if (sc->ndis_80211)
302		return;
303
304	ifp = sc->ifp;
305	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
306		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
307		len = sizeof(sc->ndis_filter);
308		error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
309		    &sc->ndis_filter, &len);
310		if (error)
311			device_printf(sc->ndis_dev,
312			    "set allmulti failed: %d\n", error);
313		return;
314	}
315
316	if (TAILQ_EMPTY(&ifp->if_multiaddrs))
317		return;
318
319	len = sizeof(mclistsz);
320	ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
321
322	mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
323
324	if (mclist == NULL) {
325		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
326		goto out;
327	}
328
329	sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
330
331	len = 0;
332	if_maddr_rlock(ifp);
333	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
334		if (ifma->ifma_addr->sa_family != AF_LINK)
335			continue;
336		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
337		    mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
338		len++;
339		if (len > mclistsz) {
340			if_maddr_runlock(ifp);
341			sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
342			sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
343			goto out;
344		}
345	}
346	if_maddr_runlock(ifp);
347
348	len = len * ETHER_ADDR_LEN;
349	error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
350	if (error) {
351		device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
352		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
353		sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
354	}
355
356out:
357	free(mclist, M_TEMP);
358
359	len = sizeof(sc->ndis_filter);
360	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
361	    &sc->ndis_filter, &len);
362	if (error)
363		device_printf(sc->ndis_dev, "set multi failed: %d\n", error);
364}
365
366static int
367ndis_set_offload(sc)
368	struct ndis_softc	*sc;
369{
370	ndis_task_offload	*nto;
371	ndis_task_offload_hdr	*ntoh;
372	ndis_task_tcpip_csum	*nttc;
373	struct ifnet		*ifp;
374	int			len, error;
375
376	if (!NDIS_INITIALIZED(sc))
377		return (EINVAL);
378
379	if (sc->ndis_80211)
380		return (EINVAL);
381	/* See if there's anything to set. */
382
383	ifp = sc->ifp;
384	error = ndis_probe_offload(sc);
385	if (error)
386		return (error);
387
388	if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
389		return (0);
390
391	len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
392	    sizeof(ndis_task_tcpip_csum);
393
394	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
395
396	if (ntoh == NULL)
397		return (ENOMEM);
398
399	ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
400	ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
401	ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
402	ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
403	ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
404	ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
405
406	nto = (ndis_task_offload *)((char *)ntoh +
407	    ntoh->ntoh_offset_firsttask);
408
409	nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
410	nto->nto_len = sizeof(ndis_task_offload);
411	nto->nto_task = NDIS_TASK_TCPIP_CSUM;
412	nto->nto_offset_nexttask = 0;
413	nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
414
415	nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
416
417	if (ifp->if_capenable & IFCAP_TXCSUM)
418		nttc->nttc_v4tx = sc->ndis_v4tx;
419
420	if (ifp->if_capenable & IFCAP_RXCSUM)
421		nttc->nttc_v4rx = sc->ndis_v4rx;
422
423	error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
424	free(ntoh, M_TEMP);
425
426	return (error);
427}
428
429static int
430ndis_probe_offload(sc)
431	struct ndis_softc	*sc;
432{
433	ndis_task_offload	*nto;
434	ndis_task_offload_hdr	*ntoh;
435	ndis_task_tcpip_csum	*nttc = NULL;
436	struct ifnet		*ifp;
437	int			len, error, dummy;
438
439	ifp = sc->ifp;
440
441	len = sizeof(dummy);
442	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
443
444	if (error != ENOSPC)
445		return (error);
446
447	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
448
449	if (ntoh == NULL)
450		return (ENOMEM);
451
452	ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
453	ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
454	ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
455	ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
456	ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
457
458	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
459
460	if (error) {
461		free(ntoh, M_TEMP);
462		return (error);
463	}
464
465	if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
466		free(ntoh, M_TEMP);
467		return (EINVAL);
468	}
469
470	nto = (ndis_task_offload *)((char *)ntoh +
471	    ntoh->ntoh_offset_firsttask);
472
473	while (1) {
474		switch (nto->nto_task) {
475		case NDIS_TASK_TCPIP_CSUM:
476			nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
477			break;
478		/* Don't handle these yet. */
479		case NDIS_TASK_IPSEC:
480		case NDIS_TASK_TCP_LARGESEND:
481		default:
482			break;
483		}
484		if (nto->nto_offset_nexttask == 0)
485			break;
486		nto = (ndis_task_offload *)((char *)nto +
487		    nto->nto_offset_nexttask);
488	}
489
490	if (nttc == NULL) {
491		free(ntoh, M_TEMP);
492		return (ENOENT);
493	}
494
495	sc->ndis_v4tx = nttc->nttc_v4tx;
496	sc->ndis_v4rx = nttc->nttc_v4rx;
497
498	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
499		sc->ndis_hwassist |= CSUM_IP;
500	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
501		sc->ndis_hwassist |= CSUM_TCP;
502	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
503		sc->ndis_hwassist |= CSUM_UDP;
504
505	if (sc->ndis_hwassist)
506		ifp->if_capabilities |= IFCAP_TXCSUM;
507
508	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
509		ifp->if_capabilities |= IFCAP_RXCSUM;
510	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
511		ifp->if_capabilities |= IFCAP_RXCSUM;
512	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
513		ifp->if_capabilities |= IFCAP_RXCSUM;
514
515	free(ntoh, M_TEMP);
516	return (0);
517}
518
519static int
520ndis_nettype_chan(uint32_t type)
521{
522	switch (type) {
523	case NDIS_80211_NETTYPE_11FH:		return (IEEE80211_CHAN_FHSS);
524	case NDIS_80211_NETTYPE_11DS:		return (IEEE80211_CHAN_B);
525	case NDIS_80211_NETTYPE_11OFDM5:	return (IEEE80211_CHAN_A);
526	case NDIS_80211_NETTYPE_11OFDM24:	return (IEEE80211_CHAN_G);
527	}
528	DPRINTF(("unknown channel nettype %d\n", type));
529	return (IEEE80211_CHAN_B);	/* Default to 11B chan */
530}
531
532static int
533ndis_nettype_mode(uint32_t type)
534{
535	switch (type) {
536	case NDIS_80211_NETTYPE_11FH:		return (IEEE80211_MODE_FH);
537	case NDIS_80211_NETTYPE_11DS:		return (IEEE80211_MODE_11B);
538	case NDIS_80211_NETTYPE_11OFDM5:	return (IEEE80211_MODE_11A);
539	case NDIS_80211_NETTYPE_11OFDM24:	return (IEEE80211_MODE_11G);
540	}
541	DPRINTF(("unknown mode nettype %d\n", type));
542	return (IEEE80211_MODE_AUTO);
543}
544
545/*
546 * Attach the interface. Allocate softc structures, do ifmedia
547 * setup and ethernet/BPF attach.
548 */
549int
550ndis_attach(device_t dev)
551{
552	struct ndis_softc	*sc;
553	driver_object		*pdrv;
554	device_object		*pdo;
555	int			error = 0, len;
556	int			i;
557
558	sc = device_get_softc(dev);
559
560	mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
561	    MTX_DEF);
562	KeInitializeSpinLock(&sc->ndis_rxlock);
563	KeInitializeSpinLock(&sc->ndisusb_tasklock);
564	KeInitializeSpinLock(&sc->ndisusb_xferdonelock);
565	InitializeListHead(&sc->ndis_shlist);
566	InitializeListHead(&sc->ndisusb_tasklist);
567	InitializeListHead(&sc->ndisusb_xferdonelist);
568	callout_init(&sc->ndis_stat_callout, 1);
569	mbufq_init(&sc->ndis_rxqueue, INT_MAX);	/* XXXGL: sane maximum */
570
571	if (sc->ndis_iftype == PCMCIABus) {
572		error = ndis_alloc_amem(sc);
573		if (error) {
574			device_printf(dev, "failed to allocate "
575			    "attribute memory\n");
576			goto fail;
577		}
578	}
579
580	/* Create sysctl registry nodes */
581	ndis_create_sysctls(sc);
582
583	/* Find the PDO for this device instance. */
584
585	if (sc->ndis_iftype == PCIBus)
586		pdrv = windrv_lookup(0, "PCI Bus");
587	else if (sc->ndis_iftype == PCMCIABus)
588		pdrv = windrv_lookup(0, "PCCARD Bus");
589	else
590		pdrv = windrv_lookup(0, "USB Bus");
591	pdo = windrv_find_pdo(pdrv, dev);
592
593	/*
594	 * Create a new functional device object for this
595	 * device. This is what creates the miniport block
596	 * for this device instance.
597	 */
598
599	if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) {
600		device_printf(dev, "failed to create FDO!\n");
601		error = ENXIO;
602		goto fail;
603	}
604
605	/* Tell the user what version of the API the driver is using. */
606	device_printf(dev, "NDIS API version: %d.%d\n",
607	    sc->ndis_chars->nmc_version_major,
608	    sc->ndis_chars->nmc_version_minor);
609
610	/* Do resource conversion. */
611	if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus)
612		ndis_convert_res(sc);
613	else
614		sc->ndis_block->nmb_rlist = NULL;
615
616	/* Install our RX and TX interrupt handlers. */
617	sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
618	sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
619	sc->ndis_block->nmb_ethrxindicate_func = ndis_rxeof_eth_wrap;
620	sc->ndis_block->nmb_ethrxdone_func = ndis_rxeof_done_wrap;
621	sc->ndis_block->nmb_tdcond_func = ndis_rxeof_xfr_done_wrap;
622
623	/* Override the status handler so we can detect link changes. */
624	sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
625	sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
626
627	/* Set up work item handlers. */
628	sc->ndis_tickitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
629	sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
630	sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
631	sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
632	sc->ndisusb_xferdoneitem =
633	    IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
634	sc->ndisusb_taskitem =
635	    IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj);
636	KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block);
637
638	/* Call driver's init routine. */
639	if (ndis_init_nic(sc)) {
640		device_printf(dev, "init handler failed\n");
641		error = ENXIO;
642		goto fail;
643	}
644
645	/*
646	 * Figure out how big to make the TX buffer pool.
647	 */
648	len = sizeof(sc->ndis_maxpkts);
649	if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
650		    &sc->ndis_maxpkts, &len)) {
651		device_printf(dev, "failed to get max TX packets\n");
652		error = ENXIO;
653		goto fail;
654	}
655
656	/*
657	 * If this is a deserialized miniport, we don't have
658	 * to honor the OID_GEN_MAXIMUM_SEND_PACKETS result.
659	 */
660	if (!NDIS_SERIALIZED(sc->ndis_block))
661		sc->ndis_maxpkts = NDIS_TXPKTS;
662
663	/* Enforce some sanity, just in case. */
664
665	if (sc->ndis_maxpkts == 0)
666		sc->ndis_maxpkts = 10;
667
668	sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
669	    sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
670
671	/* Allocate a pool of ndis_packets for TX encapsulation. */
672
673	NdisAllocatePacketPool(&i, &sc->ndis_txpool,
674	    sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
675
676	if (i != NDIS_STATUS_SUCCESS) {
677		sc->ndis_txpool = NULL;
678		device_printf(dev, "failed to allocate TX packet pool");
679		error = ENOMEM;
680		goto fail;
681	}
682
683	sc->ndis_txpending = sc->ndis_maxpkts;
684
685	sc->ndis_oidcnt = 0;
686	/* Get supported oid list. */
687	ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
688
689	/* If the NDIS module requested scatter/gather, init maps. */
690	if (sc->ndis_sc)
691		ndis_init_dma(sc);
692
693	/*
694	 * See if the OID_802_11_CONFIGURATION OID is
695	 * supported by this driver. If it is, then this an 802.11
696	 * wireless driver, and we should set up media for wireless.
697	 */
698	for (i = 0; i < sc->ndis_oidcnt; i++)
699		if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
700			sc->ndis_80211 = 1;
701			break;
702		}
703
704	if (sc->ndis_80211)
705		error = ndis_80211attach(sc);
706	else
707		error = ndis_ifattach(sc);
708
709fail:
710	if (error) {
711		ndis_detach(dev);
712		return (error);
713	}
714
715	if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
716		return (error);
717
718	DPRINTF(("attach done.\n"));
719	/* We're done talking to the NIC for now; halt it. */
720	ndis_halt_nic(sc);
721	DPRINTF(("halting done.\n"));
722
723	return (error);
724}
725
726static int
727ndis_80211attach(struct ndis_softc *sc)
728{
729	struct ieee80211com	*ic = &sc->ndis_ic;
730	ndis_80211_rates_ex	rates;
731	struct ndis_80211_nettype_list *ntl;
732	uint32_t		arg;
733	int			mode, i, r, len, nonettypes = 1;
734	uint8_t			bands[IEEE80211_MODE_BYTES] = { 0 };
735
736	callout_init(&sc->ndis_scan_callout, 1);
737
738	ic->ic_softc = sc;
739	ic->ic_ioctl = ndis_80211ioctl;
740	ic->ic_name = device_get_nameunit(sc->ndis_dev);
741	ic->ic_opmode = IEEE80211_M_STA;
742        ic->ic_phytype = IEEE80211_T_DS;
743	ic->ic_caps = IEEE80211_C_8023ENCAP |
744		IEEE80211_C_STA | IEEE80211_C_IBSS;
745	setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
746	len = 0;
747	r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
748	if (r != ENOSPC)
749		goto nonettypes;
750	ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
751	r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
752	if (r != 0) {
753		free(ntl, M_DEVBUF);
754		goto nonettypes;
755	}
756
757	for (i = 0; i < ntl->ntl_items; i++) {
758		mode = ndis_nettype_mode(ntl->ntl_type[i]);
759		if (mode) {
760			nonettypes = 0;
761			setbit(ic->ic_modecaps, mode);
762			setbit(bands, mode);
763		} else
764			device_printf(sc->ndis_dev, "Unknown nettype %d\n",
765			    ntl->ntl_type[i]);
766	}
767	free(ntl, M_DEVBUF);
768nonettypes:
769	/* Default to 11b channels if the card did not supply any */
770	if (nonettypes) {
771		setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
772		setbit(bands, IEEE80211_MODE_11B);
773	}
774	len = sizeof(rates);
775	bzero((char *)&rates, len);
776	r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
777	if (r != 0)
778		device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
779	/*
780	 * Since the supported rates only up to 8 can be supported,
781	 * if this is not 802.11b we're just going to be faking it
782	 * all up to heck.
783	 */
784
785#define TESTSETRATE(x, y)						\
786	do {								\
787		int			i;				\
788		for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) {	\
789			if (ic->ic_sup_rates[x].rs_rates[i] == (y))	\
790				break;					\
791		}							\
792		if (i == ic->ic_sup_rates[x].rs_nrates) {		\
793			ic->ic_sup_rates[x].rs_rates[i] = (y);		\
794			ic->ic_sup_rates[x].rs_nrates++;		\
795		}							\
796	} while (0)
797
798#define SETRATE(x, y)	\
799	ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
800#define INCRATE(x)	\
801	ic->ic_sup_rates[x].rs_nrates++
802
803	ic->ic_curmode = IEEE80211_MODE_AUTO;
804	if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
805		ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
806	if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
807		ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
808	if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
809		ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
810	for (i = 0; i < len; i++) {
811		switch (rates[i] & IEEE80211_RATE_VAL) {
812		case 2:
813		case 4:
814		case 11:
815		case 10:
816		case 22:
817			if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
818				/* Lazy-init 802.11b. */
819				setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
820				ic->ic_sup_rates[IEEE80211_MODE_11B].
821				    rs_nrates = 0;
822			}
823			SETRATE(IEEE80211_MODE_11B, rates[i]);
824			INCRATE(IEEE80211_MODE_11B);
825			break;
826		default:
827			if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
828				SETRATE(IEEE80211_MODE_11A, rates[i]);
829				INCRATE(IEEE80211_MODE_11A);
830			}
831			if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
832				SETRATE(IEEE80211_MODE_11G, rates[i]);
833				INCRATE(IEEE80211_MODE_11G);
834			}
835			break;
836		}
837	}
838
839	/*
840	 * If the hardware supports 802.11g, it most
841	 * likely supports 802.11b and all of the
842	 * 802.11b and 802.11g speeds, so maybe we can
843	 * just cheat here.  Just how in the heck do
844	 * we detect turbo modes, though?
845	 */
846	if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
847		TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
848		TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
849		TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
850		TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
851	}
852	if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
853		TESTSETRATE(IEEE80211_MODE_11G, 48);
854		TESTSETRATE(IEEE80211_MODE_11G, 72);
855		TESTSETRATE(IEEE80211_MODE_11G, 96);
856		TESTSETRATE(IEEE80211_MODE_11G, 108);
857	}
858	if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
859		TESTSETRATE(IEEE80211_MODE_11A, 48);
860		TESTSETRATE(IEEE80211_MODE_11A, 72);
861		TESTSETRATE(IEEE80211_MODE_11A, 96);
862		TESTSETRATE(IEEE80211_MODE_11A, 108);
863	}
864
865#undef SETRATE
866#undef INCRATE
867#undef TESTSETRATE
868
869	ieee80211_init_channels(ic, NULL, bands);
870
871	/*
872	 * To test for WPA support, we need to see if we can
873	 * set AUTHENTICATION_MODE to WPA and read it back
874	 * successfully.
875	 */
876	i = sizeof(arg);
877	arg = NDIS_80211_AUTHMODE_WPA;
878	r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
879	if (r == 0) {
880		r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
881		if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
882			ic->ic_caps |= IEEE80211_C_WPA;
883	}
884
885	/*
886	 * To test for supported ciphers, we set each
887	 * available encryption type in descending order.
888	 * If ENC3 works, then we have WEP, TKIP and AES.
889	 * If only ENC2 works, then we have WEP and TKIP.
890	 * If only ENC1 works, then we have just WEP.
891	 */
892	i = sizeof(arg);
893	arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
894	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
895	if (r == 0) {
896		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
897				  |  IEEE80211_CRYPTO_TKIP
898				  |  IEEE80211_CRYPTO_AES_CCM;
899		goto got_crypto;
900	}
901	arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
902	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
903	if (r == 0) {
904		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
905				  |  IEEE80211_CRYPTO_TKIP;
906		goto got_crypto;
907	}
908	arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
909	r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
910	if (r == 0)
911		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
912got_crypto:
913	i = sizeof(arg);
914	r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
915	if (r == 0)
916		ic->ic_caps |= IEEE80211_C_PMGT;
917
918	r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
919	if (r == 0)
920		ic->ic_caps |= IEEE80211_C_TXPMGT;
921
922	/*
923	 * Get station address from the driver.
924	 */
925	len = sizeof(ic->ic_macaddr);
926	ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
927
928	ieee80211_ifattach(ic);
929	ic->ic_raw_xmit = ndis_raw_xmit;
930	ic->ic_scan_start = ndis_scan_start;
931	ic->ic_scan_end = ndis_scan_end;
932	ic->ic_set_channel = ndis_set_channel;
933	ic->ic_scan_curchan = ndis_scan_curchan;
934	ic->ic_scan_mindwell = ndis_scan_mindwell;
935	ic->ic_bsschan = IEEE80211_CHAN_ANYC;
936	ic->ic_vap_create = ndis_vap_create;
937	ic->ic_vap_delete = ndis_vap_delete;
938	ic->ic_update_mcast = ndis_update_mcast;
939	ic->ic_update_promisc = ndis_update_promisc;
940	ic->ic_transmit = ndis_80211transmit;
941	ic->ic_parent = ndis_80211parent;
942
943	if (bootverbose)
944		ieee80211_announce(ic);
945
946	return (0);
947}
948
949static int
950ndis_ifattach(struct ndis_softc *sc)
951{
952	struct ifnet *ifp;
953	u_char eaddr[ETHER_ADDR_LEN];
954	int len;
955
956	ifp = if_alloc(IFT_ETHER);
957	if (ifp == NULL)
958		return (ENOSPC);
959	sc->ifp = ifp;
960	ifp->if_softc = sc;
961
962	/* Check for task offload support. */
963	ndis_probe_offload(sc);
964
965	/*
966	 * Get station address from the driver.
967	 */
968	len = sizeof(eaddr);
969	ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
970
971	if_initname(ifp, device_get_name(sc->ndis_dev),
972	    device_get_unit(sc->ndis_dev));
973	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
974	ifp->if_ioctl = ndis_ifioctl;
975	ifp->if_start = ndis_ifstart;
976	ifp->if_init = ndis_init;
977	ifp->if_baudrate = 10000000;
978	IFQ_SET_MAXLEN(&ifp->if_snd, 50);
979	ifp->if_snd.ifq_drv_maxlen = 25;
980	IFQ_SET_READY(&ifp->if_snd);
981	ifp->if_capenable = ifp->if_capabilities;
982	ifp->if_hwassist = sc->ndis_hwassist;
983
984	ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
985	    ndis_ifmedia_sts);
986	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
987	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
988	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
989	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
990	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
991	ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
992	ether_ifattach(ifp, eaddr);
993
994	return (0);
995}
996
997static struct ieee80211vap *
998ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
999    enum ieee80211_opmode opmode, int flags,
1000    const uint8_t bssid[IEEE80211_ADDR_LEN],
1001    const uint8_t mac[IEEE80211_ADDR_LEN])
1002{
1003	struct ndis_vap *nvp;
1004	struct ieee80211vap *vap;
1005
1006	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
1007		return NULL;
1008	nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
1009	vap = &nvp->vap;
1010	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
1011	/* override with driver methods */
1012	nvp->newstate = vap->iv_newstate;
1013	vap->iv_newstate = ndis_newstate;
1014
1015	/* complete setup */
1016	ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
1017	    mac);
1018	ic->ic_opmode = opmode;
1019	/* install key handing routines */
1020	vap->iv_key_set = ndis_add_key;
1021	vap->iv_key_delete = ndis_del_key;
1022	return vap;
1023}
1024
1025static void
1026ndis_vap_delete(struct ieee80211vap *vap)
1027{
1028	struct ndis_vap *nvp = NDIS_VAP(vap);
1029	struct ieee80211com *ic = vap->iv_ic;
1030	struct ndis_softc *sc = ic->ic_softc;
1031
1032	ndis_stop(sc);
1033	callout_drain(&sc->ndis_scan_callout);
1034	ieee80211_vap_detach(vap);
1035	free(nvp, M_80211_VAP);
1036}
1037
1038/*
1039 * Shutdown hardware and free up resources. This can be called any
1040 * time after the mutex has been initialized. It is called in both
1041 * the error case in attach and the normal detach case so it needs
1042 * to be careful about only freeing resources that have actually been
1043 * allocated.
1044 */
1045int
1046ndis_detach(device_t dev)
1047{
1048	struct ifnet		*ifp;
1049	struct ndis_softc	*sc;
1050	driver_object		*drv;
1051
1052	sc = device_get_softc(dev);
1053	NDIS_LOCK(sc);
1054	if (!sc->ndis_80211)
1055		ifp = sc->ifp;
1056	else
1057		ifp = NULL;
1058	if (ifp != NULL)
1059		ifp->if_flags &= ~IFF_UP;
1060	if (device_is_attached(dev)) {
1061		NDIS_UNLOCK(sc);
1062		ndis_stop(sc);
1063		if (sc->ndis_80211)
1064			ieee80211_ifdetach(&sc->ndis_ic);
1065		else if (ifp != NULL)
1066			ether_ifdetach(ifp);
1067	} else
1068		NDIS_UNLOCK(sc);
1069
1070	if (sc->ndis_tickitem != NULL)
1071		IoFreeWorkItem(sc->ndis_tickitem);
1072	if (sc->ndis_startitem != NULL)
1073		IoFreeWorkItem(sc->ndis_startitem);
1074	if (sc->ndis_resetitem != NULL)
1075		IoFreeWorkItem(sc->ndis_resetitem);
1076	if (sc->ndis_inputitem != NULL)
1077		IoFreeWorkItem(sc->ndis_inputitem);
1078	if (sc->ndisusb_xferdoneitem != NULL)
1079		IoFreeWorkItem(sc->ndisusb_xferdoneitem);
1080	if (sc->ndisusb_taskitem != NULL)
1081		IoFreeWorkItem(sc->ndisusb_taskitem);
1082
1083	bus_generic_detach(dev);
1084	ndis_unload_driver(sc);
1085
1086	if (sc->ndis_irq)
1087		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
1088	if (sc->ndis_res_io)
1089		bus_release_resource(dev, SYS_RES_IOPORT,
1090		    sc->ndis_io_rid, sc->ndis_res_io);
1091	if (sc->ndis_res_mem)
1092		bus_release_resource(dev, SYS_RES_MEMORY,
1093		    sc->ndis_mem_rid, sc->ndis_res_mem);
1094	if (sc->ndis_res_altmem)
1095		bus_release_resource(dev, SYS_RES_MEMORY,
1096		    sc->ndis_altmem_rid, sc->ndis_res_altmem);
1097
1098	if (ifp != NULL)
1099		if_free(ifp);
1100
1101	if (sc->ndis_iftype == PCMCIABus)
1102		ndis_free_amem(sc);
1103
1104	if (sc->ndis_sc)
1105		ndis_destroy_dma(sc);
1106
1107	if (sc->ndis_txarray)
1108		free(sc->ndis_txarray, M_DEVBUF);
1109
1110	if (!sc->ndis_80211)
1111		ifmedia_removeall(&sc->ifmedia);
1112
1113	if (sc->ndis_txpool != NULL)
1114		NdisFreePacketPool(sc->ndis_txpool);
1115
1116	/* Destroy the PDO for this device. */
1117
1118	if (sc->ndis_iftype == PCIBus)
1119		drv = windrv_lookup(0, "PCI Bus");
1120	else if (sc->ndis_iftype == PCMCIABus)
1121		drv = windrv_lookup(0, "PCCARD Bus");
1122	else
1123		drv = windrv_lookup(0, "USB Bus");
1124	if (drv == NULL)
1125		panic("couldn't find driver object");
1126	windrv_destroy_pdo(drv, dev);
1127
1128	if (sc->ndis_iftype == PCIBus)
1129		bus_dma_tag_destroy(sc->ndis_parent_tag);
1130
1131	return (0);
1132}
1133
1134int
1135ndis_suspend(dev)
1136	device_t		dev;
1137{
1138	struct ndis_softc	*sc;
1139	struct ifnet		*ifp;
1140
1141	sc = device_get_softc(dev);
1142	ifp = sc->ifp;
1143
1144#ifdef notdef
1145	if (NDIS_INITIALIZED(sc))
1146        	ndis_stop(sc);
1147#endif
1148
1149	return (0);
1150}
1151
1152int
1153ndis_resume(dev)
1154	device_t		dev;
1155{
1156	struct ndis_softc	*sc;
1157	struct ifnet		*ifp;
1158
1159	sc = device_get_softc(dev);
1160	ifp = sc->ifp;
1161
1162	if (NDIS_INITIALIZED(sc))
1163        	ndis_init(sc);
1164
1165	return (0);
1166}
1167
1168/*
1169 * The following bunch of routines are here to support drivers that
1170 * use the NdisMEthIndicateReceive()/MiniportTransferData() mechanism.
1171 * The NdisMEthIndicateReceive() handler runs at DISPATCH_LEVEL for
1172 * serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1173 * miniports.
1174 */
1175static void
1176ndis_rxeof_eth(adapter, ctx, addr, hdr, hdrlen, lookahead, lookaheadlen, pktlen)
1177	ndis_handle		adapter;
1178	ndis_handle		ctx;
1179	char			*addr;
1180	void			*hdr;
1181	uint32_t		hdrlen;
1182	void			*lookahead;
1183	uint32_t		lookaheadlen;
1184	uint32_t		pktlen;
1185{
1186	ndis_miniport_block	*block;
1187	uint8_t			irql = 0;
1188	uint32_t		status;
1189	ndis_buffer		*b;
1190	ndis_packet		*p;
1191	struct mbuf		*m;
1192	ndis_ethpriv		*priv;
1193
1194	block = adapter;
1195
1196	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1197	if (m == NULL)
1198		return;
1199
1200	/* Save the data provided to us so far. */
1201
1202	m->m_len = lookaheadlen + hdrlen;
1203	m->m_pkthdr.len = pktlen + hdrlen;
1204	m->m_next = NULL;
1205	m_copyback(m, 0, hdrlen, hdr);
1206	m_copyback(m, hdrlen, lookaheadlen, lookahead);
1207
1208	/* Now create a fake NDIS_PACKET to hold the data */
1209
1210	NdisAllocatePacket(&status, &p, block->nmb_rxpool);
1211
1212	if (status != NDIS_STATUS_SUCCESS) {
1213		m_freem(m);
1214		return;
1215	}
1216
1217	p->np_m0 = m;
1218
1219	b = IoAllocateMdl(m->m_data, m->m_pkthdr.len, FALSE, FALSE, NULL);
1220
1221	if (b == NULL) {
1222		NdisFreePacket(p);
1223		m_freem(m);
1224		return;
1225	}
1226
1227	p->np_private.npp_head = p->np_private.npp_tail = b;
1228	p->np_private.npp_totlen = m->m_pkthdr.len;
1229
1230	/* Save the packet RX context somewhere. */
1231	priv = (ndis_ethpriv *)&p->np_protocolreserved;
1232	priv->nep_ctx = ctx;
1233
1234	if (!NDIS_SERIALIZED(block))
1235		KeAcquireSpinLock(&block->nmb_lock, &irql);
1236
1237	InsertTailList((&block->nmb_packetlist), (&p->np_list));
1238
1239	if (!NDIS_SERIALIZED(block))
1240		KeReleaseSpinLock(&block->nmb_lock, irql);
1241}
1242
1243/*
1244 * NdisMEthIndicateReceiveComplete() handler, runs at DISPATCH_LEVEL
1245 * for serialized miniports, or IRQL <= DISPATCH_LEVEL for deserialized
1246 * miniports.
1247 */
1248static void
1249ndis_rxeof_done(adapter)
1250	ndis_handle		adapter;
1251{
1252	struct ndis_softc	*sc;
1253	ndis_miniport_block	*block;
1254
1255	block = adapter;
1256
1257	/* Schedule transfer/RX of queued packets. */
1258
1259	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1260
1261	KeInsertQueueDpc(&sc->ndis_rxdpc, NULL, NULL);
1262}
1263
1264/*
1265 * MiniportTransferData() handler, runs at DISPATCH_LEVEL.
1266 */
1267static void
1268ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
1269	kdpc			*dpc;
1270	ndis_handle		adapter;
1271	void			*sysarg1;
1272	void			*sysarg2;
1273{
1274	ndis_miniport_block	*block;
1275	struct ndis_softc	*sc;
1276	ndis_packet		*p;
1277	list_entry		*l;
1278	uint32_t		status;
1279	ndis_ethpriv		*priv;
1280	struct ifnet		*ifp;
1281	struct mbuf		*m;
1282
1283	block = adapter;
1284	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1285	ifp = sc->ifp;
1286
1287	KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1288
1289	l = block->nmb_packetlist.nle_flink;
1290	while(!IsListEmpty(&block->nmb_packetlist)) {
1291		l = RemoveHeadList((&block->nmb_packetlist));
1292		p = CONTAINING_RECORD(l, ndis_packet, np_list);
1293		InitializeListHead((&p->np_list));
1294
1295		priv = (ndis_ethpriv *)&p->np_protocolreserved;
1296		m = p->np_m0;
1297		p->np_softc = sc;
1298		p->np_m0 = NULL;
1299
1300		KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1301
1302		status = MSCALL6(sc->ndis_chars->nmc_transferdata_func,
1303		    p, &p->np_private.npp_totlen, block, priv->nep_ctx,
1304		    m->m_len, m->m_pkthdr.len - m->m_len);
1305
1306		KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
1307
1308		/*
1309		 * If status is NDIS_STATUS_PENDING, do nothing and
1310		 * wait for a callback to the ndis_rxeof_xfr_done()
1311		 * handler.
1312	 	 */
1313
1314		m->m_len = m->m_pkthdr.len;
1315		m->m_pkthdr.rcvif = ifp;
1316
1317		if (status == NDIS_STATUS_SUCCESS) {
1318			IoFreeMdl(p->np_private.npp_head);
1319			NdisFreePacket(p);
1320			KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1321			mbufq_enqueue(&sc->ndis_rxqueue, m);
1322			KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1323			IoQueueWorkItem(sc->ndis_inputitem,
1324			    (io_workitem_func)ndis_inputtask_wrap,
1325			    WORKQUEUE_CRITICAL, sc);
1326		}
1327
1328		if (status == NDIS_STATUS_FAILURE)
1329			m_freem(m);
1330
1331		/* Advance to next packet */
1332		l = block->nmb_packetlist.nle_flink;
1333	}
1334
1335	KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
1336}
1337
1338/*
1339 * NdisMTransferDataComplete() handler, runs at DISPATCH_LEVEL.
1340 */
1341static void
1342ndis_rxeof_xfr_done(adapter, packet, status, len)
1343	ndis_handle		adapter;
1344	ndis_packet		*packet;
1345	uint32_t		status;
1346	uint32_t		len;
1347{
1348	ndis_miniport_block	*block;
1349	struct ndis_softc	*sc;
1350	struct ifnet		*ifp;
1351	struct mbuf		*m;
1352
1353	block = adapter;
1354	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1355	ifp = sc->ifp;
1356
1357	m = packet->np_m0;
1358	IoFreeMdl(packet->np_private.npp_head);
1359	NdisFreePacket(packet);
1360
1361	if (status != NDIS_STATUS_SUCCESS) {
1362		m_freem(m);
1363		return;
1364	}
1365
1366	m->m_len = m->m_pkthdr.len;
1367	m->m_pkthdr.rcvif = ifp;
1368	KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1369	mbufq_enqueue(&sc->ndis_rxqueue, m);
1370	KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1371	IoQueueWorkItem(sc->ndis_inputitem,
1372	    (io_workitem_func)ndis_inputtask_wrap,
1373	    WORKQUEUE_CRITICAL, sc);
1374}
1375/*
1376 * A frame has been uploaded: pass the resulting mbuf chain up to
1377 * the higher level protocols.
1378 *
1379 * When handling received NDIS packets, the 'status' field in the
1380 * out-of-band portion of the ndis_packet has special meaning. In the
1381 * most common case, the underlying NDIS driver will set this field
1382 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
1383 * take possession of it. We then change the status field to
1384 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
1385 * and that we will return it at some point in the future via the
1386 * return packet handler.
1387 *
1388 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
1389 * this means the driver is running out of packet/buffer resources and
1390 * wants to maintain ownership of the packet. In this case, we have to
1391 * copy the packet data into local storage and let the driver keep the
1392 * packet.
1393 */
1394static void
1395ndis_rxeof(adapter, packets, pktcnt)
1396	ndis_handle		adapter;
1397	ndis_packet		**packets;
1398	uint32_t		pktcnt;
1399{
1400	struct ndis_softc	*sc;
1401	ndis_miniport_block	*block;
1402	ndis_packet		*p;
1403	uint32_t		s;
1404	ndis_tcpip_csum		*csum;
1405	struct ifnet		*ifp;
1406	struct mbuf		*m0, *m;
1407	int			i;
1408
1409	block = (ndis_miniport_block *)adapter;
1410	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1411	ifp = sc->ifp;
1412
1413	/*
1414	 * There's a slim chance the driver may indicate some packets
1415	 * before we're completely ready to handle them. If we detect this,
1416	 * we need to return them to the miniport and ignore them.
1417	 */
1418        if (!sc->ndis_running) {
1419		for (i = 0; i < pktcnt; i++) {
1420			p = packets[i];
1421			if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
1422				p->np_refcnt++;
1423				(void)ndis_return_packet(NULL ,p, block);
1424			}
1425		}
1426		return;
1427        }
1428
1429	for (i = 0; i < pktcnt; i++) {
1430		p = packets[i];
1431		/* Stash the softc here so ptom can use it. */
1432		p->np_softc = sc;
1433		if (ndis_ptom(&m0, p)) {
1434			device_printf(sc->ndis_dev, "ptom failed\n");
1435			if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
1436				(void)ndis_return_packet(NULL, p, block);
1437		} else {
1438#ifdef notdef
1439			if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
1440				m = m_dup(m0, M_NOWAIT);
1441				/*
1442				 * NOTE: we want to destroy the mbuf here, but
1443				 * we don't actually want to return it to the
1444				 * driver via the return packet handler. By
1445				 * bumping np_refcnt, we can prevent the
1446				 * ndis_return_packet() routine from actually
1447				 * doing anything.
1448				 */
1449				p->np_refcnt++;
1450				m_freem(m0);
1451				if (m == NULL)
1452					if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1453				else
1454					m0 = m;
1455			} else
1456				p->np_oob.npo_status = NDIS_STATUS_PENDING;
1457#endif
1458			m = m_dup(m0, M_NOWAIT);
1459			if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES)
1460				p->np_refcnt++;
1461			else
1462				p->np_oob.npo_status = NDIS_STATUS_PENDING;
1463			m_freem(m0);
1464			if (m == NULL) {
1465				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1466				continue;
1467			}
1468			m0 = m;
1469			m0->m_pkthdr.rcvif = ifp;
1470
1471			/* Deal with checksum offload. */
1472
1473			if (ifp->if_capenable & IFCAP_RXCSUM &&
1474			    p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
1475				s = (uintptr_t)
1476			 	    p->np_ext.npe_info[ndis_tcpipcsum_info];
1477				csum = (ndis_tcpip_csum *)&s;
1478				if (csum->u.ntc_rxflags &
1479				    NDIS_RXCSUM_IP_PASSED)
1480					m0->m_pkthdr.csum_flags |=
1481					    CSUM_IP_CHECKED|CSUM_IP_VALID;
1482				if (csum->u.ntc_rxflags &
1483				    (NDIS_RXCSUM_TCP_PASSED |
1484				    NDIS_RXCSUM_UDP_PASSED)) {
1485					m0->m_pkthdr.csum_flags |=
1486					    CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
1487					m0->m_pkthdr.csum_data = 0xFFFF;
1488				}
1489			}
1490
1491			KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
1492			mbufq_enqueue(&sc->ndis_rxqueue, m0);
1493			KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
1494			IoQueueWorkItem(sc->ndis_inputitem,
1495			    (io_workitem_func)ndis_inputtask_wrap,
1496			    WORKQUEUE_CRITICAL, sc);
1497		}
1498	}
1499}
1500
1501/*
1502 * This routine is run at PASSIVE_LEVEL. We use this routine to pass
1503 * packets into the stack in order to avoid calling (*ifp->if_input)()
1504 * with any locks held (at DISPATCH_LEVEL, we'll be holding the
1505 * 'dispatch level' per-cpu sleep lock).
1506 */
1507static void
1508ndis_inputtask(device_object *dobj, void *arg)
1509{
1510	ndis_miniport_block	*block;
1511	struct ndis_softc	*sc = arg;
1512	struct mbuf		*m;
1513	uint8_t			irql;
1514
1515	block = dobj->do_devext;
1516
1517	KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1518	while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
1519		KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1520		if ((sc->ndis_80211 != 0)) {
1521			struct ieee80211com *ic = &sc->ndis_ic;
1522			struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1523
1524			if (vap != NULL)
1525				vap->iv_deliver_data(vap, vap->iv_bss, m);
1526		} else {
1527			struct ifnet *ifp = sc->ifp;
1528
1529			(*ifp->if_input)(ifp, m);
1530		}
1531		KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
1532	}
1533	KeReleaseSpinLock(&sc->ndis_rxlock, irql);
1534}
1535
1536/*
1537 * A frame was downloaded to the chip. It's safe for us to clean up
1538 * the list buffers.
1539 */
1540static void
1541ndis_txeof(adapter, packet, status)
1542	ndis_handle		adapter;
1543	ndis_packet		*packet;
1544	ndis_status		status;
1545
1546{
1547	struct ndis_softc	*sc;
1548	ndis_miniport_block	*block;
1549	struct ifnet		*ifp;
1550	int			idx;
1551	struct mbuf		*m;
1552
1553	block = (ndis_miniport_block *)adapter;
1554	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1555	ifp = sc->ifp;
1556
1557	m = packet->np_m0;
1558	idx = packet->np_txidx;
1559	if (sc->ndis_sc)
1560		bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
1561
1562	ndis_free_packet(packet);
1563	m_freem(m);
1564
1565	NDIS_LOCK(sc);
1566	sc->ndis_txarray[idx] = NULL;
1567	sc->ndis_txpending++;
1568
1569	if (!sc->ndis_80211) {
1570		struct ifnet		*ifp = sc->ifp;
1571		if (status == NDIS_STATUS_SUCCESS)
1572			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1573		else
1574			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1575		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1576	}
1577	sc->ndis_tx_timer = 0;
1578
1579	NDIS_UNLOCK(sc);
1580
1581	if (!sc->ndis_80211)
1582		IoQueueWorkItem(sc->ndis_startitem,
1583		    (io_workitem_func)ndis_ifstarttask_wrap,
1584		    WORKQUEUE_CRITICAL, sc);
1585	DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
1586}
1587
1588static void
1589ndis_linksts(adapter, status, sbuf, slen)
1590	ndis_handle		adapter;
1591	ndis_status		status;
1592	void			*sbuf;
1593	uint32_t		slen;
1594{
1595	ndis_miniport_block	*block;
1596	struct ndis_softc	*sc;
1597
1598	block = adapter;
1599	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1600	sc->ndis_sts = status;
1601
1602	/* Event list is all full up, drop this one. */
1603
1604	NDIS_LOCK(sc);
1605	if (sc->ndis_evt[sc->ndis_evtpidx].ne_sts) {
1606		NDIS_UNLOCK(sc);
1607		return;
1608	}
1609
1610	/* Cache the event. */
1611
1612	if (slen) {
1613		sc->ndis_evt[sc->ndis_evtpidx].ne_buf = malloc(slen,
1614		    M_TEMP, M_NOWAIT);
1615		if (sc->ndis_evt[sc->ndis_evtpidx].ne_buf == NULL) {
1616			NDIS_UNLOCK(sc);
1617			return;
1618		}
1619		bcopy((char *)sbuf,
1620		    sc->ndis_evt[sc->ndis_evtpidx].ne_buf, slen);
1621	}
1622	sc->ndis_evt[sc->ndis_evtpidx].ne_sts = status;
1623	sc->ndis_evt[sc->ndis_evtpidx].ne_len = slen;
1624	NDIS_EVTINC(sc->ndis_evtpidx);
1625	NDIS_UNLOCK(sc);
1626}
1627
1628static void
1629ndis_linksts_done(adapter)
1630	ndis_handle		adapter;
1631{
1632	ndis_miniport_block	*block;
1633	struct ndis_softc	*sc;
1634	struct ifnet		*ifp;
1635
1636	block = adapter;
1637	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1638	ifp = sc->ifp;
1639
1640	if (!NDIS_INITIALIZED(sc))
1641		return;
1642
1643	switch (sc->ndis_sts) {
1644	case NDIS_STATUS_MEDIA_CONNECT:
1645		IoQueueWorkItem(sc->ndis_tickitem,
1646		    (io_workitem_func)ndis_ticktask_wrap,
1647		    WORKQUEUE_CRITICAL, sc);
1648		if (!sc->ndis_80211)
1649			IoQueueWorkItem(sc->ndis_startitem,
1650			    (io_workitem_func)ndis_ifstarttask_wrap,
1651			    WORKQUEUE_CRITICAL, sc);
1652		break;
1653	case NDIS_STATUS_MEDIA_DISCONNECT:
1654		if (sc->ndis_link)
1655			IoQueueWorkItem(sc->ndis_tickitem,
1656		    	    (io_workitem_func)ndis_ticktask_wrap,
1657			    WORKQUEUE_CRITICAL, sc);
1658		break;
1659	default:
1660		break;
1661	}
1662}
1663
1664static void
1665ndis_tick(xsc)
1666	void			*xsc;
1667{
1668	struct ndis_softc	*sc;
1669
1670	sc = xsc;
1671
1672	if (sc->ndis_hang_timer && --sc->ndis_hang_timer == 0) {
1673		IoQueueWorkItem(sc->ndis_tickitem,
1674		    (io_workitem_func)ndis_ticktask_wrap,
1675		    WORKQUEUE_CRITICAL, sc);
1676		sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
1677	}
1678
1679	if (sc->ndis_tx_timer && --sc->ndis_tx_timer == 0) {
1680		if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
1681		device_printf(sc->ndis_dev, "watchdog timeout\n");
1682
1683		IoQueueWorkItem(sc->ndis_resetitem,
1684		    (io_workitem_func)ndis_resettask_wrap,
1685		    WORKQUEUE_CRITICAL, sc);
1686		if (!sc->ndis_80211)
1687			IoQueueWorkItem(sc->ndis_startitem,
1688			    (io_workitem_func)ndis_ifstarttask_wrap,
1689			    WORKQUEUE_CRITICAL, sc);
1690	}
1691
1692	callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
1693}
1694
1695static void
1696ndis_ticktask(device_object *d, void *xsc)
1697{
1698	struct ndis_softc	*sc = xsc;
1699	ndis_checkforhang_handler hangfunc;
1700	uint8_t			rval;
1701
1702	NDIS_LOCK(sc);
1703	if (!NDIS_INITIALIZED(sc)) {
1704		NDIS_UNLOCK(sc);
1705		return;
1706	}
1707	NDIS_UNLOCK(sc);
1708
1709	hangfunc = sc->ndis_chars->nmc_checkhang_func;
1710
1711	if (hangfunc != NULL) {
1712		rval = MSCALL1(hangfunc,
1713		    sc->ndis_block->nmb_miniportadapterctx);
1714		if (rval == TRUE) {
1715			ndis_reset_nic(sc);
1716			return;
1717		}
1718	}
1719
1720	NDIS_LOCK(sc);
1721	if (sc->ndis_link == 0 &&
1722	    sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
1723		sc->ndis_link = 1;
1724		if (sc->ndis_80211 != 0) {
1725			struct ieee80211com *ic = &sc->ndis_ic;
1726			struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1727
1728			if (vap != NULL) {
1729				NDIS_UNLOCK(sc);
1730				ndis_getstate_80211(sc);
1731				ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
1732				NDIS_LOCK(sc);
1733				if_link_state_change(vap->iv_ifp,
1734				    LINK_STATE_UP);
1735			}
1736		} else
1737			if_link_state_change(sc->ifp, LINK_STATE_UP);
1738	}
1739
1740	if (sc->ndis_link == 1 &&
1741	    sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
1742		sc->ndis_link = 0;
1743		if (sc->ndis_80211 != 0) {
1744			struct ieee80211com *ic = &sc->ndis_ic;
1745			struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1746
1747			if (vap != NULL) {
1748				NDIS_UNLOCK(sc);
1749				ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1750				NDIS_LOCK(sc);
1751				if_link_state_change(vap->iv_ifp,
1752				    LINK_STATE_DOWN);
1753			}
1754		} else
1755			if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1756	}
1757
1758	NDIS_UNLOCK(sc);
1759}
1760
1761static void
1762ndis_map_sclist(arg, segs, nseg, mapsize, error)
1763	void			*arg;
1764	bus_dma_segment_t	*segs;
1765	int			nseg;
1766	bus_size_t		mapsize;
1767	int			error;
1768
1769{
1770	struct ndis_sc_list	*sclist;
1771	int			i;
1772
1773	if (error || arg == NULL)
1774		return;
1775
1776	sclist = arg;
1777
1778	sclist->nsl_frags = nseg;
1779
1780	for (i = 0; i < nseg; i++) {
1781		sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1782		sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1783	}
1784}
1785
1786static int
1787ndis_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1788	const struct ieee80211_bpf_params *params)
1789{
1790	/* no support; just discard */
1791	m_freem(m);
1792	ieee80211_free_node(ni);
1793	return (0);
1794}
1795
1796static void
1797ndis_update_mcast(struct ieee80211com *ic)
1798{
1799       struct ndis_softc *sc = ic->ic_softc;
1800
1801       ndis_setmulti(sc);
1802}
1803
1804static void
1805ndis_update_promisc(struct ieee80211com *ic)
1806{
1807       /* not supported */
1808}
1809
1810static void
1811ndis_ifstarttask(device_object *d, void *arg)
1812{
1813	struct ndis_softc	*sc = arg;
1814	DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
1815	if (sc->ndis_80211)
1816		return;
1817
1818	struct ifnet		*ifp = sc->ifp;
1819	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1820		ndis_ifstart(ifp);
1821}
1822
1823/*
1824 * Main transmit routine. To make NDIS drivers happy, we need to
1825 * transform mbuf chains into NDIS packets and feed them to the
1826 * send packet routines. Most drivers allow you to send several
1827 * packets at once (up to the maxpkts limit). Unfortunately, rather
1828 * that accepting them in the form of a linked list, they expect
1829 * a contiguous array of pointers to packets.
1830 *
1831 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1832 * we need to perform busdma work here. Those that use map registers
1833 * will do the mapping themselves on a buffer by buffer basis.
1834 */
1835static void
1836ndis_ifstart(struct ifnet *ifp)
1837{
1838	struct ndis_softc	*sc;
1839	struct mbuf		*m = NULL;
1840	ndis_packet		**p0 = NULL, *p = NULL;
1841	ndis_tcpip_csum		*csum;
1842	int			pcnt = 0, status;
1843
1844	sc = ifp->if_softc;
1845
1846	NDIS_LOCK(sc);
1847	if (!sc->ndis_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1848		NDIS_UNLOCK(sc);
1849		return;
1850	}
1851
1852	p0 = &sc->ndis_txarray[sc->ndis_txidx];
1853
1854	while(sc->ndis_txpending) {
1855		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1856		if (m == NULL)
1857			break;
1858
1859		NdisAllocatePacket(&status,
1860		    &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1861
1862		if (status != NDIS_STATUS_SUCCESS)
1863			break;
1864
1865		if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1866			IFQ_DRV_PREPEND(&ifp->if_snd, m);
1867			NDIS_UNLOCK(sc);
1868			return;
1869		}
1870
1871		/*
1872		 * Save pointer to original mbuf
1873		 * so we can free it later.
1874		 */
1875
1876		p = sc->ndis_txarray[sc->ndis_txidx];
1877		p->np_txidx = sc->ndis_txidx;
1878		p->np_m0 = m;
1879		p->np_oob.npo_status = NDIS_STATUS_PENDING;
1880
1881		/*
1882		 * Do scatter/gather processing, if driver requested it.
1883		 */
1884		if (sc->ndis_sc) {
1885			bus_dmamap_load_mbuf(sc->ndis_ttag,
1886			    sc->ndis_tmaps[sc->ndis_txidx], m,
1887			    ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1888			bus_dmamap_sync(sc->ndis_ttag,
1889			    sc->ndis_tmaps[sc->ndis_txidx],
1890			    BUS_DMASYNC_PREREAD);
1891			p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1892		}
1893
1894		/* Handle checksum offload. */
1895
1896		if (ifp->if_capenable & IFCAP_TXCSUM &&
1897		    m->m_pkthdr.csum_flags) {
1898			csum = (ndis_tcpip_csum *)
1899				&p->np_ext.npe_info[ndis_tcpipcsum_info];
1900			csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1901			if (m->m_pkthdr.csum_flags & CSUM_IP)
1902				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1903			if (m->m_pkthdr.csum_flags & CSUM_TCP)
1904				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1905			if (m->m_pkthdr.csum_flags & CSUM_UDP)
1906				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1907			p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1908		}
1909
1910		NDIS_INC(sc);
1911		sc->ndis_txpending--;
1912
1913		pcnt++;
1914
1915		/*
1916		 * If there's a BPF listener, bounce a copy of this frame
1917		 * to him.
1918		 */
1919		if (!sc->ndis_80211)	/* XXX handle 80211 */
1920			BPF_MTAP(ifp, m);
1921
1922		/*
1923		 * The array that p0 points to must appear contiguous,
1924		 * so we must not wrap past the end of sc->ndis_txarray[].
1925		 * If it looks like we're about to wrap, break out here
1926		 * so the this batch of packets can be transmitted, then
1927		 * wait for txeof to ask us to send the rest.
1928		 */
1929		if (sc->ndis_txidx == 0)
1930			break;
1931	}
1932
1933	if (pcnt == 0) {
1934		NDIS_UNLOCK(sc);
1935		return;
1936	}
1937
1938	if (sc->ndis_txpending == 0)
1939		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1940
1941	/*
1942	 * Set a timeout in case the chip goes out to lunch.
1943	 */
1944	sc->ndis_tx_timer = 5;
1945
1946	NDIS_UNLOCK(sc);
1947
1948	/*
1949	 * According to NDIS documentation, if a driver exports
1950	 * a MiniportSendPackets() routine, we prefer that over
1951	 * a MiniportSend() routine (which sends just a single
1952	 * packet).
1953	 */
1954	if (sc->ndis_chars->nmc_sendmulti_func != NULL)
1955		ndis_send_packets(sc, p0, pcnt);
1956	else
1957		ndis_send_packet(sc, p);
1958
1959	return;
1960}
1961
1962static int
1963ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
1964{
1965	struct ndis_softc *sc = ic->ic_softc;
1966	ndis_packet **p0 = NULL, *p = NULL;
1967	int status;
1968
1969	NDIS_LOCK(sc);
1970	if (!sc->ndis_link || !sc->ndis_running) {
1971		NDIS_UNLOCK(sc);
1972		return (ENXIO);
1973	}
1974
1975	if (sc->ndis_txpending == 0) {
1976		NDIS_UNLOCK(sc);
1977		return (ENOBUFS);
1978	}
1979
1980	p0 = &sc->ndis_txarray[sc->ndis_txidx];
1981
1982	NdisAllocatePacket(&status,
1983	    &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
1984
1985	if (status != NDIS_STATUS_SUCCESS) {
1986		NDIS_UNLOCK(sc);
1987		return (ENOBUFS);
1988	}
1989
1990	if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1991		NDIS_UNLOCK(sc);
1992		return (ENOBUFS);
1993	}
1994
1995	/*
1996	 * Save pointer to original mbuf
1997	 * so we can free it later.
1998	 */
1999
2000	p = sc->ndis_txarray[sc->ndis_txidx];
2001	p->np_txidx = sc->ndis_txidx;
2002	p->np_m0 = m;
2003	p->np_oob.npo_status = NDIS_STATUS_PENDING;
2004
2005	/*
2006	 * Do scatter/gather processing, if driver requested it.
2007	 */
2008	if (sc->ndis_sc) {
2009		bus_dmamap_load_mbuf(sc->ndis_ttag,
2010		    sc->ndis_tmaps[sc->ndis_txidx], m,
2011		    ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
2012		bus_dmamap_sync(sc->ndis_ttag,
2013		    sc->ndis_tmaps[sc->ndis_txidx],
2014		    BUS_DMASYNC_PREREAD);
2015		p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
2016	}
2017
2018	NDIS_INC(sc);
2019	sc->ndis_txpending--;
2020
2021	/*
2022	 * Set a timeout in case the chip goes out to lunch.
2023	 */
2024	sc->ndis_tx_timer = 5;
2025	NDIS_UNLOCK(sc);
2026
2027	/*
2028	 * According to NDIS documentation, if a driver exports
2029	 * a MiniportSendPackets() routine, we prefer that over
2030	 * a MiniportSend() routine (which sends just a single
2031	 * packet).
2032	 */
2033	if (sc->ndis_chars->nmc_sendmulti_func != NULL)
2034		ndis_send_packets(sc, p0, 1);
2035	else
2036		ndis_send_packet(sc, p);
2037
2038	return (0);
2039}
2040
2041static void
2042ndis_80211parent(struct ieee80211com *ic)
2043{
2044	struct ndis_softc *sc = ic->ic_softc;
2045
2046	/*NDIS_LOCK(sc);*/
2047	if (ic->ic_nrunning > 0) {
2048		if (!sc->ndis_running)
2049			ndis_init(sc);
2050	} else if (sc->ndis_running)
2051		ndis_stop(sc);
2052	/*NDIS_UNLOCK(sc);*/
2053}
2054
2055static void
2056ndis_init(void *xsc)
2057{
2058	struct ndis_softc	*sc = xsc;
2059	int			i, len, error;
2060
2061	/*
2062	 * Avoid reintializing the link unnecessarily.
2063	 * This should be dealt with in a better way by
2064	 * fixing the upper layer modules so they don't
2065	 * call ifp->if_init() quite as often.
2066	 */
2067	if (sc->ndis_link)
2068		return;
2069
2070	/*
2071	 * Cancel pending I/O and free all RX/TX buffers.
2072	 */
2073	ndis_stop(sc);
2074
2075	if (!(sc->ndis_iftype == PNPBus && ndisusb_halt == 0)) {
2076		error = ndis_init_nic(sc);
2077		if (error != 0) {
2078			device_printf(sc->ndis_dev,
2079			    "failed to initialize the device: %d\n", error);
2080			return;
2081		}
2082	}
2083
2084	/* Program the packet filter */
2085	sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
2086	    NDIS_PACKET_TYPE_BROADCAST;
2087
2088	if (sc->ndis_80211) {
2089		struct ieee80211com *ic = &sc->ndis_ic;
2090
2091		if (ic->ic_promisc > 0)
2092			sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2093	} else {
2094		struct ifnet *ifp = sc->ifp;
2095
2096		if (ifp->if_flags & IFF_PROMISC)
2097			sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
2098	}
2099
2100	len = sizeof(sc->ndis_filter);
2101
2102	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
2103	    &sc->ndis_filter, &len);
2104
2105	if (error)
2106		device_printf(sc->ndis_dev, "set filter failed: %d\n", error);
2107
2108	/*
2109	 * Set lookahead.
2110 	 */
2111	if (sc->ndis_80211)
2112		i = ETHERMTU;
2113	else
2114		i = sc->ifp->if_mtu;
2115	len = sizeof(i);
2116	ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
2117
2118	/*
2119	 * Program the multicast filter, if necessary.
2120	 */
2121	ndis_setmulti(sc);
2122
2123	/* Setup task offload. */
2124	ndis_set_offload(sc);
2125
2126	NDIS_LOCK(sc);
2127
2128	sc->ndis_txidx = 0;
2129	sc->ndis_txpending = sc->ndis_maxpkts;
2130	sc->ndis_link = 0;
2131
2132	if (!sc->ndis_80211) {
2133		if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
2134		sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
2135		sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2136	}
2137
2138	sc->ndis_tx_timer = 0;
2139
2140	/*
2141	 * Some drivers don't set this value. The NDIS spec says
2142	 * the default checkforhang timeout is "approximately 2
2143	 * seconds." We use 3 seconds, because it seems for some
2144	 * drivers, exactly 2 seconds is too fast.
2145	 */
2146	if (sc->ndis_block->nmb_checkforhangsecs == 0)
2147		sc->ndis_block->nmb_checkforhangsecs = 3;
2148
2149	sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
2150	callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
2151	sc->ndis_running = 1;
2152	NDIS_UNLOCK(sc);
2153
2154	/* XXX force handling */
2155	if (sc->ndis_80211)
2156		ieee80211_start_all(&sc->ndis_ic);	/* start all vap's */
2157}
2158
2159/*
2160 * Set media options.
2161 */
2162static int
2163ndis_ifmedia_upd(ifp)
2164	struct ifnet		*ifp;
2165{
2166	struct ndis_softc		*sc;
2167
2168	sc = ifp->if_softc;
2169
2170	if (NDIS_INITIALIZED(sc))
2171		ndis_init(sc);
2172
2173	return (0);
2174}
2175
2176/*
2177 * Report current media status.
2178 */
2179static void
2180ndis_ifmedia_sts(ifp, ifmr)
2181	struct ifnet		*ifp;
2182	struct ifmediareq	*ifmr;
2183{
2184	struct ndis_softc	*sc;
2185	uint32_t		media_info;
2186	ndis_media_state	linkstate;
2187	int			len;
2188
2189	ifmr->ifm_status = IFM_AVALID;
2190	ifmr->ifm_active = IFM_ETHER;
2191	sc = ifp->if_softc;
2192
2193	if (!NDIS_INITIALIZED(sc))
2194		return;
2195
2196	len = sizeof(linkstate);
2197	ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
2198	    (void *)&linkstate, &len);
2199
2200	len = sizeof(media_info);
2201	ndis_get_info(sc, OID_GEN_LINK_SPEED,
2202	    (void *)&media_info, &len);
2203
2204	if (linkstate == nmc_connected)
2205		ifmr->ifm_status |= IFM_ACTIVE;
2206
2207	switch (media_info) {
2208	case 100000:
2209		ifmr->ifm_active |= IFM_10_T;
2210		break;
2211	case 1000000:
2212		ifmr->ifm_active |= IFM_100_TX;
2213		break;
2214	case 10000000:
2215		ifmr->ifm_active |= IFM_1000_T;
2216		break;
2217	default:
2218		device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
2219		break;
2220	}
2221}
2222
2223static int
2224ndis_set_cipher(struct ndis_softc *sc, int cipher)
2225{
2226	struct ieee80211com	*ic = &sc->ndis_ic;
2227	int			rval = 0, len;
2228	uint32_t		arg, save;
2229
2230	len = sizeof(arg);
2231
2232	if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
2233		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_WEP))
2234			return (ENOTSUP);
2235		arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
2236	}
2237
2238	if (cipher == WPA_CSE_TKIP) {
2239		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP))
2240			return (ENOTSUP);
2241		arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
2242	}
2243
2244	if (cipher == WPA_CSE_CCMP) {
2245		if (!(ic->ic_cryptocaps & IEEE80211_CRYPTO_AES_CCM))
2246			return (ENOTSUP);
2247		arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
2248	}
2249
2250	DPRINTF(("Setting cipher to %d\n", arg));
2251	save = arg;
2252	rval = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2253
2254	if (rval)
2255		return (rval);
2256
2257	/* Check that the cipher was set correctly. */
2258
2259	len = sizeof(save);
2260	rval = ndis_get_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2261
2262	if (rval != 0 || arg != save)
2263		return (ENODEV);
2264
2265	return (0);
2266}
2267
2268/*
2269 * WPA is hairy to set up. Do the work in a separate routine
2270 * so we don't clutter the setstate function too much.
2271 * Important yet undocumented fact: first we have to set the
2272 * authentication mode, _then_ we enable the ciphers. If one
2273 * of the WPA authentication modes isn't enabled, the driver
2274 * might not permit the TKIP or AES ciphers to be selected.
2275 */
2276static int
2277ndis_set_wpa(sc, ie, ielen)
2278	struct ndis_softc	*sc;
2279	void			*ie;
2280	int			ielen;
2281{
2282	struct ieee80211_ie_wpa	*w;
2283	struct ndis_ie		*n;
2284	char			*pos;
2285	uint32_t		arg;
2286	int			i;
2287
2288	/*
2289	 * Apparently, the only way for us to know what ciphers
2290	 * and key management/authentication mode to use is for
2291	 * us to inspect the optional information element (IE)
2292	 * stored in the 802.11 state machine. This IE should be
2293	 * supplied by the WPA supplicant.
2294	 */
2295
2296	w = (struct ieee80211_ie_wpa *)ie;
2297
2298	/* Check for the right kind of IE. */
2299	if (w->wpa_id != IEEE80211_ELEMID_VENDOR) {
2300		DPRINTF(("Incorrect IE type %d\n", w->wpa_id));
2301		return (EINVAL);
2302	}
2303
2304	/* Skip over the ucast cipher OIDs. */
2305	pos = (char *)&w->wpa_uciphers[0];
2306	pos += w->wpa_uciphercnt * sizeof(struct ndis_ie);
2307
2308	/* Skip over the authmode count. */
2309	pos += sizeof(u_int16_t);
2310
2311	/*
2312	 * Check for the authentication modes. I'm
2313	 * pretty sure there's only supposed to be one.
2314	 */
2315
2316	n = (struct ndis_ie *)pos;
2317	if (n->ni_val == WPA_ASE_NONE)
2318		arg = NDIS_80211_AUTHMODE_WPANONE;
2319
2320	if (n->ni_val == WPA_ASE_8021X_UNSPEC)
2321		arg = NDIS_80211_AUTHMODE_WPA;
2322
2323	if (n->ni_val == WPA_ASE_8021X_PSK)
2324		arg = NDIS_80211_AUTHMODE_WPAPSK;
2325
2326	DPRINTF(("Setting WPA auth mode to %d\n", arg));
2327	i = sizeof(arg);
2328	if (ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i))
2329		return (ENOTSUP);
2330	i = sizeof(arg);
2331	ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
2332
2333	/* Now configure the desired ciphers. */
2334
2335	/* First, set up the multicast group cipher. */
2336	n = (struct ndis_ie *)&w->wpa_mcipher[0];
2337
2338	if (ndis_set_cipher(sc, n->ni_val))
2339		return (ENOTSUP);
2340
2341	/* Now start looking around for the unicast ciphers. */
2342	pos = (char *)&w->wpa_uciphers[0];
2343	n = (struct ndis_ie *)pos;
2344
2345	for (i = 0; i < w->wpa_uciphercnt; i++) {
2346		if (ndis_set_cipher(sc, n->ni_val))
2347			return (ENOTSUP);
2348		n++;
2349	}
2350
2351	return (0);
2352}
2353
2354static void
2355ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2356{
2357	struct ieee80211vap *vap = ifp->if_softc;
2358	struct ndis_softc *sc = vap->iv_ic->ic_softc;
2359	uint32_t txrate;
2360	int len;
2361
2362	if (!NDIS_INITIALIZED(sc))
2363		return;
2364
2365	len = sizeof(txrate);
2366	if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0)
2367		vap->iv_bss->ni_txrate = txrate / 5000;
2368	ieee80211_media_status(ifp, imr);
2369}
2370
2371static void
2372ndis_setstate_80211(struct ndis_softc *sc)
2373{
2374	struct ieee80211com	*ic = &sc->ndis_ic;
2375	struct ieee80211vap	*vap = TAILQ_FIRST(&ic->ic_vaps);
2376	ndis_80211_macaddr	bssid;
2377	ndis_80211_config	config;
2378	int			rval = 0, len;
2379	uint32_t		arg;
2380
2381	if (!NDIS_INITIALIZED(sc)) {
2382		DPRINTF(("%s: NDIS not initialized\n", __func__));
2383		return;
2384	}
2385
2386	/* Disassociate and turn off radio. */
2387	len = sizeof(arg);
2388	arg = 1;
2389	ndis_set_info(sc, OID_802_11_DISASSOCIATE, &arg, &len);
2390
2391	/* Set network infrastructure mode. */
2392
2393	len = sizeof(arg);
2394	if (ic->ic_opmode == IEEE80211_M_IBSS)
2395		arg = NDIS_80211_NET_INFRA_IBSS;
2396	else
2397		arg = NDIS_80211_NET_INFRA_BSS;
2398
2399	rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2400
2401	if (rval)
2402		device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2403
2404	/* Set power management */
2405	len = sizeof(arg);
2406	if (vap->iv_flags & IEEE80211_F_PMGTON)
2407		arg = NDIS_80211_POWERMODE_FAST_PSP;
2408	else
2409		arg = NDIS_80211_POWERMODE_CAM;
2410	ndis_set_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2411
2412	/* Set TX power */
2413	if ((ic->ic_caps & IEEE80211_C_TXPMGT) &&
2414	    ic->ic_txpowlimit < nitems(dBm2mW)) {
2415		arg = dBm2mW[ic->ic_txpowlimit];
2416		len = sizeof(arg);
2417		ndis_set_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2418	}
2419
2420	/*
2421	 * Default encryption mode to off, authentication
2422	 * to open and privacy to 'accept everything.'
2423	 */
2424	len = sizeof(arg);
2425	arg = NDIS_80211_WEPSTAT_DISABLED;
2426	ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &len);
2427
2428	len = sizeof(arg);
2429	arg = NDIS_80211_AUTHMODE_OPEN;
2430	ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2431
2432	/*
2433	 * Note that OID_802_11_PRIVACY_FILTER is optional:
2434	 * not all drivers implement it.
2435	 */
2436	len = sizeof(arg);
2437	arg = NDIS_80211_PRIVFILT_8021XWEP;
2438	ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
2439
2440	len = sizeof(config);
2441	bzero((char *)&config, len);
2442	config.nc_length = len;
2443	config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
2444	rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
2445
2446	/*
2447	 * Some drivers expect us to initialize these values, so
2448	 * provide some defaults.
2449	 */
2450
2451	if (config.nc_beaconperiod == 0)
2452		config.nc_beaconperiod = 100;
2453	if (config.nc_atimwin == 0)
2454		config.nc_atimwin = 100;
2455	if (config.nc_fhconfig.ncf_dwelltime == 0)
2456		config.nc_fhconfig.ncf_dwelltime = 200;
2457	if (rval == 0 && ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
2458		int chan, chanflag;
2459
2460		chan = ieee80211_chan2ieee(ic, ic->ic_bsschan);
2461		chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
2462		    IEEE80211_CHAN_5GHZ;
2463		if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
2464			config.nc_dsconfig =
2465				ic->ic_bsschan->ic_freq * 1000;
2466			len = sizeof(config);
2467			config.nc_length = len;
2468			config.nc_fhconfig.ncf_length =
2469			    sizeof(ndis_80211_config_fh);
2470			DPRINTF(("Setting channel to %ukHz\n", config.nc_dsconfig));
2471			rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
2472			    &config, &len);
2473			if (rval)
2474				device_printf(sc->ndis_dev, "couldn't change "
2475				    "DS config to %ukHz: %d\n",
2476				    config.nc_dsconfig, rval);
2477		}
2478	} else if (rval)
2479		device_printf(sc->ndis_dev, "couldn't retrieve "
2480		    "channel info: %d\n", rval);
2481
2482	/* Set the BSSID to our value so the driver doesn't associate */
2483	len = IEEE80211_ADDR_LEN;
2484	bcopy(vap->iv_myaddr, bssid, len);
2485	DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2486	rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2487	if (rval)
2488		device_printf(sc->ndis_dev,
2489		    "setting BSSID failed: %d\n", rval);
2490}
2491
2492static void
2493ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
2494{
2495	struct ieee80211_node	*ni = vap->iv_bss;
2496	ndis_80211_ssid		ssid;
2497	ndis_80211_macaddr	bssid;
2498	ndis_80211_wep		wep;
2499	int			i, rval = 0, len, error;
2500	uint32_t		arg;
2501
2502	if (!NDIS_INITIALIZED(sc)) {
2503		DPRINTF(("%s: NDIS not initialized\n", __func__));
2504		return;
2505	}
2506
2507	/* Initial setup */
2508	ndis_setstate_80211(sc);
2509
2510	/* Set network infrastructure mode. */
2511
2512	len = sizeof(arg);
2513	if (vap->iv_opmode == IEEE80211_M_IBSS)
2514		arg = NDIS_80211_NET_INFRA_IBSS;
2515	else
2516		arg = NDIS_80211_NET_INFRA_BSS;
2517
2518	rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
2519
2520	if (rval)
2521		device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
2522
2523	/* Set RTS threshold */
2524
2525	len = sizeof(arg);
2526	arg = vap->iv_rtsthreshold;
2527	ndis_set_info(sc, OID_802_11_RTS_THRESHOLD, &arg, &len);
2528
2529	/* Set fragmentation threshold */
2530
2531	len = sizeof(arg);
2532	arg = vap->iv_fragthreshold;
2533	ndis_set_info(sc, OID_802_11_FRAGMENTATION_THRESHOLD, &arg, &len);
2534
2535	/* Set WEP */
2536
2537	if (vap->iv_flags & IEEE80211_F_PRIVACY &&
2538	    !(vap->iv_flags & IEEE80211_F_WPA)) {
2539		int keys_set = 0;
2540
2541		if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
2542			len = sizeof(arg);
2543			arg = NDIS_80211_AUTHMODE_SHARED;
2544			DPRINTF(("Setting shared auth\n"));
2545			ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE,
2546			    &arg, &len);
2547		}
2548		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2549			if (vap->iv_nw_keys[i].wk_keylen) {
2550				if (vap->iv_nw_keys[i].wk_cipher->ic_cipher !=
2551				    IEEE80211_CIPHER_WEP)
2552					continue;
2553				bzero((char *)&wep, sizeof(wep));
2554				wep.nw_keylen = vap->iv_nw_keys[i].wk_keylen;
2555
2556				/*
2557				 * 5, 13 and 16 are the only valid
2558				 * key lengths. Anything in between
2559				 * will be zero padded out to the
2560				 * next highest boundary.
2561				 */
2562				if (vap->iv_nw_keys[i].wk_keylen < 5)
2563					wep.nw_keylen = 5;
2564				else if (vap->iv_nw_keys[i].wk_keylen > 5 &&
2565				     vap->iv_nw_keys[i].wk_keylen < 13)
2566					wep.nw_keylen = 13;
2567				else if (vap->iv_nw_keys[i].wk_keylen > 13 &&
2568				     vap->iv_nw_keys[i].wk_keylen < 16)
2569					wep.nw_keylen = 16;
2570
2571				wep.nw_keyidx = i;
2572				wep.nw_length = (sizeof(uint32_t) * 3)
2573				    + wep.nw_keylen;
2574				if (i == vap->iv_def_txkey)
2575					wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
2576				bcopy(vap->iv_nw_keys[i].wk_key,
2577				    wep.nw_keydata, wep.nw_length);
2578				len = sizeof(wep);
2579				DPRINTF(("Setting WEP key %d\n", i));
2580				rval = ndis_set_info(sc,
2581				    OID_802_11_ADD_WEP, &wep, &len);
2582				if (rval)
2583					device_printf(sc->ndis_dev,
2584					    "set wepkey failed: %d\n", rval);
2585				keys_set++;
2586			}
2587		}
2588		if (keys_set) {
2589			DPRINTF(("Setting WEP on\n"));
2590			arg = NDIS_80211_WEPSTAT_ENABLED;
2591			len = sizeof(arg);
2592			rval = ndis_set_info(sc,
2593			    OID_802_11_WEP_STATUS, &arg, &len);
2594			if (rval)
2595				device_printf(sc->ndis_dev,
2596				    "enable WEP failed: %d\n", rval);
2597			if (vap->iv_flags & IEEE80211_F_DROPUNENC)
2598				arg = NDIS_80211_PRIVFILT_8021XWEP;
2599			else
2600				arg = NDIS_80211_PRIVFILT_ACCEPTALL;
2601
2602			len = sizeof(arg);
2603			ndis_set_info(sc,
2604			    OID_802_11_PRIVACY_FILTER, &arg, &len);
2605		}
2606	}
2607
2608	/* Set up WPA. */
2609	if ((vap->iv_flags & IEEE80211_F_WPA) &&
2610	    vap->iv_appie_assocreq != NULL) {
2611		struct ieee80211_appie *ie = vap->iv_appie_assocreq;
2612		error = ndis_set_wpa(sc, ie->ie_data, ie->ie_len);
2613		if (error != 0)
2614			device_printf(sc->ndis_dev, "WPA setup failed\n");
2615	}
2616
2617#ifdef notyet
2618	/* Set network type. */
2619
2620	arg = 0;
2621
2622	switch (vap->iv_curmode) {
2623	case IEEE80211_MODE_11A:
2624		arg = NDIS_80211_NETTYPE_11OFDM5;
2625		break;
2626	case IEEE80211_MODE_11B:
2627		arg = NDIS_80211_NETTYPE_11DS;
2628		break;
2629	case IEEE80211_MODE_11G:
2630		arg = NDIS_80211_NETTYPE_11OFDM24;
2631		break;
2632	default:
2633		device_printf(sc->ndis_dev, "unknown mode: %d\n",
2634		    vap->iv_curmode);
2635	}
2636
2637	if (arg) {
2638		DPRINTF(("Setting network type to %d\n", arg));
2639		len = sizeof(arg);
2640		rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
2641		    &arg, &len);
2642		if (rval)
2643			device_printf(sc->ndis_dev,
2644			    "set nettype failed: %d\n", rval);
2645	}
2646#endif
2647
2648	/*
2649	 * If the user selected a specific BSSID, try
2650	 * to use that one. This is useful in the case where
2651	 * there are several APs in range with the same network
2652	 * name. To delete the BSSID, we use the broadcast
2653	 * address as the BSSID.
2654	 * Note that some drivers seem to allow setting a BSSID
2655	 * in ad-hoc mode, which has the effect of forcing the
2656	 * NIC to create an ad-hoc cell with a specific BSSID,
2657	 * instead of a randomly chosen one. However, the net80211
2658	 * code makes the assumtion that the BSSID setting is invalid
2659	 * when you're in ad-hoc mode, so we don't allow that here.
2660	 */
2661
2662	len = IEEE80211_ADDR_LEN;
2663	if (vap->iv_flags & IEEE80211_F_DESBSSID &&
2664	    vap->iv_opmode != IEEE80211_M_IBSS)
2665		bcopy(ni->ni_bssid, bssid, len);
2666	else
2667		bcopy(ieee80211broadcastaddr, bssid, len);
2668
2669	DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
2670	rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
2671	if (rval)
2672		device_printf(sc->ndis_dev,
2673		    "setting BSSID failed: %d\n", rval);
2674
2675	/* Set SSID -- always do this last. */
2676
2677#ifdef NDIS_DEBUG
2678	if (ndis_debug > 0) {
2679		printf("Setting ESSID to ");
2680		ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2681		printf("\n");
2682	}
2683#endif
2684
2685	len = sizeof(ssid);
2686	bzero((char *)&ssid, len);
2687	ssid.ns_ssidlen = ni->ni_esslen;
2688	if (ssid.ns_ssidlen == 0) {
2689		ssid.ns_ssidlen = 1;
2690	} else
2691		bcopy(ni->ni_essid, ssid.ns_ssid, ssid.ns_ssidlen);
2692
2693	rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
2694
2695	if (rval)
2696		device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
2697
2698	return;
2699}
2700
2701static int
2702ndis_get_bssid_list(sc, bl)
2703	struct ndis_softc	*sc;
2704	ndis_80211_bssid_list_ex	**bl;
2705{
2706	int	len, error;
2707
2708	len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
2709	*bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2710	if (*bl == NULL)
2711		return (ENOMEM);
2712
2713	error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2714	if (error == ENOSPC) {
2715		free(*bl, M_DEVBUF);
2716		*bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
2717		if (*bl == NULL)
2718			return (ENOMEM);
2719
2720		error = ndis_get_info(sc, OID_802_11_BSSID_LIST, *bl, &len);
2721	}
2722	if (error) {
2723		DPRINTF(("%s: failed to read\n", __func__));
2724		free(*bl, M_DEVBUF);
2725		return (error);
2726	}
2727
2728	return (0);
2729}
2730
2731static int
2732ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
2733{
2734	struct ieee80211com *ic = &sc->ndis_ic;
2735	struct ieee80211vap     *vap;
2736	struct ieee80211_node   *ni;
2737	ndis_80211_bssid_list_ex	*bl;
2738	ndis_wlan_bssid_ex	*bs;
2739	ndis_80211_macaddr	bssid;
2740	int			i, len, error;
2741
2742	if (!sc->ndis_link)
2743		return (ENOENT);
2744
2745	len = sizeof(bssid);
2746	error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
2747	if (error) {
2748		device_printf(sc->ndis_dev, "failed to get bssid\n");
2749		return (ENOENT);
2750	}
2751
2752	vap = TAILQ_FIRST(&ic->ic_vaps);
2753	ni = vap->iv_bss;
2754
2755	error = ndis_get_bssid_list(sc, &bl);
2756	if (error)
2757		return (error);
2758
2759	bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
2760	for (i = 0; i < bl->nblx_items; i++) {
2761		if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
2762			*assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
2763			if (*assoc == NULL) {
2764				free(bl, M_TEMP);
2765				return (ENOMEM);
2766			}
2767			bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
2768			free(bl, M_TEMP);
2769			if (ic->ic_opmode == IEEE80211_M_STA)
2770				ni->ni_associd = 1 | 0xc000; /* fake associd */
2771			return (0);
2772		}
2773		bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
2774	}
2775
2776	free(bl, M_TEMP);
2777	return (ENOENT);
2778}
2779
2780static void
2781ndis_getstate_80211(struct ndis_softc *sc)
2782{
2783	struct ieee80211com	*ic = &sc->ndis_ic;
2784	struct ieee80211vap	*vap = TAILQ_FIRST(&ic->ic_vaps);
2785	struct ieee80211_node	*ni = vap->iv_bss;
2786	ndis_wlan_bssid_ex	*bs;
2787	int			rval, len, i = 0;
2788	int			chanflag;
2789	uint32_t		arg;
2790
2791	if (!NDIS_INITIALIZED(sc))
2792		return;
2793
2794	if ((rval = ndis_get_assoc(sc, &bs)) != 0)
2795		return;
2796
2797	/* We're associated, retrieve info on the current bssid. */
2798	ic->ic_curmode = ndis_nettype_mode(bs->nwbx_nettype);
2799	chanflag = ndis_nettype_chan(bs->nwbx_nettype);
2800	IEEE80211_ADDR_COPY(ni->ni_bssid, bs->nwbx_macaddr);
2801
2802	/* Get SSID from current association info. */
2803	bcopy(bs->nwbx_ssid.ns_ssid, ni->ni_essid,
2804	    bs->nwbx_ssid.ns_ssidlen);
2805	ni->ni_esslen = bs->nwbx_ssid.ns_ssidlen;
2806
2807	if (ic->ic_caps & IEEE80211_C_PMGT) {
2808		len = sizeof(arg);
2809		rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
2810
2811		if (rval)
2812			device_printf(sc->ndis_dev,
2813			    "get power mode failed: %d\n", rval);
2814		if (arg == NDIS_80211_POWERMODE_CAM)
2815			vap->iv_flags &= ~IEEE80211_F_PMGTON;
2816		else
2817			vap->iv_flags |= IEEE80211_F_PMGTON;
2818	}
2819
2820	/* Get TX power */
2821	if (ic->ic_caps & IEEE80211_C_TXPMGT) {
2822		len = sizeof(arg);
2823		ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &len);
2824		for (i = 0; i < nitems(dBm2mW); i++)
2825			if (dBm2mW[i] >= arg)
2826				break;
2827		ic->ic_txpowlimit = i;
2828	}
2829
2830	/*
2831	 * Use the current association information to reflect
2832	 * what channel we're on.
2833	 */
2834	ic->ic_curchan = ieee80211_find_channel(ic,
2835	    bs->nwbx_config.nc_dsconfig / 1000, chanflag);
2836	if (ic->ic_curchan == NULL)
2837		ic->ic_curchan = &ic->ic_channels[0];
2838	ni->ni_chan = ic->ic_curchan;
2839	ic->ic_bsschan = ic->ic_curchan;
2840
2841	free(bs, M_TEMP);
2842
2843	/*
2844	 * Determine current authentication mode.
2845	 */
2846	len = sizeof(arg);
2847	rval = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
2848	if (rval)
2849		device_printf(sc->ndis_dev,
2850		    "get authmode status failed: %d\n", rval);
2851	else {
2852		vap->iv_flags &= ~IEEE80211_F_WPA;
2853		switch (arg) {
2854		case NDIS_80211_AUTHMODE_OPEN:
2855			ni->ni_authmode = IEEE80211_AUTH_OPEN;
2856			break;
2857		case NDIS_80211_AUTHMODE_SHARED:
2858			ni->ni_authmode = IEEE80211_AUTH_SHARED;
2859			break;
2860		case NDIS_80211_AUTHMODE_AUTO:
2861			ni->ni_authmode = IEEE80211_AUTH_AUTO;
2862			break;
2863		case NDIS_80211_AUTHMODE_WPA:
2864		case NDIS_80211_AUTHMODE_WPAPSK:
2865		case NDIS_80211_AUTHMODE_WPANONE:
2866			ni->ni_authmode = IEEE80211_AUTH_WPA;
2867			vap->iv_flags |= IEEE80211_F_WPA1;
2868			break;
2869		case NDIS_80211_AUTHMODE_WPA2:
2870		case NDIS_80211_AUTHMODE_WPA2PSK:
2871			ni->ni_authmode = IEEE80211_AUTH_WPA;
2872			vap->iv_flags |= IEEE80211_F_WPA2;
2873			break;
2874		default:
2875			ni->ni_authmode = IEEE80211_AUTH_NONE;
2876			break;
2877		}
2878	}
2879
2880	len = sizeof(arg);
2881	rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
2882
2883	if (rval)
2884		device_printf(sc->ndis_dev,
2885		    "get wep status failed: %d\n", rval);
2886
2887	if (arg == NDIS_80211_WEPSTAT_ENABLED)
2888		vap->iv_flags |= IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC;
2889	else
2890		vap->iv_flags &= ~(IEEE80211_F_PRIVACY|IEEE80211_F_DROPUNENC);
2891}
2892
2893static int
2894ndis_ifioctl(ifp, command, data)
2895	struct ifnet		*ifp;
2896	u_long			command;
2897	caddr_t			data;
2898{
2899	struct ndis_softc	*sc = ifp->if_softc;
2900	struct ifreq		*ifr = (struct ifreq *) data;
2901	int			i, error = 0;
2902
2903	/*NDIS_LOCK(sc);*/
2904
2905	switch (command) {
2906	case SIOCSIFFLAGS:
2907		if (ifp->if_flags & IFF_UP) {
2908			if (sc->ndis_running &&
2909			    ifp->if_flags & IFF_PROMISC &&
2910			    !(sc->ndis_if_flags & IFF_PROMISC)) {
2911				sc->ndis_filter |=
2912				    NDIS_PACKET_TYPE_PROMISCUOUS;
2913				i = sizeof(sc->ndis_filter);
2914				error = ndis_set_info(sc,
2915				    OID_GEN_CURRENT_PACKET_FILTER,
2916				    &sc->ndis_filter, &i);
2917			} else if (sc->ndis_running &&
2918			    !(ifp->if_flags & IFF_PROMISC) &&
2919			    sc->ndis_if_flags & IFF_PROMISC) {
2920				sc->ndis_filter &=
2921				    ~NDIS_PACKET_TYPE_PROMISCUOUS;
2922				i = sizeof(sc->ndis_filter);
2923				error = ndis_set_info(sc,
2924				    OID_GEN_CURRENT_PACKET_FILTER,
2925				    &sc->ndis_filter, &i);
2926			} else
2927				ndis_init(sc);
2928		} else {
2929			if (sc->ndis_running)
2930				ndis_stop(sc);
2931		}
2932		sc->ndis_if_flags = ifp->if_flags;
2933		error = 0;
2934		break;
2935	case SIOCADDMULTI:
2936	case SIOCDELMULTI:
2937		ndis_setmulti(sc);
2938		error = 0;
2939		break;
2940	case SIOCGIFMEDIA:
2941	case SIOCSIFMEDIA:
2942		error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
2943		break;
2944	case SIOCSIFCAP:
2945		ifp->if_capenable = ifr->ifr_reqcap;
2946		if (ifp->if_capenable & IFCAP_TXCSUM)
2947			ifp->if_hwassist = sc->ndis_hwassist;
2948		else
2949			ifp->if_hwassist = 0;
2950		ndis_set_offload(sc);
2951		break;
2952	default:
2953		error = ether_ioctl(ifp, command, data);
2954		break;
2955	}
2956
2957	/*NDIS_UNLOCK(sc);*/
2958
2959	return(error);
2960}
2961
2962static int
2963ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
2964{
2965	struct ndis_softc *sc = ic->ic_softc;
2966	struct ifreq *ifr = data;
2967	struct ndis_oid_data oid;
2968	struct ndis_evt evt;
2969	void *oidbuf = NULL;
2970	int error = 0;
2971
2972	if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
2973		return (error);
2974
2975	switch (cmd) {
2976	case SIOCGDRVSPEC:
2977	case SIOCSDRVSPEC:
2978		error = copyin(ifr->ifr_data, &oid, sizeof(oid));
2979		if (error)
2980			break;
2981		oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
2982		error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
2983	}
2984
2985	if (error) {
2986		free(oidbuf, M_TEMP);
2987		return (error);
2988	}
2989
2990	switch (cmd) {
2991	case SIOCGDRVSPEC:
2992		error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
2993		break;
2994	case SIOCSDRVSPEC:
2995		error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
2996		break;
2997	case SIOCGPRIVATE_0:
2998		NDIS_LOCK(sc);
2999		if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
3000			error = ENOENT;
3001			NDIS_UNLOCK(sc);
3002			break;
3003		}
3004		error = copyin(ifr->ifr_data, &evt, sizeof(evt));
3005		if (error) {
3006			NDIS_UNLOCK(sc);
3007			break;
3008		}
3009		if (evt.ne_len < sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3010			error = ENOSPC;
3011			NDIS_UNLOCK(sc);
3012			break;
3013		}
3014		error = copyout(&sc->ndis_evt[sc->ndis_evtcidx],
3015		    ifr->ifr_data, sizeof(uint32_t) * 2);
3016		if (error) {
3017			NDIS_UNLOCK(sc);
3018			break;
3019		}
3020		if (sc->ndis_evt[sc->ndis_evtcidx].ne_len) {
3021			error = copyout(sc->ndis_evt[sc->ndis_evtcidx].ne_buf,
3022			    ifr->ifr_data + (sizeof(uint32_t) * 2),
3023			    sc->ndis_evt[sc->ndis_evtcidx].ne_len);
3024			if (error) {
3025				NDIS_UNLOCK(sc);
3026				break;
3027			}
3028			free(sc->ndis_evt[sc->ndis_evtcidx].ne_buf, M_TEMP);
3029			sc->ndis_evt[sc->ndis_evtcidx].ne_buf = NULL;
3030		}
3031		sc->ndis_evt[sc->ndis_evtcidx].ne_len = 0;
3032		sc->ndis_evt[sc->ndis_evtcidx].ne_sts = 0;
3033		NDIS_EVTINC(sc->ndis_evtcidx);
3034		NDIS_UNLOCK(sc);
3035		break;
3036	default:
3037		error = ENOTTY;
3038		break;
3039	}
3040
3041	switch (cmd) {
3042	case SIOCGDRVSPEC:
3043	case SIOCSDRVSPEC:
3044		error = copyout(&oid, ifr->ifr_data, sizeof(oid));
3045		if (error)
3046			break;
3047		error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
3048	}
3049
3050	free(oidbuf, M_TEMP);
3051
3052	return (error);
3053}
3054
3055int
3056ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3057{
3058	struct ndis_softc	*sc = vap->iv_ic->ic_softc;
3059	ndis_80211_key		rkey;
3060	int			len, error = 0;
3061
3062	bzero((char *)&rkey, sizeof(rkey));
3063	len = sizeof(rkey);
3064
3065	rkey.nk_len = len;
3066	rkey.nk_keyidx = key->wk_keyix;
3067
3068	bcopy(vap->iv_ifp->if_broadcastaddr,
3069	    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3070
3071	error = ndis_set_info(sc, OID_802_11_REMOVE_KEY, &rkey, &len);
3072
3073	if (error)
3074		return (0);
3075
3076	return (1);
3077}
3078
3079/*
3080 * In theory this could be called for any key, but we'll
3081 * only use it for WPA TKIP or AES keys. These need to be
3082 * set after initial authentication with the AP.
3083 */
3084static int
3085ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
3086{
3087	struct ndis_softc	*sc = vap->iv_ic->ic_softc;
3088	ndis_80211_key		rkey;
3089	int			len, error = 0;
3090
3091	switch (key->wk_cipher->ic_cipher) {
3092	case IEEE80211_CIPHER_TKIP:
3093
3094		len = sizeof(ndis_80211_key);
3095		bzero((char *)&rkey, sizeof(rkey));
3096
3097		rkey.nk_len = len;
3098		rkey.nk_keylen = key->wk_keylen;
3099
3100		if (key->wk_flags & IEEE80211_KEY_SWMIC)
3101			rkey.nk_keylen += 16;
3102
3103		/* key index - gets weird in NDIS */
3104
3105		if (key->wk_keyix != IEEE80211_KEYIX_NONE)
3106			rkey.nk_keyidx = key->wk_keyix;
3107		else
3108			rkey.nk_keyidx = 0;
3109
3110		if (key->wk_flags & IEEE80211_KEY_XMIT)
3111			rkey.nk_keyidx |= 1 << 31;
3112
3113		if (key->wk_flags & IEEE80211_KEY_GROUP) {
3114			bcopy(ieee80211broadcastaddr,
3115			    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3116		} else {
3117			bcopy(vap->iv_bss->ni_bssid,
3118			    rkey.nk_bssid, IEEE80211_ADDR_LEN);
3119			/* pairwise key */
3120			rkey.nk_keyidx |= 1 << 30;
3121		}
3122
3123		/* need to set bit 29 based on keyrsc */
3124		rkey.nk_keyrsc = key->wk_keyrsc[0];	/* XXX need tid */
3125
3126		if (rkey.nk_keyrsc)
3127			rkey.nk_keyidx |= 1 << 29;
3128
3129		if (key->wk_flags & IEEE80211_KEY_SWMIC) {
3130			bcopy(key->wk_key, rkey.nk_keydata, 16);
3131			bcopy(key->wk_key + 24, rkey.nk_keydata + 16, 8);
3132			bcopy(key->wk_key + 16, rkey.nk_keydata + 24, 8);
3133		} else
3134			bcopy(key->wk_key, rkey.nk_keydata, key->wk_keylen);
3135
3136		error = ndis_set_info(sc, OID_802_11_ADD_KEY, &rkey, &len);
3137		break;
3138	case IEEE80211_CIPHER_WEP:
3139		error = 0;
3140		break;
3141	/*
3142	 * I don't know how to set up keys for the AES
3143	 * cipher yet. Is it the same as TKIP?
3144	 */
3145	case IEEE80211_CIPHER_AES_CCM:
3146	default:
3147		error = ENOTTY;
3148		break;
3149	}
3150
3151	/* We need to return 1 for success, 0 for failure. */
3152
3153	if (error)
3154		return (0);
3155
3156	return (1);
3157}
3158
3159static void
3160ndis_resettask(d, arg)
3161	device_object		*d;
3162	void			*arg;
3163{
3164	struct ndis_softc		*sc;
3165
3166	sc = arg;
3167	ndis_reset_nic(sc);
3168}
3169
3170/*
3171 * Stop the adapter and free any mbufs allocated to the
3172 * RX and TX lists.
3173 */
3174static void
3175ndis_stop(struct ndis_softc *sc)
3176{
3177	int			i;
3178
3179	callout_drain(&sc->ndis_stat_callout);
3180
3181	NDIS_LOCK(sc);
3182	sc->ndis_tx_timer = 0;
3183	sc->ndis_link = 0;
3184	if (!sc->ndis_80211)
3185		sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3186	sc->ndis_running = 0;
3187	NDIS_UNLOCK(sc);
3188
3189	if (sc->ndis_iftype != PNPBus ||
3190	    (sc->ndis_iftype == PNPBus &&
3191	     !(sc->ndisusb_status & NDISUSB_STATUS_DETACH) &&
3192	     ndisusb_halt != 0))
3193		ndis_halt_nic(sc);
3194
3195	NDIS_LOCK(sc);
3196	for (i = 0; i < NDIS_EVENTS; i++) {
3197		if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
3198			free(sc->ndis_evt[i].ne_buf, M_TEMP);
3199			sc->ndis_evt[i].ne_buf = NULL;
3200		}
3201		sc->ndis_evt[i].ne_sts = 0;
3202		sc->ndis_evt[i].ne_len = 0;
3203	}
3204	sc->ndis_evtcidx = 0;
3205	sc->ndis_evtpidx = 0;
3206	NDIS_UNLOCK(sc);
3207}
3208
3209/*
3210 * Stop all chip I/O so that the kernel's probe routines don't
3211 * get confused by errant DMAs when rebooting.
3212 */
3213void
3214ndis_shutdown(dev)
3215	device_t		dev;
3216{
3217	struct ndis_softc		*sc;
3218
3219	sc = device_get_softc(dev);
3220	ndis_stop(sc);
3221}
3222
3223static int
3224ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
3225{
3226	struct ndis_vap *nvp = NDIS_VAP(vap);
3227	struct ieee80211com *ic = vap->iv_ic;
3228	struct ndis_softc *sc = ic->ic_softc;
3229	enum ieee80211_state ostate;
3230
3231	DPRINTF(("%s: %s -> %s\n", __func__,
3232		ieee80211_state_name[vap->iv_state],
3233		ieee80211_state_name[nstate]));
3234
3235	ostate = vap->iv_state;
3236	vap->iv_state = nstate;
3237
3238	switch (nstate) {
3239	/* pass on to net80211 */
3240	case IEEE80211_S_INIT:
3241	case IEEE80211_S_SCAN:
3242		return nvp->newstate(vap, nstate, arg);
3243	case IEEE80211_S_ASSOC:
3244		if (ostate != IEEE80211_S_AUTH) {
3245			IEEE80211_UNLOCK(ic);
3246			ndis_auth_and_assoc(sc, vap);
3247			IEEE80211_LOCK(ic);
3248		}
3249		break;
3250	case IEEE80211_S_AUTH:
3251		IEEE80211_UNLOCK(ic);
3252		ndis_auth_and_assoc(sc, vap);
3253		if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
3254			ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
3255		IEEE80211_LOCK(ic);
3256		break;
3257	default:
3258		break;
3259	}
3260	return (0);
3261}
3262
3263static void
3264ndis_scan(void *arg)
3265{
3266	struct ieee80211vap *vap = arg;
3267
3268	ieee80211_scan_done(vap);
3269}
3270
3271static void
3272ndis_scan_results(struct ndis_softc *sc)
3273{
3274	struct ieee80211com *ic = &sc->ndis_ic;
3275	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3276	ndis_80211_bssid_list_ex *bl;
3277	ndis_wlan_bssid_ex	*wb;
3278	struct ieee80211_scanparams sp;
3279	struct ieee80211_frame wh;
3280	struct ieee80211_channel *saved_chan;
3281	int i, j;
3282	int rssi, noise, freq, chanflag;
3283	uint8_t ssid[2+IEEE80211_NWID_LEN];
3284	uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
3285	uint8_t *frm, *efrm;
3286
3287	saved_chan = ic->ic_curchan;
3288	noise = -96;
3289
3290	if (ndis_get_bssid_list(sc, &bl))
3291		return;
3292
3293	DPRINTF(("%s: %d results\n", __func__, bl->nblx_items));
3294	wb = &bl->nblx_bssid[0];
3295	for (i = 0; i < bl->nblx_items; i++) {
3296		memset(&sp, 0, sizeof(sp));
3297
3298		memcpy(wh.i_addr2, wb->nwbx_macaddr, sizeof(wh.i_addr2));
3299		memcpy(wh.i_addr3, wb->nwbx_macaddr, sizeof(wh.i_addr3));
3300		rssi = 100 * (wb->nwbx_rssi - noise) / (-32 - noise);
3301		rssi = max(0, min(rssi, 100));	/* limit 0 <= rssi <= 100 */
3302		if (wb->nwbx_privacy)
3303			sp.capinfo |= IEEE80211_CAPINFO_PRIVACY;
3304		sp.bintval = wb->nwbx_config.nc_beaconperiod;
3305		switch (wb->nwbx_netinfra) {
3306			case NDIS_80211_NET_INFRA_IBSS:
3307				sp.capinfo |= IEEE80211_CAPINFO_IBSS;
3308				break;
3309			case NDIS_80211_NET_INFRA_BSS:
3310				sp.capinfo |= IEEE80211_CAPINFO_ESS;
3311				break;
3312		}
3313		sp.rates = &rates[0];
3314		for (j = 0; j < IEEE80211_RATE_MAXSIZE; j++) {
3315			/* XXX - check units */
3316			if (wb->nwbx_supportedrates[j] == 0)
3317				break;
3318			rates[2 + j] =
3319			wb->nwbx_supportedrates[j] & 0x7f;
3320		}
3321		rates[1] = j;
3322		sp.ssid = (uint8_t *)&ssid[0];
3323		memcpy(sp.ssid + 2, &wb->nwbx_ssid.ns_ssid,
3324		    wb->nwbx_ssid.ns_ssidlen);
3325		sp.ssid[1] = wb->nwbx_ssid.ns_ssidlen;
3326
3327		chanflag = ndis_nettype_chan(wb->nwbx_nettype);
3328		freq = wb->nwbx_config.nc_dsconfig / 1000;
3329		sp.chan = sp.bchan = ieee80211_mhz2ieee(freq, chanflag);
3330		/* Hack ic->ic_curchan to be in sync with the scan result */
3331		ic->ic_curchan = ieee80211_find_channel(ic, freq, chanflag);
3332		if (ic->ic_curchan == NULL)
3333			ic->ic_curchan = &ic->ic_channels[0];
3334
3335		/* Process extended info from AP */
3336		if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
3337			frm = (uint8_t *)&wb->nwbx_ies;
3338			efrm = frm + wb->nwbx_ielen;
3339			if (efrm - frm < 12)
3340				goto done;
3341			sp.tstamp = frm;			frm += 8;
3342			sp.bintval = le16toh(*(uint16_t *)frm);	frm += 2;
3343			sp.capinfo = le16toh(*(uint16_t *)frm);	frm += 2;
3344			sp.ies = frm;
3345			sp.ies_len = efrm - frm;
3346		}
3347done:
3348		DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n",
3349		    ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag,
3350		    rssi));
3351		ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise);
3352		wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
3353	}
3354	free(bl, M_DEVBUF);
3355	/* Restore the channel after messing with it */
3356	ic->ic_curchan = saved_chan;
3357}
3358
3359static void
3360ndis_scan_start(struct ieee80211com *ic)
3361{
3362	struct ndis_softc *sc = ic->ic_softc;
3363	struct ieee80211vap *vap;
3364	struct ieee80211_scan_state *ss;
3365	ndis_80211_ssid ssid;
3366	int error, len;
3367
3368	ss = ic->ic_scan;
3369	vap = TAILQ_FIRST(&ic->ic_vaps);
3370
3371	if (!NDIS_INITIALIZED(sc)) {
3372		DPRINTF(("%s: scan aborted\n", __func__));
3373		ieee80211_cancel_scan(vap);
3374		return;
3375	}
3376
3377	len = sizeof(ssid);
3378	bzero((char *)&ssid, len);
3379	if (ss->ss_nssid == 0)
3380		ssid.ns_ssidlen = 1;
3381	else {
3382		/* Perform a directed scan */
3383		ssid.ns_ssidlen = ss->ss_ssid[0].len;
3384		bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
3385	}
3386
3387	error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
3388	if (error)
3389		DPRINTF(("%s: set ESSID failed\n", __func__));
3390
3391	len = 0;
3392	error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, NULL, &len);
3393	if (error) {
3394		DPRINTF(("%s: scan command failed\n", __func__));
3395		ieee80211_cancel_scan(vap);
3396		return;
3397	}
3398	/* Set a timer to collect the results */
3399	callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, vap);
3400}
3401
3402static void
3403ndis_set_channel(struct ieee80211com *ic)
3404{
3405	/* ignore */
3406}
3407
3408static void
3409ndis_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
3410{
3411	/* ignore */
3412}
3413
3414static void
3415ndis_scan_mindwell(struct ieee80211_scan_state *ss)
3416{
3417	/* NB: don't try to abort scan; wait for firmware to finish */
3418}
3419
3420static void
3421ndis_scan_end(struct ieee80211com *ic)
3422{
3423	struct ndis_softc *sc = ic->ic_softc;
3424
3425	ndis_scan_results(sc);
3426}
3427