seeq8005.c revision 1.2
1/* $NetBSD: seeq8005.c,v 1.2 2000/09/21 22:20:38 bjh21 Exp $ */
2
3/*
4 * Copyright (c) 2000 Ben Harris
5 * Copyright (c) 1995 Mark Brinicombe
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Mark Brinicombe.
19 * 4. The name of the company nor the name of the author may be used to
20 *    endorse or promote products derived from this software without specific
21 *    prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35/*
36 * seeq8005.c - SEEQ 8005 device driver
37 */
38/*
39 * This driver currently supports the following chip:
40 * SEEQ 8005 Advanced Ethernet Data Link Controller
41 */
42/*
43 * This driver is based on the arm32 ea(4) driver, hence the names of many
44 * of the functions.
45 */
46/*
47 * Bugs/possible improvements:
48 *	- Does not currently support DMA
49 *	- Does not currently support multicasts
50 *	- Does not transmit multiple packets in one go
51 *	- Does not support big-endian hosts
52 *	- Does not support 8-bit busses
53 */
54
55#include "opt_inet.h"
56#include "opt_ns.h"
57
58#include <sys/types.h>
59#include <sys/param.h>
60
61__RCSID("$NetBSD: seeq8005.c,v 1.2 2000/09/21 22:20:38 bjh21 Exp $");
62
63#include <sys/systm.h>
64#include <sys/endian.h>
65#include <sys/errno.h>
66#include <sys/ioctl.h>
67#include <sys/mbuf.h>
68#include <sys/socket.h>
69#include <sys/syslog.h>
70#include <sys/device.h>
71
72#include <net/if.h>
73#include <net/if_dl.h>
74#include <net/if_types.h>
75#include <net/if_ether.h>
76
77#ifdef INET
78#include <netinet/in.h>
79#include <netinet/in_systm.h>
80#include <netinet/in_var.h>
81#include <netinet/ip.h>
82#include <netinet/if_inarp.h>
83#endif
84
85#ifdef NS
86#include <netns/ns.h>
87#include <netns/ns_if.h>
88#endif
89
90#include "bpfilter.h"
91#if NBPFILTER > 0
92#include <net/bpf.h>
93#include <net/bpfdesc.h>
94#endif
95
96#include <machine/bus.h>
97#include <machine/intr.h>
98
99#include <dev/ic/seeq8005reg.h>
100#include <dev/ic/seeq8005var.h>
101
102#ifndef EA_TIMEOUT
103#define EA_TIMEOUT	60
104#endif
105
106#define EA_TX_BUFFER_SIZE	0x4000
107#define EA_RX_BUFFER_SIZE	0xC000
108
109/*#define EA_TX_DEBUG*/
110/*#define EA_RX_DEBUG*/
111/*#define EA_DEBUG*/
112/*#define EA_PACKET_DEBUG*/
113
114/* for debugging convenience */
115#ifdef EA_DEBUG
116#define dprintf(x) printf x
117#else
118#define dprintf(x)
119#endif
120
121/*
122 * prototypes
123 */
124
125static int ea_init(struct seeq8005_softc *);
126static int ea_ioctl(struct ifnet *, u_long, caddr_t);
127static void ea_start(struct ifnet *);
128static void ea_watchdog(struct ifnet *);
129static void ea_reinit(struct seeq8005_softc *);
130static void ea_chipreset(struct seeq8005_softc *);
131static void ea_ramtest(struct seeq8005_softc *);
132static int ea_stoptx(struct seeq8005_softc *);
133static int ea_stoprx(struct seeq8005_softc *);
134static void ea_stop(struct seeq8005_softc *);
135static void ea_await_fifo_empty(struct seeq8005_softc *);
136static void ea_await_fifo_full(struct seeq8005_softc *);
137static void ea_writebuf(struct seeq8005_softc *, u_char *, u_int, size_t);
138static void ea_readbuf(struct seeq8005_softc *, u_char *, u_int, size_t);
139static void earead(struct seeq8005_softc *, int, int);
140static struct mbuf *eaget(struct seeq8005_softc *, int, int, struct ifnet *);
141static void ea_hardreset(struct seeq8005_softc *);
142static void eagetpackets(struct seeq8005_softc *);
143static void eatxpacket(struct seeq8005_softc *);
144
145
146#ifdef EA_PACKET_DEBUG
147void ea_dump_buffer(struct seeq8005_softc *, int);
148#endif
149
150
151#ifdef EA_PACKET_DEBUG
152/*
153 * Dump the interface buffer
154 */
155
156void
157ea_dump_buffer(struct seeq8005_softc *sc, u_int offset)
158{
159	bus_space_tag_t iot = sc->sc_iot;
160	bus_space_handle_t ioh = sc->sc_ioh;
161	u_int addr;
162	int loop;
163	size_t size;
164	int ctrl;
165	int ptr;
166
167	addr = offset;
168
169	do {
170		bus_space_write_2(iot, ioh, EA_8005_COMMAND,
171				 sc->sc_command | EA_CMD_FIFO_READ);
172		bus_space_write_2(iot, ioh, EA_8005_CONFIG1,
173				  sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
174		bus_space_write_2(iot, ioh, EA_8005_DMA_ADDR, addr);
175
176		ptr = bus_space_read_2(iot, ioh, EA_8005_BUFWIN);
177		ctrl = bus_space_read_2(iot, ioh, EA_8005_BUFWIN);
178		ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff);
179
180		if (ptr == 0) break;
181		size = ptr - addr;
182
183		printf("addr=%04x size=%04x ", addr, size);
184		printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8);
185
186		for (loop = 0; loop < size - 4; loop += 2)
187			printf("%04x ",
188			       bus_space_read_2(iot, ioh, EA_8005_BUFWIN));
189		printf("\n");
190		addr = ptr;
191	} while (size != 0);
192}
193#endif
194
195/*
196 * Attach chip.
197 */
198
199void
200seeq8005_attach(struct seeq8005_softc *sc, const u_int8_t *myaddr)
201{
202	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
203	u_int id;
204
205	printf(" address %s", ether_sprintf(myaddr));
206
207	/* Get the product ID */
208
209	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EA_8005_CONFIG1,
210			  EA_BUFCODE_PRODUCTID);
211	id = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EA_8005_BUFWIN);
212
213	if ((id & 0xf0) == 0xa0) {
214		sc->sc_flags |= SEEQ8005_80C04;
215		printf(", SEEQ 80C04 rev %02x", id);
216	} else
217		printf(", SEEQ 8005");
218
219	/* Stop the board. */
220
221	ea_chipreset(sc);
222	ea_stoptx(sc);
223	ea_stoprx(sc);
224
225	/* Initialise ifnet structure. */
226
227	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
228	ifp->if_softc = sc;
229	ifp->if_start = ea_start;
230	ifp->if_ioctl = ea_ioctl;
231	ifp->if_watchdog = ea_watchdog;
232	ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
233
234	/* Now we can attach the interface. */
235
236	if_attach(ifp);
237	ether_ifattach(ifp, myaddr);
238
239	/* Finally, attach to bpf filter if it is present. */
240
241#if NBPFILTER > 0
242	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
243#endif
244
245	printf("\n");
246
247	/* Test the RAM */
248	ea_ramtest(sc);
249}
250
251
252/*
253 * Test the RAM on the ethernet card.
254 */
255
256void
257ea_ramtest(struct seeq8005_softc *sc)
258{
259	bus_space_tag_t iot = sc->sc_iot;
260	bus_space_handle_t ioh = sc->sc_ioh;
261	int loop;
262	u_int sum = 0;
263
264/*	dprintf(("ea_ramtest()\n"));*/
265
266	/*
267	 * Test the buffer memory on the board.
268	 * Write simple pattens to it and read them back.
269	 */
270
271	/* Set up the whole buffer RAM for writing */
272
273	bus_space_write_2(iot, ioh, EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
274	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, (EA_BUFFER_SIZE >> 8) - 1);
275	bus_space_write_2(iot, ioh, EA_8005_TX_PTR, 0x0000);
276	bus_space_write_2(iot, ioh, EA_8005_RX_PTR, EA_BUFFER_SIZE - 2);
277
278	/* Set the write start address and write a pattern */
279
280	ea_writebuf(sc, NULL, 0x0000, 0);
281
282	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
283		bus_space_write_2(iot, ioh, EA_8005_BUFWIN, loop);
284
285	/* Set the read start address and verify the pattern */
286
287	ea_readbuf(sc, NULL, 0x0000, 0);
288
289	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
290		if (bus_space_read_2(iot, ioh, EA_8005_BUFWIN) != loop)
291			++sum;
292
293	if (sum != 0)
294		dprintf(("sum=%d\n", sum));
295
296	/* Set the write start address and write a pattern */
297
298	ea_writebuf(sc, NULL, 0x0000, 0);
299
300	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
301		bus_space_write_2(iot, ioh, EA_8005_BUFWIN,
302			   loop ^ (EA_BUFFER_SIZE - 1));
303
304	/* Set the read start address and verify the pattern */
305
306	ea_readbuf(sc, NULL, 0x0000, 0);
307
308	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
309		if (bus_space_read_2(iot, ioh, EA_8005_BUFWIN) !=
310		    (loop ^ (EA_BUFFER_SIZE - 1)))
311			++sum;
312
313	if (sum != 0)
314		dprintf(("sum=%d\n", sum));
315
316	/* Set the write start address and write a pattern */
317
318	ea_writebuf(sc, NULL, 0x0000, 0);
319
320	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
321		bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0xaa55);
322
323	/* Set the read start address and verify the pattern */
324
325	ea_readbuf(sc, NULL, 0x0000, 0);
326
327	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
328		if (bus_space_read_2(iot, ioh, EA_8005_BUFWIN) != 0xaa55)
329			++sum;
330
331	if (sum != 0)
332		dprintf(("sum=%d\n", sum));
333
334	/* Set the write start address and write a pattern */
335
336	ea_writebuf(sc, NULL, 0x0000, 0);
337
338	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
339		bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x55aa);
340
341	/* Set the read start address and verify the pattern */
342
343	ea_readbuf(sc, NULL, 0x0000, 0);
344
345	for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
346		if (bus_space_read_2(iot, ioh, EA_8005_BUFWIN) != 0x55aa)
347			++sum;
348
349	if (sum != 0)
350		dprintf(("sum=%d\n", sum));
351
352	/* Report */
353
354	if (sum > 0)
355		printf("%s: buffer RAM failed self test, %d faults\n",
356		       sc->sc_dev.dv_xname, sum);
357}
358
359
360/*
361 * Stop and reinitialise the interface.
362 */
363
364static void
365ea_reinit(struct seeq8005_softc *sc)
366{
367	int s;
368
369	dprintf(("eareinit()\n"));
370
371	/* Stop and reinitialise the interface */
372
373	s = splnet();
374	ea_stop(sc);
375	ea_init(sc);
376	splx(s);
377}
378
379
380/*
381 * Stop the tx interface.
382 *
383 * Returns 0 if the tx was already stopped or 1 if it was active
384 */
385
386static int
387ea_stoptx(struct seeq8005_softc *sc)
388{
389	bus_space_tag_t iot = sc->sc_iot;
390	bus_space_handle_t ioh = sc->sc_ioh;
391	int timeout;
392	int status;
393
394	dprintf(("ea_stoptx()\n"));
395
396	status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
397	if (!(status & EA_STATUS_TX_ON))
398		return 0;
399
400	/* Stop any tx and wait for confirmation */
401	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
402			  sc->sc_command | EA_CMD_TX_OFF);
403
404	timeout = 20000;
405	do {
406		status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
407	} while ((status & EA_STATUS_TX_ON) && --timeout > 0);
408	if (timeout == 0)
409		dprintf(("ea_stoptx: timeout waiting for tx termination\n"));
410
411	/* Clear any pending tx interrupt */
412	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
413		   sc->sc_command | EA_CMD_TX_INTACK);
414	return 1;
415}
416
417
418/*
419 * Stop the rx interface.
420 *
421 * Returns 0 if the tx was already stopped or 1 if it was active
422 */
423
424static int
425ea_stoprx(struct seeq8005_softc *sc)
426{
427	bus_space_tag_t iot = sc->sc_iot;
428	bus_space_handle_t ioh = sc->sc_ioh;
429	int timeout;
430	int status;
431
432	dprintf(("ea_stoprx()\n"));
433
434	status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
435	if (!(status & EA_STATUS_RX_ON))
436		return 0;
437
438	/* Stop any rx and wait for confirmation */
439
440	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
441			  sc->sc_command | EA_CMD_RX_OFF);
442
443	timeout = 20000;
444	do {
445		status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
446	} while ((status & EA_STATUS_RX_ON) && --timeout > 0);
447	if (timeout == 0)
448		dprintf(("ea_stoprx: timeout waiting for rx termination\n"));
449
450	/* Clear any pending rx interrupt */
451
452	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
453		   sc->sc_command | EA_CMD_RX_INTACK);
454	return 1;
455}
456
457
458/*
459 * Stop interface.
460 * Stop all IO and shut the interface down
461 */
462
463static void
464ea_stop(struct seeq8005_softc *sc)
465{
466	bus_space_tag_t iot = sc->sc_iot;
467	bus_space_handle_t ioh = sc->sc_ioh;
468
469	dprintf(("ea_stop()\n"));
470
471	/* Stop all IO */
472	ea_stoptx(sc);
473	ea_stoprx(sc);
474
475	/* Disable rx and tx interrupts */
476	sc->sc_command &= (EA_CMD_RX_INTEN | EA_CMD_TX_INTEN);
477
478	/* Clear any pending interrupts */
479	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
480			  sc->sc_command | EA_CMD_RX_INTACK |
481			  EA_CMD_TX_INTACK | EA_CMD_DMA_INTACK |
482			  EA_CMD_BW_INTACK);
483	dprintf(("st=%08x", bus_space_read_2(iot, ioh, EA_8005_STATUS)));
484
485	/* Cancel any watchdog timer */
486       	sc->sc_ethercom.ec_if.if_timer = 0;
487}
488
489
490/*
491 * Reset the chip
492 * Following this the software registers are reset
493 */
494
495static void
496ea_chipreset(struct seeq8005_softc *sc)
497{
498	bus_space_tag_t iot = sc->sc_iot;
499	bus_space_handle_t ioh = sc->sc_ioh;
500
501	dprintf(("ea_chipreset()\n"));
502
503	/* Reset the controller. Min of 4us delay here */
504
505	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, EA_CFG2_RESET);
506	delay(100);
507
508	sc->sc_command = 0;
509	sc->sc_config1 = 0;
510	sc->sc_config2 = 0;
511}
512
513
514/*
515 * Do a hardware reset of the board, and upload the ethernet address again in
516 * case the board forgets.
517 */
518
519static void
520ea_hardreset(struct seeq8005_softc *sc)
521{
522	bus_space_tag_t iot = sc->sc_iot;
523	bus_space_handle_t ioh = sc->sc_ioh;
524	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
525	int loop;
526
527	dprintf(("ea_hardreset()\n"));
528
529	/* Stop any activity */
530	ea_stoptx(sc);
531	ea_stoprx(sc);
532
533	ea_chipreset(sc);
534
535	/* Set up defaults for the registers */
536
537	/* Set the byte order for transfers to/from board RAM. */
538#if BYTE_ORDER == BIG_ENDIAN
539	sc->sc_config2 = EA_CFG2_BYTESWAP
540#else
541	sc->sc_config2 = 0;
542#endif
543	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
544	sc->sc_command = 0x00;
545	sc->sc_config1 = EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BSIZE_1 |
546	    EA_CFG1_DMA_BURST_CONT;
547	bus_space_write_2(iot, ioh, EA_8005_CONFIG1, sc->sc_config1);
548	bus_space_write_2(iot, ioh, EA_8005_COMMAND, sc->sc_command);
549
550	bus_space_write_2(iot, ioh, EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
551	bus_space_write_2(iot, ioh, EA_8005_BUFWIN,
552			  (EA_TX_BUFFER_SIZE >> 8) - 1);
553
554	/* Write the station address - the receiver must be off */
555	bus_space_write_2(iot, ioh, EA_8005_CONFIG1,
556			  sc->sc_config1 | EA_BUFCODE_STATION_ADDR0);
557	for (loop = 0; loop < ETHER_ADDR_LEN; ++loop)
558		bus_space_write_2(iot, ioh, EA_8005_BUFWIN,
559				  LLADDR(ifp->if_sadl)[loop]);
560}
561
562
563/*
564 * If the DMA FIFO's in write mode, wait for it to empty.  Needed when
565 * switching the FIFO from write to read.  We also use it when changing
566 * the address for writes.
567 */
568static void
569ea_await_fifo_empty(struct seeq8005_softc *sc)
570{
571	bus_space_tag_t iot = sc->sc_iot;
572	bus_space_handle_t ioh = sc->sc_ioh;
573	int timeout;
574
575	timeout = 20000;
576	if ((bus_space_read_2(iot, ioh, EA_8005_STATUS) &
577	     EA_STATUS_FIFO_DIR) != 0)
578		return; /* FIFO is reading anyway. */
579	while ((bus_space_read_2(iot, ioh, EA_8005_STATUS) &
580		EA_STATUS_FIFO_EMPTY) == 0 &&
581	       --timeout > 0)
582		continue;
583}
584
585/*
586 * Wait for the DMA FIFO to fill before reading from it.
587 */
588static void
589ea_await_fifo_full(struct seeq8005_softc *sc)
590{
591	bus_space_tag_t iot = sc->sc_iot;
592	bus_space_handle_t ioh = sc->sc_ioh;
593	int timeout;
594
595	timeout = 20000;
596	while ((bus_space_read_2(iot, ioh, EA_8005_STATUS) &
597		EA_STATUS_FIFO_FULL) == 0 &&
598	       --timeout > 0)
599		continue;
600}
601
602/*
603 * write to the buffer memory on the interface
604 *
605 * The buffer address is set to ADDR.
606 * If len != 0 then data is copied from the address starting at buf
607 * to the interface buffer.
608 * BUF must be usable as a u_int16_t *.
609 * If LEN is odd, it must be safe to overwrite one extra byte.
610 */
611
612static void
613ea_writebuf(struct seeq8005_softc *sc, u_char *buf, u_int addr, size_t len)
614{
615	bus_space_tag_t iot = sc->sc_iot;
616	bus_space_handle_t ioh = sc->sc_ioh;
617
618	dprintf(("writebuf: st=%04x\n",
619		 bus_space_read_2(iot, ioh, EA_8005_STATUS)));
620
621#ifdef DIAGNOSTIC
622	if (__predict_false(!ALIGNED_POINTER(buf, u_int16_t)))
623		panic("%s: unaligned writebuf", sc->sc_dev.dv_xname);
624#endif
625	if (__predict_false(addr >= EA_BUFFER_SIZE))
626		panic("%s: writebuf out of range", sc->sc_dev.dv_xname);
627
628	/* Assume that copying too much is safe. */
629	if (len % 2 != 0)
630		len++;
631
632	ea_await_fifo_empty(sc);
633
634	bus_space_write_2(iot, ioh, EA_8005_CONFIG1,
635			  sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
636	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
637			  sc->sc_command | EA_CMD_FIFO_WRITE);
638       	bus_space_write_2(iot, ioh, EA_8005_DMA_ADDR, addr);
639
640	if (len > 0)
641		bus_space_write_multi_2(iot, ioh, EA_8005_BUFWIN,
642					(u_int16_t *)buf, len / 2);
643	/* Leave FIFO to empty in the background */
644}
645
646
647/*
648 * read from the buffer memory on the interface
649 *
650 * The buffer address is set to ADDR.
651 * If len != 0 then data is copied from the interface buffer to the
652 * address starting at buf.
653 * BUF must be usable as a u_int16_t *.
654 * If LEN is odd, it must be safe to overwrite one extra byte.
655 */
656
657static void
658ea_readbuf(struct seeq8005_softc *sc, u_char *buf, u_int addr, size_t len)
659{
660
661	bus_space_tag_t iot = sc->sc_iot;
662	bus_space_handle_t ioh = sc->sc_ioh;
663
664	dprintf(("readbuf: st=%04x addr=%04x len=%d\n",
665		 bus_space_read_2(iot, ioh, EA_8005_STATUS), addr, len));
666
667#ifdef DIAGNOSTIC
668	if (!ALIGNED_POINTER(buf, u_int16_t))
669		panic("%s: unaligned readbuf", sc->sc_dev.dv_xname);
670#endif
671	if (addr >= EA_BUFFER_SIZE)
672		panic("%s: writebuf out of range", sc->sc_dev.dv_xname);
673
674	/* Assume that copying too much is safe. */
675	if (len % 2 != 0)
676		len++;
677
678	ea_await_fifo_empty(sc);
679	bus_space_write_2(iot, ioh, EA_8005_CONFIG1,
680			  sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
681
682	bus_space_write_2(iot, ioh, EA_8005_DMA_ADDR, addr);
683	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
684			  sc->sc_command | EA_CMD_FIFO_READ);
685
686	ea_await_fifo_full(sc);
687
688	if (len > 0)
689		bus_space_read_multi_2(iot, ioh, EA_8005_BUFWIN,
690				       (u_int16_t *)buf, len / 2);
691}
692
693
694/*
695 * Initialize interface.
696 *
697 * This should leave the interface in a state for packet reception and
698 * transmission.
699 */
700
701static int
702ea_init(struct seeq8005_softc *sc)
703{
704	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
705	bus_space_tag_t iot = sc->sc_iot;
706	bus_space_handle_t ioh = sc->sc_ioh;
707	int s;
708
709	dprintf(("ea_init()\n"));
710
711	s = splnet();
712
713	/* First, reset the board. */
714
715	ea_hardreset(sc);
716
717
718	/* Configure rx. */
719	dprintf(("Configuring rx...\n"));
720	if (ifp->if_flags & IFF_PROMISC)
721		sc->sc_config1 = EA_CFG1_PROMISCUOUS;
722	else
723		sc->sc_config1 = EA_CFG1_BROADCAST;
724
725	sc->sc_config1 |= EA_CFG1_DMA_BSIZE_8 | EA_CFG1_STATION_ADDR0 |
726		EA_CFG1_DMA_BURST_CONT;
727	bus_space_write_2(iot, ioh, EA_8005_CONFIG1, sc->sc_config1);
728
729
730	/* Configure TX. */
731	dprintf(("Configuring tx...\n"));
732
733	bus_space_write_2(iot, ioh, EA_8005_CONFIG1,
734			  sc->sc_config1 | EA_BUFCODE_TX_EAP);
735	bus_space_write_2(iot, ioh, EA_8005_BUFWIN,
736			  (EA_TX_BUFFER_SIZE >> 8) - 1);
737	bus_space_write_2(iot, ioh, EA_8005_TX_PTR, 0x0000);
738
739	sc->sc_config2 |= EA_CFG2_OUTPUT;
740	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
741
742
743	/* Place a NULL header at the beginning of the transmit area */
744	ea_writebuf(sc, NULL, 0x0000, 0);
745
746	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
747	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
748
749	sc->sc_command |= EA_CMD_TX_INTEN;
750	bus_space_write_2(iot, ioh, EA_8005_COMMAND, sc->sc_command);
751
752
753	/* Setup the Rx pointers */
754	sc->sc_rx_ptr = EA_TX_BUFFER_SIZE;
755
756	bus_space_write_2(iot, ioh, EA_8005_RX_PTR, sc->sc_rx_ptr);
757	bus_space_write_2(iot, ioh, EA_8005_RX_END, sc->sc_rx_ptr >> 8);
758
759
760	/* Place a NULL header at the beginning of the receive area */
761	ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
762
763	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
764	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
765
766
767	/* Turn on Rx */
768	sc->sc_command |= EA_CMD_RX_INTEN;
769	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
770			  sc->sc_command | EA_CMD_RX_ON);
771
772
773	/* Set flags appropriately. */
774	ifp->if_flags |= IFF_RUNNING;
775	ifp->if_flags &= ~IFF_OACTIVE;
776
777	dprintf(("init: st=%04x\n",
778		 bus_space_read_2(iot, ioh, EA_8005_STATUS)));
779
780
781	/* And start output. */
782	ea_start(ifp);
783
784	splx(s);
785	return 0;
786}
787
788
789/*
790 * Start output on interface. Get datagrams from the queue and output them,
791 * giving the receiver a chance between datagrams. Call only from splnet or
792 * interrupt level!
793 */
794
795static void
796ea_start(struct ifnet *ifp)
797{
798	struct seeq8005_softc *sc = ifp->if_softc;
799	int s;
800
801	s = splnet();
802#ifdef EA_TX_DEBUG
803	dprintf(("ea_start()...\n"));
804#endif
805
806	/* Don't do anything if output is active. */
807
808	if (ifp->if_flags & IFF_OACTIVE)
809		return;
810
811	/* Mark interface as output active */
812
813	ifp->if_flags |= IFF_OACTIVE;
814
815	/* tx packets */
816
817	eatxpacket(sc);
818	splx(s);
819}
820
821
822/*
823 * Transfer a packet to the interface buffer and start transmission
824 *
825 * Called at splnet()
826 */
827
828void
829eatxpacket(struct seeq8005_softc *sc)
830{
831	bus_space_tag_t iot = sc->sc_iot;
832	bus_space_handle_t ioh = sc->sc_ioh;
833	struct mbuf *m, *m0;
834	struct ifnet *ifp;
835	int len, nextpacket;
836	u_int8_t hdr[4];
837
838	ifp = &sc->sc_ethercom.ec_if;
839
840	/* Dequeue the next packet. */
841	IF_DEQUEUE(&ifp->if_snd, m0);
842
843	/* If there's nothing to send, return. */
844	if (!m0) {
845		ifp->if_flags &= ~IFF_OACTIVE;
846		sc->sc_config2 |= EA_CFG2_OUTPUT;
847		bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
848#ifdef EA_TX_DEBUG
849		dprintf(("tx finished\n"));
850#endif
851		return;
852	}
853
854#if NBPFILTER > 0
855	/* Give the packet to the bpf, if any. */
856	if (ifp->if_bpf)
857		bpf_mtap(ifp->if_bpf, m0);
858#endif
859
860#ifdef EA_TX_DEBUG
861	dprintf(("Tx new packet\n"));
862#endif
863
864	sc->sc_config2 &= ~EA_CFG2_OUTPUT;
865	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
866
867	/*
868	 * Copy the frame to the start of the transmit area on the card,
869	 * leaving four bytes for the transmit header.
870	 */
871	len = 0;
872	for (m = m0; m; m = m->m_next) {
873		if (m->m_len == 0)
874			continue;
875		ea_writebuf(sc, mtod(m, caddr_t), 4 + len, m->m_len);
876		len += m->m_len;
877	}
878	m_freem(m0);
879
880
881	/* If packet size is odd round up to the next 16 bit boundry */
882	if (len % 2)
883		++len;
884
885	len = max(len, ETHER_MIN_LEN);
886
887	if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN))
888		log(LOG_WARNING, "%s: oversize packet = %d bytes\n",
889		    sc->sc_dev.dv_xname, len);
890
891#if 0 /*def EA_TX_DEBUG*/
892	dprintf(("ea: xfr pkt length=%d...\n", len));
893
894	dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
895	dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
896#endif
897
898/*	dprintf(("st=%04x\n", bus_space_read_2(iot, ioh, EA_8005_STATUS)));*/
899
900	/* Follow it with a NULL packet header */
901	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
902	bus_space_write_2(iot, ioh, EA_8005_BUFWIN, 0x0000);
903
904
905	/* Write the packet header */
906
907	nextpacket = len + 4;
908	hdr[0] = (nextpacket >> 8) & 0xff;
909	hdr[1] = nextpacket & 0xff;
910	hdr[2] = EA_PKTHDR_TX | EA_PKTHDR_DATA_FOLLOWS |
911		EA_TXHDR_XMIT_SUCCESS_INT | EA_TXHDR_COLLISION_INT;
912	hdr[3] = 0; /* Status byte -- will be update by hardware. */
913	ea_writebuf(sc, hdr, 0x0000, 4);
914
915	bus_space_write_2(iot, ioh, EA_8005_TX_PTR, 0x0000);
916
917/*	dprintf(("st=%04x\n", bus_space_read_2(iot, ioh, EA_8005_STATUS)));*/
918
919#ifdef EA_PACKET_DEBUG
920	ea_dump_buffer(sc, 0);
921#endif
922
923
924	/* Now transmit the datagram. */
925/*	dprintf(("st=%04x\n", bus_space_read_2(iot, ioh, EA_8005_STATUS)));*/
926	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
927			  sc->sc_command | EA_CMD_TX_ON);
928#ifdef EA_TX_DEBUG
929	dprintf(("st=%04x\n", bus_space_read_2(iot, ioh, EA_8005_STATUS)));
930	dprintf(("tx: queued\n"));
931#endif
932}
933
934
935/*
936 * Ethernet controller interrupt.
937 */
938
939int
940seeq8005intr(void *arg)
941{
942	struct seeq8005_softc *sc = arg;
943	bus_space_tag_t iot = sc->sc_iot;
944	bus_space_handle_t ioh = sc->sc_ioh;
945	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
946	int status, s, handled;
947	u_int8_t txhdr[4];
948	u_int txstatus;
949
950	handled = 0;
951	dprintf(("eaintr: "));
952
953
954	/* Get the controller status */
955	status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
956        dprintf(("st=%04x ", status));
957
958
959	/* Tx interrupt ? */
960	if (status & EA_STATUS_TX_INT) {
961		dprintf(("txint "));
962		handled = 1;
963
964		/* Acknowledge the interrupt */
965		bus_space_write_2(iot, ioh, EA_8005_COMMAND,
966				  sc->sc_command | EA_CMD_TX_INTACK);
967
968		ea_readbuf(sc, txhdr, 0x0000, 4);
969
970#ifdef EA_TX_DEBUG
971		dprintf(("txstatus=%02x %02x %02x %02x\n",
972			 txhdr[0], txhdr[1], txhdr[2], txhdr[3]));
973#endif
974		txstatus = txhdr[3];
975
976		/*
977		 * Did it succeed ? Did we collide ?
978		 *
979		 * The exact proceedure here is not clear. We should get
980		 * an interrupt on a sucessfull tx or on a collision.
981		 * The done flag is set after successfull tx or 16 collisions
982		 * We should thus get a interrupt for each of collision
983		 * and the done bit should not be set. However it does appear
984		 * to be set at the same time as the collision bit ...
985		 *
986		 * So we will count collisions and output errors and will
987		 * assume that if the done bit is set the packet was
988		 * transmitted. Stats may be wrong if 16 collisions occur on
989		 * a packet as the done flag should be set but the packet
990		 * may not have been transmitted. so the output count might
991		 * not require incrementing if the 16 collisions flags is
992		 * set. I don;t know abou this until it happens.
993		 */
994
995		if (txstatus & EA_TXHDR_COLLISION)
996			ifp->if_collisions++;
997		else if (txstatus & EA_TXHDR_ERROR_MASK)
998			ifp->if_oerrors++;
999
1000#if 0
1001		if (txstatus & EA_TXHDR_ERROR_MASK)
1002			log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
1003#endif
1004
1005		if (txstatus & EA_PKTHDR_DONE) {
1006			ifp->if_opackets++;
1007
1008			/* Tx next packet */
1009
1010			s = splnet();
1011			eatxpacket(sc);
1012			splx(s);
1013		}
1014	}
1015
1016
1017	/* Rx interrupt ? */
1018	if (status & EA_STATUS_RX_INT) {
1019		dprintf(("rxint "));
1020		handled = 1;
1021
1022		/* Acknowledge the interrupt */
1023		bus_space_write_2(iot, ioh, EA_8005_COMMAND,
1024				  sc->sc_command | EA_CMD_RX_INTACK);
1025
1026		/* Install a watchdog timer needed atm to fixed rx lockups */
1027		ifp->if_timer = EA_TIMEOUT;
1028
1029		/* Processes the received packets */
1030		eagetpackets(sc);
1031
1032
1033#if 0
1034		/* Make sure the receiver is on */
1035		if ((status & EA_STATUS_RX_ON) == 0) {
1036			bus_space_write_2(iot, ioh, EA_8005_COMMAND,
1037					  sc->sc_command | EA_CMD_RX_ON);
1038			printf("rxintr: rx is off st=%04x\n",status);
1039		}
1040#endif
1041	}
1042
1043#ifdef EA_DEBUG
1044	status = bus_space_read_2(iot, ioh, EA_8005_STATUS);
1045        dprintf(("st=%04x\n", status));
1046#endif
1047
1048	return handled;
1049}
1050
1051
1052void
1053eagetpackets(struct seeq8005_softc *sc)
1054{
1055	bus_space_tag_t iot = sc->sc_iot;
1056	bus_space_handle_t ioh = sc->sc_ioh;
1057	u_int addr;
1058	int len;
1059	int ctrl;
1060	int ptr;
1061	int pack;
1062	int status;
1063	u_int8_t rxhdr[4];
1064	struct ifnet *ifp;
1065
1066	ifp = &sc->sc_ethercom.ec_if;
1067
1068
1069	/* We start from the last rx pointer position */
1070	addr = sc->sc_rx_ptr;
1071	sc->sc_config2 &= ~EA_CFG2_OUTPUT;
1072	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
1073
1074	do {
1075		/* Read rx header */
1076		ea_readbuf(sc, rxhdr, addr, 4);
1077
1078		/* Split the packet header */
1079		ptr = (rxhdr[0] << 8) | rxhdr[1];
1080		ctrl = rxhdr[2];
1081		status = rxhdr[3];
1082
1083#ifdef EA_RX_DEBUG
1084		dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n",
1085			 addr, ptr, ctrl, status));
1086#endif
1087
1088
1089		/* Zero packet ptr ? then must be null header so exit */
1090		if (ptr == 0) break;
1091
1092
1093		/* Get packet length */
1094       		len = (ptr - addr) - 4;
1095
1096		if (len < 0)
1097			len += EA_RX_BUFFER_SIZE;
1098
1099#ifdef EA_RX_DEBUG
1100		dprintf(("len=%04x\n", len));
1101#endif
1102
1103
1104		/* Has the packet rx completed ? if not then exit */
1105		if ((status & EA_PKTHDR_DONE) == 0)
1106			break;
1107
1108		/*
1109		 * Did we have any errors? then note error and go to
1110		 * next packet
1111		 */
1112		if (__predict_false(status & 0x0f)) {
1113			++ifp->if_ierrors;
1114			log(LOG_WARNING,
1115			    "%s: rx packet error (%02x) - dropping packet\n",
1116			    sc->sc_dev.dv_xname, status & 0x0f);
1117			sc->sc_config2 |= EA_CFG2_OUTPUT;
1118			bus_space_write_2(iot, ioh, EA_8005_CONFIG2,
1119					  sc->sc_config2);
1120			ea_reinit(sc);
1121			return;
1122		}
1123
1124		/*
1125		 * Is the packet too big ? - this will probably be trapped
1126		 * above as a receive error
1127		 */
1128		if (__predict_false(len > (ETHER_MAX_LEN - ETHER_CRC_LEN))) {
1129			++ifp->if_ierrors;
1130			log(LOG_WARNING, "%s: rx packet size error len=%d\n",
1131			    sc->sc_dev.dv_xname, len);
1132			sc->sc_config2 |= EA_CFG2_OUTPUT;
1133			bus_space_write_2(iot, ioh, EA_8005_CONFIG2,
1134					  sc->sc_config2);
1135			ea_reinit(sc);
1136			return;
1137		}
1138
1139		ifp->if_ipackets++;
1140		/* Pass data up to upper levels. */
1141		earead(sc, addr + 4, len);
1142
1143		addr = ptr;
1144		++pack;
1145	} while (len != 0);
1146
1147	sc->sc_config2 |= EA_CFG2_OUTPUT;
1148	bus_space_write_2(iot, ioh, EA_8005_CONFIG2, sc->sc_config2);
1149
1150#ifdef EA_RX_DEBUG
1151	dprintf(("new rx ptr=%04x\n", addr));
1152#endif
1153
1154
1155	/* Store new rx pointer */
1156	sc->sc_rx_ptr = addr;
1157	bus_space_write_2(iot, ioh, EA_8005_RX_END, sc->sc_rx_ptr >> 8);
1158
1159	/* Make sure the receiver is on */
1160	bus_space_write_2(iot, ioh, EA_8005_COMMAND,
1161			  sc->sc_command | EA_CMD_RX_ON);
1162
1163}
1164
1165
1166/*
1167 * Pass a packet up to the higher levels.
1168 */
1169
1170static void
1171earead(struct seeq8005_softc *sc, int addr, int len)
1172{
1173	register struct ether_header *eh;
1174	struct mbuf *m;
1175	struct ifnet *ifp;
1176
1177	ifp = &sc->sc_ethercom.ec_if;
1178
1179	/* Pull packet off interface. */
1180	m = eaget(sc, addr, len, ifp);
1181	if (m == 0)
1182		return;
1183	eh = mtod(m, struct ether_header *);
1184
1185#ifdef EA_RX_DEBUG
1186	dprintf(("%s-->", ether_sprintf(eh->ether_shost)));
1187	dprintf(("%s\n", ether_sprintf(eh->ether_dhost)));
1188#endif
1189
1190#if NBPFILTER > 0
1191	/*
1192	 * Check if there's a BPF listener on this interface.
1193	 * If so, hand off the raw packet to bpf.
1194	 */
1195	if (ifp->if_bpf) {
1196		bpf_mtap(ifp->if_bpf, m);
1197
1198		/*
1199		 * Note that the interface cannot be in promiscuous mode if
1200		 * there are no BPF listeners.  And if we are in promiscuous
1201		 * mode, we have to check if this packet is really ours.
1202		 */
1203		if ((ifp->if_flags & IFF_PROMISC) &&
1204		    !ETHER_IS_MULTICAST(eh->ether_dhost) &&
1205		    bcmp(eh->ether_dhost, LLADDR(ifp->if_sadl),
1206			    sizeof(eh->ether_dhost)) != 0) {
1207			m_freem(m);
1208			return;
1209		}
1210	}
1211#endif
1212
1213	(*ifp->if_input)(ifp, m);
1214}
1215
1216/*
1217 * Pull read data off a interface.  Len is length of data, with local net
1218 * header stripped.  We copy the data into mbufs.  When full cluster sized
1219 * units are present we copy into clusters.
1220 */
1221
1222struct mbuf *
1223eaget(struct seeq8005_softc *sc, int addr, int totlen, struct ifnet *ifp)
1224{
1225        struct mbuf *top, **mp, *m;
1226        int len;
1227        u_int cp, epkt;
1228
1229        cp = addr;
1230        epkt = cp + totlen;
1231
1232        MGETHDR(m, M_DONTWAIT, MT_DATA);
1233        if (m == 0)
1234                return 0;
1235        m->m_pkthdr.rcvif = ifp;
1236        m->m_pkthdr.len = totlen;
1237        m->m_len = MHLEN;
1238        top = 0;
1239        mp = &top;
1240
1241        while (totlen > 0) {
1242                if (top) {
1243                        MGET(m, M_DONTWAIT, MT_DATA);
1244                        if (m == 0) {
1245                                m_freem(top);
1246                                return 0;
1247                        }
1248                        m->m_len = MLEN;
1249                }
1250                len = min(totlen, epkt - cp);
1251                if (len >= MINCLSIZE) {
1252                        MCLGET(m, M_DONTWAIT);
1253                        if (m->m_flags & M_EXT)
1254                                m->m_len = len = min(len, MCLBYTES);
1255                        else
1256                                len = m->m_len;
1257                } else {
1258                        /*
1259                         * Place initial small packet/header at end of mbuf.
1260                         */
1261                        if (len < m->m_len) {
1262                                if (top == 0 && len + max_linkhdr <= m->m_len)
1263                                        m->m_data += max_linkhdr;
1264                                m->m_len = len;
1265                        } else
1266                                len = m->m_len;
1267                }
1268		if (top == 0) {
1269			/* Make sure the payload is aligned */
1270			caddr_t newdata = (caddr_t)
1271			    ALIGN(m->m_data + sizeof(struct ether_header)) -
1272			    sizeof(struct ether_header);
1273			len -= newdata - m->m_data;
1274			m->m_len = len;
1275			m->m_data = newdata;
1276		}
1277                ea_readbuf(sc, mtod(m, u_char *),
1278			   cp < EA_BUFFER_SIZE ? cp : cp - EA_RX_BUFFER_SIZE,
1279			   len);
1280                cp += len;
1281                *mp = m;
1282                mp = &m->m_next;
1283                totlen -= len;
1284                if (cp == epkt)
1285                        cp = addr;
1286        }
1287
1288        return top;
1289}
1290
1291/*
1292 * Process an ioctl request. This code needs some work - it looks pretty ugly.
1293 */
1294static int
1295ea_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1296{
1297	struct seeq8005_softc *sc = ifp->if_softc;
1298	struct ifaddr *ifa = (struct ifaddr *)data;
1299/*	struct ifreq *ifr = (struct ifreq *)data;*/
1300	int s, error = 0;
1301
1302	s = splnet();
1303
1304	switch (cmd) {
1305
1306	case SIOCSIFADDR:
1307		ifp->if_flags |= IFF_UP;
1308		dprintf(("if_flags=%08x\n", ifp->if_flags));
1309
1310		switch (ifa->ifa_addr->sa_family) {
1311#ifdef INET
1312		case AF_INET:
1313			arp_ifinit(ifp, ifa);
1314			dprintf(("Interface ea is coming up (AF_INET)\n"));
1315			ea_init(sc);
1316			break;
1317#endif
1318#ifdef NS
1319		/* XXX - This code is probably wrong. */
1320		case AF_NS:
1321		    {
1322			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1323
1324			if (ns_nullhost(*ina))
1325				ina->x_host =
1326				    *(union ns_host *)LLADDR(ifp->if_sadl);
1327			else
1328				bcopy(ina->x_host.c_host,
1329				    LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
1330			/* Set new address. */
1331			dprintf(("Interface ea is coming up (AF_NS)\n"));
1332			ea_init(sc);
1333			break;
1334		    }
1335#endif
1336		default:
1337			dprintf(("Interface ea is coming up (default)\n"));
1338			ea_init(sc);
1339			break;
1340		}
1341		break;
1342
1343	case SIOCSIFFLAGS:
1344		dprintf(("if_flags=%08x\n", ifp->if_flags));
1345		if ((ifp->if_flags & IFF_UP) == 0 &&
1346		    (ifp->if_flags & IFF_RUNNING) != 0) {
1347			/*
1348			 * If interface is marked down and it is running, then
1349			 * stop it.
1350			 */
1351			dprintf(("Interface ea is stopping\n"));
1352			ea_stop(sc);
1353			ifp->if_flags &= ~IFF_RUNNING;
1354		} else if ((ifp->if_flags & IFF_UP) != 0 &&
1355		    	   (ifp->if_flags & IFF_RUNNING) == 0) {
1356			/*
1357			 * If interface is marked up and it is stopped, then
1358			 * start it.
1359			 */
1360			dprintf(("Interface ea is restarting(1)\n"));
1361			ea_init(sc);
1362		} else {
1363			/*
1364			 * Some other important flag might have changed, so
1365			 * reset.
1366			 */
1367			dprintf(("Interface ea is reinitialising\n"));
1368			ea_reinit(sc);
1369		}
1370		break;
1371
1372	default:
1373		error = EINVAL;
1374		break;
1375	}
1376
1377	splx(s);
1378	return error;
1379}
1380
1381/*
1382 * Device timeout routine.
1383 *
1384 * Ok I am not sure exactly how the device timeout should work....
1385 * Currently what will happens is that that the device timeout is only
1386 * set when a packet it received. This indicates we are on an active
1387 * network and thus we should expect more packets. If non arrive in
1388 * in the timeout period then we reinitialise as we may have jammed.
1389 * We zero the timeout at this point so that we don't end up with
1390 * an endless stream of timeouts if the network goes down.
1391 */
1392
1393static void
1394ea_watchdog(struct ifnet *ifp)
1395{
1396	struct seeq8005_softc *sc = ifp->if_softc;
1397
1398	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1399	ifp->if_oerrors++;
1400	dprintf(("ea_watchdog: "));
1401	dprintf(("st=%04x\n",
1402		 bus_space_read_2(sc->sc_iot, sc->sc_ioh, EA_8005_STATUS)));
1403
1404	/* Kick the interface */
1405
1406	ea_reinit(sc);
1407
1408/*	ifp->if_timer = EA_TIMEOUT;*/
1409	ifp->if_timer = 0;
1410}
1411
1412/* End of if_ea.c */
1413