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/ether82598.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  * intel 10gbe pci-express driver
    3  * copyright © 2007, coraid, inc.
    4  */
    5 #include "u.h"
    6 #include "../port/lib.h"
    7 #include "mem.h"
    8 #include "dat.h"
    9 #include "fns.h"
   10 #include "io.h"
   11 #include "../port/error.h"
   12 #include "../port/netif.h"
   13 #include "etherif.h"
   14 
   15 /*
   16  * // comments note conflicts with 82563-style drivers,
   17  * and the registers are all different.
   18  */
   19 
   20 enum {
   21         /* general */
   22         Ctrl            = 0x00000/4,    /* Device Control */
   23         Status          = 0x00008/4,    /* Device Status */
   24         Ctrlext         = 0x00018/4,    /* Extended Device Control */
   25         Esdp            = 0x00020/4,    /* extended sdp control */
   26         Esodp           = 0x00028/4,    /* extended od sdp control */
   27         Ledctl          = 0x00200/4,    /* led control */
   28         Tcptimer        = 0x0004c/4,    /* tcp timer */
   29         Ecc             = 0x110b0/4,    /* errata ecc control magic */
   30 
   31         /* nvm */
   32         Eec             = 0x10010/4,    /* eeprom/flash control */
   33         Eerd            = 0x10014/4,    /* eeprom read */
   34         Fla             = 0x1001c/4,    /* flash access */
   35         Flop            = 0x1013c/4,    /* flash opcode */
   36         Grc             = 0x10200/4,    /* general rx control */
   37 
   38         /* interrupt */
   39         Icr             = 0x00800/4,    /* interrupt cause read */
   40         Ics             = 0x00808/4,    /* " set */
   41         Ims             = 0x00880/4,    /* " mask read/set */
   42         Imc             = 0x00888/4,    /* " mask clear */
   43         Iac             = 0x00810/4,    /* " ayto clear */
   44         Iam             = 0x00890/4,    /* " auto mask enable */
   45         Itr             = 0x00820/4,    /* " throttling rate (0-19) */
   46         Ivar            = 0x00900/4,    /* " vector allocation regs. */
   47         /* msi interrupt */
   48         Msixt           = 0x0000/4,     /* msix table (bar3) */
   49         Msipba          = 0x2000/4,     /* msix pending bit array (bar3) */
   50         Pbacl           = 0x11068/4,    /* pba clear */
   51         Gpie            = 0x00898/4,    /* general purpose int enable */
   52 
   53         /* flow control */
   54         Pfctop          = 0x03008/4,    /* priority flow ctl type opcode */
   55         Fcttv           = 0x03200/4,    /* " transmit timer value (0-3) */
   56         Fcrtl           = 0x03220/4,    /* " rx threshold low (0-7) +8n */
   57         Fcrth           = 0x03260/4,    /* " rx threshold high (0-7) +8n */
   58         Rcrtv           = 0x032a0/4,    /* " refresh value threshold */
   59         Tfcs            = 0x0ce00/4,    /* " tx status */
   60 
   61         /* rx dma */
   62         Rbal            = 0x01000/4,    /* rx desc base low (0-63) +0x40n */
   63         Rbah            = 0x01004/4,    /* " high */
   64         Rdlen           = 0x01008/4,    /* " length */
   65         Rdh             = 0x01010/4,    /* " head */
   66         Rdt             = 0x01018/4,    /* " tail */
   67         Rxdctl          = 0x01028/4,    /* " control */
   68 
   69         Srrctl          = 0x02100/4,    /* split and replication rx ctl. */
   70         Dcarxctl        = 0x02200/4,    /* rx dca control */
   71         Rdrxctl         = 0x02f00/4,    /* rx dma control */
   72         Rxpbsize        = 0x03c00/4,    /* rx packet buffer size */
   73         Rxctl           = 0x03000/4,    /* rx control */
   74         Dropen          = 0x03d04/4,    /* drop enable control */
   75 
   76         /* rx */
   77         Rxcsum          = 0x05000/4,    /* rx checksum control */
   78         Rfctl           = 0x04008/4,    /* rx filter control */
   79         Mta             = 0x05200/4,    /* multicast table array (0-127) */
   80         Ral             = 0x05400/4,    /* rx address low */
   81         Rah             = 0x05404/4,
   82         Psrtype         = 0x05480/4,    /* packet split rx type. */
   83         Vfta            = 0x0a000/4,    /* vlan filter table array. */
   84         Fctrl           = 0x05080/4,    /* filter control */
   85         Vlnctrl         = 0x05088/4,    /* vlan control */
   86         Msctctrl        = 0x05090/4,    /* multicast control */
   87         Mrqc            = 0x05818/4,    /* multiple rx queues cmd */
   88         Vmdctl          = 0x0581c/4,    /* vmdq control */
   89         Imir            = 0x05a80/4,    /* immediate irq rx (0-7) */
   90         Imirext         = 0x05aa0/4,    /* immediate irq rx ext */
   91         Imirvp          = 0x05ac0/4,    /* immediate irq vlan priority */
   92         Reta            = 0x05c00/4,    /* redirection table */
   93         Rssrk           = 0x05c80/4,    /* rss random key */
   94 
   95         /* tx */
   96         Tdbal           = 0x06000/4,    /* tx desc base low +0x40n */
   97         Tdbah           = 0x06004/4,    /* " high */
   98         Tdlen           = 0x06008/4,    /* " len */
   99         Tdh             = 0x06010/4,    /* " head */
  100         Tdt             = 0x06018/4,    /* " tail */
  101         Txdctl          = 0x06028/4,    /* " control */
  102         Tdwbal          = 0x06038/4,    /* " write-back address low */
  103         Tdwbah          = 0x0603c/4,
  104 
  105         Dtxctl          = 0x07e00/4,    /* tx dma control */
  106         Tdcatxctrl      = 0x07200/4,    /* tx dca register (0-15) */
  107         Tipg            = 0x0cb00/4,    /* tx inter-packet gap */
  108         Txpbsize        = 0x0cc00/4,    /* tx packet-buffer size (0-15) */
  109 
  110         /* mac */
  111         Hlreg0          = 0x04240/4,    /* highlander control reg 0 */
  112         Hlreg1          = 0x04244/4,    /* highlander control reg 1 (ro) */
  113         Msca            = 0x0425c/4,    /* mdi signal cmd & addr */
  114         Msrwd           = 0x04260/4,    /* mdi single rw data */
  115         Mhadd           = 0x04268/4,    /* mac addr high & max frame */
  116         Pcss1           = 0x04288/4,    /* xgxs status 1 */
  117         Pcss2           = 0x0428c/4,
  118         Xpcss           = 0x04290/4,    /* 10gb-x pcs status */
  119         Serdesc         = 0x04298/4,    /* serdes control */
  120         Macs            = 0x0429c/4,    /* fifo control & report */
  121         Autoc           = 0x042a0/4,    /* autodetect control & status */
  122         Links           = 0x042a4/4,    /* link status */
  123         Autoc2          = 0x042a8/4,
  124 };
  125 
  126 enum {
  127         /* Ctrl */
  128         Rst             = 1<<26,        /* full nic reset */
  129 
  130         /* Txdctl */
  131         Ten             = 1<<25,
  132 
  133         /* Fctrl */
  134         Bam             = 1<<10,        /* broadcast accept mode */
  135         Upe             = 1<<9,         /* unicast promiscuous */
  136         Mpe             = 1<<8,         /* multicast promiscuous */
  137 
  138         /* Rxdctl */
  139         Pthresh         = 0,            /* prefresh threshold shift in bits */
  140         Hthresh         = 8,            /* host buffer minimum threshold " */
  141         Wthresh         = 16,           /* writeback threshold */
  142         Renable         = 1<<25,
  143 
  144         /* Rxctl */
  145         Rxen            = 1<<0,
  146         Dmbyps          = 1<<1,
  147 
  148         /* Rdrxctl */
  149         Rdmt½          = 0,
  150         Rdmt¼          = 1,
  151         Rdmt⅛         = 2,
  152 
  153         /* Rxcsum */
  154         Ippcse          = 1<<12,        /* ip payload checksum enable */
  155 
  156         /* Eerd */
  157         EEstart         = 1<<0,         /* Start Read */
  158         EEdone          = 1<<1,         /* Read done */
  159 
  160         /* interrupts */
  161         Irx0            = 1<<0,         /* driver defined */
  162         Itx0            = 1<<1,         /* driver defined */
  163         Lsc             = 1<<20,        /* link status change */
  164 
  165         /* Links */
  166         Lnkup   = 1<<30,
  167         Lnkspd  = 1<<29,
  168 
  169         /* Hlreg0 */
  170         Jumboen = 1<<2,
  171 };
  172 
  173 typedef struct {
  174         uint    reg;
  175         char    *name;
  176 } Stat;
  177 
  178 Stat stattab[] = {
  179         0x4000, "crc error",
  180         0x4004, "illegal byte",
  181         0x4008, "short packet",
  182         0x3fa0, "missed pkt0",
  183         0x4034, "mac local flt",
  184         0x4038, "mac rmt flt",
  185         0x4040, "rx length err",
  186         0x3f60, "xon tx",
  187         0xcf60, "xon rx",
  188         0x3f68, "xoff tx",
  189         0xcf68, "xoff rx",
  190         0x405c, "rx 040",
  191         0x4060, "rx 07f",
  192         0x4064, "rx 100",
  193         0x4068, "rx 200",
  194         0x406c, "rx 3ff",
  195         0x4070, "rx big",
  196         0x4074, "rx ok",
  197         0x4078, "rx bcast",
  198         0x3fc0, "rx no buf0",
  199         0x40a4, "rx runt",
  200         0x40a8, "rx frag",
  201         0x40ac, "rx ovrsz",
  202         0x40b0, "rx jab",
  203         0x40d0, "rx pkt",
  204 
  205         0x40d4, "tx pkt",
  206         0x40d8, "tx 040",
  207         0x40dc, "tx 07f",
  208         0x40e0, "tx 100",
  209         0x40e4, "tx 200",
  210         0x40e8, "tx 3ff",
  211         0x40ec, "tx big",
  212         0x40f4, "tx bcast",
  213         0x4120, "xsum err",
  214 };
  215 
  216 /* status */
  217 enum {
  218         Pif     = 1<<7, /* past exact filter (sic) */
  219         Ipcs    = 1<<6, /* ip checksum calcuated */
  220         L4cs    = 1<<5, /* layer 2 */
  221         Tcpcs   = 1<<4, /* tcp checksum calcuated */
  222         Vp      = 1<<3, /* 802.1q packet matched vet */
  223         Ixsm    = 1<<2, /* ignore checksum */
  224         Reop    = 1<<1, /* end of packet */
  225         Rdd     = 1<<0, /* descriptor done */
  226 };
  227 
  228 typedef struct {
  229         u32int  addr[2];
  230         ushort  length;
  231         ushort  cksum;
  232         uchar   status;
  233         uchar   errors;
  234         ushort  vlan;
  235 } Rd;
  236 
  237 enum {
  238         /* Td cmd */
  239         Rs      = 1<<3,
  240         Ic      = 1<<2,
  241         Ifcs    = 1<<1,
  242         Teop    = 1<<0,
  243 
  244         /* Td status */
  245         Tdd     = 1<<0,
  246 };
  247 
  248 typedef struct {
  249         u32int  addr[2];
  250         ushort  length;
  251         uchar   cso;
  252         uchar   cmd;
  253         uchar   status;
  254         uchar   css;
  255         ushort  vlan;
  256 } Td;
  257 
  258 enum {
  259         Factive         = 1<<0,
  260         Fstarted        = 1<<1,
  261 };
  262 
  263 typedef struct {
  264         Pcidev  *p;
  265         Ether   *edev;
  266         u32int  *reg;
  267         u32int  *reg3;
  268         uchar   flag;
  269         int     nrd;
  270         int     ntd;
  271         int     nrb;
  272         int     rbsz;
  273         QLock   slock;
  274         QLock   alock;
  275         QLock   tlock;
  276         Rendez  lrendez;
  277         Rendez  trendez;
  278         Rendez  rrendez;
  279         uint    im;
  280         uint    lim;
  281         uint    rim;
  282         uint    tim;
  283         Lock    imlock;
  284         char    *alloc;
  285 
  286         Rd      *rdba;
  287         Block   **rb;
  288         uint    rdt;
  289         uint    rdfree;
  290 
  291         Td      *tdba;
  292         uint    tdh;
  293         uint    tdt;
  294         Block   **tb;
  295 
  296         uchar   ra[Eaddrlen];
  297         uchar   mta[128];
  298         ulong   stats[nelem(stattab)];
  299         uint    speeds[3];
  300 } Ctlr;
  301 
  302 /* tweakable paramaters */
  303 enum {
  304         Rbsz    = 12*1024,
  305         Nrd     = 256,
  306         Ntd     = 256,
  307         Nrb     = 256,
  308 };
  309 
  310 static  Ctlr    *ctlrtab[4];
  311 static  int     nctlr;
  312 static  Lock    rblock;
  313 static  Block   *rbpool;
  314 
  315 static void
  316 readstats(Ctlr *c)
  317 {
  318         int i;
  319 
  320         qlock(&c->slock);
  321         for(i = 0; i < nelem(c->stats); i++)
  322                 c->stats[i] += c->reg[stattab[i].reg >> 2];
  323         qunlock(&c->slock);
  324 }
  325 
  326 static int speedtab[] = {
  327         0,
  328         1000,
  329         10000,
  330 };
  331 
  332 static long
  333 ifstat(Ether *e, void *a, long n, ulong offset)
  334 {
  335         uint i, *t;
  336         char *s, *p, *q;
  337         Ctlr *c;
  338 
  339         c = e->ctlr;
  340         p = s = malloc(READSTR);
  341         q = p + READSTR;
  342 
  343         readstats(c);
  344         for(i = 0; i < nelem(stattab); i++)
  345                 if(c->stats[i] > 0)
  346                         p = seprint(p, q, "%.10s  %uld\n", stattab[i].name,                                     c->stats[i]);
  347         t = c->speeds;
  348         p = seprint(p, q, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]);
  349         seprint(p, q, "rdfree %d rdh %d rdt %d\n", c->rdfree, c->reg[Rdt],
  350                 c->reg[Rdh]);
  351         n = readstr(offset, a, n, s);
  352         free(s);
  353 
  354         return n;
  355 }
  356 
  357 static void
  358 im(Ctlr *c, int i)
  359 {
  360         ilock(&c->imlock);
  361         c->im |= i;
  362         c->reg[Ims] = c->im;
  363         iunlock(&c->imlock);
  364 }
  365 
  366 static int
  367 lim(void *v)
  368 {
  369         return ((Ctlr*)v)->lim != 0;
  370 }
  371 
  372 static void
  373 lproc(void *v)
  374 {
  375         int r, i;
  376         Ctlr *c;
  377         Ether *e;
  378 
  379         e = v;
  380         c = e->ctlr;
  381         for (;;) {
  382                 r = c->reg[Links];
  383                 e->link = (r & Lnkup) != 0;
  384                 i = 0;
  385                 if(e->link)
  386                         i = 1 + ((r & Lnkspd) != 0);
  387                 c->speeds[i]++;
  388                 e->mbps = speedtab[i];
  389                 c->lim = 0;
  390                 im(c, Lsc);
  391                 sleep(&c->lrendez, lim, c);
  392                 c->lim = 0;
  393         }
  394 }
  395 
  396 static long
  397 ctl(Ether *, void *, long)
  398 {
  399         error(Ebadarg);
  400         return -1;
  401 }
  402 
  403 static Block*
  404 rballoc(void)
  405 {
  406         Block *b;
  407 
  408         ilock(&rblock);
  409         if(b = rbpool){
  410                 rbpool = b->next;
  411                 b->next = 0;
  412         }
  413         iunlock(&rblock);
  414         return b;
  415 }
  416 
  417 void
  418 rbfree(Block *b)
  419 {
  420         b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
  421         ilock(&rblock);
  422         b->next = rbpool;
  423         rbpool = b;
  424         iunlock(&rblock);
  425 }
  426 
  427 #define Next(x, m)      (((x)+1) & (m))
  428 
  429 static int
  430 cleanup(Ctlr *c, int tdh)
  431 {
  432         Block *b;
  433         uint m, n;
  434 
  435         m = c->ntd - 1;
  436         while(c->tdba[n = Next(tdh, m)].status & Tdd){
  437                 tdh = n;
  438                 b = c->tb[tdh];
  439                 c->tb[tdh] = 0;
  440                 freeb(b);
  441                 c->tdba[tdh].status = 0;
  442         }
  443         return tdh;
  444 }
  445 
  446 void
  447 transmit(Ether *e)
  448 {
  449         uint i, m, tdt, tdh;
  450         Ctlr *c;
  451         Block *b;
  452         Td *t;
  453 
  454         c = e->ctlr;
  455 //      qlock(&c->tlock);
  456         if(!canqlock(&c->tlock)){
  457                 im(c, Itx0);
  458                 return;
  459         }
  460         tdh = c->tdh = cleanup(c, c->tdh);
  461         tdt = c->tdt;
  462         m = c->ntd - 1;
  463         for(i = 0; i < 8; i++){
  464                 if(Next(tdt, m) == tdh){
  465                         im(c, Itx0);
  466                         break;
  467                 }
  468                 if(!(b = qget(e->oq)))
  469                         break;
  470                 t = c->tdba + tdt;
  471                 t->addr[0] = PCIWADDR(b->rp);
  472                 t->length = BLEN(b);
  473                 t->cmd = Rs | Ifcs | Teop;
  474                 c->tb[tdt] = b;
  475                 tdt = Next(tdt, m);
  476         }
  477         if(i){
  478                 c->tdt = tdt;
  479                 c->reg[Tdt] = tdt;
  480         }
  481         qunlock(&c->tlock);
  482 }
  483 
  484 static int
  485 tim(void *c)
  486 {
  487         return ((Ctlr*)c)->tim != 0;
  488 }
  489 
  490 static void
  491 tproc(void *v)
  492 {
  493         Ctlr *c;
  494         Ether *e;
  495 
  496         e = v;
  497         c = e->ctlr;
  498         for (;;) {
  499                 sleep(&c->trendez, tim, c);     /* transmit kicks us */
  500                 c->tim = 0;
  501                 transmit(e);
  502         }
  503 }
  504 
  505 static void
  506 rxinit(Ctlr *c)
  507 {
  508         int i;
  509         Block *b;
  510 
  511         c->reg[Rxctl] &= ~Rxen;
  512         for(i = 0; i < c->nrd; i++){
  513                 b = c->rb[i];
  514                 c->rb[i] = 0;
  515                 if(b)
  516                         freeb(b);
  517         }
  518         c->rdfree = 0;
  519 
  520         c->reg[Fctrl] |= Bam;
  521         c->reg[Rxcsum] |= Ipcs;
  522         c->reg[Srrctl] = (c->rbsz + 1023)/1024;
  523         c->reg[Mhadd] = c->rbsz << 16;
  524         c->reg[Hlreg0] |= Jumboen;
  525 
  526         c->reg[Rbal] = PCIWADDR(c->rdba);
  527         c->reg[Rbah] = 0;
  528         c->reg[Rdlen] = c->nrd*sizeof(Rd);
  529         c->reg[Rdh] = 0;
  530         c->reg[Rdt] = c->rdt = 0;
  531 
  532         c->reg[Rdrxctl] = Rdmt¼;
  533         c->reg[Rxdctl] = 8<<Wthresh | 8<<Pthresh | 4<<Hthresh | Renable;
  534         c->reg[Rxctl] |= Rxen | Dmbyps;
  535 }
  536 
  537 static void
  538 replenish(Ctlr *c, uint rdh)
  539 {
  540         int rdt, m, i;
  541         Block *b;
  542         Rd *r;
  543 
  544         m = c->nrd - 1;
  545         i = 0;
  546         for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){
  547                 r = c->rdba + rdt;
  548                 if(!(b = rballoc())){
  549                         print("82598: no buffers\n");
  550                         break;
  551                 }
  552                 c->rb[rdt] = b;
  553                 r->addr[0] = PCIWADDR(b->rp);
  554                 r->status = 0;
  555                 c->rdfree++;
  556                 i++;
  557         }
  558         if(i)
  559                 c->reg[Rdt] = c->rdt = rdt;
  560 }
  561 
  562 static int
  563 rim(void *v)
  564 {
  565         return ((Ctlr*)v)->rim != 0;
  566 }
  567 
  568 static uchar zeroea[Eaddrlen];
  569 
  570 void
  571 rproc(void *v)
  572 {
  573         uint m, rdh;
  574         Block *b;
  575         Ctlr *c;
  576         Ether *e;
  577         Rd *r;
  578 
  579         e = v;
  580         c = e->ctlr;
  581         m = c->nrd - 1;
  582         rdh = 0;
  583 loop:
  584         replenish(c, rdh);
  585         im(c, Irx0);
  586         sleep(&c->rrendez, rim, c);
  587 loop1:
  588         c->rim = 0;
  589         if(c->nrd - c->rdfree >= 16)
  590                 replenish(c, rdh);
  591         r = c->rdba + rdh;
  592         if(!(r->status & Rdd))
  593                 goto loop;              /* UGH */
  594         b = c->rb[rdh];
  595         c->rb[rdh] = 0;
  596         b->wp += r->length;
  597         b->lim = b->wp;         /* lie like a dog */
  598         if(!(r->status & Ixsm)){
  599                 if(r->status & Ipcs)
  600                         b->flag |= Bipck;
  601                 if(r->status & Tcpcs)
  602                         b->flag |= Btcpck | Budpck;
  603                 b->checksum = r->cksum;
  604         }
  605 //      r->status = 0;
  606         etheriq(e, b, 1);
  607         c->rdfree--;
  608         rdh = Next(rdh, m);
  609         goto loop1;                     /* UGH */
  610 }
  611 
  612 static void
  613 promiscuous(void *a, int on)
  614 {
  615         Ctlr *c;
  616         Ether *e;
  617 
  618         e = a;
  619         c = e->ctlr;
  620         if(on)
  621                 c->reg[Fctrl] |= Upe | Mpe;
  622         else
  623                 c->reg[Fctrl] &= ~(Upe | Mpe);
  624 }
  625 
  626 static void
  627 multicast(void *a, uchar *ea, int on)
  628 {
  629         int b, i;
  630         Ctlr *c;
  631         Ether *e;
  632 
  633         e = a;
  634         c = e->ctlr;
  635 
  636         /*
  637          * multiple ether addresses can hash to the same filter bit,
  638          * so it's never safe to clear a filter bit.
  639          * if we want to clear filter bits, we need to keep track of
  640          * all the multicast addresses in use, clear all the filter bits,
  641          * then set the ones corresponding to in-use addresses.
  642          */
  643         i = ea[5] >> 1;
  644         b = (ea[5]&1)<<4 | ea[4]>>4;
  645         b = 1 << b;
  646         if(on)
  647                 c->mta[i] |= b;
  648 //      else
  649 //              c->mta[i] &= ~b;
  650         c->reg[Mta+i] = c->mta[i];
  651 }
  652 
  653 static int
  654 detach(Ctlr *c)
  655 {
  656         int i;
  657 
  658         c->reg[Imc] = ~0;
  659         c->reg[Ctrl] |= Rst;
  660         for(i = 0; i < 100; i++){
  661                 delay(1);
  662                 if((c->reg[Ctrl] & Rst) == 0)
  663                         break;
  664         }
  665         if (i >= 100)
  666                 return -1;
  667         /* errata */
  668         delay(50);
  669         c->reg[Ecc] &= ~(1<<21 | 1<<18 | 1<<9 | 1<<6);
  670 
  671         /* not cleared by reset; kill it manually. */
  672         for(i = 1; i < 16; i++)
  673                 c->reg[Rah] &= ~(1 << 31);
  674         for(i = 0; i < 128; i++)
  675                 c->reg[Mta + i] = 0;
  676         for(i = 1; i < 640; i++)
  677                 c->reg[Vfta + i] = 0;
  678         return 0;
  679 }
  680 
  681 static void
  682 shutdown(Ether *e)
  683 {
  684         detach(e->ctlr);
  685 }
  686 
  687 /* ≤ 20ms */
  688 static ushort
  689 eeread(Ctlr *c, int i)
  690 {
  691         c->reg[Eerd] = EEstart | i<<2;
  692         while((c->reg[Eerd] & EEdone) == 0)
  693                 ;
  694         return c->reg[Eerd] >> 16;
  695 }
  696 
  697 static int
  698 eeload(Ctlr *c)
  699 {
  700         ushort u, v, p, l, i, j;
  701 
  702         if((eeread(c, 0) & 0xc0) != 0x40)
  703                 return -1;
  704         u = 0;
  705         for(i = 0; i < 0x40; i++)
  706                 u +=  eeread(c, i);
  707         for(i = 3; i < 0xf; i++){
  708                 p = eeread(c, i);
  709                 l = eeread(c, p++);
  710                 if((int)p + l + 1 > 0xffff)
  711                         continue;
  712                 for(j = p; j < p + l; j++)
  713                         u += eeread(c, j);
  714         }
  715         if(u != 0xbaba)
  716                 return -1;
  717         if(c->reg[Status] & (1<<3))
  718                 u = eeread(c, 10);
  719         else
  720                 u = eeread(c, 9);
  721         u++;
  722         for(i = 0; i < Eaddrlen;){
  723                 v = eeread(c, u + i/2);
  724                 c->ra[i++] = v;
  725                 c->ra[i++] = v>>8;
  726         }
  727         c->ra[5] += (c->reg[Status] & 0xc) >> 2;
  728         return 0;
  729 }
  730 
  731 static int
  732 reset(Ctlr *c)
  733 {
  734         int i;
  735         uchar *p;
  736 
  737         if(detach(c)){
  738                 print("82598: reset timeout\n");
  739                 return -1;
  740         }
  741         if(eeload(c)){
  742                 print("82598: eeprom failure\n");
  743                 return -1;
  744         }
  745         p = c->ra;
  746         c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
  747         c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
  748 
  749         readstats(c);
  750         for(i = 0; i<nelem(c->stats); i++)
  751                 c->stats[i] = 0;
  752 
  753         c->reg[Ctrlext] |= 1 << 16;
  754         /* make some guesses for flow control */
  755         c->reg[Fcrtl] = 0x10000 | 1<<31;
  756         c->reg[Fcrth] = 0x40000 | 1<<31;
  757         c->reg[Rcrtv] = 0x6000;
  758 
  759         /* configure interrupt mapping (don't ask) */
  760         c->reg[Ivar+0] =     0 | 1<<7;
  761         c->reg[Ivar+64/4] =  1 | 1<<7;
  762 //      c->reg[Ivar+97/4] = (2 | 1<<7) << (8*(97%4));
  763 
  764         /* interrupt throttling goes here. */
  765         for(i = Itr; i < Itr + 20; i++)
  766                 c->reg[i] = 128;                /* ¼µs intervals */
  767         c->reg[Itr + Itx0] = 256;
  768         return 0;
  769 }
  770 
  771 static void
  772 txinit(Ctlr *c)
  773 {
  774         Block *b;
  775         int i;
  776 
  777         c->reg[Txdctl] = 16<<Wthresh | 16<<Pthresh;
  778         for(i = 0; i < c->ntd; i++){
  779                 b = c->tb[i];
  780                 c->tb[i] = 0;
  781                 if(b)
  782                         freeb(b);
  783         }
  784         memset(c->tdba, 0, c->ntd * sizeof(Td));
  785         c->reg[Tdbal] = PCIWADDR(c->tdba);
  786         c->reg[Tdbah] = 0;
  787         c->reg[Tdlen] = c->ntd*sizeof(Td);
  788         c->reg[Tdh] = 0;
  789         c->reg[Tdt] = 0;
  790         c->tdh = c->ntd - 1;
  791         c->tdt = 0;
  792         c->reg[Txdctl] |= Ten;
  793 }
  794 
  795 static void
  796 attach(Ether *e)
  797 {
  798         Block *b;
  799         Ctlr *c;
  800         int t;
  801         char buf[KNAMELEN];
  802 
  803         c = e->ctlr;
  804         c->edev = e;                    /* point back to Ether* */
  805         qlock(&c->alock);
  806         if(c->alloc){
  807                 qunlock(&c->alock);
  808                 return;
  809         }
  810 
  811         c->nrd = Nrd;
  812         c->ntd = Ntd;
  813         t  = c->nrd * sizeof *c->rdba + 255;
  814         t += c->ntd * sizeof *c->tdba + 255;
  815         t += (c->ntd + c->nrd) * sizeof(Block*);
  816         c->alloc = malloc(t);
  817         qunlock(&c->alock);
  818         if(c->alloc == nil)
  819                 error(Enomem);
  820 
  821         c->rdba = (Rd*)ROUNDUP((uintptr)c->alloc, 256);
  822         c->tdba = (Td*)ROUNDUP((uintptr)(c->rdba + c->nrd), 256);
  823         c->rb = (Block**)(c->tdba + c->ntd);
  824         c->tb = (Block**)(c->rb + c->nrd);
  825 
  826         if(waserror()){
  827                 while(b = rballoc()){
  828                         b->free = 0;
  829                         freeb(b);
  830                 }
  831                 free(c->alloc);
  832                 c->alloc = nil;
  833                 nexterror();
  834         }
  835         for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){
  836                 if(!(b = allocb(c->rbsz+BY2PG)))
  837                         error(Enomem);
  838                 b->free = rbfree;
  839                 freeb(b);
  840         }
  841         poperror();
  842 
  843         rxinit(c);
  844         txinit(c);
  845 
  846         sprint(buf, "#l%dl", e->ctlrno);
  847         kproc(buf, lproc, e);
  848         sprint(buf, "#l%dr", e->ctlrno);
  849         kproc(buf, rproc, e);
  850         sprint(buf, "#l%dt", e->ctlrno);
  851         kproc(buf, tproc, e);
  852 }
  853 
  854 static void
  855 interrupt(Ureg*, void *v)
  856 {
  857         int icr, im;
  858         Ctlr *c;
  859         Ether *e;
  860 
  861         e = v;
  862         c = e->ctlr;
  863         ilock(&c->imlock);
  864         c->reg[Imc] = ~0;
  865         im = c->im;
  866         while((icr = c->reg[Icr] & c->im) != 0){
  867                 if(icr & Lsc){
  868                         im &= ~Lsc;
  869                         c->lim = icr & Lsc;
  870                         wakeup(&c->lrendez);
  871                 }
  872                 if(icr & Irx0){
  873                         im &= ~Irx0;
  874                         c->rim = icr & Irx0;
  875                         wakeup(&c->rrendez);
  876                 }
  877                 if(icr & Itx0){
  878                         im &= ~Itx0;
  879                         c->tim = icr & Itx0;
  880                         wakeup(&c->trendez);
  881                 }
  882         }
  883         c->reg[Ims] = c->im = im;
  884         iunlock(&c->imlock);
  885 }
  886 
  887 static void
  888 scan(void)
  889 {
  890         ulong io, io3;
  891         void *mem, *mem3;
  892         Ctlr *c;
  893         Pcidev *p;
  894 
  895         p = 0;
  896         while(p = pcimatch(p, 0x8086, 0)){
  897                 switch(p->did){
  898                 case 0x10c6:            /* 82598 af dual port */
  899                 case 0x10c7:            /* 82598 af single port */
  900                 case 0x10b6:            /* 82598 backplane */
  901                 case 0x10dd:            /* 82598 at cx4 */
  902                         break;
  903                 default:
  904                         continue;
  905                 }
  906                 if(nctlr == nelem(ctlrtab)){
  907                         print("i82598: too many controllers\n");
  908                         return;
  909                 }
  910                 io = p->mem[0].bar & ~0xf;
  911                 mem = vmap(io, p->mem[0].size);
  912                 if(mem == nil){
  913                         print("i82598: can't map %#p\n", p->mem[0].bar);
  914                         continue;
  915                 }
  916                 io3 = p->mem[3].bar & ~0xf;
  917                 mem3 = vmap(io3, p->mem[3].size);
  918                 if(mem3 == nil){
  919                         print("i82598: can't map %#p\n", p->mem[3].bar);
  920                         vunmap(mem, p->mem[0].size);
  921                         continue;
  922                 }
  923                 c = malloc(sizeof *c);
  924                 c->p = p;
  925                 c->reg = (u32int*)mem;
  926                 c->reg3 = (u32int*)mem3;
  927                 c->rbsz = Rbsz;
  928                 if(reset(c)){
  929                         print("i82598: can't reset\n");
  930                         free(c);
  931                         vunmap(mem, p->mem[0].size);
  932                         vunmap(mem3, p->mem[3].size);
  933                         continue;
  934                 }
  935                 pcisetbme(p);
  936                 ctlrtab[nctlr++] = c;
  937         }
  938 }
  939 
  940 static int
  941 pnp(Ether *e)
  942 {
  943         int i;
  944         Ctlr *c = nil;
  945 
  946         if(nctlr == 0)
  947                 scan();
  948         for(i = 0; i < nctlr; i++){
  949                 c = ctlrtab[i];
  950                 if(c == nil || c->flag & Factive)
  951                         continue;
  952                 if(e->port == 0 || e->port == (ulong)c->reg)
  953                         break;
  954         }
  955         if (i >= nctlr)
  956                 return -1;
  957         c->flag |= Factive;
  958         e->ctlr = c;
  959         e->port = (uintptr)c->reg;
  960         e->irq = c->p->intl;
  961         e->tbdf = c->p->tbdf;
  962         e->mbps = 10000;
  963         e->maxmtu = c->rbsz;
  964         memmove(e->ea, c->ra, Eaddrlen);
  965         e->arg = e;
  966         e->attach = attach;
  967         e->ctl = ctl;
  968         e->ifstat = ifstat;
  969         e->interrupt = interrupt;
  970         e->multicast = multicast;
  971         e->promiscuous = promiscuous;
  972         e->shutdown = shutdown;
  973         e->transmit = transmit;
  974 
  975         return 0;
  976 }
  977 
  978 void
  979 ether82598link(void)
  980 {
  981         addethercard("i82598", pnp);
  982 }

Cache object: 879b8331a4d7c1ea1c76d6d72b42c3d0


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