Пример #1
0
static int
smscreceive(Dev *ep)
{
	Block *b;
	uint hd;
	int n;

	if(Doburst)
		b = allocb(Hsburst*512);
	else
		b = allocb(Maxpkt+4);
	if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){
		freeb(b);
		return -1;
	}
	b->wp += n;
	while(BLEN(b) >= 4){
		hd = GET4(b->rp);
		b->rp += 4;
		n = hd >> 16;
		if(n > BLEN(b))
			break;
		if((hd & Rxerror) == 0){
			if(n == BLEN(b)){
				etheriq(b, 1);
				return 0;
			}
			etheriq(copyblock(b, n), 1);
		}
		b->rp += (n + 3) & ~3;
	}
	freeb(b);
	return 0;
}
Пример #2
0
static void
w_rxdone(Ether* ether)
{
	Ctlr* ctlr = (Ctlr*) ether->ctlr;
	int len, sp;
	WFrame f;
	Block* bp=0;
	Etherpkt* ep;

	sp = csr_ins(ctlr, WR_RXId);
	len = w_read(ctlr, sp, 0, &f, sizeof(f));
	if(len == 0){
		DEBUG("wavelan: read frame error\n");
		goto rxerror;
	}
	if(f.sts&WF_Err){
		goto rxerror;
	}
	switch(f.sts){
	case WF_1042:
	case WF_Tunnel:
	case WF_WMP:
		len = f.dlen + WSnapHdrLen;
		bp = iallocb(ETHERHDRSIZE + len + 2);
		if(!bp)
			goto rxerror;
		ep = (Etherpkt*) bp->wp;
		memmove(ep->d, f.addr1, Eaddrlen);
		memmove(ep->s, f.addr2, Eaddrlen);
		memmove(ep->type,&f.type,2);
		bp->wp += ETHERHDRSIZE;
		if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
			DEBUG("wavelan: read 802.11 error\n");
			goto rxerror;
		}
		bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen);
		break;
	default:
		len = ETHERHDRSIZE + f.dlen + 2;
		bp = iallocb(len);
		if(!bp)
			goto rxerror;
		if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
			DEBUG("wavelan: read 800.3 error\n");
			goto rxerror;
		}
		bp->wp += len;
	}

	ctlr->nrx++;
	etheriq(ether,bp,1);
	ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
	ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
	return;

rxerror:
	freeb(bp);
	ctlr->nrxerr++;
}
Пример #3
0
static void
receive(Ether *ether)
{
	int i;
	ulong n;
	Block *b;
	Ctlr *ctlr = ether->ctlr;
	Rx *r;

	ethercheck(ether);
	for (i = Nrx-2; i > 0; i--) {
		r = &ctlr->rx[ctlr->rxhead];	/* *r is uncached */
		assert(((uintptr)r & (Descralign - 1)) == 0);
		if(r->cs & RCSdmaown)		/* descriptor busy? */
			break;

		b = ctlr->rxb[ctlr->rxhead];	/* got input buffer? */
		if (b == nil)
			panic("ether1116: nil ctlr->rxb[ctlr->rxhead] "
				"in receive");
		ctlr->rxb[ctlr->rxhead] = nil;
		ctlr->rxhead = NEXT(ctlr->rxhead, Nrx);

		if((r->cs & (RCSfirst|RCSlast)) != (RCSfirst|RCSlast)) {
			ctlr->nofirstlast++;	/* partial packet */
			freeb(b);
			continue;
		}
		if(r->cs & RCSmacerr) {
			freeb(b);
			continue;
		}

		n = r->countsize >> 16;		/* TODO includes 2 pad bytes? */
		assert(n >= 2 && n < 2048);

		/* clear any cached packet or part thereof */
		l2cacheuinvse(b->rp, n+2);
		cachedinvse(b->rp, n+2);
		b->wp = b->rp + n;
		/*
		 * skip hardware padding intended to align ipv4 address
		 * in memory (mv-s104860-u0 §8.3.4.1)
		 */
		b->rp += 2;
		etheriq(ether, b, 1);
		etheractive(ether);
		if (i % (Nrx / 2) == 0) {
			rxreplenish(ctlr);
			rxkick(ctlr);
		}
	}
	rxreplenish(ctlr);
	rxkick(ctlr);
}
Пример #4
0
void
wifiiq(Wifi *wifi, Block *b)
{
    SNAP s;
    Wifipkt h, *w;
    Etherpkt *e;
    int hdrlen;

    if(BLEN(b) < WIFIHDRSIZE)
        goto drop;
    w = (Wifipkt*)b->rp;
    hdrlen = wifihdrlen(w);
    if(BLEN(b) < hdrlen)
        goto drop;
    if(w->fc[1] & 0x40) {
        /* encrypted */
        qpass(wifi->iq, b);
        return;
    }
    switch(w->fc[0] & 0x0c) {
    case 0x00:	/* management */
        if((w->fc[1] & 3) != 0x00)	/* STA->STA */
            break;
        qpass(wifi->iq, b);
        return;
    case 0x04:	/* control */
        break;
    case 0x08:	/* data */
        b->rp += hdrlen;
        switch(w->fc[0] & 0xf0) {
        default:
            goto drop;
        case 0x80:	/* QOS */
        case 0x00:
            break;
        }
        if(BLEN(b) < SNAPHDRSIZE)
            break;
        memmove(&s, b->rp, SNAPHDRSIZE);
        if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3)
            break;
        if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0)
            break;
        b->rp += SNAPHDRSIZE-ETHERHDRSIZE;
        h = *w;
        e = (Etherpkt*)b->rp;
        memmove(e->d, dstaddr(&h), Eaddrlen);
        memmove(e->s, srcaddr(&h), Eaddrlen);
        memmove(e->type, s.type, 2);
        etheriq(wifi->ether, b, 1);
        return;
    }
