From 0840ca4ab4184994bf3495c6ae74cd4d52464800 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 2 Aug 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-08-02 --- gnot/mmu.c | 2 +- pc/bbmalloc.c | 6 ++ pc/clock.c | 8 +- pc/devfloppy.c | 255 ++++++++++++++++++++++++++++--------------- pc/devhard.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++ pc/fns.h | 6 +- pc/headland.c | 52 +++++---- pc/main.c | 35 ------ pc/trap.c | 9 +- port/page.c | 110 ++++++++++++------- port/portdat.h | 5 +- power/lock.c | 32 +++--- power/segment.h | 7 +- 13 files changed, 594 insertions(+), 213 deletions(-) create mode 100644 pc/devhard.c diff --git a/gnot/mmu.c b/gnot/mmu.c index 92b59374297fb453251916c42698a5c6f87b4499..78e96b6e2aeed2f17ce72c120b3d4c37142bca94 100644 --- a/gnot/mmu.c +++ b/gnot/mmu.c @@ -127,7 +127,7 @@ kmapinit(void) return; } e = (4*1024*1024 - 256*1024)/BY2PG; /* screen lives at top 256K */ - i = (((ulong)ialloc(0, 0))&~KZERO)/BY2PG; + i = PGROUND(((ulong)ialloc(0, 0))&~KZERO)/BY2PG; print("%lud free map registers\n", e-i); kmapalloc.free = 0; for(k=&kmapalloc.arena[i]; itime[p->insyscall]++; } -/* if(u && p && p->state==Running){ + if(u && p && p->state==Running){ if(anyready()){ if(p->hasspin) p->hasspin = 0; else sched(); } - }/**/ + if((ur->cs&0xffff) == UESEL){ /* if was in user mode */ + if(u->nnote) + notify(ur); + } + } } diff --git a/pc/devfloppy.c b/pc/devfloppy.c index 2470a55063af797de23a1ea712e9baa5f8eb4e8a..8438a0d1d5292710806aea92df9d8fc58d7e38b2 100644 --- a/pc/devfloppy.c +++ b/pc/devfloppy.c @@ -4,11 +4,11 @@ #include "dat.h" #include "fns.h" #include "io.h" -#include "ureg.h" +#include "errno.h" -typedef struct Drive Drive; +typedef struct Drive Drive; typedef struct Controller Controller; -typedef struct Type Type; +typedef struct Type Type; enum { @@ -46,8 +46,9 @@ enum /* file types */ Qdir= 0, - Qdata= 1, - Qstruct= 2, + Qdata= (1<<2), + Qstruct= (2<<2), + Qmask= (3<<2), }; /* @@ -82,7 +83,9 @@ Type floppytype[] = #define NTYPES (sizeof(floppytype)/sizeof(Type)) /* - * bytes/sector encoding for the controller, index is (bytes per sector/128) + * bytes per sector encoding for the controller. + * - index for b2c is is (bytes per sector/128). + * - index for c2b is code from b2c */ static int b2c[] = { @@ -112,7 +115,6 @@ struct Drive ulong lasttouched; /* time last touched */ int motoron; /* motor is on */ int cyl; /* current cylinder */ - long offset; /* current offset */ int confused; /* needs to be recalibrated (or worse) */ int tcyl; /* target cylinder */ @@ -120,7 +122,6 @@ struct Drive int tsec; /* target sector */ long len; /* size of xfer */ - int busy; /* true if drive is seeking */ Rendez r; /* waiting here for motor to spin up */ }; @@ -132,11 +133,12 @@ struct Controller QLock; /* exclusive access to the contoller */ Drive d[Ndrive]; /* the floppy drives */ - int busy; /* true if a read or write in progress */ uchar stat[8]; /* status of an operation */ int confused; int intr; /* true if interrupt occured */ Rendez r; /* wait here for command termination */ + + Rendez kr; /* for motor watcher */ }; Controller floppy; @@ -150,46 +152,50 @@ static void floppykproc(void*); static int floppysend(int); static int floppyrcv(void); static int floppyresult(int); -static void floppypos(Drive*); +static void floppypos(Drive*,long); static int floppysense(Drive*); static int interrupted(void*); static int floppyrecal(Drive*); static void floppyrevive(void); static long floppyseek(Drive*); -static long floppyxfer(Drive*, int, void*, long); +static long floppyxfer(Drive*, int, void*, long, long); static void floppyintr(Ureg*); -static int -floppygen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp) -{ - long l; - Drive *dp; - - if(s >= ntab) - return -1; - if(c->dev >= Ndrive) - return -1; - - tab += s; - dp = &floppy.d[c->dev]; - if((tab->qid.path&~Mask) == Qdata) - l = dp->t->cap; - else - l = 8; - devdir(c, tab->qid, tab->name, l, tab->perm, dp); - return 1; -} +Dirtab floppydir[]={ + "fd0data", {Qdata + 0}, 0, 0600, + "fd0struct", {Qstruct + 0}, 8, 0600, + "fd1data", {Qdata + 1}, 0, 0600, + "fd1struct", {Qstruct + 1}, 8, 0600, + "fd2data", {Qdata + 2}, 0, 0600, + "fd2struct", {Qstruct + 2}, 8, 0600, + "fd3data", {Qdata + 3}, 0, 0600, + "fd3struct", {Qstruct + 3}, 8, 0600, +}; +#define NFDIR (sizeof(floppydir)/sizeof(Dirtab)) void floppyreset(void) { Drive *dp; + Type *t; + + /* + * init dependent parameters + */ + for(t = floppytype; t < &floppytype[NTYPES]; t++){ + t->cap = t->bytes * t->heads * t->sectors * t->tracks; + t->bcode = b2c[t->bytes/128]; + } + /* + * stop the motors + */ for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ + floppydir[2*dp->dev].length = dp->t->cap; dp->motoron = 1; - dp->cyl = -1; + dp->cyl = -1; /* because we don't know */ motoroff(dp); } setvec(Floppyvec, floppyintr); @@ -198,21 +204,74 @@ floppyreset(void) void floppyinit(void) { - Type *t; - - /* - * init dependent parameters - */ - for(t = floppytype; t < &floppytype[NTYPES], t++){ - t->cap = t->bytes * t->heads * t->sectors * t->tracks; - t->bcode = bcode[t->bytes/128]; - } - /* * watchdog to turn off the motors */ - kproc(floppykproc, 0); + kproc("floppy", floppykproc, 0); +} + +Chan* +floppyattach(char *spec) +{ + return devattach('f', spec); } + +Chan* +floppyclone(Chan *c, Chan *nc) +{ + return devclone(c, nc); +} + +int +floppywalk(Chan *c, char *name) +{ + return devwalk(c, name, floppydir, NFDIR, devgen); +} + +void +floppystat(Chan *c, char *dp) +{ + devstat(c, dp, floppydir, NFDIR, devgen); +} + +Chan* +floppyopen(Chan *c, int omode) +{ + return devopen(c, omode, floppydir, NFDIR, devgen); +} + +void +floppycreate(Chan *c, char *name, int omode, ulong perm) +{ + error(Eperm); +} + +void +floppyclose(Chan *c) +{ +} + +void +floppyremove(Chan *c) +{ + error(Eperm); +} + +void +floppywstat(Chan *c, char *dp) +{ + error(Eperm); +} + +static void +ul2user(uchar *a, ulong x) +{ + a[0] = x >> 24; + a[1] = x >> 16; + a[2] = x >> 8; + a[3] = x; +} + long floppyread(Chan *c, void *a, long n) { @@ -220,11 +279,30 @@ floppyread(Chan *c, void *a, long n) long rv, i; uchar *aa = a; - dp = &floppy.d[c->dev]; - for(rv = 0; rv < n; rv += i){ - i = floppyxfer(dp, Fread, aa+rv, n-rv); - if(i <= 0) - break; + if(c->qid.path == CHDIR) + return devdirread(c, a, n, floppydir, NFDIR, devgen); + + rv = 0; + dp = &floppy.d[c->qid.path & ~Qmask]; + switch ((int)(c->qid.path & Qmask)) { + case Qdata: + for(rv = 0; rv < n; rv += i){ + i = floppyxfer(dp, Fread, aa+rv, c->offset+rv, n-rv); + if(i <= 0) + break; + } + break; + case Qstruct: + if (n < 2*sizeof(ulong)) + error(Ebadarg); + if (c->offset >= 2*sizeof(ulong)) + return 0; + rv = 2*sizeof(ulong); + ul2user((uchar*)a, dp->t->cap); + ul2user((uchar*)a+sizeof(ulong), dp->t->bytes); + break; + default: + panic("floppyread: bad qid"); } return rv; } @@ -236,17 +314,27 @@ floppywrite(Chan *c, void *a, long n) long rv, i; uchar *aa = a; - dp = &floppy.d[c->dev]; - for(rv = 0; rv < n; rv += i){ - i = floppyxfer(dp, Fwrite, aa+rv, n-rv); - if(i <= 0) - break; + rv = 0; + dp = &floppy.d[c->qid.path & ~Qmask]; + switch ((int)(c->qid.path & Qmask)) { + case Qdata: + for(rv = 0; rv < n; rv += i){ + i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv); + if(i <= 0) + break; + } + break; + case Qstruct: + error(Eperm); + break; + default: + panic("floppywrite: bad qid"); } return rv; } /* - * start a floppy drive's motor. set an alarm for 1 second later to + * start a floppy drive's motor. set an alarm for .75 second later to * mark it as started (we get no interrupt to tell us). * * assume the caller qlocked the drive. @@ -258,10 +346,8 @@ motoron(Drive *dp) cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev; outb(Fmotor, cmd); - dp->busy = 1; - tsleep(&dp->r, noreturn, 0, 1000); + tsleep(&dp->r, return0, 0, 750); dp->motoron = 1; - dp->busy = 0; dp->lasttouched = m->ticks; } @@ -282,13 +368,17 @@ floppykproc(void *a) { Drive *dp; - for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ - if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 - && canqlock(dp)){ - if(TK2SEC(m->ticks - dp->lasttouched) > 5) - motoroff(dp); - qunlock(dp); + waserror(); + for(;;){ + for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ + if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 + && canqlock(dp)){ + if(TK2SEC(m->ticks - dp->lasttouched) > 5) + motoroff(dp); + qunlock(dp); + } } + tsleep(&floppy.kr, return0, 0, 5*1000); } } @@ -367,13 +457,13 @@ floppyresult(int n) * truncate dp->length if it crosses a cylinder boundary */ static void -floppypos(Drive *dp) +floppypos(Drive *dp, long off) { int lsec; int end; int cyl; - lsec = dp->off/dp->t->bytes; + lsec = off/dp->t->bytes; dp->tcyl = lsec/(dp->t->sectors*dp->t->heads); dp->tsec = (lsec % dp->t->sectors) + 1; dp->thead = (lsec/dp->t->sectors) % dp->t->heads; @@ -382,7 +472,7 @@ floppypos(Drive *dp) * can't read across cylinder boundaries. * if so, decrement the bytes to be read. */ - lsec = (dp->off+dp->len)/dp->t->bytes; + lsec = (off+dp->len)/dp->t->bytes; cyl = lsec/(dp->t->sectors*dp->t->heads); if(cyl != dp->tcyl){ dp->len -= (lsec % dp->t->sectors)*dp->t->bytes; @@ -414,7 +504,7 @@ floppysense(Drive *dp) /* * make sure it's the right drive */ - if((floppy.stat[0] & Drivemask) != dp-floppy.d){ + if((floppy.stat[0] & Drivemask) != dp->dev){ print("sense failed\n"); dp->confused = 1; return -1; @@ -517,14 +607,14 @@ floppyrevive(void) static long floppyseek(Drive *dp) { - if(dp->cyl == dp->tcyl){ - dp->offset = off; - return off; - } + if(dp->cyl == dp->tcyl) + return dp->cyl; /* * tell floppy to seek */ + floppy.intr = 0; + dp->cyl = -1; /* once the seek starts it could end anywhere */ if(floppysend(Fseek) < 0 || floppysend((dp->thead<<2) | dp->dev) < 0 || floppysend(dp->tcyl * dp->t->steps) < 0){ @@ -532,10 +622,6 @@ floppyseek(Drive *dp) floppy.confused = 1; return -1; } - - /* - * wait for interrupt - */ sleep(&floppy.r, interrupted, 0); /* @@ -563,12 +649,11 @@ floppyseek(Drive *dp) return -1; } - dp->offset = off; - return dp->offset; + return dp->cyl; } static long -floppyxfer(Drive *dp, int cmd, void *a, long n) +floppyxfer(Drive *dp, int cmd, void *a, long off, long n) { ulong addr; long offset; @@ -577,7 +662,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long n) qlock(&floppy); qlock(dp); - if(waserror){ + if(waserror()){ qunlock(&floppy); qunlock(dp); } @@ -594,7 +679,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long n) * calculate new position and seek to it (dp->len may be trimmed) */ dp->len = n; - floppypos(dp); + floppypos(dp, off); if(floppyseek(dp) < 0) errors("seeking floppy"); @@ -609,9 +694,10 @@ print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", /* * start operation */ + floppy.intr = 0; cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); if(floppysend(cmd) < 0 - || floppysend((dp->thead<<2) | dev) < 0 + || floppysend((dp->thead<<2) | dp->dev) < 0 || floppysend(dp->tcyl * dp->t->steps) < 0 || floppysend(dp->thead) < 0 || floppysend(dp->tsec) < 0 @@ -623,7 +709,6 @@ print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", floppy.confused = 1; errors("floppy command failed"); } - sleep(&floppy.r, interrupted, 0); /* @@ -645,17 +730,17 @@ print("xfer failed %lux %lux %lux\n", floppy.stat[0], offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4]; offset = offset*dp->t->sectors + floppy.stat[5] - 1; offset = offset * c2b[floppy.stat[6]]; - if(offset != dp->offset+n){ -print("new offset %d instead of %d\n", offset, dp->offset+dp->len); + if(offset != off+dp->len){ +print("new offset %d instead of %d\n", offset, off+dp->len); dp->confused = 1; errors("floppy drive lost"); } + dp->lasttouched = m->ticks; qunlock(&floppy); qunlock(dp); poperror(); - dp->offset += dp->len; return dp->len; } diff --git a/pc/devhard.c b/pc/devhard.c new file mode 100644 index 0000000000000000000000000000000000000000..96558261a64816768e560a4683c389d9968798b5 --- /dev/null +++ b/pc/devhard.c @@ -0,0 +1,280 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "errno.h" + +typedef struct Drive Drive; +typedef struct Ident Ident; +typedef struct Controller Controller; + +enum +{ + /* ports */ + Pbase= 0x10, + Pdata= Pbase+0, /* data port (16 bits) */ + Perror= Pbase+1, /* error port */ + Pcount= Pbase+2, /* sector count port */ + Psector= Pbase+3, /* sector number port */ + Pcyllsb= Pbase+4, /* least significant byte cylinder # */ + Pcylmsb= Pbase+5, /* most significant byte cylinder # */ + Pdh= Pbase+6, /* drive/head port */ + Pstatus= Pbase+7, /* status port */ + Pcmd= Pbase+7, /* cmd port */ + + /* commands */ + Crecal= 0x10, + Cread= 0x20, + Cwrite= 0x30, + Cident= 0xEC, + + /* file types */ + Qdir= 0, + Qdata= (1<<1), + Qstruct= (2<<1), + Qmask= (3<<1), +}; + +/* + * ident sector from drive + */ +struct Ident +{ + ushort magic; /* must be 0x0A5A */ + ushort lcyls; /* logical number of cylinders */ + ushort rcyl; /* number of removable cylinders */ + ushort lheads; /* logical number of heads */ + ushort b2t; /* unformatted bytes/track */ + ushort b2s; /* unformated bytes/sector */ + ushort ls2t; /* logical sectors/track */ + ushort gap; /* bytes in inter-sector gaps */ + ushort sync; /* bytes in sync fields */ + ushort magic2; /* must be 0x0000 */ + ushort serial[10]; /* serial number */ + ushort type; /* controller type (0x0003) */ + ushort bsize; /* buffer size/512 */ + ushort ecc; /* ecc bytes returned by read long */ + ushort firm[4]; /* firmware revision */ + ushort model[20]; /* model number */ + ushort s2i; /* number of sectors/interrupt */ + ushort dwtf; /* double word transfer flag */ + ushort alernate; + ushort piomode; + ushort dmamode; + ushort reserved[76]; + ushort ncyls; /* native number of cylinders */ + ushort nheads; /* native number of heads, sectors */ + ushort dlcyls; /* default logical number of cyinders */ + ushort dlheads; /* default logical number of heads, sectors */ + ushort interface; + ushort power; /* 0xFFFF if power commands supported */ + ushort flags; + ushort ageprog; /* MSB = age, LSB = program */ + ushort reserved2[120]; +}; + +/* + * a hard drive + */ +struct Drive +{ + int dev; + ulong cap; /* drive capacity */ + int bytes; /* bytes/sector */ + int cyl; /* current cylinder */ + int confused; /* needs to be recalibrated (or worse) */ + + int tcyl; /* target cylinder */ + int thead; /* target head */ + int tsec; /* target sector */ + long len; /* size of xfer */ + + Ident id; +}; + +/* + * a controller for 2 drives + */ +struct Controller +{ + QLock; /* exclusive access to the drive */ + + int intr; /* true if interrupt occured */ + Rendez r; /* wait here for command termination */ + int confused; /* needs to be recalibrated (or worse) */ + + Drive d[2]; +}; + +Controller hard; + +Dirtab harddir[]={ + "hddata", {Qdata}, 0, 0600, + "hdstruct", {Qstruct}, 8, 0600, +}; +#define NHDIR (sizeof(harddir)/sizeof(Dirtab)) + +void +hardreset(void) +{ + hard.d[0].dev = 0; + hard.d[1].dev = 1; + setvec(Hardvec, hardintr); +} + +void +hardinit(void) +{ +} + +Chan* +hardattach(char *spec) +{ + return devattach('f', spec); +} + +Chan* +hardclone(Chan *c, Chan *nc) +{ + return devclone(c, nc); +} + +int +hardwalk(Chan *c, char *name) +{ + return devwalk(c, name, harddir, NHDIR, devgen); +} + +void +hardstat(Chan *c, char *dp) +{ + devstat(c, dp, harddir, NHDIR, devgen); +} + +Chan* +hardopen(Chan *c, int omode) +{ + return devopen(c, omode, harddir, NHDIR, devgen); +} + +void +hardcreate(Chan *c, char *name, int omode, ulong perm) +{ + error(Eperm); +} + +void +hardclose(Chan *c) +{ +} + +void +hardremove(Chan *c) +{ + error(Eperm); +} + +void +hardwstat(Chan *c, char *dp) +{ + error(Eperm); +} + +static void +ul2user(uchar *a, ulong x) +{ + a[0] = x >> 24; + a[1] = x >> 16; + a[2] = x >> 8; + a[3] = x; +} + +long +hardread(Chan *c, void *a, long n) +{ + Drive *dp; + long rv, i; + uchar *aa = a; + + if(c->qid.path == CHDIR) + return devdirread(c, a, n, harddir, NHDIR, devgen); + + rv = 0; + dp = &hard.d[c->qid.path & ~Qmask]; + switch ((int)(c->qid.path & Qmask)) { + case Qdata: + for(rv = 0; rv < n; rv += i){ + i = hardxfer(dp, Fread, aa+rv, c->offset+rv, n-rv); + if(i <= 0) + break; + } + break; + case Qstruct: + hardident(dp); + if (n < 2*sizeof(ulong)) + error(Ebadarg); + if (c->offset >= 2*sizeof(ulong)) + return 0; + rv = 2*sizeof(ulong); + ul2user((uchar*)a, dp->cap); + ul2user((uchar*)a+sizeof(ulong), dp->bytes); + break; + default: + panic("hardread: bad qid"); + } + return rv; +} + +long +hardwrite(Chan *c, void *a, long n) +{ + Drive *dp; + long rv, i; + uchar *aa = a; + + rv = 0; + dp = &hard.d[c->qid.path & ~Qmask]; + switch ((int)(c->qid.path & Qmask)) { + case Qdata: + for(rv = 0; rv < n; rv += i){ + i = hardxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv); + if(i <= 0) + break; + } + break; + case Qstruct: + error(Eperm); + break; + default: + panic("hardwrite: bad qid"); + } + return rv; +} + +/* + * did an interrupt happen? + */ +static int +interrupted(Drive *dp) +{ + return hard.intr; +} + +/* + * get parameters from the drive + */ +hardident(Drive *dp) +{ + hard.intr = 0; + outb(Pdh, dp->dev<<4); + outb(Pcmd, Cident); +} + +long +hardxfer(Drive *dp, int cmd, void *va, long off, long len) +{ + errors("not implemented"); +} + diff --git a/pc/fns.h b/pc/fns.h index 66a035e6ab432620d0dd22589ede374db90d8b8d..b552fef9c82b260abf51a68acc23de16460a03e4 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -5,13 +5,11 @@ void a20enable(void); void clock(Ureg*); void clockinit(void); void delay(int); +void dmaend(int); +long dmasetup(int, void*, long, int); #define evenaddr(x) /* 386 doesn't care */ void fault386(Ureg*); void faultinit(void); -void floppyinit(void); -void floppyintr(Ureg*); -long floppyseek(int, long); -long floppyread(int, void*, long); #define flushvirt(); void fpsave(FPsave*); void fprestore(FPsave*); diff --git a/pc/headland.c b/pc/headland.c index 7f348d77d0a84e52423525e1215d67b3e6343879..f258a16ecad524e070f1f765310a380e6057090f 100644 --- a/pc/headland.c +++ b/pc/headland.c @@ -7,9 +7,15 @@ /* * headland chip set for the safari. */ +typedef struct DMAport DMAport; +typedef struct DMA DMA; +typedef struct DMAxfer DMAxfer; enum { + /* + * system control port + */ Head= 0x92, /* control port */ Reset= (1<<0), /* reset the 386 */ A20ena= (1<<1), /* enable address line 20 */ @@ -32,10 +38,9 @@ enum /* * state of a dma transfer */ -typedef struct DMAxfer DMAxfer; struct DMAxfer { - Page pg; /* page used by dma */ + Page *pg; /* page used by dma */ void *va; /* virtual address destination/src */ long len; /* bytes to be transferred */ int isread; @@ -45,7 +50,6 @@ struct DMAxfer * the dma controllers. the first half of this structure specifies * the I/O ports used by the DMA controllers. */ -typedef struct DMAport DMAport; struct DMAport { uchar addr[4]; /* current address (4 channels) */ @@ -63,7 +67,6 @@ struct DMAport Lock; }; -typdef struct DMA DMA; struct DMA { DMAport; @@ -123,21 +126,20 @@ dmasetup(int chan, void *va, long len, int isread) uchar mode; dp = &dma[(chan>>2)&1]; - chan &= 3; + chan = chan & 3; xp = &dp->x[chan]; /* - * if this isn't kernel memory, we can't count on it being - * there during the DMA. Allocate a page for the DMA. + * if this isn't kernel memory (or crossing 64k boundary), + * allocate a page for the DMA. */ - if(isphys(va)){ - pa = va & ~KZERO; - } else { + pa = ((ulong)va) & ~KZERO; + if(!isphys(va) || (pa&0xFFFF0000)!=((pa+len)&0xFFFF0000)){ xp->pg = newpage(1, 0, 0); if(len > BY2PG) len = BY2PG; if(!isread) - memmove(KZERO|xp->pg->pa, a, len); + memmove((void*)(KZERO|xp->pg->pa), va, len); xp->va = va; xp->len = len; xp->isread = isread; @@ -151,15 +153,15 @@ dmasetup(int chan, void *va, long len, int isread) outb(dp->cbp, 0); /* set count & address to their first byte */ mode = (isread ? 0x44 : 0x48) | chan; outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */ - outb(dp->addr, pa); /* set address */ - outb(dp->addr, pa>>8); - outb(dp->page, pa>>16); - outb(dp->count, len-1); /* set count */ - outb(dp->count, (len-1)>>8); + outb(dp->addr[chan], pa); /* set address */ + outb(dp->addr[chan], pa>>8); + outb(dp->page[chan], pa>>16); + outb(dp->count[chan], len-1); /* set count */ + outb(dp->count[chan], (len-1)>>8); outb(dp->sbm, chan); /* enable the channel */ unlock(dp); - return n; + return len; } /* @@ -178,13 +180,23 @@ dmaend(int chan) uchar mode; dp = &dma[(chan>>2)&1]; - chan &= 3; - outb(dp->sbm, 4|chan); /* disable the channel */ + chan = chan & 3; + + /* + * disable the channel + */ + lock(dp); + outb(dp->sbm, 4|chan); + unlock(dp); + xp = &dp->x[chan]; if(xp->pg == 0) return; - memmove(a, KZERO|xp->pg->pa, xp->len); + /* + * copy out of temporary page + */ + memmove(xp->va, (void*)(KZERO|xp->pg->pa), xp->len); putpage(xp->pg); xp->pg = 0; } diff --git a/pc/main.c b/pc/main.c index 2bd54b4c4e4f8863fae1bb4001ef0cb3184b9479..1b3dcb5b157574620fe4ee65aa48986a92c7534d 100644 --- a/pc/main.c +++ b/pc/main.c @@ -265,38 +265,3 @@ void lights(int val) { } - -/* - * headland hip set for the safari. - * - * serious magic!!! - */ - -enum -{ - Head= 0x92, /* control port */ - Reset= (1<<0), /* reset the 386 */ - A20ena= (1<<1), /* enable address line 20 */ -}; - -/* - * enable address bit 20 - */ -void -a20enable(void) -{ - outb(Head, A20ena); -} - -/* - * reset the chip - */ -void -exit(void) -{ - int i; - - u = 0; - print("exiting\n"); - outb(Head, Reset); -} diff --git a/pc/trap.c b/pc/trap.c index 1eff53b5f66a4be0e822ed68d3159b0197256f56..1d52aec7f8dc7a1827eaa840c89182548af6eaba 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -251,6 +251,7 @@ syscall(Ureg *ur) sp = ur->usp; u->nerrlab = 0; ret = -1; + spllo(); if(!waserror()){ if(ax >= sizeof systab/BY2WD){ pprint("bad sys call number %d pc %lux\n", ax, ur->pc); @@ -270,9 +271,9 @@ syscall(Ureg *ur) } u->p->insyscall = 0; ur->ax = ret; - if(ax == NOTED) + if(ax == NOTED){ noted(ur, *(ulong*)(sp+BY2WD)); - else if(u->nnote && ax!=FORK){ + } else if(u->nnote && ax!=FORK){ notify(ur); } return ret; @@ -346,7 +347,7 @@ noted(Ureg *ur, ulong arg0) validaddr(nur->pc, 1, 0); validaddr(nur->usp, BY2WD, 0); if(nur->cs!=u->svcs || nur->ss!=u->svss - || (nur->flags&0xff)!=(u->svflags&0xff)){ + || (nur->flags&0xff00)!=(u->svflags&0xff00)){ pprint("bad noted ureg cs %ux ss %ux flags %ux\n", nur->cs, nur->ss, nur->flags); pexit("Suicide", 0); @@ -359,10 +360,8 @@ noted(Ureg *ur, ulong arg0) u->notified = 0; nur->flags = (u->svflags&0xffffff00) | (ur->flags&0xff); memmove(ur, u->ureg, sizeof(Ureg)); -/* ur->ax = -1; /* return error from the interrupted syscall */ switch(arg0){ case NCONT: - splhi(); unlock(&u->p->debug); return; diff --git a/port/page.c b/port/page.c index 3a7a65321be666190c43d9ccc62e30626e58de44..14a5f26757f63cedaef0741a0dd76cbd04804172 100644 --- a/port/page.c +++ b/port/page.c @@ -51,31 +51,50 @@ unlockpage(Page *p) } /* - * Called to allocate permanent data structures, before calling pageinit(). + * Called to allocate permanent data structures, before calling pageinit(). + * We assume all of text+data+bss is in the first memory bank. */ void* ialloc(ulong n, int align) { ulong p; + ulong *ap; if(palloc.active && n!=0) print("ialloc bad\n"); - if(palloc.addr == 0) - palloc.addr = ((ulong)&end)&~KZERO; - if(align) - palloc.addr = PGROUND(palloc.addr); - if(palloc.addr+n > conf.base0 + conf.npage0*BY2PG) - palloc.addr = conf.base1; + if(palloc.addr0 == 0){ + palloc.addr0 = ((ulong)&end)&~KZERO; + palloc.addr1 = conf.base1; + } - memset((void*)(palloc.addr|KZERO), 0, n); - p = palloc.addr; - palloc.addr += n; - if(align) - palloc.addr = PGROUND(palloc.addr); + /* + * try first bank + */ + p = align ? PGROUND(palloc.addr0) : palloc.addr0; + if(p+n > conf.base0 + (conf.npage0<= conf.maxialloc) + panic("keep bill joy away 2"); - if(palloc.addr >= conf.maxialloc) - panic("keep bill joy away"); + /* + * zero it + */ + memset((void*)(p|KZERO), 0, n); + + /* + * don't put anything else into a page aligned ialloc + */ + *ap = align ? PGROUND(p+n) : (p+n); return (void*)(p|KZERO); } @@ -83,44 +102,55 @@ ialloc(ulong n, int align) void pageinit(void) { - ulong pa, nb, ppn; + ulong np, addr, lim; ulong i, vmem, pmem; Page *p; - palloc.active = 1; - - nb = (conf.npage<>PGSHIFT)*sizeof(Page); /* safe overestimate */ - nb &= ~(BY2PG-1); - pa = (conf.npage<> PGSHIFT; /* physical page number of first free page */ - palloc.page = (Page *)((palloc.addr - ppn*sizeof(Page))|KZERO); /* - * Now palloc.page[ppn] describes first free page + * calculate an upper bound to the number of pages structures + * we'll need (np). */ - palloc.minppn = ppn; - palloc.addr = ppn<>PGSHIFT; - palloc.head = &palloc.page[ppn]; - palloc.tail = &palloc.page[conf.npage-1]; - memset(palloc.head, 0, (conf.npage-ppn)*sizeof(Page)); - - pmem = ((conf.npage-ppn)*BY2PG)/1024; - vmem = pmem + ((conf.nswap)*BY2PG)/1024; - palloc.user = conf.npage-ppn; - print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem); + /* + * allocate Page structs (no more ialloc's allowed after this). + * np is useless after this ialloc since we've just eaten up + * some pages for the Page structures. + */ + palloc.head = ialloc(np*sizeof(Page), 0); + palloc.active = 1; - for(p=palloc.head; p<=palloc.tail; p++,ppn++){ + /* + * for each page in each bank, point a page structure to + * the page and chain it into the free list + */ + p = palloc.head; + addr = palloc.addr0 = PGROUND(palloc.addr0); + lim = conf.base0 + (conf.npage0<next = p+1; p->prev = p-1; - if(ppn < conf.npage0) - p->pa = conf.base0+(ppn<pa = conf.base1+((ppn-conf.npage0)<pa = addr; + p++; } + addr = palloc.addr1 = PGROUND(palloc.addr1); + lim = conf.base1 + (conf.npage1<next = p+1; + p->prev = p-1; + p->pa = addr; + p++; + } + palloc.tail = p - 1; palloc.head->prev = 0; palloc.tail->next = 0; + + palloc.user = palloc.freecount = p - palloc.head; + pmem = palloc.user*BY2PG/1024; + vmem = pmem + ((conf.nswap)*BY2PG)/1024; + print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem); } Page* diff --git a/port/portdat.h b/port/portdat.h index f6943fb2807b0f88ca93cd4b14c0e4d8ad8118fa..a7b567153775fce9ae67ad681d2a2f88502b86f7 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -388,10 +388,9 @@ struct Fgrp struct Palloc { Lock; - ulong addr; + ulong addr0; /* next available ialloc addr in bank 0 */ + ulong addr1; /* next available ialloc addr in bank 1 */ int active; - Page *page; /* base of Page structures */ - ulong minppn; /* index of first usable page */ Page *head; /* most recently used */ Page *tail; /* least recently used */ ulong freecount; /* how many pages on free list now */ diff --git a/power/lock.c b/power/lock.c index 7c2fca8664c54e22215d41a8a323d0c464f6fd9b..d83e70de84696c17d8afcfda7e4103a78f1ee72c 100644 --- a/power/lock.c +++ b/power/lock.c @@ -115,15 +115,17 @@ lock(Lock *l) sbsem = l->sbsem; if(sbsem == 0){ lock(&semalloc.lock); - if(semalloc.nsem == SEMPERPG){ - semalloc.nsem = 0; - semalloc.nextsem = lkpgalloc(); + if(l->sbsem == 0){ + if(semalloc.nsem == SEMPERPG){ + semalloc.nsem = 0; + semalloc.nextsem = lkpgalloc(); + } + l->sbsem = semalloc.nextsem; + semalloc.nextsem++; + semalloc.nsem++; + unlock(l); /* put sem in known state */ } - l->sbsem = semalloc.nextsem; - semalloc.nextsem++; - semalloc.nsem++; unlock(&semalloc.lock); - unlock(l); /* put sem in known state */ sbsem = l->sbsem; } /* @@ -151,15 +153,17 @@ canlock(Lock *l) sbsem = l->sbsem; if(sbsem == 0){ lock(&semalloc.lock); - if(semalloc.nsem == SEMPERPG){ - semalloc.nsem = 0; - semalloc.nextsem = lkpgalloc(); + if(l->sbsem == 0){ + if(semalloc.nsem == SEMPERPG){ + semalloc.nsem = 0; + semalloc.nextsem = lkpgalloc(); + } + l->sbsem = semalloc.nextsem; + semalloc.nextsem++; + semalloc.nsem++; + unlock(l); /* put sem in known state */ } - l->sbsem = semalloc.nextsem; - semalloc.nextsem++; - semalloc.nsem++; unlock(&semalloc.lock); - unlock(l); /* put sem in known state */ sbsem = l->sbsem; } if(*sbsem & 1) diff --git a/power/segment.h b/power/segment.h index 8ff7b1d053dde1db314631cb6e0b81abdbf64a15..7821c5b2659aa493ba5b45f3df053c726eb11637 100644 --- a/power/segment.h +++ b/power/segment.h @@ -12,9 +12,8 @@ struct Physseg Page *(*pgalloc)(ulong); /* Allocation if we need it */ void (*pgfree)(Page*); }physseg[] = { - { SG_PHYSICAL, "lock", 0, 1024*BY2PG, &lkpage, &lkpgfree }, - { SG_SHARED, "shared", 0, SEGMAXSIZE, &snewpage, &putpage }, - { SG_PHYSICAL, "kmem", KZERO, SEGMAXSIZE, 0, 0 }, - { SG_BSS, "memory", 0, SEGMAXSIZE, &snewpage, &putpage }, + { SG_PHYSICAL, "lock", 0, 1024*BY2PG, lkpage, lkpgfree }, + { SG_SHARED, "shared", 0, SEGMAXSIZE, snewpage, putpage }, + { SG_BSS, "memory", 0, SEGMAXSIZE, snewpage, putpage }, { 0, 0, 0, 0, 0, 0 }, };