if_wi.c revision 70808
1/*
2 * Copyright (c) 1997, 1998, 1999
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  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 * $FreeBSD: head/sys/dev/wi/if_wi.c 70808 2001-01-09 00:44:33Z peter $
33 */
34
35/*
36 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD.
37 *
38 * Written by Bill Paul <wpaul@ctr.columbia.edu>
39 * Electrical Engineering Department
40 * Columbia University, New York City
41 */
42
43/*
44 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
45 * from Lucent. Unlike the older cards, the new ones are programmed
46 * entirely via a firmware-driven controller called the Hermes.
47 * Unfortunately, Lucent will not release the Hermes programming manual
48 * without an NDA (if at all). What they do release is an API library
49 * called the HCF (Hardware Control Functions) which is supposed to
50 * do the device-specific operations of a device driver for you. The
51 * publically available version of the HCF library (the 'HCF Light') is
52 * a) extremely gross, b) lacks certain features, particularly support
53 * for 802.11 frames, and c) is contaminated by the GNU Public License.
54 *
55 * This driver does not use the HCF or HCF Light at all. Instead, it
56 * programs the Hermes controller directly, using information gleaned
57 * from the HCF Light code and corresponding documentation.
58 *
59 * This driver supports both the PCMCIA and ISA versions of the
60 * WaveLAN/IEEE cards. Note however that the ISA card isn't really
61 * anything of the sort: it's actually a PCMCIA bridge adapter
62 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
63 * inserted. Consequently, you need to use the pccard support for
64 * both the ISA and PCMCIA adapters.
65 */
66
67#define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
68#define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
69#define WICACHE			/* turn on signal strength cache code */
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/sockio.h>
74#include <sys/mbuf.h>
75#include <sys/kernel.h>
76#include <sys/socket.h>
77#include <sys/module.h>
78#include <sys/bus.h>
79#include <sys/syslog.h>
80#include <sys/sysctl.h>
81
82#include <machine/bus.h>
83#include <machine/resource.h>
84#include <machine/md_var.h>
85#include <machine/bus_pio.h>
86#include <sys/rman.h>
87
88#include <net/if.h>
89#include <net/if_arp.h>
90#include <net/ethernet.h>
91#include <net/if_dl.h>
92#include <net/if_media.h>
93#include <net/if_types.h>
94
95#include <netinet/in.h>
96#include <netinet/in_systm.h>
97#include <netinet/in_var.h>
98#include <netinet/ip.h>
99#include <netinet/if_ether.h>
100
101#include <net/bpf.h>
102
103#include <dev/wi/if_wavelan_ieee.h>
104#include <dev/wi/if_wireg.h>
105
106#if !defined(lint)
107static const char rcsid[] =
108  "$FreeBSD: head/sys/dev/wi/if_wi.c 70808 2001-01-09 00:44:33Z peter $";
109#endif
110
111#ifdef foo
112static u_int8_t	wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
113#endif
114
115static void wi_intr		__P((void *));
116static void wi_reset		__P((struct wi_softc *));
117static int wi_ioctl		__P((struct ifnet *, u_long, caddr_t));
118static void wi_init		__P((void *));
119static void wi_start		__P((struct ifnet *));
120static void wi_stop		__P((struct wi_softc *));
121static void wi_watchdog		__P((struct ifnet *));
122static void wi_rxeof		__P((struct wi_softc *));
123static void wi_txeof		__P((struct wi_softc *, int));
124static void wi_update_stats	__P((struct wi_softc *));
125static void wi_setmulti		__P((struct wi_softc *));
126
127static int wi_cmd		__P((struct wi_softc *, int, int));
128static int wi_read_record	__P((struct wi_softc *, struct wi_ltv_gen *));
129static int wi_write_record	__P((struct wi_softc *, struct wi_ltv_gen *));
130static int wi_read_data		__P((struct wi_softc *, int,
131					int, caddr_t, int));
132static int wi_write_data	__P((struct wi_softc *, int,
133					int, caddr_t, int));
134static int wi_seek		__P((struct wi_softc *, int, int, int));
135static int wi_alloc_nicmem	__P((struct wi_softc *, int, int *));
136static void wi_inquire		__P((void *));
137static void wi_setdef		__P((struct wi_softc *, struct wi_req *));
138static int wi_mgmt_xmit		__P((struct wi_softc *, caddr_t, int));
139
140#ifdef WICACHE
141static
142void wi_cache_store __P((struct wi_softc *, struct ether_header *,
143	struct mbuf *, unsigned short));
144#endif
145
146static int wi_pccard_probe	__P((device_t));
147static int wi_pccard_attach	__P((device_t));
148static int wi_pccard_detach	__P((device_t));
149static void wi_shutdown		__P((device_t));
150
151static int wi_alloc		__P((device_t));
152static void wi_free		__P((device_t));
153
154static device_method_t wi_pccard_methods[] = {
155	/* Device interface */
156	DEVMETHOD(device_probe,		wi_pccard_probe),
157	DEVMETHOD(device_attach,	wi_pccard_attach),
158	DEVMETHOD(device_detach,	wi_pccard_detach),
159	DEVMETHOD(device_shutdown,	wi_shutdown),
160
161	{ 0, 0 }
162};
163
164static driver_t wi_pccard_driver = {
165	"wi",
166	wi_pccard_methods,
167	sizeof(struct wi_softc)
168};
169
170static devclass_t wi_pccard_devclass;
171
172DRIVER_MODULE(if_wi, pccard, wi_pccard_driver, wi_pccard_devclass, 0, 0);
173
174static int wi_pccard_probe(dev)
175	device_t	dev;
176{
177	struct wi_softc	*sc;
178	int		error;
179
180	sc = device_get_softc(dev);
181	sc->wi_gone = 0;
182
183	error = wi_alloc(dev);
184	if (error)
185		return (error);
186
187	device_set_desc(dev, "WaveLAN/IEEE 802.11");
188	wi_free(dev);
189
190	/* Make sure interrupts are disabled. */
191	CSR_WRITE_2(sc, WI_INT_EN, 0);
192	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
193
194	return (0);
195}
196
197static int wi_pccard_detach(dev)
198	device_t		dev;
199{
200	struct wi_softc		*sc;
201	struct ifnet		*ifp;
202
203	sc = device_get_softc(dev);
204	WI_LOCK(sc);
205	ifp = &sc->arpcom.ac_if;
206
207	if (sc->wi_gone) {
208		device_printf(dev, "already unloaded\n");
209		WI_UNLOCK(sc);
210		return(ENODEV);
211	}
212
213	wi_stop(sc);
214
215	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
216	bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
217	wi_free(dev);
218	sc->wi_gone = 1;
219
220	device_printf(dev, "unload\n");
221	WI_UNLOCK(sc);
222	mtx_destroy(&sc->wi_mtx);
223
224	return(0);
225}
226
227static int wi_pccard_attach(device_t dev)
228{
229	struct wi_softc		*sc;
230	struct wi_ltv_macaddr	mac;
231	struct wi_ltv_gen	gen;
232	struct ifnet		*ifp;
233	int			error;
234	u_int32_t		flags;
235
236	sc = device_get_softc(dev);
237	ifp = &sc->arpcom.ac_if;
238
239	/*
240	 *	XXX: quick hack to support Prism II chip.
241	 *	Currently, we need to set a flags in pccard.conf to specify
242	 *	which type chip is used.
243	 *
244	 *	We need to replace this code in a future.
245	 *	It is better to use CIS than using a flag.
246	 */
247	flags = device_get_flags(dev);
248#define	WI_FLAGS_PRISM2	0x10000
249	if (flags & WI_FLAGS_PRISM2) {
250		sc->wi_prism2 = 1;
251		if (bootverbose) {
252			device_printf(dev, "found PrismII chip\n");
253		}
254	}
255	else {
256		sc->wi_prism2 = 0;
257		if (bootverbose) {
258			device_printf(dev, "found Lucent chip\n");
259		}
260	}
261
262	error = wi_alloc(dev);
263	if (error) {
264		device_printf(dev, "wi_alloc() failed! (%d)\n", error);
265		return (error);
266	}
267
268	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
269			       wi_intr, sc, &sc->wi_intrhand);
270
271	if (error) {
272		device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
273		wi_free(dev);
274		return (error);
275	}
276
277	mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_DEF);
278	WI_LOCK(sc);
279
280	/* Reset the NIC. */
281	wi_reset(sc);
282
283	/* Read the station address. */
284	mac.wi_type = WI_RID_MAC_NODE;
285	mac.wi_len = 4;
286	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
287	bcopy((char *)&mac.wi_mac_addr,
288	   (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
289
290	device_printf(dev, "Ethernet address: %6D\n",
291	    sc->arpcom.ac_enaddr, ":");
292
293	ifp->if_softc = sc;
294	ifp->if_unit = sc->wi_unit;
295	ifp->if_name = "wi";
296	ifp->if_mtu = ETHERMTU;
297	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
298	ifp->if_ioctl = wi_ioctl;
299	ifp->if_output = ether_output;
300	ifp->if_start = wi_start;
301	ifp->if_watchdog = wi_watchdog;
302	ifp->if_init = wi_init;
303	ifp->if_baudrate = 10000000;
304	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
305
306	bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
307	bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
308	    sizeof(WI_DEFAULT_NODENAME) - 1);
309
310	bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
311	bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
312	    sizeof(WI_DEFAULT_NETNAME) - 1);
313
314	bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
315	bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
316	    sizeof(WI_DEFAULT_IBSS) - 1);
317
318	sc->wi_portnum = WI_DEFAULT_PORT;
319	sc->wi_ptype = WI_PORTTYPE_ADHOC;
320	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
321	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
322	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
323	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
324	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
325	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
326	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
327
328	/*
329	 * Read the default channel from the NIC. This may vary
330	 * depending on the country where the NIC was purchased, so
331	 * we can't hard-code a default and expect it to work for
332	 * everyone.
333	 */
334	gen.wi_type = WI_RID_OWN_CHNL;
335	gen.wi_len = 2;
336	wi_read_record(sc, &gen);
337	sc->wi_channel = gen.wi_val;
338
339	/*
340	 * Find out if we support WEP on this card.
341	 */
342	gen.wi_type = WI_RID_WEP_AVAIL;
343	gen.wi_len = 2;
344	wi_read_record(sc, &gen);
345	sc->wi_has_wep = gen.wi_val;
346
347	if (bootverbose) {
348		device_printf(sc->dev,
349				__FUNCTION__ ":wi_has_wep = %d\n",
350				sc->wi_has_wep);
351	}
352
353	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
354
355	wi_init(sc);
356	wi_stop(sc);
357
358	/*
359	 * Call MI attach routine.
360	 */
361	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
362	callout_handle_init(&sc->wi_stat_ch);
363	WI_UNLOCK(sc);
364
365	return(0);
366}
367
368static void wi_rxeof(sc)
369	struct wi_softc		*sc;
370{
371	struct ifnet		*ifp;
372	struct ether_header	*eh;
373	struct wi_frame		rx_frame;
374	struct mbuf		*m;
375	int			id;
376
377	ifp = &sc->arpcom.ac_if;
378
379	id = CSR_READ_2(sc, WI_RX_FID);
380
381	/* First read in the frame header */
382	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
383		ifp->if_ierrors++;
384		return;
385	}
386
387	if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
388		ifp->if_ierrors++;
389		return;
390	}
391
392	MGETHDR(m, M_DONTWAIT, MT_DATA);
393	if (m == NULL) {
394		ifp->if_ierrors++;
395		return;
396	}
397	MCLGET(m, M_DONTWAIT);
398	if (!(m->m_flags & M_EXT)) {
399		m_freem(m);
400		ifp->if_ierrors++;
401		return;
402	}
403
404	eh = mtod(m, struct ether_header *);
405	m->m_pkthdr.rcvif = ifp;
406
407	if (rx_frame.wi_status == WI_STAT_1042 ||
408	    rx_frame.wi_status == WI_STAT_TUNNEL ||
409	    rx_frame.wi_status == WI_STAT_WMP_MSG) {
410		if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
411			device_printf(sc->dev, "oversized packet received "
412			    "(wi_dat_len=%d, wi_status=0x%x)\n",
413			    rx_frame.wi_dat_len, rx_frame.wi_status);
414			m_freem(m);
415			ifp->if_ierrors++;
416			return;
417		}
418		m->m_pkthdr.len = m->m_len =
419		    rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
420
421		bcopy((char *)&rx_frame.wi_addr1,
422		    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
423		if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {
424			bcopy((char *)&rx_frame.wi_addr2,
425			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
426		} else {
427			bcopy((char *)&rx_frame.wi_addr3,
428			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
429		}
430		bcopy((char *)&rx_frame.wi_type,
431		    (char *)&eh->ether_type, sizeof(u_int16_t));
432
433		if (wi_read_data(sc, id, WI_802_11_OFFSET,
434		    mtod(m, caddr_t) + sizeof(struct ether_header),
435		    m->m_len + 2)) {
436			m_freem(m);
437			ifp->if_ierrors++;
438			return;
439		}
440	} else {
441		if((rx_frame.wi_dat_len +
442		    sizeof(struct ether_header)) > MCLBYTES) {
443			device_printf(sc->dev, "oversized packet received "
444			    "(wi_dat_len=%d, wi_status=0x%x)\n",
445			    rx_frame.wi_dat_len, rx_frame.wi_status);
446			m_freem(m);
447			ifp->if_ierrors++;
448			return;
449		}
450		m->m_pkthdr.len = m->m_len =
451		    rx_frame.wi_dat_len + sizeof(struct ether_header);
452
453		if (wi_read_data(sc, id, WI_802_3_OFFSET,
454		    mtod(m, caddr_t), m->m_len + 2)) {
455			m_freem(m);
456			ifp->if_ierrors++;
457			return;
458		}
459	}
460
461	ifp->if_ipackets++;
462
463	/* Receive packet. */
464	m_adj(m, sizeof(struct ether_header));
465#ifdef WICACHE
466	wi_cache_store(sc, eh, m, rx_frame.wi_q_info);
467#endif
468	ether_input(ifp, eh, m);
469}
470
471static void wi_txeof(sc, status)
472	struct wi_softc		*sc;
473	int			status;
474{
475	struct ifnet		*ifp;
476
477	ifp = &sc->arpcom.ac_if;
478
479	ifp->if_timer = 0;
480	ifp->if_flags &= ~IFF_OACTIVE;
481
482	if (status & WI_EV_TX_EXC)
483		ifp->if_oerrors++;
484	else
485		ifp->if_opackets++;
486
487	return;
488}
489
490void wi_inquire(xsc)
491	void			*xsc;
492{
493	struct wi_softc		*sc;
494	struct ifnet		*ifp;
495
496	sc = xsc;
497	ifp = &sc->arpcom.ac_if;
498
499	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
500
501	/* Don't do this while we're transmitting */
502	if (ifp->if_flags & IFF_OACTIVE)
503		return;
504
505	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
506
507	return;
508}
509
510void wi_update_stats(sc)
511	struct wi_softc		*sc;
512{
513	struct wi_ltv_gen	gen;
514	u_int16_t		id;
515	struct ifnet		*ifp;
516	u_int32_t		*ptr;
517	int			i;
518	u_int16_t		t;
519
520	ifp = &sc->arpcom.ac_if;
521
522	id = CSR_READ_2(sc, WI_INFO_FID);
523
524	wi_read_data(sc, id, 0, (char *)&gen, 4);
525
526	if (gen.wi_type != WI_INFO_COUNTERS ||
527	    gen.wi_len > (sizeof(sc->wi_stats) / 4) + 1)
528		return;
529
530	ptr = (u_int32_t *)&sc->wi_stats;
531
532	for (i = 0; i < gen.wi_len - 1; i++) {
533		t = CSR_READ_2(sc, WI_DATA1);
534#ifdef WI_HERMES_STATS_WAR
535		if (t > 0xF000)
536			t = ~t & 0xFFFF;
537#endif
538		ptr[i] += t;
539	}
540
541	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
542	    sc->wi_stats.wi_tx_multi_retries +
543	    sc->wi_stats.wi_tx_retry_limit;
544
545	return;
546}
547
548static void wi_intr(xsc)
549	void		*xsc;
550{
551	struct wi_softc		*sc = xsc;
552	struct ifnet		*ifp;
553	u_int16_t		status;
554
555	WI_LOCK(sc);
556
557	ifp = &sc->arpcom.ac_if;
558
559	if (!(ifp->if_flags & IFF_UP)) {
560		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
561		CSR_WRITE_2(sc, WI_INT_EN, 0);
562		WI_UNLOCK(sc);
563		return;
564	}
565
566	/* Disable interrupts. */
567	CSR_WRITE_2(sc, WI_INT_EN, 0);
568
569	status = CSR_READ_2(sc, WI_EVENT_STAT);
570	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
571
572	if (status & WI_EV_RX) {
573		wi_rxeof(sc);
574		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
575	}
576
577	if (status & WI_EV_TX) {
578		wi_txeof(sc, status);
579		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
580	}
581
582	if (status & WI_EV_ALLOC) {
583		int			id;
584		id = CSR_READ_2(sc, WI_ALLOC_FID);
585		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
586		if (id == sc->wi_tx_data_id)
587			wi_txeof(sc, status);
588	}
589
590	if (status & WI_EV_INFO) {
591		wi_update_stats(sc);
592		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
593	}
594
595	if (status & WI_EV_TX_EXC) {
596		wi_txeof(sc, status);
597		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
598	}
599
600	if (status & WI_EV_INFO_DROP) {
601		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
602	}
603
604	/* Re-enable interrupts. */
605	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
606
607	if (ifp->if_snd.ifq_head != NULL)
608		wi_start(ifp);
609
610	WI_UNLOCK(sc);
611
612	return;
613}
614
615static int wi_cmd(sc, cmd, val)
616	struct wi_softc		*sc;
617	int			cmd;
618	int			val;
619{
620	int			i, s = 0;
621
622	/* wait for the busy bit to clear */
623	for (i = 0; i < WI_TIMEOUT; i++) {
624		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
625			break;
626		}
627		DELAY(10*1000);	/* 10 m sec */
628	}
629
630	if (i == WI_TIMEOUT) {
631		return(ETIMEDOUT);
632	}
633
634	CSR_WRITE_2(sc, WI_PARAM0, val);
635	CSR_WRITE_2(sc, WI_PARAM1, 0);
636	CSR_WRITE_2(sc, WI_PARAM2, 0);
637	CSR_WRITE_2(sc, WI_COMMAND, cmd);
638
639	for (i = 0; i < WI_TIMEOUT; i++) {
640		/*
641		 * Wait for 'command complete' bit to be
642		 * set in the event status register.
643		 */
644		s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
645		if (s) {
646			/* Ack the event and read result code. */
647			s = CSR_READ_2(sc, WI_STATUS);
648			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
649#ifdef foo
650			if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
651				return(EIO);
652#endif
653			if (s & WI_STAT_CMD_RESULT)
654				return(EIO);
655			break;
656		}
657	}
658
659	if (i == WI_TIMEOUT)
660		return(ETIMEDOUT);
661
662	return(0);
663}
664
665static void wi_reset(sc)
666	struct wi_softc		*sc;
667{
668#ifdef foo
669	wi_cmd(sc, WI_CMD_INI, 0);
670	DELAY(100000);
671	wi_cmd(sc, WI_CMD_INI, 0);
672#endif
673	DELAY(100000);
674	if (wi_cmd(sc, WI_CMD_INI, 0))
675		device_printf(sc->dev, "init failed\n");
676	CSR_WRITE_2(sc, WI_INT_EN, 0);
677	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
678
679	/* Calibrate timer. */
680	WI_SETVAL(WI_RID_TICK_TIME, 8);
681
682	return;
683}
684
685/*
686 * Read an LTV record from the NIC.
687 */
688static int wi_read_record(sc, ltv)
689	struct wi_softc		*sc;
690	struct wi_ltv_gen	*ltv;
691{
692	u_int16_t		*ptr;
693	int			i, len, code;
694	struct wi_ltv_gen	*oltv, p2ltv;
695
696	oltv = ltv;
697	if (sc->wi_prism2) {
698		switch (ltv->wi_type) {
699		case WI_RID_ENCRYPTION:
700			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
701			p2ltv.wi_len = 2;
702			ltv = &p2ltv;
703			break;
704		case WI_RID_TX_CRYPT_KEY:
705			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
706			p2ltv.wi_len = 2;
707			ltv = &p2ltv;
708			break;
709		}
710	}
711
712	/* Tell the NIC to enter record read mode. */
713	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
714		return(EIO);
715
716	/* Seek to the record. */
717	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
718		return(EIO);
719
720	/*
721	 * Read the length and record type and make sure they
722	 * match what we expect (this verifies that we have enough
723	 * room to hold all of the returned data).
724	 */
725	len = CSR_READ_2(sc, WI_DATA1);
726	if (len > ltv->wi_len)
727		return(ENOSPC);
728	code = CSR_READ_2(sc, WI_DATA1);
729	if (code != ltv->wi_type)
730		return(EIO);
731
732	ltv->wi_len = len;
733	ltv->wi_type = code;
734
735	/* Now read the data. */
736	ptr = &ltv->wi_val;
737	for (i = 0; i < ltv->wi_len - 1; i++)
738		ptr[i] = CSR_READ_2(sc, WI_DATA1);
739
740	if (sc->wi_prism2) {
741		switch (oltv->wi_type) {
742		case WI_RID_TX_RATE:
743		case WI_RID_CUR_TX_RATE:
744			switch (ltv->wi_val) {
745			case 1: oltv->wi_val = 1; break;
746			case 2: oltv->wi_val = 2; break;
747			case 3:	oltv->wi_val = 6; break;
748			case 4: oltv->wi_val = 5; break;
749			case 7: oltv->wi_val = 7; break;
750			case 8: oltv->wi_val = 11; break;
751			case 15: oltv->wi_val = 3; break;
752			default: oltv->wi_val = 0x100 + ltv->wi_val; break;
753			}
754			break;
755		case WI_RID_ENCRYPTION:
756			oltv->wi_len = 2;
757			if (ltv->wi_val & 0x01)
758				oltv->wi_val = 1;
759			else
760				oltv->wi_val = 0;
761			break;
762		case WI_RID_TX_CRYPT_KEY:
763			oltv->wi_len = 2;
764			oltv->wi_val = ltv->wi_val;
765			break;
766		}
767	}
768
769	return(0);
770}
771
772/*
773 * Same as read, except we inject data instead of reading it.
774 */
775static int wi_write_record(sc, ltv)
776	struct wi_softc		*sc;
777	struct wi_ltv_gen	*ltv;
778{
779	u_int16_t		*ptr;
780	int			i;
781	struct wi_ltv_gen	p2ltv;
782
783	if (sc->wi_prism2) {
784		switch (ltv->wi_type) {
785		case WI_RID_TX_RATE:
786			p2ltv.wi_type = WI_RID_TX_RATE;
787			p2ltv.wi_len = 2;
788			switch (ltv->wi_val) {
789			case 1: p2ltv.wi_val = 1; break;
790			case 2: p2ltv.wi_val = 2; break;
791			case 3:	p2ltv.wi_val = 15; break;
792			case 5: p2ltv.wi_val = 4; break;
793			case 6: p2ltv.wi_val = 3; break;
794			case 7: p2ltv.wi_val = 7; break;
795			case 11: p2ltv.wi_val = 8; break;
796			default: return EINVAL;
797			}
798			ltv = &p2ltv;
799			break;
800		case WI_RID_ENCRYPTION:
801			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
802			p2ltv.wi_len = 2;
803			if (ltv->wi_val)
804				p2ltv.wi_val = 0x03;
805			else
806				p2ltv.wi_val = 0x90;
807			ltv = &p2ltv;
808			break;
809		case WI_RID_TX_CRYPT_KEY:
810			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
811			p2ltv.wi_len = 2;
812			p2ltv.wi_val = ltv->wi_val;
813			ltv = &p2ltv;
814			break;
815		case WI_RID_DEFLT_CRYPT_KEYS:
816		    {
817			int error;
818			struct wi_ltv_str	ws;
819			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
820			for (i = 0; i < 4; i++) {
821				ws.wi_len = 4;
822				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
823				memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
824				ws.wi_str[5] = '\0';
825				error = wi_write_record(sc,
826				    (struct wi_ltv_gen *)&ws);
827				if (error)
828					return error;
829			}
830			return 0;
831		    }
832		}
833	}
834
835	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
836		return(EIO);
837
838	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
839	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
840
841	ptr = &ltv->wi_val;
842	for (i = 0; i < ltv->wi_len - 1; i++)
843		CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
844
845	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
846		return(EIO);
847
848	return(0);
849}
850
851static int wi_seek(sc, id, off, chan)
852	struct wi_softc		*sc;
853	int			id, off, chan;
854{
855	int			i;
856	int			selreg, offreg;
857
858	switch (chan) {
859	case WI_BAP0:
860		selreg = WI_SEL0;
861		offreg = WI_OFF0;
862		break;
863	case WI_BAP1:
864		selreg = WI_SEL1;
865		offreg = WI_OFF1;
866		break;
867	default:
868		device_printf(sc->dev, "invalid data path: %x\n", chan);
869		return(EIO);
870	}
871
872	CSR_WRITE_2(sc, selreg, id);
873	CSR_WRITE_2(sc, offreg, off);
874
875	for (i = 0; i < WI_TIMEOUT; i++) {
876		if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
877			break;
878	}
879
880	if (i == WI_TIMEOUT)
881		return(ETIMEDOUT);
882
883	return(0);
884}
885
886static int wi_read_data(sc, id, off, buf, len)
887	struct wi_softc		*sc;
888	int			id, off;
889	caddr_t			buf;
890	int			len;
891{
892	int			i;
893	u_int16_t		*ptr;
894
895	if (wi_seek(sc, id, off, WI_BAP1))
896		return(EIO);
897
898	ptr = (u_int16_t *)buf;
899	for (i = 0; i < len / 2; i++)
900		ptr[i] = CSR_READ_2(sc, WI_DATA1);
901
902	return(0);
903}
904
905/*
906 * According to the comments in the HCF Light code, there is a bug in
907 * the Hermes (or possibly in certain Hermes firmware revisions) where
908 * the chip's internal autoincrement counter gets thrown off during
909 * data writes: the autoincrement is missed, causing one data word to
910 * be overwritten and subsequent words to be written to the wrong memory
911 * locations. The end result is that we could end up transmitting bogus
912 * frames without realizing it. The workaround for this is to write a
913 * couple of extra guard words after the end of the transfer, then
914 * attempt to read then back. If we fail to locate the guard words where
915 * we expect them, we preform the transfer over again.
916 */
917static int wi_write_data(sc, id, off, buf, len)
918	struct wi_softc		*sc;
919	int			id, off;
920	caddr_t			buf;
921	int			len;
922{
923	int			i;
924	u_int16_t		*ptr;
925
926#ifdef WI_HERMES_AUTOINC_WAR
927again:
928#endif
929
930	if (wi_seek(sc, id, off, WI_BAP0))
931		return(EIO);
932
933	ptr = (u_int16_t *)buf;
934	for (i = 0; i < (len / 2); i++)
935		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
936
937#ifdef WI_HERMES_AUTOINC_WAR
938	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
939	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
940
941	if (wi_seek(sc, id, off + len, WI_BAP0))
942		return(EIO);
943
944	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
945	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
946		goto again;
947#endif
948
949	return(0);
950}
951
952/*
953 * Allocate a region of memory inside the NIC and zero
954 * it out.
955 */
956static int wi_alloc_nicmem(sc, len, id)
957	struct wi_softc		*sc;
958	int			len;
959	int			*id;
960{
961	int			i;
962
963	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
964		device_printf(sc->dev, "failed to allocate %d bytes on NIC\n", len);
965		return(ENOMEM);
966	}
967
968	for (i = 0; i < WI_TIMEOUT; i++) {
969		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
970			break;
971	}
972
973	if (i == WI_TIMEOUT)
974		return(ETIMEDOUT);
975
976	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
977	*id = CSR_READ_2(sc, WI_ALLOC_FID);
978
979	if (wi_seek(sc, *id, 0, WI_BAP0))
980		return(EIO);
981
982	for (i = 0; i < len / 2; i++)
983		CSR_WRITE_2(sc, WI_DATA0, 0);
984
985	return(0);
986}
987
988static void wi_setmulti(sc)
989	struct wi_softc		*sc;
990{
991	struct ifnet		*ifp;
992	int			i = 0;
993	struct ifmultiaddr	*ifma;
994	struct wi_ltv_mcast	mcast;
995
996	ifp = &sc->arpcom.ac_if;
997
998	bzero((char *)&mcast, sizeof(mcast));
999
1000	mcast.wi_type = WI_RID_MCAST;
1001	mcast.wi_len = (3 * 16) + 1;
1002
1003	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1004		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1005		return;
1006	}
1007
1008	for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
1009				ifma = ifma->ifma_link.le_next) {
1010		if (ifma->ifma_addr->sa_family != AF_LINK)
1011			continue;
1012		if (i < 16) {
1013			bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
1014			    (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
1015			i++;
1016		} else {
1017			bzero((char *)&mcast, sizeof(mcast));
1018			break;
1019		}
1020	}
1021
1022	mcast.wi_len = (i * 3) + 1;
1023	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1024
1025	return;
1026}
1027
1028static void wi_setdef(sc, wreq)
1029	struct wi_softc		*sc;
1030	struct wi_req		*wreq;
1031{
1032	struct sockaddr_dl	*sdl;
1033	struct ifaddr		*ifa;
1034	struct ifnet		*ifp;
1035
1036	ifp = &sc->arpcom.ac_if;
1037
1038	switch(wreq->wi_type) {
1039	case WI_RID_MAC_NODE:
1040		ifa = ifnet_addrs[ifp->if_index - 1];
1041		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1042		bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
1043		   ETHER_ADDR_LEN);
1044		bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
1045		break;
1046	case WI_RID_PORTTYPE:
1047		sc->wi_ptype = wreq->wi_val[0];
1048		break;
1049	case WI_RID_TX_RATE:
1050		sc->wi_tx_rate = wreq->wi_val[0];
1051		break;
1052	case WI_RID_MAX_DATALEN:
1053		sc->wi_max_data_len = wreq->wi_val[0];
1054		break;
1055	case WI_RID_RTS_THRESH:
1056		sc->wi_rts_thresh = wreq->wi_val[0];
1057		break;
1058	case WI_RID_SYSTEM_SCALE:
1059		sc->wi_ap_density = wreq->wi_val[0];
1060		break;
1061	case WI_RID_CREATE_IBSS:
1062		sc->wi_create_ibss = wreq->wi_val[0];
1063		break;
1064	case WI_RID_OWN_CHNL:
1065		sc->wi_channel = wreq->wi_val[0];
1066		break;
1067	case WI_RID_NODENAME:
1068		bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
1069		bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
1070		break;
1071	case WI_RID_DESIRED_SSID:
1072		bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
1073		bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
1074		break;
1075	case WI_RID_OWN_SSID:
1076		bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
1077		bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
1078		break;
1079	case WI_RID_PM_ENABLED:
1080		sc->wi_pm_enabled = wreq->wi_val[0];
1081		break;
1082	case WI_RID_MAX_SLEEP:
1083		sc->wi_max_sleep = wreq->wi_val[0];
1084		break;
1085	case WI_RID_ENCRYPTION:
1086		sc->wi_use_wep = wreq->wi_val[0];
1087		break;
1088	case WI_RID_TX_CRYPT_KEY:
1089		sc->wi_tx_key = wreq->wi_val[0];
1090		break;
1091	case WI_RID_DEFLT_CRYPT_KEYS:
1092		bcopy((char *)wreq, (char *)&sc->wi_keys,
1093		    sizeof(struct wi_ltv_keys));
1094		break;
1095	default:
1096		break;
1097	}
1098
1099	/* Reinitialize WaveLAN. */
1100	wi_init(sc);
1101
1102	return;
1103}
1104
1105static int wi_ioctl(ifp, command, data)
1106	struct ifnet		*ifp;
1107	u_long			command;
1108	caddr_t			data;
1109{
1110	int			error = 0;
1111	struct wi_softc		*sc;
1112	struct wi_req		wreq;
1113	struct ifreq		*ifr;
1114	struct proc		*p = curproc;
1115
1116	sc = ifp->if_softc;
1117	WI_LOCK(sc);
1118	ifr = (struct ifreq *)data;
1119
1120	if (sc->wi_gone) {
1121		error = ENODEV;
1122		goto out;
1123	}
1124
1125	switch(command) {
1126	case SIOCSIFADDR:
1127	case SIOCGIFADDR:
1128	case SIOCSIFMTU:
1129		error = ether_ioctl(ifp, command, data);
1130		break;
1131	case SIOCSIFFLAGS:
1132		if (ifp->if_flags & IFF_UP) {
1133			if (ifp->if_flags & IFF_RUNNING &&
1134			    ifp->if_flags & IFF_PROMISC &&
1135			    !(sc->wi_if_flags & IFF_PROMISC)) {
1136				WI_SETVAL(WI_RID_PROMISC, 1);
1137			} else if (ifp->if_flags & IFF_RUNNING &&
1138			    !(ifp->if_flags & IFF_PROMISC) &&
1139			    sc->wi_if_flags & IFF_PROMISC) {
1140				WI_SETVAL(WI_RID_PROMISC, 0);
1141			} else
1142				wi_init(sc);
1143		} else {
1144			if (ifp->if_flags & IFF_RUNNING) {
1145				wi_stop(sc);
1146			}
1147		}
1148		sc->wi_if_flags = ifp->if_flags;
1149		error = 0;
1150		break;
1151	case SIOCADDMULTI:
1152	case SIOCDELMULTI:
1153		wi_setmulti(sc);
1154		error = 0;
1155		break;
1156	case SIOCGWAVELAN:
1157		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1158		if (error)
1159			break;
1160		/* Don't show WEP keys to non-root users. */
1161		if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && suser(p))
1162			break;
1163		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1164			bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1165			    sizeof(sc->wi_stats));
1166			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1167		} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1168			bcopy((char *)&sc->wi_keys, (char *)&wreq,
1169			    sizeof(struct wi_ltv_keys));
1170		}
1171#ifdef WICACHE
1172		else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
1173			sc->wi_sigitems = sc->wi_nextitem = 0;
1174		} else if (wreq.wi_type == WI_RID_READ_CACHE) {
1175			char *pt = (char *)&wreq.wi_val;
1176			bcopy((char *)&sc->wi_sigitems,
1177			    (char *)pt, sizeof(int));
1178			pt += (sizeof (int));
1179			wreq.wi_len = sizeof(int) / 2;
1180			bcopy((char *)&sc->wi_sigcache, (char *)pt,
1181			    sizeof(struct wi_sigcache) * sc->wi_sigitems);
1182			wreq.wi_len += ((sizeof(struct wi_sigcache) *
1183			    sc->wi_sigitems) / 2) + 1;
1184		}
1185#endif
1186		else {
1187			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1188				error = EINVAL;
1189				break;
1190			}
1191		}
1192		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1193		break;
1194	case SIOCSWAVELAN:
1195		if ((error = suser(p)))
1196			goto out;
1197		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1198		if (error)
1199			break;
1200		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1201			error = EINVAL;
1202			break;
1203		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1204			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1205			    wreq.wi_len);
1206		} else {
1207			error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1208			if (!error)
1209				wi_setdef(sc, &wreq);
1210		}
1211		break;
1212	default:
1213		error = EINVAL;
1214		break;
1215	}
1216out:
1217	WI_UNLOCK(sc);
1218
1219	return(error);
1220}
1221
1222static void wi_init(xsc)
1223	void			*xsc;
1224{
1225	struct wi_softc		*sc = xsc;
1226	struct ifnet		*ifp = &sc->arpcom.ac_if;
1227	struct wi_ltv_macaddr	mac;
1228	int			id = 0;
1229
1230	WI_LOCK(sc);
1231
1232	if (sc->wi_gone) {
1233		WI_UNLOCK(sc);
1234		return;
1235	}
1236
1237	if (ifp->if_flags & IFF_RUNNING)
1238		wi_stop(sc);
1239
1240	wi_reset(sc);
1241
1242	/* Program max data length. */
1243	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1244
1245	/* Enable/disable IBSS creation. */
1246	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1247
1248	/* Set the port type. */
1249	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1250
1251	/* Program the RTS/CTS threshold. */
1252	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1253
1254	/* Program the TX rate */
1255	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1256
1257	/* Access point density */
1258	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1259
1260	/* Power Management Enabled */
1261	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1262
1263	/* Power Managment Max Sleep */
1264	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1265
1266	/* Specify the IBSS name */
1267	WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1268
1269	/* Specify the network name */
1270	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1271
1272	/* Specify the frequency to use */
1273	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1274
1275	/* Program the nodename. */
1276	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1277
1278	/* Set our MAC address. */
1279	mac.wi_len = 4;
1280	mac.wi_type = WI_RID_MAC_NODE;
1281	bcopy((char *)&sc->arpcom.ac_enaddr,
1282	   (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1283	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1284
1285	/* Configure WEP. */
1286	if (sc->wi_has_wep) {
1287		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1288		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1289		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1290		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1291		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1292	}
1293
1294	/* Initialize promisc mode. */
1295	if (ifp->if_flags & IFF_PROMISC) {
1296		WI_SETVAL(WI_RID_PROMISC, 1);
1297	} else {
1298		WI_SETVAL(WI_RID_PROMISC, 0);
1299	}
1300
1301	/* Set multicast filter. */
1302	wi_setmulti(sc);
1303
1304	/* Enable desired port */
1305	wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1306
1307	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1308		device_printf(sc->dev, "tx buffer allocation failed\n");
1309	sc->wi_tx_data_id = id;
1310
1311	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1312		device_printf(sc->dev, "mgmt. buffer allocation failed\n");
1313	sc->wi_tx_mgmt_id = id;
1314
1315	/* enable interrupts */
1316	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1317
1318	ifp->if_flags |= IFF_RUNNING;
1319	ifp->if_flags &= ~IFF_OACTIVE;
1320
1321	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
1322	WI_UNLOCK(sc);
1323
1324	return;
1325}
1326
1327static void wi_start(ifp)
1328	struct ifnet		*ifp;
1329{
1330	struct wi_softc		*sc;
1331	struct mbuf		*m0;
1332	struct wi_frame		tx_frame;
1333	struct ether_header	*eh;
1334	int			id;
1335
1336	sc = ifp->if_softc;
1337	WI_LOCK(sc);
1338
1339	if (sc->wi_gone) {
1340		WI_UNLOCK(sc);
1341		return;
1342	}
1343
1344	if (ifp->if_flags & IFF_OACTIVE) {
1345		WI_UNLOCK(sc);
1346		return;
1347	}
1348
1349	IF_DEQUEUE(&ifp->if_snd, m0);
1350	if (m0 == NULL) {
1351		WI_UNLOCK(sc);
1352		return;
1353	}
1354
1355	bzero((char *)&tx_frame, sizeof(tx_frame));
1356	id = sc->wi_tx_data_id;
1357	eh = mtod(m0, struct ether_header *);
1358
1359	/*
1360	 * Use RFC1042 encoding for IP and ARP datagrams,
1361	 * 802.3 for anything else.
1362	 */
1363	if (ntohs(eh->ether_type) > 1518) {
1364		bcopy((char *)&eh->ether_dhost,
1365		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1366		bcopy((char *)&eh->ether_shost,
1367		    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1368		bcopy((char *)&eh->ether_dhost,
1369		    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1370		bcopy((char *)&eh->ether_shost,
1371		    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1372
1373		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
1374		tx_frame.wi_frame_ctl = WI_FTYPE_DATA;
1375		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1376		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1377		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1378		tx_frame.wi_type = eh->ether_type;
1379
1380		m_copydata(m0, sizeof(struct ether_header),
1381		    m0->m_pkthdr.len - sizeof(struct ether_header),
1382		    (caddr_t)&sc->wi_txbuf);
1383
1384		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1385		    sizeof(struct wi_frame));
1386		wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1387		    (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1388	} else {
1389		tx_frame.wi_dat_len = m0->m_pkthdr.len;
1390
1391		eh->ether_type = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1392		m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1393
1394		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1395		    sizeof(struct wi_frame));
1396		wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1397		    m0->m_pkthdr.len + 2);
1398	}
1399
1400	/*
1401	 * If there's a BPF listner, bounce a copy of
1402	 * this frame to him.
1403	 */
1404	if (ifp->if_bpf)
1405		bpf_mtap(ifp, m0);
1406
1407	m_freem(m0);
1408
1409	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1410		device_printf(sc->dev, "xmit failed\n");
1411
1412	ifp->if_flags |= IFF_OACTIVE;
1413
1414	/*
1415	 * Set a timeout in case the chip goes out to lunch.
1416	 */
1417	ifp->if_timer = 5;
1418
1419	WI_UNLOCK(sc);
1420	return;
1421}
1422
1423static int wi_mgmt_xmit(sc, data, len)
1424	struct wi_softc		*sc;
1425	caddr_t			data;
1426	int			len;
1427{
1428	struct wi_frame		tx_frame;
1429	int			id;
1430	struct wi_80211_hdr	*hdr;
1431	caddr_t			dptr;
1432
1433	if (sc->wi_gone)
1434		return(ENODEV);
1435
1436	hdr = (struct wi_80211_hdr *)data;
1437	dptr = data + sizeof(struct wi_80211_hdr);
1438
1439	bzero((char *)&tx_frame, sizeof(tx_frame));
1440	id = sc->wi_tx_mgmt_id;
1441
1442	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1443	   sizeof(struct wi_80211_hdr));
1444
1445	tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1446	tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1447
1448	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1449	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1450	    (len - sizeof(struct wi_80211_hdr)) + 2);
1451
1452	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1453		device_printf(sc->dev, "xmit failed\n");
1454		return(EIO);
1455	}
1456
1457	return(0);
1458}
1459
1460static void wi_stop(sc)
1461	struct wi_softc		*sc;
1462{
1463	struct ifnet		*ifp;
1464
1465	WI_LOCK(sc);
1466
1467	if (sc->wi_gone) {
1468		WI_UNLOCK(sc);
1469		return;
1470	}
1471
1472	ifp = &sc->arpcom.ac_if;
1473
1474	/*
1475	 * If the card is gone and the memory port isn't mapped, we will
1476	 * (hopefully) get 0xffff back from the status read, which is not
1477	 * a valid status value.
1478	 */
1479	if (CSR_READ_2(sc, WI_STATUS) != 0xffff) {
1480		CSR_WRITE_2(sc, WI_INT_EN, 0);
1481		wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1482	}
1483
1484	untimeout(wi_inquire, sc, sc->wi_stat_ch);
1485
1486	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1487
1488	WI_UNLOCK(sc);
1489	return;
1490}
1491
1492static void wi_watchdog(ifp)
1493	struct ifnet		*ifp;
1494{
1495	struct wi_softc		*sc;
1496
1497	sc = ifp->if_softc;
1498
1499	device_printf(sc->dev,"device timeout\n");
1500
1501	wi_init(sc);
1502
1503	ifp->if_oerrors++;
1504
1505	return;
1506}
1507
1508static int wi_alloc(dev)
1509	device_t		dev;
1510{
1511	struct wi_softc		*sc = device_get_softc(dev);
1512	int			rid;
1513
1514	rid = 0;
1515	sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1516				0, ~0, (1 << 6),
1517				rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
1518	if (!sc->iobase) {
1519		device_printf(dev, "No I/O space?!\n");
1520		return (ENXIO);
1521	}
1522
1523	rid = 0;
1524	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
1525				     0, ~0, 1, RF_ACTIVE);
1526	if (!sc->irq) {
1527		device_printf(dev, "No irq?!\n");
1528		return (ENXIO);
1529	}
1530
1531	sc->dev = dev;
1532	sc->wi_unit = device_get_unit(dev);
1533	sc->wi_io_addr = rman_get_start(sc->iobase);
1534	sc->wi_btag = rman_get_bustag(sc->iobase);
1535	sc->wi_bhandle = rman_get_bushandle(sc->iobase);
1536
1537	return (0);
1538}
1539
1540static void wi_free(dev)
1541	device_t		dev;
1542{
1543	struct wi_softc		*sc = device_get_softc(dev);
1544
1545	if (sc->iobase != NULL)
1546		bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iobase);
1547	if (sc->irq != NULL)
1548		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
1549
1550	return;
1551}
1552
1553static void wi_shutdown(dev)
1554	device_t		dev;
1555{
1556	struct wi_softc		*sc;
1557
1558	sc = device_get_softc(dev);
1559	wi_stop(sc);
1560
1561	return;
1562}
1563
1564#ifdef WICACHE
1565/* wavelan signal strength cache code.
1566 * store signal/noise/quality on per MAC src basis in
1567 * a small fixed cache.  The cache wraps if > MAX slots
1568 * used.  The cache may be zeroed out to start over.
1569 * Two simple filters exist to reduce computation:
1570 * 1. ip only (literally 0x800) which may be used
1571 * to ignore some packets.  It defaults to ip only.
1572 * it could be used to focus on broadcast, non-IP 802.11 beacons.
1573 * 2. multicast/broadcast only.  This may be used to
1574 * ignore unicast packets and only cache signal strength
1575 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
1576 * beacons and not unicast traffic.
1577 *
1578 * The cache stores (MAC src(index), IP src (major clue), signal,
1579 *	quality, noise)
1580 *
1581 * No apologies for storing IP src here.  It's easy and saves much
1582 * trouble elsewhere.  The cache is assumed to be INET dependent,
1583 * although it need not be.
1584 */
1585
1586#ifdef documentation
1587
1588int wi_sigitems;                                /* number of cached entries */
1589struct wi_sigcache wi_sigcache[MAXWICACHE];  /*  array of cache entries */
1590int wi_nextitem;                                /*  index/# of entries */
1591
1592
1593#endif
1594
1595/* control variables for cache filtering.  Basic idea is
1596 * to reduce cost (e.g., to only Mobile-IP agent beacons
1597 * which are broadcast or multicast).  Still you might
1598 * want to measure signal strength with unicast ping packets
1599 * on a pt. to pt. ant. setup.
1600 */
1601/* set true if you want to limit cache items to broadcast/mcast
1602 * only packets (not unicast).  Useful for mobile-ip beacons which
1603 * are broadcast/multicast at network layer.  Default is all packets
1604 * so ping/unicast will work say with pt. to pt. antennae setup.
1605 */
1606static int wi_cache_mcastonly = 0;
1607SYSCTL_INT(_machdep, OID_AUTO, wi_cache_mcastonly, CTLFLAG_RW,
1608	&wi_cache_mcastonly, 0, "");
1609
1610/* set true if you want to limit cache items to IP packets only
1611*/
1612static int wi_cache_iponly = 1;
1613SYSCTL_INT(_machdep, OID_AUTO, wi_cache_iponly, CTLFLAG_RW,
1614	&wi_cache_iponly, 0, "");
1615
1616/*
1617 * Original comments:
1618 * -----------------
1619 * wi_cache_store, per rx packet store signal
1620 * strength in MAC (src) indexed cache.
1621 *
1622 * follows linux driver in how signal strength is computed.
1623 * In ad hoc mode, we use the rx_quality field.
1624 * signal and noise are trimmed to fit in the range from 47..138.
1625 * rx_quality field MSB is signal strength.
1626 * rx_quality field LSB is noise.
1627 * "quality" is (signal - noise) as is log value.
1628 * note: quality CAN be negative.
1629 *
1630 * In BSS mode, we use the RID for communication quality.
1631 * TBD:  BSS mode is currently untested.
1632 *
1633 * Bill's comments:
1634 * ---------------
1635 * Actually, we use the rx_quality field all the time for both "ad-hoc"
1636 * and BSS modes. Why? Because reading an RID is really, really expensive:
1637 * there's a bunch of PIO operations that have to be done to read a record
1638 * from the NIC, and reading the comms quality RID each time a packet is
1639 * received can really hurt performance. We don't have to do this anyway:
1640 * the comms quality field only reflects the values in the rx_quality field
1641 * anyway. The comms quality RID is only meaningful in infrastructure mode,
1642 * but the values it contains are updated based on the rx_quality from
1643 * frames received from the access point.
1644 *
1645 * Also, according to Lucent, the signal strength and noise level values
1646 * can be converted to dBms by subtracting 149, so I've modified the code
1647 * to do that instead of the scaling it did originally.
1648 */
1649static
1650void wi_cache_store (struct wi_softc *sc, struct ether_header *eh,
1651                     struct mbuf *m, unsigned short rx_quality)
1652{
1653	struct ip *ip = 0;
1654	int i;
1655	static int cache_slot = 0; 	/* use this cache entry */
1656	static int wrapindex = 0;       /* next "free" cache entry */
1657	int sig, noise;
1658	int sawip=0;
1659
1660	/* filters:
1661	 * 1. ip only
1662	 * 2. configurable filter to throw out unicast packets,
1663	 * keep multicast only.
1664	 */
1665
1666	if ((ntohs(eh->ether_type) == 0x800)) {
1667		sawip = 1;
1668	}
1669
1670	/* filter for ip packets only
1671	*/
1672	if (wi_cache_iponly && !sawip) {
1673		return;
1674	}
1675
1676	/* filter for broadcast/multicast only
1677	 */
1678	if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
1679		return;
1680	}
1681
1682#ifdef SIGDEBUG
1683	printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
1684	    rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
1685#endif
1686
1687	/* find the ip header.  we want to store the ip_src
1688	 * address.
1689	 */
1690	if (sawip) {
1691		ip = mtod(m, struct ip *);
1692	}
1693
1694	/* do a linear search for a matching MAC address
1695	 * in the cache table
1696	 * . MAC address is 6 bytes,
1697	 * . var w_nextitem holds total number of entries already cached
1698	 */
1699	for(i = 0; i < sc->wi_nextitem; i++) {
1700		if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc,  6 )) {
1701			/* Match!,
1702			 * so we already have this entry,
1703			 * update the data
1704			 */
1705			break;
1706		}
1707	}
1708
1709	/* did we find a matching mac address?
1710	 * if yes, then overwrite a previously existing cache entry
1711	 */
1712	if (i < sc->wi_nextitem )   {
1713		cache_slot = i;
1714	}
1715	/* else, have a new address entry,so
1716	 * add this new entry,
1717	 * if table full, then we need to replace LRU entry
1718	 */
1719	else    {
1720
1721		/* check for space in cache table
1722		 * note: wi_nextitem also holds number of entries
1723		 * added in the cache table
1724		 */
1725		if ( sc->wi_nextitem < MAXWICACHE ) {
1726			cache_slot = sc->wi_nextitem;
1727			sc->wi_nextitem++;
1728			sc->wi_sigitems = sc->wi_nextitem;
1729		}
1730        	/* no space found, so simply wrap with wrap index
1731		 * and "zap" the next entry
1732		 */
1733		else {
1734			if (wrapindex == MAXWICACHE) {
1735				wrapindex = 0;
1736			}
1737			cache_slot = wrapindex++;
1738		}
1739	}
1740
1741	/* invariant: cache_slot now points at some slot
1742	 * in cache.
1743	 */
1744	if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
1745		log(LOG_ERR, "wi_cache_store, bad index: %d of "
1746		    "[0..%d], gross cache error\n",
1747		    cache_slot, MAXWICACHE);
1748		return;
1749	}
1750
1751	/*  store items in cache
1752	 *  .ip source address
1753	 *  .mac src
1754	 *  .signal, etc.
1755	 */
1756	if (sawip) {
1757		sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
1758	}
1759	bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc,  6);
1760
1761	sig = (rx_quality >> 8) & 0xFF;
1762	noise = rx_quality & 0xFF;
1763	sc->wi_sigcache[cache_slot].signal = sig - 149;
1764	sc->wi_sigcache[cache_slot].noise = noise - 149;
1765	sc->wi_sigcache[cache_slot].quality = sig - noise;
1766
1767	return;
1768}
1769#endif
1770