drop:
    freeb(b);
}
Пример #5
0
static void
receive(Ether* ether)
{
	int port;
	Block* bp;
	int pktno, status, len;

	/* assumes ctlr is locked and bank 2 is selected */
	/* leaves bank 2 selected on return */
	port = ether->port;

	pktno = ins(port + FifoPorts);
	if (pktno & FpRxEmpty) {
		return;
	}

	outs(port + Pointer, PtrRead | PtrRcv | PtrAutoInc);
	status = ins(port + Data1);
	len = ins(port + Data1) & RxLenMask - HdrSize;
	
	if (status & RsOddFrame)
		len++;
	
	if ((status & RsError) || (bp = iallocb(len)) == 0) {

		if (status & RsAlgnErr)
			ether->frames++;
		if (status & (RsTooShort | RsTooLong))
			ether->buffs++;
		if (status & RsBadCrc)
			ether->crcs++;

		outs(port + MmuCmd, McRelease);
		return;
	}

	/* packet length is padded to word */
	inss(port + Data1, bp->rp, len / 2);
	bp->wp = bp->rp + (len & ~1);
	
	if (len & 1) {
		*bp->wp = inb(port + Data1);
		bp->wp++;
	}
	  
	etheriq(ether, bp, 1);
	ether->inpackets++;
	outs(port + MmuCmd, McRelease);
}
Пример #6
0
static void
vgberxeof(Ether* edev)
{
	Ctlr* ctlr;
	int i;
	Block* block;
	ulong length, status;
	RxDesc* desc;

	ctlr = edev->ctlr;

	if(ctlr->debugflags & DumpRx)
		print("vgbe: rx_eof\n");

	for(i = 0; i < RxCount; i++){
		/* Remember that block. */
		desc = &ctlr->rx_ring[i];

		status = le32toh(desc->status);

		if(status & RxDesc_Status_Own)
			continue;

		if(status & RxDesc_Status_Goodframe){
			length = status >> RxDesc_Status_SizShift;
			length &= RxDesc_Status_SizMask;

			if(ctlr->debugflags & DumpRx)
				print("vgbe: Rx-desc[%03d] status=%#08ulx ctl=%#08ulx len=%uld bytes\n",
					i, status, desc->control, length);

			block = ctlr->rx_blocks[i];
			block->wp = block->rp + length;

			ctlr->stats.rx++;
			etheriq(edev, block, 1);
		}
		else
Пример #7
0
static void
vt6102receive(Ether* edev)
{
	Ds *ds;
	Block *bp;
	Ctlr *ctlr;
	int i, len;

	ctlr = edev->ctlr;

	ds = ctlr->rdh;
	while(!(ds->status & Own) && ds->status != 0){
		if(ds->status & Rerr){
			for(i = 0; i < Nrxstats; i++){
				if(ds->status & (1<<i))
					ctlr->rxstats[i]++;
			}
		}
		else if(bp = iallocb(Rdbsz+3)){
			len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
			ds->bp->wp = ds->bp->rp+len;
			etheriq(edev, ds->bp, 1);
			bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
			ds->addr = PCIWADDR(bp->rp);
			ds->bp = bp;
		}
		ds->control = Rdbsz;
		ds->branch = 0;
		ds->status = 0;

		ds->prev->branch = PCIWADDR(ds);
		coherence();
		ds->prev->status = Own;

		ds = ds->next;
	}
Пример #8
0
static void
interrupt(Ureg*, void* arg)
{
	Ctlr *ctlr;
	Ether *ether;
	int len, status;
	Des *des;
	Block *bp;

	ether = arg;
	ctlr = ether->ctlr;

	while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
		/*
		 * Acknowledge the interrupts and mask-out
		 * the ones that are implicitly handled.
		 */
		csr32w(ctlr, 5, status);
		status &= (ctlr->mask & ~(Nis|Ti));

		if(status & Ais){
			if(status & Tps)
				ctlr->tps++;
			if(status & Tu)
				ctlr->tu++;
			if(status & Tjt)
				ctlr->tjt++;
			if(status & Ru)
				ctlr->ru++;
			if(status & Rps)
				ctlr->rps++;
			if(status & Rwt)
				ctlr->rwt++;
			status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps);
		}

		/*
		 * Received packets.
		 */
		if(status & Ri){
			des = &ctlr->rdr[ctlr->rdrx];
			while(!(des->status & Own)){
				if(des->status & Es){
					if(des->status & Of)
						ctlr->of++;
					if(des->status & Ce)
						ctlr->ce++;
					if(des->status & Cs)
						ctlr->cs++;
					if(des->status & Tl)
						ctlr->tl++;
					if(des->status & Rf)
						ctlr->rf++;
					if(des->status & De)
						ctlr->de++;
				}
				else if(bp = iallocb(Rbsz)){
					len = ((des->status & Fl)>>16)-4;
					des->bp->wp = des->bp->rp+len;
					etheriq(ether, des->bp, 1);
					des->bp = bp;
					des->addr = PCIWADDR(bp->rp);
				}

				des->control &= Er;
				des->control |= Rbsz;
				coherence();
				des->status = Own;

				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
				des = &ctlr->rdr[ctlr->rdrx];
			}
			status &= ~Ri;
		}
Пример #9
0
static void
interrupt(Ureg*, void*arg)
{
	Ctlr*ctlr;
	Ether*ether = arg;
	Etherpkt*pkt;
	ushort ie;
	int rx, len;
	Block *b;

	ctlr = ether->ctlr;
	if(!ctlr->active)
		return;	/* not ours */
	ctlr->interrupts++;

	ilock(ctlr);
	ie = *eisr;
	*eisr = ie;
	intack();

	if(ie==0)
		iprint("interrupt: no interrupt source?\n");

	if(ie&Ei_txdone){
		if((*etcr&Etcr_txstart)==0){
			if(ctlr->txbusy){
				ctlr->txbusy = 0;
				ctlr->ntx--;
				ctlr->txfull++;
				if(ctlr->txfull==Ntx)
					ctlr->txfull = 0;
			}
			txrestart(ctlr);
			txfill(ether, ctlr);
			txrestart(ctlr);
		}
		else
			iprint("interrupt: bogus tx interrupt\n");
		ie &= ~Ei_txdone;
	}

	if(ie&Ei_rxdone){
		rx=*ersr&Ersr_rxfpmask;
		while(ctlr->rxlast!=rx){

			ctlr->rxlast++;
			if(ctlr->rxlast >= Nrx)
				ctlr->rxlast = 0;

			pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);
			len = *(ushort*)pkt;
			if((b = iallocb(len+sizeof(ushort))) != nil){
				memmove(b->wp, pkt, len+sizeof(ushort));
				b->rp += sizeof(ushort);
				b->wp = b->rp + len;
				etheriq(ether, b, 1);
			}else
				ether->soverflows++;
			rx=*ersr&Ersr_rxfpmask;
		}
		ie &= ~Ei_rxdone;
	}

	if(ie&Ei_txretry){
		iprint("ethersaturn: txretry!\n");
		ie &= ~Ei_txretry;
		ctlr->txbusy = 0;
		txrestart(ctlr);
	}

	ie &= ~Ei_txcrs;
	if(ie)
		iprint("interrupt: unhandled interrupts %.4uX\n", ie);
	iunlock(ctlr);
}
Пример #10
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);
	}