if_wi.c revision 46611
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 *	$Id: if_wi.c,v 1.53 1999/05/07 03:14:21 wpaul Exp $
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 fearures, 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
70#include "bpfilter.h"
71#include "card.h"
72#include "wi.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/sockio.h>
77#include <sys/mbuf.h>
78#include <sys/malloc.h>
79#include <sys/kernel.h>
80#include <sys/socket.h>
81
82#include <net/if.h>
83#include <net/if_arp.h>
84#include <net/ethernet.h>
85#include <net/if_dl.h>
86#include <net/if_media.h>
87#include <net/if_types.h>
88
89#ifdef INET
90#include <netinet/in.h>
91#include <netinet/in_systm.h>
92#include <netinet/in_var.h>
93#include <netinet/ip.h>
94#include <netinet/if_ether.h>
95#endif
96
97#if NBPFILTER > 0
98#include <net/bpf.h>
99#endif
100
101#include <machine/clock.h>
102#include <machine/md_var.h>
103#include <machine/bus_pio.h>
104#include <machine/bus.h>
105
106#include <i386/isa/isa_device.h>
107#include <i386/isa/icu.h>
108#include <i386/isa/if_wireg.h>
109#include <machine/if_wavelan_ieee.h>
110
111#if NCARD > 0
112#include <sys/select.h>
113#include <pccard/cardinfo.h>
114#include <pccard/slot.h>
115#endif
116
117#if !defined(lint)
118static const char rcsid[] =
119	"$Id: if_wi.c,v 1.53 1999/05/07 03:14:21 wpaul Exp $";
120#endif
121
122static struct wi_softc wi_softc[NWI];
123
124#ifdef foo
125static u_int8_t	wi_mcast_addr[6] = { 0x00, 0x60, 0x1D, 0x00, 0x01, 0x00 };
126#endif
127
128static int wi_probe		__P((struct isa_device *));
129static int wi_attach		__P((struct isa_device *));
130#ifdef PCCARD_MODULE
131static ointhand2_t		wi_intr;
132#endif
133static void wi_reset		__P((struct wi_softc *));
134static int wi_ioctl		__P((struct ifnet *, u_long, caddr_t));
135static void wi_init		__P((void *));
136static void wi_start		__P((struct ifnet *));
137static void wi_stop		__P((struct wi_softc *));
138static void wi_watchdog		__P((struct ifnet *));
139static void wi_shutdown		__P((int, void *));
140static void wi_rxeof		__P((struct wi_softc *));
141static void wi_txeof		__P((struct wi_softc *, int));
142static void wi_update_stats	__P((struct wi_softc *));
143static void wi_setmulti		__P((struct wi_softc *));
144
145static int wi_cmd		__P((struct wi_softc *, int, int));
146static int wi_read_record	__P((struct wi_softc *, struct wi_ltv_gen *));
147static int wi_write_record	__P((struct wi_softc *, struct wi_ltv_gen *));
148static int wi_read_data		__P((struct wi_softc *, int,
149					int, caddr_t, int));
150static int wi_write_data	__P((struct wi_softc *, int,
151					int, caddr_t, int));
152static int wi_seek		__P((struct wi_softc *, int, int, int));
153static int wi_alloc_nicmem	__P((struct wi_softc *, int, int *));
154static void wi_inquire		__P((void *));
155static void wi_setdef		__P((struct wi_softc *, struct wi_req *));
156static int wi_mgmt_xmit		__P((struct wi_softc *, caddr_t, int));
157
158struct isa_driver widriver = {
159	wi_probe,
160	wi_attach,
161	"wi",
162	1
163};
164
165#if NCARD > 0
166static int wi_pccard_init	__P((struct pccard_devinfo *));
167static void wi_pccard_unload	__P((struct pccard_devinfo *));
168static int wi_pccard_intr	__P((struct pccard_devinfo *));
169
170#ifdef PCCARD_MODULE
171PCCARD_MODULE(wi, wi_pccard_init, wi_pccard_unload,
172		wi_pccard_intr, 0, net_imask);
173#else
174static struct pccard_device wi_info = {
175	"wi",
176	wi_pccard_init,
177	wi_pccard_unload,
178	wi_pccard_intr,
179	0,			/* Attributes - presently unused */
180	&net_imask		/* Interrupt mask for device */
181				/* XXX - Should this also include net_imask? */
182};
183
184DATA_SET(pccarddrv_set, wi_info);
185#endif
186
187/* Initialize the PCCARD. */
188static int wi_pccard_init(sc_p)
189	struct pccard_devinfo	*sc_p;
190{
191	struct wi_softc		*sc;
192	int			i;
193	u_int32_t		irq;
194
195	if (sc_p->isahd.id_unit >= NWI)
196		return(ENODEV);
197
198	sc = &wi_softc[sc_p->isahd.id_unit];
199	sc->wi_gone = 0;
200	sc->wi_unit = sc_p->isahd.id_unit;
201	sc->wi_bhandle = sc_p->isahd.id_iobase;
202	sc->wi_btag = I386_BUS_SPACE_IO;
203
204	/* Make sure interrupts are disabled. */
205	CSR_WRITE_2(sc, WI_INT_EN, 0);
206	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
207
208	/* Grr. IRQ is encoded as a bitmask. */
209	irq = sc_p->isahd.id_irq;
210	for (i = 0; i < 32; i++) {
211		if (irq & 0x1)
212			break;
213		irq >>= 1;
214	}
215
216	/*
217	 * Print a nice probe message to let the operator
218	 * know something interesting is happening.
219	 */
220	printf("wi%d: <WaveLAN/IEEE 802.11> at 0x%x-0x%x irq %d on isa\n",
221	    sc_p->isahd.id_unit, sc_p->isahd.id_iobase,
222	    sc_p->isahd.id_iobase + WI_IOSIZ - 1, i);
223
224	if (wi_attach(&sc_p->isahd))
225		return(ENXIO);
226
227	return(0);
228}
229
230static void wi_pccard_unload(sc_p)
231	struct pccard_devinfo	*sc_p;
232{
233	struct wi_softc		*sc;
234	struct ifnet		*ifp;
235
236	sc = &wi_softc[sc_p->isahd.id_unit];
237	ifp = &sc->arpcom.ac_if;
238
239	if (sc->wi_gone) {
240		printf("wi%d: already unloaded\n", sc_p->isahd.id_unit);
241		return;
242	}
243
244	ifp->if_flags &= ~IFF_RUNNING;
245	if_down(ifp);
246	sc->wi_gone = 1;
247	printf("wi%d: unloaded\n", sc_p->isahd.id_unit);
248
249	return;
250}
251
252static int wi_pccard_intr(sc_p)
253	struct pccard_devinfo	*sc_p;
254{
255	wi_intr(sc_p->isahd.id_unit);
256	return(1);
257}
258#endif
259
260static int wi_probe(isa_dev)
261	struct isa_device	*isa_dev;
262{
263	/*
264	 * The ISA WaveLAN/IEEE card is actually not an ISA card:
265	 * it's a PCMCIA card plugged into a PCMCIA expander card
266	 * that fits into an ISA slot. Consequently, we will always
267	 * be using the pccard support to probe and attach these
268	 * devices, so we can never actually probe one from here.
269	 */
270	return(0);
271}
272
273static int wi_attach(isa_dev)
274	struct isa_device	*isa_dev;
275{
276	struct wi_softc		*sc;
277	struct wi_ltv_macaddr	mac;
278	struct wi_ltv_gen	gen;
279	struct ifnet		*ifp;
280	char			ifname[IFNAMSIZ];
281
282#ifdef PCCARD_MODULE
283	isa_dev->id_ointr = wi_intr;
284#endif
285	sc = &wi_softc[isa_dev->id_unit];
286	ifp = &sc->arpcom.ac_if;
287
288	/* Reset the NIC. */
289	wi_reset(sc);
290
291	/* Read the station address. */
292	mac.wi_type = WI_RID_MAC_NODE;
293	mac.wi_len = 4;
294	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
295	bcopy((char *)&mac.wi_mac_addr,
296	   (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
297
298	printf("wi%d: Ethernet address: %6D\n", sc->wi_unit,
299	    sc->arpcom.ac_enaddr, ":");
300
301	ifp->if_softc = sc;
302	ifp->if_unit = sc->wi_unit;
303	ifp->if_name = "wi";
304	ifp->if_mtu = ETHERMTU;
305	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
306	ifp->if_ioctl = wi_ioctl;
307	ifp->if_output = ether_output;
308	ifp->if_start = wi_start;
309	ifp->if_watchdog = wi_watchdog;
310	ifp->if_init = wi_init;
311	ifp->if_baudrate = 10000000;
312	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
313
314	bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
315	bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
316	    sizeof(WI_DEFAULT_NODENAME) - 1);
317
318	bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
319	bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
320	    sizeof(WI_DEFAULT_NETNAME) - 1);
321
322	bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
323	bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
324	    sizeof(WI_DEFAULT_IBSS) - 1);
325
326	sc->wi_portnum = WI_DEFAULT_PORT;
327	sc->wi_ptype = WI_PORTTYPE_ADHOC;
328	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
329	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
330	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
331	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
332	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
333	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
334	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
335
336	/*
337	 * Read the default channel from the NIC. This may vary
338	 * depending on the country where the NIC was purchased, so
339	 * we can't hard-code a default and expect it to work for
340	 * everyone.
341	 */
342	gen.wi_type = WI_RID_OWN_CHNL;
343	gen.wi_len = 2;
344	wi_read_record(sc, &gen);
345	sc->wi_channel = gen.wi_val;
346
347	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
348
349	wi_init(sc);
350	wi_stop(sc);
351
352	/*
353	 * If this logical interface has already been attached,
354	 * don't attach it again or chaos will ensue.
355	 */
356	sprintf(ifname, "wi%d", sc->wi_unit);
357
358	if (ifunit(ifname) == NULL) {
359		callout_handle_init(&sc->wi_stat_ch);
360		/*
361		 * Call MI attach routines.
362		 */
363		if_attach(ifp);
364		ether_ifattach(ifp);
365
366#if NBPFILTER > 0
367		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
368#endif
369
370		at_shutdown(wi_shutdown, sc, SHUTDOWN_POST_SYNC);
371	}
372
373	return(0);
374}
375
376static void wi_rxeof(sc)
377	struct wi_softc		*sc;
378{
379	struct ifnet		*ifp;
380	struct ether_header	*eh;
381	struct wi_frame		rx_frame;
382	struct mbuf		*m;
383	int			id;
384
385	ifp = &sc->arpcom.ac_if;
386
387	id = CSR_READ_2(sc, WI_RX_FID);
388
389	/* First read in the frame header */
390	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
391		ifp->if_ierrors++;
392		return;
393	}
394
395	if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
396		ifp->if_ierrors++;
397		return;
398	}
399
400	MGETHDR(m, M_DONTWAIT, MT_DATA);
401	if (m == NULL) {
402		ifp->if_ierrors++;
403		return;
404	}
405	MCLGET(m, M_DONTWAIT);
406	if (!(m->m_flags & M_EXT)) {
407		m_freem(m);
408		ifp->if_ierrors++;
409		return;
410	}
411
412	eh = mtod(m, struct ether_header *);
413	m->m_pkthdr.rcvif = ifp;
414
415	if (rx_frame.wi_status == WI_STAT_1042 ||
416	    rx_frame.wi_status == WI_STAT_TUNNEL ||
417	    rx_frame.wi_status == WI_STAT_WMP_MSG) {
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		bcopy((char *)&rx_frame.wi_addr2,
424		    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
425		bcopy((char *)&rx_frame.wi_type,
426		    (char *)&eh->ether_type, sizeof(u_int16_t));
427
428		if (wi_read_data(sc, id, WI_802_11_OFFSET,
429		    mtod(m, caddr_t) + sizeof(struct ether_header),
430		    m->m_len + 2)) {
431			m_freem(m);
432			ifp->if_ierrors++;
433			return;
434		}
435	} else {
436		m->m_pkthdr.len = m->m_len =
437		    rx_frame.wi_dat_len + sizeof(struct ether_header);
438
439		if (wi_read_data(sc, id, WI_802_3_OFFSET,
440		    mtod(m, caddr_t), m->m_len + 2)) {
441			m_freem(m);
442			ifp->if_ierrors++;
443			return;
444		}
445	}
446
447	ifp->if_ipackets++;
448
449#if NBPFILTER > 0
450	/* Handle BPF listeners. */
451	if (ifp->if_bpf) {
452		bpf_mtap(ifp, m);
453		if (ifp->if_flags & IFF_PROMISC &&
454		    (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
455		    ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
456			m_freem(m);
457			return;
458		}
459	}
460#endif
461
462	/* Receive packet. */
463	m_adj(m, sizeof(struct ether_header));
464	ether_input(ifp, eh, m);
465
466	return;
467}
468
469static void wi_txeof(sc, status)
470	struct wi_softc		*sc;
471	int			status;
472{
473	struct ifnet		*ifp;
474
475	ifp = &sc->arpcom.ac_if;
476
477	ifp->if_timer = 0;
478	ifp->if_flags &= ~IFF_OACTIVE;
479
480	if (status & WI_EV_TX_EXC)
481		ifp->if_oerrors++;
482	else
483		ifp->if_opackets++;
484
485	return;
486}
487
488void wi_inquire(xsc)
489	void			*xsc;
490{
491	struct wi_softc		*sc;
492	struct ifnet		*ifp;
493
494	sc = xsc;
495	ifp = &sc->arpcom.ac_if;
496
497	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
498
499	/* Don't do this while we're transmitting */
500	if (ifp->if_flags & IFF_OACTIVE)
501		return;
502
503	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
504
505	return;
506}
507
508void wi_update_stats(sc)
509	struct wi_softc		*sc;
510{
511	struct wi_ltv_gen	gen;
512	u_int16_t		id;
513	struct ifnet		*ifp;
514	u_int32_t		*ptr;
515	int			i;
516	u_int16_t		t;
517
518	ifp = &sc->arpcom.ac_if;
519
520	id = CSR_READ_2(sc, WI_INFO_FID);
521
522	wi_read_data(sc, id, 0, (char *)&gen, 4);
523
524	if (gen.wi_type != WI_INFO_COUNTERS ||
525	    gen.wi_len > (sizeof(sc->wi_stats) / 4) + 1)
526		return;
527
528	ptr = (u_int32_t *)&sc->wi_stats;
529
530	for (i = 0; i < gen.wi_len - 1; i++) {
531		t = CSR_READ_2(sc, WI_DATA1);
532#ifdef WI_HERMES_STATS_WAR
533		if (t > 0xF000)
534			t = ~t & 0xFFFF;
535#endif
536		ptr[i] += t;
537	}
538
539	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
540	    sc->wi_stats.wi_tx_multi_retries +
541	    sc->wi_stats.wi_tx_retry_limit;
542
543	return;
544}
545
546void wi_intr(unit)
547	int			unit;
548{
549	struct wi_softc		*sc;
550	struct ifnet		*ifp;
551	u_int16_t		status;
552
553	sc = &wi_softc[unit];
554	ifp = &sc->arpcom.ac_if;
555
556	if (!(ifp->if_flags & IFF_UP)) {
557		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
558		CSR_WRITE_2(sc, WI_INT_EN, 0);
559		return;
560	}
561
562	/* Disable interrupts. */
563	CSR_WRITE_2(sc, WI_INT_EN, 0);
564
565	status = CSR_READ_2(sc, WI_EVENT_STAT);
566	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
567
568	if (status & WI_EV_RX) {
569		wi_rxeof(sc);
570		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
571	}
572
573	if (status & WI_EV_TX) {
574		wi_txeof(sc, status);
575		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
576	}
577
578	if (status & WI_EV_ALLOC) {
579		int			id;
580		id = CSR_READ_2(sc, WI_ALLOC_FID);
581		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
582		if (id == sc->wi_tx_data_id)
583			wi_txeof(sc, status);
584	}
585
586	if (status & WI_EV_INFO) {
587		wi_update_stats(sc);
588		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
589	}
590
591	if (status & WI_EV_TX_EXC) {
592		wi_txeof(sc, status);
593		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
594	}
595
596	if (status & WI_EV_INFO_DROP) {
597		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
598	}
599
600	/* Re-enable interrupts. */
601	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
602
603	if (ifp->if_snd.ifq_head != NULL)
604		wi_start(ifp);
605
606	return;
607}
608
609static int wi_cmd(sc, cmd, val)
610	struct wi_softc		*sc;
611	int			cmd;
612	int			val;
613{
614	int			i, s = 0;
615
616	CSR_WRITE_2(sc, WI_PARAM0, val);
617	CSR_WRITE_2(sc, WI_COMMAND, cmd);
618
619	for (i = 0; i < WI_TIMEOUT; i++) {
620		/*
621		 * Wait for 'command complete' bit to be
622		 * set in the event status register.
623		 */
624		s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
625		if (s) {
626			/* Ack the event and read result code. */
627			s = CSR_READ_2(sc, WI_STATUS);
628			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
629#ifdef foo
630			if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
631				return(EIO);
632#endif
633			if (s & WI_STAT_CMD_RESULT)
634				return(EIO);
635			break;
636		}
637	}
638
639	if (i == WI_TIMEOUT)
640		return(ETIMEDOUT);
641
642	return(0);
643}
644
645static void wi_reset(sc)
646	struct wi_softc		*sc;
647{
648	if (wi_cmd(sc, WI_CMD_INI, 0))
649		printf("wi%d: init failed\n", sc->wi_unit);
650	CSR_WRITE_2(sc, WI_INT_EN, 0);
651	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
652
653	/* Calibrate timer. */
654	WI_SETVAL(WI_RID_TICK_TIME, 8);
655
656	return;
657}
658
659/*
660 * Read an LTV record from the NIC.
661 */
662static int wi_read_record(sc, ltv)
663	struct wi_softc		*sc;
664	struct wi_ltv_gen	*ltv;
665{
666	u_int16_t		*ptr;
667	int			i, len, code;
668
669	/* Tell the NIC to enter record read mode. */
670	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
671		return(EIO);
672
673	/* Select the record we want to read. */
674	CSR_WRITE_2(sc, WI_SEL1, ltv->wi_type);
675
676	/* Specify offset -- we always read the whole record. */
677	CSR_WRITE_2(sc, WI_OFF1, 0);
678
679	/* Wait for NIC to acknowledge */
680	for (i = 0; i < WI_TIMEOUT; i++) {
681		if (!(CSR_READ_2(sc, WI_OFF1) & (WI_OFF_BUSY|WI_OFF_ERR)))
682			break;
683	}
684
685	if (i == WI_TIMEOUT)
686		return(ETIMEDOUT);
687
688	/*
689	 * Read the length and record type and make sure they
690	 * match what we expect (this verifies that we have enough
691	 * room to hold all of the returned data.
692	 */
693	len = CSR_READ_2(sc, WI_DATA1);
694	if (len > ltv->wi_len)
695		return(ENOSPC);
696	code = CSR_READ_2(sc, WI_DATA1);
697	if (code != ltv->wi_type)
698		return(EIO);
699
700	ltv->wi_len = len;
701	ltv->wi_type = code;
702
703	/* Now read the data. */
704	ptr = &ltv->wi_val;
705	for (i = 0; i < ltv->wi_len - 1; i++)
706		ptr[i] = CSR_READ_2(sc, WI_DATA1);
707
708	return(0);
709}
710
711/*
712 * Same as read, except we inject data instead of reading it.
713 */
714static int wi_write_record(sc, ltv)
715	struct wi_softc		*sc;
716	struct wi_ltv_gen	*ltv;
717{
718	u_int16_t		*ptr;
719	int			i;
720
721	CSR_WRITE_2(sc, WI_SEL1, ltv->wi_type);
722	CSR_WRITE_2(sc, WI_OFF1, 0);
723
724	for (i = 0; i < WI_TIMEOUT; i++) {
725		if (!(CSR_READ_2(sc, WI_OFF1) & (WI_OFF_BUSY|WI_OFF_ERR)))
726			break;
727	}
728
729	if (i == WI_TIMEOUT)
730		return(ETIMEDOUT);
731
732	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
733	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
734
735	ptr = &ltv->wi_val;
736	for (i = 0; i < ltv->wi_len - 1; i++)
737		CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
738
739	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
740		return(EIO);
741
742	return(0);
743}
744
745static int wi_seek(sc, id, off, chan)
746	struct wi_softc		*sc;
747	int			id, off, chan;
748{
749	int			i;
750	int			selreg, offreg;
751
752	switch (chan) {
753	case WI_BAP0:
754		selreg = WI_SEL0;
755		offreg = WI_OFF0;
756		break;
757	case WI_BAP1:
758		selreg = WI_SEL1;
759		offreg = WI_OFF1;
760		break;
761	default:
762		printf("wi%d: invalid data path: %x\n", sc->wi_unit, chan);
763		return(EIO);
764	}
765
766	CSR_WRITE_2(sc, selreg, id);
767	CSR_WRITE_2(sc, offreg, off);
768
769	for (i = 0; i < WI_TIMEOUT; i++) {
770		if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
771			break;
772	}
773
774	if (i == WI_TIMEOUT)
775		return(ETIMEDOUT);
776
777	return(0);
778}
779
780static int wi_read_data(sc, id, off, buf, len)
781	struct wi_softc		*sc;
782	int			id, off;
783	caddr_t			buf;
784	int			len;
785{
786	int			i;
787	u_int16_t		*ptr;
788
789	if (wi_seek(sc, id, off, WI_BAP1))
790		return(EIO);
791
792	ptr = (u_int16_t *)buf;
793	for (i = 0; i < len / 2; i++)
794		ptr[i] = CSR_READ_2(sc, WI_DATA1);
795
796	return(0);
797}
798
799/*
800 * According to the comments in the HCF Light code, there is a bug in
801 * the Hermes (or possibly in certain Hermes firmware revisions) where
802 * the chip's internal autoincrement counter gets thrown off during
803 * data writes: the autoincrement is missed, causing one data word to
804 * be overwritten and subsequent words to be written to the wrong memory
805 * locations. The end result is that we could end up transmitting bogus
806 * frames without realizing it. The workaround for this is to write a
807 * couple of extra guard words after the end of the transfer, then
808 * attempt to read then back. If we fail to locate the guard words where
809 * we expect them, we preform the transfer over again.
810 */
811static int wi_write_data(sc, id, off, buf, len)
812	struct wi_softc		*sc;
813	int			id, off;
814	caddr_t			buf;
815	int			len;
816{
817	int			i;
818	u_int16_t		*ptr;
819
820#ifdef WI_HERMES_AUTOINC_WAR
821again:
822#endif
823
824	if (wi_seek(sc, id, off, WI_BAP0))
825		return(EIO);
826
827	ptr = (u_int16_t *)buf;
828	for (i = 0; i < (len / 2); i++)
829		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
830
831#ifdef WI_HERMES_AUTOINC_WAR
832	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
833	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
834
835	if (wi_seek(sc, id, off + len, WI_BAP0))
836		return(EIO);
837
838	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
839	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
840		goto again;
841#endif
842
843	return(0);
844}
845
846/*
847 * Allocate a region of memory inside the NIC and zero
848 * it out.
849 */
850static int wi_alloc_nicmem(sc, len, id)
851	struct wi_softc		*sc;
852	int			len;
853	int			*id;
854{
855	int			i;
856
857	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
858		printf("wi%d: failed to allocate %d bytes on NIC\n",
859		    sc->wi_unit, len);
860		return(ENOMEM);
861	}
862
863	for (i = 0; i < WI_TIMEOUT; i++) {
864		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
865			break;
866	}
867
868	if (i == WI_TIMEOUT)
869		return(ETIMEDOUT);
870
871	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
872	*id = CSR_READ_2(sc, WI_ALLOC_FID);
873
874	wi_seek(sc, *id, 0, WI_BAP0);
875
876	for (i = 0; i < len / 2; i++)
877		CSR_WRITE_2(sc, WI_DATA0, 0);
878
879	return(0);
880}
881
882static void wi_setmulti(sc)
883	struct wi_softc		*sc;
884{
885	struct ifnet		*ifp;
886	int			i = 0;
887	struct ifmultiaddr	*ifma;
888	struct wi_ltv_mcast	mcast;
889
890	ifp = &sc->arpcom.ac_if;
891
892	bzero((char *)&mcast, sizeof(mcast));
893
894	mcast.wi_type = WI_RID_MCAST;
895	mcast.wi_len = (3 * 16) + 1;
896
897	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
898		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
899		return;
900	}
901
902	for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
903				ifma = ifma->ifma_link.le_next) {
904		if (ifma->ifma_addr->sa_family != AF_LINK)
905			continue;
906		if (i < 16) {
907			bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
908			    (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
909			i++;
910		} else {
911			bzero((char *)&mcast, sizeof(mcast));
912			break;
913		}
914	}
915
916	mcast.wi_len = (i * 3) + 1;
917	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
918
919	return;
920}
921
922static void wi_setdef(sc, wreq)
923	struct wi_softc		*sc;
924	struct wi_req		*wreq;
925{
926	struct sockaddr_dl	*sdl;
927	struct ifaddr		*ifa;
928	struct ifnet		*ifp;
929
930	ifp = &sc->arpcom.ac_if;
931
932	switch(wreq->wi_type) {
933	case WI_RID_MAC_NODE:
934		ifa = ifnet_addrs[ifp->if_index - 1];
935		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
936		bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
937		   ETHER_ADDR_LEN);
938		bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
939		break;
940	case WI_RID_PORTTYPE:
941		sc->wi_ptype = wreq->wi_val[0];
942		break;
943	case WI_RID_TX_RATE:
944		sc->wi_tx_rate = wreq->wi_val[0];
945		break;
946	case WI_RID_MAX_DATALEN:
947		sc->wi_max_data_len = wreq->wi_val[0];
948		break;
949	case WI_RID_RTS_THRESH:
950		sc->wi_rts_thresh = wreq->wi_val[0];
951		break;
952	case WI_RID_SYSTEM_SCALE:
953		sc->wi_ap_density = wreq->wi_val[0];
954		break;
955	case WI_RID_CREATE_IBSS:
956		sc->wi_create_ibss = wreq->wi_val[0];
957		break;
958	case WI_RID_OWN_CHNL:
959		sc->wi_channel = wreq->wi_val[0];
960		break;
961	case WI_RID_NODENAME:
962		bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
963		bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
964		break;
965	case WI_RID_DESIRED_SSID:
966		bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
967		bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
968		break;
969	case WI_RID_OWN_SSID:
970		bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
971		bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
972		break;
973	case WI_RID_PM_ENABLED:
974		sc->wi_pm_enabled = wreq->wi_val[0];
975		break;
976	case WI_RID_MAX_SLEEP:
977		sc->wi_max_sleep = wreq->wi_val[0];
978		break;
979	default:
980		break;
981	}
982
983	/* Reinitialize WaveLAN. */
984	wi_init(sc);
985
986	return;
987}
988
989static int wi_ioctl(ifp, command, data)
990	struct ifnet		*ifp;
991	u_long			command;
992	caddr_t			data;
993{
994	int			s, error = 0;
995	struct wi_softc		*sc;
996	struct wi_req		wreq;
997	struct ifreq		*ifr;
998
999	s = splimp();
1000
1001	sc = ifp->if_softc;
1002	ifr = (struct ifreq *)data;
1003
1004	if (sc->wi_gone)
1005		return(ENODEV);
1006
1007	switch(command) {
1008	case SIOCSIFADDR:
1009	case SIOCGIFADDR:
1010	case SIOCSIFMTU:
1011		error = ether_ioctl(ifp, command, data);
1012		break;
1013	case SIOCSIFFLAGS:
1014		if (ifp->if_flags & IFF_UP) {
1015			if (ifp->if_flags & IFF_RUNNING &&
1016			    ifp->if_flags & IFF_PROMISC &&
1017			    !(sc->wi_if_flags & IFF_PROMISC)) {
1018				WI_SETVAL(WI_RID_PROMISC, 1);
1019			} else if (ifp->if_flags & IFF_RUNNING &&
1020			    !(ifp->if_flags & IFF_PROMISC) &&
1021			    sc->wi_if_flags & IFF_PROMISC) {
1022				WI_SETVAL(WI_RID_PROMISC, 0);
1023			} else
1024				wi_init(sc);
1025		} else {
1026			if (ifp->if_flags & IFF_RUNNING) {
1027				wi_stop(sc);
1028			}
1029		}
1030		sc->wi_if_flags = ifp->if_flags;
1031		error = 0;
1032		break;
1033	case SIOCADDMULTI:
1034	case SIOCDELMULTI:
1035		wi_setmulti(sc);
1036		error = 0;
1037		break;
1038	case SIOCGWAVELAN:
1039		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1040		if (error)
1041			break;
1042		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1043			bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1044			    sizeof(sc->wi_stats));
1045			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1046		} else {
1047			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1048				error = EINVAL;
1049				break;
1050			}
1051		}
1052		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1053		break;
1054	case SIOCSWAVELAN:
1055		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1056		if (error)
1057			break;
1058		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1059			error = EINVAL;
1060			break;
1061		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1062			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1063			    wreq.wi_len);
1064		} else {
1065			error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1066			if (!error)
1067				wi_setdef(sc, &wreq);
1068		}
1069		break;
1070	default:
1071		error = EINVAL;
1072		break;
1073	}
1074
1075	splx(s);
1076
1077	return(error);
1078}
1079
1080static void wi_init(xsc)
1081	void			*xsc;
1082{
1083	struct wi_softc		*sc = xsc;
1084	struct ifnet		*ifp = &sc->arpcom.ac_if;
1085	int			s;
1086	struct wi_ltv_macaddr	mac;
1087	int			id = 0;
1088
1089	if (sc->wi_gone)
1090		return;
1091
1092	s = splimp();
1093
1094	if (ifp->if_flags & IFF_RUNNING)
1095		wi_stop(sc);
1096
1097	wi_reset(sc);
1098
1099	/* Program max data length. */
1100	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1101
1102	/* Enable/disable IBSS ctration. */
1103	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1104
1105	/* Set the port type. */
1106	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1107
1108	/* Program the RTS/CTS threshold. */
1109	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1110
1111	/* Program the TX rate */
1112	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1113
1114	/* Access point density */
1115	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1116
1117	/* Power Management Enabled */
1118	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1119
1120	/* Power Managment Max Sleep */
1121	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1122
1123	/* Specify the IBSS name */
1124	WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1125
1126	/* Specify the network name */
1127	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1128
1129	/* Specify the frequency to use */
1130	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1131
1132	/* Program the nodename. */
1133	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1134
1135	/* Set our MAC address. */
1136	mac.wi_len = 4;
1137	mac.wi_type = WI_RID_MAC_NODE;
1138	bcopy((char *)&sc->arpcom.ac_enaddr,
1139	   (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1140	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1141
1142	/* Initialize promisc mode. */
1143	if (ifp->if_flags & IFF_PROMISC) {
1144		WI_SETVAL(WI_RID_PROMISC, 1);
1145	} else {
1146		WI_SETVAL(WI_RID_PROMISC, 0);
1147	}
1148
1149	/* Set multicast filter. */
1150	wi_setmulti(sc);
1151
1152	/* Enable desired port */
1153	wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1154
1155	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1156		printf("wi%d: tx buffer allocation failed\n", sc->wi_unit);
1157	sc->wi_tx_data_id = id;
1158
1159	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1160		printf("wi%d: mgmt. buffer allocation failed\n", sc->wi_unit);
1161	sc->wi_tx_mgmt_id = id;
1162
1163	/* enable interrupts */
1164	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1165
1166	splx(s);
1167
1168	ifp->if_flags |= IFF_RUNNING;
1169	ifp->if_flags &= ~IFF_OACTIVE;
1170
1171	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
1172
1173	return;
1174}
1175
1176static void wi_start(ifp)
1177	struct ifnet		*ifp;
1178{
1179	struct wi_softc		*sc;
1180	struct mbuf		*m0;
1181	struct wi_frame		tx_frame;
1182	struct ether_header	*eh;
1183	int			id;
1184
1185	sc = ifp->if_softc;
1186
1187	if (sc->wi_gone)
1188		return;
1189
1190	if (ifp->if_flags & IFF_OACTIVE)
1191		return;
1192
1193	IF_DEQUEUE(&ifp->if_snd, m0);
1194	if (m0 == NULL)
1195		return;
1196
1197	bzero((char *)&tx_frame, sizeof(tx_frame));
1198	id = sc->wi_tx_data_id;
1199	eh = mtod(m0, struct ether_header *);
1200
1201	/*
1202	 * Use RFC1042 encoding for IP and ARP datagrames,
1203	 * 802.3 for anything else.
1204	 */
1205	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1206	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1207	    ntohs(eh->ether_type) == ETHERTYPE_REVARP) {
1208		bcopy((char *)&eh->ether_dhost,
1209		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1210		bcopy((char *)&eh->ether_shost,
1211		    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1212		bcopy((char *)&eh->ether_dhost,
1213		    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1214		bcopy((char *)&eh->ether_shost,
1215		    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1216
1217		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
1218		tx_frame.wi_frame_ctl = WI_FTYPE_DATA;
1219		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1220		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1221		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1222		tx_frame.wi_type = eh->ether_type;
1223
1224		m_copydata(m0, sizeof(struct ether_header),
1225		    m0->m_pkthdr.len - sizeof(struct ether_header),
1226		    (caddr_t)&sc->wi_txbuf);
1227
1228		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1229		    sizeof(struct wi_frame));
1230		wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1231		    (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1232	} else {
1233		tx_frame.wi_dat_len = m0->m_pkthdr.len;
1234
1235		m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1236
1237		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1238		    sizeof(struct wi_frame));
1239		wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1240		    m0->m_pkthdr.len + 2);
1241	}
1242
1243#if NBPFILTER > 0
1244	/*
1245	 * If there's a BPF listner, bounce a copy of
1246	 * this frame to him.
1247	 */
1248	if (ifp->if_bpf)
1249		bpf_mtap(ifp, m0);
1250#endif
1251
1252	m_freem(m0);
1253
1254	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1255		printf("wi%d: xmit failed\n", sc->wi_unit);
1256
1257	ifp->if_flags |= IFF_OACTIVE;
1258
1259	/*
1260	 * Set a timeout in case the chip goes out to lunch.
1261	 */
1262	ifp->if_timer = 5;
1263
1264	return;
1265}
1266
1267static int wi_mgmt_xmit(sc, data, len)
1268	struct wi_softc		*sc;
1269	caddr_t			data;
1270	int			len;
1271{
1272	struct wi_frame		tx_frame;
1273	int			id;
1274	struct wi_80211_hdr	*hdr;
1275	caddr_t			dptr;
1276
1277	if (sc->wi_gone)
1278		return(ENODEV);
1279
1280	hdr = (struct wi_80211_hdr *)data;
1281	dptr = data + sizeof(struct wi_80211_hdr);
1282
1283	bzero((char *)&tx_frame, sizeof(tx_frame));
1284	id = sc->wi_tx_mgmt_id;
1285
1286	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1287	   sizeof(struct wi_80211_hdr));
1288
1289	tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1290	tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1291
1292	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1293	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1294	    (len - sizeof(struct wi_80211_hdr)) + 2);
1295
1296	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1297		printf("wi%d: xmit failed\n", sc->wi_unit);
1298		return(EIO);
1299	}
1300
1301	return(0);
1302}
1303
1304static void wi_stop(sc)
1305	struct wi_softc		*sc;
1306{
1307	struct ifnet		*ifp;
1308
1309	if (sc->wi_gone)
1310		return;
1311
1312	ifp = &sc->arpcom.ac_if;
1313
1314	CSR_WRITE_2(sc, WI_INT_EN, 0);
1315	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1316
1317	untimeout(wi_inquire, sc, sc->wi_stat_ch);
1318
1319	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1320
1321	return;
1322}
1323
1324static void wi_watchdog(ifp)
1325	struct ifnet		*ifp;
1326{
1327	struct wi_softc		*sc;
1328
1329	sc = ifp->if_softc;
1330
1331	printf("wi%d: device timeout\n", sc->wi_unit);
1332
1333	wi_init(sc);
1334
1335	ifp->if_oerrors++;
1336
1337	return;
1338}
1339
1340static void wi_shutdown(howto, arg)
1341	int			howto;
1342	void			*arg;
1343{
1344	struct wi_softc		*sc;
1345
1346	sc = arg;
1347	wi_stop(sc);
1348
1349	return;
1350}
1351