diff options
-rw-r--r-- | sys/src/9/sgi/etherseeq.c | 102 |
1 files changed, 55 insertions, 47 deletions
diff --git a/sys/src/9/sgi/etherseeq.c b/sys/src/9/sgi/etherseeq.c index 4f9d930ac..ce2036225 100644 --- a/sys/src/9/sgi/etherseeq.c +++ b/sys/src/9/sgi/etherseeq.c @@ -110,6 +110,7 @@ struct Ring { Rendez; int size; + int free; uchar* base; Desc* head; Desc* tail; @@ -119,9 +120,10 @@ enum { Eor= 1<<31, /* end of ring */ Eop= 1<<30, - Ie= 1<<29, + Ioc= 1<<29, /* interrupt on completion */ Busy= 1<<24, Empty= 1<<14, /* no data here */ + Done= 1<<15, /* transmit done */ }; enum { @@ -141,6 +143,32 @@ struct Ctlr static ulong dummy; static void +txintr(Ctlr *ctlr) +{ + Hio *io; + ulong s; + Desc *p; + + io = ctlr->io; + s = io->xstat; + if((s & Xdma) != 0) + return; + p = IO(Desc, ctlr->tx.head->next); + while((p->count & Busy) != 0){ + if((p->count & Done) == 0){ + io->nxbdp = PADDR(p); + io->xstat = Xdma; + break; + } + ctlr->tx.head = p; + p->count = Eor|Eop; + p = IO(Desc, p->next); + ctlr->tx.free++; + } + wakeup(&ctlr->tx); +} + +static void interrupt(Ureg *, void *arg) { Ether *edev; @@ -156,6 +184,7 @@ interrupt(Ureg *, void *arg) io->ctl = Cnormal | Cover; if(s & Cint) { io->ctl = Cnormal | Cint; + txintr(ctlr); wakeup(&ctlr->rx); } } @@ -164,12 +193,6 @@ static int notempty(void *arg) { Ctlr *ctlr = arg; - Hio *io; - - io = ctlr->io; - dummy = io->piocfg; - if((io->rstat & Rdma) == 0) - return 1; return (IO(Desc, ctlr->rx.head->next)->count & Empty) == 0; } @@ -178,7 +201,6 @@ rxproc(void *arg) { Ether *edev = arg; Ctlr *ctlr; - Hio *io; Block *b; Desc *p; int n; @@ -187,12 +209,9 @@ rxproc(void *arg) ; ctlr = edev->ctlr; - io = ctlr->io; for(p = IO(Desc, ctlr->rx.head->next);; p = IO(Desc, p->next)){ - while((p->count & Empty) != 0){ - io->rstat = Rdma; - tsleep(&ctlr->rx, notempty, ctlr, 500); - } + while((p->count & Empty) != 0) + sleep(&ctlr->rx, notempty, ctlr); n = Rbsize - (p->count & 0x3fff)-3; if(n >= ETHERMINTU){ if((p->base[n+2] & Rok) != 0){ @@ -203,50 +222,35 @@ rxproc(void *arg) } } p->addr = PADDR(p->base); - p->count = Ie|Empty|Rbsize; + p->count = Ioc|Empty|Rbsize; ctlr->rx.head = p; } } +static int +notbusy(void *arg) +{ + Ctlr *ctlr = arg; + return ctlr->tx.free > 0; +} + static void txproc(void *arg) { Ether *edev = arg; Ctlr *ctlr; - Hio *io; Block *b; Desc *p; - int clean, n; + int n; while(waserror()) ; ctlr = edev->ctlr; - io = ctlr->io; - clean = ctlr->tx.size / 2; for(p = IO(Desc, ctlr->tx.tail->next); (b = qbread(edev->oq, 1000000)) != nil; p = IO(Desc, p->next)){ - while(!clean){ - splhi(); - p = ctlr->tx.head; - dummy = io->piocfg; - ctlr->tx.head = IO(Desc, io->nxbdp & ~0xf); - spllo(); - while(p != ctlr->tx.head){ - if((p->count & Busy) == 0) - break; - clean++; - p->count = Eor|Eop; - p = IO(Desc, p->next); - } - - p = IO(Desc, ctlr->tx.tail->next); - if(clean) - break; - - io->xstat = Xdma; - tsleep(&ctlr->tx, return0, nil, 10); - } - clean--; + while(ctlr->tx.free == 0) + sleep(&ctlr->tx, notbusy, ctlr); + ctlr->tx.free--; n = BLEN(b); if(n > ETHERMAXTU) @@ -254,12 +258,14 @@ txproc(void *arg) memmove(p->base, b->rp, n); p->addr = PADDR(p->base); - p->count = Eor|Eop|Busy|n; + p->count = Ioc|Eor|Eop|Busy|n; - ctlr->tx.tail->count &= ~Eor; + ctlr->tx.tail->count &= ~(Ioc|Eor); ctlr->tx.tail = p; - io->xstat = Xdma; + splhi(); + txintr(ctlr); + spllo(); freeb(b); } @@ -273,7 +279,8 @@ allocring(Ring *r, int n) int m; r->size = n; - + r->free = n; + m = n*BY2PG/2; b = xspanalloc(m, BY2PG, 0); dcflush(b, m); @@ -324,7 +331,7 @@ init(Ether *edev) p = ctlr->rx.head; do { p->addr = PADDR(p->base); - p->count = Ie|Empty|Rbsize; + p->count = Ioc|Empty|Rbsize; p = IO(Desc, p->next); } while(p != ctlr->rx.head); io->crbdp = PADDR(p); @@ -336,16 +343,17 @@ init(Ether *edev) p->count = Eor|Eop; p = IO(Desc, p->next); } while(p != ctlr->tx.tail); - ctlr->tx.head = IO(Desc, p->next); io->cxbdp = PADDR(p); io->nxbdp = p->next; for(i=0; i<6; i++) io->eaddr[i] = edev->ea[i]; - io->csx = 0; /* XIok | XImaxtry | XIcoll | XIunder; -- no interrupts needed */ + io->csx = XIok | XImaxtry | XIcoll | XIunder; io->csr = Rprom | RIok|RIend|RIshort|RIdrbl|RIcrc; + io->rstat = Rdma; + return 0; } |