]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/ether82598.c
ether82563, ether82598, etherx550: round rbsz to multiple of 1K
[plan9front.git] / sys / src / 9 / pc / ether82598.c
index 459b1fb0fbf9a61562684d7bd4309743e02f4ec7..0c60c3afb3c90fddbdca4863aeb26b0f17aede32 100644 (file)
@@ -10,7 +10,7 @@
 #include "io.h"
 #include "../port/error.h"
 #include "../port/netif.h"
-#include "etherif.h"
+#include "../port/etherif.h"
 
 /*
  * // comments note conflicts with 82563-style drivers,
@@ -101,7 +101,8 @@ enum {
        Txdctl          = 0x06028/4,    /* " control */
        Tdwbal          = 0x06038/4,    /* " write-back address low */
        Tdwbah          = 0x0603c/4,
-
+       Dmatxctl        = 0x04a80/4,
+       
        Dtxctl          = 0x07e00/4,    /* tx dma control */
        Tdcatxctrl      = 0x07200/4,    /* tx dca register (0-15) */
        Tipg            = 0x0cb00/4,    /* tx inter-packet gap */
@@ -141,6 +142,9 @@ enum {
        Wthresh         = 16,           /* writeback threshold */
        Renable         = 1<<25,
 
+       /* Dmatxctl */
+       Txen            = 1<<0,
+
        /* Rxctl */
        Rxen            = 1<<0,
        Dmbyps          = 1<<1,
@@ -263,12 +267,12 @@ enum {
 typedef struct {
        Pcidev  *p;
        Ether   *edev;
+       uintptr io;
        u32int  *reg;
-       u32int  *reg3;
+       u32int  *regmsi;
        uchar   flag;
        int     nrd;
        int     ntd;
-       int     nrb;
        int     rbsz;
        Lock    slock;
        Lock    alock;
@@ -294,14 +298,14 @@ typedef struct {
        Block   **tb;
 
        uchar   ra[Eaddrlen];
-       uchar   mta[128];
+       u32int  mta[128];
        ulong   stats[nelem(stattab)];
        uint    speeds[3];
 } Ctlr;
 
 /* tweakable paramaters */
 enum {
-       Rbsz    = 12*1024,
+       Mtu     = 12*1024,
        Nrd     = 256,
        Ntd     = 256,
        Nrb     = 256,
@@ -309,8 +313,6 @@ enum {
 
 static Ctlr    *ctlrtab[4];
 static int     nctlr;
-static Lock    rblock;
-static Block   *rbpool;
 
 static void
 readstats(Ctlr *c)
@@ -336,10 +338,10 @@ ifstat(Ether *e, void *a, long n, ulong offset)
        char *s, *p, *q;
        Ctlr *c;
 
-       c = e->ctlr;
-       p = s = malloc(READSTR);
+       p = s = smalloc(READSTR);
        q = p + READSTR;
 
+       c = e->ctlr;
        readstats(c);
        for(i = 0; i < nelem(stattab); i++)
                if(c->stats[i] > 0)
@@ -378,6 +380,8 @@ lproc(void *v)
 
        e = v;
        c = e->ctlr;
+       while(waserror())
+               ;
        for (;;) {
                r = c->reg[Links];
                e->link = (r & Lnkup) != 0;
@@ -400,32 +404,6 @@ ctl(Ether *, void *, long)
        return -1;
 }
 
-static Block*
-rballoc(void)
-{
-       Block *bp;
-
-       ilock(&rblock);
-       if((bp = rbpool) != nil){
-               rbpool = bp->next;
-               bp->next = 0;
-               _xinc(&bp->ref);        /* prevent bp from being freed */
-       }
-       iunlock(&rblock);
-       return bp;
-}
-
-void
-rbfree(Block *b)
-{
-       b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
-       b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
-       ilock(&rblock);
-       b->next = rbpool;
-       rbpool = b;
-       iunlock(&rblock);
-}
-
 #define Next(x, m)     (((x)+1) & (m))
 
 static int
@@ -496,6 +474,8 @@ tproc(void *v)
 
        e = v;
        c = e->ctlr;
+       while(waserror())
+               ;
        for (;;) {
                sleep(&c->trendez, tim, c);     /* transmit kicks us */
                c->tim = 0;
@@ -520,7 +500,7 @@ rxinit(Ctlr *c)
 
        c->reg[Fctrl] |= Bam;
        c->reg[Rxcsum] |= Ipcs;
-       c->reg[Srrctl] = (c->rbsz + 1023)/1024;
+       c->reg[Srrctl] = c->rbsz / 1024;
        c->reg[Mhadd] = c->rbsz << 16;
        c->reg[Hlreg0] |= Jumboen;
 
@@ -545,12 +525,11 @@ replenish(Ctlr *c, uint rdh)
        m = c->nrd - 1;
        i = 0;
        for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){
-               r = c->rdba + rdt;
-               if(!(b = rballoc())){
-                       print("82598: no buffers\n");
-                       break;
-               }
+               b = allocb(c->rbsz+BY2PG);
+               b->rp = (uchar*)PGROUND((uintptr)b->base);
+               b->wp = b->rp;
                c->rb[rdt] = b;
+               r = c->rdba + rdt;
                r->addr[0] = PCIWADDR(b->rp);
                r->status = 0;
                c->rdfree++;
@@ -581,6 +560,8 @@ rproc(void *v)
        c = e->ctlr;
        m = c->nrd - 1;
        rdh = 0;
+       while(waserror())
+               ;
 loop:
        replenish(c, rdh);
        im(c, Irx0);
@@ -595,7 +576,6 @@ loop1:
        b = c->rb[rdh];
        c->rb[rdh] = 0;
        b->wp += r->length;
-       b->lim = b->wp;         /* lie like a dog */
        if(!(r->status & Ixsm)){
                if(r->status & Ipcs)
                        b->flag |= Bipck;
@@ -604,7 +584,7 @@ loop1:
                b->checksum = r->cksum;
        }
 //     r->status = 0;
-       etheriq(e, b, 1);
+       etheriq(e, b);
        c->rdfree--;
        rdh = Next(rdh, m);
        goto loop1;                     /* UGH */
@@ -733,7 +713,6 @@ static int
 reset(Ctlr *c)
 {
        int i;
-       uchar *p;
 
        if(detach(c)){
                print("82598: reset timeout\n");
@@ -741,11 +720,8 @@ reset(Ctlr *c)
        }
        if(eeload(c)){
                print("82598: eeprom failure\n");
-               return -1;
+               memset(c->ra, 0, Eaddrlen);
        }
-       p = c->ra;
-       c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
-       c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
 
        readstats(c);
        for(i = 0; i<nelem(c->stats); i++)
@@ -791,12 +767,13 @@ txinit(Ctlr *c)
        c->tdh = c->ntd - 1;
        c->tdt = 0;
        c->reg[Txdctl] |= Ten;
+
+       c->reg[Dmatxctl] |= Txen;
 }
 
 static void
 attach(Ether *e)
 {
-       Block *b;
        Ctlr *c;
        int t;
        char buf[KNAMELEN];
@@ -824,23 +801,6 @@ attach(Ether *e)
        c->rb = (Block**)(c->tdba + c->ntd);
        c->tb = (Block**)(c->rb + c->nrd);
 
-       if(waserror()){
-               while(b = rballoc()){
-                       b->free = 0;
-                       freeb(b);
-               }
-               free(c->alloc);
-               c->alloc = nil;
-               nexterror();
-       }
-       for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){
-               if(!(b = allocb(c->rbsz+BY2PG)))
-                       error(Enomem);
-               b->free = rbfree;
-               freeb(b);
-       }
-       poperror();
-
        rxinit(c);
        txinit(c);
 
@@ -888,8 +848,9 @@ interrupt(Ureg*, void *v)
 static void
 scan(void)
 {
-       ulong io, io3;
-       void *mem, *mem3;
+       uintptr io, iomsi;
+       void *mem, *memmsi;
+       int pciregs, pcimsix;
        Ctlr *c;
        Pcidev *p;
 
@@ -901,37 +862,52 @@ scan(void)
                case 0x10b6:            /* 82598 backplane */
                case 0x10dd:            /* 82598 at cx4 */
                case 0x10ec:            /* 82598 at cx4 dual port */
+                       pcimsix = 3;
+                       break;
+               case 0x10fb:            /* 82599 */
+               case 0x1528:            /* T540-T1 */
+                       pcimsix = 4;
                        break;
+
                default:
                        continue;
                }
+               pciregs = 0;
                if(nctlr == nelem(ctlrtab)){
                        print("i82598: too many controllers\n");
                        return;
                }
-               io = p->mem[0].bar & ~0xf;
-               mem = vmap(io, p->mem[0].size);
+               c = malloc(sizeof *c);
+               if(c == nil){
+                       print("i82598: can't allocate memory\n");
+                       continue;
+               }
+               io = p->mem[pciregs].bar & ~0xf;
+               mem = vmap(io, p->mem[pciregs].size);
                if(mem == nil){
-                       print("i82598: can't map %#p\n", p->mem[0].bar);
+                       print("i82598: can't map regs %#p\n", io);
+                       free(c);
                        continue;
                }
-               io3 = p->mem[3].bar & ~0xf;
-               mem3 = vmap(io3, p->mem[3].size);
-               if(mem3 == nil){
-                       print("i82598: can't map %#p\n", p->mem[3].bar);
-                       vunmap(mem, p->mem[0].size);
+               iomsi = p->mem[pcimsix].bar & ~0xf;
+               memmsi = vmap(iomsi, p->mem[pcimsix].size);
+               if(memmsi == nil){
+                       print("i82598: can't map msi-x regs %#p\n", iomsi);
+                       vunmap(mem, p->mem[pciregs].size);
+                       free(c);
                        continue;
                }
-               c = malloc(sizeof *c);
+               pcienable(p);
                c->p = p;
+               c->io = io;
                c->reg = (u32int*)mem;
-               c->reg3 = (u32int*)mem3;
-               c->rbsz = Rbsz;
+               c->regmsi = (u32int*)memmsi;
+               c->rbsz = ROUND(Mtu, 1024);
                if(reset(c)){
                        print("i82598: can't reset\n");
                        free(c);
-                       vunmap(mem, p->mem[0].size);
-                       vunmap(mem3, p->mem[3].size);
+                       vunmap(mem, p->mem[pciregs].size);
+                       vunmap(memmsi, p->mem[pcimsix].size);
                        continue;
                }
                pcisetbme(p);
@@ -942,8 +918,10 @@ scan(void)
 static int
 pnp(Ether *e)
 {
+       static uchar zeros[Eaddrlen];
        int i;
        Ctlr *c = nil;
+       uchar *p;
 
        if(nctlr == 0)
                scan();
@@ -951,29 +929,38 @@ pnp(Ether *e)
                c = ctlrtab[i];
                if(c == nil || c->flag & Factive)
                        continue;
-               if(e->port == 0 || e->port == (ulong)c->reg)
+               if(e->port == 0 || e->port == c->io)
                        break;
        }
        if (i >= nctlr)
                return -1;
+
+       if(memcmp(c->ra, zeros, Eaddrlen) != 0)
+               memmove(e->ea, c->ra, Eaddrlen);
+
+       p = e->ea;
+       c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
+       c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
+
        c->flag |= Factive;
        e->ctlr = c;
        e->port = (uintptr)c->reg;
        e->irq = c->p->intl;
        e->tbdf = c->p->tbdf;
        e->mbps = 10000;
-       e->maxmtu = c->rbsz;
-       memmove(e->ea, c->ra, Eaddrlen);
+       e->maxmtu = Mtu;
+
        e->arg = e;
        e->attach = attach;
        e->ctl = ctl;
        e->ifstat = ifstat;
-       e->interrupt = interrupt;
        e->multicast = multicast;
        e->promiscuous = promiscuous;
        e->shutdown = shutdown;
        e->transmit = transmit;
 
+       intrenable(e->irq, interrupt, e, e->tbdf, e->name);
+
        return 0;
 }