The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_el.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 "el.h"
   23 #include "opt_inet.h"
   24 #include "opt_ipx.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/systm.h>
   28 #include <sys/sockio.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/socket.h>
   31 #include <sys/syslog.h>
   32 
   33 #include <net/ethernet.h>
   34 #include <net/if.h>
   35 
   36 #include <netinet/in.h>
   37 #include <netinet/if_ether.h>
   38 
   39 #include <net/bpf.h>
   40 
   41 #include <machine/clock.h>
   42 
   43 #include <i386/isa/isa_device.h>
   44 #include <i386/isa/if_elreg.h>
   45 
   46 /* For debugging convenience */
   47 #ifdef EL_DEBUG
   48 #define dprintf(x) printf x
   49 #else
   50 #define dprintf(x)
   51 #endif
   52 
   53 /* el_softc: per line info and status */
   54 static struct el_softc {
   55         struct arpcom arpcom;   /* Ethernet common */
   56         u_short el_base;        /* Base I/O addr */
   57         char el_pktbuf[EL_BUFSIZ];      /* Frame buffer */
   58 } el_softc[NEL];
   59 
   60 /* Prototypes */
   61 static int el_attach(struct isa_device *);
   62 static void el_init(void *);
   63 static int el_ioctl(struct ifnet *,u_long,caddr_t);
   64 static int el_probe(struct isa_device *);
   65 static void el_start(struct ifnet *);
   66 static void el_reset(void *);
   67 static void el_watchdog(struct ifnet *);
   68 
   69 static void el_stop(void *);
   70 static int el_xmit(struct el_softc *,int);
   71 static ointhand2_t elintr;
   72 static __inline void elread(struct el_softc *,caddr_t,int);
   73 static struct mbuf *elget(caddr_t,int,struct ifnet *);
   74 static __inline void el_hardreset(void *);
   75 
   76 /* isa_driver structure for autoconf */
   77 struct isa_driver eldriver = {
   78         el_probe, el_attach, "el"
   79 };
   80 
   81 /* Probe routine.  See if the card is there and at the right place. */
   82 static int
   83 el_probe(struct isa_device *idev)
   84 {
   85         struct el_softc *sc;
   86         u_short base; /* Just for convenience */
   87         u_char station_addr[ETHER_ADDR_LEN];
   88         int i;
   89 
   90         /* Grab some info for our structure */
   91         sc = &el_softc[idev->id_unit];
   92         sc->el_base = idev->id_iobase;
   93         base = sc->el_base;
   94 
   95         /* First check the base */
   96         if((base < 0x280) || (base > 0x3f0)) {
   97                 printf("el%d: ioaddr must be between 0x280 and 0x3f0\n",
   98                         idev->id_unit);
   99                 return(0);
  100         }
  101 
  102         /* Now attempt to grab the station address from the PROM
  103          * and see if it contains the 3com vendor code.
  104          */
  105         dprintf(("Probing 3c501 at 0x%x...\n",base));
  106 
  107         /* Reset the board */
  108         dprintf(("Resetting board...\n"));
  109         outb(base+EL_AC,EL_AC_RESET);
  110         DELAY(5);
  111         outb(base+EL_AC,0);
  112         dprintf(("Reading station address...\n"));
  113         /* Now read the address */
  114         for(i=0;i<ETHER_ADDR_LEN;i++) {
  115                 outb(base+EL_GPBL,i);
  116                 station_addr[i] = inb(base+EL_EAW);
  117         }
  118         dprintf(("Address is %6D\n",station_addr, ":"));
  119 
  120         /* If the vendor code is ok, return a 1.  We'll assume that
  121          * whoever configured this system is right about the IRQ.
  122          */
  123         if((station_addr[0] != 0x02) || (station_addr[1] != 0x60)
  124            || (station_addr[2] != 0x8c)) {
  125                 dprintf(("Bad vendor code.\n"));
  126                 return(0);
  127         } else {
  128                 dprintf(("Vendor code ok.\n"));
  129                 /* Copy the station address into the arpcom structure */
  130                 bcopy(station_addr,sc->arpcom.ac_enaddr,ETHER_ADDR_LEN);
  131                 return(1);
  132         }
  133 }
  134 
  135 /* Do a hardware reset of the 3c501.  Do not call until after el_probe()! */
  136 static __inline void
  137 el_hardreset(xsc)
  138         void *xsc;
  139 {
  140         register struct el_softc *sc = xsc;
  141         register int base;
  142         register int j;
  143 
  144         base = sc->el_base;
  145 
  146         /* First reset the board */
  147         outb(base+EL_AC,EL_AC_RESET);
  148         DELAY(5);
  149         outb(base+EL_AC,0);
  150 
  151         /* Then give it back its ethernet address.  Thanks to the mach
  152          * source code for this undocumented goodie...
  153          */
  154         for(j=0;j<ETHER_ADDR_LEN;j++)
  155                 outb(base+j,sc->arpcom.ac_enaddr[j]);
  156 }
  157 
  158 /* Attach the interface to the kernel data structures.  By the time
  159  * this is called, we know that the card exists at the given I/O address.
  160  * We still assume that the IRQ given is correct.
  161  */
  162 static int
  163 el_attach(struct isa_device *idev)
  164 {
  165         struct el_softc *sc;
  166         struct ifnet *ifp;
  167         u_short base;
  168 
  169         dprintf(("Attaching el%d...\n",idev->id_unit));
  170 
  171         /* Get things pointing to the right places. */
  172         idev->id_ointr = elintr;
  173         sc = &el_softc[idev->id_unit];
  174         ifp = &sc->arpcom.ac_if;
  175         base = sc->el_base;
  176 
  177         /* Now reset the board */
  178         dprintf(("Resetting board...\n"));
  179         el_hardreset(sc);
  180 
  181         /* Initialize ifnet structure */
  182         ifp->if_softc = sc;
  183         ifp->if_unit = idev->id_unit;
  184         ifp->if_name = "el";
  185         ifp->if_mtu = ETHERMTU;
  186         ifp->if_output = ether_output;
  187         ifp->if_start = el_start;
  188         ifp->if_ioctl = el_ioctl;
  189         ifp->if_watchdog = el_watchdog;
  190         ifp->if_init = el_init;
  191         ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX);
  192 
  193         /* Now we can attach the interface */
  194         dprintf(("Attaching interface...\n"));
  195         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
  196 
  197         /* Print out some information for the user */
  198         printf("el%d: 3c501 address %6D\n",idev->id_unit,
  199           sc->arpcom.ac_enaddr, ":");
  200 
  201         dprintf(("el_attach() finished.\n"));
  202         return(1);
  203 }
  204 
  205 /* This routine resets the interface. */
  206 static void 
  207 el_reset(xsc)
  208         void *xsc;
  209 {
  210         struct el_softc *sc = xsc;
  211         int s;
  212 
  213         dprintf(("elreset()\n"));
  214         s = splimp();
  215         el_stop(sc);
  216         el_init(sc);
  217         splx(s);
  218 }
  219 
  220 static void el_stop(xsc)
  221         void *xsc;
  222 {
  223         struct el_softc *sc = xsc;
  224 
  225         outb(sc->el_base+EL_AC,0);
  226 }
  227 
  228 /* Initialize interface.  */
  229 static void 
  230 el_init(xsc)
  231         void *xsc;
  232 {
  233         struct el_softc *sc = xsc;
  234         struct ifnet *ifp;
  235         int s;
  236         u_short base;
  237 
  238         /* Set up pointers */
  239         ifp = &sc->arpcom.ac_if;
  240         base = sc->el_base;
  241 
  242         /* If address not known, do nothing. */
  243         if(TAILQ_EMPTY(&ifp->if_addrhead)) /* XXX unlikely */
  244                 return;
  245 
  246         s = splimp();
  247 
  248         /* First, reset the board. */
  249         dprintf(("Resetting board...\n"));
  250         el_hardreset(sc);
  251 
  252         /* Configure rx */
  253         dprintf(("Configuring rx...\n"));
  254         if(ifp->if_flags & IFF_PROMISC)
  255                 outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  256         else
  257                 outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  258         outb(base+EL_RBC,0);
  259 
  260         /* Configure TX */
  261         dprintf(("Configuring tx...\n"));
  262         outb(base+EL_TXC,0);
  263 
  264         /* Start reception */
  265         dprintf(("Starting reception...\n"));
  266         outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  267 
  268         /* Set flags appropriately */
  269         ifp->if_flags |= IFF_RUNNING;
  270         ifp->if_flags &= ~IFF_OACTIVE;
  271 
  272         /* And start output. */
  273         el_start(ifp);
  274 
  275         splx(s);
  276 }
  277 
  278 /* Start output on interface.  Get datagrams from the queue and output
  279  * them, giving the receiver a chance between datagrams.  Call only
  280  * from splimp or interrupt level!
  281  */
  282 static void
  283 el_start(struct ifnet *ifp)
  284 {
  285         struct el_softc *sc;
  286         u_short base;
  287         struct mbuf *m, *m0;
  288         int s, i, len, retries, done;
  289 
  290         /* Get things pointing in the right directions */
  291         sc = ifp->if_softc;
  292         base = sc->el_base;
  293 
  294         dprintf(("el_start()...\n"));
  295         s = splimp();
  296 
  297         /* Don't do anything if output is active */
  298         if(sc->arpcom.ac_if.if_flags & IFF_OACTIVE)
  299                 return;
  300         sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
  301 
  302         /* The main loop.  They warned me against endless loops, but
  303          * would I listen?  NOOO....
  304          */
  305         while(1) {
  306                 /* Dequeue the next datagram */
  307                 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd,m0);
  308 
  309                 /* If there's nothing to send, return. */
  310                 if(m0 == NULL) {
  311                         sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  312                         splx(s);
  313                         return;
  314                 }
  315 
  316                 /* Disable the receiver */
  317                 outb(base+EL_AC,EL_AC_HOST);
  318                 outb(base+EL_RBC,0);
  319 
  320                 /* Copy the datagram to the buffer. */
  321                 len = 0;
  322                 for(m = m0; m != NULL; m = m->m_next) {
  323                         if(m->m_len == 0)
  324                                 continue;
  325                         bcopy(mtod(m,caddr_t),sc->el_pktbuf+len,m->m_len);
  326                         len += m->m_len;
  327                 }
  328                 m_freem(m0);
  329 
  330                 len = max(len,ETHER_MIN_LEN);
  331 
  332                 /* Give the packet to the bpf, if any */
  333                 if(sc->arpcom.ac_if.if_bpf)
  334                         bpf_tap(&sc->arpcom.ac_if, sc->el_pktbuf, len);
  335 
  336                 /* Transfer datagram to board */
  337                 dprintf(("el: xfr pkt length=%d...\n",len));
  338                 i = EL_BUFSIZ - len;
  339                 outb(base+EL_GPBL,(i & 0xff));
  340                 outb(base+EL_GPBH,((i>>8)&0xff));
  341                 outsb(base+EL_BUF,sc->el_pktbuf,len);
  342 
  343                 /* Now transmit the datagram */
  344                 retries=0;
  345                 done=0;
  346                 while(!done) {
  347                         if(el_xmit(sc,len)) { /* Something went wrong */
  348                                 done = -1;
  349                                 break;
  350                         }
  351                         /* Check out status */
  352                         i = inb(base+EL_TXS);
  353                         dprintf(("tx status=0x%x\n",i));
  354                         if(!(i & EL_TXS_READY)) {
  355                                 dprintf(("el: err txs=%x\n",i));
  356                                 sc->arpcom.ac_if.if_oerrors++;
  357                                 if(i & (EL_TXS_COLL|EL_TXS_COLL16)) {
  358                                         if((!(i & EL_TXC_DCOLL16)) && retries < 15) {
  359                                                 retries++;
  360                                                 outb(base+EL_AC,EL_AC_HOST);
  361                                         }
  362                                 }
  363                                 else
  364                                         done = 1;
  365                         }
  366                         else {
  367                                 sc->arpcom.ac_if.if_opackets++;
  368                                 done = 1;
  369                         }
  370                 }
  371                 if(done == -1)  /* Packet not transmitted */
  372                         continue;
  373 
  374                 /* Now give the card a chance to receive.
  375                  * Gotta love 3c501s...
  376                  */
  377                 (void)inb(base+EL_AS);
  378                 outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  379                 splx(s);
  380                 /* Interrupt here */
  381                 s = splimp();
  382         }
  383 }
  384 
  385 /* This function actually attempts to transmit a datagram downloaded
  386  * to the board.  Call at splimp or interrupt, after downloading data!
  387  * Returns 0 on success, non-0 on failure
  388  */
  389 static int
  390 el_xmit(struct el_softc *sc,int len)
  391 {
  392         int gpl;
  393         int i;
  394 
  395         gpl = EL_BUFSIZ - len;
  396         dprintf(("el: xmit..."));
  397         outb((sc->el_base)+EL_GPBL,(gpl & 0xff));
  398         outb((sc->el_base)+EL_GPBH,((gpl>>8)&0xff));
  399         outb((sc->el_base)+EL_AC,EL_AC_TXFRX);
  400         i = 20000;
  401         while((inb((sc->el_base)+EL_AS) & EL_AS_TXBUSY) && (i>0))
  402                 i--;
  403         if(i == 0) {
  404                 dprintf(("tx not ready\n"));
  405                 sc->arpcom.ac_if.if_oerrors++;
  406                 return(-1);
  407         }
  408         dprintf(("%d cycles.\n",(20000-i)));
  409         return(0);
  410 }
  411 
  412 /* Pass a packet up to the higher levels. */
  413 static __inline void
  414 elread(struct el_softc *sc,caddr_t buf,int len)
  415 {
  416         register struct ether_header *eh;
  417         struct mbuf *m;
  418 
  419         eh = (struct ether_header *)buf;
  420 
  421         /*
  422          * Put packet into an mbuf chain
  423          */
  424         m = elget(buf,len,&sc->arpcom.ac_if);
  425         if(m == 0)
  426                 return;
  427 
  428         ether_input(&sc->arpcom.ac_if,eh,m);
  429 }
  430 
  431 /* controller interrupt */
  432 static void
  433 elintr(int unit)
  434 {
  435         register struct el_softc *sc;
  436         register int base;
  437         int stat, rxstat, len, done;
  438 
  439         /* Get things pointing properly */
  440         sc = &el_softc[unit];
  441         base = sc->el_base;
  442 
  443         dprintf(("elintr: "));
  444 
  445         /* Check board status */
  446         stat = inb(base+EL_AS);
  447         if(stat & EL_AS_RXBUSY) {
  448                 (void)inb(base+EL_RXC);
  449                 outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  450                 return;
  451         }
  452 
  453         done = 0;
  454         while(!done) {
  455                 rxstat = inb(base+EL_RXS);
  456                 if(rxstat & EL_RXS_STALE) {
  457                         (void)inb(base+EL_RXC);
  458                         outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  459                         return;
  460                 }
  461 
  462                 /* If there's an overflow, reinit the board. */
  463                 if(!(rxstat & EL_RXS_NOFLOW)) {
  464                         dprintf(("overflow.\n"));
  465                         el_hardreset(sc);
  466                         /* Put board back into receive mode */
  467                         if(sc->arpcom.ac_if.if_flags & IFF_PROMISC)
  468                                 outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  469                         else
  470                                 outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  471                         (void)inb(base+EL_AS);
  472                         outb(base+EL_RBC,0);
  473                         (void)inb(base+EL_RXC);
  474                         outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  475                         return;
  476                 }
  477 
  478                 /* Incoming packet */
  479                 len = inb(base+EL_RBL);
  480                 len |= inb(base+EL_RBH) << 8;
  481                 dprintf(("receive len=%d rxstat=%x ",len,rxstat));
  482                 outb(base+EL_AC,EL_AC_HOST);
  483 
  484                 /* If packet too short or too long, restore rx mode and return
  485                  */
  486                 if((len <= sizeof(struct ether_header)) || (len > ETHER_MAX_LEN)) {
  487                         if(sc->arpcom.ac_if.if_flags & IFF_PROMISC)
  488                                 outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  489                         else
  490                                 outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
  491                         (void)inb(base+EL_AS);
  492                         outb(base+EL_RBC,0);
  493                         (void)inb(base+EL_RXC);
  494                         outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  495                         return;
  496                 }
  497 
  498                 sc->arpcom.ac_if.if_ipackets++;
  499 
  500                 /* Copy the data into our buffer */
  501                 outb(base+EL_GPBL,0);
  502                 outb(base+EL_GPBH,0);
  503                 insb(base+EL_BUF,sc->el_pktbuf,len);
  504                 outb(base+EL_RBC,0);
  505                 outb(base+EL_AC,EL_AC_RX);
  506                 dprintf(("%6D-->",sc->el_pktbuf+6,":"));
  507                 dprintf(("%6D\n",sc->el_pktbuf,":"));
  508 
  509                 /* Pass data up to upper levels */
  510                 len -= sizeof(struct ether_header);
  511                 elread(sc,(caddr_t)(sc->el_pktbuf),len);
  512 
  513                 /* Is there another packet? */
  514                 stat = inb(base+EL_AS);
  515 
  516                 /* If so, do it all again (i.e. don't set done to 1) */
  517                 if(!(stat & EL_AS_RXBUSY))
  518                         dprintf(("<rescan> "));
  519                 else
  520                         done = 1;
  521         }
  522 
  523         (void)inb(base+EL_RXC);
  524         outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
  525         return;
  526 }
  527 
  528 /*
  529  * Pull read data off a interface.
  530  * Len is length of data, with local net header stripped.
  531  */
  532 static struct mbuf *
  533 elget(buf, totlen, ifp)
  534         caddr_t buf;
  535         int totlen;
  536         struct ifnet *ifp;
  537 {
  538         struct mbuf *top, **mp, *m;
  539         int len;
  540         register caddr_t cp;
  541         char *epkt;
  542 
  543         buf += sizeof(struct ether_header);
  544         cp = buf;
  545         epkt = cp + totlen;
  546 
  547         MGETHDR(m, M_DONTWAIT, MT_DATA);
  548         if (m == 0)
  549                 return (0);
  550         m->m_pkthdr.rcvif = ifp;
  551         m->m_pkthdr.len = totlen;
  552         m->m_len = MHLEN;
  553         top = 0;
  554         mp = &top;
  555         while (totlen > 0) {
  556                 if (top) {
  557                         MGET(m, M_DONTWAIT, MT_DATA);
  558                         if (m == 0) {
  559                                 m_freem(top);
  560                                 return (0);
  561                         }
  562                         m->m_len = MLEN;
  563                 }
  564                 len = min(totlen, epkt - cp);
  565                 if (len >= MINCLSIZE) {
  566                         MCLGET(m, M_DONTWAIT);
  567                         if (m->m_flags & M_EXT)
  568                                 m->m_len = len = min(len, MCLBYTES);
  569                         else
  570                                 len = m->m_len;
  571                 } else {
  572                         /*
  573                          * Place initial small packet/header at end of mbuf.
  574                          */
  575                         if (len < m->m_len) {
  576                                 if (top == 0 && len + max_linkhdr <= m->m_len)
  577                                         m->m_data += max_linkhdr;
  578                                 m->m_len = len;
  579                         } else
  580                                 len = m->m_len;
  581                 }
  582                 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
  583                 cp += len;
  584                 *mp = m;
  585                 mp = &m->m_next;
  586                 totlen -= len;
  587                 if (cp == epkt)
  588                         cp = buf;
  589         }
  590         return (top);
  591 }
  592 
  593 /*
  594  * Process an ioctl request. This code needs some work - it looks
  595  *      pretty ugly.
  596  */
  597 static int
  598 el_ioctl(ifp, command, data)
  599         register struct ifnet *ifp;
  600         u_long command;
  601         caddr_t data;
  602 {
  603         int s, error = 0;
  604 
  605         s = splimp();
  606 
  607         switch (command) {
  608         case SIOCSIFADDR:
  609         case SIOCGIFADDR:
  610         case SIOCSIFMTU:
  611                 error = ether_ioctl(ifp, command, data);
  612                 break;
  613 
  614         case SIOCSIFFLAGS:
  615                 /*
  616                  * If interface is marked down and it is running, then stop it
  617                  */
  618                 if (((ifp->if_flags & IFF_UP) == 0) &&
  619                     (ifp->if_flags & IFF_RUNNING)) {
  620                         el_stop(ifp->if_softc);
  621                         ifp->if_flags &= ~IFF_RUNNING;
  622                 } else {
  623                 /*
  624                  * If interface is marked up and it is stopped, then start it
  625                  */
  626                         if ((ifp->if_flags & IFF_UP) &&
  627                             ((ifp->if_flags & IFF_RUNNING) == 0))
  628                                 el_init(ifp->if_softc);
  629                 }
  630                 break;
  631         default:
  632                 error = EINVAL;
  633         }
  634         (void) splx(s);
  635         return (error);
  636 }
  637 
  638 /* Device timeout routine */
  639 static void
  640 el_watchdog(struct ifnet *ifp)
  641 {
  642         log(LOG_ERR,"el%d: device timeout\n", ifp->if_unit);
  643         ifp->if_oerrors++;
  644         el_reset(ifp->if_softc);
  645 }

Cache object: 226d68d06508dbdbe6b1184f31f6f7b2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.