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

📄 uartsaturn.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "msaturn.h"enum{	UartAoffs = Saturn + 0x0a00,	UartBoffs = Saturn + 0x0b00,	Nuart = 2,	Baudfreq = 14745600 / 16,	Lcr_div = RBIT(1, uchar),	Lcr_peven = RBIT(3, uchar),	Lcr_pen = RBIT(4, uchar),	Lcr_stop = RBIT(5, uchar),	Lcr_wrdlenmask = RBIT(6, uchar) | RBIT(7, uchar),	Lcr_wrdlenshift = 0,	Lsr_tbre = RBIT(2, uchar),		Fcr_txreset = RBIT(5, uchar),	Fcr_rxreset = RBIT(6, uchar),	Iir_txempty = RBIT(5, uchar),	Iir_rxfull = RBIT(6, uchar),	Iir_rxerr = RBIT(7, uchar),	Ier_rxerr = RBIT(5, uchar),	Ier_txempty = RBIT(6, uchar),	Ier_rxfull = RBIT(7, uchar),	Lsr_rxavail = RBIT(7, uchar),	Txsize = 16,	Rxsize = 16,};typedef struct Saturnuart Saturnuart;struct Saturnuart {	uchar	rxb;#define txb	rxb#define dll	rxb	uchar	ier;			// Interrupt enable, divisor latch#define dlm	ier	uchar	iir;			// Interrupt identification, fifo control#define fcr	iir		uchar	lcr;			// Line control register	uchar	f1;			uchar	lsr;			// Line status register	ushort	f2;};typedef struct UartData UartData;struct UartData {	int			suno;	/* saturn uart number: 0 or 1 */	Saturnuart	*su;	char			*rxbuf;	char			*txbuf;	int			initialized;	int			enabled;} uartdata[Nuart];extern PhysUart saturnphysuart;Uart suart[Nuart] = {	{		.name = "SaturnUart1",		.baud = 19200,		.bits = 8,		.stop = 1,		.parity = 'n',		.phys = &saturnphysuart,		.special = 0,	},	{		.name = "SaturnUart2",		.baud = 115200,		.bits = 8,		.stop = 1,		.parity = 'n',		.phys = &saturnphysuart,		.special = 0,	},};static void suinterrupt(Ureg*, void*);static Uart*supnp(void){	int i;	for (i = 0; i < nelem(suart)-1; i++)		suart[i].next = &suart[i + 1];	suart[nelem(suart)-1].next=nil;	return suart;}static voidsuinit(Uart*uart){	UartData *ud;	Saturnuart *su;	ud = uart->regs;	su = ud->su;	su->fcr=Fcr_txreset|Fcr_rxreset;	ud->initialized=1;}static voidsuenable(Uart*uart, int ie){	Saturnuart *su;	UartData *ud;	int nr;	nr = uart - suart;	if (nr < 0 || nr > Nuart)		panic("No uart %d", nr);	ud = uartdata + nr;	ud->suno = nr;	su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs);	uart->regs = ud;	if(ud->initialized==0)		suinit(uart);	if(!ud->enabled && ie){		intrenable(Vecuart0+nr , suinterrupt, uart, uart->name);		su->ier=Ier_txempty|Ier_rxfull;		ud->enabled=1;	}}static longsustatus(Uart* uart, void* buf, long n, long offset){	Saturnuart *su;	char p[128];	su = ((UartData*)uart->regs)->su;	snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"		"dev(%d) type(%d) framing(%d) overruns(%d)\n",		uart->baud,		uart->hup_dcd, 		uart->hup_dsr,		Txsize,		(su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n',		(su->lcr & Lcr_stop)? 2: 1,		uart->dev,		uart->type,		uart->ferr,		uart->oerr);	n = readstr(offset, buf, n, p);	free(p);	return n;}static voidsufifo(Uart*, int){}static voidsudtr(Uart*, int){}static voidsurts(Uart*, int){}static voidsumodemctl(Uart*, int){}static intsuparity(Uart*uart, int parity){	int lcr;	Saturnuart *su;	su = ((UartData*)uart->regs)->su;	lcr = su->lcr & ~(Lcr_pen|Lcr_peven);	switch(parity){	case 'e':		lcr |= (Lcr_pen|Lcr_peven);		break;	case 'o':		lcr |= Lcr_pen;		break;	case 'n':	default:		break;	}	su->lcr = lcr;	uart->parity = parity;	return 0;}static intsustop(Uart* uart, int stop){	int lcr;	Saturnuart *su;	su = ((UartData*)uart->regs)->su;	lcr = su->lcr & ~Lcr_stop;	switch(stop){	case 1:		break;	case 2:		lcr |= Lcr_stop;		break;	default:		return -1;	}	/* Set new value and reenable if device was previously enabled */	su->lcr = lcr;	uart->stop = stop;	return 0;}static intsubits(Uart*uart, int n){		Saturnuart *su;	uchar lcr;	su = ((UartData*)uart->regs)->su;	if(n<5||n>8)		return -1;	lcr = su->lcr & ~Lcr_wrdlenmask;	lcr |= (n-5) << Lcr_wrdlenshift;	su->lcr = lcr;	return 0;}static intsubaud(Uart* uart, int baud){	ushort v;	Saturnuart *su;	if (uart->enabled){		su = ((UartData*)uart->regs)->su;			if(baud <= 0)			return -1;		v = Baudfreq / baud;		su->lcr |= Lcr_div;		su->dll = v;		su->dlm = v >> 8;		su->lcr &= ~Lcr_div;	}	uart->baud = baud;	return 0;}static voidsubreak(Uart*, int){}static voidsukick(Uart *uart){	Saturnuart *su;	int i;	if(uart->blocked)		return;	su = ((UartData*)uart->regs)->su;	if((su->iir & Iir_txempty) == 0)		return;	for(i = 0; i < Txsize; i++){		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)			break;		su->txb = *(uart->op++);		su->ier |= Ier_txempty;		break;	}}static voidsuputc(Uart *uart, int c){	Saturnuart *su;	su = ((UartData*)uart->regs)->su;	while((su->lsr&Lsr_tbre) == 0)		;	su->txb=c;	while((su->lsr&Lsr_tbre) == 0)			;}static intgetchars(Uart *uart, uchar *cbuf){	int nc;	UartData *ud;	Saturnuart *su;	ud = uart->regs;	su = ud->su;	while((su->lsr&Lsr_rxavail) == 0)		;	*cbuf++ = su->rxb;	nc = 1;	while(su->lsr&Lsr_rxavail){		*cbuf++ = su->rxb;		nc++;	}	return nc;}static intsugetc(Uart *uart){	static uchar buf[128], *p;	static int cnt;	char	c;	if (cnt <= 0) {		cnt = getchars(uart, buf);		p = buf;	}	c = *p++;	cnt--;	return c;}static voidsuinterrupt(Ureg*, void*u){	Saturnuart *su;	Uart *uart;	uchar iir;	uart = u;	if (uart == nil)		panic("uart is nil");	su = ((UartData*)uart->regs)->su;	iir = su->iir;	if(iir&Iir_rxfull)		while(su->lsr&Lsr_rxavail)			uartrecv(uart, su->rxb);	if(iir & Iir_txempty){		su->ier&=~Ier_txempty;		uartkick(uart);	}	if (iir & Iir_rxerr)		uart->oerr++;	intack();}static voidsudisable(Uart* uart){	Saturnuart *su;	su = ((UartData*)uart->regs)->su;	su->ier&=~(Ier_txempty|Ier_rxfull);}PhysUart saturnphysuart = {	.name		= "su",	.pnp			= supnp,	.enable		= suenable,	.disable		= sudisable,	.kick			= sukick,	.dobreak		= subreak,	.baud		= subaud,	.bits			= subits,	.stop			= sustop,	.parity		= suparity,	.modemctl	= sumodemctl,	.rts			= surts,	.dtr			= sudtr,	.status		= sustatus,	.fifo			= sufifo,	.getc			= sugetc,	.putc			= suputc,};voidconsole(void){	Uart *uart;	int n;	char *cmd, *p;	if((p = getconf("console")) == nil)		return;	n = strtoul(p, &cmd, 0);	if(p == cmd)		return;	if(n < 0 || n >= nelem(suart))		return;	uart = suart + n;/*	uartctl(uart, "b115200 l8 pn s1"); */	if(*cmd != '\0')		uartctl(uart, cmd);	(*uart->phys->enable)(uart, 0);	consuart = uart;	uart->console = 1;} Saturnuart*uart = (Saturnuart*)UartAoffs;voiddbgputc(int c){	while((uart->lsr&Lsr_tbre) == 0)		;	uart->txb=c;	while((uart->lsr&Lsr_tbre) == 0)			;}voiddbgputs(char*s){	while(*s)		dbgputc(*s++);}voiddbgputx(ulong x){	int i;	char c;	for(i=0; i < sizeof(ulong) * 2; i++){		c = ((x >> (28 - i * 4))) & 0xf;		if(c >= 0 && c <= 9)			c += '0';		else			c += 'a' - 10;		while((uart->lsr&Lsr_tbre) == 0)			;		uart->txb=c;	}	while((uart->lsr&Lsr_tbre) == 0)			;	uart->txb='\n';	while((uart->lsr&Lsr_tbre) == 0)			;}

⌨️ 快捷键说明

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