~kris/9p

9hist

6071b841af879a6a0c2ae9ae73bfb22f954fa0e7 — David du Colombier 23 years ago 511bd86
Plan 9 from Bell Labs 2003-03-26
M pc/devarch.c => pc/devarch.c +81 -26
@@ 55,6 55,7 @@ int narchdir = Qbase;
int (*_pcmspecial)(char*, ISAConf*);
void (*_pcmspecialclose)(int);

extern int i8253dotimerset;

/*
 * Add a file to the #P listing.  Once added, you can't delete it.


@@ 110,9 111,9 @@ ioinit(void)
	ioalloc(0x10000, 1, 0, "dummy");
	/*
	 * Someone needs to explain why this was here...
	 */
	ioalloc(0x0fff, 1, 0, "dummy");	// i82557 is at 0x1000, the dummy
					// entry is needed for swappable devs.
	 */

	if ((excluded = getconf("ioexclude")) != nil) {
		char *s;


@@ 498,7 499,15 @@ nop(void)
{
}

void (*coherence)(void) = nop;
/*
 * On a uniprocessor, you'd think that coherence could be nop,
 * but it can't.  We still need wbflush when using coherence() in
 * device drivers.
 *
 * On VMware, it's safe (and a huge win) to set this to nop.
 * Aux/vmware does this via the #P/archctl file.
 */
void (*coherence)(void) = wbflush;

PCArch* arch;
extern PCArch* knownarch[];


@@ 732,31 741,80 @@ cputyperead(Chan*, void *a, long n, vlong offset)
}

static long
pgewrite(Chan*, void *a, long n, vlong)
archctlread(Chan*, void *a, long nn, vlong offset)
{
	if(!m->havepge)
		error("processor does not support pge");

	if(n==3 && memcmp(a, "off", 3)==0){
		putcr4(getcr4() & ~0x80);
		return n;
	}
	if(n==2 && memcmp(a, "on", 2)==0){
		putcr4(getcr4() | 0x80);
		return n;
	}
	error("invalid control message");
	return -1;
	char buf[256];
	int n;
	
	n = snprint(buf, sizeof buf, "cpu %s %lud%s\n",
		cputype->name, (ulong)(m->cpuhz+999999)/1000000,
		m->havepge ? " pge" : "");
	n += snprint(buf+n, sizeof buf-n, "pge %s\n", getcr4()&0x80 ? "on" : "off");
	n += snprint(buf+n, sizeof buf-n, "coherence %s\n",
		coherence==wbflush ? "wbflush" : "nop");
	buf[n] = 0;
	return readstr(offset, a, nn, buf);
}

enum
{
	CMpge,
	CMcoherence,
	CMi8253set,
};

static Cmdtab archctlmsg[] =
{
	CMpge,		"pge",		2,
	CMcoherence,	"coherence",	2,
	CMi8253set,	"i8253set",	2,
};

static long
pgeread(Chan*, void *a, long n, vlong offset)
archctlwrite(Chan*, void *a, long n, vlong)
{
	if(n < 16)
		error("need more room");
	if(offset)
		return 0;
	n = snprint(a, n, "%s pge; %s", m->havepge ? "have" : "no", getcr4()&0x80 ? "on" : "off");
	Cmdbuf *cb;
	Cmdtab *ct;

	cb = parsecmd(a, n);
	if(waserror()){
		free(cb);
		nexterror();
	}
	ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg));
	switch(ct->index){
	case CMpge:
		if(!m->havepge)
			error("processor does not support pge");
		if(strcmp(cb->f[1], "on") == 0)
			putcr4(getcr4() | 0x80);
		else if(strcmp(cb->f[1], "off") == 0)
			putcr4(getcr4() & ~0x80);
		else
			cmderror(cb, "invalid pge ctl");
		break;
	case CMcoherence:
		if(strcmp(cb->f[1], "wbflush") == 0)
			coherence = wbflush;
		else if(strcmp(cb->f[1], "nop") == 0){
			/* only safe on vmware */
			if(conf.nmach > 1)
				error("cannot disable coherence on a multiprocessor");
			coherence = nop;
		}else
			cmderror(cb, "invalid coherence ctl");
		break;
	case CMi8253set:
		if(strcmp(cb->f[1], "on") == 0)
			i8253dotimerset = 1;
		else if(strcmp(cb->f[1], "off") == 0)
			i8253dotimerset = 0;
		else
			cmderror(cb, "invalid i2853set ctl");
		break;
	}
	free(cb);
	poperror();
	return n;
}



