256 lines · 4.3 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" enum {	Qdir = 0,	Qiob,	Qiow,	Qiol,	Qbase, 	Qmax = 16,}; typedef long Rdwrfn(Chan*, void*, long, vlong); static Rdwrfn *readfn[Qmax];static Rdwrfn *writefn[Qmax]; static Dirtab archdir[] = {	".",	{ Qdir, 0, QTDIR },	0,	0555,	"iob",		{ Qiob, 0 },		0,	0660,	"iow",		{ Qiow, 0 },		0,	0660,	"iol",		{ Qiol, 0 },		0,	0660,};Lock archwlock;	/* the lock is only for changing archdir */int narchdir = Qbase;int (*_pcmspecial)(char *, ISAConf *);void (*_pcmspecialclose)(int); /* * Add a file to the #P listing.  Once added, you can't delete it. * You can't add a file with the same name as one already there, * and you get a pointer to the Dirtab entry so you can do things * like change the Qid version.  Changing the Qid path is disallowed. */Dirtab*addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn){	int i;	Dirtab d;	Dirtab *dp; 	memset(&d, 0, sizeof d);	strcpy(d.name, name);	d.perm = perm; 	lock(&archwlock);	if(narchdir >= Qmax){		unlock(&archwlock);		return nil;	} 	for(i=0; i<narchdir; i++)		if(strcmp(archdir[i].name, name) == 0){			unlock(&archwlock);			return nil;		} 	d.qid.path = narchdir;	archdir[narchdir] = d;	readfn[narchdir] = rdfn;	writefn[narchdir] = wrfn;	dp = &archdir[narchdir++];	unlock(&archwlock); 	return dp;} voidioinit(void){	iomapinit(IOSIZE-1); 	// a dummy entry at 2^17	ioalloc(0x20000, 1, 0, "dummy");} static voidcheckport(int start, int end){	/* standard vga regs are OK */	if(start >= 0x2b0 && end <= 0x2df+1)		return;	if(start >= 0x3c0 && end <= 0x3da+1)		return; 	if(iounused(start, end))		return;	error(Eperm);} static Chan*archattach(char* spec){	return devattach('P', spec);} Walkqid*archwalk(Chan* c, Chan *nc, char** name, int nname){	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);} static intarchstat(Chan* c, uchar* dp, int n){	return devstat(c, dp, n, archdir, narchdir, devgen);} static Chan*archopen(Chan* c, int omode){	return devopen(c, omode, archdir, nelem(archdir), devgen);} static voidarchclose(Chan*){} static longarchread(Chan *c, void *a, long n, vlong offset){	int port;	uchar *cp;	ushort *sp;	ulong *lp;	IOMap *m;	Rdwrfn *fn; 	switch((ulong)c->qid.path){ 	case Qdir:		return devdirread(c, a, n, archdir, nelem(archdir), devgen); 	case Qiob:		port = offset;		checkport(offset, offset+n);		for(cp = a; port < offset+n; port++)			*cp++ = inb(port);		return n; 	case Qiow:		if((n & 0x01) || (offset & 0x01))			error(Ebadarg);		checkport(offset, offset+n+1);		n /= 2;		sp = a;		for(port = offset; port < offset+n; port += 2)			*sp++ = ins(port);		return n*2; 	case Qiol:		if((n & 0x03) || (offset & 0x03))			error(Ebadarg);		checkport(offset, offset+n+3);		n /= 4;		lp = a;		for(port = offset; port < offset+n; port += 4)			*lp++ = inl(port);		return n*4; 	default:		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))			return fn(c, a, n, offset);		error(Eperm);		break;	}	return 0;} static longarchwrite(Chan *c, void *a, long n, vlong offset){	int port;	uchar *cp;	ushort *sp;	ulong *lp;	Rdwrfn *fn; 	switch((ulong)c->qid.path){ 	case Qiob:		cp = a;		checkport(offset, offset+n);		for(port = offset; port < offset+n; port++)			outb(port, *cp++);		return n; 	case Qiow:		if((n & 01) || (offset & 01))			error(Ebadarg);		checkport(offset, offset+n+1);		n /= 2;		sp = a;		for(port = offset; port < offset+n; port += 2)			outs(port, *sp++);		return n*2; 	case Qiol:		if((n & 0x03) || (offset & 0x03))			error(Ebadarg);		checkport(offset, offset+n+3);		n /= 4;		lp = a;		for(port = offset; port < offset+n; port += 4)			outl(port, *lp++);		return n*4; 	default:		if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))			return fn(c, a, n, offset);		error(Eperm);		break;	}	return 0;} Dev archdevtab = {	'P',	"arch", 	devreset,	devinit,	devshutdown,	archattach,	archwalk,	archstat,	archopen,	devcreate,	archclose,	archread,	devbread,	archwrite,	devbwrite,	devremove,	devwstat,}; intpcmspecial(char *idstr, ISAConf *isa){	return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;} voidpcmspecialclose(int a){	if (_pcmspecialclose != nil)		_pcmspecialclose(a);}