Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/mpc/etherscc.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname mpc/etherscc.c 1999/0122
## diff -e /dev/null /n/emeliedump/1999/0122/sys/src/brazil/mpc/etherscc.c
0a
/*
 * SCCn ethernet
 */

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"

#include "etherif.h"

enum {
	Nrdre		= 16,	/* receive descriptor ring entries */
	Ntdre		= 16,	/* transmit descriptor ring entries */

	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
	Bufsize		= (Rbsize+7)&~7,	/* aligned */
};

enum {
	/* ether-specific Rx BD bits */
	RxMiss=		1<<8,
	RxeLG=		1<<5,
	RxeNO=		1<<4,
	RxeSH=		1<<3,
	RxeCR=		1<<2,
	RxeOV=		1<<1,
	RxeCL=		1<<0,
	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */

	/* ether-specific Tx BD bits */
	TxPad=		1<<14,	/* pad short frames */
	TxTC=		1<<10,	/* transmit CRC */
	TxeDEF=		1<<9,
	TxeHB=		1<<8,
	TxeLC=		1<<7,
	TxeRL=		1<<6,
	TxeUN=		1<<1,
	TxeCSL=		1<<0,

	/* scce */
	RXB=	1<<0,
	TXB=	1<<1,
	BSY=		1<<2,
	RXF=		1<<3,
	TXE=		1<<4,

	/* psmr */
	PRO=	1<<9,	/* promiscuous mode */

	/* gsmrl */
	ENR=	1<<5,
	ENT=	1<<4,
};

typedef struct Etherparam Etherparam;
struct Etherparam {
	SCCparam;
	ulong	c_pres;		/* preset CRC */
	ulong	c_mask;		/* constant mask for CRC */
	ulong	crcec;		/* CRC error counter */
	ulong	alec;		/* alighnment error counter */
	ulong	disfc;		/* discard frame counter */
	ushort	pads;		/* short frame PAD characters */
	ushort	ret_lim;	/* retry limit threshold */
	ushort	ret_cnt;	/* retry limit counter */
	ushort	mflr;		/* maximum frame length reg */
	ushort	minflr;		/* minimum frame length reg */
	ushort	maxd1;		/* maximum DMA1 length reg */
	ushort	maxd2;		/* maximum DMA2 length reg */
	ushort	maxd;		/* rx max DMA */
	ushort	dma_cnt;	/* rx dma counter */
	ushort	max_b;		/* max bd byte count */
	ushort	gaddr[4];		/* group address filter */
	ulong	tbuf0_data0;	/* save area 0 - current frm */
	ulong	tbuf0_data1;	/* save area 1 - current frm */
	ulong	tbuf0_rba0;
	ulong	tbuf0_crc;
	ushort	tbuf0_bcnt;
	ushort	paddr[3];	/* physical address LSB to MSB increasing */
	ushort	p_per;		/* persistence */
	ushort	rfbd_ptr;	/* rx first bd pointer */
	ushort	tfbd_ptr;	/* tx first bd pointer */
	ushort	tlbd_ptr;	/* tx last bd pointer */
	ulong	tbuf1_data0;	/* save area 0 - next frame */
	ulong	tbuf1_data1;	/* save area 1 - next frame */
	ulong	tbuf1_rba0;
	ulong	tbuf1_crc;
	ushort	tbuf1_bcnt;
	ushort	tx_len;		/* tx frame length counter */
	ushort	iaddr[4];		/* individual address filter*/
	ushort	boff_cnt;	/* back-off counter */
	ushort	taddr[3];	/* temp address */
};

typedef struct {
	Lock;
	int	sccid;
	int	port;
	int	init;
	int	active;
	SCC*	scc;

	Ring;

	ulong	interrupts;			/* statistics */
	ulong	deferred;
	ulong	heartbeat;
	ulong	latecoll;
	ulong	retrylim;
	ulong	underrun;
	ulong	overrun;
	ulong	carrierlost;
	ulong	retrycount;
} Ctlr;

static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
static	int	sccbase[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};

static void
attach(Ether *ether)
{
	Ctlr *ctlr;

	ctlr = ether->ctlr;
	ctlr->active = 1;
	ctlr->scc->gsmrl |= ENR|ENT;
	eieio();
//	m->bcsr[1] &= ~DisableEther;
}

static void
closed(Ether *ether)
{
	Ctlr *ctlr;

	ctlr = ether->ctlr;
	if(0){
		if(ether->port == 2)
			scc2stop(ctlr->scc);
		ilock(ctlr);
		ctlr->active = 0;
		iunlock(ctlr);
		print("Ether closed\n");
	}
}

