]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/i386/isa/if_el.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / sys / i386 / isa / if_el.c
1 /*-
2  * Copyright (c) 1994, Matthew E. Kimmel.  Permission is hereby granted
3  * to use, copy, modify and distribute this software provided that both
4  * the copyright notice and this permission notice appear in all copies
5  * of the software, derivative works or modified versions, and any
6  * portions thereof.
7  *
8  * Questions, comments, bug reports and fixes to kimmel@cs.umass.edu.
9  */
10
11 #include <sys/cdefs.h>
12 __FBSDID("$FreeBSD$");
13
14 /* Except of course for the portions of code lifted from other FreeBSD
15  * drivers (mainly elread, elget and el_ioctl)
16  */
17 /* 3COM Etherlink 3C501 device driver for FreeBSD */
18 /* Yeah, I know these cards suck, but you can also get them for free
19  * really easily...
20  */
21 /* Bugs/possible improvements:
22  *      - Does not currently support DMA
23  *      - Does not currently support multicasts
24  */
25 #include "opt_inet.h"
26 #include "opt_ipx.h"
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kernel.h>
31 #include <sys/module.h>
32 #include <sys/sockio.h>
33 #include <sys/mbuf.h>
34 #include <sys/socket.h>
35 #include <sys/syslog.h>
36 #include <sys/bus.h>
37
38 #include <net/ethernet.h>
39 #include <net/if.h>
40 #include <net/if_types.h>
41
42 #include <netinet/in.h>
43 #include <netinet/if_ether.h>
44
45 #include <net/bpf.h>
46
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/bus.h>
50 #include <sys/rman.h>
51
52 #include <isa/isavar.h>
53
54 #include <i386/isa/if_elreg.h>
55
56 /* For debugging convenience */
57 #ifdef EL_DEBUG
58 #define dprintf(x) printf x
59 #else
60 #define dprintf(x)
61 #endif
62
63 /* el_softc: per line info and status */
64 struct el_softc {
65         struct ifnet            *el_ifp;
66         u_char                  el_enaddr[6];
67         bus_space_handle_t      el_bhandle;
68         bus_space_tag_t         el_btag;
69         void                    *el_intrhand;
70         struct resource         *el_irq;
71         struct resource         *el_res;
72         struct mtx              el_mtx;
73         char el_pktbuf[EL_BUFSIZ];      /* Frame buffer */
74 };
75
76 /* Prototypes */
77 static int el_attach(device_t);
78 static int el_detach(device_t);
79 static void el_init(void *);
80 static int el_ioctl(struct ifnet *,u_long,caddr_t);
81 static int el_probe(device_t);
82 static void el_start(struct ifnet *);
83 static void el_reset(void *);
84 static void el_watchdog(struct ifnet *);
85 static int el_shutdown(device_t);
86
87 static void el_stop(void *);
88 static int el_xmit(struct el_softc *,int);
89 static void elintr(void *);
90 static __inline void elread(struct el_softc *,caddr_t,int);
91 static struct mbuf *elget(caddr_t,int,struct ifnet *);
92 static __inline void el_hardreset(void *);
93
94 static device_method_t el_methods[] = {
95         /* Device interface */
96         DEVMETHOD(device_probe,         el_probe),
97         DEVMETHOD(device_attach,        el_attach),
98         DEVMETHOD(device_detach,        el_detach),
99         DEVMETHOD(device_shutdown,      el_shutdown),
100         { 0, 0 }
101 };
102
103 static driver_t el_driver = {
104         "el",
105         el_methods,
106         sizeof(struct el_softc)
107 };
108
109 static devclass_t el_devclass;
110
111 DRIVER_MODULE(if_el, isa, el_driver, el_devclass, 0, 0);
112
113 #define CSR_WRITE_1(sc, reg, val)       \
114         bus_space_write_1(sc->el_btag, sc->el_bhandle, reg, val)
115 #define CSR_READ_1(sc, reg)             \
116         bus_space_read_1(sc->el_btag, sc->el_bhandle, reg)
117
118 #define EL_LOCK(_sc)            mtx_lock(&(_sc)->el_mtx)
119 #define EL_UNLOCK(_sc)          mtx_unlock(&(_sc)->el_mtx)
120
121 /* Probe routine.  See if the card is there and at the right place. */
122 static int
123 el_probe(device_t dev)
124 {
125         struct el_softc *sc;
126         u_short base; /* Just for convenience */
127         int i, rid;
128
129         /* Grab some info for our structure */
130         sc = device_get_softc(dev);
131
132         if (isa_get_logicalid(dev))             /* skip PnP probes */
133                 return (ENXIO);
134
135         if ((base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
136                 return (ENXIO);
137
138         /* First check the base */
139         if((base < 0x280) || (base > 0x3f0)) {
140                 device_printf(dev,
141                     "ioaddr must be between 0x280 and 0x3f0\n");
142                 return(ENXIO);
143         }
144
145         /* Temporarily map the resources. */
146         rid = 0;
147         sc->el_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
148             0, ~0, EL_IOSIZ, RF_ACTIVE);
149
150         if (sc->el_res == NULL)
151                 return(ENXIO);
152
153         sc->el_btag = rman_get_bustag(sc->el_res);
154         sc->el_bhandle = rman_get_bushandle(sc->el_res);
155         mtx_init(&sc->el_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
156             MTX_DEF | MTX_RECURSE);
157         EL_LOCK(sc);
158
159         /* Now attempt to grab the station address from the PROM
160          * and see if it contains the 3com vendor code.
161          */
162         dprintf(("Probing 3c501 at 0x%x...\n",base));
163
164         /* Reset the board */
165         dprintf(("Resetting board...\n"));
166         CSR_WRITE_1(sc,EL_AC,EL_AC_RESET);
167         DELAY(5);
168         CSR_WRITE_1(sc,EL_AC,0);
169         dprintf(("Reading station address...\n"));
170         /* Now read the address */
171         for(i=0;i<ETHER_ADDR_LEN;i++) {
172                 CSR_WRITE_1(sc,EL_GPBL,i);
173                 sc->el_enaddr[i] = CSR_READ_1(sc,EL_EAW);
174         }
175
176         /* Now release resources */
177         bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->el_res);
178         EL_UNLOCK(sc);
179         mtx_destroy(&sc->el_mtx);
180
181         dprintf(("Address is %6D\n",sc->el_enaddr, ":"));
182
183         /* If the vendor code is ok, return a 1.  We'll assume that
184          * whoever configured this system is right about the IRQ.
185          */
186         if((sc->el_enaddr[0] != 0x02) || (sc->el_enaddr[1] != 0x60)
187            || (sc->el_enaddr[2] != 0x8c)) {
188                 dprintf(("Bad vendor code.\n"));
189                 return(ENXIO);
190         } else {
191                 dprintf(("Vendor code ok.\n"));
192         }
193
194         device_set_desc(dev, "3Com 3c501 Ethernet");
195
196         return(0);
197 }
198
199 /* Do a hardware reset of the 3c501.  Do not call until after el_probe()! */
200 static __inline void
201 el_hardreset(xsc)
202         void *xsc;
203 {
204         register struct el_softc *sc = xsc;
205         register int j;
206
207         /* First reset the board */
208         CSR_WRITE_1(sc,EL_AC,EL_AC_RESET);
209         DELAY(5);
210         CSR_WRITE_1(sc,EL_AC,0);
211
212         /* Then give it back its ethernet address.  Thanks to the mach
213          * source code for this undocumented goodie...
214          */
215         for(j=0;j<ETHER_ADDR_LEN;j++)
216                 CSR_WRITE_1(sc,j,IFP2ENADDR(sc->el_ifp)[j]);
217 }
218
219 /* Attach the interface to the kernel data structures.  By the time
220  * this is called, we know that the card exists at the given I/O address.
221  * We still assume that the IRQ given is correct.
222  */
223 static int
224 el_attach(device_t dev)
225 {
226         struct el_softc *sc;
227         struct ifnet *ifp;
228         int rid, error;
229
230         dprintf(("Attaching el%d...\n",device_get_unit(dev)));
231
232         /* Get things pointing to the right places. */
233         sc = device_get_softc(dev);
234         ifp = sc->el_ifp = if_alloc(IFT_ETHER);
235
236         if (ifp == NULL)
237                 return (ENOSPC);
238
239         rid = 0;
240         sc->el_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
241             0, ~0, EL_IOSIZ, RF_ACTIVE);
242
243         if (sc->el_res == NULL) {
244                 if_free(ifp);
245                 return(ENXIO);
246         }
247
248         rid = 0;
249         sc->el_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
250             RF_SHAREABLE | RF_ACTIVE);
251
252         if (sc->el_irq == NULL) {
253                 if_free(ifp);
254                 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->el_res);
255                 return(ENXIO);
256         }
257
258         error = bus_setup_intr(dev, sc->el_irq, INTR_TYPE_NET,
259                 elintr, sc, &sc->el_intrhand);
260
261         if (error) {
262                 if_free(ifp);
263                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->el_irq);
264                 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->el_res);
265                 return(ENXIO);
266         }
267
268         /* Initialize ifnet structure */
269         ifp->if_softc = sc;
270         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
271         ifp->if_mtu = ETHERMTU;
272         ifp->if_start = el_start;
273         ifp->if_ioctl = el_ioctl;
274         ifp->if_watchdog = el_watchdog;
275         ifp->if_init = el_init;
276         ifp->if_flags = (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
277         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
278
279         /* Now we can attach the interface */
280         dprintf(("Attaching interface...\n"));
281         ether_ifattach(ifp, sc->el_enaddr);
282
283         /* Now reset the board */
284         dprintf(("Resetting board...\n"));
285         el_hardreset(sc);
286
287         dprintf(("el_attach() finished.\n"));
288         return(0);
289 }
290
291 static int el_detach(dev)
292         device_t dev;
293 {
294         struct el_softc *sc;
295         struct ifnet *ifp;
296
297         sc = device_get_softc(dev);
298         ifp = sc->el_ifp;
299
300         el_stop(sc);
301         EL_LOCK(sc);
302         ether_ifdetach(ifp);
303         if_free(ifp);
304         bus_teardown_intr(dev, sc->el_irq, sc->el_intrhand);
305         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->el_irq);
306         bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->el_res);
307         EL_UNLOCK(sc);
308         mtx_destroy(&sc->el_mtx);
309
310         return(0);
311 }
312
313 static int
314 el_shutdown(dev)
315         device_t dev;
316 {
317         struct el_softc *sc;
318
319         sc = device_get_softc(dev);
320         el_stop(sc);
321         return(0);
322 }
323
324 /* This routine resets the interface. */
325 static void 
326 el_reset(xsc)
327         void *xsc;
328 {
329         struct el_softc *sc = xsc;
330
331         dprintf(("elreset()\n"));
332         el_stop(sc);
333         el_init(sc);
334 }
335
336 static void el_stop(xsc)
337         void *xsc;
338 {
339         struct el_softc *sc = xsc;
340
341         EL_LOCK(sc);
342         CSR_WRITE_1(sc,EL_AC,0);
343         el_hardreset(sc);
344         EL_UNLOCK(sc);
345 }
346
347 /* Initialize interface.  */
348 static void 
349 el_init(xsc)
350         void *xsc;
351 {
352         struct el_softc *sc = xsc;
353         struct ifnet *ifp;
354
355         /* Set up pointers */
356         ifp = sc->el_ifp;
357
358         /* If address not known, do nothing. */
359         if(TAILQ_EMPTY(&ifp->if_addrhead)) /* XXX unlikely */
360                 return;
361
362         EL_LOCK(sc);
363
364         /* First, reset the board. */
365         dprintf(("Resetting board...\n"));
366         el_hardreset(sc);
367
368         /* Configure rx */
369         dprintf(("Configuring rx...\n"));
370         if(ifp->if_flags & IFF_PROMISC)
371                 CSR_WRITE_1(sc,EL_RXC,
372                     (EL_RXC_PROMISC|EL_RXC_ABROAD|EL_RXC_AMULTI|
373                     EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
374         else
375                 CSR_WRITE_1(sc,EL_RXC,
376                     (EL_RXC_ABROAD|EL_RXC_AMULTI|
377                     EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
378         CSR_WRITE_1(sc,EL_RBC,0);
379
380         /* Configure TX */
381         dprintf(("Configuring tx...\n"));
382         CSR_WRITE_1(sc,EL_TXC,0);
383
384         /* Start reception */
385         dprintf(("Starting reception...\n"));
386         CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
387
388         /* Set flags appropriately */
389         ifp->if_drv_flags |= IFF_DRV_RUNNING;
390         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
391
392         /* And start output. */
393         el_start(ifp);
394
395         EL_UNLOCK(sc);
396 }
397
398 /* Start output on interface.  Get datagrams from the queue and output
399  * them, giving the receiver a chance between datagrams.  Call only
400  * from splimp or interrupt level!
401  */
402 static void
403 el_start(struct ifnet *ifp)
404 {
405         struct el_softc *sc;
406         struct mbuf *m, *m0;
407         int i, len, retries, done;
408
409         /* Get things pointing in the right directions */
410         sc = ifp->if_softc;
411
412         dprintf(("el_start()...\n"));
413         EL_LOCK(sc);
414
415         /* Don't do anything if output is active */
416         if(sc->el_ifp->if_drv_flags & IFF_DRV_OACTIVE)
417                 return;
418         sc->el_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
419
420         /* The main loop.  They warned me against endless loops, but
421          * would I listen?  NOOO....
422          */
423         while(1) {
424                 /* Dequeue the next datagram */
425                 IF_DEQUEUE(&sc->el_ifp->if_snd,m0);
426
427                 /* If there's nothing to send, return. */
428                 if(m0 == NULL) {
429                         sc->el_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
430                         EL_UNLOCK(sc);
431                         return;
432                 }
433
434                 /* Disable the receiver */
435                 CSR_WRITE_1(sc,EL_AC,EL_AC_HOST);
436                 CSR_WRITE_1(sc,EL_RBC,0);
437
438                 /* Copy the datagram to the buffer. */
439                 len = 0;
440                 for(m = m0; m != NULL; m = m->m_next) {
441                         if(m->m_len == 0)
442                                 continue;
443                         bcopy(mtod(m,caddr_t),sc->el_pktbuf+len,m->m_len);
444                         len += m->m_len;
445                 }
446                 m_freem(m0);
447
448                 len = max(len,ETHER_MIN_LEN);
449
450                 /* Give the packet to the bpf, if any */
451                 BPF_TAP(sc->el_ifp, sc->el_pktbuf, len);
452
453                 /* Transfer datagram to board */
454                 dprintf(("el: xfr pkt length=%d...\n",len));
455                 i = EL_BUFSIZ - len;
456                 CSR_WRITE_1(sc,EL_GPBL,(i & 0xff));
457                 CSR_WRITE_1(sc,EL_GPBH,((i>>8)&0xff));
458                 bus_space_write_multi_1(sc->el_btag, sc->el_bhandle,
459                     EL_BUF, sc->el_pktbuf, len);
460
461                 /* Now transmit the datagram */
462                 retries=0;
463                 done=0;
464                 while(!done) {
465                         if(el_xmit(sc,len)) { /* Something went wrong */
466                                 done = -1;
467                                 break;
468                         }
469                         /* Check out status */
470                         i = CSR_READ_1(sc,EL_TXS);
471                         dprintf(("tx status=0x%x\n",i));
472                         if(!(i & EL_TXS_READY)) {
473                                 dprintf(("el: err txs=%x\n",i));
474                                 sc->el_ifp->if_oerrors++;
475                                 if(i & (EL_TXS_COLL|EL_TXS_COLL16)) {
476                                         if((!(i & EL_TXC_DCOLL16)) && retries < 15) {
477                                                 retries++;
478                                                 CSR_WRITE_1(sc,EL_AC,EL_AC_HOST);
479                                         }
480                                 }
481                                 else
482                                         done = 1;
483                         }
484                         else {
485                                 sc->el_ifp->if_opackets++;
486                                 done = 1;
487                         }
488                 }
489                 if(done == -1)  /* Packet not transmitted */
490                         continue;
491
492                 /* Now give the card a chance to receive.
493                  * Gotta love 3c501s...
494                  */
495                 (void)CSR_READ_1(sc,EL_AS);
496                 CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
497                 EL_UNLOCK(sc);
498                 /* Interrupt here */
499                 EL_LOCK(sc);
500         }
501 }
502
503 /* This function actually attempts to transmit a datagram downloaded
504  * to the board.  Call at splimp or interrupt, after downloading data!
505  * Returns 0 on success, non-0 on failure
506  */
507 static int
508 el_xmit(struct el_softc *sc,int len)
509 {
510         int gpl;
511         int i;
512
513         gpl = EL_BUFSIZ - len;
514         dprintf(("el: xmit..."));
515         CSR_WRITE_1(sc,EL_GPBL,(gpl & 0xff));
516         CSR_WRITE_1(sc,EL_GPBH,((gpl>>8)&0xff));
517         CSR_WRITE_1(sc,EL_AC,EL_AC_TXFRX);
518         i = 20000;
519         while((CSR_READ_1(sc,EL_AS) & EL_AS_TXBUSY) && (i>0))
520                 i--;
521         if(i == 0) {
522                 dprintf(("tx not ready\n"));
523                 sc->el_ifp->if_oerrors++;
524                 return(-1);
525         }
526         dprintf(("%d cycles.\n",(20000-i)));
527         return(0);
528 }
529
530 /* Pass a packet up to the higher levels. */
531 static __inline void
532 elread(struct el_softc *sc,caddr_t buf,int len)
533 {
534         struct ifnet *ifp = sc->el_ifp;
535         struct mbuf *m;
536
537         /*
538          * Put packet into an mbuf chain
539          */
540         m = elget(buf,len,ifp);
541         if(m == 0)
542                 return;
543
544         (*ifp->if_input)(ifp,m);
545 }
546
547 /* controller interrupt */
548 static void
549 elintr(void *xsc)
550 {
551         register struct el_softc *sc;
552         int stat, rxstat, len, done;
553
554
555         /* Get things pointing properly */
556         sc = xsc;
557         EL_LOCK(sc);
558         dprintf(("elintr: "));
559
560         /* Check board status */
561         stat = CSR_READ_1(sc,EL_AS);
562         if(stat & EL_AS_RXBUSY) {
563                 (void)CSR_READ_1(sc,EL_RXC);
564                 CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
565                 EL_UNLOCK(sc);
566                 return;
567         }
568
569         done = 0;
570         while(!done) {
571                 rxstat = CSR_READ_1(sc,EL_RXS);
572                 if(rxstat & EL_RXS_STALE) {
573                         (void)CSR_READ_1(sc,EL_RXC);
574                         CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
575                         EL_UNLOCK(sc);
576                         return;
577                 }
578
579                 /* If there's an overflow, reinit the board. */
580                 if(!(rxstat & EL_RXS_NOFLOW)) {
581                         dprintf(("overflow.\n"));
582                         el_hardreset(sc);
583                         /* Put board back into receive mode */
584                         if(sc->el_ifp->if_flags & IFF_PROMISC)
585                                 CSR_WRITE_1(sc,EL_RXC,
586                                     (EL_RXC_PROMISC|EL_RXC_ABROAD|
587                                     EL_RXC_AMULTI|EL_RXC_AGF|EL_RXC_DSHORT|
588                                     EL_RXC_DDRIB|EL_RXC_DOFLOW));
589                         else
590                                 CSR_WRITE_1(sc,EL_RXC,
591                                     (EL_RXC_ABROAD|
592                                     EL_RXC_AMULTI|EL_RXC_AGF|EL_RXC_DSHORT|
593                                     EL_RXC_DDRIB|EL_RXC_DOFLOW));
594                         (void)CSR_READ_1(sc,EL_AS);
595                         CSR_WRITE_1(sc,EL_RBC,0);
596                         (void)CSR_READ_1(sc,EL_RXC);
597                         CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
598                         EL_UNLOCK(sc);
599                         return;
600                 }
601
602                 /* Incoming packet */
603                 len = CSR_READ_1(sc,EL_RBL);
604                 len |= CSR_READ_1(sc,EL_RBH) << 8;
605                 dprintf(("receive len=%d rxstat=%x ",len,rxstat));
606                 CSR_WRITE_1(sc,EL_AC,EL_AC_HOST);
607
608                 /* If packet too short or too long, restore rx mode and return
609                  */
610                 if((len <= sizeof(struct ether_header)) || (len > ETHER_MAX_LEN)) {
611                         if(sc->el_ifp->if_flags & IFF_PROMISC)
612                                 CSR_WRITE_1(sc,EL_RXC,
613                                     (EL_RXC_PROMISC|EL_RXC_ABROAD|
614                                     EL_RXC_AMULTI|EL_RXC_AGF|EL_RXC_DSHORT|
615                                     EL_RXC_DDRIB|EL_RXC_DOFLOW));
616                         else
617                                 CSR_WRITE_1(sc,EL_RXC,
618                                     (EL_RXC_ABROAD|
619                                     EL_RXC_AMULTI|EL_RXC_AGF|EL_RXC_DSHORT|
620                                     EL_RXC_DDRIB|EL_RXC_DOFLOW));
621                         (void)CSR_READ_1(sc,EL_AS);
622                         CSR_WRITE_1(sc,EL_RBC,0);
623                         (void)CSR_READ_1(sc,EL_RXC);
624                         CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
625                         EL_UNLOCK(sc);
626                         return;
627                 }
628
629                 sc->el_ifp->if_ipackets++;
630
631                 /* Copy the data into our buffer */
632                 CSR_WRITE_1(sc,EL_GPBL,0);
633                 CSR_WRITE_1(sc,EL_GPBH,0);
634                 bus_space_read_multi_1(sc->el_btag, sc->el_bhandle,
635                     EL_BUF, sc->el_pktbuf, len);
636                 CSR_WRITE_1(sc,EL_RBC,0);
637                 CSR_WRITE_1(sc,EL_AC,EL_AC_RX);
638                 dprintf(("%6D-->",sc->el_pktbuf+6,":"));
639                 dprintf(("%6D\n",sc->el_pktbuf,":"));
640
641                 /* Pass data up to upper levels */
642                 elread(sc,(caddr_t)(sc->el_pktbuf),len);
643
644                 /* Is there another packet? */
645                 stat = CSR_READ_1(sc,EL_AS);
646
647                 /* If so, do it all again (i.e. don't set done to 1) */
648                 if(!(stat & EL_AS_RXBUSY))
649                         dprintf(("<rescan> "));
650                 else
651                         done = 1;
652         }
653
654         (void)CSR_READ_1(sc,EL_RXC);
655         CSR_WRITE_1(sc,EL_AC,(EL_AC_IRQE|EL_AC_RX));
656         EL_UNLOCK(sc);
657         return;
658 }
659
660 /*
661  * Pull read data off an interface.
662  * Len is length of data, with local net header stripped.
663  */
664 static struct mbuf *
665 elget(buf, totlen, ifp)
666         caddr_t buf;
667         int totlen;
668         struct ifnet *ifp;
669 {
670         struct mbuf *top, **mp, *m;
671         int len;
672         register caddr_t cp;
673         char *epkt;
674
675         buf += sizeof(struct ether_header);
676         cp = buf;
677         epkt = cp + totlen;
678
679         MGETHDR(m, M_DONTWAIT, MT_DATA);
680         if (m == 0)
681                 return (0);
682         m->m_pkthdr.rcvif = ifp;
683         m->m_pkthdr.len = totlen;
684         m->m_len = MHLEN;
685         top = 0;
686         mp = &top;
687         while (totlen > 0) {
688                 if (top) {
689                         MGET(m, M_DONTWAIT, MT_DATA);
690                         if (m == 0) {
691                                 m_freem(top);
692                                 return (0);
693                         }
694                         m->m_len = MLEN;
695                 }
696                 len = min(totlen, epkt - cp);
697                 if (len >= MINCLSIZE) {
698                         MCLGET(m, M_DONTWAIT);
699                         if (m->m_flags & M_EXT)
700                                 m->m_len = len = min(len, MCLBYTES);
701                         else
702                                 len = m->m_len;
703                 } else {
704                         /*
705                          * Place initial small packet/header at end of mbuf.
706                          */
707                         if (len < m->m_len) {
708                                 if (top == 0 && len + max_linkhdr <= m->m_len)
709                                         m->m_data += max_linkhdr;
710                                 m->m_len = len;
711                         } else
712                                 len = m->m_len;
713                 }
714                 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
715                 cp += len;
716                 *mp = m;
717                 mp = &m->m_next;
718                 totlen -= len;
719                 if (cp == epkt)
720                         cp = buf;
721         }
722         return (top);
723 }
724
725 /*
726  * Process an ioctl request. This code needs some work - it looks
727  *      pretty ugly.
728  */
729 static int
730 el_ioctl(ifp, command, data)
731         register struct ifnet *ifp;
732         u_long command;
733         caddr_t data;
734 {
735         int error = 0;
736         struct el_softc *sc;
737
738         sc = ifp->if_softc;
739         EL_LOCK(sc);
740
741         switch (command) {
742         case SIOCSIFFLAGS:
743                 /*
744                  * If interface is marked down and it is running, then stop it
745                  */
746                 if (((ifp->if_flags & IFF_UP) == 0) &&
747                     (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
748                         el_stop(ifp->if_softc);
749                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
750                 } else {
751                 /*
752                  * If interface is marked up and it is stopped, then start it
753                  */
754                         if ((ifp->if_flags & IFF_UP) &&
755                             ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))
756                                 el_init(ifp->if_softc);
757                 }
758                 break;
759         default:
760                 error = ether_ioctl(ifp, command, data);
761                 break;
762         }
763         EL_UNLOCK(sc);
764         return (error);
765 }
766
767 /* Device timeout routine */
768 static void
769 el_watchdog(struct ifnet *ifp)
770 {
771         log(LOG_ERR,"%s: device timeout\n", ifp->if_xname);
772         ifp->if_oerrors++;
773         el_reset(ifp->if_softc);
774 }