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