static void
promiscuous(void* arg, int on)
{
	Ether *ether;
	Ctlr *ctlr;

	ether = (Ether*)arg;
	ctlr = ether->ctlr;

	ilock(ctlr);
	if(on || ether->nmaddr)
		ctlr->scc->psmr |= PRO;
	else
		ctlr->scc->psmr &= ~PRO;
	iunlock(ctlr);
}

static void
multicast(void* arg, uchar *addr, int on)
{
	Ether *ether;
	Ctlr *ctlr;

	USED(addr, on);	/* if on, could SetGroupAddress; if !on, it's hard */

	ether = (Ether*)arg;
	ctlr = ether->ctlr;

	ilock(ctlr);
	if(ether->prom || ether->nmaddr)
		ctlr->scc->psmr |= PRO;
	else
		ctlr->scc->psmr &= ~PRO;
	iunlock(ctlr);
}

static void
txstart(Ether *ether)
{
	int len;
	Ctlr *ctlr;
	Block *b;
	BD *dre;

	ctlr = ether->ctlr;
	if(ctlr->init)
		return;
	while(ctlr->ntq < Ntdre-1){
		b = qget(ether->oq);
		if(b == 0)
			break;

		dre = &ctlr->tdr[ctlr->tdrh];
		if(dre->status & BDReady)
			panic("ether: txstart");
	
		/*
		 * Give ownership of the descriptor to the chip, increment the
		 * software ring descriptor pointer and tell the chip to poll.
		 */
		len = BLEN(b);
		dcflush(b->rp, len);
		if(ctlr->txb[ctlr->tdrh] != nil)
			panic("scc/ether: txstart");
		ctlr->txb[ctlr->tdrh] = b;
		if((ulong)b->rp&1)
			panic("scc/ether: txstart align");	/* TO DO: ensure alignment */
		dre->addr = PADDR(b->rp);
		dre->length = len;
		eieio();
		dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
		eieio();
		ctlr->scc->todr = 1<<15;	/* transmit now */
		eieio();
		ctlr->ntq++;
		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
	}
}

static void
transmit(Ether* ether)
{
	Ctlr *ctlr;

	ctlr = ether->ctlr;
	ilock(ctlr);
	txstart(ether);
	iunlock(ctlr);
}

static void
interrupt(Ureg*, Ether *ether)
{
	int len, events, status;
	Ctlr *ctlr;
	BD *dre;
	Block *b;

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

	/*
	 * Acknowledge all interrupts and whine about those that shouldn't
	 * happen.
	 */
	events = ctlr->scc->scce;
	eieio();
	ctlr->scc->scce = events;
	eieio();
	ctlr->interrupts++;

	if(events & (TXE|BSY|RXB)){
		if(events & RXB)
			ctlr->overrun++;
		if(events & TXE)
			ether->oerrs++;
		if(0 || events & TXE)
			print("ETHER.SCC#%d: scce = 0x%uX\n", ether->ctlrno, events);
	}
	/*
	 * 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|RXB) || 1){
		dre = &ctlr->rdr[ctlr->rdrx];
		while(((status = dre->status) & BDEmpty) == 0){
			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;
				if((b = iallocb(len)) != 0){
					memmove(b->wp, KADDR(dre->addr), len);
					b->wp += len;
					etheriq(ether, b, 1);
					dcflush(KADDR(dre->addr), len);
				}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;
			eieio();

			ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
			dre = &ctlr->rdr[ctlr->rdrx];
		}
	}

	/*
	 * Transmitter interrupt: handle anything queued for a free descriptor.
	 */
	if(events & TXB){
		lock(ctlr);
		while(ctlr->ntq){
			dre = &ctlr->tdr[ctlr->tdri];
			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++;
			ctlr->retrycount += (status>>2)&0xF;
			b = ctlr->txb[ctlr->tdri];
			if(b == nil)
				panic("scce/interrupt: bufp");
			ctlr->txb[ctlr->tdri] = nil;
			freeb(b);
			ctlr->ntq--;
			ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
		}
		txstart(ether);
		unlock(ctlr);
	}
	if(events & TXE)
		cpmop(RestartTx, ctlr->sccid, 0);
}