@@ 797,11 855,8 @@ archinit(void)
	if(X86FAMILY(m->cpuidax) == 3)
		conf.copymode = 1;

//	if(X86FAMILY(m->cpuidax) >= 5 && conf.nmach > 1)
		coherence = wbflush;

	addarchfile("cputype", 0444, cputyperead, nil);
	addarchfile("pge", 0664, pgeread, pgewrite);
	addarchfile("archctl", 0664, archctlread, archctlwrite);
}

/*

M pc/i8253.c => pc/i8253.c +0 -29
@@ 243,38 243,9 @@ i8253enable(void)
	intrenable(IrqCLOCK, i8253clock, 0, BUSUNKNOWN, "clock");
}

static long
i8253timerread(Chan*, void *a, long n, vlong offset)
{
	if(n < 16)
		error("need more room");
	if(offset)
		return 0;
	return snprint(a, n, "timerset %s", i8253dotimerset ? "on" : "off");
}

static long
i8253timerwrite(Chan*, void *a, long n, vlong)
{
	if(n==3 && memcmp(a, "off", 3) == 0){
		i8253dotimerset = 0;
		outb(Tmode, Load0|Square);
		outb(T0cntr, (Freq/HZ));
		outb(T0cntr, (Freq/HZ)>>8);
		return n;
	}
	if(n==2 && memcmp(a, "on", 2) == 0){
		i8253dotimerset = 1;
		return n;
	}
	error("invalid control message");
	return -1;
}

void
i8253link(void)
{
	addarchfile("i8253timerset", 0664, i8253timerread, i8253timerwrite);
}

/*

M pc/main.c => pc/main.c +4 -1
@@ 30,7 30,6 @@ char *confval[MAXCONF];
int nconf;
uchar *sp;	/* user stack of init proc */


static void
options(void)
{


@@ 584,6 583,10 @@ procsave(Proc *p)
	 * the free list where they could be reallocated and overwritten.
	 * When this processor eventually has to get an entry from the
	 * trashed page tables it will crash.
	 *
	 * If there's only one processor, this can't happen.
	 * You might think it would be a win not to do this in that case,
	 * especially on VMware, but it turns out not to matter.
	 */
	mmuflushtlb(PADDR(m->pdb));
}

M pc/mp.c => pc/mp.c +1 -6
@@ 581,14 581,9 @@ mpinit(void)
	 *
	 *  set conf.copymode here if nmach > 1.
	 *  Should look for an ExtINT line and enable it.
	 *
	 *  also need to flush write buffer to make things
	 *  visible to other processors.
	 */
	if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1)
		conf.copymode = 1;
	if(X86FAMILY(m->cpuidax) >= 5 && conf.nmach > 1)
		coherence = wbflush;
}

static int


@@ 631,7 626,7 @@ mpintrenablex(Vctl* v, int tbdf)
			irq = (dno<<2)|(n-1);
		else
			irq = -1;
		//print("pcidev %uX: irq %d v->irq %uX\n", tbdf, irq, v->irq);
		//print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq);
	}
	else
		irq = v->irq;

M pc/pcmciamodem.c => pc/pcmciamodem.c +1 -0
@@ 28,6 28,7 @@ static char* modems[] = {
	"REM10",
	"GSM/GPRS",
	"AirCard 555",
	"Gold Card Global",		/* Psion V90 Gold card */
	0,
};


M pc/vgahiqvideo.c => pc/vgahiqvideo.c +2 -0
@@ 51,6 51,7 @@ hiqvideolinear(VGAscr* scr, int* size, int* align)
		case 0x00C0:		/* 69000 HiQVideo */
		case 0x00E0:		/* 65550 HiQV32 */
		case 0x00E4:		/* 65554 HiQV32 */
		case 0x00E5:		/* 65555 HiQV32 */
			aperture = p->mem[0].bar & ~0x0F;
			*size = p->mem[0].size;
			break;


