⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uartaxp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Avanstar Xp pci uart driver */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "uartaxp.i"typedef struct Cc Cc;typedef struct Ccb Ccb;typedef struct Ctlr Ctlr;typedef struct Gcb Gcb;/* * Global Control Block. * Service Request fields must be accessed using XCHG. */struct Gcb {	u16int	gcw;				/* Global Command Word */	u16int	gsw;				/* Global Status Word */	u16int	gsr;				/* Global Service Request */	u16int	abs;				/* Available Buffer Space */	u16int	bt;				/* Board Type */	u16int	cpv;				/* Control Program Version */	u16int	ccbn;				/* Ccb count */	u16int	ccboff;				/* Ccb offset */	u16int	ccbsz;				/* Ccb size */	u16int	gcw2;				/* Global Command Word 2 */	u16int	gsw2;				/* Global Status Word 2 */	u16int	esr;				/* Error Service Request */	u16int	isr;				/* Input Service Request */	u16int	osr;				/* Output Service Request */	u16int	msr;				/* Modem Service Request */	u16int	csr;				/* Command Service Request */};/* * Channel Control Block. */struct Ccb {	u16int	br;				/* Baud Rate */	u16int	df;				/* Data Format */	u16int	lp;				/* Line Protocol */	u16int	ibs;				/* Input Buffer Size */	u16int	obs;				/* Output Buffer Size */	u16int 	ibtr;				/* Ib Trigger Rate */	u16int	oblw;				/* Ob Low Watermark */	u8int	ixon[2];			/* IXON characters */	u16int	ibhw;				/* Ib High Watermark */	u16int	iblw;				/* Ib Low Watermark */	u16int	cc;				/* Channel Command */	u16int	cs;				/* Channel Status */	u16int	ibsa;				/* Ib Start Addr */	u16int 	ibea;				/* Ib Ending Addr */	u16int	obsa;				/* Ob Start Addr */	u16int 	obea;				/* Ob Ending Addr */	u16int	ibwp;				/* Ib write pointer (RO) */	u16int	ibrp;				/* Ib read pointer (R/W) */	u16int	obwp;				/* Ob write pointer (R/W) */	u16int	obrp;				/* Ob read pointer (RO) */	u16int	ces;				/* Communication Error Status */	u16int	bcp;				/* Bad Character Pointer */	u16int	mc;				/* Modem Control */	u16int	ms;				/* Modem Status */	u16int	bs;				/* Blocking Status */	u16int	crf;				/* Character Received Flag */	u8int	ixoff[2];			/* IXOFF characters */	u16int	cs2;				/* Channel Status 2 */	u8int	sec[2];				/* Strip/Error Characters */};enum {						/* br */	Br76800		= 0xFF00,	Br115200	= 0xFF01,};enum {						/* df */	Db5		= 0x0000,		/* Data Bits - 5 bits/byte */	Db6		= 0x0001,		/*	6 bits/byte */	Db7		= 0x0002,		/*	7 bits/byte */	Db8		= 0x0003,		/*	8 bits/byte */	DbMASK		= 0x0003,	Sb1		= 0x0000,		/* 1 Stop Bit */	Sb2		= 0x0004,		/* 2 Stop Bit */	SbMASK		= 0x0004,	Np		= 0x0000,		/* No Parity */	Op		= 0x0008,		/* Odd Parity */	Ep		= 0x0010,		/* Even Parity */	Mp		= 0x0020,		/* Mark Parity */	Sp		= 0x0030,		/* Space Parity */	PMASK		= 0x0038,	Cmn		= 0x0000,		/* Channel Mode Normal */	Cme		= 0x0040,		/* CM Echo */	Cmll		= 0x0080,		/* CM Local Loopback */	Cmrl		= 0x00C0,		/* CM Remote Loopback */};enum {						/* lp */	Ixon		= 0x0001,		/* Obey IXON/IXOFF */	Ixany		= 0x0002,		/* Any character retarts Tx */	Ixgen		= 0x0004,		/* Generate IXON/IXOFF  */	Cts		= 0x0008,		/* CTS controls Tx */	Dtr		= 0x0010,		/* Rx controls DTR */	½d		= 0x0020,		/* RTS off during Tx */	Rts		= 0x0040,		/* generate RTS */	Emcs		= 0x0080,		/* Enable Modem Control */	Ecs		= 0x1000,		/* Enable Character Stripping */	Eia422		= 0x2000,		/* EIA422 */};enum {						/* cc */	Ccu		= 0x0001,		/* Configure Channel and UART */	Cco		= 0x0002,		/* Configure Channel Only */	Fib		= 0x0004,		/* Flush Input Buffer */	Fob		= 0x0008,		/* Flush Output Buffer */	Er		= 0x0010,		/* Enable Receiver */	Dr		= 0x0020,		/* Disable Receiver */	Et		= 0x0040,		/* Enable Transmitter */	Dt		= 0x0080,		/* Disable Transmitter */};enum {						/* ces */	Oe		= 0x0001,		/* Overrun Error */	Pe		= 0x0002,		/* Parity Error */	Fe		= 0x0004,		/* Framing Error */	Br		= 0x0008,		/* Break Received */};enum {						/* mc */	Adtr		= 0x0001,		/* Assert DTR */	Arts		= 0x0002,		/* Assert RTS */	Ab		= 0x0010,		/* Assert BREAK */};enum {						/* ms */	Scts		= 0x0001,		/* Status od CTS */	Sdsr		= 0x0002,		/* Status of DSR */	Sri		= 0x0004,		/* Status of RI */	Sdcd		= 0x0008,		/* Status of DCD */};enum {						/* bs */	Rd		= 0x0001,		/* Receiver Disabled */	Td		= 0x0002,		/* Transmitter Disabled */	Tbxoff		= 0x0004,		/* Tx Blocked by XOFF */	Tbcts		= 0x0008,		/* Tx Blocked by CTS */	Rbxoff		= 0x0010,		/* Rx Blocked by XOFF */	Rbrts		= 0x0020,		/* Rx Blocked by RTS */};enum {						/* Local Configuration */	Range		= 0x00,	Remap		= 0x04,	Region		= 0x18,	Mb0		= 0x40,			/* Mailbox 0 */	Ldb		= 0x60,			/* PCI to Local Doorbell */	Pdb		= 0x64,			/* Local to PCI Doorbell */	Ics		= 0x68,			/* Interrupt Control/Status */	Mcc		= 0x6C,			/* Misc. Command and Control */};enum {						/* Mb0 */	Edcc		= 1,			/* exec. downloaded code cmd */	Aic		= 0x10,			/* adapter init'zed correctly */	Cpr		= 1ul << 31,		/* control program ready */};enum {						/* Mcc */	Rcr		= 1ul << 29,		/* reload config. reg.s */	Asr		= 1ul << 30,		/* pci adapter sw reset */	Lis		= 1ul << 31,		/* local init status */};typedef struct Cc Cc;typedef struct Ccb Ccb;typedef struct Ctlr Ctlr;/* * Channel Control, one per uart. * Devuart communicates via the PhysUart functions with * a Uart* argument. Uart.regs is filled in by this driver * to point to a Cc, and Cc.ctlr points to the Axp board * controller. */struct Cc {	int	uartno;	Ccb*	ccb;	Ctlr*	ctlr;	Rendez;	Uart;};typedef struct Ctlr {	char*	name;	Pcidev*	pcidev;	int	ctlrno;	Ctlr*	next;	u32int*	reg;	uchar*	mem;	Gcb*	gcb;	int	im;		/* interrupt mask */	Cc	cc[16];} Ctlr;#define csr32r(c, r)	(*((c)->reg+((r)/4)))#define csr32w(c, r, v)	(*((c)->reg+((r)/4)) = (v))static Ctlr* axpctlrhead;static Ctlr* axpctlrtail;extern PhysUart axpphysuart;static intaxpccdone(void* ccb){	return !((Ccb*)ccb)->cc;	/* hw sets ccb->cc to zero */}static voidaxpcc(Cc* cc, int cmd){	Ccb *ccb;	int timeo;	u16int cs;	ccb = cc->ccb;	ccb->cc = cmd;	if(!cc->ctlr->im)		for(timeo = 0; timeo < 1000000; timeo++){			if(!ccb->cc)				break;			microdelay(1);		}	else		tsleep(cc, axpccdone, ccb, 1000);	cs = ccb->cs;	if(ccb->cc || cs){		print("%s: cmd %#ux didn't terminate: %#ux %#ux\n",			cc->name, cmd, ccb->cc, cs);		if(cc->ctlr->im)			error(Eio);	}}static longaxpstatus(Uart* uart, void* buf, long n, long offset){	char *p;	Ccb *ccb;	u16int bs, fstat, ms;	ccb = ((Cc*)(uart->regs))->ccb;	p = malloc(READSTR);	bs = ccb->bs;	fstat = ccb->df;	ms = ccb->ms;	snprint(p, READSTR,		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"		"dev(%d) type(%d) framing(%d) overruns(%d) "		"berr(%d) serr(%d)%s%s%s%s\n",		uart->baud,		uart->hup_dcd,		ms & Sdsr,		uart->hup_dsr,		(fstat & DbMASK) + 5,		0,		(fstat & PMASK) ? ((fstat & Ep) == Ep? 'e': 'o'): 'n',		(bs & Rbrts) ? 1 : 0,		(fstat & Sb2) ? 2 : 1,		0,		uart->dev,		uart->type,		uart->ferr,		uart->oerr,		uart->berr,		uart->serr,		(ms & Scts) ? " cts"  : "",		(ms & Sdsr) ? " dsr"  : "",		(ms & Sdcd) ? " dcd"  : "",		(ms & Sri) ? " ring" : ""	);	n = readstr(offset, buf, n, p);	free(p);	return n;}static voidaxpfifo(Uart*, int){}static voidaxpdtr(Uart* uart, int on){	Ccb *ccb;	u16int mc;	ccb = ((Cc*)(uart->regs))->ccb;	mc = ccb->mc;	if(on)		mc |= Adtr;	else		mc &= ~Adtr;	ccb->mc = mc;}/* * can be called from uartstageinput() during an input interrupt, * with uart->rlock ilocked or the uart qlocked, sometimes both. */static voidaxprts(Uart* uart, int on){	Ccb *ccb;	u16int mc;	ccb = ((Cc*)(uart->regs))->ccb;	mc = ccb->mc;	if(on)		mc |= Arts;	else		mc &= ~Arts;	ccb->mc = mc;}static voidaxpmodemctl(Uart* uart, int on){	Ccb *ccb;	u16int lp;	ccb = ((Cc*)(uart->regs))->ccb;	ilock(&uart->tlock);	lp = ccb->lp;	if(on){		lp |= Cts|Rts;		lp &= ~Emcs;		uart->cts = ccb->ms & Scts;	}	else{		lp &= ~(Cts|Rts);		lp |= Emcs;		uart->cts = 1;	}	uart->modem = on;	iunlock(&uart->tlock);	ccb->lp = lp;	axpcc(uart->regs, Ccu);}static intaxpparity(Uart* uart, int parity){	Ccb *ccb;	u16int df;	switch(parity){	default:		return -1;	case 'e':		parity = Ep;		break;	case 'o':		parity = Op;		break;	case 'n':		parity = Np;		break;	}	ccb = ((Cc*)(uart->regs))->ccb;	df = ccb->df & ~PMASK;	ccb->df = df|parity;	axpcc(uart->regs, Ccu);	return 0;}static intaxpstop(Uart* uart, int stop){	Ccb *ccb;	u16int df;	switch(stop){	default:		return -1;	case 1:		stop = Sb1;		break;	case 2:		stop = Sb2;		break;	}	ccb = ((Cc*)(uart->regs))->ccb;	df = ccb->df & ~SbMASK;	ccb->df = df|stop;	axpcc(uart->regs, Ccu);	return 0;}static intaxpbits(Uart* uart, int bits){	Ccb *ccb;	u16int df;	bits -= 5;	if(bits < 0 || bits > 3)		return -1;	ccb = ((Cc*)(uart->regs))->ccb;	df = ccb->df & ~DbMASK;	ccb->df = df|bits;	axpcc(uart->regs, Ccu);	return 0;}static intaxpbaud(Uart* uart, int baud){	Ccb *ccb;	int i, ibtr;	/*	 * Set baud rate (high rates are special - only 16 bits).	 */	if(baud <= 0)		return -1;	uart->baud = baud;	ccb = ((Cc*)(uart->regs))->ccb;	switch(baud){	default:		ccb->br = baud;		break;	case 76800:		ccb->br = Br76800;		break;	case 115200:		ccb->br = Br115200;		break;	}	/*	 * Set trigger level to about 50 per second.	 */	ibtr = baud/500;	i = (ccb->ibea - ccb->ibsa)/2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -