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