static long
ifstat(Ether* ether, void* a, long n, ulong offset)
{
	char *p;
	int len;
	Ctlr *ctlr;

	if(n == 0)
		return 0;

	ctlr = ether->ctlr;

	p = malloc(READSTR);
	len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
	len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
	len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
	len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
	len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
	len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
	len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
	len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
	snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
	n = readstr(offset, a, n, p);
	free(p);

	return n;
}

/*
 * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
 * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
 * and those for the 860/821 development board for SCC1.
 */
static void
sccsetup(Ctlr *ctlr, SCC *scc, uchar *ea)
{
	int i, rcs, tcs;
	Etherparam *p;
	IMM *io;

	io = ioplock();
	if(ctlr->port == 2){
		io->papar |= SIBIT(12)|SIBIT(13);	/* enable TXD2 and RXD2 pins */
		io->padir &= ~(SIBIT(12)|SIBIT(13));
		io->paodr &= ~SIBIT(12);

		io->pcpar &= ~(SIBIT(9)|SIBIT(8));	/* enable CLSN (CTS2) and RENA (CD2) */
		io->pcdir &= ~(SIBIT(9)|SIBIT(8));
		io->pcso |= SIBIT(9)|SIBIT(8);

		io->papar |= SIBIT(6)|SIBIT(5);	/* enable CLK2 and CLK3 */
		io->padir &= ~(SIBIT(6)|SIBIT(5));
		eieio();

		rcs = CLK2;
		tcs = CLK3;
	}else{
		io->papar |= SIBIT(14)|SIBIT(15);	/* enable TXD1 and RXD1 pins */
		io->padir &= ~(SIBIT(14)|SIBIT(15));
		io->paodr &= ~SIBIT(14);

		io->pcpar &= ~(SIBIT(10)|SIBIT(11));	/* enable CLSN (CTS1) and RENA (CD1) */
		io->pcdir &= ~(SIBIT(10)|SIBIT(11));
		io->pcso |= SIBIT(10)|SIBIT(11);
		eieio();

		io->papar |= SIBIT(6)|SIBIT(7);	/* enable CLK2 and CLK1 */
		io->padir &= ~(SIBIT(6)|SIBIT(7));
		eieio();

		io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6));	/* ETHLOOP, TPFULDL~, TPSQEL~ */
		io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
		io->pcdat &= ~SIBIT(4);
		io->pcdat |= SIBIT(5)|SIBIT(6);
		eieio();

		rcs = CLK2;
		tcs = CLK1;
	}
	iopunlock();

	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */

	p = (Etherparam*)KADDR(ctlr->sccid==SCC1ID? SCC1P: SCC2P);
	memset(p, 0, sizeof(*p));
	p->rfcr = 0x18;
	p->tfcr = 0x18;
	p->mrblr = Bufsize;
	p->rbase = PADDR(ctlr->rdr);
	p->tbase = PADDR(ctlr->tdr);

	cpmop(InitRxTx, ctlr->sccid, 0);

	p->c_pres = ~0;
	p->c_mask = 0xDEBB20E3;
	p->crcec = 0;
	p->alec = 0;
	p->disfc = 0;
	p->pads = 0x8888;
	p->ret_lim = 0xF;
	p->mflr = Rbsize;
	p->minflr = ETHERMINTU+4;
	p->maxd1 = Bufsize;
	p->maxd2 = Bufsize;
	p->p_per = 0;	/* only moderate aggression */

	for(i=0; i<Eaddrlen; i+=2)
		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */

	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
	scc->dsr = 0xd555;
	scc->gsmrh = 0;	/* normal operation */
	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
	eieio();
	scc->scce = ~0;	/* clear all events */
	eieio();
	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
	eieio();

	if(ctlr->sccid == SCC2ID){
		io->pbpar |= IBIT(18);	/* enable TENA pin (RTS2) */
		io->pbdir |= IBIT(18);
	}else{
		io->pbpar |= IBIT(19);	/* enable TENA pin (RTS1) */
		io->pbdir |= IBIT(19);
	}
	eieio();

	/* enable is deferred until attach */
}

