#include "dat.h"
#include "fns.h"
#include "io.h"
+#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
-#include "etherif.h"
+#include "../port/etherif.h"
#define Pciwaddrh(x) 0
#define Pciwaddrl(x) PCIWADDR(x)
Fprobe = 1<<0,
Sringcnt = 2048,
Tringcnt = 512,
-// Rringcnt = Nrb,
Rringcnt = 512,
Rringl = Rringcnt - 8,
};
Isrc2 = 0x001c/4,
Eisr = 0x0024/4,
Lisr = 0x0028/4, /* leave isr */
+ Icr = 0x002c/4,
Macadr = 0x0100, /* mac address 2ports*3 */
Pmd = 0x0119,
Maccfg = 0x011a,
uchar rev;
uchar nports;
uchar portno;
- uintptr io;
+ uvlong io;
uchar *reg8;
ushort *reg16;
uint *reg;
static Vtab vtab[] = {
0x11ab, 0x4354, 1514, "88e8040", /* unsure on mtu */
0x11ab, 0x4362, 1514, "88e8053",
+ 0x11ab, 0x4363, 1514, "88e8055",
0x11ab, 0x4364, 1514, "88e8056",
0x11ab, 0x4380, 1514, "88e8057",
0x11ab, 0x436b, 1514, "88e8071", /* unsure on mtu */
static int debug;
static Ctlr *ctlrtab[Nctlr];
static int nctlr;
-static struct {
- union {
- struct {
- Lock;
- Block *b;
- uint starve;
- };
- uchar pad[128]; /* cacheline */
- };
- Kproc *k;
- Block *x;
- uint nfast;
- uint nslow;
-} rbtab[Nctlr];
static int
icansleep(void *v)
k->event = 0;
}
-static Status*
-getslot(Sring *r, Kproc *k)
-{
- if(r->rp + r->m - r->wp & ~r->m)
- starve(k);
- return r->r + (r->wp++ & r->m);
-}
-
static int
getnslot(Sring *r, uint *wp, Status **t, uint n)
{
int i;
- if(r->rp + r->m - (n - 1) - wp[0] & ~r->m)
+ if(r->m - (int)(wp[0] - r->rp) < n)
return -1;
for(i = 0; i < n; i++)
t[i] = r->r + (wp[0]++ & r->m);
return 0;
}
-/* assume allocs come from a single thread; 30*0.999x speedup */
-static Block*
-rballoc(int t)
-{
- Block *b;
-
- if((b = rbtab[t].x) != nil){
- rbtab[t].nfast++;
- rbtab[t].x = b->next;
- b->next = nil;
-b->ref = 1;
- return b;
- }
-
- ilock(&rbtab[t]);
- b = rbtab[t].x = rbtab[t].b;
- rbtab[t].b = nil;
- if(b == nil)
- rbtab[t].starve = 1;
- iunlock(&rbtab[t]);
-
- rbtab[t].nslow++;
- if(b != nil){
- rbtab[t].x = b->next;
- b->next = nil;
-b->ref = 1;
- }
- return b;
-}
-
-static void
-rbfree(Block *b, int t)
-{
- b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
- b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
- ilock(&rbtab[t]);
- b->next = rbtab[t].b;
- if(b->next == nil && rbtab[t].starve){
- rbtab[t].starve = 0;
- unstarve(rbtab[t].k);
- }
- rbtab[t].b = b;
- iunlock(&rbtab[t]);
-}
-
-static void
-rbfree0(Block *b)
-{
- rbfree(b, 0);
-}
-
-static void
-rbfree1(Block *b)
-{
- rbfree(b, 1);
-}
-
-static void
-rbfree2(Block *b)
-{
- rbfree(b, 2);
-}
-
-static void
-rbfree3(Block *b)
-{
- rbfree(b, 3);
-}
-
-static Freefn freetab[Nctlr] = {
- rbfree0,
- rbfree1,
- rbfree2,
- rbfree3,
-};
-
static uint
macread32(Ctlr *c, uint r)
{
Block *b;
Ctlr *c;
Ether *e;
- Kproc *k;
Sring *r;
- Status *t;
+ Status *tab[2], *t;
e = v;
c = e->ctlr;
- k = &c->txmit;
r = &c->tx;
txinit(e);
for(;;){
if((b = qbread(e->oq, 100000)) == nil)
break;
- if(Pciwaddrh(b->rp) != 0){
- t = getslot(r, k);
+ while(getnslot(r, &r->wp, tab, 1 + is64()) == -1)
+ starve(&c->txmit);
+ t = tab[is64()];
+ c->tbring[t - r->r] = b;
+ if(is64()){
+ Status *t = tab[0];
t->ctl = 0;
t->op = Oaddr64 | Hw;
putle(t->status, Pciwaddrh(b->rp), 4);
}
- t = getslot(r, k);
- c->tbring[t - r->r] = b;
putle(t->status, Pciwaddrl(b->rp), 4);
putle(t->l, BLEN(b), 2);
t->op = Opkt | Hw;
static void
rxinit(Ether *e)
{
- int i;
Ctlr *c;
- Block *b;
Sring *r;
Status *t;
if(c->rxinit == 1)
return;
c->rxinit = 1;
- for(i = 0; i < Nrb; i++){
- b = allocb(c->rbsz + Rbalign);
- b->free = freetab[c->qno];
- freeb(b);
- }
-
qinit(c, Qr);
if(c->type == Yukecu && (c->rev == 2 || c->rev == 3))
qrwrite(c, Qr + Qtest, Qramdis);
pinit(c, Qr, &c->rx);
if((c->flag & Fnewle) == 0){
- t = getslot(r, &c->rxmit);
+ while(getnslot(r, &r->wp, &t, 1) == -1)
+ starve(&c->rxmit);
putle(t->status, 14<<16 | 14, 4);
t->ctl = 0;
t->op = Ock | Hw;
Ctlr *c;
c = e->ctlr;
- if(wp - r->rp > r->cnt){
- print("rxscrew1 wp %ud(%ud) rp %ud %lud\n", wp, r->wp, r->rp, t-r->r);
+ if((int)(wp - r->rp) >= r->cnt){
+ print("rxscrew1 wp %ud(%ud) rp %ud %zd\n", wp, r->wp, r->rp, t-r->r);
return -1;
}
if(c->rbring[t - r->r]){
- print("rxscrew2 wp %ud rp %ud %lud\n", wp, r->rp, t-r->r);
+ print("rxscrew2 wp %ud rp %ud %zd\n", wp, r->rp, t-r->r);
descriptorfu(e, Qr);
return -1;
}
static int
replenish(Ether *e, Ctlr *c)
{
- int req, n, lim;
+ int n, lim;
uint wp;
Block *b;
Sring *r;
r = &c->rx;
wp = r->wp;
- req = 1 + is64();
lim = r->cnt/2;
if(lim > 128)
lim = 128; /* hw limit? */
for(n = 0; n < lim; n++){
- b = rballoc(c->qno);
- if(b == nil || getnslot(r, &wp, tab, req) == -1){
+ b = iallocb(c->rbsz + Rbalign);
+ if(b == nil || getnslot(r, &wp, tab, 1 + is64()) == -1){
+ freeb(b);
+ break;
+ }
+ b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
+
+ t = tab[is64()];
+ if(rxscrew(e, r, t, wp) == -1){
freeb(b);
break;
}
- t = tab[0];
+ c->rbring[t - r->r] = b;
+
if(is64()){
+ Status *t = tab[0];
putle(t->status, Pciwaddrh(b->wp), 4);
t->ctl = 0;
t->op = Oaddr64 | Hw;
- t = tab[1];
}
- if(rxscrew(e, r, t, wp) == -1)
- break;
- assert(c->rbring[t - r->r] == nil);
- c->rbring[t - r->r] = b;
-
putle(t->status, Pciwaddrl(b->wp), 4);
putle(t->l, c->rbsz, 2);
t->ctl = 0;
t->op = Opkt | Hw;
}
if(n>0){
+ r->wp = wp;
sfence();
prwrite16(c, Qr + Pputidx, wp & r->m);
- r->wp = wp;
dprint("yuk: replenish %d %ud-%ud [%d-%d]\n", n, r->rp, wp, r->rp&r->m, wp&r->m);
}
- return lim - n == 0;
+ return n == lim;
}
static void
{
Ctlr *c;
Ether *e;
- Kproc *k;
e = v;
c = e->ctlr;
- k = &c->rxmit;
rxinit(e);
linkup(c, Rxen);
while(waserror())
;
- for(;;)
- if(replenish(e, c) == 0){
- starve(k);
- print("yuk: rx unstarve?\n");
- }
+ for(;;){
+ if(replenish(e, c) == 0)
+ starve(&c->rxmit);
+ }
}
static void
static void
txcleanup(Ctlr *c, uint end)
{
- uint rp0, rp;
+ uint rp;
Block *b;
Sring *r;
Status *t;
r = &c->tx;
- rp0 = r->rp & r->m;
- for(rp = rp0; rp != end; rp = r->rp & r->m){
+ end &= r->m;
+ for(rp = r->rp & r->m; rp != end; rp = r->rp & r->m){
t = r->r + rp;
r->rp++;
if((t->ctl & Eop) == 0)
if(b != nil)
freeb(b);
}
- if(r->wp - r->rp > 16){ /* BOTCH */
- print("TX unstarve %ud - %ud \n", r->wp, r->rp);
- unstarve(&c->txmit);
- }
+ unstarve(&c->txmit);
}
static void
c = e->ctlr;
r = &c->rx;
for(rp = r->rp;;){
+ if(rp == r->wp){
+ print("#l%d: yuk rx empty\n", e->ctlrno);
+ return;
+ }
i = rp++&r->m;
b = c->rbring[i];
c->rbring[i] = nil;
if(b != nil)
break;
}
+ r->rp = rp;
cnt = x>>16 & 0x7fff;
- if(cnt != l || x&Rxerror &&
+ if((cnt != l || x&Rxerror) &&
!(c->type == Yukfep && c->rev == 0)){
print("#l%d: yuk rx error %.4ux\n", e->ctlrno, x&0xffff);
freeb(b);
}else{
b->wp += l;
- b->lim = b->wp; /* lie like a dog */
b->flag |= flag;
- etheriq(e, b, 1);
+ etheriq(e, b);
}
- r->rp = rp;
+ unstarve(&c->rxmit);
}
static uint
static void
sring(Ether *e)
{
- uint i, p, lim, op, l, x;
+ uint i, lim, op, l, x;
Ctlr *c;
Sring *r;
Status *s;
c = e->ctlr;
r = &c->status;
- lim = r->rp & r->m;
- p = 0;
+ lim = c->reg16[Stathd] & r->m;
for(;;){
- if((r->rp & r->m) == lim){
- lim = c->reg16[Stathd];
- if((r->rp & r->m) == lim)
+ i = r->rp & r->m;
+ if(i == lim){
+ lim = c->reg16[Stathd] & r->m;
+ if(i == lim)
break;
}
- i = r->rp & r->m;
s = r->r + i;
op = s->op;
if((op & Hw) == 0)
x = getle(s->status, 4);
rx(e, l, x, cksum(c, ck, s->ctl));
ck = Badck;
- p++;
break;
case Otxidx:
l = getle(s->l, 2);
s->op = 0;
r->rp++;
}
- while(p && replenish(e, c) != 0)
- ;
c->reg[Statctl] = Statirqclr;
}
uint cause, d;
Ether *e;
Ctlr *c;
- Kproc *k;
e = v;
c = e->ctlr;
- k = &c->iproc;
while(waserror())
;
for(;;){
- starve(k);
+ starve(&c->iproc);
cause = c->reg[Eisr];
if(cause & Iphy)
link(e);
e = v;
c = e->ctlr;
+ /* reading Isrc2 masks interrupts */
cause = c->reg[Isrc2];
- if(cause != 0 && cause != ~0)
- unstarve(&c->iproc);
+ if(cause == 0 || cause == ~0){
+ /* reenable interrupts */
+ c->reg[Icr] = 2;
+ return;
+ }
+ unstarve(&c->iproc);
}
static void
p = seprint(p, e, "%s\t%ud\n", stattab[i].name, u);
}
p = seprint(p, e, "stat %.4ux ctl %.3ux\n", gmacread(c, Stat), gmacread(c, Ctl));
- p = seprint(p, e, "irq %.8ux\n", c->reg[Isrc2]);
p = seprint(p, e, "pref %.8ux %.4ux\n", prread32(c, Qr + Pctl), prread16(c, Qr + Pgetidx));
- p = seprint(p, e, "nfast %ud nslow %ud\n", rbtab[c->qno].nfast, rbtab[c->qno].nslow);
if(debug){
p = dumppci(c, p, e);
p = dumpgmac(c, p, e);
Pcidev *p;
p = c->p;
+ if(p->mem[0].bar & 1)
+ return -1;
c->io = p->mem[0].bar&~0xf;
mem = vmap(c->io, p->mem[0].size);
if(mem == nil){
- print("yuk: cant map %#p\n", c->io);
+ print("yuk: cant map %llux\n", c->io);
return -1;
}
+ pcienable(p);
c->p = p;
c->reg = (uint*)mem;
c->reg8 = (uchar*)mem;
c->rx.r = slice(&v, 16*4096, sizeof c->rx.r[0] * c->rx.cnt);
c->nports = 1; /* BOTCH */
- pcisetbme(p);
if(reset(c)){
print("yuk: cant reset\n");
- pciclrbme(p);
free(c->alloc);
vunmap(mem, p->mem[0].size);
+ pcidisable(p);
return -1;
}
macinit(c);
+ pcisetbme(p);
return 0;
}
return;
}
c = malloc(sizeof *c);
+ if(c == nil){
+ print("yuk: no memory for Ctlr\n");
+ return;
+ }
c->p = p;
c->qno = nctlr;
- rbtab[c->qno].k = &c->rxmit;
c->rbsz = vtab[i].mtu;
ctlrtab[nctlr++] = c;
}
c = ctlrtab[i];
if(c == nil || c->flag&Fprobe)
continue;
- if(e->port != 0 && e->port != (ulong)c->reg)
+ if(e->port != 0 && e->port != (ulong)(uintptr)c->reg)
continue;
c->flag |= Fprobe;
if(setup(c) != 0)
e->attach = attach;
e->ctl = ctl;
e->ifstat = ifstat;
- e->interrupt = interrupt;
e->multicast = multicast;
e->promiscuous = promiscuous;
e->shutdown = shutdown;
e->transmit = nil;
+ intrenable(e->irq, interrupt, e, e->tbdf, e->name);
+
return 0;
}