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/pc/ether83815.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  * National Semiconductor DP83815
    3  *
    4  * Supports only internal PHY and has been tested on:
    5  *      Netgear FA311TX (using Netgear DS108 10/100 hub)
    6  *      SiS 900 within SiS 630
    7  * To do:
    8  *      check Ethernet address;
    9  *      test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
   10  *      external PHY via MII (should be common code for MII);
   11  *      thresholds;
   12  *      ring sizing;
   13  *      physical link changes/disconnect;
   14  *      push initialisation back to attach.
   15  *
   16  * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
   17  */
   18 
   19 #include "u.h"
   20 #include "../port/lib.h"
   21 #include "mem.h"
   22 #include "dat.h"
   23 #include "fns.h"
   24 #include "io.h"
   25 #include "../port/error.h"
   26 #include "../port/netif.h"
   27 
   28 #include "etherif.h"
   29 
   30 #define DEBUG           0
   31 #define debug           if(DEBUG)print
   32 
   33 enum {
   34         Nrde            = 64,
   35         Ntde            = 64,
   36 };
   37 
   38 #define Rbsz            ROUNDUP(sizeof(Etherpkt)+4, 4)
   39 
   40 typedef struct Des {
   41         ulong   next;
   42         int     cmdsts;
   43         ulong   addr;
   44         Block*  bp;
   45 } Des;
   46 
   47 enum {  /* cmdsts */
   48         Own     = 1<<31,        /* set by data producer to hand to consumer */
   49         More    = 1<<30,        /* more of packet in next descriptor */
   50         Intr    = 1<<29,        /* interrupt when device is done with it */
   51         Supcrc  = 1<<28,        /* suppress crc on transmit */
   52         Inccrc  = 1<<28,        /* crc included on receive (always) */
   53         Ok      = 1<<27,        /* packet ok */
   54         Size    = 0xFFF,        /* packet size in bytes */
   55 
   56         /* transmit */
   57         Txa     = 1<<26,        /* transmission aborted */
   58         Tfu     = 1<<25,        /* transmit fifo underrun */
   59         Crs     = 1<<24,        /* carrier sense lost */
   60         Td      = 1<<23,        /* transmission deferred */
   61         Ed      = 1<<22,        /* excessive deferral */
   62         Owc     = 1<<21,        /* out of window collision */
   63         Ec      = 1<<20,        /* excessive collisions */
   64         /* 19-16 collision count */
   65 
   66         /* receive */
   67         Rxa     = 1<<26,        /* receive aborted (same as Rxo) */
   68         Rxo     = 1<<25,        /* receive overrun */
   69         Dest    = 3<<23,        /* destination class */
   70           Drej= 0<<23,          /* packet was rejected */
   71           Duni= 1<<23,          /* unicast */
   72           Dmulti=       2<<23,          /* multicast */
   73           Dbroad=       3<<23,          /* broadcast */
   74         Long = 1<<22,           /* too long packet received */
   75         Runt =  1<<21,          /* packet less than 64 bytes */
   76         Ise =   1<<20,          /* invalid symbol */
   77         Crce =  1<<19,          /* invalid crc */
   78         Fae =   1<<18,          /* frame alignment error */
   79         Lbp =   1<<17,          /* loopback packet */
   80         Col =   1<<16,          /* collision during receive */
   81 };
   82 
   83 enum {                          /* PCI vendor & device IDs */
   84         Nat83815        = (0x0020<<16)|0x100B,
   85         SiS =   0x1039,
   86         SiS900 =        (0x0900<<16)|SiS,
   87         SiS7016 =       (0x7016<<16)|SiS,
   88 
   89         SiS630bridge    = 0x0008,
   90 
   91         /* SiS 900 PCI revision codes */
   92         SiSrev630s =    0x81,
   93         SiSrev630e =    0x82,
   94         SiSrev630ea1 =  0x83,
   95 
   96         SiSeenodeaddr = 8,              /* short addr of SiS eeprom mac addr */
   97         SiS630eenodeaddr =      9,      /* likewise for the 630 */
   98         Nseenodeaddr =  6,              /* " for NS eeprom */
   99         Nat83815avng =  0x403,
  100         Nat83816avng =  0x505,          /* 83816 acts like submodel of 83815 */
  101                                         /* using reg. 0x58 to disambiguate. */
  102 };
  103 
  104 typedef struct Ctlr Ctlr;
  105 typedef struct Ctlr {
  106         int     port;
  107         Pcidev* pcidev;
  108         Ctlr*   next;
  109         int     active;
  110         int     id;                     /* (pcidev->did<<16)|pcidev->vid */
  111 
  112         ushort  srom[0xB+1];
  113         uchar   sromea[Eaddrlen];       /* MAC address */
  114 
  115         uchar   fd;                     /* option or auto negotiation */
  116 
  117         int     mbps;
  118 
  119         Lock    lock;
  120 
  121         Des*    rdr;                    /* receive descriptor ring */
  122         int     nrdr;                   /* size of rdr */
  123         int     rdrx;                   /* index into rdr */
  124 
  125         Lock    tlock;
  126         Des*    tdr;                    /* transmit descriptor ring */
  127         int     ntdr;                   /* size of tdr */
  128         int     tdrh;                   /* host index into tdr */
  129         int     tdri;                   /* interface index into tdr */
  130         int     ntq;                    /* descriptors active */
  131         int     ntqmax;
  132 
  133         ulong   rxa;                    /* receive statistics */
  134         ulong   rxo;
  135         ulong   rlong;
  136         ulong   runt;
  137         ulong   ise;
  138         ulong   crce;
  139         ulong   fae;
  140         ulong   lbp;
  141         ulong   col;
  142         ulong   rxsovr;
  143         ulong   rxorn;
  144 
  145         ulong   txa;                    /* transmit statistics */
  146         ulong   tfu;
  147         ulong   crs;
  148         ulong   td;
  149         ulong   ed;
  150         ulong   owc;
  151         ulong   ec;
  152         ulong   txurn;
  153 
  154         ulong   dperr;                  /* system errors */
  155         ulong   rmabt;
  156         ulong   rtabt;
  157         ulong   sserr;
  158         ulong   rxsover;
  159 
  160         ulong   version;                /* silicon version; register 0x58h */
  161 } Ctlr;
  162 
  163 static Ctlr* ctlrhead;
  164 static Ctlr* ctlrtail;
  165 
  166 enum {
  167         /* registers (could memory map) */
  168         Rcr=    0x00,           /* command register */
  169           Rst=          1<<8,
  170           Rxr=          1<<5,   /* receiver reset */
  171           Txr=          1<<4,   /* transmitter reset */
  172           Rxd=          1<<3,   /* receiver disable */
  173           Rxe=          1<<2,   /* receiver enable */
  174           Txd=          1<<1,   /* transmitter disable */
  175           Txe=          1<<0,   /* transmitter enable */
  176         Rcfg=   0x04,           /* configuration */
  177           Lnksts=       1<<31,  /* link good */
  178           Speed100=     1<<30,  /* 100 Mb/s link */
  179           Fdup=         1<<29,  /* full duplex */
  180           Pol=          1<<28,  /* polarity reversal (10baseT) */
  181           Aneg_dn=      1<<27,  /* autonegotiation done */
  182           Pint_acen=    1<<17,  /* PHY interrupt auto clear enable */
  183           Pause_adv=    1<<16,  /* advertise pause during auto neg */
  184           Paneg_ena=    1<<13,  /* auto negotiation enable */
  185           Paneg_all=    7<<13,  /* auto negotiation enable 10/100 half & full */
  186           Ext_phy=      1<<12,  /* enable MII for external PHY */
  187           Phy_rst=      1<<10,  /* reset internal PHY */
  188           Phy_dis=      1<<9,   /* disable internal PHY (eg, low power) */
  189           Req_alg=      1<<7,   /* PCI bus request: set means less aggressive */
  190           Sb=           1<<6,   /* single slot back-off not random */
  191           Pow=          1<<5,   /* out of window timer selection */
  192           Exd=          1<<4,   /* disable excessive deferral timer */
  193           Pesel=        1<<3,   /* parity error algorithm selection */
  194           Brom_dis=     1<<2,   /* disable boot rom interface */
  195           Bem=          1<<0,   /* big-endian mode */
  196         Rmear=  0x08,           /* eeprom access */
  197           Mdc=          1<<6,   /* MII mangement check */
  198           Mddir=        1<<5,   /* MII management direction */
  199           Mdio=         1<<4,   /* MII mangement data */
  200           Eesel=        1<<3,   /* EEPROM chip select */
  201           Eeclk=        1<<2,   /* EEPROM clock */
  202           Eedo=         1<<1,   /* EEPROM data out (from chip) */
  203           Eedi=         1<<0,   /* EEPROM data in (to chip) */
  204         Rptscr= 0x0C,           /* pci test control */
  205         Risr=   0x10,           /* interrupt status */
  206           Txrcmp=       1<<25,  /* transmit reset complete */
  207           Rxrcmp=       1<<24,  /* receiver reset complete */
  208           Dperr=        1<<23,  /* detected parity error */
  209           Sserr=        1<<22,  /* signalled system error */
  210           Rmabt=        1<<21,  /* received master abort */
  211           Rtabt=        1<<20,  /* received target abort */
  212           Rxsovr=       1<<16,  /* RX status FIFO overrun */
  213           Hiberr=       1<<15,  /* high bits error set (OR of 25-16) */
  214           Phy=          1<<14,  /* PHY interrupt */
  215           Pme=          1<<13,  /* power management event (wake online) */
  216           Swi=          1<<12,  /* software interrupt */
  217           Mib=          1<<11,  /* MIB service */
  218           Txurn=        1<<10,  /* TX underrun */
  219           Txidle=       1<<9,   /* TX idle */
  220           Txerr=        1<<8,   /* TX packet error */
  221           Txdesc=       1<<7,   /* TX descriptor (with Intr bit done) */
  222           Txok=         1<<6,   /* TX ok */
  223           Rxorn=        1<<5,   /* RX overrun */
  224           Rxidle=       1<<4,   /* RX idle */
  225           Rxearly=      1<<3,   /* RX early threshold */
  226           Rxerr=        1<<2,   /* RX packet error */
  227           Rxdesc=       1<<1,   /* RX descriptor (with Intr bit done) */
  228           Rxok=         1<<0,   /* RX ok */
  229         Rimr=   0x14,           /* interrupt mask */
  230         Rier=   0x18,           /* interrupt enable */
  231           Ie=           1<<0,   /* interrupt enable */
  232         Rtxdp=  0x20,           /* transmit descriptor pointer */
  233         Rtxcfg= 0x24,           /* transmit configuration */
  234           Csi=          1<<31,  /* carrier sense ignore (needed for full duplex) */
  235           Hbi=          1<<30,  /* heartbeat ignore (needed for full duplex) */
  236           Atp=          1<<28,  /* automatic padding of runt packets */
  237           Mxdma=        7<<20,  /* maximum dma transfer field */
  238           Mxdma32=      4<<20,  /* 4x32-bit words (32 bytes) */
  239           Mxdma64=      5<<20,  /* 8x32-bit words (64 bytes) */
  240           Flth=         0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
  241           Drth=         0x3F<<0,/* Tx drain threshold (units of 32 bytes) */
  242           Flth128=      4<<8,   /* fill at 128 bytes */
  243           Drth512=      16<<0,  /* drain at 512 bytes */
  244         Rrxdp=  0x30,           /* receive descriptor pointer */
  245         Rrxcfg= 0x34,           /* receive configuration */
  246           Atx=          1<<28,  /* accept transmit packets (needed for full duplex) */
  247           Rdrth=        0x1F<<1,/* Rx drain threshold (units of 32 bytes) */
  248           Rdrth64=      2<<1,   /* drain at 64 bytes */
  249         Rccsr=  0x3C,           /* CLKRUN control/status */
  250           Pmests=       1<<15,  /* PME status */
  251         Rwcsr=  0x40,           /* wake on lan control/status */
  252         Rpcr=   0x44,           /* pause control/status */
  253         Rrfcr=  0x48,           /* receive filter/match control */
  254           Rfen=         1<<31,  /* receive filter enable */
  255           Aab=          1<<30,  /* accept all broadcast */
  256           Aam=          1<<29,  /* accept all multicast */
  257           Aau=          1<<28,  /* accept all unicast */
  258           Apm=          1<<27,  /* accept on perfect match */
  259           Apat=         0xF<<23,/* accept on pattern match */
  260           Aarp=         1<<22,  /* accept ARP */
  261           Mhen=         1<<21,  /* multicast hash enable */
  262           Uhen=         1<<20,  /* unicast hash enable */
  263           Ulm=          1<<19,  /* U/L bit mask */
  264                                 /* bits 0-9 are rfaddr */
  265         Rrfdr=  0x4C,           /* receive filter/match data */
  266         Rbrar=  0x50,           /* boot rom address */
  267         Rbrdr=  0x54,           /* boot rom data */
  268         Rsrr=   0x58,           /* silicon revision */
  269         Rmibc=  0x5C,           /* MIB control */
  270                                 /* 60-78 MIB data */
  271 
  272         /* PHY registers */
  273         Rbmcr=  0x80,           /* basic mode configuration */
  274           Reset=        1<<15,
  275           Sel100=       1<<13,  /* select 100Mb/sec if no auto neg */
  276           Anena=        1<<12,  /* auto negotiation enable */
  277           Anrestart=    1<<9,   /* restart auto negotiation */
  278           Selfdx=       1<<8,   /* select full duplex if no auto neg */
  279         Rbmsr=  0x84,           /* basic mode status */
  280           Ancomp=       1<<5,   /* autonegotiation complete */
  281         Rphyidr1= 0x88,
  282         Rphyidr2= 0x8C,
  283         Ranar=  0x90,           /* autonegotiation advertisement */
  284         Ranlpar= 0x94,          /* autonegotiation link partner ability */
  285         Raner=  0x98,           /* autonegotiation expansion */
  286         Rannptr= 0x9C,          /* autonegotiation next page TX */
  287         Rphysts= 0xC0,          /* PHY status */
  288         Rmicr=  0xC4,           /* MII control */
  289           Inten=        1<<1,   /* PHY interrupt enable */
  290         Rmisr=  0xC8,           /* MII status */
  291         Rfcscr= 0xD0,           /* false carrier sense counter */
  292         Rrecr=  0xD4,           /* receive error counter */
  293         Rpcsr=  0xD8,           /* 100Mb config/status */
  294         Rphycr= 0xE4,           /* PHY control */
  295         Rtbscr= 0xE8,           /* 10BaseT status/control */
  296 };
  297 
  298 /*
  299  * eeprom addresses
  300  *      7 to 9 (16 bit words): mac address, shifted and reversed
  301  */
  302 
  303 #define csr32r(c, r)    (inl((c)->port+(r)))
  304 #define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
  305 #define csr16r(c, r)    (ins((c)->port+(r)))
  306 #define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l)))
  307 
  308 static void
  309 dumpcregs(Ctlr *ctlr)
  310 {
  311         int i;
  312 
  313         for(i=0; i<=0x5C; i+=4)
  314                 print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
  315 }
  316 
  317 static void
  318 promiscuous(void* arg, int on)
  319 {
  320         Ctlr *ctlr;
  321         ulong w;
  322 
  323         ctlr = ((Ether*)arg)->ctlr;
  324         ilock(&ctlr->lock);
  325         w = csr32r(ctlr, Rrfcr);
  326         if(on != ((w&Aau)!=0)){
  327                 csr32w(ctlr, Rrfcr, w & ~Rfen);
  328                 csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau));
  329         }
  330         iunlock(&ctlr->lock);
  331 }
  332 
  333 static void
  334 attach(Ether* ether)
  335 {
  336         Ctlr *ctlr;
  337 
  338         ctlr = ether->ctlr;
  339         ilock(&ctlr->lock);
  340         if(0)
  341                 dumpcregs(ctlr);
  342         csr32w(ctlr, Rcr, Rxe);
  343         iunlock(&ctlr->lock);
  344 }
  345 
  346 static long
  347 ifstat(Ether* ether, void* a, long n, ulong offset)
  348 {
  349         Ctlr *ctlr;
  350         char *buf, *p;
  351         int i, l, len;
  352 
  353         ctlr = ether->ctlr;
  354 
  355         ether->crcs = ctlr->crce;
  356         ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae;
  357         ether->buffs = ctlr->rxorn+ctlr->tfu;
  358         ether->overflows = ctlr->rxsovr;
  359 
  360         if(n == 0)
  361                 return 0;
  362 
  363         p = malloc(READSTR);
  364         l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa);
  365         l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo);
  366         l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong);
  367         l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt);
  368         l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise);
  369         l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae);
  370         l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp);
  371         l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu);
  372         l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa);
  373         l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce);
  374         l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col);
  375         l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong);
  376         l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt);
  377         l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn);
  378         l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn);
  379         l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
  380         l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc);
  381         l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs);
  382         l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr);
  383         l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt);
  384         l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover);
  385         snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
  386         ctlr->ntqmax = 0;
  387         buf = a;
  388         len = readstr(offset, buf, n, p);
  389         if(offset > l)
  390                 offset -= l;
  391         else
  392                 offset = 0;
  393         buf += len;
  394         n -= len;
  395 
  396         l = snprint(p, READSTR, "srom:");
  397         for(i = 0; i < nelem(ctlr->srom); i++){
  398                 if(i && ((i & 0x0F) == 0))
  399                         l += snprint(p+l, READSTR-l, "\n     ");
  400                 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]);
  401         }
  402 
  403         snprint(p+l, READSTR-l, "\n");
  404         len += readstr(offset, buf, n, p);
  405         free(p);
  406 
  407         return len;
  408 }
  409 
  410 static void
  411 txstart(Ether* ether)
  412 {
  413         Ctlr *ctlr;
  414         Block *bp;
  415         Des *des;
  416         int started;
  417 
  418         ctlr = ether->ctlr;
  419         started = 0;
  420         while(ctlr->ntq < ctlr->ntdr-1){
  421                 bp = qget(ether->oq);
  422                 if(bp == nil)
  423                         break;
  424                 des = &ctlr->tdr[ctlr->tdrh];
  425                 des->bp = bp;
  426                 des->addr = PADDR(bp->rp);
  427                 ctlr->ntq++;
  428                 coherence();
  429                 des->cmdsts = Own | BLEN(bp);
  430                 ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
  431                 started = 1;
  432         }
  433         if(started){
  434                 coherence();
  435                 csr32w(ctlr, Rcr, Txe); /* prompt */
  436         }
  437 
  438         if(ctlr->ntq > ctlr->ntqmax)
  439                 ctlr->ntqmax = ctlr->ntq;
  440 }
  441 
  442 static void
  443 transmit(Ether* ether)
  444 {
  445         Ctlr *ctlr;
  446 
  447         ctlr = ether->ctlr;
  448         ilock(&ctlr->tlock);
  449         txstart(ether);
  450         iunlock(&ctlr->tlock);
  451 }
  452 
  453 static void
  454 txrxcfg(Ctlr *ctlr, int txdrth)
  455 {
  456         ulong rx, tx;
  457 
  458         rx = csr32r(ctlr, Rrxcfg);
  459         tx = csr32r(ctlr, Rtxcfg);
  460         if(ctlr->fd){
  461                 rx |= Atx;
  462                 tx |= Csi | Hbi;
  463         }else{
  464                 rx &= ~Atx;
  465                 tx &= ~(Csi | Hbi);
  466         }
  467         tx &= ~(Mxdma|Drth|Flth);
  468         tx |= Mxdma64 | Flth128 | txdrth;
  469         csr32w(ctlr, Rtxcfg, tx);
  470         rx &= ~(Mxdma|Rdrth);
  471         rx |= Mxdma64 | Rdrth64;
  472         csr32w(ctlr, Rrxcfg, rx);
  473 }
  474 
  475 static void
  476 interrupt(Ureg*, void* arg)
  477 {
  478         int len, status, cmdsts, n;
  479         Ctlr *ctlr;
  480         Ether *ether;
  481         Des *des;
  482         Block *bp;
  483 
  484         ether = arg;
  485         ctlr = ether->ctlr;
  486 
  487         while((status = csr32r(ctlr, Risr)) != 0){
  488 
  489                 status &= ~(Pme|Mib);
  490 
  491                 if(status & Hiberr){
  492                         if(status & Rxsovr)
  493                                 ctlr->rxsover++;
  494                         if(status & Sserr)
  495                                 ctlr->sserr++;
  496                         if(status & Dperr)
  497                                 ctlr->dperr++;
  498                         if(status & Rmabt)
  499                                 ctlr->rmabt++;
  500                         if(status & Rtabt)
  501                                 ctlr->rtabt++;
  502                         status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
  503                 }
  504 
  505                 /* update link state */
  506                 if(status&Phy){
  507                         status &= ~Phy;
  508                         csr32r(ctlr, Rcfg);
  509                         n = csr32r(ctlr, Rcfg);
  510 //                      iprint("83815 phy %x %x\n", n, n&Lnksts);
  511                         ether->link = (n&Lnksts) != 0;
  512                 }
  513 
  514                 /*
  515                  * Received packets.
  516                  */
  517                 if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
  518                         des = &ctlr->rdr[ctlr->rdrx];
  519                         while((cmdsts = des->cmdsts) & Own){
  520                                 if((cmdsts&Ok) == 0){
  521                                         if(cmdsts & Rxa)
  522                                                 ctlr->rxa++;
  523                                         if(cmdsts & Rxo)
  524                                                 ctlr->rxo++;
  525                                         if(cmdsts & Long)
  526                                                 ctlr->rlong++;
  527                                         if(cmdsts & Runt)
  528                                                 ctlr->runt++;
  529                                         if(cmdsts & Ise)
  530                                                 ctlr->ise++;
  531                                         if(cmdsts & Crce)
  532                                                 ctlr->crce++;
  533                                         if(cmdsts & Fae)
  534                                                 ctlr->fae++;
  535                                         if(cmdsts & Lbp)
  536                                                 ctlr->lbp++;
  537                                         if(cmdsts & Col)
  538                                                 ctlr->col++;
  539                                 }
  540                                 else if(bp = iallocb(Rbsz)){
  541                                         len = (cmdsts&Size)-4;
  542                                         if(len <= 0){
  543                                                 debug("ns83815: packet len %d <=0\n", len);
  544                                                 freeb(des->bp);
  545                                         }else{
  546                                                 des->bp->wp = des->bp->rp+len;
  547                                                 etheriq(ether, des->bp, 1);
  548                                         }
  549                                         des->bp = bp;
  550                                         des->addr = PADDR(bp->rp);
  551                                         coherence();
  552                                 }else{
  553                                         debug("ns83815: interrupt: iallocb for input buffer failed\n");
  554                                         des->bp->next = 0;
  555                                 }
  556 
  557                                 des->cmdsts = Rbsz;
  558                                 coherence();
  559 
  560                                 ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
  561                                 des = &ctlr->rdr[ctlr->rdrx];
  562                         }
  563                         status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
  564                 }
  565 
  566                 /*
  567                  * Check the transmit side:
  568                  *      check for Transmit Underflow and Adjust
  569                  *      the threshold upwards;
  570                  *      free any transmitted buffers and try to
  571                  *      top-up the ring.
  572                  */
  573                 if(status & Txurn){
  574                         ctlr->txurn++;
  575                         ilock(&ctlr->lock);
  576                         /* change threshold */
  577                         iunlock(&ctlr->lock);
  578                         status &= ~(Txurn);
  579                 }
  580 
  581                 ilock(&ctlr->tlock);
  582                 while(ctlr->ntq){
  583                         des = &ctlr->tdr[ctlr->tdri];
  584                         cmdsts = des->cmdsts;
  585                         if(cmdsts & Own)
  586                                 break;
  587 
  588                         if((cmdsts & Ok) == 0){
  589                                 if(cmdsts & Txa)
  590                                         ctlr->txa++;
  591                                 if(cmdsts & Tfu)
  592                                         ctlr->tfu++;
  593                                 if(cmdsts & Td)
  594                                         ctlr->td++;
  595                                 if(cmdsts & Ed)
  596                                         ctlr->ed++;
  597                                 if(cmdsts & Owc)
  598                                         ctlr->owc++;
  599                                 if(cmdsts & Ec)
  600                                         ctlr->ec++;
  601                                 ether->oerrs++;
  602                         }
  603 
  604                         freeb(des->bp);
  605                         des->bp = nil;
  606                         des->cmdsts = 0;
  607 
  608                         ctlr->ntq--;
  609                         ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
  610                 }
  611                 txstart(ether);
  612                 iunlock(&ctlr->tlock);
  613 
  614                 status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
  615 
  616                 /*
  617                  * Anything left not catered for?
  618                  */
  619                 if(status)
  620                         print("#l%d: status %8.8uX\n", ether->ctlrno, status);
  621         }
  622 }
  623 
  624 static void
  625 ctlrinit(Ether* ether)
  626 {
  627         Ctlr *ctlr;
  628         Des *des, *last;
  629 
  630         ctlr = ether->ctlr;
  631 
  632         /*
  633          * Allocate suitable aligned descriptors
  634          * for the transmit and receive rings;
  635          * initialise the receive ring;
  636          * initialise the transmit ring;
  637          * unmask interrupts and start the transmit side.
  638          */
  639         des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0);
  640         ctlr->tdr = des;
  641         ctlr->rdr = des+ctlr->ntdr;
  642 
  643         last = nil;
  644         for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
  645                 des->bp = iallocb(Rbsz);
  646                 if(des->bp == nil)
  647                         error(Enomem);
  648                 des->cmdsts = Rbsz;
  649                 des->addr = PADDR(des->bp->rp);
  650                 if(last != nil)
  651                         last->next = PADDR(des);
  652                 last = des;
  653         }
  654         ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
  655         ctlr->rdrx = 0;
  656         csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
  657 
  658         last = nil;
  659         for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
  660                 des->cmdsts = 0;
  661                 des->bp = nil;
  662                 des->addr = ~0;
  663                 if(last != nil)
  664                         last->next = PADDR(des);
  665                 last = des;
  666         }
  667         ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
  668         ctlr->tdrh = 0;
  669         ctlr->tdri = 0;
  670         csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
  671 
  672         txrxcfg(ctlr, Drth512);
  673 
  674         csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
  675                 Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);   /* Phy|Pme|Mib */
  676         csr32w(ctlr, Rmicr, Inten);     /* enable phy interrupts */
  677         csr32r(ctlr, Risr);             /* clear status */
  678         csr32w(ctlr, Rier, Ie);
  679 }
  680 
  681 static void
  682 eeclk(Ctlr *ctlr, int clk)
  683 {
  684         csr32w(ctlr, Rmear, Eesel | clk);
  685         microdelay(2);
  686 }
  687 
  688 static void
  689 eeidle(Ctlr *ctlr)
  690 {
  691         int i;
  692 
  693         eeclk(ctlr, 0);
  694         eeclk(ctlr, Eeclk);
  695         for(i=0; i<25; i++){
  696                 eeclk(ctlr, 0);
  697                 eeclk(ctlr, Eeclk);
  698         }
  699         eeclk(ctlr, 0);
  700         csr32w(ctlr, Rmear, 0);
  701         microdelay(2);
  702 }
  703 
  704 static ushort
  705 eegetw(Ctlr *ctlr, int a)
  706 {
  707         int d, i, w;
  708 
  709         eeidle(ctlr);
  710         eeclk(ctlr, 0);
  711         eeclk(ctlr, Eeclk);
  712         d = 0x180 | a;
  713         for(i=0x400; i; i>>=1){
  714                 if(d & i)
  715                         csr32w(ctlr, Rmear, Eesel|Eedi);
  716                 else
  717                         csr32w(ctlr, Rmear, Eesel);
  718                 eeclk(ctlr, Eeclk);
  719                 eeclk(ctlr, 0);
  720                 microdelay(2);
  721         }
  722         w = 0;
  723         for(i=0x8000; i; i >>= 1){
  724                 eeclk(ctlr, Eeclk);
  725                 if(csr32r(ctlr, Rmear) & Eedo)
  726                         w |= i;
  727                 microdelay(2);
  728                 eeclk(ctlr, 0);
  729         }
  730         eeidle(ctlr);
  731         return w;
  732 }
  733 
  734 static int
  735 resetctlr(Ctlr *ctlr)
  736 {
  737         int i;
  738 
  739         /*
  740          * Soft-reset the controller
  741          */
  742         csr32w(ctlr, Rcr, Rst);
  743         for(i=0;; i++){
  744                 if(i > 100){
  745                         print("ns83815: soft reset did not complete\n");
  746                         return -1;
  747                 }
  748                 microdelay(250);
  749                 if((csr32r(ctlr, Rcr) & Rst) == 0)
  750                         break;
  751                 delay(1);
  752         }
  753         return 0;
  754 }
  755 
  756 static void
  757 shutdown(Ether* ether)
  758 {
  759         Ctlr *ctlr = ether->ctlr;
  760 
  761 print("ether83815 shutting down\n");
  762         csr32w(ctlr, Rcr, Rxd|Txd);     /* disable transceiver */
  763         resetctlr(ctlr);
  764 }
  765 
  766 static int
  767 softreset(Ctlr* ctlr, int resetphys)
  768 {
  769         int i, w;
  770 
  771         /*
  772          * Soft-reset the controller
  773          */
  774         resetctlr(ctlr);
  775         csr32w(ctlr, Rccsr, Pmests);
  776         csr32w(ctlr, Rccsr, 0);
  777         csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
  778         ctlr->version = csr32r(ctlr, Rsrr);
  779         if(resetphys){
  780                 /*
  781                  * Soft-reset the PHY
  782                  */
  783                 csr32w(ctlr, Rbmcr, Reset);
  784                 for(i=0;; i++){
  785                         if(i > 100){
  786                                 print("ns83815: PHY soft reset time out\n");
  787                                 return -1;
  788                         }
  789                         if((csr32r(ctlr, Rbmcr) & Reset) == 0)
  790                                 break;
  791                         delay(1);
  792                 }
  793         }
  794 
  795         /*
  796          * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
  797          */
  798         csr16w(ctlr, 0xCC, 0x0001);     /* PGSEL */
  799         csr16w(ctlr, 0xE4, 0x189C);     /* PMCCSR */
  800         csr16w(ctlr, 0xFC, 0x0000);     /* TSTDAT */
  801         csr16w(ctlr, 0xF4, 0x5040);     /* DSPCFG */
  802         csr16w(ctlr, 0xF8, 0x008C);     /* SDCFG */
  803 
  804         /*
  805          * Auto negotiate
  806          */
  807         csr16r(ctlr, Rbmsr);            /* clear latched bits */
  808         debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
  809         csr16w(ctlr, Rbmcr, Anena);
  810         if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
  811                 csr16w(ctlr, Rbmcr, Anena|Anrestart);
  812                 for(i=0;; i++){
  813                         if(i > 3000){
  814                                 print("ns83815: auto neg timed out\n");
  815                                 return -1;
  816                         }
  817                         if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
  818                                 break;
  819                         delay(1);
  820                 }
  821                 debug("%d ms\n", i);
  822                 w &= 0xFFFF;
  823                 debug("bmsr: %4.4ux\n", w);
  824                 USED(w);
  825         }
  826         debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
  827         debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
  828         debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
  829         debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
  830         debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
  831         return 0;
  832 }
  833 
  834 static int
  835 media(Ether* ether)
  836 {
  837         Ctlr* ctlr;
  838         ulong cfg;
  839 
  840         ctlr = ether->ctlr;
  841         cfg = csr32r(ctlr, Rcfg);
  842         ctlr->fd = (cfg & Fdup) != 0;
  843         ether->link = (cfg&Lnksts) != 0;
  844         return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
  845 }
  846 
  847 static char* mediatable[9] = {
  848         "10BASE-T",                             /* TP */
  849         "10BASE-2",                             /* BNC */
  850         "10BASE-5",                             /* AUI */
  851         "100BASE-TX",
  852         "10BASE-TFD",
  853         "100BASE-TXFD",
  854         "100BASE-T4",
  855         "100BASE-FX",
  856         "100BASE-FXFD",
  857 };
  858 
  859 static int
  860 is630(ulong id, Pcidev *p)
  861 {
  862         if(id == SiS900)
  863                 switch (p->rid) {
  864                 case SiSrev630s:
  865                 case SiSrev630e:
  866                 case SiSrev630ea1:
  867                         return 1;
  868                 }
  869         return 0;
  870 }
  871 
  872 enum {
  873         MagicReg = 0x48,
  874         MagicRegSz = 1,
  875         Magicrden = 0x40,       /* read enable, apparently */
  876         Paddr=          0x70,   /* address port */
  877         Pdata=          0x71,   /* data port */
  878 };
  879 
  880 /* rcmos() originally from LANL's SiS 900 driver's rcmos() */
  881 static int
  882 sisrdcmos(Ctlr *ctlr)
  883 {
  884         int i;
  885         unsigned reg;
  886         ulong port;
  887         Pcidev *p;
  888 
  889         debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);
  890         p = pcimatch(nil, SiS, SiS630bridge);
  891         if(p == nil) {
  892                 print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",
  893                         ctlr->pcidev->rid);
  894                 return 0;
  895         }
  896         port = p->mem[0].bar & ~0x01;
  897         debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);
  898 
  899         reg = pcicfgr8(p, MagicReg);
  900         pcicfgw8(p, MagicReg, reg|Magicrden);
  901 
  902         for (i = 0; i < Eaddrlen; i++) {
  903                 outb(port+Paddr, SiS630eenodeaddr + i);
  904                 ctlr->sromea[i] = inb(port+Pdata);
  905         }
  906 
  907         pcicfgw8(p, MagicReg, reg & ~Magicrden);
  908         return 1;
  909 }
  910 
  911 /*
  912  * If this is a SiS 630E chipset with an embedded SiS 900 controller,
  913  * we have to read the MAC address from the APC CMOS RAM. - sez freebsd.
  914  * However, CMOS *is* NVRAM normally.  See devrtc.c:440, memory.c:88.
  915  */
  916 static void
  917 sissrom(Ctlr *ctlr)
  918 {
  919         union {
  920                 uchar   eaddr[Eaddrlen];
  921                 ushort  alignment;
  922         } ee;
  923         int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);
  924         ushort *shp = (ushort *)ee.eaddr;
  925 
  926         if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {
  927                 for (i = 0; i < cnt; i++)
  928                         *shp++ = eegetw(ctlr, off++);
  929                 memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
  930         }
  931 }
  932 
  933 ushort
  934 søkrisee(Ctlr *c, int n)
  935 {
  936         int i;
  937         uint cmd;
  938         ushort r;
  939 
  940         csr32w(c, Rmear, Eesel);
  941 
  942         cmd = 0x180|n;
  943         for(i = 10; i >= 0; i--){
  944                 n = 1<<3;
  945                 if(cmd&(1<<i))
  946                         n |= 1;
  947                 csr32w(c, Rmear, n);
  948                 csr32r(c, Rmear);
  949                 csr32w(c, Rmear, n|4);
  950                 csr32r(c, Rmear);
  951         }
  952 
  953         csr32w(c, Rmear, 1<<3);
  954         csr32r(c, Rmear);
  955 
  956         r = 0;
  957         for(i = 0; i < 16; i++){
  958                 csr32w(c, Rmear, 1<<3 | 1<<2);
  959                 csr32r(c, Rmear);
  960                 if(csr32r(c, Rmear) & 2)
  961                         r |= 1<<i;
  962                 csr32w(c, Rmear, 1<<3);
  963                 csr32r(c, Rmear);
  964         }
  965 
  966         csr32w(c, Rmear, 1<<3);
  967         csr32w(c, Rmear, 0);
  968 
  969         return r;
  970 }
  971 
  972 static void
  973 nsnormalea(Ctlr *ctlr)
  974 {
  975         int i, j;
  976 
  977         /*
  978          * the MAC address is reversed, straddling word boundaries
  979          */
  980         j = Nseenodeaddr*16 + 15;
  981         for(i = 0; i < 48; i++){
  982                 ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
  983                 j++;
  984         }
  985 }
  986 
  987 static void
  988 ns403ea(Ctlr *ctlr)
  989 {
  990         int i;
  991         ushort s, t;
  992 
  993         s = ctlr->srom[6];
  994         for(i = 0; i < 3; i++){
  995                 t = ctlr->srom[i+7];
  996                 ctlr->sromea[i*2]   = t<<1 | s>>15;
  997                 ctlr->sromea[i*2+1] = t>>7;
  998                 s = t;
  999         }
 1000 }
 1001 
 1002 static void
 1003 nssrom(Ctlr* ctlr)
 1004 {
 1005         int i, ns403;
 1006         ulong vers;
 1007         ushort (*ee)(Ctlr*, int);
 1008 
 1009         vers = ctlr->version;
 1010         ns403 = vers == Nat83815avng || vers == Nat83816avng;
 1011         if(ns403){
 1012                 ee = søkrisee;
 1013                 print("soekris %lx\n", vers);
 1014         }else
 1015                 ee = eegetw;
 1016 
 1017         for(i = 0; i < nelem(ctlr->srom); i++)
 1018                 ctlr->srom[i] = ee(ctlr, i);
 1019 
 1020         if(ns403)
 1021                 ns403ea(ctlr);
 1022         else
 1023                 nsnormalea(ctlr);
 1024 }
 1025 
 1026 static void
 1027 srom(Ctlr* ctlr)
 1028 {
 1029         memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
 1030         switch (ctlr->id) {
 1031         case SiS900:
 1032         case SiS7016:
 1033                 sissrom(ctlr);
 1034                 break;
 1035         case Nat83815:
 1036                 nssrom(ctlr);
 1037                 break;
 1038         default:
 1039                 print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);
 1040                 break;
 1041         }
 1042 }
 1043 
 1044 static void
 1045 scanpci83815(void)
 1046 {
 1047         Ctlr *ctlr;
 1048         Pcidev *p;
 1049         ulong id;
 1050 
 1051         p = nil;
 1052         while(p = pcimatch(p, 0, 0)){
 1053                 if(p->ccrb != Pcibcnet || p->ccru != 0)
 1054                         continue;
 1055                 id = (p->did<<16)|p->vid;
 1056                 switch(id){
 1057                 default:
 1058                         continue;
 1059 
 1060                 case Nat83815:
 1061                         break;
 1062                 case SiS900:
 1063                         break;
 1064                 }
 1065 
 1066                 /*
 1067                  * bar[0] is the I/O port register address and
 1068                  * bar[1] is the memory-mapped register address.
 1069                  */
 1070                 ctlr = malloc(sizeof(Ctlr));
 1071                 ctlr->port = p->mem[0].bar & ~0x01;
 1072                 ctlr->pcidev = p;
 1073                 ctlr->id = id;
 1074 
 1075                 if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
 1076                         print("ns83815: port 0x%uX in use\n", ctlr->port);
 1077                         free(ctlr);
 1078                         continue;
 1079                 }
 1080 
 1081                 if(softreset(ctlr, 0) == -1){
 1082                         free(ctlr);
 1083                         continue;
 1084                 }
 1085                 srom(ctlr);
 1086 
 1087                 if(ctlrhead != nil)
 1088                         ctlrtail->next = ctlr;
 1089                 else
 1090                         ctlrhead = ctlr;
 1091                 ctlrtail = ctlr;
 1092         }
 1093 }
 1094 
 1095 /* multicast already on, don't need to do anything */
 1096 static void
 1097 multicast(void*, uchar*, int)
 1098 {
 1099 }
 1100 
 1101 static int
 1102 reset(Ether* ether)
 1103 {
 1104         Ctlr *ctlr;
 1105         int i, x;
 1106         ulong ctladdr;
 1107         uchar ea[Eaddrlen];
 1108         static int scandone;
 1109 
 1110         if(scandone == 0){
 1111                 scanpci83815();
 1112                 scandone = 1;
 1113         }
 1114 
 1115         /*
 1116          * Any adapter matches if no ether->port is supplied,
 1117          * otherwise the ports must match.
 1118          */
 1119         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1120                 if(ctlr->active)
 1121                         continue;
 1122                 if(ether->port == 0 || ether->port == ctlr->port){
 1123                         ctlr->active = 1;
 1124                         break;
 1125                 }
 1126         }
 1127         if(ctlr == nil)
 1128                 return -1;
 1129 
 1130         ether->ctlr = ctlr;
 1131         ether->port = ctlr->port;
 1132         ether->irq = ctlr->pcidev->intl;
 1133         ether->tbdf = ctlr->pcidev->tbdf;
 1134 
 1135         /*
 1136          * Check if the adapter's station address is to be overridden.
 1137          * If not, read it from the EEPROM and set in ether->ea prior to
 1138          * loading the station address in the hardware.
 1139          */
 1140         memset(ea, 0, Eaddrlen);
 1141         if(memcmp(ea, ether->ea, Eaddrlen) == 0)
 1142                 memmove(ether->ea, ctlr->sromea, Eaddrlen);
 1143         for(i=0; i<Eaddrlen; i+=2){
 1144                 x = ether->ea[i] | (ether->ea[i+1]<<8);
 1145                 ctladdr = (ctlr->id == Nat83815? i: i<<15);
 1146                 csr32w(ctlr, Rrfcr, ctladdr);
 1147                 csr32w(ctlr, Rrfdr, x);
 1148         }
 1149         csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
 1150 
 1151         ether->mbps = media(ether);
 1152 
 1153         /*
 1154          * Look for a medium override in case there's no autonegotiation
 1155          * the autonegotiation fails.
 1156          */
 1157 
 1158         for(i = 0; i < ether->nopt; i++){
 1159                 if(cistrcmp(ether->opt[i], "FD") == 0){
 1160                         ctlr->fd = 1;
 1161                         continue;
 1162                 }
 1163                 for(x = 0; x < nelem(mediatable); x++){
 1164                         debug("compare <%s> <%s>\n", mediatable[x],
 1165                                 ether->opt[i]);
 1166                         if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
 1167                                 if(x != 4 && x >= 3)
 1168                                         ether->mbps = 100;
 1169                                 else
 1170                                         ether->mbps = 10;
 1171                                 switch(x){
 1172                                 default:
 1173                                         ctlr->fd = 0;
 1174                                         break;
 1175 
 1176                                 case 0x04:              /* 10BASE-TFD */
 1177                                 case 0x05:              /* 100BASE-TXFD */
 1178                                 case 0x08:              /* 100BASE-FXFD */
 1179                                         ctlr->fd = 1;
 1180                                         break;
 1181                                 }
 1182                                 break;
 1183                         }
 1184                 }
 1185         }
 1186 
 1187         /*
 1188          * Initialise descriptor rings, ethernet address.
 1189          */
 1190         ctlr->nrdr = Nrde;
 1191         ctlr->ntdr = Ntde;
 1192         pcisetbme(ctlr->pcidev);
 1193         ctlrinit(ether);
 1194 
 1195         /*
 1196          * Linkage to the generic ethernet driver.
 1197          */
 1198         ether->attach = attach;
 1199         ether->transmit = transmit;
 1200         ether->interrupt = interrupt;
 1201         ether->ifstat = ifstat;
 1202 
 1203         ether->arg = ether;
 1204         ether->promiscuous = promiscuous;
 1205         ether->multicast = multicast;
 1206         ether->shutdown = shutdown;
 1207         return 0;
 1208 }
 1209 
 1210 void
 1211 ether83815link(void)
 1212 {
 1213         addethercard("83815",  reset);
 1214 }

Cache object: fe805a267c4c61bd2816e8356938c919


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