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_eg.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 /*
    2  * Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Dean Huxley.
   16  * 4. The name of Dean Huxley may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  *
   30  * $FreeBSD: src/sys/i386/isa/if_eg.c,v 1.19.2.1 1999/09/05 08:12:46 peter Exp $
   31  *
   32  * Support for 3Com 3c505 Etherlink+ card.
   33  */
   34 
   35 /* To do:
   36  * - multicast
   37  * - promiscuous
   38  */
   39 #include "eg.h"
   40 #include "bpfilter.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/conf.h>
   45 #include <sys/errno.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/socket.h>
   49 #include <sys/syslog.h>
   50 
   51 #include <net/if.h>
   52 #include <net/if_dl.h>
   53 #include <net/if_types.h>
   54 
   55 #ifdef INET
   56 #include <netinet/in.h>
   57 #include <netinet/in_systm.h>
   58 #include <netinet/in_var.h>
   59 #include <netinet/ip.h>
   60 #include <netinet/if_ether.h>
   61 #endif
   62 
   63 #ifdef IPX
   64 #include <netipx/ipx.h>
   65 #include <netipx/ipx_if.h>
   66 #endif
   67 
   68 #ifdef NS
   69 #include <netns/ns.h>
   70 #include <netns/ns_if.h>
   71 #endif
   72 
   73 #if NBPFILTER > 0
   74 #include <net/bpf.h>
   75 #include <net/bpfdesc.h>
   76 #endif
   77 
   78 #include <machine/clock.h>
   79 
   80 #include <i386/isa/isa_device.h>
   81 #include <i386/isa/if_egreg.h>
   82 
   83 /* for debugging convenience */
   84 #ifdef EGDEBUG
   85 #define dprintf(x) printf x
   86 #else
   87 #define dprintf(x)
   88 #endif
   89 
   90 #define EG_INLEN        10
   91 #define EG_BUFLEN       0x0670
   92 
   93 /*
   94  * Ethernet software status per interface.
   95  */
   96 static struct eg_softc {
   97         struct arpcom sc_arpcom;        /* Ethernet common part */
   98         int eg_cmd;                     /* Command register R/W */
   99         int eg_ctl;                     /* Control register R/W (EG_CTL_*) */
  100         int eg_stat;                    /* Status register R/O (EG_STAT_*) */
  101         int eg_data;                    /* Data register R/W (16 bits) */
  102         u_char  eg_rom_major;           /* Cards ROM version (major number) */
  103         u_char  eg_rom_minor;           /* Cards ROM version (minor number) */
  104         short   eg_ram;                 /* Amount of RAM on the card */
  105         u_char  eg_pcb[64];             /* Primary Command Block buffer */
  106         u_char  eg_incount;             /* Number of buffers currently used */
  107         u_char  *eg_inbuf;              /* Incoming packet buffer */
  108         u_char  *eg_outbuf;             /* Outgoing packet buffer */
  109 } eg_softc[NEG];
  110 
  111 static int egprobe (struct isa_device *);
  112 static int egattach (struct isa_device *);
  113 
  114 struct isa_driver egdriver = {
  115         egprobe, egattach, "eg", 0
  116 };
  117 
  118 static void egprintpcb __P((struct eg_softc *sc));
  119 static void egprintstat __P((int b));
  120 static int egoutPCB __P((struct eg_softc *sc, int b));
  121 static int egreadPCBstat __P((struct eg_softc *sc, int statb));
  122 static int egreadPCBready __P((struct eg_softc *sc));
  123 static int egwritePCB __P((struct eg_softc *sc));
  124 static int egreadPCB __P((struct eg_softc *sc));
  125 static void eginit __P((struct eg_softc *sc));
  126 static int egioctl (struct ifnet *, int, caddr_t);
  127 static void egrecv(struct eg_softc *);
  128 static void egstart(struct ifnet *);
  129 static void egread __P((struct eg_softc *, caddr_t, int));
  130 static void egstop __P((struct eg_softc *));
  131 
  132 static void egwatchdog __P((struct ifnet *));
  133 static void egreset __P((struct eg_softc *));
  134 static struct mbuf *egget __P((struct eg_softc *, caddr_t, int));
  135 
  136 /*
  137  * Support stuff
  138  */
  139         
  140 static void
  141 egprintpcb(sc)
  142         struct eg_softc *sc;
  143 {
  144         int i;
  145         
  146         for (i = 0; i < sc->eg_pcb[1] + 2; i++)
  147                 dprintf(("eg#: pcb[%2d] = %x\n", i, sc->eg_pcb[i]));
  148 }
  149 
  150 
  151 static void
  152 egprintstat(b)
  153         u_char b;
  154 {
  155         dprintf(("eg#: %s %s %s %s %s %s %s\n", 
  156                  (b & EG_STAT_HCRE)?"HCRE":"",
  157                  (b & EG_STAT_ACRF)?"ACRF":"",
  158                  (b & EG_STAT_DIR )?"DIR ":"",
  159                  (b & EG_STAT_DONE)?"DONE":"",
  160                  (b & EG_STAT_ASF3)?"ASF3":"",
  161                  (b & EG_STAT_ASF2)?"ASF2":"",
  162                  (b & EG_STAT_ASF1)?"ASF1":""));
  163 }
  164 
  165 static int
  166 egoutPCB(sc, b)
  167         struct eg_softc *sc;
  168         u_char b;
  169 {
  170         int i;
  171 
  172         for (i=0; i < 4000; i++) {
  173                 if (inb(sc->eg_stat) & EG_STAT_HCRE) {
  174                         outb(sc->eg_cmd, b);
  175                         return 0;
  176                 }
  177                 DELAY(10);
  178         }
  179         dprintf(("eg#: egoutPCB failed\n"));
  180         return 1;
  181 }
  182         
  183 static int
  184 egreadPCBstat(sc, statb)
  185         struct eg_softc *sc;
  186         u_char statb;
  187 {
  188         int i;
  189 
  190         for (i=0; i < 5000; i++) {
  191                 if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) 
  192                         break;
  193                 DELAY(10);
  194         }
  195         if ((inb(sc->eg_stat) & EG_PCB_STAT) == statb) 
  196                 return 0;
  197         return 1;
  198 }
  199 
  200 static int
  201 egreadPCBready(sc)
  202         struct eg_softc *sc;
  203 {
  204         int i;
  205 
  206         for (i=0; i < 10000; i++) {
  207                 if (inb(sc->eg_stat) & EG_STAT_ACRF)
  208                         return 0;
  209                 DELAY(5);
  210         }
  211         dprintf(("eg#: PCB read not ready\n"));
  212         return 1;
  213 }
  214         
  215 static int
  216 egwritePCB(sc)
  217         struct eg_softc *sc;
  218 {
  219         int i;
  220         u_char len;
  221 
  222         outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL);
  223 
  224         len = sc->eg_pcb[1] + 2;
  225         for (i = 0; i < len; i++)
  226                 egoutPCB(sc, sc->eg_pcb[i]);
  227         
  228         for (i=0; i < 4000; i++) {
  229                 if (inb(sc->eg_stat) & EG_STAT_HCRE)
  230                         break;
  231                 DELAY(10);
  232         }
  233 
  234         outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_DONE);
  235 
  236         egoutPCB(sc, len);
  237 
  238         if (egreadPCBstat(sc, EG_PCB_ACCEPT))
  239                 return 1;
  240         return 0;
  241 }       
  242         
  243 static int
  244 egreadPCB(sc)
  245         struct eg_softc *sc;
  246 {
  247         int i;
  248         u_char b;
  249         
  250         outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL);
  251 
  252         bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
  253 
  254         if (egreadPCBready(sc))
  255                 return 1;
  256 
  257         sc->eg_pcb[0] = inb(sc->eg_cmd);
  258         
  259         if (egreadPCBready(sc))
  260                 return 1;
  261 
  262         sc->eg_pcb[1] = inb(sc->eg_cmd);
  263 
  264         if (sc->eg_pcb[1] > 62) {
  265                 dprintf(("eg#: len %d too large\n", sc->eg_pcb[1]));
  266                 return 1;
  267         }
  268         
  269         for (i = 0; i < sc->eg_pcb[1]; i++) {
  270                 if (egreadPCBready(sc))
  271                         return 1;
  272                 sc->eg_pcb[2+i] = inb(sc->eg_cmd);
  273         }
  274         if (egreadPCBready(sc))
  275                 return 1;
  276         if (egreadPCBstat(sc, EG_PCB_DONE))
  277                 return 1;
  278         if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1] + 2) {
  279                 dprintf(("eg#: %d != %d\n", b, sc->eg_pcb[1] + 2));
  280                 return 1;
  281         }
  282 
  283         outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_ACCEPT);
  284 
  285         return 0;
  286 }       
  287 
  288 /*
  289  * Real stuff
  290  */
  291 
  292 static int
  293 egprobe(struct isa_device * id)
  294 {
  295         struct eg_softc *sc = &eg_softc[id->id_unit];
  296         int i;
  297 
  298         if (id->id_iobase & ~0x07f0 != 0) {
  299                 dprintf(("eg#: Weird iobase %x\n", ia->ia_iobase));
  300                 return 0;
  301         }
  302         
  303         sc->eg_cmd = id->id_iobase + EG_COMMAND;
  304         sc->eg_ctl = id->id_iobase + EG_CONTROL;
  305         sc->eg_stat = id->id_iobase + EG_STATUS;
  306         sc->eg_data = id->id_iobase + EG_DATA;
  307 
  308         /* hard reset card */
  309         outb(sc->eg_ctl, EG_CTL_RESET); 
  310         outb(sc->eg_ctl, 0);
  311         for (i = 0; i < 1600; i++) {
  312                 DELAY(10000);
  313                 if ((inb(sc->eg_stat) & EG_PCB_STAT) == EG_PCB_NULL) 
  314                         break;
  315         }
  316         if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) {
  317                 dprintf(("eg#: eg: Reset failed\n"));
  318                 return 0;
  319         }
  320         sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
  321         sc->eg_pcb[1] = 0;
  322         if (egwritePCB(sc) != 0)
  323                 return 0;
  324         
  325         if (egreadPCB(sc) != 0) {
  326                 egprintpcb(sc);
  327                 return 0;
  328         }
  329 
  330         if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
  331             sc->eg_pcb[1] != 0x0a) {
  332                 egprintpcb(sc);
  333                 return 0;
  334         }
  335         sc->eg_rom_major = sc->eg_pcb[3];
  336         sc->eg_rom_minor = sc->eg_pcb[2];
  337         sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
  338         
  339         return 8;
  340 }
  341 
  342 static int 
  343 egattach(struct isa_device *id)
  344 {
  345         struct eg_softc *sc = &eg_softc[id->id_unit];
  346         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  347         
  348         egstop(sc);
  349 
  350         sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
  351         sc->eg_pcb[1] = 0;
  352         if (egwritePCB(sc) != 0) {
  353                 dprintf(("eg#: write error\n"));
  354                 return 0;
  355         }       
  356         if (egreadPCB(sc) != 0) {
  357                 dprintf(("eg#: read error\n"));
  358                 egprintpcb(sc);
  359                 return 0;
  360         }
  361 
  362         /* check Get station address response */
  363         if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) { 
  364                 dprintf(("eg#: parse error\n"));
  365                 egprintpcb(sc);
  366                 return 0;
  367         }
  368         bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
  369 
  370         printf("eg%d: address %6D, type=3COM 3c505 (v%d.%02d, %dk)\n",
  371             id->id_unit, sc->sc_arpcom.ac_enaddr, ":",
  372             sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram);
  373 
  374         sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
  375         if (egwritePCB(sc) != 0) {
  376                 dprintf(("eg#: write error2\n"));
  377                 return 0;
  378         }
  379         if (egreadPCB(sc) != 0) {
  380                 dprintf(("eg#: read error2\n"));
  381                 egprintpcb(sc);
  382                 return 0;
  383         }
  384         if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
  385             sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
  386                 dprintf(("eg#: parse error2\n"));
  387                 egprintpcb(sc);
  388                 return 0;
  389         }
  390 
  391         /* Initialize ifnet structure. */
  392         ifp->if_softc = sc;
  393         ifp->if_unit = id->id_unit;
  394         ifp->if_name = "eg";
  395         ifp->if_output = ether_output;
  396         ifp->if_start = egstart;
  397         ifp->if_ioctl = egioctl;
  398         ifp->if_init = (if_init_f_t*)eginit;
  399         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  400         ifp->if_watchdog = egwatchdog;
  401         
  402         /* Now we can attach the interface. */
  403         if_attach(ifp);
  404         ether_ifattach(ifp);
  405 
  406 #if NBPFILTER > 0
  407         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
  408 #endif
  409 
  410         return 1;
  411 }
  412 
  413 static void
  414 eginit(struct eg_softc *sc)
  415 {
  416         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  417 
  418         /* soft reset the board */
  419         outb(sc->eg_ctl, EG_CTL_FLSH);
  420         DELAY(100);
  421         outb(sc->eg_ctl, EG_CTL_ATTN);
  422         DELAY(100);
  423         outb(sc->eg_ctl, 0);
  424         DELAY(200);
  425 
  426         sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
  427         sc->eg_pcb[1] = 2;
  428         sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
  429         sc->eg_pcb[3] = 0;
  430 #ifdef EGDEBUG
  431         if (egwritePCB(sc) != 0)
  432                 dprintf(("eg#: write error3\n"));
  433 #endif
  434 
  435         if (egreadPCB(sc) != 0) {
  436                 dprintf(("eg#: read error\n"));
  437                 egprintpcb(sc);
  438         } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
  439                 printf("eg%d: configure card command failed\n", ifp->if_unit);
  440 
  441         if (sc->eg_inbuf == NULL)
  442                 sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
  443         sc->eg_incount = 0;
  444 
  445         if (sc->eg_outbuf == NULL)
  446                 sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
  447 
  448         outb(sc->eg_ctl, EG_CTL_CMDE);
  449 
  450         sc->eg_incount = 0;
  451         egrecv(sc);
  452 
  453         /* Interface is now `running', with no output active. */
  454         ifp->if_flags |= IFF_RUNNING;
  455         ifp->if_flags &= ~IFF_OACTIVE;
  456 
  457         /* Attempt to start output, if any. */
  458         egstart(ifp);
  459 }
  460 
  461 static void
  462 egrecv(sc)
  463         struct eg_softc *sc;
  464 {
  465 
  466         while (sc->eg_incount < EG_INLEN) {
  467                 sc->eg_pcb[0] = EG_CMD_RECVPACKET;
  468                 sc->eg_pcb[1] = 0x08;
  469                 sc->eg_pcb[2] = 0; /* address not used.. we send zero */
  470                 sc->eg_pcb[3] = 0;
  471                 sc->eg_pcb[4] = 0;
  472                 sc->eg_pcb[5] = 0;
  473                 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
  474                 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
  475                 sc->eg_pcb[8] = 0; /* timeout, 0 == none */
  476                 sc->eg_pcb[9] = 0;
  477                 if (egwritePCB(sc) != 0)
  478                         break;
  479                 sc->eg_incount++;
  480         }
  481 }
  482 
  483 static void
  484 egstart(ifp)
  485         struct ifnet *ifp;
  486 {
  487         register struct eg_softc *sc = ifp->if_softc;
  488         struct mbuf *m0, *m;
  489         caddr_t buffer;
  490         int len;
  491         u_short *ptr;
  492 
  493         /* Don't transmit if interface is busy or not running */
  494         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  495                 return;
  496 
  497 loop:
  498         /* Dequeue the next datagram. */
  499         IF_DEQUEUE(&ifp->if_snd, m0);
  500         if (m0 == 0)
  501                 return;
  502         
  503         ifp->if_flags |= IFF_OACTIVE;
  504 
  505         /* We need to use m->m_pkthdr.len, so require the header */
  506         if ((m0->m_flags & M_PKTHDR) == 0)
  507                 panic("egstart: no header mbuf");
  508         len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
  509 
  510 #if NBPFILTER > 0
  511         if (ifp->if_bpf)
  512                 bpf_mtap(ifp, m0);
  513 #endif
  514 
  515         sc->eg_pcb[0] = EG_CMD_SENDPACKET;
  516         sc->eg_pcb[1] = 0x06;
  517         sc->eg_pcb[2] = 0; /* address not used, we send zero */
  518         sc->eg_pcb[3] = 0;
  519         sc->eg_pcb[4] = 0;
  520         sc->eg_pcb[5] = 0;
  521         sc->eg_pcb[6] = len; /* length of packet */
  522         sc->eg_pcb[7] = len >> 8;
  523         if (egwritePCB(sc) != 0) {
  524                 dprintf(("eg#: egwritePCB in egstart failed\n"));
  525                 ifp->if_oerrors++;
  526                 ifp->if_flags &= ~IFF_OACTIVE;
  527                 goto loop;
  528         }
  529 
  530         buffer = sc->eg_outbuf;
  531         for (m = m0; m != 0; m = m->m_next) {
  532                 bcopy(mtod(m, caddr_t), buffer, m->m_len);
  533                 buffer += m->m_len;
  534         }
  535 
  536         /* set direction bit: host -> adapter */
  537         outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR); 
  538         
  539         for (ptr = (u_short *) sc->eg_outbuf; len > 0; len -= 2) {
  540                 outw(sc->eg_data, *ptr++);
  541                 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
  542                         ; /* XXX need timeout here */
  543         }
  544         
  545         m_freem(m0);
  546 }
  547 
  548 void
  549 egintr(int unit)
  550 {
  551         register struct eg_softc *sc = &eg_softc[unit];
  552         int i, len;
  553         u_short *ptr;
  554 
  555         while (inb(sc->eg_stat) & EG_STAT_ACRF) {
  556                 egreadPCB(sc);
  557                 switch (sc->eg_pcb[0]) {
  558                 case EG_RSP_RECVPACKET:
  559                         len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
  560         
  561                         /* Set direction bit : Adapter -> host */
  562                         outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR); 
  563 
  564                         for (ptr = (u_short *) sc->eg_inbuf; len > 0; len -= 2) {
  565                                 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
  566                                         ;
  567                                 *ptr++ = inw(sc->eg_data);
  568                         }
  569 
  570                         len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);
  571                         egread(sc, sc->eg_inbuf, len);
  572 
  573                         sc->eg_incount--;
  574                         egrecv(sc);
  575                         break;
  576 
  577                 case EG_RSP_SENDPACKET:
  578                         if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
  579                                 dprintf(("eg#: packet dropped\n"));
  580                                 sc->sc_arpcom.ac_if.if_oerrors++;
  581                         } else
  582                                 sc->sc_arpcom.ac_if.if_opackets++;
  583                         sc->sc_arpcom.ac_if.if_collisions += sc->eg_pcb[8] & 0xf;
  584                         sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  585                         egstart(&sc->sc_arpcom.ac_if);
  586                         break;
  587 
  588                 case EG_RSP_GETSTATS:
  589                         dprintf(("eg#: Card Statistics\n"));
  590                         bcopy(&sc->eg_pcb[2], &i, sizeof(i));
  591                         dprintf(("eg#: Receive Packets %d\n", i));
  592                         bcopy(&sc->eg_pcb[6], &i, sizeof(i));
  593                         dprintf(("eg#: Transmit Packets %d\n", i));
  594                         dprintf(("eg#: CRC errors %d\n", *(short*) &sc->eg_pcb[10]));
  595                         dprintf(("eg#: alignment errors %d\n", *(short*) &sc->eg_pcb[12]));
  596                         dprintf(("eg#: no resources errors %d\n", *(short*) &sc->eg_pcb[14]));
  597                         dprintf(("eg#: overrun errors %d\n", *(short*) &sc->eg_pcb[16]));
  598                         break;
  599                         
  600                 default:
  601                         dprintf(("eg#: egintr: Unknown response %x??\n",
  602                             sc->eg_pcb[0]));
  603                         egprintpcb(sc);
  604                         break;
  605                 }
  606         }
  607 
  608         return;
  609 }
  610 
  611 /*
  612  * Pass a packet up to the higher levels.
  613  */
  614 static void
  615 egread(sc, buf, len)
  616         struct eg_softc *sc;
  617         caddr_t buf;
  618         int len;
  619 {
  620         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  621         struct mbuf *m;
  622         struct ether_header *eh;
  623         
  624         if (len <= sizeof(struct ether_header) ||
  625             len > ETHER_MAX_LEN) {
  626                 printf("eg#: invalid packet size %d; dropping\n", len);
  627                 ifp->if_ierrors++;
  628                 return;
  629         }
  630 
  631         /* Pull packet off interface. */
  632         m = egget(sc, buf, len);
  633         if (m == 0) {
  634                 ifp->if_ierrors++;
  635                 return;
  636         }
  637 
  638         ifp->if_ipackets++;
  639 
  640         /* We assume the header fit entirely in one mbuf. */
  641         eh = mtod(m, struct ether_header *);
  642 
  643 #if NBPFILTER > 0
  644         /*
  645          * Check if there's a BPF listener on this interface.
  646          * If so, hand off the raw packet to BPF.
  647          */
  648         if (ifp->if_bpf) {
  649                 bpf_mtap(ifp, m);
  650 
  651                 /*
  652                  * Note that the interface cannot be in promiscuous mode if
  653                  * there are no BPF listeners.  And if we are in promiscuous
  654                  * mode, we have to check if this packet is really ours.
  655                  */
  656                 if ((ifp->if_flags & IFF_PROMISC) &&
  657                     (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
  658                     bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
  659                             sizeof(eh->ether_dhost)) != 0) {
  660                         m_freem(m);
  661                         return;
  662                 }
  663         }
  664 #endif
  665 
  666         /* We assume the header fit entirely in one mbuf. */
  667         m_adj(m, sizeof(struct ether_header));
  668         ether_input(ifp, eh, m);
  669 }
  670 
  671 /*
  672  * convert buf into mbufs
  673  */
  674 static struct mbuf *
  675 egget(sc, buf, totlen)
  676         struct eg_softc *sc;
  677         caddr_t buf;
  678         int totlen;
  679 {
  680         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  681         struct mbuf *top, **mp, *m;
  682         int len;
  683 
  684         MGETHDR(m, M_DONTWAIT, MT_DATA);
  685         if (m == 0)
  686                 return 0;
  687         m->m_pkthdr.rcvif = ifp;
  688         m->m_pkthdr.len = totlen;
  689         len = MHLEN;
  690         top = 0;
  691         mp = &top;
  692 
  693         while (totlen > 0) {
  694                 if (top) {
  695                         MGET(m, M_DONTWAIT, MT_DATA);
  696                         if (m == 0) {
  697                                 m_freem(top);
  698                                 return 0;
  699                         }
  700                         len = MLEN;
  701                 }
  702                 if (totlen >= MINCLSIZE) {
  703                         MCLGET(m, M_DONTWAIT);
  704                         if (m->m_flags & M_EXT)
  705                                 len = MCLBYTES;
  706                 }
  707                 m->m_len = len = min(totlen, len);
  708                 bcopy((caddr_t)buf, mtod(m, caddr_t), len);
  709                 buf += len;
  710                 totlen -= len;
  711                 *mp = m;
  712                 mp = &m->m_next;
  713         }
  714 
  715         return top;
  716 }
  717 
  718 static int
  719 egioctl(ifp, command, data)
  720         register struct ifnet *ifp;
  721         int command;
  722         caddr_t data;
  723 {
  724         struct eg_softc *sc = ifp->if_softc;
  725         int s, error = 0;
  726 
  727         s = splnet();
  728 
  729         switch (command) {
  730 
  731         case SIOCSIFADDR:
  732         case SIOCGIFADDR:
  733                 ether_ioctl(ifp, command, data);
  734                 break;
  735 
  736         case SIOCSIFFLAGS:
  737                 if ((ifp->if_flags & IFF_UP) == 0 &&
  738                     (ifp->if_flags & IFF_RUNNING) != 0) {
  739                         /*
  740                          * If interface is marked down and it is running, then
  741                          * stop it.
  742                          */
  743                         egstop(sc);
  744                         ifp->if_flags &= ~IFF_RUNNING;
  745                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  746                            (ifp->if_flags & IFF_RUNNING) == 0) {
  747                         /*
  748                          * If interface is marked up and it is stopped, then
  749                          * start it.
  750                          */
  751                         eginit(sc);
  752                 } else {
  753                         sc->eg_pcb[0] = EG_CMD_GETSTATS;
  754                         sc->eg_pcb[1] = 0;
  755 #ifdef EGDEBUG
  756                         if (egwritePCB(sc) != 0)
  757                                 dprintf(("eg#: write error\n"));
  758 #endif
  759                         /*
  760                          * XXX deal with flags changes:
  761                          * IFF_MULTICAST, IFF_PROMISC,
  762                          * IFF_LINK0, IFF_LINK1,
  763                          */
  764                 }
  765                 break;
  766 
  767         default:
  768                 error = EINVAL;
  769                 break;
  770         }
  771 
  772         splx(s);
  773         return error;
  774 }
  775 
  776 static void
  777 egreset(sc)
  778         struct eg_softc *sc;
  779 {
  780         int s;
  781 
  782         dprintf(("eg#: egreset()\n"));
  783         s = splnet();
  784         egstop(sc);
  785         eginit(sc);
  786         splx(s);
  787 }
  788 
  789 static void
  790 egwatchdog(ifp)
  791         struct ifnet *ifp;
  792 {
  793         struct eg_softc *sc = ifp->if_softc;
  794 
  795         log(LOG_ERR, "%s: device timeout\n", "eg#");
  796         sc->sc_arpcom.ac_if.if_oerrors++;
  797 
  798         egreset(sc);
  799 }
  800 
  801 static void
  802 egstop(sc)
  803         register struct eg_softc *sc;
  804 {
  805         
  806         outb(sc->eg_ctl, 0);
  807 }

Cache object: 73324b209abd0d077e330035c8f7434b


[ 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.