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/ether2114x.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  * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller.
    3  * To do:
    4  *      thresholds;
    5  *      ring sizing;
    6  *      handle more error conditions;
    7  *      tidy setup packet mess;
    8  *      push initialisation back to attach;
    9  *      full SROM decoding.
   10  */
   11 #include "u.h"
   12 #include "../port/lib.h"
   13 #include "mem.h"
   14 #include "dat.h"
   15 #include "fns.h"
   16 #include "io.h"
   17 #include "../port/error.h"
   18 #include "../port/netif.h"
   19 
   20 #include "etherif.h"
   21 
   22 #define DEBUG           (0)
   23 #define debug           if(DEBUG)print
   24 
   25 enum {
   26         Nrde            = 64,
   27         Ntde            = 64,
   28 };
   29 
   30 #define Rbsz            ROUNDUP(sizeof(Etherpkt)+4, 4)
   31 
   32 enum {                                  /* CRS0 - Bus Mode */
   33         Swr             = 0x00000001,   /* Software Reset */
   34         Bar             = 0x00000002,   /* Bus Arbitration */
   35         Dsl             = 0x0000007C,   /* Descriptor Skip Length (field) */
   36         Ble             = 0x00000080,   /* Big/Little Endian */
   37         Pbl             = 0x00003F00,   /* Programmable Burst Length (field) */
   38         Cal             = 0x0000C000,   /* Cache Alignment (field) */
   39         Cal8            = 0x00004000,   /* 8 longword boundary alignment */
   40         Cal16           = 0x00008000,   /* 16 longword boundary alignment */
   41         Cal32           = 0x0000C000,   /* 32 longword boundary alignment */
   42         Tap             = 0x000E0000,   /* Transmit Automatic Polling (field) */
   43         Dbo             = 0x00100000,   /* Descriptor Byte Ordering Mode */
   44         Rml             = 0x00200000,   /* Read Multiple */
   45 }; 
   46 
   47 enum {                                  /* CSR[57] - Status and Interrupt Enable */
   48         Ti              = 0x00000001,   /* Transmit Interrupt */
   49         Tps             = 0x00000002,   /* Transmit Process Stopped */
   50         Tu              = 0x00000004,   /* Transmit buffer Unavailable */
   51         Tjt             = 0x00000008,   /* Transmit Jabber Timeout */
   52         Unf             = 0x00000020,   /* transmit UNderFlow */
   53         Ri              = 0x00000040,   /* Receive Interrupt */
   54         Ru              = 0x00000080,   /* Receive buffer Unavailable */
   55         Rps             = 0x00000100,   /* Receive Process Stopped */
   56         Rwt             = 0x00000200,   /* Receive Watchdog Timeout */
   57         Eti             = 0x00000400,   /* Early Transmit Interrupt */
   58         Gte             = 0x00000800,   /* General purpose Timer Expired */
   59         Fbe             = 0x00002000,   /* Fatal Bit Error */
   60         Ais             = 0x00008000,   /* Abnormal Interrupt Summary */
   61         Nis             = 0x00010000,   /* Normal Interrupt Summary */
   62         Rs              = 0x000E0000,   /* Receive process State (field) */
   63         Ts              = 0x00700000,   /* Transmit process State (field) */
   64         Eb              = 0x03800000,   /* Error bits */
   65 };
   66 
   67 enum {                                  /* CSR6 - Operating Mode */
   68         Hp              = 0x00000001,   /* Hash/Perfect receive filtering mode */
   69         Sr              = 0x00000002,   /* Start/stop Receive */
   70         Ho              = 0x00000004,   /* Hash-Only filtering mode */
   71         Pb              = 0x00000008,   /* Pass Bad frames */
   72         If              = 0x00000010,   /* Inverse Filtering */
   73         Sb              = 0x00000020,   /* Start/stop Backoff counter */
   74         Pr              = 0x00000040,   /* Promiscuous Mode */
   75         Pm              = 0x00000080,   /* Pass all Multicast */
   76         Fd              = 0x00000200,   /* Full Duplex mode */
   77         Om              = 0x00000C00,   /* Operating Mode (field) */
   78         Fc              = 0x00001000,   /* Force Collision */
   79         St              = 0x00002000,   /* Start/stop Transmission Command */
   80         Tr              = 0x0000C000,   /* ThReshold control bits (field) */
   81         Tr128           = 0x00000000,
   82         Tr256           = 0x00004000,
   83         Tr512           = 0x00008000,
   84         Tr1024          = 0x0000C000,
   85         Ca              = 0x00020000,   /* CApture effect enable */
   86         Ps              = 0x00040000,   /* Port Select */
   87         Hbd             = 0x00080000,   /* HeartBeat Disable */
   88         Imm             = 0x00100000,   /* IMMediate mode */
   89         Sf              = 0x00200000,   /* Store and Forward */
   90         Ttm             = 0x00400000,   /* Transmit Threshold Mode */
   91         Pcs             = 0x00800000,   /* PCS function */
   92         Scr             = 0x01000000,   /* SCRambler mode */
   93         Mbo             = 0x02000000,   /* Must Be One */
   94         Ra              = 0x40000000,   /* Receive All */
   95         Sc              = 0x80000000,   /* Special Capture effect enable */
   96 
   97         TrMODE          = Tr512,        /* default transmission threshold */
   98 };
   99 
  100 enum {                                  /* CSR9 - ROM and MII Management */
  101         Scs             = 0x00000001,   /* serial ROM chip select */
  102         Sclk            = 0x00000002,   /* serial ROM clock */
  103         Sdi             = 0x00000004,   /* serial ROM data in */
  104         Sdo             = 0x00000008,   /* serial ROM data out */
  105         Ss              = 0x00000800,   /* serial ROM select */
  106         Wr              = 0x00002000,   /* write */
  107         Rd              = 0x00004000,   /* read */
  108 
  109         Mdc             = 0x00010000,   /* MII management clock */
  110         Mdo             = 0x00020000,   /* MII management write data */
  111         Mii             = 0x00040000,   /* MII management operation mode (W) */
  112         Mdi             = 0x00080000,   /* MII management data in */
  113 };
  114 
  115 enum {                                  /* CSR12 - General-Purpose Port */
  116         Gpc             = 0x00000100,   /* General Purpose Control */
  117 };
  118 
  119 typedef struct Des {
  120         int     status;
  121         int     control;
  122         ulong   addr;
  123         Block*  bp;
  124 } Des;
  125 
  126 enum {                                  /* status */
  127         Of              = 0x00000001,   /* Rx: OverFlow */
  128         Ce              = 0x00000002,   /* Rx: CRC Error */
  129         Db              = 0x00000004,   /* Rx: Dribbling Bit */
  130         Re              = 0x00000008,   /* Rx: Report on MII Error */
  131         Rw              = 0x00000010,   /* Rx: Receive Watchdog */
  132         Ft              = 0x00000020,   /* Rx: Frame Type */
  133         Cs              = 0x00000040,   /* Rx: Collision Seen */
  134         Tl              = 0x00000080,   /* Rx: Frame too Long */
  135         Ls              = 0x00000100,   /* Rx: Last deScriptor */
  136         Fs              = 0x00000200,   /* Rx: First deScriptor */
  137         Mf              = 0x00000400,   /* Rx: Multicast Frame */
  138         Rf              = 0x00000800,   /* Rx: Runt Frame */
  139         Dt              = 0x00003000,   /* Rx: Data Type (field) */
  140         De              = 0x00004000,   /* Rx: Descriptor Error */
  141         Fl              = 0x3FFF0000,   /* Rx: Frame Length (field) */
  142         Ff              = 0x40000000,   /* Rx: Filtering Fail */
  143 
  144         Def             = 0x00000001,   /* Tx: DEFerred */
  145         Uf              = 0x00000002,   /* Tx: UnderFlow error */
  146         Lf              = 0x00000004,   /* Tx: Link Fail report */
  147         Cc              = 0x00000078,   /* Tx: Collision Count (field) */
  148         Hf              = 0x00000080,   /* Tx: Heartbeat Fail */
  149         Ec              = 0x00000100,   /* Tx: Excessive Collisions */
  150         Lc              = 0x00000200,   /* Tx: Late Collision */
  151         Nc              = 0x00000400,   /* Tx: No Carrier */
  152         Lo              = 0x00000800,   /* Tx: LOss of carrier */
  153         To              = 0x00004000,   /* Tx: Transmission jabber timeOut */
  154 
  155         Es              = 0x00008000,   /* [RT]x: Error Summary */
  156         Own             = 0x80000000,   /* [RT]x: OWN bit */
  157 };
  158 
  159 enum {                                  /* control */
  160         Bs1             = 0x000007FF,   /* [RT]x: Buffer 1 Size */
  161         Bs2             = 0x003FF800,   /* [RT]x: Buffer 2 Size */
  162 
  163         Ch              = 0x01000000,   /* [RT]x: second address CHained */
  164         Er              = 0x02000000,   /* [RT]x: End of Ring */
  165 
  166         Ft0             = 0x00400000,   /* Tx: Filtering Type 0 */
  167         Dpd             = 0x00800000,   /* Tx: Disabled PaDding */
  168         Ac              = 0x04000000,   /* Tx: Add CRC disable */
  169         Set             = 0x08000000,   /* Tx: SETup packet */
  170         Ft1             = 0x10000000,   /* Tx: Filtering Type 1 */
  171         Fseg            = 0x20000000,   /* Tx: First SEGment */
  172         Lseg            = 0x40000000,   /* Tx: Last SEGment */
  173         Ic              = 0x80000000,   /* Tx: Interrupt on Completion */
  174 };
  175 
  176 enum {                                  /* PHY registers */
  177         Bmcr            = 0,            /* Basic Mode Control */
  178         Bmsr            = 1,            /* Basic Mode Status */
  179         Phyidr1         = 2,            /* PHY Identifier #1 */
  180         Phyidr2         = 3,            /* PHY Identifier #2 */
  181         Anar            = 4,            /* Auto-Negotiation Advertisment */
  182         Anlpar          = 5,            /* Auto-Negotiation Link Partner Ability */
  183         Aner            = 6,            /* Auto-Negotiation Expansion */
  184 };
  185 
  186 enum {                                  /* Variants */
  187         Tulip0          = (0x0009<<16)|0x1011,
  188         Tulip1          = (0x0014<<16)|0x1011,
  189         Tulip3          = (0x0019<<16)|0x1011,
  190         Pnic            = (0x0002<<16)|0x11AD,
  191         Pnic2           = (0xC115<<16)|0x11AD,
  192         CentaurP        = (0x0985<<16)|0x1317,
  193         CentaurPcb      = (0x1985<<16)|0x1317,
  194 };
  195 
  196 typedef struct Ctlr Ctlr;
  197 typedef struct Ctlr {
  198         int     port;
  199         Pcidev* pcidev;
  200         Ctlr*   next;
  201         int     active;
  202         int     id;                     /* (pcidev->did<<16)|pcidev->vid */
  203 
  204         uchar*  srom;
  205         int     sromsz;                 /* address size in bits */
  206         uchar*  sromea;                 /* MAC address */
  207         uchar*  leaf;
  208         int     sct;                    /* selected connection type */
  209         int     k;                      /* info block count */
  210         uchar*  infoblock[16];
  211         int     sctk;                   /* sct block index */
  212         int     curk;                   /* current block index */
  213         uchar*  type5block;
  214 
  215         int     phy[32];                /* logical to physical map */
  216         int     phyreset;               /* reset bitmap */
  217         int     curphyad;
  218         int     fdx;
  219         int     ttm;
  220 
  221         uchar   fd;                     /* option */
  222         int     medium;                 /* option */
  223 
  224         int     csr6;                   /* CSR6 - operating mode */
  225         int     mask;                   /* CSR[57] - interrupt mask */
  226         int     mbps;
  227 
  228         Lock    lock;
  229 
  230         Des*    rdr;                    /* receive descriptor ring */
  231         int     nrdr;                   /* size of rdr */
  232         int     rdrx;                   /* index into rdr */
  233 
  234         Lock    tlock;
  235         Des*    tdr;                    /* transmit descriptor ring */
  236         int     ntdr;                   /* size of tdr */
  237         int     tdrh;                   /* host index into tdr */
  238         int     tdri;                   /* interface index into tdr */
  239         int     ntq;                    /* descriptors active */
  240         int     ntqmax;
  241         Block*  setupbp;
  242 
  243         ulong   of;                     /* receive statistics */
  244         ulong   ce;
  245         ulong   cs;
  246         ulong   tl;
  247         ulong   rf;
  248         ulong   de;
  249 
  250         ulong   ru;
  251         ulong   rps;
  252         ulong   rwt;
  253 
  254         ulong   uf;                     /* transmit statistics */
  255         ulong   ec;
  256         ulong   lc;
  257         ulong   nc;
  258         ulong   lo;
  259         ulong   to;
  260 
  261         ulong   tps;
  262         ulong   tu;
  263         ulong   tjt;
  264         ulong   unf;
  265 } Ctlr;
  266 
  267 static Ctlr* ctlrhead;
  268 static Ctlr* ctlrtail;
  269 
  270 #define csr32r(c, r)    (inl((c)->port+((r)*8)))
  271 #define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l)))
  272 
  273 static void
  274 promiscuous(void* arg, int on)
  275 {
  276         Ctlr *ctlr;
  277 
  278         ctlr = ((Ether*)arg)->ctlr;
  279         ilock(&ctlr->lock);
  280         if(on)
  281                 ctlr->csr6 |= Pr;
  282         else
  283                 ctlr->csr6 &= ~Pr;
  284         csr32w(ctlr, 6, ctlr->csr6);
  285         iunlock(&ctlr->lock);
  286 }
  287 
  288 /* multicast already on, don't need to do anything */
  289 static void
  290 multicast(void*, uchar*, int)
  291 {
  292 }
  293 
  294 static void
  295 attach(Ether* ether)
  296 {
  297         Ctlr *ctlr;
  298 
  299         ctlr = ether->ctlr;
  300         ilock(&ctlr->lock);
  301         if(!(ctlr->csr6 & Sr)){
  302                 ctlr->csr6 |= Sr;
  303                 csr32w(ctlr, 6, ctlr->csr6);
  304         }
  305         iunlock(&ctlr->lock);
  306 }
  307 
  308 static long
  309 ifstat(Ether* ether, void* a, long n, ulong offset)
  310 {
  311         Ctlr *ctlr;
  312         char *buf, *p;
  313         int i, l, len;
  314 
  315         ctlr = ether->ctlr;
  316 
  317         ether->crcs = ctlr->ce;
  318         ether->frames = ctlr->rf+ctlr->cs;
  319         ether->buffs = ctlr->de+ctlr->tl;
  320         ether->overflows = ctlr->of;
  321 
  322         if(n == 0)
  323                 return 0;
  324 
  325         p = malloc(READSTR);
  326         l = snprint(p, READSTR, "Overflow: %lud\n", ctlr->of);
  327         l += snprint(p+l, READSTR-l, "Ru: %lud\n", ctlr->ru);
  328         l += snprint(p+l, READSTR-l, "Rps: %lud\n", ctlr->rps);
  329         l += snprint(p+l, READSTR-l, "Rwt: %lud\n", ctlr->rwt);
  330         l += snprint(p+l, READSTR-l, "Tps: %lud\n", ctlr->tps);
  331         l += snprint(p+l, READSTR-l, "Tu: %lud\n", ctlr->tu);
  332         l += snprint(p+l, READSTR-l, "Tjt: %lud\n", ctlr->tjt);
  333         l += snprint(p+l, READSTR-l, "Unf: %lud\n", ctlr->unf);
  334         l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->ce);
  335         l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->cs);
  336         l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->tl);
  337         l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->rf);
  338         l += snprint(p+l, READSTR-l, "Descriptor Error: %lud\n", ctlr->de);
  339         l += snprint(p+l, READSTR-l, "Underflow Error: %lud\n", ctlr->uf);
  340         l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
  341         l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->lc);
  342         l += snprint(p+l, READSTR-l, "No Carrier: %lud\n", ctlr->nc);
  343         l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->lo);
  344         l += snprint(p+l, READSTR-l, "Transmit Jabber Timeout: %lud\n",
  345                 ctlr->to);
  346         l += snprint(p+l, READSTR-l, "csr6: %luX %uX\n", csr32r(ctlr, 6),
  347                 ctlr->csr6);
  348         snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
  349         ctlr->ntqmax = 0;
  350         buf = a;
  351         len = readstr(offset, buf, n, p);
  352         if(offset > l)
  353                 offset -= l;
  354         else
  355                 offset = 0;
  356         buf += len;
  357         n -= len;
  358 
  359         l = snprint(p, READSTR, "srom:");
  360         for(i = 0; i < (1<<(ctlr->sromsz)*sizeof(ushort)); i++){
  361                 if(i && ((i & 0x0F) == 0))
  362                         l += snprint(p+l, READSTR-l, "\n     ");
  363                 l += snprint(p+l, READSTR-l, " %2.2uX", ctlr->srom[i]);
  364         }
  365 
  366         snprint(p+l, READSTR-l, "\n");
  367         len += readstr(offset, buf, n, p);
  368         free(p);
  369 
  370         return len;
  371 }
  372 
  373 static void
  374 txstart(Ether* ether)
  375 {
  376         Ctlr *ctlr;
  377         Block *bp;
  378         Des *des;
  379         int control;
  380 
  381         ctlr = ether->ctlr;
  382         while(ctlr->ntq < (ctlr->ntdr-1)){
  383                 if(ctlr->setupbp){
  384                         bp = ctlr->setupbp;
  385                         ctlr->setupbp = 0;
  386                         control = Ic|Set|BLEN(bp);
  387                 }
  388                 else{
  389                         bp = qget(ether->oq);
  390                         if(bp == nil)
  391                                 break;
  392                         control = Ic|Lseg|Fseg|BLEN(bp);
  393                 }
  394 
  395                 ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
  396                 des = &ctlr->tdr[ctlr->tdrh];
  397                 des->bp = bp;
  398                 des->addr = PCIWADDR(bp->rp);
  399                 des->control |= control;
  400                 ctlr->ntq++;
  401                 coherence();
  402                 des->status = Own;
  403                 csr32w(ctlr, 1, 0);
  404                 ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
  405         }
  406 
  407         if(ctlr->ntq > ctlr->ntqmax)
  408                 ctlr->ntqmax = ctlr->ntq;
  409 }
  410 
  411 static void
  412 transmit(Ether* ether)
  413 {
  414         Ctlr *ctlr;
  415 
  416         ctlr = ether->ctlr;
  417         ilock(&ctlr->tlock);
  418         txstart(ether);
  419         iunlock(&ctlr->tlock);
  420 }
  421 
  422 static void
  423 interrupt(Ureg*, void* arg)
  424 {
  425         Ctlr *ctlr;
  426         Ether *ether;
  427         int len, status;
  428         Des *des;
  429         Block *bp;
  430 
  431         ether = arg;
  432         ctlr = ether->ctlr;
  433 
  434         while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
  435                 /*
  436                  * Acknowledge the interrupts and mask-out
  437                  * the ones that are implicitly handled.
  438                  */
  439                 csr32w(ctlr, 5, status);
  440                 status &= (ctlr->mask & ~(Nis|Ti));
  441 
  442                 if(status & Ais){
  443                         if(status & Tps)
  444                                 ctlr->tps++;
  445                         if(status & Tu)
  446                                 ctlr->tu++;
  447                         if(status & Tjt)
  448                                 ctlr->tjt++;
  449                         if(status & Ru)
  450                                 ctlr->ru++;
  451                         if(status & Rps)
  452                                 ctlr->rps++;
  453                         if(status & Rwt)
  454                                 ctlr->rwt++;
  455                         status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps);
  456                 }
  457 
  458                 /*
  459                  * Received packets.
  460                  */
  461                 if(status & Ri){
  462                         des = &ctlr->rdr[ctlr->rdrx];
  463                         while(!(des->status & Own)){
  464                                 if(des->status & Es){
  465                                         if(des->status & Of)
  466                                                 ctlr->of++;
  467                                         if(des->status & Ce)
  468                                                 ctlr->ce++;
  469                                         if(des->status & Cs)
  470                                                 ctlr->cs++;
  471                                         if(des->status & Tl)
  472                                                 ctlr->tl++;
  473                                         if(des->status & Rf)
  474                                                 ctlr->rf++;
  475                                         if(des->status & De)
  476                                                 ctlr->de++;
  477                                 }
  478                                 else if(bp = iallocb(Rbsz)){
  479                                         len = ((des->status & Fl)>>16)-4;
  480                                         des->bp->wp = des->bp->rp+len;
  481                                         etheriq(ether, des->bp, 1);
  482                                         des->bp = bp;
  483                                         des->addr = PCIWADDR(bp->rp);
  484                                 }
  485 
  486                                 des->control &= Er;
  487                                 des->control |= Rbsz;
  488                                 coherence();
  489                                 des->status = Own;
  490 
  491                                 ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
  492                                 des = &ctlr->rdr[ctlr->rdrx];
  493                         }
  494                         status &= ~Ri;
  495                 }
  496 
  497                 /*
  498                  * Check the transmit side:
  499                  *      check for Transmit Underflow and Adjust
  500                  *      the threshold upwards;
  501                  *      free any transmitted buffers and try to
  502                  *      top-up the ring.
  503                  */
  504                 if(status & Unf){
  505                         ctlr->unf++;
  506                         ilock(&ctlr->lock);
  507                         csr32w(ctlr, 6, ctlr->csr6 & ~St);
  508                         switch(ctlr->csr6 & Tr){
  509                         case Tr128:
  510                                 len = Tr256;
  511                                 break;
  512                         case Tr256:
  513                                 len = Tr512;
  514                                 break;
  515                         case Tr512:
  516                                 len = Tr1024;
  517                                 break;
  518                         default:
  519                         case Tr1024:
  520                                 len = Sf;
  521                                 break;
  522                         }
  523                         ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
  524                         csr32w(ctlr, 6, ctlr->csr6);
  525                         iunlock(&ctlr->lock);
  526                         csr32w(ctlr, 5, Tps);
  527                         status &= ~(Unf|Tps);
  528                 }
  529 
  530                 ilock(&ctlr->tlock);
  531                 while(ctlr->ntq){
  532                         des = &ctlr->tdr[ctlr->tdri];
  533                         if(des->status & Own)
  534                                 break;
  535 
  536                         if(des->status & Es){
  537                                 if(des->status & Uf)
  538                                         ctlr->uf++;
  539                                 if(des->status & Ec)
  540                                         ctlr->ec++;
  541                                 if(des->status & Lc)
  542                                         ctlr->lc++;
  543                                 if(des->status & Nc)
  544                                         ctlr->nc++;
  545                                 if(des->status & Lo)
  546                                         ctlr->lo++;
  547                                 if(des->status & To)
  548                                         ctlr->to++;
  549                                 ether->oerrs++;
  550                         }
  551 
  552                         freeb(des->bp);
  553                         des->control &= Er;
  554 
  555                         ctlr->ntq--;
  556                         ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
  557                 }
  558                 txstart(ether);
  559                 iunlock(&ctlr->tlock);
  560 
  561                 /*
  562                  * Anything left not catered for?
  563                  */
  564                 if(status)
  565                         panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
  566         }
  567 }
  568 
  569 static void
  570 ctlrinit(Ether* ether)
  571 {
  572         Ctlr *ctlr;
  573         Des *des;
  574         Block *bp;
  575         int i;
  576         uchar bi[Eaddrlen*2];
  577 
  578         ctlr = ether->ctlr;
  579 
  580         /*
  581          * Allocate and initialise the receive ring;
  582          * allocate and initialise the transmit ring;
  583          * unmask interrupts and start the transmit side;
  584          * create and post a setup packet to initialise
  585          * the physical ethernet address.
  586          */
  587         ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0);
  588         for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
  589                 des->bp = iallocb(Rbsz);
  590                 if(des->bp == nil)
  591                         panic("can't allocate ethernet receive ring\n");
  592                 des->status = Own;
  593                 des->control = Rbsz;
  594                 des->addr = PCIWADDR(des->bp->rp);
  595         }
  596         ctlr->rdr[ctlr->nrdr-1].control |= Er;
  597         ctlr->rdrx = 0;
  598         csr32w(ctlr, 3, PCIWADDR(ctlr->rdr));
  599 
  600         ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
  601         ctlr->tdr[ctlr->ntdr-1].control |= Er;
  602         ctlr->tdrh = 0;
  603         ctlr->tdri = 0;
  604         csr32w(ctlr, 4, PCIWADDR(ctlr->tdr));
  605 
  606         /*
  607          * Clear any bits in the Status Register (CSR5) as
  608          * the PNIC has a different reset value from a true 2114x.
  609          */
  610         ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
  611         csr32w(ctlr, 5, ctlr->mask);
  612         csr32w(ctlr, 7, ctlr->mask);
  613         ctlr->csr6 |= St|Pm;
  614         csr32w(ctlr, 6, ctlr->csr6);
  615 
  616         for(i = 0; i < Eaddrlen/2; i++){
  617                 bi[i*4] = ether->ea[i*2];
  618                 bi[i*4+1] = ether->ea[i*2+1];
  619                 bi[i*4+2] = ether->ea[i*2+1];
  620                 bi[i*4+3] = ether->ea[i*2];
  621         }
  622         bp = iallocb(Eaddrlen*2*16);
  623         if(bp == nil)
  624                 panic("can't allocate ethernet setup buffer\n");
  625         memset(bp->rp, 0xFF, sizeof(bi));
  626         for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
  627                 memmove(bp->rp+i, bi, sizeof(bi));
  628         bp->wp += sizeof(bi)*16;
  629 
  630         ctlr->setupbp = bp;
  631         ether->oq = qopen(256*1024, Qmsg, 0, 0);
  632         transmit(ether);
  633 }
  634 
  635 static void
  636 csr9w(Ctlr* ctlr, int data)
  637 {
  638         csr32w(ctlr, 9, data);
  639         microdelay(1);
  640 }
  641 
  642 static int
  643 miimdi(Ctlr* ctlr, int n)
  644 {
  645         int data, i;
  646 
  647         /*
  648          * Read n bits from the MII Management Register.
  649          */
  650         data = 0;
  651         for(i = n-1; i >= 0; i--){
  652                 if(csr32r(ctlr, 9) & Mdi)
  653                         data |= (1<<i);
  654                 csr9w(ctlr, Mii|Mdc);
  655                 csr9w(ctlr, Mii);
  656         }
  657         csr9w(ctlr, 0);
  658 
  659         return data;
  660 }
  661 
  662 static void
  663 miimdo(Ctlr* ctlr, int bits, int n)
  664 {
  665         int i, mdo;
  666 
  667         /*
  668          * Write n bits to the MII Management Register.
  669          */
  670         for(i = n-1; i >= 0; i--){
  671                 if(bits & (1<<i))
  672                         mdo = Mdo;
  673                 else
  674                         mdo = 0;
  675                 csr9w(ctlr, mdo);
  676                 csr9w(ctlr, mdo|Mdc);
  677                 csr9w(ctlr, mdo);
  678         }
  679 }
  680 
  681 static int
  682 miir(Ctlr* ctlr, int phyad, int regad)
  683 {
  684         int data, i;
  685 
  686         if(ctlr->id == Pnic){
  687                 i = 1000;
  688                 csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
  689                 do{
  690                         microdelay(1);
  691                         data = csr32r(ctlr, 20);
  692                 }while((data & 0x80000000) && --i);
  693 
  694                 if(i == 0)
  695                         return -1;
  696                 return data & 0xFFFF;
  697         }
  698 
  699         /*
  700          * Preamble;
  701          * ST+OP+PHYAD+REGAD;
  702          * TA + 16 data bits.
  703          */
  704         miimdo(ctlr, 0xFFFFFFFF, 32);
  705         miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
  706         data = miimdi(ctlr, 18);
  707 
  708         if(data & 0x10000)
  709                 return -1;
  710 
  711         return data & 0xFFFF;
  712 }
  713 
  714 static void
  715 miiw(Ctlr* ctlr, int phyad, int regad, int data)
  716 {
  717         /*
  718          * Preamble;
  719          * ST+OP+PHYAD+REGAD+TA + 16 data bits;
  720          * Z.
  721          */
  722         miimdo(ctlr, 0xFFFFFFFF, 32);
  723         data &= 0xFFFF;
  724         data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
  725         miimdo(ctlr, data, 32);
  726         csr9w(ctlr, Mdc);
  727         csr9w(ctlr, 0);
  728 }
  729 
  730 static int
  731 sromr(Ctlr* ctlr, int r)
  732 {
  733         int i, op, data, size;
  734 
  735         if(ctlr->id == Pnic){
  736                 i = 1000;
  737                 csr32w(ctlr, 19, 0x600|r);
  738                 do{
  739                         microdelay(1);
  740                         data = csr32r(ctlr, 19);
  741                 }while((data & 0x80000000) && --i);
  742 
  743                 if(ctlr->sromsz == 0)
  744                         ctlr->sromsz = 6;
  745 
  746                 return csr32r(ctlr, 9) & 0xFFFF;
  747         }
  748 
  749         /*
  750          * This sequence for reading a 16-bit register 'r'
  751          * in the EEPROM is taken (pretty much) straight from Section
  752          * 7.4 of the 21140 Hardware Reference Manual.
  753          */
  754 reread:
  755         csr9w(ctlr, Rd|Ss);
  756         csr9w(ctlr, Rd|Ss|Scs);
  757         csr9w(ctlr, Rd|Ss|Sclk|Scs);
  758         csr9w(ctlr, Rd|Ss);
  759 
  760         op = 0x06;
  761         for(i = 3-1; i >= 0; i--){
  762                 data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
  763                 csr9w(ctlr, data);
  764                 csr9w(ctlr, data|Sclk);
  765                 csr9w(ctlr, data);
  766         }
  767 
  768         /*
  769          * First time through must work out the EEPROM size.
  770          * This doesn't seem to work on the 21041 as implemented
  771          * in Virtual PC for the Mac, so wire any 21041 to 6,
  772          * it's the only 21041 this code will ever likely see.
  773          */
  774         if((size = ctlr->sromsz) == 0){
  775                 if(ctlr->id == Tulip1)
  776                         ctlr->sromsz = size = 6;
  777                 else
  778                         size = 8;
  779         }
  780 
  781         for(size = size-1; size >= 0; size--){
  782                 data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
  783                 csr9w(ctlr, data);
  784                 csr9w(ctlr, data|Sclk);
  785                 csr9w(ctlr, data);
  786                 microdelay(1);
  787                 if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
  788                         break;
  789         }
  790 
  791         data = 0;
  792         for(i = 16-1; i >= 0; i--){
  793                 csr9w(ctlr, Rd|Ss|Sclk|Scs);
  794                 if(csr32r(ctlr, 9) & Sdo)
  795                         data |= (1<<i);
  796                 csr9w(ctlr, Rd|Ss|Scs);
  797         }
  798 
  799         csr9w(ctlr, 0);
  800 
  801         if(ctlr->sromsz == 0){
  802                 ctlr->sromsz = 8-size;
  803                 goto reread;
  804         }
  805 
  806         return data & 0xFFFF;
  807 }
  808 
  809 static void
  810 shutdown(Ether* ether)
  811 {
  812         Ctlr *ctlr = ether->ctlr;
  813 
  814 print("ether2114x shutting down\n");
  815         csr32w(ctlr, 0, Swr);
  816 }
  817 
  818 static void
  819 softreset(Ctlr* ctlr)
  820 {
  821         /*
  822          * Soft-reset the controller and initialise bus mode.
  823          * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
  824          */
  825         csr32w(ctlr, 0, Swr);
  826         microdelay(10);
  827         csr32w(ctlr, 0, Rml|Cal16);
  828         delay(1);
  829 }
  830 
  831 static int
  832 type5block(Ctlr* ctlr, uchar* block)
  833 {
  834         int csr15, i, len;
  835 
  836         /*
  837          * Reset or GPR sequence. Reset should be once only,
  838          * before the GPR sequence.
  839          * Note 'block' is not a pointer to the block head but
  840          * a pointer to the data in the block starting at the
  841          * reset length value so type5block can be used for the
  842          * sequences contained in type 1 and type 3 blocks.
  843          * The SROM docs state the 21140 type 5 block is the
  844          * same as that for the 21143, but the two controllers
  845          * use different registers and sequence-element lengths
  846          * so the 21140 code here is a guess for a real type 5
  847          * sequence.
  848          */
  849         len = *block++;
  850         if(ctlr->id != Tulip3){
  851                 for(i = 0; i < len; i++){
  852                         csr32w(ctlr, 12, *block);
  853                         block++;
  854                 }
  855                 return len;
  856         }
  857 
  858         for(i = 0; i < len; i++){
  859                 csr15 = *block++<<16;
  860                 csr15 |= *block++<<24;
  861                 csr32w(ctlr, 15, csr15);
  862                 debug("%8.8uX ", csr15);
  863         }
  864         return 2*len;
  865 }
  866 
  867 static int
  868 typephylink(Ctlr* ctlr, uchar*)
  869 {
  870         int an, bmcr, bmsr, csr6, x;
  871 
  872         /*
  873          * Fail if
  874          *      auto-negotiataion enabled but not complete;
  875          *      no valid link established.
  876          */
  877         bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
  878         miir(ctlr, ctlr->curphyad, Bmsr);
  879         bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
  880         debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
  881         if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
  882                 return 0;
  883 
  884         if(bmcr & 0x1000){
  885                 an = miir(ctlr, ctlr->curphyad, Anar);
  886                 an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
  887                 debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
  888                         miir(ctlr, ctlr->curphyad, Anar),
  889                         miir(ctlr, ctlr->curphyad, Anlpar),
  890                         an);
  891         
  892                 if(an & 0x0100)
  893                         x = 0x4000;
  894                 else if(an & 0x0080)
  895                         x = 0x2000;
  896                 else if(an & 0x0040)
  897                         x = 0x1000;
  898                 else if(an & 0x0020)
  899                         x = 0x0800;
  900                 else
  901                         x = 0;
  902         }
  903         else if((bmcr & 0x2100) == 0x2100)
  904                 x = 0x4000;
  905         else if(bmcr & 0x2000){
  906                 /*
  907                  * If FD capable, force it if necessary.
  908                  */
  909                 if((bmsr & 0x4000) && ctlr->fd){
  910                         miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
  911                         x = 0x4000;
  912                 }
  913                 else
  914                         x = 0x2000;
  915         }
  916         else if(bmcr & 0x0100)
  917                 x = 0x1000;
  918         else
  919                 x = 0x0800;
  920 
  921         csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
  922         if(ctlr->fdx & x)
  923                 csr6 |= Fd;
  924         if(ctlr->ttm & x)
  925                 csr6 |= Ttm;
  926         debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
  927                 csr6, ctlr->csr6, csr32r(ctlr, 6));
  928         if(csr6 != ctlr->csr6){
  929                 ctlr->csr6 = csr6;
  930                 csr32w(ctlr, 6, csr6);
  931         }
  932 
  933         return 1;
  934 }
  935 
  936 static int
  937 typephymode(Ctlr* ctlr, uchar* block, int wait)
  938 {
  939         uchar *p;
  940         int len, mc, nway, phyx, timeo;
  941 
  942         if(DEBUG){
  943                 int i;
  944 
  945                 len = (block[0] & ~0x80)+1;
  946                 for(i = 0; i < len; i++)
  947                         debug("%2.2uX ", block[i]);
  948                 debug("\n");
  949         }
  950 
  951         if(block[1] == 1)
  952                 len = 1;
  953         else if(block[1] == 3)
  954                 len = 2;
  955         else
  956                 return -1;
  957 
  958         /*
  959          * Snarf the media capabilities, nway advertisment,
  960          * FDX and TTM bitmaps.
  961          */
  962         p = &block[5+len*block[3]+len*block[4+len*block[3]]];
  963         mc = *p++;
  964         mc |= *p++<<8;
  965         nway = *p++;
  966         nway |= *p++<<8;
  967         ctlr->fdx = *p++;
  968         ctlr->fdx |= *p++<<8;
  969         ctlr->ttm = *p++;
  970         ctlr->ttm |= *p<<8;
  971         debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
  972                 mc, nway, ctlr->fdx, ctlr->ttm);
  973         USED(mc);
  974 
  975         phyx = block[2];
  976         ctlr->curphyad = ctlr->phy[phyx];
  977 
  978         ctlr->csr6 = 0;         /* Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; */
  979         // csr32w(ctlr, 6, ctlr->csr6);
  980         if(typephylink(ctlr, block))
  981                 return 0;
  982 
  983         if(!(ctlr->phyreset & (1<<phyx))){
  984                 debug("reset seq: len %d: ", block[3]);
  985                 if(ctlr->type5block)
  986                         type5block(ctlr, &ctlr->type5block[2]);
  987                 else
  988                         type5block(ctlr, &block[4+len*block[3]]);
  989                 debug("\n");
  990                 ctlr->phyreset |= (1<<phyx);
  991         }
  992 
  993         /*
  994          * GPR sequence.
  995          */
  996         debug("gpr seq: len %d: ", block[3]);
  997         type5block(ctlr, &block[3]);
  998         debug("\n");
  999 
 1000         ctlr->csr6 = 0;         /* Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; */
 1001         // csr32w(ctlr, 6, ctlr->csr6);
 1002         if(typephylink(ctlr, block))
 1003                 return 0;
 1004 
 1005         /*
 1006          * Turn off auto-negotiation, set the auto-negotiation
 1007          * advertisment register then start the auto-negotiation
 1008          * process again.
 1009          */
 1010         miiw(ctlr, ctlr->curphyad, Bmcr, 0);
 1011         miiw(ctlr, ctlr->curphyad, Anar, nway|1);
 1012         miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
 1013 
 1014         if(!wait)
 1015                 return 0;
 1016 
 1017         for(timeo = 0; timeo < 45; timeo++){
 1018                 if(typephylink(ctlr, block))
 1019                         return 0;
 1020                 delay(100);
 1021         }
 1022 
 1023         return -1;
 1024 }
 1025 
 1026 static int
 1027 typesymmode(Ctlr *ctlr, uchar *block, int wait)
 1028 {
 1029         uint gpmode, gpdata, command;
 1030 
 1031         USED(wait);
 1032         gpmode = block[3] | ((uint) block[4] << 8);
 1033         gpdata = block[5] | ((uint) block[6] << 8);
 1034         command = (block[7] | ((uint) block[8] << 8)) & 0x71;
 1035         if (command & 0x8000) {
 1036                 print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
 1037                 return -1;
 1038         }
 1039         csr32w(ctlr, 15, gpmode);
 1040         csr32w(ctlr, 15, gpdata);
 1041         ctlr->csr6 = (command & 0x71) << 18;
 1042         csr32w(ctlr, 6, ctlr->csr6);
 1043         return 0;
 1044 }
 1045 
 1046 static int
 1047 type2mode(Ctlr* ctlr, uchar* block, int)
 1048 {
 1049         uchar *p;
 1050         int csr6, csr13, csr14, csr15, gpc, gpd;
 1051 
 1052         csr6 = Sc|Mbo|Ca|TrMODE|Sb;
 1053         debug("type2mode: medium 0x%2.2uX\n", block[2]);
 1054 
 1055         /*
 1056          * Don't attempt full-duplex
 1057          * unless explicitly requested.
 1058          */
 1059         if((block[2] & 0x3F) == 0x04){  /* 10BASE-TFD */
 1060                 if(!ctlr->fd)
 1061                         return -1;
 1062                 csr6 |= Fd;
 1063         }
 1064 
 1065         /*
 1066          * Operating mode programming values from the datasheet
 1067          * unless media specific data is explicitly given.
 1068          */
 1069         p = &block[3];
 1070         if(block[2] & 0x40){
 1071                 csr13 = (block[4]<<8)|block[3];
 1072                 csr14 = (block[6]<<8)|block[5];
 1073                 csr15 = (block[8]<<8)|block[7];
 1074                 p += 6;
 1075         }
 1076         else switch(block[2] & 0x3F){
 1077         default:
 1078                 return -1;
 1079         case 0x00:                      /* 10BASE-T */
 1080                 csr13 = 0x00000001;
 1081                 csr14 = 0x00007F3F;
 1082                 csr15 = 0x00000008;
 1083                 break;
 1084         case 0x01:                      /* 10BASE-2 */
 1085                 csr13 = 0x00000009;
 1086                 csr14 = 0x00000705;
 1087                 csr15 = 0x00000006;
 1088                 break;
 1089         case 0x02:                      /* 10BASE-5 (AUI) */
 1090                 csr13 = 0x00000009;
 1091                 csr14 = 0x00000705;
 1092                 csr15 = 0x0000000E;
 1093                 break;
 1094         case 0x04:                      /* 10BASE-TFD */
 1095                 csr13 = 0x00000001;
 1096                 csr14 = 0x00007F3D;
 1097                 csr15 = 0x00000008;
 1098                 break;
 1099         }
 1100         gpc = *p++<<16;
 1101         gpc |= *p++<<24;
 1102         gpd = *p++<<16;
 1103         gpd |= *p<<24;
 1104 
 1105         csr32w(ctlr, 13, 0);
 1106         csr32w(ctlr, 14, csr14);
 1107         csr32w(ctlr, 15, gpc|csr15);
 1108         delay(10);
 1109         csr32w(ctlr, 15, gpd|csr15);
 1110         csr32w(ctlr, 13, csr13);
 1111 
 1112         ctlr->csr6 = csr6;
 1113         csr32w(ctlr, 6, ctlr->csr6);
 1114 
 1115         debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
 1116                 csr13, csr14, csr15);
 1117         debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
 1118                 gpc, gpd, csr6);
 1119 
 1120         return 0;
 1121 }
 1122 
 1123 static int
 1124 type0link(Ctlr* ctlr, uchar* block)
 1125 {
 1126         int m, polarity, sense;
 1127 
 1128         m = (block[3]<<8)|block[2];
 1129         sense = 1<<((m & 0x000E)>>1);
 1130         if(m & 0x0080)
 1131                 polarity = sense;
 1132         else
 1133                 polarity = 0;
 1134 
 1135         return (csr32r(ctlr, 12) & sense)^polarity;
 1136 }
 1137 
 1138 static int
 1139 type0mode(Ctlr* ctlr, uchar* block, int wait)
 1140 {
 1141         int csr6, m, timeo;
 1142 
 1143         csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
 1144 debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
 1145     ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); 
 1146         switch(block[0]){
 1147         default:
 1148                 break;
 1149 
 1150         case 0x04:                      /* 10BASE-TFD */
 1151         case 0x05:                      /* 100BASE-TXFD */
 1152         case 0x08:                      /* 100BASE-FXFD */
 1153                 /*
 1154                  * Don't attempt full-duplex
 1155                  * unless explicitly requested.
 1156                  */
 1157                 if(!ctlr->fd)
 1158                         return -1;
 1159                 csr6 |= Fd;
 1160                 break;
 1161         }
 1162 
 1163         m = (block[3]<<8)|block[2];
 1164         if(m & 0x0001)
 1165                 csr6 |= Ps;
 1166         if(m & 0x0010)
 1167                 csr6 |= Ttm;
 1168         if(m & 0x0020)
 1169                 csr6 |= Pcs;
 1170         if(m & 0x0040)
 1171                 csr6 |= Scr;
 1172 
 1173         csr32w(ctlr, 12, block[1]);
 1174         microdelay(10);
 1175         csr32w(ctlr, 6, csr6);
 1176         ctlr->csr6 = csr6;
 1177 
 1178         if(!wait)
 1179                 return 0;
 1180 
 1181         for(timeo = 0; timeo < 30; timeo++){
 1182                 if(type0link(ctlr, block))
 1183                         return 0;
 1184                 delay(100);
 1185         }
 1186 
 1187         return -1;
 1188 }
 1189 
 1190 static int
 1191 media21041(Ether* ether, int wait)
 1192 {
 1193         Ctlr* ctlr;
 1194         uchar *block;
 1195         int csr6, csr13, csr14, csr15, medium, timeo;
 1196 
 1197         ctlr = ether->ctlr;
 1198         block = ctlr->infoblock[ctlr->curk];
 1199         debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
 1200                 block[0], ctlr->medium, ctlr->sct);
 1201 
 1202         medium = block[0] & 0x3F;
 1203         if(ctlr->medium >= 0 && medium != ctlr->medium)
 1204                 return 0;
 1205         if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
 1206                 return 0;
 1207 
 1208         csr6 = Sc|Mbo|Ca|TrMODE|Sb;
 1209         if(block[0] & 0x40){
 1210                 csr13 = (block[2]<<8)|block[1];
 1211                 csr14 = (block[4]<<8)|block[3];
 1212                 csr15 = (block[6]<<8)|block[5];
 1213         }
 1214         else switch(medium){
 1215         default:
 1216                 return -1;
 1217         case 0x00:              /* 10BASE-T */
 1218                 csr13 = 0xEF01;
 1219                 csr14 = 0xFF3F;
 1220                 csr15 = 0x0008;
 1221                 break;
 1222         case 0x01:              /* 10BASE-2 */
 1223                 csr13 = 0xEF09;
 1224                 csr14 = 0xF73D;
 1225                 csr15 = 0x0006;
 1226                 break;
 1227         case 0x02:              /* 10BASE-5 */
 1228                 csr13 = 0xEF09;
 1229                 csr14 = 0xF73D;
 1230                 csr15 = 0x000E;
 1231                 break;
 1232         case 0x04:              /* 10BASE-TFD */
 1233                 csr13 = 0xEF01;
 1234                 csr14 = 0xFF3D;
 1235                 csr15 = 0x0008;
 1236                 break;
 1237         }
 1238 
 1239         csr32w(ctlr, 13, 0);
 1240         csr32w(ctlr, 14, csr14);
 1241         csr32w(ctlr, 15, csr15);
 1242         csr32w(ctlr, 13, csr13);
 1243         delay(10);
 1244 
 1245         if(medium == 0x04)
 1246                 csr6 |= Fd;
 1247         ctlr->csr6 = csr6;
 1248         csr32w(ctlr, 6, ctlr->csr6);
 1249 
 1250         debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
 1251                 csr6, csr13, csr14, csr15);
 1252 
 1253         if(!wait)
 1254                 return 0;
 1255 
 1256         for(timeo = 0; timeo < 30; timeo++){
 1257                 if(!(csr32r(ctlr, 12) & 0x0002)){
 1258                         debug("media21041: ok: csr12 %4.4luX timeo %d\n",
 1259                                 csr32r(ctlr, 12), timeo);
 1260                         return 10;
 1261                 }
 1262                 delay(100);
 1263         }
 1264         debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
 1265 
 1266         return -1;
 1267 }
 1268 
 1269 static int
 1270 mediaxx(Ether* ether, int wait)
 1271 {
 1272         Ctlr* ctlr;
 1273         uchar *block;
 1274 
 1275         ctlr = ether->ctlr;
 1276         block = ctlr->infoblock[ctlr->curk];
 1277         if(block[0] & 0x80){
 1278                 switch(block[1]){
 1279                 default:
 1280                         return -1;
 1281                 case 0:
 1282                         if(ctlr->medium >= 0 && block[2] != ctlr->medium)
 1283                                 return 0;
 1284 /* need this test? */   if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
 1285                                 return 0;
 1286                         if(type0mode(ctlr, block+2, wait))
 1287                                 return 0;
 1288                         break;
 1289                 case 1:
 1290                         if(typephymode(ctlr, block, wait))
 1291                                 return 0;
 1292                         break;
 1293                 case 2:
 1294                         debug("type2: medium %d block[2] %d\n",
 1295                                 ctlr->medium, block[2]);
 1296                         if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
 1297                                 return 0;
 1298                         if(type2mode(ctlr, block, wait))
 1299                                 return 0;
 1300                         break;
 1301                 case 3:
 1302                         if(typephymode(ctlr, block, wait))
 1303                                 return 0;
 1304                         break;
 1305                 case 4:
 1306                         debug("type4: medium %d block[2] %d\n",
 1307                                 ctlr->medium, block[2]);
 1308                         if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
 1309                                 return 0;
 1310                         if(typesymmode(ctlr, block, wait))
 1311                                 return 0;
 1312                         break;
 1313                 }
 1314         }
 1315         else{
 1316                 if(ctlr->medium >= 0 && block[0] != ctlr->medium)
 1317                         return 0;
 1318 /* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
 1319                         return 0;
 1320                 if(type0mode(ctlr, block, wait))
 1321                         return 0;
 1322         }
 1323 
 1324         if(ctlr->csr6){
 1325                 if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
 1326                         return 10;
 1327                 return 100;
 1328         }
 1329 
 1330         return 0;
 1331 }
 1332 
 1333 static int
 1334 media(Ether* ether, int wait)
 1335 {
 1336         Ctlr* ctlr;
 1337         int k, mbps;
 1338 
 1339         ctlr = ether->ctlr;
 1340         for(k = 0; k < ctlr->k; k++){
 1341                 switch(ctlr->id){
 1342                 default:
 1343                         mbps = mediaxx(ether, wait);
 1344                         break;
 1345                 case Tulip1:                    /* 21041 */
 1346                         mbps = media21041(ether, wait);
 1347                         break;
 1348                 }
 1349                 if(mbps > 0)
 1350                         return mbps;
 1351                 if(ctlr->curk == 0)
 1352                         ctlr->curk = ctlr->k-1;
 1353                 else
 1354                         ctlr->curk--;
 1355         }
 1356 
 1357         return 0;
 1358 }
 1359 
 1360 static char* mediatable[9] = {
 1361         "10BASE-T",                             /* TP */
 1362         "10BASE-2",                             /* BNC */
 1363         "10BASE-5",                             /* AUI */
 1364         "100BASE-TX",
 1365         "10BASE-TFD",
 1366         "100BASE-TXFD",
 1367         "100BASE-T4",
 1368         "100BASE-FX",
 1369         "100BASE-FXFD",
 1370 };
 1371 
 1372 static uchar en1207[] = {               /* Accton EN1207-COMBO */
 1373         0x00, 0x00, 0xE8,               /* [0]  vendor ethernet code */
 1374         0x00,                           /* [3]  spare */
 1375 
 1376         0x00, 0x08,                     /* [4]  connection (LSB+MSB = 0x0800) */
 1377         0x1F,                           /* [6]  general purpose control */
 1378         2,                              /* [7]  block count */
 1379 
 1380         0x00,                           /* [8]  media code (10BASE-TX) */
 1381         0x0B,                           /* [9]  general purpose port data */
 1382         0x9E, 0x00,                     /* [10] command (LSB+MSB = 0x009E) */
 1383 
 1384         0x03,                           /* [8]  media code (100BASE-TX) */
 1385         0x1B,                           /* [9]  general purpose port data */
 1386         0x6D, 0x00,                     /* [10] command (LSB+MSB = 0x006D) */
 1387 
 1388                                         /* There is 10BASE-2 as well, but... */
 1389 };
 1390 
 1391 static uchar ana6910fx[] = {            /* Adaptec (Cogent) ANA-6910FX */
 1392         0x00, 0x00, 0x92,               /* [0]  vendor ethernet code */
 1393         0x00,                           /* [3]  spare */
 1394 
 1395         0x00, 0x08,                     /* [4]  connection (LSB+MSB = 0x0800) */
 1396         0x3F,                           /* [6]  general purpose control */
 1397         1,                              /* [7]  block count */
 1398 
 1399         0x07,                           /* [8]  media code (100BASE-FX) */
 1400         0x03,                           /* [9]  general purpose port data */
 1401         0x2D, 0x00                      /* [10] command (LSB+MSB = 0x000D) */
 1402 };
 1403 
 1404 static uchar smc9332[] = {              /* SMC 9332 */
 1405         0x00, 0x00, 0xC0,               /* [0]  vendor ethernet code */
 1406         0x00,                           /* [3]  spare */
 1407 
 1408         0x00, 0x08,                     /* [4]  connection (LSB+MSB = 0x0800) */
 1409         0x1F,                           /* [6]  general purpose control */
 1410         2,                              /* [7]  block count */
 1411 
 1412         0x00,                           /* [8]  media code (10BASE-TX) */
 1413         0x00,                           /* [9]  general purpose port data */
 1414         0x9E, 0x00,                     /* [10] command (LSB+MSB = 0x009E) */
 1415 
 1416         0x03,                           /* [8]  media code (100BASE-TX) */
 1417         0x09,                           /* [9]  general purpose port data */
 1418         0x6D, 0x00,                     /* [10] command (LSB+MSB = 0x006D) */
 1419 };
 1420 
 1421 static uchar* leaf21140[] = {
 1422         en1207,                         /* Accton EN1207-COMBO */
 1423         ana6910fx,                      /* Adaptec (Cogent) ANA-6910FX */
 1424         smc9332,                        /* SMC 9332 */
 1425         nil,
 1426 };
 1427 
 1428 /*
 1429  * Copied to ctlr->srom at offset 20.
 1430  */
 1431 static uchar leafpnic[] = {
 1432         0x00, 0x00, 0x00, 0x00,         /* MAC address */
 1433         0x00, 0x00,
 1434         0x00,                           /* controller 0 device number */
 1435         0x1E, 0x00,                     /* controller 0 info leaf offset */
 1436         0x00,                           /* reserved */
 1437         0x00, 0x08,                     /* selected connection type */
 1438         0x00,                           /* general purpose control */
 1439         0x01,                           /* block count */
 1440 
 1441         0x8C,                           /* format indicator and count */
 1442         0x01,                           /* block type */
 1443         0x00,                           /* PHY number */
 1444         0x00,                           /* GPR sequence length */
 1445         0x00,                           /* reset sequence length */
 1446         0x00, 0x78,                     /* media capabilities */
 1447         0xE0, 0x01,                     /* Nway advertisment */
 1448         0x00, 0x50,                     /* FDX bitmap */
 1449         0x00, 0x18,                     /* TTM bitmap */
 1450 };
 1451 
 1452 static int
 1453 srom(Ctlr* ctlr)
 1454 {
 1455         int i, k, oui, phy, x;
 1456         uchar *p;
 1457 
 1458         /*
 1459          * This is a partial decoding of the SROM format described in
 1460          * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
 1461          * 2-Mar-98'. Only the 2114[03] are handled, support for other
 1462          * controllers can be added as needed.
 1463          * Do a dummy read first to get the size and allocate ctlr->srom.
 1464          */
 1465         sromr(ctlr, 0);
 1466         if(ctlr->srom == nil)
 1467                 ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
 1468         for(i = 0; i < (1<<ctlr->sromsz); i++){
 1469                 x = sromr(ctlr, i);
 1470                 ctlr->srom[2*i] = x;
 1471                 ctlr->srom[2*i+1] = x>>8;
 1472         }
 1473 
 1474         if(DEBUG){
 1475                 print("srom:");
 1476                 for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
 1477                         if(i && ((i & 0x0F) == 0))
 1478                                 print("\n     ");
 1479                         print(" %2.2uX", ctlr->srom[i]);
 1480                 }
 1481                 print("\n");
 1482         }
 1483 
 1484         /*
 1485          * There are at least 2 SROM layouts:
 1486          *      e.g. Digital EtherWORKS station address at offset 20;
 1487          *                              this complies with the 21140A SROM
 1488          *                              application note from Digital;
 1489          *      e.g. SMC9332            station address at offset 0 followed by
 1490          *                              2 additional bytes, repeated at offset
 1491          *                              6; the 8 bytes are also repeated in
 1492          *                              reverse order at offset 8.
 1493          * To check which it is, read the SROM and check for the repeating
 1494          * patterns of the non-compliant cards; if that fails use the one at
 1495          * offset 20.
 1496          */
 1497         ctlr->sromea = ctlr->srom;
 1498         for(i = 0; i < 8; i++){
 1499                 x = ctlr->srom[i];
 1500                 if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
 1501                         ctlr->sromea = &ctlr->srom[20];
 1502                         break;
 1503                 }
 1504         }
 1505 
 1506         /*
 1507          * Fake up the SROM for the PNIC and AMDtek.
 1508          * They look like a 21140 with a PHY.
 1509          * The MAC address is byte-swapped in the orginal
 1510          * PNIC SROM data.
 1511          */
 1512         if(ctlr->id == Pnic){
 1513                 memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
 1514                 for(i = 0; i < Eaddrlen; i += 2){
 1515                         ctlr->srom[20+i] = ctlr->srom[i+1];
 1516                         ctlr->srom[20+i+1] = ctlr->srom[i];
 1517                 }
 1518         }
 1519         if(ctlr->id == CentaurP || ctlr->id == CentaurPcb){
 1520                 memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
 1521                 for(i = 0; i < Eaddrlen; i += 2){
 1522                         ctlr->srom[20+i] = ctlr->srom[8+i];
 1523                         ctlr->srom[20+i+1] = ctlr->srom[8+i+1];
 1524                 }
 1525         }
 1526 
 1527         /*
 1528          * Next, try to find the info leaf in the SROM for media detection.
 1529          * If it's a non-conforming card try to match the vendor ethernet code
 1530          * and point p at a fake info leaf with compact 21140 entries.
 1531          */
 1532         if(ctlr->sromea == ctlr->srom){
 1533                 p = nil;
 1534                 for(i = 0; leaf21140[i] != nil; i++){
 1535                         if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
 1536                                 p = &leaf21140[i][4];
 1537                                 break;
 1538                         }
 1539                 }
 1540                 if(p == nil)
 1541                         return -1;
 1542         }
 1543         else
 1544                 p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
 1545 
 1546         /*
 1547          * Set up the info needed for later media detection.
 1548          * For the 21140, set the general-purpose mask in CSR12.
 1549          * The info block entries are stored in order of increasing
 1550          * precedence, so detection will work backwards through the
 1551          * stored indexes into ctlr->srom.
 1552          * If an entry is found which matches the selected connection
 1553          * type, save the index. Otherwise, start at the last entry.
 1554          * If any MII entries are found (type 1 and 3 blocks), scan
 1555          * for PHYs.
 1556          */
 1557         ctlr->leaf = p;
 1558         ctlr->sct = *p++;
 1559         ctlr->sct |= *p++<<8;
 1560         if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
 1561                 csr32w(ctlr, 12, Gpc|*p++);
 1562                 delay(200);
 1563         }
 1564         ctlr->k = *p++;
 1565         if(ctlr->k >= nelem(ctlr->infoblock))
 1566                 ctlr->k = nelem(ctlr->infoblock)-1;
 1567         ctlr->sctk = ctlr->k-1;
 1568         phy = 0;
 1569         for(k = 0; k < ctlr->k; k++){
 1570                 ctlr->infoblock[k] = p;
 1571                 if(ctlr->id == Tulip1){
 1572                         debug("type21041: 0x%2.2uX\n", p[0]); 
 1573                         if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
 1574                                 ctlr->sctk = k;
 1575                         if(*p & 0x40)
 1576                                 p += 7;
 1577                         else
 1578                                 p += 1;
 1579                 }
 1580                 /*
 1581                  * The RAMIX PMC665 has a badly-coded SROM,
 1582                  * hence the test for 21143 and type 3.
 1583                  */
 1584                 else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
 1585                         *p |= 0x80;
 1586                         if(*(p+1) == 1 || *(p+1) == 3)
 1587                                 phy = 1;
 1588                         if(*(p+1) == 5)
 1589                                 ctlr->type5block = p;
 1590                         p += (*p & ~0x80)+1;
 1591                 }
 1592                 else{
 1593                         debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
 1594                                 p[0], p[1], p[2], p[3]); 
 1595                         if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
 1596                                 ctlr->sctk = k;
 1597                         p += 4;
 1598                 }
 1599         }
 1600         ctlr->curk = ctlr->sctk;
 1601         debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
 1602                 ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
 1603 
 1604         if(phy){
 1605                 x = 0;
 1606                 for(k = 0; k < nelem(ctlr->phy); k++){
 1607                         if((ctlr->id == CentaurP || ctlr->id == CentaurPcb) && k != 1)
 1608                                 continue;
 1609                         if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
 1610                                 continue;
 1611                         debug("phy reg 2 %4.4uX\n", oui);
 1612                         if(DEBUG){
 1613                                 oui = (oui & 0x3FF)<<6;
 1614                                 oui |= miir(ctlr, k, 3)>>10;
 1615                                 miir(ctlr, k, 1);
 1616                                 debug("phy%d: index %d oui %uX reg1 %uX\n",
 1617                                         x, k, oui, miir(ctlr, k, 1));
 1618                                 USED(oui);
 1619                         }
 1620                         ctlr->phy[x] = k;
 1621                 }
 1622         }
 1623 
 1624         ctlr->fd = 0;
 1625         ctlr->medium = -1;
 1626 
 1627         return 0;
 1628 }
 1629 
 1630 static void
 1631 dec2114xpci(void)
 1632 {
 1633         Ctlr *ctlr;
 1634         Pcidev *p;
 1635         int x;
 1636 
 1637         p = nil;
 1638         while(p = pcimatch(p, 0, 0)){
 1639                 if(p->ccrb != 0x02 || p->ccru != 0)
 1640                         continue;
 1641                 switch((p->did<<16)|p->vid){
 1642                 default:
 1643                         continue;
 1644 
 1645                 case Tulip3:                    /* 21143 */
 1646                         /*
 1647                          * Exit sleep mode.
 1648                          */
 1649                         x = pcicfgr32(p, 0x40);
 1650                         x &= ~0xC0000000;
 1651                         pcicfgw32(p, 0x40, x);
 1652                         /*FALLTHROUGH*/
 1653 
 1654                 case Tulip0:                    /* 21140 */
 1655                 case Tulip1:                    /* 21041 */
 1656                 case Pnic:                      /* PNIC */
 1657                 case Pnic2:                     /* PNIC-II */
 1658                 case CentaurP:                  /* ADMtek */
 1659                 case CentaurPcb:                /* ADMtek CardBus */
 1660                         break;
 1661                 }
 1662 
 1663                 /*
 1664                  * bar[0] is the I/O port register address and
 1665                  * bar[1] is the memory-mapped register address.
 1666                  */
 1667                 ctlr = malloc(sizeof(Ctlr));
 1668                 ctlr->port = p->mem[0].bar & ~0x01;
 1669                 ctlr->pcidev = p;
 1670                 ctlr->id = (p->did<<16)|p->vid;
 1671 
 1672                 if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){
 1673                         print("dec2114x: port 0x%uX in use\n", ctlr->port);
 1674                         free(ctlr);
 1675                         continue;
 1676                 }
 1677 
 1678                 /*
 1679                  * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
 1680                  * set or they don't always work right after a hardware
 1681                  * reset.
 1682                  */
 1683                 csr32w(ctlr, 6, Mbo|Ps);
 1684                 softreset(ctlr);
 1685 
 1686                 if(srom(ctlr)){
 1687                         iofree(ctlr->port);
 1688                         free(ctlr);
 1689                         continue;
 1690                 }
 1691 
 1692                 switch(ctlr->id){
 1693                 default:
 1694                         break;
 1695                 case Pnic:                      /* PNIC */
 1696                         /*
 1697                          * Turn off the jabber timer.
 1698                          */
 1699                         csr32w(ctlr, 15, 0x00000001);
 1700                         break;
 1701                 case CentaurP:
 1702                 case CentaurPcb:
 1703                         /*
 1704                          * Nice - the register offsets change from *8 to *4
 1705                          * for CSR16 and up...
 1706                          * CSR25/26 give the MAC address read from the SROM.
 1707                          * Don't really need to use this other than as a check,
 1708                          * the SROM will be read in anyway so the value there
 1709                          * can be used directly.
 1710                          */
 1711                         debug("csr25 %8.8luX csr26 %8.8luX\n",
 1712                                 inl(ctlr->port+0xA4), inl(ctlr->port+0xA8));
 1713                         debug("phyidr1 %4.4luX phyidr2 %4.4luX\n",
 1714                                 inl(ctlr->port+0xBC), inl(ctlr->port+0xC0));
 1715                         break;
 1716                 }
 1717 
 1718                 if(ctlrhead != nil)
 1719                         ctlrtail->next = ctlr;
 1720                 else
 1721                         ctlrhead = ctlr;
 1722                 ctlrtail = ctlr;
 1723         }
 1724 }
 1725 
 1726 static int
 1727 reset(Ether* ether)
 1728 {
 1729         Ctlr *ctlr;
 1730         int i, x;
 1731         uchar ea[Eaddrlen];
 1732         static int scandone;
 1733 
 1734         if(scandone == 0){
 1735                 dec2114xpci();
 1736                 scandone = 1;
 1737         }
 1738 
 1739         /*
 1740          * Any adapter matches if no ether->port is supplied,
 1741          * otherwise the ports must match.
 1742          */
 1743         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1744                 if(ctlr->active)
 1745                         continue;
 1746                 if(ether->port == 0 || ether->port == ctlr->port){
 1747                         ctlr->active = 1;
 1748                         break;
 1749                 }
 1750         }
 1751         if(ctlr == nil)
 1752                 return -1;
 1753 
 1754         ether->ctlr = ctlr;
 1755         ether->port = ctlr->port;
 1756         ether->irq = ctlr->pcidev->intl;
 1757         ether->tbdf = ctlr->pcidev->tbdf;
 1758 
 1759         /*
 1760          * Check if the adapter's station address is to be overridden.
 1761          * If not, read it from the EEPROM and set in ether->ea prior to
 1762          * loading the station address in the hardware.
 1763          */
 1764         memset(ea, 0, Eaddrlen);
 1765         if(memcmp(ea, ether->ea, Eaddrlen) == 0)
 1766                 memmove(ether->ea, ctlr->sromea, Eaddrlen);
 1767 
 1768         /*
 1769          * Look for a medium override in case there's no autonegotiation
 1770          * (no MII) or the autonegotiation fails.
 1771          */
 1772         for(i = 0; i < ether->nopt; i++){
 1773                 if(cistrcmp(ether->opt[i], "FD") == 0){
 1774                         ctlr->fd = 1;
 1775                         continue;
 1776                 }
 1777                 for(x = 0; x < nelem(mediatable); x++){
 1778                         debug("compare <%s> <%s>\n", mediatable[x],
 1779                                 ether->opt[i]);
 1780                         if(cistrcmp(mediatable[x], ether->opt[i]))
 1781                                 continue;
 1782                         ctlr->medium = x;
 1783         
 1784                         switch(ctlr->medium){
 1785                         default:
 1786                                 ctlr->fd = 0;
 1787                                 break;
 1788         
 1789                         case 0x04:              /* 10BASE-TFD */
 1790                         case 0x05:              /* 100BASE-TXFD */
 1791                         case 0x08:              /* 100BASE-FXFD */
 1792                                 ctlr->fd = 1;
 1793                                 break;
 1794                         }
 1795                         break;
 1796                 }
 1797         }
 1798 
 1799         ether->mbps = media(ether, 1);
 1800 
 1801         /*
 1802          * Initialise descriptor rings, ethernet address.
 1803          */
 1804         ctlr->nrdr = Nrde;
 1805         ctlr->ntdr = Ntde;
 1806         pcisetbme(ctlr->pcidev);
 1807         ctlrinit(ether);
 1808 
 1809         /*
 1810          * Linkage to the generic ethernet driver.
 1811          */
 1812         ether->attach = attach;
 1813         ether->transmit = transmit;
 1814         ether->interrupt = interrupt;
 1815         ether->ifstat = ifstat;
 1816 
 1817         ether->arg = ether;
 1818         ether->shutdown = shutdown;
 1819         ether->multicast = multicast;
 1820         ether->promiscuous = promiscuous;
 1821 
 1822         return 0;
 1823 }
 1824 
 1825 void
 1826 ether2114xlink(void)
 1827 {
 1828         addethercard("2114x",  reset);
 1829         addethercard("21140",  reset);
 1830 }

Cache object: bd76aa50504a7e53ada71dc257234ea3


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