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

📄 devlpt.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"/* Centronix parallel (printer) port *//* base addresses */static int lptbase[] = {	0x378,	/* lpt1 */	0x3bc,	/* lpt2 */	0x278	/* lpt3 (sic) */};#define NDEV	nelem(lptbase)static int lptallocd[NDEV];/* offsets, and bits in the registers */enum{	Qdir=		0x8000,	/* data latch register */	Qdlr=		0x0,	/* printer status register */	Qpsr=		0x1,	Fnotbusy=	0x80,	Fack=		0x40,	Fpe=		0x20,	Fselect=	0x10,	Fnoerror=	0x08,	/* printer control register */	Qpcr=		0x2,	Fie=		0x10,	Fselectin=	0x08,	Finitbar=	0x04,	Faf=		0x02,	Fstrobe=	0x01,	/* fake `data register' */	Qdata=		0x3,};static int	lptready(void*);static void	outch(int, int);static void	lptintr(Ureg*, void*);static Rendez	lptrendez;Dirtab lptdir[]={	".",	{Qdir, 0, QTDIR},	0,	DMDIR|0555,	"dlr",	{Qdlr},			1,	0666,	"psr",	{Qpsr},			5,	0444,	"pcr",	{Qpcr},			0,	0222,	"data",	{Qdata},		0,	0222,};static intlptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp){	Qid qid;	if(i == DEVDOTDOT){		mkqid(&qid, Qdir, 0, QTDIR);		devdir(c, qid, ".", 0, eve, 0555, dp);		return 1;	}	i++; /* skip first element for . itself */	if(tab==0 || i>=ntab)		return -1;	tab += i;	qid = tab->qid;	qid.path &= ~Qdir;	if(qid.path < Qdata)		qid.path += lptbase[c->dev];	qid.vers = c->dev;	sprint(up->genbuf, "lpt%lud%s", c->dev+1, tab->name);	devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp);	return 1;}static Chan*lptattach(char *spec){	Chan *c;	int i  = (spec && *spec) ? strtol(spec, 0, 0) : 1;	char name[5];	static int set;	if(!set){		outb(lptbase[i-1]+Qpcr, 0);	/* turn off interrupts */		set = 1;		intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt");	}	if(i < 1 || i > NDEV)		error(Ebadarg);	if(lptallocd[i-1] == 0){		int ecr;		sprint(name, "lpt%d", i-1);		if(ioalloc(lptbase[i-1], 3, 0, name) < 0)			error("lpt port space in use");		lptallocd[i-1] = 1;		// Detect ECP - if found, put into PS/2 mode to suit style of driver		ecr = lptbase[i-1] + 0x402;		if ((inb(ecr) & 3) == 1) {			outb(ecr, 0x34);			if (inb(ecr) == 0x35) {				outb(ecr, (inb(ecr) & 0x1f) | (1 << 5));				if(ioalloc(ecr, 1, 0, name) < 0)					error("lpt ecr port space in use");			}		}	}	c = devattach('L', spec);	c->qid.path = Qdir;	c->dev = i-1;	return c;}static Walkqid*lptwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen);}static intlptstat(Chan *c, uchar *dp, int n){	return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen);}static Chan*lptopen(Chan *c, int omode){	return devopen(c, omode, lptdir, nelem(lptdir), lptgen);}static voidlptclose(Chan *){}static longlptread(Chan *c, void *a, long n, vlong){	char str[16];	int size;	ulong o;	if(c->qid.path == Qdir)		return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen);	size = sprint(str, "0x%2.2ux\n", inb(c->qid.path));	o = c->offset;	if(o >= size)		return 0;	if(o+n > size)		n = size-c->offset;	memmove(a, str+o, n);	return n;}static longlptwrite(Chan *c, void *a, long n, vlong){	char str[16], *p;	long base, k;	if(n <= 0)		return 0;	if(c->qid.path != Qdata){		if(n > sizeof str-1)			n = sizeof str-1;		memmove(str, a, n);		str[n] = 0;		outb(c->qid.path, strtoul(str, 0, 0));		return n;	}	p = a;	k = n;	base = lptbase[c->dev];	if(waserror()){		outb(base+Qpcr, Finitbar);		nexterror();	}	while(--k >= 0)		outch(base, *p++);	poperror();	return n;}static voidoutch(int base, int c){	int status, tries;	for(tries=0;; tries++) {		status = inb(base+Qpsr);		if(status&Fnotbusy)			break;		if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror))			error(Eio);		if(tries < 10)			tsleep(&lptrendez, return0, nil, 1);		else {			outb(base+Qpcr, Finitbar|Fie);			tsleep(&lptrendez, lptready, (void *)base, 100);		}	}	outb(base+Qdlr, c);	outb(base+Qpcr, Finitbar|Fstrobe);	outb(base+Qpcr, Finitbar);}static intlptready(void *base){	return inb((int)base+Qpsr)&Fnotbusy;}static voidlptintr(Ureg *, void *){	wakeup(&lptrendez);}Dev lptdevtab = {	'L',	"lpt",	devreset,	devinit,	devshutdown,	lptattach,	lptwalk,	lptstat,	lptopen,	devcreate,	lptclose,	lptread,	devbread,	lptwrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

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