static int
reset(Ether* ether)
{
	uchar ea[Eaddrlen];
	Ctlr *ctlr;
	SCC *scc;

	if(m->speed < 24){
		print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
		return -1;
	}

	if(!(ether->port >= 1 && ether->port <= 4)){
		print("%s ether: no SCC port %d\n", ether->type, ether->port);
		return -1;
	}

	ether->irq = VectorCPIC + sccirq[ether->port];
	scc = IOREGS(sccbase[ether->port], SCC);
	if(ether->port == 2)
		scc2claim(1, DisableEther, scc2stop, scc);

	ctlr = malloc(sizeof(*ctlr));
	ether->ctlr = ctlr;
	memset(ctlr, 0, sizeof(*ctlr));
	ctlr->scc = scc;
	ctlr->port = ether->port;
	ctlr->sccid = sccid[ether->port];

	if(ioringinit(ctlr, Nrdre, Ntdre, Bufsize) < 0)
		panic("etherscc init");

	sccsetup(ctlr, scc, ether->ea);

	ether->mbps = 10;	/* TO DO: could be 100mbps on 860T */
	ether->attach = attach;
	ether->closed = closed;
	ether->transmit = transmit;
	ether->interrupt = interrupt;
	ether->ifstat = ifstat;

	ether->arg = ether;
	ether->promiscuous = promiscuous;
	ether->multicast = multicast;

	/*
	 * Until we know where to find it, insist that the plan9.ini
	 * entry holds the Ethernet address.
	 */
	memset(ea, 0, Eaddrlen);
	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
		print("no ether address");
		return -1;
	}

	return 0;
}

void
etherscclink(void)
{
	addethercard("SCC", reset);
	addethercard("SCC2", reset);
}
.
## diffname mpc/etherscc.c 1999/0508
## diff -e /n/emeliedump/1999/0122/sys/src/brazil/mpc/etherscc.c /n/emeliedump/1999/0508/sys/src/brazil/mpc/etherscc.c
551c
//	addethercard("SCC2", reset);
.
502c
		print("%s ether: no SCC port %ld\n", ether->type, ether->port);
.
486c
	// step 30:
	scc->gsmrh = 0;	/* normal operation */

	// step 31:
	scc->gsmrl = 0x1088000c;

	// step 32:
	scc->dsr = 0xd555;

	// step 33:
	scc->psmr = 0x080A;	/* 32-bit CRC, non-promiscuous */

	// step 34
	io->pcpar |= SIBIT(15);	/* enable TENA pin (RTS2) */
	io->pcdir &= ~SIBIT(15);

	// step 35: done at attach time
.
477,484c
	// step 29:
	// set by setvec
.
475c
	p->p_per = 0;	/* only moderate aggression */
.
473c
	
	// step 28:
.
467,471c
	// step 22
	p->p_per = 0;	/* only moderate aggression */

	// step 23:
	memset(p->iaddr, 0, sizeof(p->iaddr));

	// step 24:
	memset(p->taddr, 0, sizeof(p->taddr));

	// step 25:

	// step 26:

	// step 27:
.
465c
		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];
.
463a
	// step 19:
	p->maxd1 = Bufsize;	/* was 0x5F0 */
	p->maxd2 = Bufsize;	/* was 0x5F0 */

	// step 20:
	memset(p->gaddr, 0, sizeof(p->gaddr));

	// step 21:
.
460,462d
458a

	// step 18:
.
457a

	// step 17:
.
456a
	
	// step 16:
.
455a

	// step 15:
.
452a

	// step 14:
.
451a

	// step 13:
.
450a
	// step 10
	p->rfcr = 0x18;   // manuals say 0x10
	p->tfcr = 0x18;

	// step 11
	p->mrblr = Bufsize;

	// step 12:
.
449c
	// step 9:
	cpmop(InitRxTx, SCC1ID, 0);
.
441,445c
	// step 8:
.
439c
//	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
.
434,436d
428,432c
	// step 7: set dma priority
	io->sdcr = 1;
.
424,426c
	// step 5/6: route clocks
	io->sicr = (7<<3) | (5);
	eieio();
.
419,422c
	// step 4: enable clocks
	io->papar |= SIBIT(6)|SIBIT(4);	/* enable CLK2 and CLK4 */
	io->padir &= ~(SIBIT(6)|SIBIT(4));
	eieio();
.
412,417c
	// setp 3
	io->pcpar &= ~SIBIT(15);		/* disble TENA pin */
.
408,410c
	// step 1: enable TXD RXD ports
	io->papar |= SIBIT(14)|SIBIT(15);
	io->padir &= ~(SIBIT(14)|SIBIT(15));
	io->paodr &= ~SIBIT(14);
		
	// step 2: enable CLSN and RENA ports
	io->pcpar &= ~(SIBIT(11)|SIBIT(10));
	io->pcdir &= ~(SIBIT(11)|SIBIT(10));
	io->pcso |= SIBIT(11)|SIBIT(10);
	eieio();
.
404,406c
	if(ctlr->port != 1)
		panic("only do SCC1 at the momment");