@@ 100,6 101,7 @@ hiqvideoenable(VGAscr* scr)
			break;
		case 0x00E0:		/* 65550 HiQV32 */
		case 0x00E4:		/* 65554 HiQV32 */
		case 0x00E5:		/* 65555 HiQV32 */
			switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
			default:
			case 0:

M pc/vganvidia.c => pc/vganvidia.c +13 -40
@@ 24,47 24,20 @@ enum {
	hwCurImage = Pramin + (0x00010000 - 0x0800),
};

static ushort nvidiadid[] = {
	0x0020,		/* Riva TNT */
	0x0028,		/* Riva TNT2 */
	0x0029,		/* Riva TNT2 (Ultra)*/
	0x002C,		/* Riva TNT2 (Vanta) */
	0x002D,		/* Riva TNT2 M64 */
	0x00A0,		/* Riva TNT2 (Integrated) */
	0x0100,		/* GeForce 256 */
	0x0101,		/* GeForce DDR */
	0x0103,		/* Quadro */
	0x0110,		/* GeForce2 MX */
	0x0111,		/* GeForce2 MX DDR */
	0x0112,		/* GeForce 2 Go */
	0x0113,		/* Quadro 2 MXR */
	0x0150,		/* GeForce2 GTS */
	0x0151,		/* GeForce2 GTS (rev 1) */
	0x0152,		/* GeForce2 Ultra */
	0x0153,		/* Quadro 2 Pro */
	0x0200,		/* GeForce3 */
	0x0201,
	0x0202,
	0,
};

/* Nvidia is good about backwards compatibility -- any did > 0x20 is fine */
static Pcidev*
nvidiapci(void)
{
	Pcidev *p;
	ushort *did;

	if((p = pcimatch(nil, 0x10DE, 0)) == nil)
		return nil;
	for(did = nvidiadid; *did; did++){
		if(*did == p->did)
	p = nil;
	while((p = pcimatch(p, 0x10DE, 0)) != nil)
		if(p->did > 0x20 && p->ccrp == 3)	/* video card */
			return p;
	}

	return nil;
}


