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