henesyinit from p9f0ed2a895 years agoHistory
1463 lines · 25.8 KB · C
RawDownload
#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" enum {	FADS823 = 1, 	Rbufsize=	32,	// read buffer size	Nuart=	3,	/* max per machine (SMC1, SMC2, SCC2) */	CTLS=	's'&037,	CTLQ=	'q'&037,}; enum {	/* status bits in SCC receive buffer descriptors */	RxBRK=	1<<7,	/* break ended frame (async hdlc) */	RxDE=	1<<7,	/* DPLL error (hdlc) */	RxBOF=	1<<6,	/* BOF ended frame (async hdlc) */	RxLG=	1<<5,	/* frame too large (hdlc) */	RxNO=	1<<4,	/* bad bit alignment (hdlc) */	RxBR=	1<<5,	/* break received during frame (uart) */	RxFR=	1<<4,	/* framing error (uart) */	RxPR=	1<<3,	/* parity error (uart) */	RxAB=	1<<3,	/* frame aborted (hdlc, async hdlc) */	RxCR=	1<<2,	/* bad CRC (hdlc, async hdlc) */	RxOV=	1<<1,	/* receiver overrun (all) */	RxCD=	1<<0,	/* CD lost (all) */ 	/* hdlc-specific Rx/Tx BDs */	TxTC=	1<<10,}; /* *  SMC in UART mode */enum {	USESMC2 = 0}; typedef struct Uartsmc Uartsmc;struct Uartsmc {	IOCparam;	ushort	maxidl;	ushort	idlc;	ushort	brkln;	ushort	brkec;	ushort	brkcr;	ushort	rmask;}; /* * SCC2 UART parameters */enum {	USESCC2 = 0, 	/* special mode bits */	SccAHDLC = 1<<0,	SccHDLC = 1<<1,	SccIR = 1<<2,	SccPPP = 1<<3,}; typedef struct Uartscc Uartscc;struct Uartscc {	SCCparam;	uchar	rsvd[8];	ushort	max_idl;	ushort	idlc;	ushort	brkcr;	ushort	parec;	ushort	frmec;	ushort	nosec;	ushort	brkec;	ushort	brkln;	ushort	uaddr1;	ushort	uaddr2;	ushort	rtemp;	ushort	toseq;	ushort	character[8];	ushort	rccm;	ushort	rccrp;	ushort	rlbc;}; typedef struct UartAHDLC UartAHDLC;struct UartAHDLC {	SCCparam;	ulong	rsvd1;	ulong	c_mask;	ulong	c_pres;	ushort	bof;	ushort	eof;	ushort	esc;	ushort	rsvd2[2];	ushort	zero;	ushort	rsvd3;	ushort	rfthr;	ushort	resvd4[2];	ulong	txctl_tbl;	ulong	rxctl_tbl;	ushort	nof;	ushort	rsvd5;}; typedef struct UartHDLC UartHDLC;struct UartHDLC {	SCCparam;	ulong	rsvd1;	ulong	c_mask;	ulong	c_pres;	ushort	disfc;	ushort	crcec;	ushort	abtsc;	ushort	nmarc;	ushort	retrc;	ushort	mflr;	ushort	max_cnt;	ushort	rfthr;	ushort	rfcnt;	ushort	hmask;	ushort	haddr[4];	ushort	tmp;	ushort	tmp_mb;}; enum {	/* SCC events of possible interest here eventually */	AB=	1<<9,	/* autobaud detected */	GRA= 1<<7,	/* graceful stop completed */	CCR= 1<<3,	/* control character detected */ 	/* SCC, SMC common interrupt events */	BSY=	1<<2,	/* receive buffer was busy (overrun) */	TXB= 1<<1,	/* block sent */	RXB= 1<<0,	/* block received */ 	/* SCC events */	TXE = 1<<4,	/* transmission error */	RXF = 1<<3,	/* final block received */ 	/* gsmr_l */	ENR = 2<<4,	/* enable receiver */	ENT = 1<<4,	/* enable transmitter */}; typedef struct Uart Uart;struct Uart{	QLock; 	Uart	*elist;		/* next enabled interface */	char	name[NAMELEN]; 	int	x;		/* index: x in SMCx or SCCx */	int	cpmid;		/* eg, SCC1ID, SMC1ID */	int	opens;	uchar	bpc;	/* bits/char */	uchar	parity;	uchar	stopb;	uchar	setup;	uchar	enabled;	int	dev; 	ulong	frame;		/* framing errors */	ulong	perror;	ulong	overrun;	/* rcvr overruns */	ulong	crcerr;	ulong	interrupts;	int	baud;		/* baud rate */ 	/* flow control */	int	xonoff;		/* software flow control on */	int	blocked;	int	modem;		/* hardware flow control on */	int	cts;		/* ... cts state */	int	rts;		/* ... rts state */	Rendez	r; 	/* buffers */	int	(*putc)(Queue*, int);	Queue	*iq;	Queue	*oq; 	int	rdrx;	/* last buffer read */ 	Lock	plock;		/* for output variables */	Block*	outb;	/* currently transmitting Block */ 	BD*	rxb;	BD*	txb; 	SMC*	smc;	SCC*	scc;	IOCparam*	param;	ushort*	brkcr;	/* brkcr location in appropriate block */	int	brgc;	int	mode;	Block*	partial;	int	loopback;}; static Uart *uart[Nuart];static int nuart; struct Uartalloc {	Lock;	Uart *elist;	/* list of enabled interfaces */} uartalloc; static void uartintr(Uart*, int);static void smcuintr(Ureg*, void*);static void sccuintr(Ureg*, void*); 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 voiduartsetbuf(Uart *up){	IOCparam *p;	BD *bd;	int n;	uchar *buf; 	p = up->param;	p->rfcr = 0x18;	p->tfcr = 0x18;	p->mrblr = Rbufsize; 	// allocate buffer for receive	// the buffers need to be CACHELINESZ aligned and	// a multiple of CACHELINESZ long in order for	// the manul cache coherence to work	n = 2*ROUND(Rbufsize, CACHELINESZ)+CACHELINESZ-1;	buf = malloc(n);	buf = (uchar*)ROUND((long)buf, CACHELINESZ);		if((bd = up->rxb) == nil){		bd = bdalloc(2);		up->rxb = bd;	}	p->rbase = (ushort)bd;	bd->status = BDEmpty|BDInt;	bd->length = 0;	bd->addr = PADDR(buf);	bd++;	bd->status = BDEmpty|BDInt|BDWrap;	bd->length = 0;	bd->addr = PADDR(buf + ROUND(Rbufsize, CACHELINESZ));	dcflush(buf, 2*ROUND(Rbufsize, CACHELINESZ));	up->rdrx = 0; 	if((bd = up->txb) == nil){		bd = bdalloc(1);		up->txb = bd;	}	p->tbase = (ushort)bd;	bd->status = BDWrap|BDInt;	bd->length = 0;	bd->addr = 0;} static voidsmcsetup(Uart *up){	IMM *io;	Uartsmc *p;	SMC *smc; 	up->brgc = brgalloc();	if(up->brgc < 0)		error(Eio); 	io = ioplock();	/* step 1 */	io->papar |= SIBIT(8)|SIBIT(9);	io->padir &= ~(SIBIT(8)|SIBIT(9));	io->paodr &= ~(SIBIT(8)|SIBIT(9)); 	io->brgc[up->brgc] = baudgen(up->baud, 16) | BaudEnable; 	/* step 3: route clock to SMC2 */	io->simode = (io->simode & ~0xF0000000) | (up->brgc<<28); 	iopunlock(); 	up->param = KADDR(SMC2P);	uartsetbuf(up); 	cpmop(InitRxTx, SMC2ID, 0); 	/* SMC protocol parameters */	p = (Uartsmc*)up->param;	up->brkcr = &p->brkcr;	p->maxidl = 10;	p->brkln = 0;	p->brkec = 0;	p->brkcr = 1;	smc = IOREGS(0xA90, SMC);	smc->smce = 0xff;	/* clear events */	smc->smcm = BSY|RXB|TXB;	/* enable all possible interrupts */	up->smc = smc;	smc->smcmr = ((1+8+1-1)<<11)|(2<<4);	/* 8-bit, 1 stop, no parity; UART mode */	intrenable(VectorCPIC+3, smcuintr, up, BUSUNKNOWN);	smc->smcmr |= 3;	/* enable rx/tx */} static voidsmcuintr(Ureg*, void *a){	Uart *up;	int events; 	up = a;	events = up->smc->smce;	eieio();	up->smc->smce = events;	uartintr(up, events&(BSY|RXB|TXB));} static voidsccustop(void *a){	Uart *up; 	up = a;	if(up->setup){		scc2stop(up->scc);		brgfree(up->brgc);		up->brgc = -1;		up->setup = 0;	}}		static voidsccsetup(Uart *up){	IMM *io;	SCC *scc;	ulong bg;	int i; 	scc = IOREGS(sccbase[up->x], SCC);	if(up->x == 2){	/* BUG: 823FADS-specific */		if(scc->gsmrl & (ENT|ENR))			scc2stop(scc);		scc->gsmrl &= ~(ENT|ENR);		scc2claim(1, up->mode&SccIR? DisableIR: DisableRS232b, sccustop, scc);	}	up->scc = scc;	if(up->brgc < 0){		up->brgc = brgalloc();		if(up->brgc < 0)			error(Eio);	}	bg = baudgen(up->baud, 16) | BaudEnable; 	io = ioplock();	io->papar |= SIBIT(12)|SIBIT(13);	/* enable TXD2 and RXD2 pins */	io->padir &= ~(SIBIT(12)|SIBIT(13));	if((up->mode & SccIR) == 0)		io->paodr |= SIBIT(12);	/* TO DO: is this right? */	else		io->paodr &= ~(SIBIT(12)|SIBIT(13));	/* TO DO: is this right? */ 	io->pbpar &= ~IBIT(18);	/* disable RTS2 */	io->pbdir &= ~IBIT(18);	if((up->mode&SccIR) == 0)		io->pcpar |= SIBIT(14);	/* RTS2~ */	else		io->pcpar &= ~SIBIT(14);	io->pcpar &= ~(SIBIT(9)|SIBIT(8));	/* CTS2~ and CD2~ */	io->pcdir &= ~(SIBIT(14)|SIBIT(9)|SIBIT(8));	if(FADS823 || up->mode)		io->pcso &= ~(SIBIT(9)|SIBIT(8));	/* 82xFADS: force CTS and CD on */	else		io->pcso |= SIBIT(9)|SIBIT(8);	eieio(); 	io->brgc[up->brgc] = bg;	iopunlock(); 	sccnmsi(2, up->brgc, up->brgc); 	up->param = KADDR(sccparam[up->x]);	uartsetbuf(up); 	cpmop(InitRxTx, up->cpmid, 0); 	/* SCC protocol parameters */	if((up->mode & (SccAHDLC|SccHDLC)) == 0){		Uartscc *sp;		sp = (Uartscc*)up->param;		sp->max_idl = 1;		sp->brkcr = 1;		sp->parec = 0;		sp->frmec = 0;		sp->nosec = 0;		sp->brkec = 0;		sp->brkln = 0;		sp->brkec = 0;		sp->uaddr1 = 0;		sp->uaddr2 = 0;		sp->toseq = 0;		for(i=0; i<8; i++)			sp->character[i] = 0x8000;		sp->rccm = 0xC0FF;		up->brkcr = &sp->brkcr;		scc->irmode = 0;		scc->dsr = ~0;		scc->gsmrh = 1<<5;	/* 8-bit oriented receive fifo */		scc->gsmrl = 0x28004;	/* UART mode */	}else{		UartAHDLC *hp;		hp = (UartAHDLC*)up->param;		hp->c_mask = 0x0000F0B8;		hp->c_pres = 0x0000FFFF;		if(up->mode & SccIR){			hp->bof = 0xC0;			hp->eof = 0xC1;			//scc->dsr = 0xC0C0;			scc->dsr = 0x7E7E;		}else{			hp->bof = 0x7E;			hp->eof = 0x7E;			scc->dsr = 0x7E7E;		}		hp->esc = 0x7D;		hp->zero = 0;		if(up->mode & SccHDLC)			hp->rfthr = 1;		else			hp->rfthr = 0;	/* receive threshold of 1 doesn't work properly for Async HDLC */		hp->txctl_tbl = 0;		hp->rxctl_tbl = 0;		if(up->mode & SccIR){			/* low-speed infrared */			hp->nof = 12-1;	/* 12 flags */			scc->irsip = 0;			scc->irmode = (2<<8) | 1;//			m->bcsr[1] |= DisableIR;//			microdelay(2);//			m->bcsr[1] &= ~DisableIR;	/* put TFDS6000 xcvr in low-speed mode (see 4.9.2.1 in FADS manual) */			if(up->loopback)				scc->irmode = (3<<4)|1;	/* loopback */		}else{			scc->irmode = 0;			hp->txctl_tbl = ~0;			hp->rxctl_tbl = ~0;			hp->nof = 1-1;	/* one opening flag */		}		up->brkcr = nil;		scc->gsmrh = 1<<5;	/* 8-bit oriented receive fifo */		if(up->mode & SccHDLC)			scc->gsmrl = 0x28000;	/* HDLC */		else			scc->gsmrl = 0x28006;	/* async HDLC/IrDA */	}	scc->scce = ~0;	/* clear events */	scc->sccm = TXE|BSY|RXF|TXB|RXB;	/* enable all interesting interrupts */	intrenable(VectorCPIC+sccirq[up->x], sccuintr, up, BUSUNKNOWN);	scc->psmr = 3<<12;	/* 8-bit, 1 stop, no parity; UART mode */	if(up->loopback && (up->mode & SccIR) == 0)		scc->gsmrl |= 1<<6;	/* internal loop back */	scc->gsmrl |= ENT|ENR;	/* enable rx/tx */	if(0){		print("gsmrl=%8.8lux gsmrh=%8.8lux dsr=%4.4ux irmode=%4.4ux\n", scc->gsmrl, scc->gsmrh, scc->dsr, scc->irmode);		for(i=0; i<sizeof(Uartscc); i+=4)			print("%2.2ux %8.8lux\n", i, *(ulong*)((uchar*)up->param+i));	}} static voidsccuintr(Ureg*, void *a){	Uart *up;	int events; 	up = a;	if(/*(m->bcsr[1] & (DisableRS232b|DisableIR)) == (DisableRS232b|DisableIR) ||*/ up->scc == nil)		return;	events = up->scc->scce;	eieio();	up->scc->scce = events;	if(up->enabled){		if(0)			print("#%ux|", events);		uartintr(up, events);	}} 

Lines 1–500 of 1463.