plan 9 kernel history: overview | file list | diff list

1997/0327/pc/devlpt.c (diff list | history)

pc/devlpt.c on 1991/1204
1991/1204    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/1204    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1991/1204    
 
/* Centronix parallel (printer) port */ 
 
/* base addresses */ 
1992/0205    
static int lptbase[] = { 
1994/0324    
	0x378,	/* lpt1 */ 
	0x3bc,	/* lpt2 */ 
1991/1204    
	0x278	/* lpt3 (sic) */ 
}; 
#define NDEV	(sizeof lptbase/sizeof lptbase[0]) 
 
/* offsets, and bits in the registers */ 
enum 
{ 
	/* 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); 
1994/0324    
static void	lptintr(Ureg*, void*); 
1991/1204    
 
static Rendez	lptrendez; 
 
Dirtab lptdir[]={ 
	"dlr",		{Qdlr},		1,		0666, 
	"psr",		{Qpsr},		5,		0444, 
	"pcr",		{Qpcr},		0,		0222, 
	"data",		{Qdata},	0,		0222, 
}; 
 
static int 
lptgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) 
{ 
	Qid qid; 
	char name[NAMELEN]; 
 
	if(tab==0 || i>=ntab) 
		return -1; 
	tab += i; 
	qid = tab->qid; 
	if(qid.path < Qdata) 
		qid.path += lptbase[c->dev]; 
	qid.vers = c->dev; 
	sprint(name, "lpt%d%s", c->dev+1, tab->name); 
	devdir(c, qid, name, tab->length, eve, tab->perm, dp); 
	return 1; 
} 
 
1997/0327    
static Chan* 
1991/1204    
lptattach(char *spec) 
{ 
	Chan *c; 
	int i  = (spec && *spec) ? strtol(spec, 0, 0) : 1; 
1993/0224    
	static int set; 
1991/1204    
 
1993/0224    
	if(!set){ 
1994/0513    
		outb(lptbase[i-1]+Qpcr, 0);	/* turn off interrupts */ 
1993/0224    
		set = 1; 
1997/0327    
		intrenable(VectorLPT, lptintr, 0, BUSUNKNOWN); 
1993/0224    
	} 
1991/1204    
	if(i < 1 || i > NDEV) 
1992/0114    
		error(Ebadarg); 
1991/1204    
	c = devattach('L', spec); 
	c->dev = i-1; 
	return c; 
} 
 
1997/0327    
static int 
1991/1204    
lptwalk(Chan *c, char *name) 
{ 
1997/0327    
	return devwalk(c, name, lptdir, nelem(lptdir), lptgen); 
1991/1204    
} 
 
1997/0327    
static void 
1991/1204    
lptstat(Chan *c, char *dp) 
{ 
1997/0327    
	devstat(c, dp, lptdir, nelem(lptdir), lptgen); 
1991/1204    
} 
 
1997/0327    
static Chan* 
1991/1204    
lptopen(Chan *c, int omode) 
{ 
1997/0327    
	return devopen(c, omode, lptdir, nelem(lptdir), lptgen); 
1991/1204    
} 
 
1997/0327    
static void 
1991/1204    
lptclose(Chan *c) 
1992/0711    
{ 
	USED(c); 
} 
1991/1204    
 
1997/0327    
static long 
lptread(Chan *c, void *a, long n, ulong) 
1991/1204    
{ 
	char str[16]; int size; 
 
	if(c->qid.path == CHDIR) 
1997/0327    
		return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen); 
1991/1204    
	size = sprint(str, "0x%2.2ux\n", inb(c->qid.path)); 
	if(c->offset >= size) 
		return 0; 
	if(c->offset+n > size) 
		n = size-c->offset; 
	memmove(a, str+c->offset, n); 
	return n; 
} 
 
1997/0327    
static long 
lptwrite(Chan *c, void *a, long n, ulong) 
1995/0108    
{ 
1991/1204    
	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; 
1995/0108    
} 
 
1991/1204    
static void 
outch(int base, int c) 
{ 
1994/0331    
	int status, tries; 
1991/1204    
 
1994/0331    
	for(tries = 0;; tries++){ 
		status = inb(base+Qpsr); 
		if(!(status & Fselect) || !(status & Fnoerror)) 
			error(Eio); 
		if(status & Fnotbusy) 
			break; 
		if(tries > 1000){ 
			outb(base+Qpcr, Finitbar|Fie); 
			tsleep(&lptrendez, lptready, (void *)base, MS2HZ); 
		} 
1991/1204    
	} 
	outb(base+Qdlr, c); 
	outb(base+Qpcr, Finitbar|Fstrobe); 
	outb(base+Qpcr, Finitbar); 
} 
 
static int 
lptready(void *base) 
{ 
	return inb((int)base+Qpsr)&Fnotbusy; 
} 
 
static void 
1994/0324    
lptintr(Ureg *ur, void *arg) 
1991/1204    
{ 
1994/0324    
	USED(ur, arg); 
1991/1204    
	wakeup(&lptrendez); 
} 
1997/0327    
 
Dev lptdevtab = { 
	devreset, 
	devinit, 
	lptattach, 
	devclone, 
	lptwalk, 
	lptstat, 
	lptopen, 
	devcreate, 
	lptclose, 
	lptread, 
	devbread, 
	lptwrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)