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{