.
399,402c
	p = (Etherparam*)KADDR(SCC1P);
.
397a
print("sccsetup\n");

.
135d
## diffname mpc/etherscc.c 1999/0608
## diff -e /n/emeliedump/1999/0508/sys/src/brazil/mpc/etherscc.c /n/emeliedump/1999/0608/sys/src/brazil/mpc/etherscc.c
397,398d
## diffname mpc/etherscc.c 1999/0623
## diff -e /n/emeliedump/1999/0608/sys/src/brazil/mpc/etherscc.c /n/emeliedump/1999/0623/sys/src/brazil/mpc/etherscc.c
249a
	Ether *ether = arg;
.
244c
interrupt(Ureg*, void *arg)
.
## diffname mpc/etherscc.c 2000/0516
## diff -e /n/emeliedump/1999/0623/sys/src/brazil/mpc/etherscc.c /n/emeliedump/2000/0516/sys/src/9/mpc/etherscc.c
586c
//	addethercard("SCC3", reset);
.
530a
print("etherscc: reset\n");

.
517,519c
	// step 34: enable TENA 
	switch(ctlr->port) {
	case 2:
		io->pcpar |= SIBIT(14);
		io->pcdir &= ~SIBIT(14);
		break;
	case 3:
		io->pcpar |= SIBIT(13);
		io->pcdir &= ~SIBIT(13);
		break;
	}
.
439c
	cpmop(InitRxTx, sccid[ctlr->port], 0);
.
432,433d
429c
	
.
426a
	case 3:
		p = (Etherparam*)KADDR(SCC3P);

		// step 1: enable TXD RXD ports
		io->pbpar |= IBIT(24)|IBIT(25);
		io->pbdir |= IBIT(24)|IBIT(25);
		io->pbodr &= ~(IBIT(24)|IBIT(25));
			
		// step 2: enable CLSN and RENA ports
		io->pcpar &= ~(SIBIT(4)|SIBIT(5));
		io->pcdir &= ~(SIBIT(4)|SIBIT(5));
		io->pcso |= SIBIT(4)|SIBIT(5);
		eieio();
	
		// setp 3
		io->pcpar &= ~SIBIT(13);
		io->pcdir &= ~SIBIT(13);
	
		// step 4: enable clocks
		io->papar |= SIBIT(4)|SIBIT(5);
		io->padir &= ~(SIBIT(4)|SIBIT(5));
		eieio();
	
		// step 5/6: route clocks
		iopunlock();
		sccnmsi(3, CLK3, CLK4);
		io = ioplock();
		break;
	}

.
423,425c
		// step 5/6: route clocks
		iopunlock();
		sccnmsi(2, CLK1, CLK2);	/* connect the clocks */
		io = ioplock();
		break;
.
418,421c
		// setp 3: disble TENA pin */
		io->pcpar &= ~SIBIT(14);
		io->pcdir &= ~SIBIT(14);
	
		// step 4: enable clocks CLK3 and CLK4
		io->papar |= SIBIT(6)|SIBIT(7);
		io->padir &= ~(SIBIT(6)|SIBIT(7));
.
415,416c
		// step 2: enable CLSN and RENA ports
		io->pcpar &= ~(SIBIT(8)|SIBIT(9));
		io->pcdir &= ~(SIBIT(8)|SIBIT(9));
		io->pcso |= SIBIT(8)|SIBIT(9);
.
404,413c
		// step 1: enable TXD RXD ports
		io->papar |= SIBIT(12)|SIBIT(13);
		io->padir &= ~(SIBIT(12)|SIBIT(13));
		io->paodr &= ~(SIBIT(12)|SIBIT(13));
.
401,402c
	switch(ctlr->port) {
	default:
		iopunlock();
		return;
	case 2:
		p = (Etherparam*)(SCC2P);
.
399d
394c
	int i;
.
354,355d
350a

		if(events & TXE)
			cpmop(RestartTx, ctlr->sccid, 0);

.
323c
	if(events & (TXB|TXE)){
.
291c
				print("eth rx: %ux\n", status);
.
279c
	if(events & (RXF|RXB)){
.
273a

.
271,272d
143a
		Ctlr *ctlr;

		ctlr = ether->ctlr;
.
140,142d
## diffname mpc/etherscc.c 2001/0527 # deleted
## diff -e /n/emeliedump/2000/0516/sys/src/9/mpc/etherscc.c /n/emeliedump/2001/0527/sys/src/9/mpc/etherscc.c
1,630d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.