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