This commit is contained in:
cinap_lenrek 2015-03-30 23:46:31 +02:00
commit 166afefab9

View file

@ -133,14 +133,16 @@ enum {
struct Ctlr struct Ctlr
{ {
int attach; int attach;
char* txerr;
ulong txwdog;
Hio *io; Hio* io;
Ring rx; Ring rx;
Ring tx; Ring tx;
}; };
static ulong dummy; static int reset(Ether*);
static void static void
txintr(Ctlr *ctlr) txintr(Ctlr *ctlr)
@ -153,17 +155,21 @@ txintr(Ctlr *ctlr)
s = io->xstat; s = io->xstat;
if((s & Xdma) != 0) if((s & Xdma) != 0)
return; return;
p = IO(Desc, ctlr->tx.head->next); if((s & Xmaxtry) != 0)
while((p->count & Busy) != 0){ ctlr->txerr = "transmission failed";
if((s & Xunder) != 0)
ctlr->txerr = "transmitter underflowed";
for(p = IO(Desc, ctlr->tx.head->next); (p->count & Busy) != 0; p = IO(Desc, p->next)){
if((p->count & Done) == 0){ if((p->count & Done) == 0){
io->nxbdp = PADDR(p); io->nxbdp = PADDR(p);
io->xstat = Xdma; io->xstat = Xdma;
ctlr->txwdog = MACHP(0)->ticks;
break; break;
} }
ctlr->tx.head = p;
p->count = Eor|Eop; p->count = Eor|Eop;
p = IO(Desc, p->next); ctlr->tx.head = p;
ctlr->tx.free++; ctlr->tx.free++;
ctlr->txwdog = 0;
} }
wakeup(&ctlr->tx); wakeup(&ctlr->tx);
} }
@ -180,8 +186,10 @@ interrupt(Ureg *, void *arg)
ctlr = edev->ctlr; ctlr = edev->ctlr;
io = ctlr->io; io = ctlr->io;
s = io->ctl; s = io->ctl;
if(s & Cover) if(s & Cover){
io->ctl = Cnormal | Cover; io->ctl = Cnormal | Cover;
edev->overflows++;
}
if(s & Cint) { if(s & Cint) {
io->ctl = Cnormal | Cint; io->ctl = Cnormal | Cint;
txintr(ctlr); txintr(ctlr);
@ -193,14 +201,31 @@ static int
notempty(void *arg) notempty(void *arg)
{ {
Ctlr *ctlr = arg; Ctlr *ctlr = arg;
return (IO(Desc, ctlr->rx.head->next)->count & Empty) == 0; return (IO(Desc, ctlr->rx.head->next)->count & Empty) == 0;
} }
static char*
checkerr(Ctlr *ctlr)
{
ulong t;
if(ctlr->txerr != nil)
return ctlr->txerr;
t = ctlr->txwdog;
if(t != 0 && TK2MS(MACHP(0)->ticks - t) > 1000)
return "transmitter dma timeout";
if((ctlr->io->rstat & Rdma) == 0)
return "recevier dma stopped";
return nil;
}
static void static void
rxproc(void *arg) rxproc(void *arg)
{ {
Ether *edev = arg; Ether *edev = arg;
Ctlr *ctlr; Ctlr *ctlr;
char *err;
Block *b; Block *b;
Desc *p; Desc *p;
int n; int n;
@ -210,16 +235,22 @@ rxproc(void *arg)
ctlr = edev->ctlr; ctlr = edev->ctlr;
for(p = IO(Desc, ctlr->rx.head->next);; p = IO(Desc, p->next)){ for(p = IO(Desc, ctlr->rx.head->next);; p = IO(Desc, p->next)){
while((p->count & Empty) != 0) while((p->count & Empty) != 0){
sleep(&ctlr->rx, notempty, ctlr); err = checkerr(ctlr);
n = Rbsize - (p->count & 0x3fff)-3; if(err != nil){
if(n >= ETHERMINTU){ print("%s: %s; reseting\n", up->text, err);
if((p->base[n+2] & Rok) != 0){ splhi();
b = allocb(n); reset(edev);
b->wp += n; spllo();
memmove(b->rp, p->base+2, n);
etheriq(edev, b, 1);
} }
tsleep(&ctlr->rx, notempty, ctlr, 500);
}
n = Rbsize - (p->count & 0x3fff)-3;
if(n >= ETHERMINTU && (p->base[n+2] & Rok) != 0){
b = allocb(n);
b->wp += n;
memmove(b->rp, p->base+2, n);
etheriq(edev, b, 1);
} }
p->addr = PADDR(p->base); p->addr = PADDR(p->base);
p->count = Ioc|Empty|Rbsize; p->count = Ioc|Empty|Rbsize;
@ -250,7 +281,6 @@ txproc(void *arg)
for(p = IO(Desc, ctlr->tx.tail->next); (b = qbread(edev->oq, 1000000)) != nil; p = IO(Desc, p->next)){ for(p = IO(Desc, ctlr->tx.tail->next); (b = qbread(edev->oq, 1000000)) != nil; p = IO(Desc, p->next)){
while(ctlr->tx.free == 0) while(ctlr->tx.free == 0)
sleep(&ctlr->tx, notbusy, ctlr); sleep(&ctlr->tx, notbusy, ctlr);
ctlr->tx.free--;
n = BLEN(b); n = BLEN(b);
if(n > ETHERMAXTU) if(n > ETHERMAXTU)
@ -264,6 +294,7 @@ txproc(void *arg)
ctlr->tx.tail = p; ctlr->tx.tail = p;
splhi(); splhi();
ctlr->tx.free--;
txintr(ctlr); txintr(ctlr);
spllo(); spllo();
@ -303,21 +334,20 @@ allocring(Ring *r, int n)
} }
static int static int
init(Ether *edev) reset(Ether *edev)
{ {
Ctlr *ctlr; Ctlr *ctlr;
Desc *p; Desc *p;
Hio *io; Hio *io;
int i; int i;
io = IO(Hio, edev->port);
ctlr = edev->ctlr; ctlr = edev->ctlr;
ctlr->io = io; io = ctlr->io;
ctlr->txerr = nil;
ctlr->txwdog = 0;
io->csx = Xreg0; io->csx = Xreg0;
allocring(&ctlr->rx, 256);
allocring(&ctlr->tx, 64);
io->rstat = 0; io->rstat = 0;
io->xstat = 0; io->xstat = 0;
io->ctl = Cnormal | Creset | Cint; io->ctl = Cnormal | Creset | Cint;
@ -336,15 +366,19 @@ init(Ether *edev)
} while(p != ctlr->rx.head); } while(p != ctlr->rx.head);
io->crbdp = PADDR(p); io->crbdp = PADDR(p);
io->nrbdp = p->next; io->nrbdp = p->next;
ctlr->rx.tail = p;
ctlr->rx.free = ctlr->rx.size;
p = ctlr->tx.tail; p = ctlr->tx.tail;
do { do {
p->addr = 0; p->addr = PADDR(p->base);
p->count = Eor|Eop; p->count = Eor|Eop;
p = IO(Desc, p->next); p = IO(Desc, p->next);
} while(p != ctlr->tx.tail); } while(p != ctlr->tx.tail);
io->cxbdp = PADDR(p); io->cxbdp = PADDR(p);
io->nxbdp = p->next; io->nxbdp = p->next;
ctlr->tx.head = p;
ctlr->tx.free = ctlr->tx.size;
for(i=0; i<6; i++) for(i=0; i<6; i++)
io->eaddr[i] = edev->ea[i]; io->eaddr[i] = edev->ea[i];
@ -354,7 +388,24 @@ init(Ether *edev)
io->rstat = Rdma; io->rstat = Rdma;
wakeup(&ctlr->rx);
wakeup(&ctlr->tx);
return 0; return 0;
}
static int
init(Ether *edev)
{
Ctlr *ctlr;
ctlr = edev->ctlr;
ctlr->io = IO(Hio, edev->port);
allocring(&ctlr->rx, 256);
allocring(&ctlr->tx, 64);
return reset(edev);
} }
/* /*
@ -379,8 +430,8 @@ attach(Ether *edev)
if(ctlr->attach) if(ctlr->attach)
return; return;
ctlr->attach = 1; ctlr->attach = 1;
kproc("#0rx", rxproc, edev); kproc("#l0rx", rxproc, edev);
kproc("#0tx", txproc, edev); kproc("#l0tx", txproc, edev);
} }
static int static int