if_ndis.c revision 133080
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
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 133080 2004-08-03 17:00:39Z wpaul $");
35
36#include "opt_bdg.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/sockio.h>
41#include <sys/mbuf.h>
42#include <sys/malloc.h>
43#include <sys/kernel.h>
44#include <sys/socket.h>
45#include <sys/queue.h>
46#if __FreeBSD_version < 502113
47#include <sys/sysctl.h>
48#endif
49
50#include <net/if.h>
51#include <net/if_arp.h>
52#include <net/ethernet.h>
53#include <net/if_dl.h>
54#include <net/if_media.h>
55#include <net/route.h>
56
57#include <net/bpf.h>
58
59#include <machine/bus_memio.h>
60#include <machine/bus_pio.h>
61#include <machine/bus.h>
62#include <machine/resource.h>
63#include <sys/bus.h>
64#include <sys/rman.h>
65
66#include <net80211/ieee80211_var.h>
67#include <net80211/ieee80211_ioctl.h>
68
69#include <dev/wi/if_wavelan_ieee.h>
70
71#include <dev/pci/pcireg.h>
72#include <dev/pci/pcivar.h>
73
74#include <compat/ndis/pe_var.h>
75#include <compat/ndis/resource_var.h>
76#include <compat/ndis/ntoskrnl_var.h>
77#include <compat/ndis/hal_var.h>
78#include <compat/ndis/ndis_var.h>
79#include <compat/ndis/cfg_var.h>
80#include <dev/if_ndis/if_ndisvar.h>
81
82#define NDIS_IMAGE
83#define NDIS_REGVALS
84
85#include "ndis_driver_data.h"
86
87int ndis_attach			(device_t);
88int ndis_detach			(device_t);
89int ndis_suspend		(device_t);
90int ndis_resume			(device_t);
91void ndis_shutdown		(device_t);
92
93static __stdcall void ndis_txeof	(ndis_handle,
94	ndis_packet *, ndis_status);
95static __stdcall void ndis_rxeof	(ndis_handle,
96	ndis_packet **, uint32_t);
97static __stdcall void ndis_linksts	(ndis_handle,
98	ndis_status, void *, uint32_t);
99static __stdcall void ndis_linksts_done	(ndis_handle);
100
101static void ndis_intr		(void *);
102static void ndis_intrtask	(void *);
103static void ndis_tick		(void *);
104static void ndis_ticktask	(void *);
105static void ndis_start		(struct ifnet *);
106static void ndis_starttask	(void *);
107static int ndis_ioctl		(struct ifnet *, u_long, caddr_t);
108static int ndis_wi_ioctl_get	(struct ifnet *, u_long, caddr_t);
109static int ndis_wi_ioctl_set	(struct ifnet *, u_long, caddr_t);
110static void ndis_init		(void *);
111static void ndis_stop		(struct ndis_softc *);
112static void ndis_watchdog	(struct ifnet *);
113static int ndis_ifmedia_upd	(struct ifnet *);
114static void ndis_ifmedia_sts	(struct ifnet *, struct ifmediareq *);
115static int ndis_get_assoc	(struct ndis_softc *, ndis_wlan_bssid_ex **);
116static int ndis_probe_offload	(struct ndis_softc *);
117static int ndis_set_offload	(struct ndis_softc *);
118static void ndis_getstate_80211	(struct ndis_softc *);
119static void ndis_setstate_80211	(struct ndis_softc *);
120static void ndis_media_status	(struct ifnet *, struct ifmediareq *);
121
122static void ndis_setmulti	(struct ndis_softc *);
123static void ndis_map_sclist	(void *, bus_dma_segment_t *,
124	int, bus_size_t, int);
125
126extern struct mtx_pool *ndis_mtxpool;
127
128/*
129 * Program the 64-bit multicast hash filter.
130 */
131static void
132ndis_setmulti(sc)
133	struct ndis_softc	*sc;
134{
135	struct ifnet		*ifp;
136	struct ifmultiaddr	*ifma;
137	int			len, mclistsz, error;
138	uint8_t			*mclist;
139
140	ifp = &sc->arpcom.ac_if;
141
142	if (!NDIS_INITIALIZED(sc))
143		return;
144
145	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
146		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
147		len = sizeof(sc->ndis_filter);
148		error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
149		    &sc->ndis_filter, &len);
150		if (error)
151			device_printf (sc->ndis_dev,
152			    "set filter failed: %d\n", error);
153		return;
154	}
155
156	if (TAILQ_EMPTY(&ifp->if_multiaddrs))
157		return;
158
159	len = sizeof(mclistsz);
160	ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
161
162	mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
163
164	if (mclist == NULL) {
165		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
166		goto out;
167	}
168
169	sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
170
171	len = 0;
172	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
173		if (ifma->ifma_addr->sa_family != AF_LINK)
174			continue;
175		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
176		    mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
177		len++;
178		if (len > mclistsz) {
179			sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
180			sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
181			goto out;
182		}
183	}
184
185	len = len * ETHER_ADDR_LEN;
186	error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
187	if (error) {
188		device_printf (sc->ndis_dev, "set mclist failed: %d\n", error);
189		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
190		sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
191	}
192
193out:
194	free(mclist, M_TEMP);
195
196	len = sizeof(sc->ndis_filter);
197	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
198	    &sc->ndis_filter, &len);
199	if (error)
200		device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
201
202	return;
203}
204
205static int
206ndis_set_offload(sc)
207	struct ndis_softc	*sc;
208{
209	ndis_task_offload	*nto;
210	ndis_task_offload_hdr	*ntoh;
211	ndis_task_tcpip_csum	*nttc;
212	struct ifnet		*ifp;
213	int			len, error;
214
215	ifp = &sc->arpcom.ac_if;
216
217	if (!NDIS_INITIALIZED(sc))
218		return(EINVAL);
219
220	/* See if there's anything to set. */
221
222	error = ndis_probe_offload(sc);
223	if (error)
224		return(error);
225
226	if (sc->ndis_hwassist == 0 && ifp->if_capabilities == 0)
227		return(0);
228
229	len = sizeof(ndis_task_offload_hdr) + sizeof(ndis_task_offload) +
230	    sizeof(ndis_task_tcpip_csum);
231
232	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
233
234	if (ntoh == NULL)
235		return(ENOMEM);
236
237	ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
238	ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
239	ntoh->ntoh_offset_firsttask = sizeof(ndis_task_offload_hdr);
240	ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
241	ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
242	ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
243
244	nto = (ndis_task_offload *)((char *)ntoh +
245	    ntoh->ntoh_offset_firsttask);
246
247	nto->nto_vers = NDIS_TASK_OFFLOAD_VERSION;
248	nto->nto_len = sizeof(ndis_task_offload);
249	nto->nto_task = NDIS_TASK_TCPIP_CSUM;
250	nto->nto_offset_nexttask = 0;
251	nto->nto_taskbuflen = sizeof(ndis_task_tcpip_csum);
252
253	nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
254
255	if (ifp->if_capenable & IFCAP_TXCSUM)
256		nttc->nttc_v4tx = sc->ndis_v4tx;
257
258	if (ifp->if_capenable & IFCAP_RXCSUM)
259		nttc->nttc_v4rx = sc->ndis_v4rx;
260
261	error = ndis_set_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
262	free(ntoh, M_TEMP);
263
264	return(error);
265}
266
267static int
268ndis_probe_offload(sc)
269	struct ndis_softc	*sc;
270{
271	ndis_task_offload	*nto;
272	ndis_task_offload_hdr	*ntoh;
273	ndis_task_tcpip_csum	*nttc = NULL;
274	struct ifnet		*ifp;
275	int			len, error, dummy;
276
277	ifp = &sc->arpcom.ac_if;
278
279	len = sizeof(dummy);
280	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, &dummy, &len);
281
282	if (error != ENOSPC)
283		return(error);
284
285	ntoh = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
286
287	if (ntoh == NULL)
288		return(ENOMEM);
289
290	ntoh->ntoh_vers = NDIS_TASK_OFFLOAD_VERSION;
291	ntoh->ntoh_len = sizeof(ndis_task_offload_hdr);
292	ntoh->ntoh_encapfmt.nef_encaphdrlen = sizeof(struct ether_header);
293	ntoh->ntoh_encapfmt.nef_encap = NDIS_ENCAP_IEEE802_3;
294	ntoh->ntoh_encapfmt.nef_flags = NDIS_ENCAPFLAG_FIXEDHDRLEN;
295
296	error = ndis_get_info(sc, OID_TCP_TASK_OFFLOAD, ntoh, &len);
297
298	if (error) {
299		free(ntoh, M_TEMP);
300		return(error);
301	}
302
303	if (ntoh->ntoh_vers != NDIS_TASK_OFFLOAD_VERSION) {
304		free(ntoh, M_TEMP);
305		return(EINVAL);
306	}
307
308	nto = (ndis_task_offload *)((char *)ntoh +
309	    ntoh->ntoh_offset_firsttask);
310
311	while (1) {
312		switch (nto->nto_task) {
313		case NDIS_TASK_TCPIP_CSUM:
314			nttc = (ndis_task_tcpip_csum *)nto->nto_taskbuf;
315			break;
316		/* Don't handle these yet. */
317		case NDIS_TASK_IPSEC:
318		case NDIS_TASK_TCP_LARGESEND:
319		default:
320			break;
321		}
322		if (nto->nto_offset_nexttask == 0)
323			break;
324		nto = (ndis_task_offload *)((char *)nto +
325		    nto->nto_offset_nexttask);
326	}
327
328	if (nttc == NULL) {
329		free(ntoh, M_TEMP);
330		return(ENOENT);
331	}
332
333	sc->ndis_v4tx = nttc->nttc_v4tx;
334	sc->ndis_v4rx = nttc->nttc_v4rx;
335
336	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_IP_CSUM)
337		sc->ndis_hwassist |= CSUM_IP;
338	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
339		sc->ndis_hwassist |= CSUM_TCP;
340	if (nttc->nttc_v4tx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
341		sc->ndis_hwassist |= CSUM_UDP;
342
343	if (sc->ndis_hwassist)
344		ifp->if_capabilities |= IFCAP_TXCSUM;
345
346	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_IP_CSUM)
347		ifp->if_capabilities |= IFCAP_RXCSUM;
348	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_TCP_CSUM)
349		ifp->if_capabilities |= IFCAP_RXCSUM;
350	if (nttc->nttc_v4rx & NDIS_TCPSUM_FLAGS_UDP_CSUM)
351		ifp->if_capabilities |= IFCAP_RXCSUM;
352
353	free(ntoh, M_TEMP);
354	return(0);
355}
356
357/*
358 * Attach the interface. Allocate softc structures, do ifmedia
359 * setup and ethernet/BPF attach.
360 */
361int
362ndis_attach(dev)
363	device_t		dev;
364{
365	u_char			eaddr[ETHER_ADDR_LEN];
366	struct ndis_softc	*sc;
367	struct ifnet		*ifp = NULL;
368	void			*img;
369	int			error = 0, len;
370	int			i;
371
372	sc = device_get_softc(dev);
373
374	mtx_init(&sc->ndis_mtx, "ndis softc lock",
375	    MTX_NETWORK_LOCK, MTX_DEF);
376	mtx_init(&sc->ndis_intrmtx,
377	    "ndis irq lock", MTX_NETWORK_LOCK, MTX_DEF);
378
379        /*
380	 * Hook interrupt early, since calling the driver's
381	 * init routine may trigger an interrupt.
382	 */
383
384	error = bus_setup_intr(dev, sc->ndis_irq, INTR_TYPE_NET | INTR_MPSAFE,
385	    ndis_intr, sc, &sc->ndis_intrhand);
386
387	if (error) {
388		device_printf(dev, "couldn't set up irq\n");
389		goto fail;
390	}
391
392	if (sc->ndis_iftype == PCMCIABus) {
393		error = ndis_alloc_amem(sc);
394		if (error) {
395			device_printf(dev, "failed to allocate "
396			    "attribute memory\n");
397			goto fail;
398		}
399	}
400
401	sc->ndis_regvals = ndis_regvals;
402
403#if __FreeBSD_version < 502113
404	sysctl_ctx_init(&sc->ndis_ctx);
405
406#endif
407	/* Create sysctl registry nodes */
408	ndis_create_sysctls(sc);
409
410	/* Set up driver image in memory. */
411	img = drv_data;
412	ndis_load_driver((vm_offset_t)img, sc);
413
414	/* Tell the user what version of the API the driver is using. */
415	device_printf(dev, "NDIS API version: %d.%d\n",
416	    sc->ndis_chars.nmc_version_major,
417	    sc->ndis_chars.nmc_version_minor);
418
419	/* Do resource conversion. */
420	ndis_convert_res(sc);
421
422	/* Install our RX and TX interrupt handlers. */
423	sc->ndis_block.nmb_senddone_func = ndis_txeof;
424	sc->ndis_block.nmb_pktind_func = ndis_rxeof;
425
426	/* Call driver's init routine. */
427	if (ndis_init_nic(sc)) {
428		device_printf (dev, "init handler failed\n");
429		error = ENXIO;
430		goto fail;
431	}
432
433	/*
434	 * Get station address from the driver.
435	 */
436	len = sizeof(eaddr);
437	ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
438
439	bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
440
441	/*
442	 * Figure out if we're allowed to use multipacket sends
443	 * with this driver, and if so, how many.
444	 */
445
446	if (sc->ndis_chars.nmc_sendsingle_func &&
447	    sc->ndis_chars.nmc_sendmulti_func == NULL) {
448		sc->ndis_maxpkts = 1;
449	} else {
450		len = sizeof(sc->ndis_maxpkts);
451		ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
452		    &sc->ndis_maxpkts, &len);
453	}
454
455	sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
456	    sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
457
458	sc->ndis_txpending = sc->ndis_maxpkts;
459
460	sc->ndis_oidcnt = 0;
461	/* Get supported oid list. */
462	ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt);
463
464	/* If the NDIS module requested scatter/gather, init maps. */
465	if (sc->ndis_sc)
466		ndis_init_dma(sc);
467
468	/*
469	 * See if the OID_802_11_CONFIGURATION OID is
470	 * supported by this driver. If it is, then this an 802.11
471	 * wireless driver, and we should set up media for wireless.
472	 */
473	for (i = 0; i < sc->ndis_oidcnt; i++) {
474		if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
475			sc->ndis_80211++;
476			break;
477		}
478	}
479
480	/* Check for task offload support. */
481	ndis_probe_offload(sc);
482
483	ifp = &sc->arpcom.ac_if;
484	ifp->if_softc = sc;
485	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
486	ifp->if_mtu = ETHERMTU;
487	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
488	ifp->if_ioctl = ndis_ioctl;
489	ifp->if_start = ndis_start;
490	ifp->if_watchdog = ndis_watchdog;
491	ifp->if_init = ndis_init;
492	ifp->if_baudrate = 10000000;
493#if __FreeBSD_version < 502114
494	ifp->if_snd.ifq_maxlen = 50;
495#else
496	IFQ_SET_MAXLEN(&ifp->if_snd, 50);
497	ifp->if_snd.ifq_drv_maxlen = 25;
498	IFQ_SET_READY(&ifp->if_snd);
499#endif
500	ifp->if_capenable = ifp->if_capabilities;
501	ifp->if_hwassist = sc->ndis_hwassist;
502
503	/* Do media setup */
504	if (sc->ndis_80211) {
505		struct ieee80211com	*ic = (void *)ifp;
506		ndis_80211_rates_ex	rates;
507		struct ndis_80211_nettype_list *ntl;
508		uint32_t		arg;
509		int			r;
510
511	        ic->ic_phytype = IEEE80211_T_DS;
512		ic->ic_opmode = IEEE80211_M_STA;
513		ic->ic_caps = IEEE80211_C_IBSS;
514		ic->ic_state = IEEE80211_S_ASSOC;
515		ic->ic_modecaps = (1<<IEEE80211_MODE_AUTO);
516		len = 0;
517		r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
518		    NULL, &len);
519		if (r != ENOSPC)
520			goto nonettypes;
521		ntl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
522		r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
523		    ntl, &len);
524		if (r != 0) {
525			free(ntl, M_DEVBUF);
526			goto nonettypes;
527		}
528
529		for (i = 0; i < ntl->ntl_items; i++) {
530			switch (ntl->ntl_type[i]) {
531			case NDIS_80211_NETTYPE_11FH:
532			case NDIS_80211_NETTYPE_11DS:
533				ic->ic_modecaps |= (1<<IEEE80211_MODE_11B);
534				break;
535			case NDIS_80211_NETTYPE_11OFDM5:
536				ic->ic_modecaps |= (1<<IEEE80211_MODE_11A);
537				break;
538			case NDIS_80211_NETTYPE_11OFDM24:
539				ic->ic_modecaps |= (1<<IEEE80211_MODE_11G);
540				break;
541			default:
542				break;
543			}
544		}
545		free(ntl, M_DEVBUF);
546nonettypes:
547		len = sizeof(rates);
548		bzero((char *)&rates, len);
549		r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
550		    (void *)rates, &len);
551		if (r)
552			device_printf (dev, "get rates failed: 0x%x\n", r);
553		/*
554		 * Since the supported rates only up to 8 can be supported,
555		 * if this is not 802.11b we're just going to be faking it
556		 * all up to heck.
557		 */
558
559#define TESTSETRATE(x, y)						\
560	do {								\
561		int			i;				\
562		for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) {	\
563			if (ic->ic_sup_rates[x].rs_rates[i] == (y))	\
564				break;					\
565		}							\
566		if (i == ic->ic_sup_rates[x].rs_nrates) {		\
567			ic->ic_sup_rates[x].rs_rates[i] = (y);		\
568			ic->ic_sup_rates[x].rs_nrates++;		\
569		}							\
570	} while (0)
571
572#define SETRATE(x, y)	\
573	ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y)
574#define INCRATE(x)	\
575	ic->ic_sup_rates[x].rs_nrates++
576
577		ic->ic_curmode = IEEE80211_MODE_AUTO;
578		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A))
579			ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
580		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B))
581			ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
582		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G))
583			ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
584		for (i = 0; i < len; i++) {
585			switch (rates[i] & IEEE80211_RATE_VAL) {
586			case 2:
587			case 4:
588			case 11:
589			case 10:
590			case 22:
591				if (!(ic->ic_modecaps &
592				    (1<<IEEE80211_MODE_11B))) {
593					/* Lazy-init 802.11b. */
594					ic->ic_modecaps |=
595					    (1<<IEEE80211_MODE_11B);
596					ic->ic_sup_rates[IEEE80211_MODE_11B].
597					    rs_nrates = 0;
598				}
599				SETRATE(IEEE80211_MODE_11B, rates[i]);
600				INCRATE(IEEE80211_MODE_11B);
601				break;
602			default:
603				if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) {
604					SETRATE(IEEE80211_MODE_11A, rates[i]);
605					INCRATE(IEEE80211_MODE_11A);
606				}
607				if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
608					SETRATE(IEEE80211_MODE_11G, rates[i]);
609					INCRATE(IEEE80211_MODE_11G);
610				}
611				break;
612			}
613		}
614
615		/*
616		 * If the hardware supports 802.11g, it most
617		 * likely supports 802.11b and all of the
618		 * 802.11b and 802.11g speeds, so maybe we can
619		 * just cheat here.  Just how in the heck do
620		 * we detect turbo modes, though?
621		 */
622		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) {
623			TESTSETRATE(IEEE80211_MODE_11B,
624			    IEEE80211_RATE_BASIC|2);
625			TESTSETRATE(IEEE80211_MODE_11B,
626			    IEEE80211_RATE_BASIC|4);
627			TESTSETRATE(IEEE80211_MODE_11B,
628			    IEEE80211_RATE_BASIC|11);
629			TESTSETRATE(IEEE80211_MODE_11B,
630			    IEEE80211_RATE_BASIC|22);
631		}
632		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
633			TESTSETRATE(IEEE80211_MODE_11G, 47);
634			TESTSETRATE(IEEE80211_MODE_11G, 72);
635			TESTSETRATE(IEEE80211_MODE_11G, 96);
636			TESTSETRATE(IEEE80211_MODE_11G, 108);
637		}
638		if (ic->ic_modecaps & (1<<IEEE80211_MODE_11A)) {
639			TESTSETRATE(IEEE80211_MODE_11A, 47);
640			TESTSETRATE(IEEE80211_MODE_11A, 72);
641			TESTSETRATE(IEEE80211_MODE_11A, 96);
642			TESTSETRATE(IEEE80211_MODE_11A, 108);
643		}
644#undef SETRATE
645#undef INCRATE
646		/*
647		 * Taking yet more guesses here.
648		 */
649		for (i = 1; i < IEEE80211_CHAN_MAX; i++) {
650			int chanflag = 0;
651
652			if (ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates)
653				chanflag |= IEEE80211_CHAN_G;
654			if (i <= 14)
655				chanflag |= IEEE80211_CHAN_B;
656			if (ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates &&
657			    i > 14)
658				chanflag = IEEE80211_CHAN_A;
659			if (chanflag == 0)
660				break;
661			ic->ic_channels[i].ic_freq =
662			    ieee80211_ieee2mhz(i, chanflag);
663			ic->ic_channels[i].ic_flags = chanflag;
664		}
665
666		i = sizeof(arg);
667		r = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &i);
668		if (arg != NDIS_80211_WEPSTAT_NOTSUPPORTED)
669			ic->ic_caps |= IEEE80211_C_WEP;
670		i = sizeof(arg);
671		r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
672		if (r == 0)
673			ic->ic_caps |= IEEE80211_C_PMGT;
674		bcopy(eaddr, &ic->ic_myaddr, sizeof(eaddr));
675		ieee80211_ifattach(ifp);
676		ieee80211_media_init(ifp, ieee80211_media_change,
677		    ndis_media_status);
678		ic->ic_ibss_chan = IEEE80211_CHAN_ANYC;
679		ic->ic_bss->ni_chan = ic->ic_ibss_chan;
680	} else {
681		ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
682		    ndis_ifmedia_sts);
683		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
684		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
685		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
686		ifmedia_add(&sc->ifmedia,
687		    IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
688		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
689		ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
690		ether_ifattach(ifp, eaddr);
691	}
692
693	/* Override the status handler so we can detect link changes. */
694	sc->ndis_block.nmb_status_func = ndis_linksts;
695	sc->ndis_block.nmb_statusdone_func = ndis_linksts_done;
696fail:
697	if (error)
698		ndis_detach(dev);
699	else
700		/* We're done talking to the NIC for now; halt it. */
701		ndis_halt_nic(sc);
702
703	return(error);
704}
705
706/*
707 * Shutdown hardware and free up resources. This can be called any
708 * time after the mutex has been initialized. It is called in both
709 * the error case in attach and the normal detach case so it needs
710 * to be careful about only freeing resources that have actually been
711 * allocated.
712 */
713int
714ndis_detach(dev)
715	device_t		dev;
716{
717	struct ndis_softc	*sc;
718	struct ifnet		*ifp;
719
720	sc = device_get_softc(dev);
721	KASSERT(mtx_initialized(&sc->ndis_mtx),
722	    ("ndis mutex not initialized"));
723	KASSERT(mtx_initialized(&sc->ndis_intrmtx),
724	    ("ndis interrupt mutex not initialized"));
725	NDIS_LOCK(sc);
726	ifp = &sc->arpcom.ac_if;
727	ifp->if_flags &= ~IFF_UP;
728
729	if (device_is_attached(dev)) {
730		NDIS_UNLOCK(sc);
731		ndis_stop(sc);
732		if (sc->ndis_80211)
733			ieee80211_ifdetach(ifp);
734		else
735			ether_ifdetach(ifp);
736	} else
737		NDIS_UNLOCK(sc);
738
739	bus_generic_detach(dev);
740
741	if (sc->ndis_intrhand)
742		bus_teardown_intr(dev, sc->ndis_irq, sc->ndis_intrhand);
743	if (sc->ndis_irq)
744		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq);
745	if (sc->ndis_res_io)
746		bus_release_resource(dev, SYS_RES_IOPORT,
747		    sc->ndis_io_rid, sc->ndis_res_io);
748	if (sc->ndis_res_mem)
749		bus_release_resource(dev, SYS_RES_MEMORY,
750		    sc->ndis_mem_rid, sc->ndis_res_mem);
751	if (sc->ndis_res_altmem)
752		bus_release_resource(dev, SYS_RES_MEMORY,
753		    sc->ndis_altmem_rid, sc->ndis_res_altmem);
754
755	if (sc->ndis_iftype == PCMCIABus)
756		ndis_free_amem(sc);
757
758	if (sc->ndis_sc)
759		ndis_destroy_dma(sc);
760
761	if (sc->ndis_txarray)
762		free(sc->ndis_txarray, M_DEVBUF);
763
764	if (!sc->ndis_80211)
765		ifmedia_removeall(&sc->ifmedia);
766
767	ndis_unload_driver((void *)ifp);
768
769	if (sc->ndis_iftype == PCIBus)
770		bus_dma_tag_destroy(sc->ndis_parent_tag);
771
772#if __FreeBSD_version < 502113
773	sysctl_ctx_free(&sc->ndis_ctx);
774#endif
775
776	mtx_destroy(&sc->ndis_mtx);
777	mtx_destroy(&sc->ndis_intrmtx);
778
779	return(0);
780}
781
782int
783ndis_suspend(dev)
784	device_t		dev;
785{
786	struct ndis_softc	*sc;
787	struct ifnet		*ifp;
788
789	sc = device_get_softc(dev);
790	ifp = &sc->arpcom.ac_if;
791
792#ifdef notdef
793	if (NDIS_INITIALIZED(sc))
794        	ndis_stop(sc);
795#endif
796
797	return(0);
798}
799
800int
801ndis_resume(dev)
802	device_t		dev;
803{
804	struct ndis_softc	*sc;
805	struct ifnet		*ifp;
806
807	sc = device_get_softc(dev);
808	ifp = &sc->arpcom.ac_if;
809
810	if (NDIS_INITIALIZED(sc))
811        	ndis_init(sc);
812
813	return(0);
814}
815
816/*
817 * A frame has been uploaded: pass the resulting mbuf chain up to
818 * the higher level protocols.
819 *
820 * When handling received NDIS packets, the 'status' field in the
821 * out-of-band portion of the ndis_packet has special meaning. In the
822 * most common case, the underlying NDIS driver will set this field
823 * to NDIS_STATUS_SUCCESS, which indicates that it's ok for us to
824 * take posession of it. We then change the status field to
825 * NDIS_STATUS_PENDING to tell the driver that we now own the packet,
826 * and that we will return it at some point in the future via the
827 * return packet handler.
828 *
829 * If the driver hands us a packet with a status of NDIS_STATUS_RESOURCES,
830 * this means the driver is running out of packet/buffer resources and
831 * wants to maintain ownership of the packet. In this case, we have to
832 * copy the packet data into local storage and let the driver keep the
833 * packet.
834 */
835__stdcall static void
836ndis_rxeof(adapter, packets, pktcnt)
837	ndis_handle		adapter;
838	ndis_packet		**packets;
839	uint32_t		pktcnt;
840{
841	struct ndis_softc	*sc;
842	ndis_miniport_block	*block;
843	ndis_packet		*p;
844	uint32_t		s;
845	ndis_tcpip_csum		*csum;
846	struct ifnet		*ifp;
847	struct mbuf		*m0, *m;
848	int			i;
849
850	block = (ndis_miniport_block *)adapter;
851	sc = (struct ndis_softc *)(block->nmb_ifp);
852	ifp = block->nmb_ifp;
853
854	for (i = 0; i < pktcnt; i++) {
855		p = packets[i];
856		/* Stash the softc here so ptom can use it. */
857		p->np_softc = sc;
858		if (ndis_ptom(&m0, p)) {
859			device_printf (sc->ndis_dev, "ptom failed\n");
860			if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS)
861				ndis_return_packet(sc, p);
862		} else {
863			if (p->np_oob.npo_status == NDIS_STATUS_RESOURCES) {
864				m = m_dup(m0, M_DONTWAIT);
865				/*
866				 * NOTE: we want to destroy the mbuf here, but
867				 * we don't actually want to return it to the
868				 * driver via the return packet handler. By
869				 * bumping np_refcnt, we can prevent the
870				 * ndis_return_packet() routine from actually
871				 * doing anything.
872				 */
873				p->np_refcnt++;
874				m_freem(m0);
875				if (m == NULL)
876					ifp->if_ierrors++;
877				else
878					m0 = m;
879			} else
880				p->np_oob.npo_status = NDIS_STATUS_PENDING;
881			m0->m_pkthdr.rcvif = ifp;
882			ifp->if_ipackets++;
883
884			/* Deal with checksum offload. */
885
886			if (ifp->if_capenable & IFCAP_RXCSUM &&
887			    p->np_ext.npe_info[ndis_tcpipcsum_info] != NULL) {
888				s = (uintptr_t)
889			 	    p->np_ext.npe_info[ndis_tcpipcsum_info];
890				csum = (ndis_tcpip_csum *)&s;
891				if (csum->u.ntc_rxflags &
892				    NDIS_RXCSUM_IP_PASSED)
893					m0->m_pkthdr.csum_flags |=
894					    CSUM_IP_CHECKED|CSUM_IP_VALID;
895				if (csum->u.ntc_rxflags &
896				    (NDIS_RXCSUM_TCP_PASSED |
897				    NDIS_RXCSUM_UDP_PASSED)) {
898					m0->m_pkthdr.csum_flags |=
899					    CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
900					m0->m_pkthdr.csum_data = 0xFFFF;
901				}
902			}
903
904			(*ifp->if_input)(ifp, m0);
905		}
906	}
907
908	return;
909}
910
911/*
912 * A frame was downloaded to the chip. It's safe for us to clean up
913 * the list buffers.
914 */
915__stdcall static void
916ndis_txeof(adapter, packet, status)
917	ndis_handle		adapter;
918	ndis_packet		*packet;
919	ndis_status		status;
920
921{
922	struct ndis_softc	*sc;
923	ndis_miniport_block	*block;
924	struct ifnet		*ifp;
925	int			idx;
926	struct mbuf		*m;
927
928	block = (ndis_miniport_block *)adapter;
929	sc = (struct ndis_softc *)block->nmb_ifp;
930	ifp = block->nmb_ifp;
931
932	m = packet->np_m0;
933	idx = packet->np_txidx;
934	if (sc->ndis_sc)
935		bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
936
937	ndis_free_packet(packet);
938	m_freem(m);
939
940	NDIS_LOCK(sc);
941	sc->ndis_txarray[idx] = NULL;
942	sc->ndis_txpending++;
943
944	if (status == NDIS_STATUS_SUCCESS)
945		ifp->if_opackets++;
946	else
947		ifp->if_oerrors++;
948	ifp->if_timer = 0;
949	ifp->if_flags &= ~IFF_OACTIVE;
950	NDIS_UNLOCK(sc);
951
952	ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
953
954	return;
955}
956
957__stdcall static void
958ndis_linksts(adapter, status, sbuf, slen)
959	ndis_handle		adapter;
960	ndis_status		status;
961	void			*sbuf;
962	uint32_t		slen;
963{
964	ndis_miniport_block	*block;
965
966	block = adapter;
967	block->nmb_getstat = status;
968
969	return;
970}
971
972__stdcall static void
973ndis_linksts_done(adapter)
974	ndis_handle		adapter;
975{
976	ndis_miniport_block	*block;
977	struct ndis_softc	*sc;
978	struct ifnet		*ifp;
979
980	block = adapter;
981	ifp = block->nmb_ifp;
982	sc = ifp->if_softc;
983
984	NDIS_LOCK(sc);
985	if (!NDIS_INITIALIZED(sc)) {
986		NDIS_UNLOCK(sc);
987		return;
988	}
989
990	switch (block->nmb_getstat) {
991	case NDIS_STATUS_MEDIA_CONNECT:
992		ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
993		ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
994		break;
995	case NDIS_STATUS_MEDIA_DISCONNECT:
996		if (sc->ndis_link)
997			ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
998		break;
999	default:
1000		break;
1001	}
1002
1003	NDIS_UNLOCK(sc);
1004	return;
1005}
1006
1007static void
1008ndis_intrtask(arg)
1009	void			*arg;
1010{
1011	struct ndis_softc	*sc;
1012	struct ifnet		*ifp;
1013	uint8_t			irql;
1014
1015	sc = arg;
1016	ifp = &sc->arpcom.ac_if;
1017
1018	irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL);
1019	ndis_intrhand(sc);
1020	FASTCALL1(hal_lower_irql, irql);
1021	mtx_lock(&sc->ndis_intrmtx);
1022	ndis_enable_intr(sc);
1023	mtx_unlock(&sc->ndis_intrmtx);
1024
1025	return;
1026}
1027
1028static void
1029ndis_intr(arg)
1030	void			*arg;
1031{
1032	struct ndis_softc	*sc;
1033	struct ifnet		*ifp;
1034	int			is_our_intr = 0;
1035	int			call_isr = 0;
1036
1037	sc = arg;
1038	ifp = &sc->arpcom.ac_if;
1039
1040	if (sc->ndis_block.nmb_miniportadapterctx == NULL)
1041		return;
1042
1043	mtx_lock(&sc->ndis_intrmtx);
1044	if (sc->ndis_block.nmb_interrupt->ni_isrreq == TRUE)
1045		ndis_isr(sc, &is_our_intr, &call_isr);
1046	else {
1047		ndis_disable_intr(sc);
1048		call_isr = 1;
1049	}
1050	mtx_unlock(&sc->ndis_intrmtx);
1051
1052	if ((is_our_intr || call_isr))
1053		ndis_sched(ndis_intrtask, ifp, NDIS_SWI);
1054
1055	return;
1056}
1057
1058static void
1059ndis_tick(xsc)
1060	void			*xsc;
1061{
1062	struct ndis_softc	*sc;
1063
1064	mtx_unlock(&Giant);
1065
1066	sc = xsc;
1067
1068	ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE);
1069	sc->ndis_stat_ch = timeout(ndis_tick, sc, hz *
1070	    sc->ndis_block.nmb_checkforhangsecs);
1071
1072	mtx_lock(&Giant);
1073
1074	return;
1075}
1076
1077static void
1078ndis_ticktask(xsc)
1079	void			*xsc;
1080{
1081	struct ndis_softc	*sc;
1082	__stdcall ndis_checkforhang_handler hangfunc;
1083	uint8_t			rval;
1084	ndis_media_state	linkstate;
1085	int			error, len;
1086
1087	sc = xsc;
1088
1089	hangfunc = sc->ndis_chars.nmc_checkhang_func;
1090
1091	if (hangfunc != NULL) {
1092		rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx);
1093		if (rval == TRUE) {
1094			ndis_reset_nic(sc);
1095			return;
1096		}
1097	}
1098
1099	len = sizeof(linkstate);
1100	error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
1101	    (void *)&linkstate, &len);
1102
1103	NDIS_LOCK(sc);
1104
1105	if (sc->ndis_link == 0 && linkstate == nmc_connected) {
1106		device_printf(sc->ndis_dev, "link up\n");
1107		sc->ndis_link = 1;
1108		NDIS_UNLOCK(sc);
1109		if (sc->ndis_80211)
1110			ndis_getstate_80211(sc);
1111		NDIS_LOCK(sc);
1112#ifdef LINK_STATE_UP
1113		sc->arpcom.ac_if.if_link_state = LINK_STATE_UP;
1114		rt_ifmsg(&(sc->arpcom.ac_if));
1115#endif /* LINK_STATE_UP */
1116	}
1117
1118	if (sc->ndis_link == 1 && linkstate == nmc_disconnected) {
1119		device_printf(sc->ndis_dev, "link down\n");
1120		sc->ndis_link = 0;
1121#ifdef LINK_STATE_DOWN
1122		sc->arpcom.ac_if.if_link_state = LINK_STATE_DOWN;
1123		rt_ifmsg(&(sc->arpcom.ac_if));
1124#endif /* LINK_STATE_DOWN */
1125	}
1126
1127	NDIS_UNLOCK(sc);
1128
1129	return;
1130}
1131
1132static void
1133ndis_map_sclist(arg, segs, nseg, mapsize, error)
1134	void			*arg;
1135	bus_dma_segment_t	*segs;
1136	int			nseg;
1137	bus_size_t		mapsize;
1138	int			error;
1139
1140{
1141	struct ndis_sc_list	*sclist;
1142	int			i;
1143
1144	if (error || arg == NULL)
1145		return;
1146
1147	sclist = arg;
1148
1149	sclist->nsl_frags = nseg;
1150
1151	for (i = 0; i < nseg; i++) {
1152		sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr;
1153		sclist->nsl_elements[i].nse_len = segs[i].ds_len;
1154	}
1155
1156	return;
1157}
1158
1159static void
1160ndis_starttask(arg)
1161	void			*arg;
1162{
1163	struct ifnet		*ifp;
1164
1165	ifp = arg;
1166#if __FreeBSD_version < 502114
1167	if (ifp->if_snd.ifq_head != NULL)
1168#else
1169	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1170#endif
1171		ndis_start(ifp);
1172	return;
1173}
1174
1175/*
1176 * Main transmit routine. To make NDIS drivers happy, we need to
1177 * transform mbuf chains into NDIS packets and feed them to the
1178 * send packet routines. Most drivers allow you to send several
1179 * packets at once (up to the maxpkts limit). Unfortunately, rather
1180 * that accepting them in the form of a linked list, they expect
1181 * a contiguous array of pointers to packets.
1182 *
1183 * For those drivers which use the NDIS scatter/gather DMA mechanism,
1184 * we need to perform busdma work here. Those that use map registers
1185 * will do the mapping themselves on a buffer by buffer basis.
1186 */
1187
1188static void
1189ndis_start(ifp)
1190	struct ifnet		*ifp;
1191{
1192	struct ndis_softc	*sc;
1193	struct mbuf		*m = NULL;
1194	ndis_packet		**p0 = NULL, *p = NULL;
1195	ndis_tcpip_csum		*csum;
1196	int			pcnt = 0;
1197
1198	sc = ifp->if_softc;
1199
1200	NDIS_LOCK(sc);
1201
1202	if (!sc->ndis_link || ifp->if_flags & IFF_OACTIVE) {
1203		NDIS_UNLOCK(sc);
1204		return;
1205	}
1206
1207	p0 = &sc->ndis_txarray[sc->ndis_txidx];
1208
1209	while(sc->ndis_txpending) {
1210#if __FreeBSD_version < 502114
1211		IF_DEQUEUE(&ifp->if_snd, m);
1212#else
1213		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1214#endif
1215		if (m == NULL)
1216			break;
1217
1218		sc->ndis_txarray[sc->ndis_txidx] = NULL;
1219
1220		if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
1221#if __FreeBSD_version >= 502114
1222			IFQ_DRV_PREPEND(&ifp->if_snd, m);
1223#endif
1224			NDIS_UNLOCK(sc);
1225#if __FreeBSD_version < 502114
1226			IF_PREPEND(&ifp->if_snd, m);
1227#endif
1228			return;
1229		}
1230
1231		/*
1232		 * Save pointer to original mbuf
1233		 * so we can free it later.
1234		 */
1235
1236		p = sc->ndis_txarray[sc->ndis_txidx];
1237		p->np_txidx = sc->ndis_txidx;
1238		p->np_m0 = m;
1239		p->np_oob.npo_status = NDIS_STATUS_PENDING;
1240
1241		/*
1242		 * Do scatter/gather processing, if driver requested it.
1243		 */
1244		if (sc->ndis_sc) {
1245			bus_dmamap_load_mbuf(sc->ndis_ttag,
1246			    sc->ndis_tmaps[sc->ndis_txidx], m,
1247			    ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
1248			bus_dmamap_sync(sc->ndis_ttag,
1249			    sc->ndis_tmaps[sc->ndis_txidx],
1250			    BUS_DMASYNC_PREREAD);
1251			p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
1252		}
1253
1254		/* Handle checksum offload. */
1255
1256		if (ifp->if_capenable & IFCAP_TXCSUM &&
1257		    m->m_pkthdr.csum_flags) {
1258			csum = (ndis_tcpip_csum *)
1259				&p->np_ext.npe_info[ndis_tcpipcsum_info];
1260			csum->u.ntc_txflags = NDIS_TXCSUM_DO_IPV4;
1261			if (m->m_pkthdr.csum_flags & CSUM_IP)
1262				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_IP;
1263			if (m->m_pkthdr.csum_flags & CSUM_TCP)
1264				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_TCP;
1265			if (m->m_pkthdr.csum_flags & CSUM_UDP)
1266				csum->u.ntc_txflags |= NDIS_TXCSUM_DO_UDP;
1267			p->np_private.npp_flags = NDIS_PROTOCOL_ID_TCP_IP;
1268		}
1269
1270		NDIS_INC(sc);
1271		sc->ndis_txpending--;
1272
1273		pcnt++;
1274
1275		/*
1276		 * If there's a BPF listener, bounce a copy of this frame
1277		 * to him.
1278		 */
1279
1280		BPF_MTAP(ifp, m);
1281
1282		/*
1283		 * The array that p0 points to must appear contiguous,
1284		 * so we must not wrap past the end of sc->ndis_txarray[].
1285		 * If it looks like we're about to wrap, break out here
1286		 * so the this batch of packets can be transmitted, then
1287		 * wait for txeof to ask us to send the rest.
1288		 */
1289
1290		if (sc->ndis_txidx == 0)
1291			break;
1292	}
1293
1294	if (sc->ndis_txpending == 0)
1295		ifp->if_flags |= IFF_OACTIVE;
1296
1297	/*
1298	 * Set a timeout in case the chip goes out to lunch.
1299	 */
1300	ifp->if_timer = 5;
1301
1302	NDIS_UNLOCK(sc);
1303
1304	if (sc->ndis_maxpkts == 1)
1305		ndis_send_packet(sc, p);
1306	else
1307		ndis_send_packets(sc, p0, pcnt);
1308
1309	return;
1310}
1311
1312static void
1313ndis_init(xsc)
1314	void			*xsc;
1315{
1316	struct ndis_softc	*sc = xsc;
1317	struct ifnet		*ifp = &sc->arpcom.ac_if;
1318	int			i, error;
1319
1320	/*
1321	 * Avoid reintializing the link unnecessarily.
1322	 * This should be dealt with in a better way by
1323	 * fixing the upper layer modules so they don't
1324	 * call ifp->if_init() quite as often.
1325	 */
1326	if (sc->ndis_link && sc->ndis_skip)
1327		return;
1328
1329	/*
1330	 * Cancel pending I/O and free all RX/TX buffers.
1331	 */
1332	ndis_stop(sc);
1333	if (ndis_init_nic(sc))
1334		return;
1335
1336	/* Init our MAC address */
1337
1338	/* Program the packet filter */
1339
1340	sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
1341
1342	if (ifp->if_flags & IFF_BROADCAST)
1343		sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
1344
1345	if (ifp->if_flags & IFF_PROMISC)
1346		sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
1347
1348	i = sizeof(sc->ndis_filter);
1349
1350	error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
1351	    &sc->ndis_filter, &i);
1352
1353	if (error)
1354		device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
1355
1356	/*
1357	 * Program the multicast filter, if necessary.
1358	 */
1359	ndis_setmulti(sc);
1360
1361	/* Setup task offload. */
1362	ndis_set_offload(sc);
1363
1364	/* Enable interrupts. */
1365	ndis_enable_intr(sc);
1366
1367	if (sc->ndis_80211)
1368		ndis_setstate_80211(sc);
1369
1370	NDIS_LOCK(sc);
1371
1372	sc->ndis_txidx = 0;
1373	sc->ndis_txpending = sc->ndis_maxpkts;
1374	sc->ndis_link = 0;
1375
1376	ifp->if_flags |= IFF_RUNNING;
1377	ifp->if_flags &= ~IFF_OACTIVE;
1378
1379	NDIS_UNLOCK(sc);
1380
1381	/*
1382	 * Some drivers don't set this value. The NDIS spec says
1383	 * the default checkforhang timeout is "approximately 2
1384	 * seconds." We use 3 seconds, because it seems for some
1385	 * drivers, exactly 2 seconds is too fast.
1386	 */
1387
1388	if (sc->ndis_block.nmb_checkforhangsecs == 0)
1389		sc->ndis_block.nmb_checkforhangsecs = 3;
1390
1391	sc->ndis_stat_ch = timeout(ndis_tick, sc,
1392	    hz * sc->ndis_block.nmb_checkforhangsecs);
1393
1394	return;
1395}
1396
1397/*
1398 * Set media options.
1399 */
1400static int
1401ndis_ifmedia_upd(ifp)
1402	struct ifnet		*ifp;
1403{
1404	struct ndis_softc		*sc;
1405
1406	sc = ifp->if_softc;
1407
1408	if (NDIS_INITIALIZED(sc))
1409		ndis_init(sc);
1410
1411	return(0);
1412}
1413
1414/*
1415 * Report current media status.
1416 */
1417static void
1418ndis_ifmedia_sts(ifp, ifmr)
1419	struct ifnet		*ifp;
1420	struct ifmediareq	*ifmr;
1421{
1422	struct ndis_softc	*sc;
1423	uint32_t		media_info;
1424	ndis_media_state	linkstate;
1425	int			error, len;
1426
1427	ifmr->ifm_status = IFM_AVALID;
1428	ifmr->ifm_active = IFM_ETHER;
1429	sc = ifp->if_softc;
1430
1431	if (!NDIS_INITIALIZED(sc))
1432		return;
1433
1434	len = sizeof(linkstate);
1435	error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
1436	    (void *)&linkstate, &len);
1437
1438	len = sizeof(media_info);
1439	error = ndis_get_info(sc, OID_GEN_LINK_SPEED,
1440	    (void *)&media_info, &len);
1441
1442	if (linkstate == nmc_connected)
1443		ifmr->ifm_status |= IFM_ACTIVE;
1444
1445	switch(media_info) {
1446	case 100000:
1447		ifmr->ifm_active |= IFM_10_T;
1448		break;
1449	case 1000000:
1450		ifmr->ifm_active |= IFM_100_TX;
1451		break;
1452	case 10000000:
1453		ifmr->ifm_active |= IFM_1000_T;
1454		break;
1455	default:
1456		device_printf(sc->ndis_dev, "unknown speed: %d\n", media_info);
1457		break;
1458	}
1459
1460	return;
1461}
1462
1463static void
1464ndis_setstate_80211(sc)
1465	struct ndis_softc	*sc;
1466{
1467	struct ieee80211com	*ic;
1468	ndis_80211_ssid		ssid;
1469	ndis_80211_config	config;
1470	ndis_80211_wep		wep;
1471	int			i, rval = 0, len;
1472	uint32_t		arg;
1473	struct ifnet		*ifp;
1474
1475	ic = &sc->ic;
1476	ifp = &sc->ic.ic_ac.ac_if;
1477
1478	if (!NDIS_INITIALIZED(sc))
1479		return;
1480
1481	/* Set network infrastructure mode. */
1482
1483	len = sizeof(arg);
1484	if (ic->ic_opmode == IEEE80211_M_IBSS)
1485		arg = NDIS_80211_NET_INFRA_IBSS;
1486	else
1487		arg = NDIS_80211_NET_INFRA_BSS;
1488
1489	rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
1490
1491	if (rval)
1492		device_printf (sc->ndis_dev, "set infra failed: %d\n", rval);
1493
1494	/* Set WEP */
1495
1496#ifdef IEEE80211_F_WEPON
1497	if (ic->ic_flags & IEEE80211_F_WEPON) {
1498#else
1499	if (ic->ic_wep_mode >= IEEE80211_WEP_ON) {
1500#endif
1501		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1502			if (ic->ic_nw_keys[i].wk_len) {
1503				bzero((char *)&wep, sizeof(wep));
1504				wep.nw_keylen = ic->ic_nw_keys[i].wk_len;
1505#ifdef notdef
1506				/* 5 and 13 are the only valid key lengths */
1507				if (ic->ic_nw_keys[i].wk_len < 5)
1508					wep.nw_keylen = 5;
1509				else if (ic->ic_nw_keys[i].wk_len > 5 &&
1510				     ic->ic_nw_keys[i].wk_len < 13)
1511					wep.nw_keylen = 13;
1512#endif
1513				wep.nw_keyidx = i;
1514				wep.nw_length = (sizeof(uint32_t) * 3)
1515				    + wep.nw_keylen;
1516				if (i == ic->ic_wep_txkey)
1517					wep.nw_keyidx |= NDIS_80211_WEPKEY_TX;
1518				bcopy(ic->ic_nw_keys[i].wk_key,
1519				    wep.nw_keydata, wep.nw_length);
1520				len = sizeof(wep);
1521				rval = ndis_set_info(sc,
1522				    OID_802_11_ADD_WEP, &wep, &len);
1523				if (rval)
1524					device_printf(sc->ndis_dev,
1525					    "set wepkey failed: %d\n", rval);
1526			}
1527		}
1528		arg = NDIS_80211_WEPSTAT_ENABLED;
1529		len = sizeof(arg);
1530		rval = ndis_set_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
1531		if (rval)
1532			device_printf(sc->ndis_dev,
1533			    "enable WEP failed: %d\n", rval);
1534#ifndef IEEE80211_F_WEPON
1535		if (ic->ic_wep_mode != IEEE80211_WEP_8021X &&
1536		    ic->ic_wep_mode != IEEE80211_WEP_ON)
1537			arg = NDIS_80211_PRIVFILT_ACCEPTALL;
1538		else
1539#endif
1540			arg = NDIS_80211_PRIVFILT_8021XWEP;
1541		len = sizeof(arg);
1542		rval = ndis_set_info(sc, OID_802_11_PRIVACY_FILTER, &arg, &len);
1543#ifdef IEEE80211_WEP_8021X /*IEEE80211_F_WEPON*/
1544		/* Accept that we only have "shared" and 802.1x modes. */
1545		if (rval == 0) {
1546			if (arg == NDIS_80211_PRIVFILT_ACCEPTALL)
1547				ic->ic_wep_mode = IEEE80211_WEP_MIXED;
1548			else
1549				ic->ic_wep_mode = IEEE80211_WEP_8021X;
1550		}
1551#endif
1552		arg = NDIS_80211_AUTHMODE_OPEN;
1553	} else {
1554		arg = NDIS_80211_WEPSTAT_DISABLED;
1555		len = sizeof(arg);
1556		ndis_set_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
1557		arg = NDIS_80211_AUTHMODE_OPEN;
1558	}
1559
1560	len = sizeof(arg);
1561	rval = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
1562
1563#ifdef notyet
1564	if (rval)
1565		device_printf (sc->ndis_dev, "set auth failed: %d\n", rval);
1566#endif
1567
1568#ifdef notyet
1569	/* Set network type. */
1570
1571	arg = 0;
1572
1573	switch (ic->ic_curmode) {
1574	case IEEE80211_MODE_11A:
1575		arg = NDIS_80211_NETTYPE_11OFDM5;
1576		break;
1577	case IEEE80211_MODE_11B:
1578		arg = NDIS_80211_NETTYPE_11DS;
1579		break;
1580	case IEEE80211_MODE_11G:
1581		arg = NDIS_80211_NETTYPE_11OFDM24;
1582		break;
1583	default:
1584		device_printf(sc->ndis_dev, "unknown mode: %d\n",
1585		    ic->ic_curmode);
1586	}
1587
1588	if (arg) {
1589		len = sizeof(arg);
1590		rval = ndis_set_info(sc, OID_802_11_NETWORK_TYPE_IN_USE,
1591		    &arg, &len);
1592		if (rval)
1593			device_printf (sc->ndis_dev,
1594			    "set nettype failed: %d\n", rval);
1595	}
1596#endif
1597
1598	len = sizeof(config);
1599	bzero((char *)&config, len);
1600	config.nc_length = len;
1601	config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
1602	rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
1603
1604	/*
1605	 * Some drivers expect us to initialize these values, so
1606	 * provide some defaults.
1607	 */
1608	if (config.nc_beaconperiod == 0)
1609		config.nc_beaconperiod = 100;
1610	if (config.nc_atimwin == 0)
1611		config.nc_atimwin = 100;
1612	if (config.nc_fhconfig.ncf_dwelltime == 0)
1613		config.nc_fhconfig.ncf_dwelltime = 200;
1614
1615	if (rval == 0 && ic->ic_ibss_chan != IEEE80211_CHAN_ANYC) {
1616		int chan, chanflag;
1617
1618		chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
1619		chanflag = config.nc_dsconfig > 2500000 ? IEEE80211_CHAN_2GHZ :
1620		    IEEE80211_CHAN_5GHZ;
1621		if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
1622			config.nc_dsconfig =
1623			    ic->ic_ibss_chan->ic_freq * 1000;
1624			ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1625			len = sizeof(config);
1626			config.nc_length = len;
1627			config.nc_fhconfig.ncf_length =
1628			    sizeof(ndis_80211_config_fh);
1629			rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
1630			    &config, &len);
1631			if (rval)
1632				device_printf(sc->ndis_dev, "couldn't change "
1633				    "DS config to %ukHz: %d\n",
1634				    config.nc_dsconfig, rval);
1635		}
1636	} else if (rval)
1637		device_printf(sc->ndis_dev, "couldn't retrieve "
1638		    "channel info: %d\n", rval);
1639
1640	/* Set SSID -- always do this last. */
1641
1642	len = sizeof(ssid);
1643	bzero((char *)&ssid, len);
1644	ssid.ns_ssidlen = ic->ic_des_esslen;
1645	if (ssid.ns_ssidlen == 0) {
1646		ssid.ns_ssidlen = 1;
1647	} else
1648		bcopy(ic->ic_des_essid, ssid.ns_ssid, ssid.ns_ssidlen);
1649	rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
1650
1651	if (rval)
1652		device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
1653
1654	return;
1655}
1656
1657static void
1658ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1659{
1660        struct ieee80211com *ic = (void *)ifp;
1661        struct ieee80211_node *ni = NULL;
1662
1663        imr->ifm_status = IFM_AVALID;
1664        imr->ifm_active = IFM_IEEE80211;
1665        if (ic->ic_state == IEEE80211_S_RUN)
1666                imr->ifm_status |= IFM_ACTIVE;
1667        imr->ifm_active |= IFM_AUTO;
1668        switch (ic->ic_opmode) {
1669        case IEEE80211_M_STA:
1670                ni = ic->ic_bss;
1671                /* calculate rate subtype */
1672                imr->ifm_active |= ieee80211_rate2media(ic,
1673                        ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
1674                break;
1675        case IEEE80211_M_IBSS:
1676                ni = ic->ic_bss;
1677                /* calculate rate subtype */
1678                imr->ifm_active |= ieee80211_rate2media(ic,
1679                        ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
1680                imr->ifm_active |= IFM_IEEE80211_ADHOC;
1681                break;
1682        case IEEE80211_M_AHDEMO:
1683                /* should not come here */
1684                break;
1685        case IEEE80211_M_HOSTAP:
1686                imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1687                break;
1688        case IEEE80211_M_MONITOR:
1689                imr->ifm_active |= IFM_IEEE80211_MONITOR;
1690                break;
1691        }
1692        switch (ic->ic_curmode) {
1693        case IEEE80211_MODE_11A:
1694                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A);
1695                break;
1696        case IEEE80211_MODE_11B:
1697                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B);
1698                break;
1699        case IEEE80211_MODE_11G:
1700                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G);
1701                break;
1702        case IEEE80211_MODE_TURBO:
1703                imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A)
1704                                |  IFM_IEEE80211_TURBO;
1705                break;
1706        }
1707}
1708
1709static int
1710ndis_get_assoc(sc, assoc)
1711	struct ndis_softc	*sc;
1712	ndis_wlan_bssid_ex	**assoc;
1713{
1714	ndis_80211_bssid_list_ex	*bl;
1715	ndis_wlan_bssid_ex	*bs;
1716	ndis_80211_macaddr	bssid;
1717	int			i, len, error;
1718
1719	if (!sc->ndis_link)
1720		return(ENOENT);
1721
1722	len = sizeof(bssid);
1723	error = ndis_get_info(sc, OID_802_11_BSSID, &bssid, &len);
1724	if (error) {
1725		device_printf(sc->ndis_dev, "failed to get bssid\n");
1726		return(ENOENT);
1727	}
1728	len = 0;
1729	error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
1730	if (error != ENOSPC) {
1731		device_printf(sc->ndis_dev, "bssid_list failed\n");
1732		return (error);
1733	}
1734
1735	bl = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
1736	error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
1737	if (error) {
1738		free(bl, M_TEMP);
1739		device_printf(sc->ndis_dev, "bssid_list failed\n");
1740		return (error);
1741	}
1742
1743	bs = (ndis_wlan_bssid_ex *)&bl->nblx_bssid[0];
1744	for (i = 0; i < bl->nblx_items; i++) {
1745		if (bcmp(bs->nwbx_macaddr, bssid, sizeof(bssid)) == 0) {
1746			*assoc = malloc(bs->nwbx_len, M_TEMP, M_NOWAIT);
1747			if (*assoc == NULL) {
1748				free(bl, M_TEMP);
1749				return(ENOMEM);
1750			}
1751			bcopy((char *)bs, (char *)*assoc, bs->nwbx_len);
1752			free(bl, M_TEMP);
1753			return(0);
1754		}
1755		bs = (ndis_wlan_bssid_ex *)((char *)bs + bs->nwbx_len);
1756	}
1757
1758	free(bl, M_TEMP);
1759	return(ENOENT);
1760}
1761
1762static void
1763ndis_getstate_80211(sc)
1764	struct ndis_softc	*sc;
1765{
1766	struct ieee80211com	*ic;
1767	ndis_80211_ssid		ssid;
1768	ndis_80211_config	config;
1769	ndis_wlan_bssid_ex	*bs;
1770	int			rval, len, i = 0;
1771	uint32_t		arg;
1772	struct ifnet		*ifp;
1773
1774	ic = &sc->ic;
1775	ifp = &sc->ic.ic_ac.ac_if;
1776
1777	if (!NDIS_INITIALIZED(sc))
1778		return;
1779
1780	if (sc->ndis_link)
1781		ic->ic_state = IEEE80211_S_RUN;
1782	else
1783		ic->ic_state = IEEE80211_S_ASSOC;
1784
1785
1786	/*
1787	 * If we're associated, retrieve info on the current bssid.
1788	 */
1789	if ((rval = ndis_get_assoc(sc, &bs)) == 0) {
1790		switch(bs->nwbx_nettype) {
1791		case NDIS_80211_NETTYPE_11FH:
1792		case NDIS_80211_NETTYPE_11DS:
1793			ic->ic_curmode = IEEE80211_MODE_11B;
1794			break;
1795		case NDIS_80211_NETTYPE_11OFDM5:
1796			ic->ic_curmode = IEEE80211_MODE_11A;
1797			break;
1798		case NDIS_80211_NETTYPE_11OFDM24:
1799			ic->ic_curmode = IEEE80211_MODE_11G;
1800			break;
1801		default:
1802			device_printf(sc->ndis_dev,
1803			    "unknown nettype %d\n", arg);
1804			break;
1805		}
1806		free(bs, M_TEMP);
1807	} else
1808		return;
1809
1810	len = sizeof(ssid);
1811	bzero((char *)&ssid, len);
1812	rval = ndis_get_info(sc, OID_802_11_SSID, &ssid, &len);
1813
1814	if (rval)
1815		device_printf (sc->ndis_dev, "get ssid failed: %d\n", rval);
1816	bcopy(ssid.ns_ssid, ic->ic_bss->ni_essid, ssid.ns_ssidlen);
1817	ic->ic_bss->ni_esslen = ssid.ns_ssidlen;
1818
1819	len = sizeof(arg);
1820	rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
1821	if (rval)
1822		device_printf (sc->ndis_dev, "get link speed failed: %d\n",
1823		    rval);
1824
1825	if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) {
1826		ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
1827		for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
1828			if ((ic->ic_bss->ni_rates.rs_rates[i] &
1829			    IEEE80211_RATE_VAL) == arg / 5000)
1830				break;
1831		}
1832	}
1833
1834	if (i == ic->ic_bss->ni_rates.rs_nrates &&
1835	    ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
1836		ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G];
1837		for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
1838			if ((ic->ic_bss->ni_rates.rs_rates[i] &
1839			    IEEE80211_RATE_VAL) == arg / 5000)
1840				break;
1841		}
1842	}
1843
1844	if (i == ic->ic_bss->ni_rates.rs_nrates)
1845		device_printf(sc->ndis_dev, "no matching rate for: %d\n",
1846		    arg / 5000);
1847	else
1848		ic->ic_bss->ni_txrate = i;
1849
1850	if (ic->ic_caps & IEEE80211_C_PMGT) {
1851		len = sizeof(arg);
1852		rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
1853
1854		if (rval)
1855			device_printf(sc->ndis_dev,
1856			    "get power mode failed: %d\n", rval);
1857		if (arg == NDIS_80211_POWERMODE_CAM)
1858			ic->ic_flags &= ~IEEE80211_F_PMGTON;
1859		else
1860			ic->ic_flags |= IEEE80211_F_PMGTON;
1861	}
1862
1863	len = sizeof(config);
1864	bzero((char *)&config, len);
1865	config.nc_length = len;
1866	config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
1867	rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
1868	if (rval == 0) {
1869		int chan;
1870
1871		chan = ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0);
1872		if (chan < 0 || chan >= IEEE80211_CHAN_MAX) {
1873			if (ifp->if_flags & IFF_DEBUG)
1874				device_printf(sc->ndis_dev, "current channel "
1875				    "(%uMHz) out of bounds\n",
1876				    config.nc_dsconfig / 1000);
1877			ic->ic_bss->ni_chan = &ic->ic_channels[1];
1878		} else
1879			ic->ic_bss->ni_chan = &ic->ic_channels[chan];
1880	} else
1881		device_printf(sc->ndis_dev, "couldn't retrieve "
1882		    "channel info: %d\n", rval);
1883
1884/*
1885	len = sizeof(arg);
1886	rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
1887
1888	if (rval)
1889		device_printf (sc->ndis_dev,
1890		    "get wep status failed: %d\n", rval);
1891
1892	if (arg == NDIS_80211_WEPSTAT_ENABLED)
1893		ic->ic_flags |= IEEE80211_F_WEPON;
1894	else
1895		ic->ic_flags &= ~IEEE80211_F_WEPON;
1896*/
1897	return;
1898}
1899
1900static int
1901ndis_ioctl(ifp, command, data)
1902	struct ifnet		*ifp;
1903	u_long			command;
1904	caddr_t			data;
1905{
1906	struct ndis_softc	*sc = ifp->if_softc;
1907	struct ifreq		*ifr = (struct ifreq *) data;
1908	int			i, error = 0;
1909
1910	/*NDIS_LOCK(sc);*/
1911
1912	switch(command) {
1913	case SIOCSIFFLAGS:
1914		if (ifp->if_flags & IFF_UP) {
1915			if (ifp->if_flags & IFF_RUNNING &&
1916			    ifp->if_flags & IFF_PROMISC &&
1917			    !(sc->ndis_if_flags & IFF_PROMISC)) {
1918				sc->ndis_filter |=
1919				    NDIS_PACKET_TYPE_PROMISCUOUS;
1920				i = sizeof(sc->ndis_filter);
1921				error = ndis_set_info(sc,
1922				    OID_GEN_CURRENT_PACKET_FILTER,
1923				    &sc->ndis_filter, &i);
1924			} else if (ifp->if_flags & IFF_RUNNING &&
1925			    !(ifp->if_flags & IFF_PROMISC) &&
1926			    sc->ndis_if_flags & IFF_PROMISC) {
1927				sc->ndis_filter &=
1928				    ~NDIS_PACKET_TYPE_PROMISCUOUS;
1929				i = sizeof(sc->ndis_filter);
1930				error = ndis_set_info(sc,
1931				    OID_GEN_CURRENT_PACKET_FILTER,
1932				    &sc->ndis_filter, &i);
1933			} else
1934				ndis_init(sc);
1935		} else {
1936			if (ifp->if_flags & IFF_RUNNING)
1937				ndis_stop(sc);
1938		}
1939		sc->ndis_if_flags = ifp->if_flags;
1940		error = 0;
1941		break;
1942	case SIOCADDMULTI:
1943	case SIOCDELMULTI:
1944		ndis_setmulti(sc);
1945		error = 0;
1946		break;
1947	case SIOCGIFMEDIA:
1948	case SIOCSIFMEDIA:
1949		if (sc->ndis_80211) {
1950			error = ieee80211_ioctl(ifp, command, data);
1951			if (error == ENETRESET) {
1952				ndis_setstate_80211(sc);
1953				/*ndis_init(sc);*/
1954				error = 0;
1955			}
1956		} else
1957			error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
1958		break;
1959	case SIOCSIFCAP:
1960		ifp->if_capenable = ifr->ifr_reqcap;
1961		if (ifp->if_capenable & IFCAP_TXCSUM)
1962			ifp->if_hwassist = sc->ndis_hwassist;
1963		else
1964			ifp->if_hwassist = 0;
1965		ndis_set_offload(sc);
1966		break;
1967	case SIOCGIFGENERIC:
1968	case SIOCSIFGENERIC:
1969		if (sc->ndis_80211 && NDIS_INITIALIZED(sc)) {
1970			if (command == SIOCGIFGENERIC)
1971				error = ndis_wi_ioctl_get(ifp, command, data);
1972			else
1973				error = ndis_wi_ioctl_set(ifp, command, data);
1974		} else
1975			error = ENOTTY;
1976		if (error != ENOTTY)
1977			break;
1978	default:
1979		sc->ndis_skip = 1;
1980		if (sc->ndis_80211) {
1981			error = ieee80211_ioctl(ifp, command, data);
1982			if (error == ENETRESET) {
1983				ndis_setstate_80211(sc);
1984				error = 0;
1985			}
1986		} else
1987			error = ether_ioctl(ifp, command, data);
1988		sc->ndis_skip = 0;
1989		break;
1990	}
1991
1992	/*NDIS_UNLOCK(sc);*/
1993
1994	return(error);
1995}
1996
1997static int
1998ndis_wi_ioctl_get(ifp, command, data)
1999	struct ifnet		*ifp;
2000	u_long			command;
2001	caddr_t			data;
2002{
2003	struct wi_req		wreq;
2004	struct ifreq		*ifr;
2005	struct ndis_softc	*sc;
2006	ndis_80211_bssid_list_ex *bl;
2007	ndis_wlan_bssid_ex	*wb;
2008	struct wi_apinfo	*api;
2009	int			error, i, j, len, maxaps;
2010
2011	sc = ifp->if_softc;
2012	ifr = (struct ifreq *)data;
2013	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2014	if (error)
2015		return (error);
2016
2017	switch (wreq.wi_type) {
2018	case WI_RID_READ_APS:
2019		len = 0;
2020		error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
2021		    NULL, &len);
2022		if (error == 0)
2023			tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2);
2024		len = 0;
2025		error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
2026		if (error != ENOSPC)
2027			break;
2028		bl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
2029		error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
2030		if (error) {
2031			free(bl, M_DEVBUF);
2032			break;
2033		}
2034		maxaps = (2 * wreq.wi_len - sizeof(int)) / sizeof(*api);
2035		maxaps = MIN(maxaps, bl->nblx_items);
2036		wreq.wi_len = (maxaps * sizeof(*api) + sizeof(int)) / 2;
2037		*(int *)&wreq.wi_val = maxaps;
2038		api = (struct wi_apinfo *)&((int *)&wreq.wi_val)[1];
2039		wb = bl->nblx_bssid;
2040		while (maxaps--) {
2041			bzero(api, sizeof(*api));
2042			bcopy(&wb->nwbx_macaddr, &api->bssid,
2043			    sizeof(api->bssid));
2044			api->namelen = wb->nwbx_ssid.ns_ssidlen;
2045			bcopy(&wb->nwbx_ssid.ns_ssid, &api->name, api->namelen);
2046			if (wb->nwbx_privacy)
2047				api->capinfo |= IEEE80211_CAPINFO_PRIVACY;
2048			/* XXX Where can we get noise information? */
2049			api->signal = wb->nwbx_rssi + 149;	/* XXX */
2050			api->quality = api->signal;
2051			api->channel =
2052			    ieee80211_mhz2ieee(wb->nwbx_config.nc_dsconfig /
2053			    1000, 0);
2054			/* In "auto" infrastructure mode, this is useless. */
2055			if (wb->nwbx_netinfra == NDIS_80211_NET_INFRA_IBSS)
2056				api->capinfo |= IEEE80211_CAPINFO_IBSS;
2057			if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) {
2058				j = sizeof(ndis_80211_rates_ex);
2059				/* handle other extended things */
2060			} else
2061				j = sizeof(ndis_80211_rates);
2062			for (i = api->rate = 0; i < j; i++)
2063				api->rate = MAX(api->rate, 5 *
2064				    (wb->nwbx_supportedrates[i] & 0x7f));
2065			api++;
2066			wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len);
2067		}
2068		free(bl, M_DEVBUF);
2069		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
2070		break;
2071	default:
2072		error = ENOTTY;
2073		break;
2074	}
2075	return (error);
2076}
2077
2078static int
2079ndis_wi_ioctl_set(ifp, command, data)
2080	struct ifnet		*ifp;
2081	u_long			command;
2082	caddr_t			data;
2083{
2084	struct wi_req		wreq;
2085	struct ifreq		*ifr;
2086	struct ndis_softc	*sc;
2087	uint32_t		foo;
2088	int			error, len;
2089
2090	error = suser(curthread);
2091	if (error)
2092		return (error);
2093
2094	sc = ifp->if_softc;
2095	ifr = (struct ifreq *)data;
2096	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2097	if (error)
2098		return (error);
2099
2100	switch (wreq.wi_type) {
2101	case WI_RID_SCAN_APS:
2102	case WI_RID_SCAN_REQ:			/* arguments ignored */
2103		len = sizeof(foo);
2104		foo = 0;
2105		error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, &foo,
2106		    &len);
2107		break;
2108	default:
2109		error = ENOTTY;
2110		break;
2111	}
2112	return (error);
2113}
2114
2115static void
2116ndis_watchdog(ifp)
2117	struct ifnet		*ifp;
2118{
2119	struct ndis_softc		*sc;
2120
2121	sc = ifp->if_softc;
2122
2123	NDIS_LOCK(sc);
2124	ifp->if_oerrors++;
2125	device_printf(sc->ndis_dev, "watchdog timeout\n");
2126	NDIS_UNLOCK(sc);
2127
2128	ndis_sched((void(*)(void *))ndis_reset_nic, sc, NDIS_TASKQUEUE);
2129	ndis_sched(ndis_starttask, ifp, NDIS_TASKQUEUE);
2130
2131	return;
2132}
2133
2134/*
2135 * Stop the adapter and free any mbufs allocated to the
2136 * RX and TX lists.
2137 */
2138static void
2139ndis_stop(sc)
2140	struct ndis_softc		*sc;
2141{
2142	struct ifnet		*ifp;
2143
2144	ifp = &sc->arpcom.ac_if;
2145	untimeout(ndis_tick, sc, sc->ndis_stat_ch);
2146
2147	ndis_halt_nic(sc);
2148
2149	NDIS_LOCK(sc);
2150	ifp->if_timer = 0;
2151	sc->ndis_link = 0;
2152	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2153	NDIS_UNLOCK(sc);
2154
2155	return;
2156}
2157
2158/*
2159 * Stop all chip I/O so that the kernel's probe routines don't
2160 * get confused by errant DMAs when rebooting.
2161 */
2162void
2163ndis_shutdown(dev)
2164	device_t		dev;
2165{
2166	struct ndis_softc		*sc;
2167
2168	sc = device_get_softc(dev);
2169	ndis_shutdown_nic(sc);
2170
2171	return;
2172}
2173