if_el.c revision 1.22 1 /* $NetBSD: if_el.c,v 1.22 1995/04/11 05:10:24 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted
5 * to use, copy, modify and distribute this software provided that both
6 * the copyright notice and this permission notice appear in all copies
7 * of the software, derivative works or modified versions, and any
8 * portions thereof.
9 */
10
11 /*
12 * 3COM Etherlink 3C501 device driver
13 */
14
15 /*
16 * Bugs/possible improvements:
17 * - Does not currently support DMA
18 * - Does not currently support multicasts
19 */
20
21 #include "bpfilter.h"
22
23 #include <sys/param.h>
24 #include <sys/errno.h>
25 #include <sys/ioctl.h>
26 #include <sys/mbuf.h>
27 #include <sys/socket.h>
28 #include <sys/syslog.h>
29 #include <sys/device.h>
30
31 #include <net/if.h>
32 #include <net/if_dl.h>
33 #include <net/if_types.h>
34
35 #ifdef INET
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38 #include <netinet/in_var.h>
39 #include <netinet/ip.h>
40 #include <netinet/if_ether.h>
41 #endif
42
43 #ifdef NS
44 #include <netns/ns.h>
45 #include <netns/ns_if.h>
46 #endif
47
48 #if NBPFILTER > 0
49 #include <net/bpf.h>
50 #include <net/bpfdesc.h>
51 #endif
52
53 #include <machine/cpu.h>
54 #include <machine/pio.h>
55
56 #include <i386/isa/isavar.h>
57 #include <dev/isa/if_elreg.h>
58
59 #define ETHER_MIN_LEN 64
60 #define ETHER_MAX_LEN 1518
61 #define ETHER_ADDR_LEN 6
62
63 /* for debugging convenience */
64 #ifdef EL_DEBUG
65 #define dprintf(x) printf x
66 #else
67 #define dprintf(x)
68 #endif
69
70 /*
71 * per-line info and status
72 */
73 struct el_softc {
74 struct device sc_dev;
75 struct intrhand sc_ih;
76
77 struct arpcom sc_arpcom; /* ethernet common */
78 int sc_iobase; /* base I/O addr */
79 char sc_pktbuf[EL_BUFSIZ]; /* frame buffer */
80 };
81
82 /*
83 * prototypes
84 */
85 int elintr __P((struct el_softc *));
86 static int el_init __P((struct el_softc *));
87 static int el_ioctl __P((struct ifnet *, u_long, caddr_t));
88 static void el_start __P((struct ifnet *));
89 static void el_watchdog __P((int));
90 static void el_reset __P((struct el_softc *));
91 static void el_stop __P((struct el_softc *));
92 static int el_xmit __P((struct el_softc *, int));
93 static inline void elread __P((struct el_softc *, caddr_t, int));
94 static struct mbuf *elget __P((caddr_t, int, struct ifnet *));
95 static inline void el_hardreset __P((struct el_softc *));
96
97 int elprobe __P((struct device *, void *, void *));
98 void elattach __P((struct device *, struct device *, void *));
99
100 /* isa_driver structure for autoconf */
101 struct cfdriver elcd = {
102 NULL, "el", elprobe, elattach, DV_IFNET, sizeof(struct el_softc)
103 };
104
105 /*
106 * Probe routine.
107 *
108 * See if the card is there and at the right place.
109 * (XXX - cgd -- needs help)
110 */
111 int
112 elprobe(parent, match, aux)
113 struct device *parent;
114 void *match, *aux;
115 {
116 struct el_softc *sc = match;
117 struct isa_attach_args *ia = aux;
118 int iobase = ia->ia_iobase;
119 u_char station_addr[ETHER_ADDR_LEN];
120 int i;
121
122 /* First check the base. */
123 if (iobase < 0x280 || iobase > 0x3f0)
124 return 0;
125
126 /* Grab some info for our structure. */
127 sc->sc_iobase = iobase;
128
129 /*
130 * Now attempt to grab the station address from the PROM and see if it
131 * contains the 3com vendor code.
132 */
133 dprintf(("Probing 3c501 at 0x%x...\n", iobase));
134
135 /* Reset the board. */
136 dprintf(("Resetting board...\n"));
137 outb(iobase+EL_AC, EL_AC_RESET);
138 delay(5);
139 outb(iobase+EL_AC, 0);
140
141 /* Now read the address. */
142 dprintf(("Reading station address...\n"));
143 for (i = 0; i < ETHER_ADDR_LEN; i++) {
144 outb(iobase+EL_GPBL, i);
145 station_addr[i] = inb(iobase+EL_EAW);
146 }
147 dprintf(("Address is %s\n", ether_sprintf(station_addr)));
148
149 /*
150 * If the vendor code is ok, return a 1. We'll assume that whoever
151 * configured this system is right about the IRQ.
152 */
153 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 ||
154 station_addr[2] != 0x8c) {
155 dprintf(("Bad vendor code.\n"));
156 return 0;
157 }
158
159 dprintf(("Vendor code ok.\n"));
160 /* Copy the station address into the arpcom structure. */
161 bcopy(station_addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
162
163 ia->ia_iosize = 4; /* XXX */
164 ia->ia_msize = 0;
165 return 1;
166 }
167
168 /*
169 * Attach the interface to the kernel data structures. By the time this is
170 * called, we know that the card exists at the given I/O address. We still
171 * assume that the IRQ given is correct.
172 */
173 void
174 elattach(parent, self, aux)
175 struct device *parent, *self;
176 void *aux;
177 {
178 struct el_softc *sc = (void *)self;
179 struct isa_attach_args *ia = aux;
180 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
181
182 dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));
183
184 /* Stop the board. */
185 el_stop(sc);
186
187 /* Initialize ifnet structure. */
188 ifp->if_unit = sc->sc_dev.dv_unit;
189 ifp->if_name = elcd.cd_name;
190 ifp->if_start = el_start;
191 ifp->if_ioctl = el_ioctl;
192 ifp->if_watchdog = el_watchdog;
193 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
194
195 /* Now we can attach the interface. */
196 dprintf(("Attaching interface...\n"));
197 if_attach(ifp);
198 ether_ifattach(ifp);
199
200 /* Print out some information for the user. */
201 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
202
203 /* Finally, attach to bpf filter if it is present. */
204 #if NBPFILTER > 0
205 dprintf(("Attaching to BPF...\n"));
206 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
207 #endif
208
209 sc->sc_ih.ih_fun = elintr;
210 sc->sc_ih.ih_arg = sc;
211 sc->sc_ih.ih_level = IPL_NET;
212 intr_establish(ia->ia_irq, IST_EDGE, &sc->sc_ih);
213
214 dprintf(("elattach() finished.\n"));
215 }
216
217 /*
218 * Reset interface.
219 */
220 static void
221 el_reset(sc)
222 struct el_softc *sc;
223 {
224 int s;
225
226 dprintf(("elreset()\n"));
227 s = splimp();
228 el_stop(sc);
229 el_init(sc);
230 splx(s);
231 }
232
233 /*
234 * Stop interface.
235 */
236 static void
237 el_stop(sc)
238 struct el_softc *sc;
239 {
240
241 outb(sc->sc_iobase+EL_AC, 0);
242 }
243
244 /*
245 * Do a hardware reset of the board, and upload the ethernet address again in
246 * case the board forgets.
247 */
248 static inline void
249 el_hardreset(sc)
250 struct el_softc *sc;
251 {
252 int iobase = sc->sc_iobase;
253 int i;
254
255 outb(iobase+EL_AC, EL_AC_RESET);
256 delay(5);
257 outb(iobase+EL_AC, 0);
258
259 for (i = 0; i < ETHER_ADDR_LEN; i++)
260 outb(iobase+i, sc->sc_arpcom.ac_enaddr[i]);
261 }
262
263 /*
264 * Initialize interface.
265 */
266 static int
267 el_init(sc)
268 struct el_softc *sc;
269 {
270 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
271 int iobase = sc->sc_iobase;
272 int s;
273
274 /* If address not known, do nothing. */
275 if (ifp->if_addrlist == 0)
276 return;
277
278 s = splimp();
279
280 /* First, reset the board. */
281 el_hardreset(sc);
282
283 /* Configure rx. */
284 dprintf(("Configuring rx...\n"));
285 if (ifp->if_flags & IFF_PROMISC)
286 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
287 else
288 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
289 outb(iobase+EL_RBC, 0);
290
291 /* Configure TX. */
292 dprintf(("Configuring tx...\n"));
293 outb(iobase+EL_TXC, 0);
294
295 /* Start reception. */
296 dprintf(("Starting reception...\n"));
297 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
298
299 /* Set flags appropriately. */
300 ifp->if_flags |= IFF_RUNNING;
301 ifp->if_flags &= ~IFF_OACTIVE;
302
303 /* And start output. */
304 el_start(ifp);
305
306 splx(s);
307 }
308
309 /*
310 * Start output on interface. Get datagrams from the queue and output them,
311 * giving the receiver a chance between datagrams. Call only from splimp or
312 * interrupt level!
313 */
314 static void
315 el_start(ifp)
316 struct ifnet *ifp;
317 {
318 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
319 int iobase = sc->sc_iobase;
320 struct mbuf *m, *m0;
321 int s, i, len, retries, done;
322
323 dprintf(("el_start()...\n"));
324 s = splimp();
325
326 /* Don't do anything if output is active. */
327 if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
328 return;
329 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
330
331 /*
332 * The main loop. They warned me against endless loops, but would I
333 * listen? NOOO....
334 */
335 for (;;) {
336 /* Dequeue the next datagram. */
337 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
338
339 /* If there's nothing to send, return. */
340 if (!m0) {
341 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
342 splx(s);
343 return;
344 }
345
346 /* Disable the receiver. */
347 outb(iobase+EL_AC, EL_AC_HOST);
348 outb(iobase+EL_RBC, 0);
349
350 /* Copy the datagram to the buffer. */
351 len = 0;
352 for (m = m0; m; m = m->m_next) {
353 if (m->m_len == 0)
354 continue;
355 bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
356 len += m->m_len;
357 }
358 m_freem(m0);
359
360 len = max(len, ETHER_MIN_LEN);
361
362 /* Give the packet to the bpf, if any. */
363 #if NBPFILTER > 0
364 if (sc->sc_arpcom.ac_if.if_bpf)
365 bpf_tap(sc->sc_arpcom.ac_if.if_bpf, sc->sc_pktbuf, len);
366 #endif
367
368 /* Transfer datagram to board. */
369 dprintf(("el: xfr pkt length=%d...\n", len));
370 i = EL_BUFSIZ - len;
371 outb(iobase+EL_GPBL, i);
372 outb(iobase+EL_GPBH, i >> 8);
373 outsb(iobase+EL_BUF, sc->sc_pktbuf, len);
374
375 /* Now transmit the datagram. */
376 retries = 0;
377 done = 0;
378 while (!done) {
379 if (el_xmit(sc, len)) {
380 /* Something went wrong. */
381 done = -1;
382 break;
383 }
384 /* Check out status. */
385 i = inb(iobase+EL_TXS);
386 dprintf(("tx status=0x%x\n", i));
387 if ((i & EL_TXS_READY) == 0) {
388 dprintf(("el: err txs=%x\n", i));
389 sc->sc_arpcom.ac_if.if_oerrors++;
390 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) {
391 if ((i & EL_TXC_DCOLL16) == 0 &&
392 retries < 15) {
393 retries++;
394 outb(iobase+EL_AC, EL_AC_HOST);
395 }
396 } else
397 done = 1;
398 } else {
399 sc->sc_arpcom.ac_if.if_opackets++;
400 done = 1;
401 }
402 }
403 if (done == -1)
404 /* Packet not transmitted. */
405 continue;
406
407 /*
408 * Now give the card a chance to receive.
409 * Gotta love 3c501s...
410 */
411 (void)inb(iobase+EL_AS);
412 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
413 splx(s);
414 /* Interrupt here. */
415 s = splimp();
416 }
417 }
418
419 /*
420 * This function actually attempts to transmit a datagram downloaded to the
421 * board. Call at splimp or interrupt, after downloading data! Returns 0 on
422 * success, non-0 on failure.
423 */
424 static int
425 el_xmit(sc, len)
426 struct el_softc *sc;
427 int len;
428 {
429 int iobase = sc->sc_iobase;
430 int gpl;
431 int i;
432
433 gpl = EL_BUFSIZ - len;
434 dprintf(("el: xmit..."));
435 outb(iobase+EL_GPBL, gpl);
436 outb(iobase+EL_GPBH, gpl >> 8);
437 outb(iobase+EL_AC, EL_AC_TXFRX);
438 i = 20000;
439 while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0))
440 i--;
441 if (i == 0) {
442 dprintf(("tx not ready\n"));
443 sc->sc_arpcom.ac_if.if_oerrors++;
444 return -1;
445 }
446 dprintf(("%d cycles.\n", 20000 - i));
447 return 0;
448 }
449
450 /*
451 * Controller interrupt.
452 */
453 int
454 elintr(sc)
455 register struct el_softc *sc;
456 {
457 int iobase = sc->sc_iobase;
458 int stat, rxstat, len, done;
459
460 dprintf(("elintr: "));
461
462 /* Check board status. */
463 stat = inb(iobase+EL_AS);
464 if (stat & EL_AS_RXBUSY) {
465 (void)inb(iobase+EL_RXC);
466 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
467 return 0;
468 }
469
470 done = 0;
471 while (!done) {
472 rxstat = inb(iobase+EL_RXS);
473 if (rxstat & EL_RXS_STALE) {
474 (void)inb(iobase+EL_RXC);
475 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
476 return 1;
477 }
478
479 /* If there's an overflow, reinit the board. */
480 if ((rxstat & EL_RXS_NOFLOW) == 0) {
481 dprintf(("overflow.\n"));
482 el_hardreset(sc);
483 /* Put board back into receive mode. */
484 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
485 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
486 else
487 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
488 (void)inb(iobase+EL_AS);
489 outb(iobase+EL_RBC, 0);
490 (void)inb(iobase+EL_RXC);
491 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
492 return 1;
493 }
494
495 /* Incoming packet. */
496 len = inb(iobase+EL_RBL);
497 len |= inb(iobase+EL_RBH) << 8;
498 dprintf(("receive len=%d rxstat=%x ", len, rxstat));
499 outb(iobase+EL_AC, EL_AC_HOST);
500
501 /*
502 * If packet too short or too long, restore rx mode and return.
503 */
504 if (len <= sizeof(struct ether_header) ||
505 len > ETHER_MAX_LEN) {
506 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
507 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
508 else
509 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
510 (void)inb(iobase+EL_AS);
511 outb(iobase+EL_RBC, 0);
512 (void)inb(iobase+EL_RXC);
513 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
514 return 1;
515 }
516
517 sc->sc_arpcom.ac_if.if_ipackets++;
518
519 /* Copy the data into our buffer. */
520 outb(iobase+EL_GPBL, 0);
521 outb(iobase+EL_GPBH, 0);
522 insb(iobase+EL_BUF, sc->sc_pktbuf, len);
523 outb(iobase+EL_RBC, 0);
524 outb(iobase+EL_AC, EL_AC_RX);
525 dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
526 dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
527
528 /* Pass data up to upper levels. */
529 elread(sc, (caddr_t)sc->sc_pktbuf, len);
530
531 /* Is there another packet? */
532 stat = inb(iobase+EL_AS);
533
534 /* If so, do it all again (i.e. don't set done to 1). */
535 if ((stat & EL_AS_RXBUSY) == 0)
536 dprintf(("<rescan> "));
537 else
538 done = 1;
539 }
540
541 (void)inb(iobase+EL_RXC);
542 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
543 return 1;
544 }
545
546 /*
547 * Pass a packet up to the higher levels.
548 */
549 static inline void
550 elread(sc, buf, len)
551 struct el_softc *sc;
552 caddr_t buf;
553 int len;
554 {
555 register struct ether_header *eh;
556 struct mbuf *m;
557
558 eh = (struct ether_header *)buf;
559 len -= sizeof(struct ether_header);
560 if (len <= 0)
561 return;
562
563 /* Pull packet off interface. */
564 m = elget(buf, len, &sc->sc_arpcom.ac_if);
565 if (m == 0)
566 return;
567
568 #if NBPFILTER > 0
569 /*
570 * Check if there's a BPF listener on this interface.
571 * If so, hand off the raw packet to bpf.
572 */
573 if (sc->sc_arpcom.ac_if.if_bpf) {
574 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
575
576 /*
577 * Note that the interface cannot be in promiscuous mode if
578 * there are no BPF listeners. And if we are in promiscuous
579 * mode, we have to check if this packet is really ours.
580 */
581 if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
582 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
583 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
584 sizeof(eh->ether_dhost)) != 0) {
585 m_freem(m);
586 return;
587 }
588 }
589 #endif
590
591 ether_input(&sc->sc_arpcom.ac_if, eh, m);
592 }
593
594 /*
595 * Pull read data off a interface. Len is length of data, with local net
596 * header stripped. We copy the data into mbufs. When full cluster sized
597 * units are present we copy into clusters.
598 */
599 struct mbuf *
600 elget(buf, totlen, ifp)
601 caddr_t buf;
602 int totlen;
603 struct ifnet *ifp;
604 {
605 struct mbuf *top, **mp, *m, *p;
606 int len;
607 register caddr_t cp = buf;
608 char *epkt;
609
610 buf += sizeof(struct ether_header);
611 cp = buf;
612 epkt = cp + totlen;
613
614 MGETHDR(m, M_DONTWAIT, MT_DATA);
615 if (m == 0)
616 return 0;
617 m->m_pkthdr.rcvif = ifp;
618 m->m_pkthdr.len = totlen;
619 m->m_len = MHLEN;
620 top = 0;
621 mp = ⊤
622
623 while (totlen > 0) {
624 if (top) {
625 MGET(m, M_DONTWAIT, MT_DATA);
626 if (m == 0) {
627 m_freem(top);
628 return 0;
629 }
630 m->m_len = MLEN;
631 }
632 len = min(totlen, epkt - cp);
633 if (len >= MINCLSIZE) {
634 MCLGET(m, M_DONTWAIT);
635 if (m->m_flags & M_EXT)
636 m->m_len = len = min(len, MCLBYTES);
637 else
638 len = m->m_len;
639 } else {
640 /*
641 * Place initial small packet/header at end of mbuf.
642 */
643 if (len < m->m_len) {
644 if (top == 0 && len + max_linkhdr <= m->m_len)
645 m->m_data += max_linkhdr;
646 m->m_len = len;
647 } else
648 len = m->m_len;
649 }
650 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
651 cp += len;
652 *mp = m;
653 mp = &m->m_next;
654 totlen -= len;
655 if (cp == epkt)
656 cp = buf;
657 }
658
659 return top;
660 }
661
662 /*
663 * Process an ioctl request. This code needs some work - it looks pretty ugly.
664 */
665 static int
666 el_ioctl(ifp, cmd, data)
667 register struct ifnet *ifp;
668 u_long cmd;
669 caddr_t data;
670 {
671 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
672 struct ifaddr *ifa = (struct ifaddr *)data;
673 struct ifreq *ifr = (struct ifreq *)data;
674 int s, error = 0;
675
676 s = splimp();
677
678 switch (cmd) {
679
680 case SIOCSIFADDR:
681 ifp->if_flags |= IFF_UP;
682
683 switch (ifa->ifa_addr->sa_family) {
684 #ifdef INET
685 case AF_INET:
686 el_init(sc);
687 arp_ifinit(&sc->sc_arpcom, ifa);
688 break;
689 #endif
690 #ifdef NS
691 /*
692 * XXX - This code is probably wrong.
693 */
694 case AF_NS:
695 {
696 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
697
698 if (ns_nullhost(*ina))
699 ina->x_host =
700 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
701 else {
702 /*
703 *
704 */
705 bcopy((caddr_t)ina->x_host.c_host,
706 (caddr_t)sc->sc_arpcom.ac_enaddr,
707 sizeof(sc->sc_arpcom.ac_enaddr));
708 }
709 /* Set new address. */
710 el_init(sc);
711 break;
712 }
713 #endif
714 default:
715 el_init(sc);
716 break;
717 }
718 break;
719
720 case SIOCSIFFLAGS:
721 if ((ifp->if_flags & IFF_UP) == 0 &&
722 (ifp->if_flags & IFF_RUNNING) != 0) {
723 /*
724 * If interface is marked down and it is running, then
725 * stop it.
726 */
727 el_stop(sc);
728 ifp->if_flags &= ~IFF_RUNNING;
729 } else if ((ifp->if_flags & IFF_UP) != 0 &&
730 (ifp->if_flags & IFF_RUNNING) == 0) {
731 /*
732 * If interface is marked up and it is stopped, then
733 * start it.
734 */
735 el_init(sc);
736 } else {
737 /*
738 * Some other important flag might have changed, so
739 * reset.
740 */
741 el_reset(sc);
742 }
743
744 default:
745 error = EINVAL;
746 }
747 splx(s);
748 return error;
749 }
750
751 /*
752 * Device timeout routine.
753 */
754 static void
755 el_watchdog(unit)
756 int unit;
757 {
758 struct el_softc *sc = elcd.cd_devs[unit];
759
760 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
761 sc->sc_arpcom.ac_if.if_oerrors++;
762
763 el_reset(sc);
764 }
765