From 6071b841af879a6a0c2ae9ae73bfb22f954fa0e7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 26 Mar 2003 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2003-03-26 --- pc/devarch.c | 107 +++++++++++++++++++++++++++++++++++------------ pc/i8253.c | 29 ------------- pc/main.c | 5 ++- pc/mp.c | 7 +--- pc/pcmciamodem.c | 1 + pc/vgahiqvideo.c | 2 + pc/vganvidia.c | 53 ++++++----------------- pc/vgas3.c | 2 + port/devmouse.c | 2 + port/portdat.h | 1 + port/sysfile.c | 33 ++++++++++----- 11 files changed, 130 insertions(+), 112 deletions(-) diff --git a/pc/devarch.c b/pc/devarch.c index febf520e83e8608dfeef405b0255579b65bfb80e..f6cb972240fec65ac386ed56fabb808f937b9983 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -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); } /* diff --git a/pc/i8253.c b/pc/i8253.c index 766b7c1567a43dffcbd102f43800c63aac33f294..d1b1d81d362c7b721b839d4f697b401a294fee89 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -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); } /* diff --git a/pc/main.c b/pc/main.c index 5d3afa7653da84303ef39847322bac515192b686..d6dbf923581e79a290d9edf042693de3c9f40365 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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)); } diff --git a/pc/mp.c b/pc/mp.c index edf03c209d7c80e23d5fe4a3b4a7993208e57e31..654731691ba19f726bc32d7c32e51d939bdedcde 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -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; diff --git a/pc/pcmciamodem.c b/pc/pcmciamodem.c index ad88eece55223fd6c2c5f54865f83f95855bd2f7..30019f9179b6ef04fdfc461ce93a545e08661880 100644 --- a/pc/pcmciamodem.c +++ b/pc/pcmciamodem.c @@ -28,6 +28,7 @@ static char* modems[] = { "REM10", "GSM/GPRS", "AirCard 555", + "Gold Card Global", /* Psion V90 Gold card */ 0, }; diff --git a/pc/vgahiqvideo.c b/pc/vgahiqvideo.c index 5488989ae44df56f111a80b108ba5fe1a326b01d..6ae02b0492cc4d95ad7ba49bc1cfceb4d187dbf2 100644 --- a/pc/vgahiqvideo.c +++ b/pc/vgahiqvideo.c @@ -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: diff --git a/pc/vganvidia.c b/pc/vganvidia.c index 89e074715c8e50dacef70c512123c5f3c6c34638..a87aee6b001bfdd8cbae33d11ea002ae31b82093 100644 --- a/pc/vganvidia.c +++ b/pc/vganvidia.c @@ -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; diff --git a/pc/vgas3.c b/pc/vgas3.c index dc2d6b5d3521bad0535caa5b41a87abe1bc84433..9f77b0213f393d3a979c743785c147132f7cf1a7 100644 --- a/pc/vgas3.c +++ b/pc/vgas3.c @@ -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; diff --git a/port/devmouse.c b/port/devmouse.c index 31d8b7887267d830fa2cbd68467a406268c6c2ee..1adcdd1cbde787acdf0e765453e1bcdf4262d03c 100644 --- a/port/devmouse.c +++ b/port/devmouse.c @@ -107,6 +107,8 @@ mouseinit(void) if(!conf.monitor) return; + curs = arrow; + Cursortocursor(&arrow); cursoron(1); } diff --git a/port/portdat.h b/port/portdat.h index fa464013b2a83593e4a4bf0c3cb678352da5624f..cc340406a4443e6ca560a5e287de5b1795cc2350 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -463,6 +463,7 @@ struct Fgrp Chan **fd; int nfd; /* number allocated */ int maxfd; /* highest fd in use */ + int exceed; /* debugging */ }; enum diff --git a/port/sysfile.c b/port/sysfile.c index c9d053a2cada12a828b6d8b1df4e621aa95e496e..3393be56ae2424180c81f599af668befc34dfe2d 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -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{