static void igbetransmit(Ether* edev) { Block *bp; Ctlr *ctlr; Tdesc *tdesc; RingBuf *tb; int tdh; /* * For now there are no smarts here. Tuning comes later. */ ctlr = edev->ctlr; ilock(&ctlr->tdlock); /* * Free any completed packets * - try to get the soft tdh to catch the tdt; * - if the packet had an underrun bump the threshold * - the Tu bit doesn't seem to ever be set, perhaps * because Rs mode is used? */ tdh = ctlr->tdh; for(;;){ tdesc = &ctlr->tdba[tdh]; if(!(tdesc->status & Tdd)) break; if(tdesc->status & Tu){ ctlr->ett++; csr32w(ctlr, Ett, ctlr->ett); } tdesc->status = 0; if(ctlr->tb[tdh] != nil){ freeb(ctlr->tb[tdh]); ctlr->tb[tdh] = nil; } tdh = NEXT(tdh, Ntdesc); } ctlr->tdh = tdh; /* copy packets from the software RingBuf to the transmission q */ /* from boot ether83815.c */ while((tb = &edev->tb[edev->ti])->owner == Interface){ bp = fromringbuf(edev); /* put the buffer on the transmit queue */ if(ctlr->bqhead) ctlr->bqtail->next = bp; else ctlr->bqhead = bp; ctlr->bqtail = bp; txstart(edev); /* kick transmitter */ tb->owner = Host; /* give descriptor back */ edev->ti = NEXT(edev->ti, edev->ntb); } iunlock(&ctlr->tdlock); }
static void transmit(Ether* ether) { Ctlr *ctlr; ctlr = ether->ctlr; ilock(&ctlr->tlock); txstart(ether); iunlock(&ctlr->tlock); }
static void i82563transmit(Ether* edev) { Block *bp; Ctlr *ctlr; Tdesc *tdesc; RingBuf *tb; int tdh; ctlr = edev->ctlr; ilock(&ctlr->tdlock); /* * Free any completed packets * - try to get the soft tdh to catch the tdt; * - if the packet had an underrun bump the threshold * - the Tu bit doesn't seem to ever be set, perhaps * because Rs mode is used? */ tdh = ctlr->tdh; for(;;){ tdesc = &ctlr->tdba[tdh]; if(!(tdesc->status & Tdd)) break; if(ctlr->tb[tdh] != nil){ freeb(ctlr->tb[tdh]); ctlr->tb[tdh] = nil; } tdesc->status = 0; tdh = NEXT(tdh, Ntdesc); } ctlr->tdh = tdh; /* copy packets from the software RingBuf to the transmission q */ while((tb = &edev->tb[edev->ti])->owner == Interface){ bp = fromringbuf(edev); // print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp, // bp->rp+6); if(ctlr->bqhead) ctlr->bqtail->next = bp; else ctlr->bqhead = bp; ctlr->bqtail = bp; txstart(edev); /* kick transmitter */ tb->owner = Host; /* give descriptor back */ edev->ti = NEXT(edev->ti, edev->ntb); } iunlock(&ctlr->tdlock); }
static void interrupt(Ureg*, void *arg) { int sts, nb, ext, avail; Ctlr *ctlr; Block *b; IICregs *iic; ctlr = arg; iic = ctlr->regs; if(0) iicdump("intr", iic); sts = iic->sts; if(sts & Pt) iprint("iic: unexpected status: %.2ux", iic->sts); ext = iic->extsts; if(sts & Mdbs) nb = iic->xfrcnt & 7; else nb = 0; eieio(); iic->sts = sts; if(sts & Err && (ext & (La|Xfra)) != 0) iprint("iic: s=%.2ux es=%.2ux (IO)\n", sts, ext); ctlr->status = ext; switch(ctlr->phase) { default: iprint("iic: unexpected interrupt: p-%d s=%.2ux es=%.2ux\n", ctlr->phase, sts, ext); break; case Halting: ctlr->phase = Idle; break; case Busy: b = ctlr->b; if(b == nil) panic("iic: no buffer"); if(ctlr->cntl & Read) { /* copy data in from FIFO */ avail = b->lim - b->wp; if(nb > avail) nb = avail; while(--nb >= 0) *b->wp++ = iic->mdbuf; /* ``the IIC interface handles the [FIFO] latency'' (22-4) */ if(sts & Err || ctlr->rdcount <= 0) { ctlr->phase = Done; wakeup(&ctlr->r); break; } rxstart(ctlr); } else { /* account for data transmitted */ if((b->rp += nb) > b->wp) b->rp = b->wp; if(sts & Err || BLEN(b) <= 0) { ctlr->phase = Done; wakeup(&ctlr->r); break; } txstart(ctlr); } } }
static void interrupt(Ureg*, void *arg) { int sts, idl; Ctlr *ctlr; Block *b; I2Cregs *i2c; char xx[12]; ctlr = arg; i2c = ctlr->regs; idl = (i2c->ibmr & 3) == 3; if(Chatty && ctlr->phase != Read && ctlr->phase != Write){ snprint(xx, sizeof(xx), "intr %d", ctlr->phase); i2cdump(xx, i2c); } sts = i2c->isr; if(sts & (Bed | Sad | Gcad | Ald)) iprint("i2c: unexpected status: %.4ux", sts); i2c->isr = sts; ctlr->status = sts; i2c->icr &= ~(Start | Stop | Nak | Ma | Iteie); if(sts & Err){ failed(ctlr); return; } switch(ctlr->phase){ default: iprint("i2c: unexpected interrupt: p-%d s=%.4ux\n", ctlr->phase, sts); break; case Halting: ctlr->phase = Idle; break; case Subaddress: if(ctlr->salen){ /* push out next byte of subaddress */ ctlr->salen -= 8; i2c->idbr = ctlr->offset >> ctlr->salen; i2c->icr |= Aldie | Tb | Iteie; break; } /* subaddress finished */ if(ctlr->cntl & Rbit){ /* must readdress if reading to change mode */ i2c->idbr = (ctlr->addr << 1) | Rbit; i2c->icr |= Start | Tb | Iteie; ctlr->phase = Address; /* readdress */ break; } /* FALL THROUGH if writing */ case Address: /* if not sub-addressed, rxstart/txstart */ if(ctlr->cntl & Rbit) rxstart(ctlr); else txstart(ctlr); break; case Read: b = ctlr->b; if(b == nil) panic("i2c: no buffer"); /* master receive: next byte */ if(sts & Irf){ ctlr->rdcount--; if(b->wp < b->lim) *b->wp++ = i2c->idbr; } if(ctlr->rdcount <= 0 || sts & Nakrcv || idl){ if(Chatty) iprint("done: %.4ux\n", sts); done(ctlr); break; } rxstart(ctlr); break; case Write: b = ctlr->b; if(b == nil) panic("i2c: no buffer"); /* account for data transmitted */ if(BLEN(b) <= 0 || sts & Nakrcv){ done(ctlr); break; } txstart(ctlr); break; }
static void interrupt(Ureg*, void *arg) { int len, status, rcvd, xmtd, restart; ushort events; Ctlr *ctlr; BD *dre; Block *b, *nb; Ether *ether = arg; ctlr = ether->ctlr; if(!ctlr->active) return; /* not ours */ /* * Acknowledge all interrupts and whine about those that shouldn't * happen. */ events = ctlr->fcc->fcce; ctlr->fcc->fcce = events; /* clear events */ #ifdef DBG ehisto[events & 0x7f]++; #endif ctlr->interrupts++; if(events & BSY) ctlr->overrun++; if(events & TXE) ether->oerrs++; #ifdef DBG rcvd = xmtd = 0; #endif /* * Receiver interrupt: run round the descriptor ring logging * errors and passing valid receive data up to the higher levels * until we encounter a descriptor still owned by the chip. */ if(events & RXF){ dre = &ctlr->rdr[ctlr->rdrx]; dczap(dre, sizeof(BD)); while(((status = dre->status) & BDEmpty) == 0){ rcvd++; if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){ if(status & (RxeLG|RxeSH)) ether->buffs++; if(status & RxeNO) ether->frames++; if(status & RxeCR) ether->crcs++; if(status & RxeOV) ether->overflows++; print("eth rx: %ux\n", status); }else{ /* * We have a packet. Read it in. */ len = dre->length-4; b = ctlr->rcvbufs[ctlr->rdrx]; assert(dre->addr == PADDR(b->rp)); dczap(b->rp, len); if(nb = iallocb(Bufsize)){ b->wp += len; etheriq(ether, b, 1); b = nb; b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1)); b->wp = b->rp; ctlr->rcvbufs[ctlr->rdrx] = b; ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp); }else ether->soverflows++; } /* * Finished with this descriptor, reinitialise it, * give it back to the chip, then on to the next... */ dre->length = 0; dre->status = (status & BDWrap) | BDEmpty | BDInt; dcflush(dre, sizeof(BD)); ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); dre = &ctlr->rdr[ctlr->rdrx]; dczap(dre, sizeof(BD)); } } /* * Transmitter interrupt: handle anything queued for a free descriptor. */ if(events & (TXB|TXE)){ ilock(ctlr); restart = 0; while(ctlr->ntq){ dre = &ctlr->tdr[ctlr->tdri]; dczap(dre, sizeof(BD)); status = dre->status; if(status & BDReady) break; if(status & TxeDEF) ctlr->deferred++; if(status & TxeHB) ctlr->heartbeat++; if(status & TxeLC) ctlr->latecoll++; if(status & TxeRL) ctlr->retrylim++; if(status & TxeUN) ctlr->underrun++; if(status & TxeCSL) ctlr->carrierlost++; if(status & (TxeLC|TxeRL|TxeUN)) restart = 1; ctlr->retrycount += (status>>2)&0xF; b = ctlr->txb[ctlr->tdri]; if(b == nil) panic("fcce/interrupt: bufp"); ctlr->txb[ctlr->tdri] = nil; freeb(b); ctlr->ntq--; ctlr->tdri = NEXT(ctlr->tdri, Ntdre); xmtd++; } if(restart){ ctlr->fcc->gfmr &= ~ENT; delay(10); ctlr->fcc->gfmr |= ENT; cpmop(RestartTx, ctlr->fccid, 0xc); } txstart(ether); iunlock(ctlr); }