From 052458ba28fcc4327434b2c9cff79a2e2b4cfbd8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Jul 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-07-28 --- pc/devfloppy.c | 42 ++++++++--------- pc/headland.c | 120 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 122 insertions(+), 40 deletions(-) diff --git a/pc/devfloppy.c b/pc/devfloppy.c index e92a22104d1ddc2189262dadfd54757e935a7cf1..d964650499dd7c16bb67f4a6e10a39171039d8bd 100644 --- a/pc/devfloppy.c +++ b/pc/devfloppy.c @@ -29,15 +29,10 @@ enum Fwrite= 0x47, /* write cmd */ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ - DMAmode0= 0xb, - DMAmode1= 0xc, - DMAaddr= 0x4, - DMAtop= 0x81, - DMAinit= 0xa, - DMAcount= 0x5, - Nfloppy= 4, /* floppies/controller */ + DMAchan= 2, /* floppy dma channel */ + /* sector size encodings */ S128= 0, S256= 1, @@ -48,6 +43,11 @@ enum Drivemask= 3<<0, Seekend= 1<<5, Codemask= (3<<6)|(3<<3), + + /* file types */ + Qdir= 0, + Qdata= 16, + Qstruct= 32, }; /* @@ -117,7 +117,7 @@ struct Controller int confused; }; -Controller floppy[1]; +Controller floppy; /* * start a floppy drive's motor. set an alarm for 1 second later to @@ -151,8 +151,6 @@ floppystop(Drive *dp) { int cmd; - if(!canqlock(dp)) - return; cmd = Fintena | Fena | dp->dev; outb(Fmotor, cmd); dp->motoron = 0; @@ -162,14 +160,13 @@ floppykproc(Alarm* a) { Drive *dp; - if(waserror()) for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ - if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5) + if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 + && canqlock(dp)){ floppystop(dp); + qunlock(dp); + } } - - alarm(5*1000, floppyalarm, 0); - cancel(a); } int @@ -341,18 +338,23 @@ floppyrecal(Drive *dp) } void -floppyinit(void) +floppyreset(void) { Drive *dp; for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ - dp->t = &floppytype[0]; - dp->cyl = -1; + dp->dev = dp - floppy.d; + dp->t = &floppytype[0]; /* default type */ dp->motoron = 1; + dp->cyl = -1; floppystop(dp); } - setvec(22, floppyintr); - alarm(5*1000, floppyalarm, (void *)0); +} + +void +floppyinit(void) +{ + kproc(floppykproc, 0); } void diff --git a/pc/headland.c b/pc/headland.c index 684c8c797bc11b727315b6e6dcab5aefca8398ac..15f9baacae8deee2a3b2fd67284f77d9baa4142f 100644 --- a/pc/headland.c +++ b/pc/headland.c @@ -5,9 +5,7 @@ #include "fns.h" /* - * headland hip set for the safari. - * - * serious magic!!! + * headland chip set for the safari. */ enum @@ -18,10 +16,24 @@ enum }; /* - * ports used by the DMA controllers + * state of a dma transfer */ -typedef struct DMA DMA; -struct DMA { +typedef struct DMAxfer DMAxfer; +struct DMAxfer +{ + Page pg; /* page used by dma */ + void *va; /* virtual address destination/src */ + long len; /* bytes to be transferred */ + int isread; +}; + +/* + * 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) */ uchar count[4]; /* current count (4 channels) */ uchar page[4]; /* page registers (4 channels) */ @@ -33,6 +45,16 @@ struct DMA { uchar mc; /* master clear */ uchar cmask; /* clear mask register */ uchar wam; /* write all mask register bit */ + + Lock; +}; + +typdef struct DMA DMA; +struct DMA +{ + DMAport; + Lock; + DMAxfer x[4]; }; DMA dma[2] = { @@ -69,25 +91,83 @@ exit(void) } /* - * setup a dma transfer. return count actually set up. we DMA up - * to a page. + * setup a dma transfer. if the destination is not in kernel + * memory, allocate a page for the transfer. + * + * we assume BIOS has set up the command register before we + * are booted. */ long -dmasetup(int d, int chan, Page *pg, long len, int isread) +dmasetup(int chan, void *va, long len, int isread) { DMA *dp; - ulong addr; + DMAxfer *xp; + ulong pa; + uchar mode; + + dp = &dma[(chan>>2)&1]; + chan &= 3; + xp = &dp->x[chan]; - dp = &dma[d]; - addr = (ulong)a; - addr &= ~KZERO; + /* + * if this isn't kernel memory, we can't count on it being + * there during the DMA. Allocate a page for the DMA. + */ + if(isphys(va)){ + pa = va & ~KZERO; + } else { + xp->pg = newpage(1, 0, 0); + if(len > BY2PG) + len = BY2PG; + if(!isread) + memmove(KZERO|xp->pg->pa, a, len); + xp->va = va; + xp->len = len; + xp->isread = isread; + pa = xp->pg->pa; + } - outb(dp->cbp, isread ? 0x46 : 0x4a); - outb(dp->mode, isread ? 0x46 : 0x4a); - outb(dp->addr, addr); - outb(dp->addr, addr>>8); - outb(dp->page, addr>>16); - outb(dp->count, len-1); + /* + * this setup must be atomic + */ + lock(dp); + 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->sbm, 2); + outb(dp->sbm, chan); /* enable the channel */ + unlock(dp); + + return n; +} + +/* + * this must be called after a dma has been completed. + * + * if a page has been allocated for the dma, + * copy the data into the actual destination + * and free the page. + */ +void +dmaend(int chan) +{ + DMA *dp; + DMAxfer *xp; + ulong addr; + uchar mode; + + dp = &dma[(chan>>2)&1]; + chan &= 3; + outb(dp->sbm, 4|chan); /* disable the channel */ + xp = &dp->x[chan]; + if(xp->pg == 0) + return; + + memmove(a, KZERO|xp->pg->pa, xp->len); + putpage(xp->pg); + xp->pg = 0; }