static ulong
nvidialinear(VGAscr* scr, int* size, int* align)
{


@@ 82,7 55,7 @@ nvidialinear(VGAscr* scr, int* size, int* align)
		*size = p->mem[1].size;
	}

	if(wasupamem) {
	if(wasupamem){
		if(oaperture == aperture)
			return oaperture;
		upafree(oaperture, oapsize);


@@ 123,14 96,14 @@ nvidiaenable(VGAscr* scr)
		return;

	scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
	if (scr->io == 0)
	if(scr->io == 0)
		return;
	addvgaseg("nvidiammio", scr->io, p->mem[0].size);

	size = p->mem[1].size;
	align = 0;
	aperture = nvidialinear(scr, &size, &align);
	if(aperture) {
	if(aperture){
		scr->aperture = aperture;
		scr->apsize = size;
		addvgaseg("nvidiascreen", aperture, size);


@@ 161,16 134,16 @@ nvidiacurload(VGAscr* scr, Cursor* curs)

	p = KADDR(scr->io + hwCurImage);

	for (i=0; i<16; i++) {
	for(i=0; i<16; i++) {
		c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
		s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
		tmp = 0;
		for (j=0; j<16; j++) {
		for (j=0; j<16; j++){
			if(s&0x8000)
				tmp |= 0x80000000;
			else if(c&0x8000)
				tmp |= 0xFFFF0000;
			if (j&0x1) {
			if (j&0x1){
				*p++ = tmp;
				tmp = 0;
			} else {


@@ 258,7 231,7 @@ waitforidle(VGAscr *scr)
	pgraph = KADDR(scr->io + Pgraph);

	x = 0;
	while (pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
	while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
		;

	if(x >= 1000000)


@@ 274,7 247,7 @@ waitforfifo(VGAscr *scr, int fifo, int entries)
	x = 0;
	fifofree = KADDR(scr->io + Fifo + fifo + 0x10);

	while (((*fifofree >> 2) < entries) && x++ < 1000000)
	while(((*fifofree >> 2) < entries) && x++ < 1000000)
		;

	if(x >= 1000000)


@@ 328,7 301,7 @@ nvidiablank(VGAscr*, int blank)
	seq1 = vgaxi(Seqx, 1) & ~0x20;
	crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;

	if(blank) {
	if(blank){
		seq1 |= 0x20;
//		crtc1A |= 0xC0;
		crtc1A |= 0x80;

M pc/vgas3.c => pc/vgas3.c +2 -0
@@ 409,6 409,8 @@ waitforlinearfifo(VGAscr *scr)
	switch(scr->id){
	default:
		panic("unknown scr->id in s3 waitforlinearfifo");
	case 0x8A01:	/* ViRGE/[DG]X.  XFree86 says no waiting necessary */
		return;
	case 0x5631:	/* ViRGE */
	case 0x883D:	/* ViRGE/VX */
		mask = 0x0F<<6;

M port/devmouse.c => port/devmouse.c +2 -0
@@ 107,6 107,8 @@ mouseinit(void)
	if(!conf.monitor)
		return;

	curs = arrow;
	Cursortocursor(&arrow);
	cursoron(1);
}


M port/portdat.h => port/portdat.h +1 -0
@@ 463,6 463,7 @@ struct Fgrp
	Chan	**fd;
	int	nfd;			/* number allocated */
	int	maxfd;			/* highest fd in use */
	int	exceed;			/* debugging */
};

enum

M port/sysfile.c => port/sysfile.c +23 -10
@@ 9,6 9,18 @@
 * The sys*() routines needn't poperror() as they return directly to syscall().
 */

static void
unlockfgrp(Fgrp *f)
{
	int ex;

	ex = f->exceed;
	f->exceed = 0;
	unlock(f);
	if(ex)
		pprint("warning: process exceeds %d file descriptors\n", ex);
}

int
growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
{


@@ 18,8 30,6 @@ growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
		return 0;
	if(fd >= f->nfd+DELTAFD)
		return -1;	/* out of range */
	if(fd % 100 == 0)
		pprint("warning: process exceeds %d file descriptors\n", fd);
	/*
	 * Unbounded allocation is unwise; besides, there are only 16 bits
	 * of fid in 9P


@@ 37,8 47,11 @@ growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
	f->fd = newfd;
	free(oldfd);
	f->nfd += DELTAFD;
	if(fd > f->maxfd)
	if(fd > f->maxfd){
		if(fd/100 > f->maxfd/100)
			f->exceed = (fd/100)*100;
		f->maxfd = fd;
	}
	return 1;
}



@@ 68,13 81,13 @@ newfd(Chan *c)
	lock(f);
	fd = findfreefd(f, 0);
	if(fd < 0){
		unlock(f);
		unlockfgrp(f);
		return -1;
	}
	if(fd > f->maxfd)
		f->maxfd = fd;
	f->fd[fd] = c;
	unlock(f);
	unlockfgrp(f);
	return fd;
}



@@ 87,19 100,19 @@ newfd2(int fd[2], Chan *c[2])
	lock(f);
	fd[0] = findfreefd(f, 0);
	if(fd[0] < 0){
		unlock(f);
		unlockfgrp(f);
		return -1;
	}
	fd[1] = findfreefd(f, fd[0]+1);
	if(fd[1] < 0){
		unlock(f);
		unlockfgrp(f);
		return -1;
	}
	if(fd[1] > f->maxfd)
		f->maxfd = fd[1];
	f->fd[fd[0]] = c[0];
	f->fd[fd[1]] = c[1];
	unlock(f);
	unlockfgrp(f);

	return 0;
}


@@ 227,7 240,7 @@ sysdup(ulong *arg)
	if(fd != -1){
		lock(f);
		if(fd<0 || growfd(f, fd)<0) {
			unlock(f);
			unlockfgrp(f);
			cclose(c);
			error(Ebadfd);
		}


@@ 236,7 249,7 @@ sysdup(ulong *arg)

		oc = f->fd[fd];
		f->fd[fd] = c;
		unlock(f);
		unlockfgrp(f);
		if(oc)
			cclose(oc);
	}else{