Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
static void
transmit(Ether* ether)
{
	Ctlr *ctlr;

	ctlr = ether->ctlr;
	ilock(&ctlr->tlock);
	txstart(ether);
	iunlock(&ctlr->tlock);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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);
        }
    }
}
Exemplo n.º 5
0
Arquivo: i2c.c Projeto: 8l/inferno
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;
	}
Exemplo n.º 6
0
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);
	}