if_wi.c revision 52632
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 52632 1999-10-29 17:28:09Z imp $
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
70#include "card.h"
71#undef NCARD
72#define NCARD 0
73#include "wi.h"
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/eventhandler.h>
78#include <sys/sockio.h>
79#include <sys/mbuf.h>
80#include <sys/malloc.h>
81#include <sys/kernel.h>
82#include <sys/socket.h>
83
84#include <net/if.h>
85#include <net/if_arp.h>
86#include <net/ethernet.h>
87#include <net/if_dl.h>
88#include <net/if_media.h>
89#include <net/if_types.h>
90
91#ifdef INET
92#include <netinet/in.h>
93#include <netinet/in_systm.h>
94#include <netinet/in_var.h>
95#include <netinet/ip.h>
96#include <netinet/if_ether.h>
97#endif
98
99#include <net/bpf.h>
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  "$FreeBSD: head/sys/dev/wi/if_wi.c 52632 1999-10-29 17:28:09Z imp $";
120#endif
121
122static struct wi_softc wi_softc[NWI];
123
124#ifdef foo
125static u_int8_t	wi_mcast_addr[6] = { 0x01, 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((void *, int));
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 bridge adapter
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		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
367
368		EVENTHANDLER_REGISTER(shutdown_post_sync, wi_shutdown, sc,
369				      SHUTDOWN_PRI_DEFAULT);
370	}
371
372	return(0);
373}
374
375static void wi_rxeof(sc)
376	struct wi_softc		*sc;
377{
378	struct ifnet		*ifp;
379	struct ether_header	*eh;
380	struct wi_frame		rx_frame;
381	struct mbuf		*m;
382	int			id;
383
384	ifp = &sc->arpcom.ac_if;
385
386	id = CSR_READ_2(sc, WI_RX_FID);
387
388	/* First read in the frame header */
389	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
390		ifp->if_ierrors++;
391		return;
392	}
393
394	if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
395		ifp->if_ierrors++;
396		return;
397	}
398
399	MGETHDR(m, M_DONTWAIT, MT_DATA);
400	if (m == NULL) {
401		ifp->if_ierrors++;
402		return;
403	}
404	MCLGET(m, M_DONTWAIT);
405	if (!(m->m_flags & M_EXT)) {
406		m_freem(m);
407		ifp->if_ierrors++;
408		return;
409	}
410
411	eh = mtod(m, struct ether_header *);
412	m->m_pkthdr.rcvif = ifp;
413
414	if (rx_frame.wi_status == WI_STAT_1042 ||
415	    rx_frame.wi_status == WI_STAT_TUNNEL ||
416	    rx_frame.wi_status == WI_STAT_WMP_MSG) {
417		if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
418			printf("wi%d: oversized packet received "
419			    "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
420			    rx_frame.wi_dat_len, rx_frame.wi_status);
421			m_freem(m);
422			ifp->if_ierrors++;
423			return;
424		}
425		m->m_pkthdr.len = m->m_len =
426		    rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
427
428		bcopy((char *)&rx_frame.wi_addr1,
429		    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
430		bcopy((char *)&rx_frame.wi_addr2,
431		    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
432		bcopy((char *)&rx_frame.wi_type,
433		    (char *)&eh->ether_type, sizeof(u_int16_t));
434
435		if (wi_read_data(sc, id, WI_802_11_OFFSET,
436		    mtod(m, caddr_t) + sizeof(struct ether_header),
437		    m->m_len + 2)) {
438			m_freem(m);
439			ifp->if_ierrors++;
440			return;
441		}
442	} else {
443		if((rx_frame.wi_dat_len +
444		    sizeof(struct ether_header)) > MCLBYTES) {
445			printf("wi%d: oversized packet received "
446			    "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit,
447			    rx_frame.wi_dat_len, rx_frame.wi_status);
448			m_freem(m);
449			ifp->if_ierrors++;
450			return;
451		}
452		m->m_pkthdr.len = m->m_len =
453		    rx_frame.wi_dat_len + sizeof(struct ether_header);
454
455		if (wi_read_data(sc, id, WI_802_3_OFFSET,
456		    mtod(m, caddr_t), m->m_len + 2)) {
457			m_freem(m);
458			ifp->if_ierrors++;
459			return;
460		}
461	}
462
463	ifp->if_ipackets++;
464
465	/* Handle BPF listeners. */
466	if (ifp->if_bpf) {
467		bpf_mtap(ifp, m);
468		if (ifp->if_flags & IFF_PROMISC &&
469		    (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
470		    ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
471			m_freem(m);
472			return;
473		}
474	}
475
476	/* Receive packet. */
477	m_adj(m, sizeof(struct ether_header));
478	ether_input(ifp, eh, m);
479
480	return;
481}
482
483static void wi_txeof(sc, status)
484	struct wi_softc		*sc;
485	int			status;
486{
487	struct ifnet		*ifp;
488
489	ifp = &sc->arpcom.ac_if;
490
491	ifp->if_timer = 0;
492	ifp->if_flags &= ~IFF_OACTIVE;
493
494	if (status & WI_EV_TX_EXC)
495		ifp->if_oerrors++;
496	else
497		ifp->if_opackets++;
498
499	return;
500}
501
502void wi_inquire(xsc)
503	void			*xsc;
504{
505	struct wi_softc		*sc;
506	struct ifnet		*ifp;
507
508	sc = xsc;
509	ifp = &sc->arpcom.ac_if;
510
511	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
512
513	/* Don't do this while we're transmitting */
514	if (ifp->if_flags & IFF_OACTIVE)
515		return;
516
517	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
518
519	return;
520}
521
522void wi_update_stats(sc)
523	struct wi_softc		*sc;
524{
525	struct wi_ltv_gen	gen;
526	u_int16_t		id;
527	struct ifnet		*ifp;
528	u_int32_t		*ptr;
529	int			i;
530	u_int16_t		t;
531
532	ifp = &sc->arpcom.ac_if;
533
534	id = CSR_READ_2(sc, WI_INFO_FID);
535
536	wi_read_data(sc, id, 0, (char *)&gen, 4);
537
538	if (gen.wi_type != WI_INFO_COUNTERS ||
539	    gen.wi_len > (sizeof(sc->wi_stats) / 4) + 1)
540		return;
541
542	ptr = (u_int32_t *)&sc->wi_stats;
543
544	for (i = 0; i < gen.wi_len - 1; i++) {
545		t = CSR_READ_2(sc, WI_DATA1);
546#ifdef WI_HERMES_STATS_WAR
547		if (t > 0xF000)
548			t = ~t & 0xFFFF;
549#endif
550		ptr[i] += t;
551	}
552
553	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
554	    sc->wi_stats.wi_tx_multi_retries +
555	    sc->wi_stats.wi_tx_retry_limit;
556
557	return;
558}
559
560void wi_intr(unit)
561	int			unit;
562{
563	struct wi_softc		*sc;
564	struct ifnet		*ifp;
565	u_int16_t		status;
566
567	sc = &wi_softc[unit];
568	ifp = &sc->arpcom.ac_if;
569
570	if (!(ifp->if_flags & IFF_UP)) {
571		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
572		CSR_WRITE_2(sc, WI_INT_EN, 0);
573		return;
574	}
575
576	/* Disable interrupts. */
577	CSR_WRITE_2(sc, WI_INT_EN, 0);
578
579	status = CSR_READ_2(sc, WI_EVENT_STAT);
580	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
581
582	if (status & WI_EV_RX) {
583		wi_rxeof(sc);
584		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
585	}
586
587	if (status & WI_EV_TX) {
588		wi_txeof(sc, status);
589		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
590	}
591
592	if (status & WI_EV_ALLOC) {
593		int			id;
594		id = CSR_READ_2(sc, WI_ALLOC_FID);
595		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
596		if (id == sc->wi_tx_data_id)
597			wi_txeof(sc, status);
598	}
599
600	if (status & WI_EV_INFO) {
601		wi_update_stats(sc);
602		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
603	}
604
605	if (status & WI_EV_TX_EXC) {
606		wi_txeof(sc, status);
607		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
608	}
609
610	if (status & WI_EV_INFO_DROP) {
611		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
612	}
613
614	/* Re-enable interrupts. */
615	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
616
617	if (ifp->if_snd.ifq_head != NULL)
618		wi_start(ifp);
619
620	return;
621}
622
623static int wi_cmd(sc, cmd, val)
624	struct wi_softc		*sc;
625	int			cmd;
626	int			val;
627{
628	int			i, s = 0;
629
630	CSR_WRITE_2(sc, WI_PARAM0, val);
631	CSR_WRITE_2(sc, WI_COMMAND, cmd);
632
633	for (i = 0; i < WI_TIMEOUT; i++) {
634		/*
635		 * Wait for 'command complete' bit to be
636		 * set in the event status register.
637		 */
638		s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
639		if (s) {
640			/* Ack the event and read result code. */
641			s = CSR_READ_2(sc, WI_STATUS);
642			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
643#ifdef foo
644			if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
645				return(EIO);
646#endif
647			if (s & WI_STAT_CMD_RESULT)
648				return(EIO);
649			break;
650		}
651	}
652
653	if (i == WI_TIMEOUT)
654		return(ETIMEDOUT);
655
656	return(0);
657}
658
659static void wi_reset(sc)
660	struct wi_softc		*sc;
661{
662	if (wi_cmd(sc, WI_CMD_INI, 0))
663		printf("wi%d: init failed\n", sc->wi_unit);
664	CSR_WRITE_2(sc, WI_INT_EN, 0);
665	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
666
667	/* Calibrate timer. */
668	WI_SETVAL(WI_RID_TICK_TIME, 8);
669
670	return;
671}
672
673/*
674 * Read an LTV record from the NIC.
675 */
676static int wi_read_record(sc, ltv)
677	struct wi_softc		*sc;
678	struct wi_ltv_gen	*ltv;
679{
680	u_int16_t		*ptr;
681	int			i, len, code;
682
683	/* Tell the NIC to enter record read mode. */
684	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
685		return(EIO);
686
687	/* Seek to the record. */
688	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
689		return(EIO);
690
691	/*
692	 * Read the length and record type and make sure they
693	 * match what we expect (this verifies that we have enough
694	 * room to hold all of the returned data).
695	 */
696	len = CSR_READ_2(sc, WI_DATA1);
697	if (len > ltv->wi_len)
698		return(ENOSPC);
699	code = CSR_READ_2(sc, WI_DATA1);
700	if (code != ltv->wi_type)
701		return(EIO);
702
703	ltv->wi_len = len;
704	ltv->wi_type = code;
705
706	/* Now read the data. */
707	ptr = &ltv->wi_val;
708	for (i = 0; i < ltv->wi_len - 1; i++)
709		ptr[i] = CSR_READ_2(sc, WI_DATA1);
710
711	return(0);
712}
713
714/*
715 * Same as read, except we inject data instead of reading it.
716 */
717static int wi_write_record(sc, ltv)
718	struct wi_softc		*sc;
719	struct wi_ltv_gen	*ltv;
720{
721	u_int16_t		*ptr;
722	int			i;
723
724	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
725		return(EIO);
726
727	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
728	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
729
730	ptr = &ltv->wi_val;
731	for (i = 0; i < ltv->wi_len - 1; i++)
732		CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
733
734	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
735		return(EIO);
736
737	return(0);
738}
739
740static int wi_seek(sc, id, off, chan)
741	struct wi_softc		*sc;
742	int			id, off, chan;
743{
744	int			i;
745	int			selreg, offreg;
746
747	switch (chan) {
748	case WI_BAP0:
749		selreg = WI_SEL0;
750		offreg = WI_OFF0;
751		break;
752	case WI_BAP1:
753		selreg = WI_SEL1;
754		offreg = WI_OFF1;
755		break;
756	default:
757		printf("wi%d: invalid data path: %x\n", sc->wi_unit, chan);
758		return(EIO);
759	}
760
761	CSR_WRITE_2(sc, selreg, id);
762	CSR_WRITE_2(sc, offreg, off);
763
764	for (i = 0; i < WI_TIMEOUT; i++) {
765		if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
766			break;
767	}
768
769	if (i == WI_TIMEOUT)
770		return(ETIMEDOUT);
771
772	return(0);
773}
774
775static int wi_read_data(sc, id, off, buf, len)
776	struct wi_softc		*sc;
777	int			id, off;
778	caddr_t			buf;
779	int			len;
780{
781	int			i;
782	u_int16_t		*ptr;
783
784	if (wi_seek(sc, id, off, WI_BAP1))
785		return(EIO);
786
787	ptr = (u_int16_t *)buf;
788	for (i = 0; i < len / 2; i++)
789		ptr[i] = CSR_READ_2(sc, WI_DATA1);
790
791	return(0);
792}
793
794/*
795 * According to the comments in the HCF Light code, there is a bug in
796 * the Hermes (or possibly in certain Hermes firmware revisions) where
797 * the chip's internal autoincrement counter gets thrown off during
798 * data writes: the autoincrement is missed, causing one data word to
799 * be overwritten and subsequent words to be written to the wrong memory
800 * locations. The end result is that we could end up transmitting bogus
801 * frames without realizing it. The workaround for this is to write a
802 * couple of extra guard words after the end of the transfer, then
803 * attempt to read then back. If we fail to locate the guard words where
804 * we expect them, we preform the transfer over again.
805 */
806static int wi_write_data(sc, id, off, buf, len)
807	struct wi_softc		*sc;
808	int			id, off;
809	caddr_t			buf;
810	int			len;
811{
812	int			i;
813	u_int16_t		*ptr;
814
815#ifdef WI_HERMES_AUTOINC_WAR
816again:
817#endif
818
819	if (wi_seek(sc, id, off, WI_BAP0))
820		return(EIO);
821
822	ptr = (u_int16_t *)buf;
823	for (i = 0; i < (len / 2); i++)
824		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
825
826#ifdef WI_HERMES_AUTOINC_WAR
827	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
828	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
829
830	if (wi_seek(sc, id, off + len, WI_BAP0))
831		return(EIO);
832
833	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
834	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
835		goto again;
836#endif
837
838	return(0);
839}
840
841/*
842 * Allocate a region of memory inside the NIC and zero
843 * it out.
844 */
845static int wi_alloc_nicmem(sc, len, id)
846	struct wi_softc		*sc;
847	int			len;
848	int			*id;
849{
850	int			i;
851
852	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
853		printf("wi%d: failed to allocate %d bytes on NIC\n",
854		    sc->wi_unit, len);
855		return(ENOMEM);
856	}
857
858	for (i = 0; i < WI_TIMEOUT; i++) {
859		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
860			break;
861	}
862
863	if (i == WI_TIMEOUT)
864		return(ETIMEDOUT);
865
866	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
867	*id = CSR_READ_2(sc, WI_ALLOC_FID);
868
869	if (wi_seek(sc, *id, 0, WI_BAP0))
870		return(EIO);
871
872	for (i = 0; i < len / 2; i++)
873		CSR_WRITE_2(sc, WI_DATA0, 0);
874
875	return(0);
876}
877
878static void wi_setmulti(sc)
879	struct wi_softc		*sc;
880{
881	struct ifnet		*ifp;
882	int			i = 0;
883	struct ifmultiaddr	*ifma;
884	struct wi_ltv_mcast	mcast;
885
886	ifp = &sc->arpcom.ac_if;
887
888	bzero((char *)&mcast, sizeof(mcast));
889
890	mcast.wi_type = WI_RID_MCAST;
891	mcast.wi_len = (3 * 16) + 1;
892
893	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
894		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
895		return;
896	}
897
898	for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
899				ifma = ifma->ifma_link.le_next) {
900		if (ifma->ifma_addr->sa_family != AF_LINK)
901			continue;
902		if (i < 16) {
903			bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
904			    (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
905			i++;
906		} else {
907			bzero((char *)&mcast, sizeof(mcast));
908			break;
909		}
910	}
911
912	mcast.wi_len = (i * 3) + 1;
913	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
914
915	return;
916}
917
918static void wi_setdef(sc, wreq)
919	struct wi_softc		*sc;
920	struct wi_req		*wreq;
921{
922	struct sockaddr_dl	*sdl;
923	struct ifaddr		*ifa;
924	struct ifnet		*ifp;
925
926	ifp = &sc->arpcom.ac_if;
927
928	switch(wreq->wi_type) {
929	case WI_RID_MAC_NODE:
930		ifa = ifnet_addrs[ifp->if_index - 1];
931		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
932		bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
933		   ETHER_ADDR_LEN);
934		bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
935		break;
936	case WI_RID_PORTTYPE:
937		sc->wi_ptype = wreq->wi_val[0];
938		break;
939	case WI_RID_TX_RATE:
940		sc->wi_tx_rate = wreq->wi_val[0];
941		break;
942	case WI_RID_MAX_DATALEN:
943		sc->wi_max_data_len = wreq->wi_val[0];
944		break;
945	case WI_RID_RTS_THRESH:
946		sc->wi_rts_thresh = wreq->wi_val[0];
947		break;
948	case WI_RID_SYSTEM_SCALE:
949		sc->wi_ap_density = wreq->wi_val[0];
950		break;
951	case WI_RID_CREATE_IBSS:
952		sc->wi_create_ibss = wreq->wi_val[0];
953		break;
954	case WI_RID_OWN_CHNL:
955		sc->wi_channel = wreq->wi_val[0];
956		break;
957	case WI_RID_NODENAME:
958		bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
959		bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
960		break;
961	case WI_RID_DESIRED_SSID:
962		bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
963		bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
964		break;
965	case WI_RID_OWN_SSID:
966		bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
967		bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
968		break;
969	case WI_RID_PM_ENABLED:
970		sc->wi_pm_enabled = wreq->wi_val[0];
971		break;
972	case WI_RID_MAX_SLEEP:
973		sc->wi_max_sleep = wreq->wi_val[0];
974		break;
975	default:
976		break;
977	}
978
979	/* Reinitialize WaveLAN. */
980	wi_init(sc);
981
982	return;
983}
984
985static int wi_ioctl(ifp, command, data)
986	struct ifnet		*ifp;
987	u_long			command;
988	caddr_t			data;
989{
990	int			s, error = 0;
991	struct wi_softc		*sc;
992	struct wi_req		wreq;
993	struct ifreq		*ifr;
994
995	s = splimp();
996
997	sc = ifp->if_softc;
998	ifr = (struct ifreq *)data;
999
1000	if (sc->wi_gone)
1001		return(ENODEV);
1002
1003	switch(command) {
1004	case SIOCSIFADDR:
1005	case SIOCGIFADDR:
1006	case SIOCSIFMTU:
1007		error = ether_ioctl(ifp, command, data);
1008		break;
1009	case SIOCSIFFLAGS:
1010		if (ifp->if_flags & IFF_UP) {
1011			if (ifp->if_flags & IFF_RUNNING &&
1012			    ifp->if_flags & IFF_PROMISC &&
1013			    !(sc->wi_if_flags & IFF_PROMISC)) {
1014				WI_SETVAL(WI_RID_PROMISC, 1);
1015			} else 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, 0);
1019			} else
1020				wi_init(sc);
1021		} else {
1022			if (ifp->if_flags & IFF_RUNNING) {
1023				wi_stop(sc);
1024			}
1025		}
1026		sc->wi_if_flags = ifp->if_flags;
1027		error = 0;
1028		break;
1029	case SIOCADDMULTI:
1030	case SIOCDELMULTI:
1031		wi_setmulti(sc);
1032		error = 0;
1033		break;
1034	case SIOCGWAVELAN:
1035		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1036		if (error)
1037			break;
1038		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1039			bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1040			    sizeof(sc->wi_stats));
1041			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1042		} else {
1043			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1044				error = EINVAL;
1045				break;
1046			}
1047		}
1048		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1049		break;
1050	case SIOCSWAVELAN:
1051		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1052		if (error)
1053			break;
1054		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1055			error = EINVAL;
1056			break;
1057		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1058			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1059			    wreq.wi_len);
1060		} else {
1061			error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1062			if (!error)
1063				wi_setdef(sc, &wreq);
1064		}
1065		break;
1066	default:
1067		error = EINVAL;
1068		break;
1069	}
1070
1071	splx(s);
1072
1073	return(error);
1074}
1075
1076static void wi_init(xsc)
1077	void			*xsc;
1078{
1079	struct wi_softc		*sc = xsc;
1080	struct ifnet		*ifp = &sc->arpcom.ac_if;
1081	int			s;
1082	struct wi_ltv_macaddr	mac;
1083	int			id = 0;
1084
1085	if (sc->wi_gone)
1086		return;
1087
1088	s = splimp();
1089
1090	if (ifp->if_flags & IFF_RUNNING)
1091		wi_stop(sc);
1092
1093	wi_reset(sc);
1094
1095	/* Program max data length. */
1096	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1097
1098	/* Enable/disable IBSS creation. */
1099	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1100
1101	/* Set the port type. */
1102	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1103
1104	/* Program the RTS/CTS threshold. */
1105	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1106
1107	/* Program the TX rate */
1108	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1109
1110	/* Access point density */
1111	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1112
1113	/* Power Management Enabled */
1114	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1115
1116	/* Power Managment Max Sleep */
1117	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1118
1119	/* Specify the IBSS name */
1120	WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1121
1122	/* Specify the network name */
1123	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1124
1125	/* Specify the frequency to use */
1126	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1127
1128	/* Program the nodename. */
1129	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1130
1131	/* Set our MAC address. */
1132	mac.wi_len = 4;
1133	mac.wi_type = WI_RID_MAC_NODE;
1134	bcopy((char *)&sc->arpcom.ac_enaddr,
1135	   (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1136	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1137
1138	/* Initialize promisc mode. */
1139	if (ifp->if_flags & IFF_PROMISC) {
1140		WI_SETVAL(WI_RID_PROMISC, 1);
1141	} else {
1142		WI_SETVAL(WI_RID_PROMISC, 0);
1143	}
1144
1145	/* Set multicast filter. */
1146	wi_setmulti(sc);
1147
1148	/* Enable desired port */
1149	wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0);
1150
1151	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1152		printf("wi%d: tx buffer allocation failed\n", sc->wi_unit);
1153	sc->wi_tx_data_id = id;
1154
1155	if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id))
1156		printf("wi%d: mgmt. buffer allocation failed\n", sc->wi_unit);
1157	sc->wi_tx_mgmt_id = id;
1158
1159	/* enable interrupts */
1160	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1161
1162	splx(s);
1163
1164	ifp->if_flags |= IFF_RUNNING;
1165	ifp->if_flags &= ~IFF_OACTIVE;
1166
1167	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
1168
1169	return;
1170}
1171
1172static void wi_start(ifp)
1173	struct ifnet		*ifp;
1174{
1175	struct wi_softc		*sc;
1176	struct mbuf		*m0;
1177	struct wi_frame		tx_frame;
1178	struct ether_header	*eh;
1179	int			id;
1180
1181	sc = ifp->if_softc;
1182
1183	if (sc->wi_gone)
1184		return;
1185
1186	if (ifp->if_flags & IFF_OACTIVE)
1187		return;
1188
1189	IF_DEQUEUE(&ifp->if_snd, m0);
1190	if (m0 == NULL)
1191		return;
1192
1193	bzero((char *)&tx_frame, sizeof(tx_frame));
1194	id = sc->wi_tx_data_id;
1195	eh = mtod(m0, struct ether_header *);
1196
1197	/*
1198	 * Use RFC1042 encoding for IP and ARP datagrams,
1199	 * 802.3 for anything else.
1200	 */
1201	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1202	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1203	    ntohs(eh->ether_type) == ETHERTYPE_REVARP) {
1204		bcopy((char *)&eh->ether_dhost,
1205		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1206		bcopy((char *)&eh->ether_shost,
1207		    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1208		bcopy((char *)&eh->ether_dhost,
1209		    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1210		bcopy((char *)&eh->ether_shost,
1211		    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1212
1213		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
1214		tx_frame.wi_frame_ctl = WI_FTYPE_DATA;
1215		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1216		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1217		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1218		tx_frame.wi_type = eh->ether_type;
1219
1220		m_copydata(m0, sizeof(struct ether_header),
1221		    m0->m_pkthdr.len - sizeof(struct ether_header),
1222		    (caddr_t)&sc->wi_txbuf);
1223
1224		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1225		    sizeof(struct wi_frame));
1226		wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1227		    (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1228	} else {
1229		tx_frame.wi_dat_len = m0->m_pkthdr.len;
1230
1231		m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1232
1233		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1234		    sizeof(struct wi_frame));
1235		wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1236		    m0->m_pkthdr.len + 2);
1237	}
1238
1239	/*
1240	 * If there's a BPF listner, bounce a copy of
1241	 * this frame to him.
1242	 */
1243	if (ifp->if_bpf)
1244		bpf_mtap(ifp, m0);
1245
1246	m_freem(m0);
1247
1248	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1249		printf("wi%d: xmit failed\n", sc->wi_unit);
1250
1251	ifp->if_flags |= IFF_OACTIVE;
1252
1253	/*
1254	 * Set a timeout in case the chip goes out to lunch.
1255	 */
1256	ifp->if_timer = 5;
1257
1258	return;
1259}
1260
1261static int wi_mgmt_xmit(sc, data, len)
1262	struct wi_softc		*sc;
1263	caddr_t			data;
1264	int			len;
1265{
1266	struct wi_frame		tx_frame;
1267	int			id;
1268	struct wi_80211_hdr	*hdr;
1269	caddr_t			dptr;
1270
1271	if (sc->wi_gone)
1272		return(ENODEV);
1273
1274	hdr = (struct wi_80211_hdr *)data;
1275	dptr = data + sizeof(struct wi_80211_hdr);
1276
1277	bzero((char *)&tx_frame, sizeof(tx_frame));
1278	id = sc->wi_tx_mgmt_id;
1279
1280	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1281	   sizeof(struct wi_80211_hdr));
1282
1283	tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN;
1284	tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1285
1286	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1287	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1288	    (len - sizeof(struct wi_80211_hdr)) + 2);
1289
1290	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1291		printf("wi%d: xmit failed\n", sc->wi_unit);
1292		return(EIO);
1293	}
1294
1295	return(0);
1296}
1297
1298static void wi_stop(sc)
1299	struct wi_softc		*sc;
1300{
1301	struct ifnet		*ifp;
1302
1303	if (sc->wi_gone)
1304		return;
1305
1306	ifp = &sc->arpcom.ac_if;
1307
1308	CSR_WRITE_2(sc, WI_INT_EN, 0);
1309	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1310
1311	untimeout(wi_inquire, sc, sc->wi_stat_ch);
1312
1313	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1314
1315	return;
1316}
1317
1318static void wi_watchdog(ifp)
1319	struct ifnet		*ifp;
1320{
1321	struct wi_softc		*sc;
1322
1323	sc = ifp->if_softc;
1324
1325	printf("wi%d: device timeout\n", sc->wi_unit);
1326
1327	wi_init(sc);
1328
1329	ifp->if_oerrors++;
1330
1331	return;
1332}
1333
1334static void wi_shutdown(arg, howto)
1335	void			*arg;
1336	int			howto;
1337{
1338	struct wi_softc		*sc;
1339
1340	sc = arg;
1341	wi_stop(sc);
1342
1343	return;
1344}
1345