From 8eb8147866d18bcb14155aab3b7eeb61f99747e7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 22 Aug 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-08-22 --- alphapc/trap.c | 2 + bitsy/devpenmouse.c | 5 +- bitsy/l.s | 3 +- bitsy/power.c | 2 - bitsy/trap.c | 3 + mtx/trap.c | 3 + pc/devvga.c | 1 + pc/ether79c970.c | 175 +++++++++++++++++++++++++-------------- pc/screen.c | 3 - pc/sdata.c | 5 -- pc/trap.c | 3 + pc/uarti8250.c | 4 +- pc/vga.c | 1 + pc/vgavmware.c | 194 ++++++++++++++++++++++++++++++++++++++++++++ port/allocb.c | 9 +- port/chan.c | 44 ++++++---- port/dev.c | 8 +- port/devdup.c | 2 +- port/devmnt.c | 1 - port/portdat.h | 4 +- port/proc.c | 3 +- port/sysfile.c | 3 +- port/sysproc.c | 41 ++++------ 23 files changed, 388 insertions(+), 131 deletions(-) create mode 100644 pc/vgavmware.c diff --git a/alphapc/trap.c b/alphapc/trap.c index 83dc0a604dc54bd4ce795caa0f709c01996160c6..9e051edb8d156a52b9360b169ca7ce7dd08fb65a 100644 --- a/alphapc/trap.c +++ b/alphapc/trap.c @@ -703,6 +703,8 @@ print("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); poperror(); error: + /* failure: save the error buffer for errstr */ + kstrcpy(up->syserror, up->error, sizeof up->syserror); up->nerrlab = 0; up->psstate = 0; up->insyscall = 0; diff --git a/bitsy/devpenmouse.c b/bitsy/devpenmouse.c index 13f5c4cade662373c1d0afedb63ae67787e60712..143cd14b69becc0993c699bec54c23afcd5cafef 100644 --- a/bitsy/devpenmouse.c +++ b/bitsy/devpenmouse.c @@ -92,7 +92,10 @@ extern Memimage* gscreen; void penbutton(int up, int b) { - if (b & 0x20) { + // button 5 (side button) immediately causes an event + // when the pen is down (button 1), other buttons also + // cause events, allowing chording with button 1 + if ((b & 0x20) || (mouse.buttons & 0x1)) { if (up) mouse.buttons &= ~b; else diff --git a/bitsy/l.s b/bitsy/l.s index 6adc62422c16c75f12149d285430079eaee613af..d2e279a3c0a9b5550d0ec35d2caf8327facf355e 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -688,7 +688,8 @@ TEXT power_down(SB), $-4 MOVW R2,0x10(R3) MOVW $0,R2 MOVW R2,0x18(R3) - MOVW $power_resume+0(SB),R2 +/* MOVW $power_resume+0(SB),R2 */ + MOVW $0,R2 MOVW R2,0x8(R3) MOVW $0,R2 MOVW R2,0x4(R6) diff --git a/bitsy/power.c b/bitsy/power.c index 0f4e907a22a1ade10c87a52d13a1082a19f6566f..981fba6231fa33a444331eb09131082effb4d3b9 100644 --- a/bitsy/power.c +++ b/bitsy/power.c @@ -275,7 +275,6 @@ powerinit(void) void idlehands(void) { -#ifdef notdef char *msgb = "idlehands called with splhi\n"; char *msga = "doze returns with splhi\n"; @@ -288,6 +287,5 @@ idlehands(void) serialputs(msgb, strlen(msgb)); spllo(); } -#endif } diff --git a/bitsy/trap.c b/bitsy/trap.c index 273c884571124d7f60873efee937da2512c63d47..0b3d22309d25075c7d9fb91409c14a339b530d21 100644 --- a/bitsy/trap.c +++ b/bitsy/trap.c @@ -462,6 +462,9 @@ syscall(Ureg* ureg) ret = systab[scallnr](up->s.args); poperror(); + }else{ + /* failure: save the error buffer for errstr */ + kstrcpy(up->syserror, up->error, sizeof up->syserror); } if(up->nerrlab){ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); diff --git a/mtx/trap.c b/mtx/trap.c index abc14d0e92d85aae8cd307c2d27bad05d10f2267..6cd588ff90d332129a4023d95e99425ba011a9d4 100644 --- a/mtx/trap.c +++ b/mtx/trap.c @@ -653,6 +653,9 @@ syscall(Ureg* ureg) ret = systab[scallnr](up->s.args); poperror(); + }else{ + /* failure: save the error buffer for errstr */ + kstrcpy(up->syserror, up->error, sizeof up->syserror); } if(up->nerrlab){ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); diff --git a/pc/devvga.c b/pc/devvga.c index 1d2a760b7b852151be96c29fcd6d4857ca76f499..2fcfe8e195caad5997baa2b43225ae9fcbaf45b4 100644 --- a/pc/devvga.c +++ b/pc/devvga.c @@ -276,6 +276,7 @@ vgactl(char* a) return; } else if(strcmp(field[0], "drawinit") == 0){ + memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP); if(scr && scr->dev && scr->dev->drawinit) scr->dev->drawinit(scr); return; diff --git a/pc/ether79c970.c b/pc/ether79c970.c index 9d08a9fbf06d37213acbaedc1748d6328ce8146c..a6724c3aced241480b6a2bf56a795220e9dad0bf 100644 --- a/pc/ether79c970.c +++ b/pc/ether79c970.c @@ -1,5 +1,5 @@ /* - * AM79C970 + * AMD79C970 * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus * To do: * finish this rewrite @@ -108,7 +108,7 @@ enum { /* md2 */ }; typedef struct Ctlr Ctlr; -typedef struct Ctlr { +struct Ctlr { Lock; int port; Pcidev* pcidev; @@ -140,28 +140,49 @@ typedef struct Ctlr { ulong merr; /* bobf is such a whiner */ ulong miss; ulong babl; -} Ctlr; + + int (*ior)(Ctlr*, int); + void (*iow)(Ctlr*, int, int); +}; static Ctlr* ctlrhead; static Ctlr* ctlrtail; -#define csr32r(c, r) (inl((c)->port+(r))) -#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l))) +/* + * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above. + * To get to 16-bit offsets, scale down with 0x10 staying the same. + */ +static int +io16r(Ctlr *c, int r) +{ + if(r >= Rdp) + r = (r-Rdp)/2+Rdp; + return ins(c->port+r); +} static void -attach(Ether* ether) +io16w(Ctlr *c, int r, int v) { - Ctlr *ctlr; + if(r >= Rdp) + r = (r-Rdp)/2+Rdp; + outs(c->port+r, v); +} - ctlr = ether->ctlr; +static int +io32r(Ctlr *c, int r) +{ + return inl(c->port+r); +} - ilock(ctlr); - if(ctlr->init){ - iunlock(ctlr); - return; - } - csr32w(ctlr, Rdp, Iena|Strt); - iunlock(ctlr); +static void +io32w(Ctlr *c, int r, int v) +{ + outl(c->port+r, v); +} + +static void +attach(Ether*) +{ } static long @@ -260,20 +281,20 @@ promiscuous(void* arg, int on) while(ctlr->ntq) ; - csr32w(ctlr, Rdp, Stop); + ctlr->iow(ctlr, Rdp, Stop); - csr32w(ctlr, Rap, 15); - x = csr32r(ctlr, Rdp) & ~Prom; + ctlr->iow(ctlr, Rap, 15); + x = ctlr->ior(ctlr, Rdp) & ~Prom; if(on) x |= Prom; - csr32w(ctlr, Rdp, x); - csr32w(ctlr, Rap, 0); + ctlr->iow(ctlr, Rdp, x); + ctlr->iow(ctlr, Rap, 0); ringinit(ctlr); ilock(ctlr); ctlr->init = 0; - csr32w(ctlr, Rdp, Iena|Strt); + ctlr->iow(ctlr, Rdp, Iena|Strt); iunlock(ctlr); } @@ -299,7 +320,7 @@ txstart(Ether* ether) * increment the software ring descriptor pointer * and tell the chip to poll. * There's no need to pad to ETHERMINTU - * here as ApadXmit is set in CSR4. + * here as ApadXmt is set in CSR4. */ dre = &ctlr->tdr[ctlr->tdrh]; dre->bp = bp; @@ -307,7 +328,7 @@ txstart(Ether* ether) dre->md2 = 0; dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF); ctlr->ntq++; - csr32w(ctlr, Rdp, Iena|Tdmd); + ctlr->iow(ctlr, Rdp, Iena|Tdmd); ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); } } @@ -340,8 +361,8 @@ interrupt(Ureg*, void* arg) * happen. */ intrloop: - csr0 = csr32r(ctlr, Rdp) & 0xFFFF; - csr32w(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); + csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF; + ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); if(csr0 & Merr) ctlr->merr++; if(csr0 & Miss) @@ -488,46 +509,67 @@ reset(Ether* ether) ilock(ctlr); ctlr->init = 1; + io32r(ctlr, Sreset); + io16r(ctlr, Sreset); + + if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){ + ctlr->ior = io16r; + ctlr->iow = io16w; + }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){ + ctlr->ior = io32r; + ctlr->iow = io32w; + }else{ + print("#l%d: card doesn't talk right\n", ether->ctlrno); + iunlock(ctlr); + return -1; + } + + ctlr->iow(ctlr, Rap, 88); + x = ctlr->ior(ctlr, Rdp); + ctlr->iow(ctlr, Rap, 89); + x |= ctlr->ior(ctlr, Rdp)<<16; + + switch(x&0xFFFFFFF){ + case 0x2420003: /* PCnet/PCI 79C970 */ + case 0x2621003: /* PCnet/PCI II 79C970A */ + break; + default: + print("#l%d: unknown PCnet card version %.7ux\n", + ether->ctlrno, x&0xFFFFFFF); + iunlock(ctlr); + return -1; + } + /* - * How to tell what mode the chip is in at this point - if it's in WORD - * mode then the only 32-bit access allowed is a write to the RDP, which - * forces the chip to DWORD mode; if it's in DWORD mode then only DWORD - * accesses are allowed? - * Assuming a DWORD write is done to the RDP, what will be overwritten as - * the RAP can't reliably be accessed? - * - * Force DWORD mode by writing to RDP, doing a reset then writing to RDP - * again. The value of RAP after a reset is 0, so the second DWORD write - * will be to CSR0. * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access. * Set the auto pad transmit in CSR4. */ - csr32w(ctlr, Rdp, 0x00); - csr32r(ctlr, Sreset); - csr32w(ctlr, Rdp, Stop); - - csr32w(ctlr, Rap, 20); - csr32w(ctlr, Bdp, 0x0002); + ctlr->iow(ctlr, Rap, 20); + ctlr->iow(ctlr, Bdp, 0x0002); - csr32w(ctlr, Rap, 4); - x = csr32r(ctlr, Rdp) & 0xFFFF; - csr32w(ctlr, Rdp, ApadXmt|x); + ctlr->iow(ctlr, Rap, 4); + x = ctlr->ior(ctlr, Rdp) & 0xFFFF; + ctlr->iow(ctlr, Rdp, ApadXmt|x); - csr32w(ctlr, Rap, 0); + ctlr->iow(ctlr, Rap, 0); /* - * Check if the adapter's station address is to be over-ridden. - * If not, read it from the I/O-space and set in ether->ea prior to loading the - * station address in the initialisation block. + * Check if the adapter's station address is to be overridden. + * If not, read it from the I/O-space and set in ether->ea prior to + * loading the station address in the initialisation block. */ memset(ea, 0, Eaddrlen); if(!memcmp(ea, ether->ea, Eaddrlen)){ - x = csr32r(ctlr, Aprom); + x = ctlr->ior(ctlr, Aprom); ether->ea[0] = x; ether->ea[1] = x>>8; - ether->ea[2] = x>>16; - ether->ea[3] = x>>24; - x = csr32r(ctlr, Aprom+4); + if(ctlr->ior == io16r) + x = ctlr->ior(ctlr, Aprom+2); + else + x >>= 16; + ether->ea[2] = x; + ether->ea[3] = x>>8; + x = ctlr->ior(ctlr, Aprom+4); ether->ea[4] = x; ether->ea[5] = x>>8; } @@ -550,18 +592,25 @@ reset(Ether* ether) * enables will be set later when attaching to the network. */ x = PADDR(&ctlr->iblock); - csr32w(ctlr, Rap, 1); - csr32w(ctlr, Rdp, x & 0xFFFF); - csr32w(ctlr, Rap, 2); - csr32w(ctlr, Rdp, (x>>16) & 0xFFFF); - csr32w(ctlr, Rap, 3); - csr32w(ctlr, Rdp, Idon); - csr32w(ctlr, Rap, 0); - csr32w(ctlr, Rdp, Init); - - while(!(csr32r(ctlr, Rdp) & Idon)) + ctlr->iow(ctlr, Rap, 1); + ctlr->iow(ctlr, Rdp, x & 0xFFFF); + ctlr->iow(ctlr, Rap, 2); + ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF); + ctlr->iow(ctlr, Rap, 3); + ctlr->iow(ctlr, Rdp, Idon); + ctlr->iow(ctlr, Rap, 0); + ctlr->iow(ctlr, Rdp, Init); + + while(!(ctlr->ior(ctlr, Rdp) & Idon)) ; - csr32w(ctlr, Rdp, Idon|Stop); + + /* + * We used to set CSR0 to Idon|Stop here, and then + * in attach change it to Iena|Strt. Apparently the simulated + * 79C970 in VMware never enables after a write of Idon|Stop, + * so we enable the device here now. + */ + ctlr->iow(ctlr, Rdp, Iena|Strt); ctlr->init = 0; iunlock(ctlr); diff --git a/pc/screen.c b/pc/screen.c index f428c85945c4492c08e3f43d2b58fe42be395e9c..023be595b29f3939cf76e0ada8e457712d848747 100644 --- a/pc/screen.c +++ b/pc/screen.c @@ -72,9 +72,6 @@ screensize(int x, int y, int z, ulong chan) if(gscreen == nil) return -1; -/* memset(gscreen->data->bdata, 0x15, (x*y*z+7)/8); /* RSC BUG */ - memfillcolor(gscreen, DRed); - scr->palettedepth = 6; /* default */ scr->gscreendata = &gscreendata; scr->memdefont = getmemdefont(); diff --git a/pc/sdata.c b/pc/sdata.c index 604b36c6684af060d0345194a286e933baa571e8..8b69db0b4f906cec038ec0bb44224f2fe1b8e6e3 100644 --- a/pc/sdata.c +++ b/pc/sdata.c @@ -1590,14 +1590,12 @@ atapnp(void) Pcidev *p; int channel, ispc87415, pi, r; SDev *legacy[2], *sdev, *head, *tail; -//int i; legacy[0] = legacy[1] = head = tail = nil; if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){ head = tail = sdev; legacy[0] = sdev; } -//print("probe 1, sdev %p\n", sdev); if(sdev = ataprobe(0x170, 0x374, IrqATA1)){ if(head != nil) tail->next = sdev; @@ -1606,7 +1604,6 @@ atapnp(void) tail = sdev; legacy[1] = sdev; } -//print("probe 2, sdev %p\n", sdev); p = nil; while(p = pcimatch(p, 0, 0)){ @@ -1662,8 +1659,6 @@ atapnp(void) */ break; case (0x0646<<16)|0x1095: /* CMD 646 */ -//for(i = 0; i <= 4; i++) print("bar%d: addr %lux size %d\n", i, p->mem[i].bar, p->mem[i].size); - break; case (0x0571<<16)|0x1106: /* VIA 82C686 */ case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */ case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */ diff --git a/pc/trap.c b/pc/trap.c index 793375de51be856fb141f1c571738c187f4111f3..a2fc341959a0a9dd9043a93bcab530c3517c59ab 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -502,6 +502,9 @@ syscall(Ureg* ureg) ret = systab[scallnr](up->s.args); poperror(); + }else{ + /* failure: save the error buffer for errstr */ + kstrcpy(up->syserror, up->error, sizeof up->syserror); } if(up->nerrlab){ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); diff --git a/pc/uarti8250.c b/pc/uarti8250.c index b2ca39d58a0a3a1f00f37dde8c9d5863308c41a3..301f51d5861b973592abf1b5de4989891b1934bd 100644 --- a/pc/uarti8250.c +++ b/pc/uarti8250.c @@ -135,14 +135,14 @@ static Uart i8250uart[2] = { .name = "COM1", .freq = UartFREQ, .phys = &i8250physuart, - .special=0, + .special= 0, .next = &i8250uart[1], }, { .regs = &i8250ctlr[1], .name = "COM2", .freq = UartFREQ, .phys = &i8250physuart, - .special=0, + .special= 0, .next = nil, }, }; diff --git a/pc/vga.c b/pc/vga.c index daf77be4b082a82cc6593ac1a74055d3b32ac54c..e740c139461a822565276d22fa009a7f6244e9d9 100644 --- a/pc/vga.c +++ b/pc/vga.c @@ -189,6 +189,7 @@ vgascreenwin(VGAscr* scr) curpos = window.min; screenputs = vgascreenputs; + } /* diff --git a/pc/vgavmware.c b/pc/vgavmware.c new file mode 100644 index 0000000000000000000000000000000000000000..323f9e209f4519593b91d8f2d5dfd9cd6bca12ad --- /dev/null +++ b/pc/vgavmware.c @@ -0,0 +1,194 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +enum { + PCIVMWARE = 0x15AD, /* PCI VID */ + + VMWARE1 = 0x0710, /* PCI DID */ + VMWARE2 = 0x0405, +}; + +enum { + Rid = 0, + Renable, + Rwidth, + Rheight, + Rmaxwidth, + Rmaxheight, + Rdepth, + Rbpp, + Rpseudocolor, + Rrmask, + Rgmask, + Rbmask, + Rbpl, + Rfbstart, + Rfboffset, + Rfbmaxsize, + Rfbsize, + Rcap, + Rmemstart, + Rmemsize, + Rconfigdone, + Rsync, + Rbusy, + Rguestid, + Rcursorid, + Rcursorx, + Rcursory, + Rcursoron, + Nreg, + + Rpalette = 1024, +}; + +typedef struct Vmware Vmware; +struct Vmware { + ulong mmio; + ulong fb; + + ulong ra; + ulong rd; + + ulong r[Nreg]; + + char chan[32]; + int depth; +}; + +Vmware xvm; +Vmware *vm=&xvm; + +static ulong +vmrd(Vmware *vm, int i) +{ + outl(vm->ra, i); + return inl(vm->rd); +} + +static void +vmwr(Vmware *vm, int i, ulong v) +{ + outl(vm->ra, i); + outl(vm->rd, v); +} + +static ulong +vmwarelinear(VGAscr* scr, int* size, int* align) +{ + char err[64]; + ulong aperture, oaperture; + int osize, oapsize, wasupamem; + Pcidev *p; + Physseg seg; + + osize = *size; + oaperture = scr->aperture; + oapsize = scr->apsize; + wasupamem = scr->isupamem; + + p = pcimatch(nil, PCIVMWARE, 0); + if(p == nil) + error("no vmware card found"); + + switch(p->did){ + default: + snprint(err, sizeof err, "unknown vmware id %.4ux", p->did); + error(err); + + case VMWARE1: + vm->ra = 0x4560; + vm->rd = 0x4560+4; + break; + + case VMWARE2: + vm->ra = p->mem[0].bar&~3; + vm->rd = vm->ra + 1; + } + + aperture = (ulong)(vmrd(vm, Rfbstart)); + *size = vmrd(vm, Rfbsize); + + if(wasupamem) + upafree(oaperture, oapsize); + scr->isupamem = 0; + + aperture = upamalloc(aperture, *size, *align); + if(aperture == 0){ + if(wasupamem && upamalloc(oaperture, oapsize, 0)) + scr->isupamem = 1; + }else + scr->isupamem = 1; + + if(oaperture) + print("warning (BUG): redefinition of aperture does not change vmwarescreen segment\n"); + memset(&seg, 0, sizeof(seg)); + seg.attr = SG_PHYSICAL; + seg.name = smalloc(32); + snprint(seg.name, 32, "vmwarescreen"); + seg.pa = aperture; + seg.size = osize; + addphysseg(&seg); + return aperture; +} + +static void +vmwaredisable(VGAscr*) +{ +} + +static void +vmwareload(VGAscr*, Cursor*) +{ +} + +static int +vmwaremove(VGAscr*, Point) +{ + return 0; +} + +static void +vmwareenable(VGAscr*) +{ +} + +static void +vmwareblank(int) +{ +} + +static void +vmwaredrawinit(VGAscr*) +{ +} + +VGAdev vgavmwaredev = { + "vmware", + + 0, + 0, + 0, + vmwarelinear, + vmwaredrawinit, +}; + +VGAcur vgavmwarecur = { + "vmwarehwgc", + + vmwareenable, + vmwaredisable, + vmwareload, + vmwaremove, +}; diff --git a/port/allocb.c b/port/allocb.c index 5e7275bc4f2356255bc72dd942bd124dd0dacbb2..9cfb79f79e3c823c40a95217fe79d0c763bf91c4 100644 --- a/port/allocb.c +++ b/port/allocb.c @@ -62,12 +62,11 @@ allocb(int size) */ if(up == nil) panic("allocb without up: %uX\n", getcallerpc(&size)); - if((b = _allocb(size)) == nil) -{ -xsummary(); -mallocsummary(); + if((b = _allocb(size)) == nil){ + xsummary(); + mallocsummary(); panic("allocb: no memory for %d bytes\n", size); -} + } setmalloctag(b, getcallerpc(&size)); return b; diff --git a/port/chan.c b/port/chan.c index ffcd93e7dac7611c5d18ec857cf8821beaca7272..4e975a3b61a5d869051373d934a881ad698a6799 100644 --- a/port/chan.c +++ b/port/chan.c @@ -237,6 +237,7 @@ newchan(void) c->iounit = 0; c->umh = 0; c->uri = 0; + c->dri = 0; c->aux = 0; c->mchan = 0; c->mcp = 0; @@ -546,9 +547,9 @@ cunmount(Chan *mnt, Chan *mounted) Mount *f, **p; if(mnt->umh) /* should not happen */ - print("cunmount newp extra umh\n"); + print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); if(mounted && mounted->umh) - print("cunmount old extra umh\n"); + print("cunmount old extra umh %p has %p\n", mounted, mounted->umh); pg = up->pgrp; wlock(&pg->ns); @@ -771,7 +772,7 @@ walk(Chan **cp, char **names, int nnames, int nomount) runlock(&mh->lock); nexterror(); } - for(f = mh->mount; f; f = f->next) + for(f = mh->mount->next; f; f = f->next) if((wq = devtab[f->to->type]->walk(f->to, nil, names, ntry)) != nil) break; poperror(); @@ -969,6 +970,7 @@ namec(char *aname, int amode, int omode, ulong perm) Elemlist e; Rune r; Mhead *m; + char createerr[ERRMAX]; char *name; name = aname; @@ -1086,29 +1088,36 @@ namec(char *aname, int amode, int omode, ulong perm) cnameclose(c->name); c->name = cname; - if(amode == Aremove){ + switch(amode){ + case Aremove: putmhead(m); break; - } + case Aopen: + case Acreate: if(c->umh != nil){ print("cunique umh\n"); putmhead(c->umh); } - c->umh = m; + if(c->qid.type&QTDIR) + c->umh = m; + else + putmhead(m); - /* save registers else error() in open has wrong value of c saved */ - saveregisters(); + /* save registers else error() in open has wrong value of c saved */ + saveregisters(); - if(omode == OEXEC) - c->flag &= ~CCACHE; + if(omode == OEXEC) + c->flag &= ~CCACHE; - c = devtab[c->type]->open(c, omode&~OCEXEC); + c = devtab[c->type]->open(c, omode&~OCEXEC); - if(omode & OCEXEC) - c->flag |= CCEXEC; - if(omode & ORCLOSE) - c->flag |= CRCLOSE; + if(omode & OCEXEC) + c->flag |= CCEXEC; + if(omode & ORCLOSE) + c->flag |= CRCLOSE; + break; + } break; case Atodir: @@ -1222,8 +1231,10 @@ if(c->umh != nil){ putmhead(m); if(omode & OEXCL) nexterror(); + /* save error */ + kstrcpy(createerr, up->error, sizeof createerr); if(walk(&c, e.elems+e.nelems-1, 1, nomount) < 0) - nexterror(); + error(createerr); /* report true error */ omode |= OTRUNC; goto Open; } @@ -1242,6 +1253,7 @@ if(c->umh != nil){ kstrcpy(up->genbuf, ".", sizeof up->genbuf); free(e.name); free(e.elems); + return c; } diff --git a/port/dev.c b/port/dev.c index 730df47827778caa0b699f428dafce48fee43fc1..ada172e9ab5603b36585d7f2b5a68870f7e1abdc 100644 --- a/port/dev.c +++ b/port/dev.c @@ -254,20 +254,18 @@ devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen) long devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) { - long k, m, dsz; + long m, dsz; struct{ Dir; char slop[100]; }dir; - k = c->offset; - for(m=0; mdri++) { + switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){ case -1: return m; case 0: - c->offset++; /* BUG??? (was DIRLEN: skip entry) */ break; case 1: diff --git a/port/devdup.c b/port/devdup.c index 254a73c26e5f4786f95432f82a1353d53f2ecc6d..ad4e42df79ca98240e1fd8cdcb2bef15f00c5869 100644 --- a/port/devdup.c +++ b/port/devdup.c @@ -103,7 +103,7 @@ dupread(Chan *c, void *va, long n, vlong offset) { char *a = va; char buf[256]; - int fd, twicefd, m; + int fd, twicefd; Fgrp *f; if(c->qid.type == QTDIR) diff --git a/port/devmnt.c b/port/devmnt.c index cdfa2e7135b5f9eaced6174fddfba7f3ded149b1..29dd0b36a07f14bfa5f8d57a3f3e9b729ad0e162 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -410,7 +410,6 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) if(waserror()) { mntfree(r); nexterror(); - return nil; } r->request.type = Twalk; r->request.fid = c->fid; diff --git a/port/portdat.h b/port/portdat.h index 8f1ad3310e40390e6aaef7c52354d0916e07baab..46ddd657239e39bcb80979739f3f8a48e38a9410 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -155,6 +155,7 @@ struct Chan Chan* umc; /* channel in union; held for union read */ QLock umqlock; /* serialize unionreads */ int uri; /* union read index */ + int dri; /* devdirread index */ ulong mountid; Mntcache *mcp; /* Mount cache pointer */ Mnt *mux; /* Mnt for clients using me for messages */ @@ -609,7 +610,8 @@ struct Proc Sargs s; /* address of this is known by db */ int nerrlab; Label errlab[NERR]; - char error[ERRMAX]; + char syserror[ERRMAX]; /* last error from a system call */ + char error[ERRMAX]; /* reason we're unwinding the error stack */ char genbuf[128]; /* buffer used e.g. for last name element from namec */ Chan *slash; Chan *dot; diff --git a/port/proc.c b/port/proc.c index 619c53435f62044509b0df59a599acf459a0273c..94f468f6c38e3ee40fd4bd6eac636c66c3c4c2a3 100644 --- a/port/proc.c +++ b/port/proc.c @@ -339,6 +339,7 @@ newproc(void) p->wired = 0; p->ureg = 0; p->error[0] = '\0'; + p->syserror[0] = '\0'; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); @@ -1108,7 +1109,7 @@ void error(char *err) { spllo(); - strncpy(up->error, err, ERRMAX); + kstrcpy(up->error, err, sizeof up->error); nexterror(); } diff --git a/port/sysfile.c b/port/sysfile.c index 403d834093d5e9420589fb715906047d0e16ed8e..50f24da8440298cbab715741f47ad4fc9940750a 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -557,6 +557,7 @@ sseek(ulong *arg) } *(vlong*)arg[0] = off; c->uri = 0; + c->dri = 0; cclose(c); poperror(); } @@ -783,7 +784,7 @@ sysunmount(ulong *arg) nexterror(); } validaddr(arg[0], 1, 0); - cmounted = namec((char*)arg[0], Aopen, OREAD, 0); + cmounted = namec((char*)arg[0], Aaccess, OREAD, 0); poperror(); } diff --git a/port/sysproc.c b/port/sysproc.c index 5210b364a61a3820166ec53d57c52295f2cae475..3fd34e24066e0f425fe13996b6978d838c728b82 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -633,41 +633,36 @@ werrstr(char *fmt, ...) va_end(va); } -long -syserrstr(ulong *arg) +static long +generrstr(char *buf, uint nbuf) { - char *e, tmp[sizeof up->error]; - uint n; + char tmp[sizeof up->syserror]; - n = arg[1]; - if(n > sizeof tmp) - n = sizeof tmp; - validaddr(arg[0], n, 1); - e = (char*)arg[0]; - memmove(tmp, e, n); + validaddr((ulong)buf, nbuf, 1); + if(nbuf > sizeof tmp) + nbuf = sizeof tmp; + memmove(tmp, buf, nbuf); /* make sure it's NUL-terminated */ - tmp[n-1] = '\0'; - memmove(e, up->error, n); - e[n-1] = '\0'; - memmove(up->error, tmp, n); + tmp[nbuf-1] = '\0'; + memmove(buf, up->syserror, nbuf); + buf[nbuf-1] = '\0'; + memmove(up->syserror, tmp, nbuf); return 0; } +long +syserrstr(ulong *arg) +{ + return generrstr((char*)arg[0], arg[1]); +} + /* compatibility for old binaries */ long sys_errstr(ulong *arg) { - char *e, tmp[64]; - - validaddr(arg[0], 64, 1); - e = (char*)arg[0]; - memmove(tmp, e, 64); - memmove(e, up->error, 64); - memmove(up->error, tmp, 64); - return 0; + return generrstr((char*)arg[0], 64); } - long sysnotify(ulong *arg) {