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