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