From f90b2249fb5c368c5002206e650bf147efd4b812 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 19 Feb 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-02-19 --- pc/devata.c | 96 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/pc/devata.c b/pc/devata.c index c4a83d88c1260bd758fbeccc076b221148086184..b672da82714441ca79a9cc1d42435186721a05cd 100644 --- a/pc/devata.c +++ b/pc/devata.c @@ -10,9 +10,9 @@ #include "io.h" #include "../port/error.h" - -#define DPRINT if(0)print -#define XPRINT if(0)print +#define DEBUG 0 +#define DPRINT if(DEBUG)print +#define XPRINT if(DEBUG)print #define ILOCK(x) #define IUNLOCK(x) @@ -69,6 +69,7 @@ enum Creqsense= 0x03, Ccapacity= 0x25, Cread2= 0x28, + Cwrite2= 0x2A, /* disk states */ Sspinning, @@ -199,7 +200,7 @@ static void atasleep(Controller*, int); static void ataclock(void); static int isatapi(Drive*); -static long atapirwio(Chan*, char*, ulong, ulong); +static long atapirwio(Chan*, uchar*, ulong, ulong, int); static void atapipart(Drive*); static void atapiintr(Controller*); @@ -400,7 +401,6 @@ atactlrprobe(int ctlrno, int irq, int resetok) atapi = 0; mask = 0; - status = inb(port+Pstatus); DPRINT("ata%d: ATAPI %uX %uX %uX\n", ctlrno, status, inb(port+Pcylmsb), inb(port+Pcyllsb)); if(status == 0 && inb(port+Pcylmsb) == 0xEB && inb(port+Pcyllsb) == 0x14){ @@ -408,8 +408,7 @@ atactlrprobe(int ctlrno, int irq, int resetok) intrenable(irq, ataintr, ctlr, ctlr->tbdf); atapi |= 0x01; mask |= 0x01; -// goto skipedd; -goto atapislave; + goto atapislave; } if(atactlrwait(ctlr, DHmagic, 0, MS2TK(1)) || waserror()){ DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", ctlrno, @@ -441,9 +440,11 @@ goto atapislave; * in the cylinder registers after reset. Of course, if the drive * has been messed about by the BIOS or some other O/S then the * signature may be gone. + * When checking status, mask off the IDX bit. */ error = inb(port+Perror); - DPRINT("ata%d: master diag error %ux\n", ctlr->ctlrno, error); + DPRINT("ata%d: master diag status %uX, error %ux\n", + ctlr->ctlrno, inb(port+Pstatus), error); if((error & ~0x80) == 0x01) mask |= 0x01; @@ -453,7 +454,7 @@ atapislave: status = inb(port+Pstatus); error = inb(port+Perror); DPRINT("ata%d: slave diag status %ux, error %ux\n", ctlr->ctlrno, status, error); - if(status && (status & (Sbusy|Serr)) == 0 && (error & ~0x80) == 0x01) + if((status & ~0x02) && (status & (Sbusy|Serr)) == 0 && (error & ~0x80) == 0x01) mask |= 0x02; else if(status == 0){ msb = inb(port+Pcylmsb); @@ -658,7 +659,7 @@ ataread(Chan* c, void* a, long n, ulong offset) atapipart(dp); qunlock(dp); poperror(); - return atapirwio(c, a, n, offset); + return atapirwio(c, a, n, offset, Cread2); } pp = &dp->p[PART(c->qid.path)]; @@ -699,8 +700,19 @@ atawrite(Chan *c, void *a, long n, ulong offset) error(Eisdir); dp = atadrive[DRIVE(c->qid.path)]; - if(dp->atapi) - error(Eperm); + if(dp->atapi){ + if(dp->online == 0 || dp->atapi == 1) + error(Eio); + if(waserror()){ + qunlock(dp); + nexterror(); + } + qlock(dp); + if(dp->partok == 0) + atapipart(dp); + qunlock(dp); + poperror(); + } pp = &dp->p[PART(c->qid.path)]; buf = smalloc(Maxxfer); @@ -716,13 +728,19 @@ atawrite(Chan *c, void *a, long n, ulong offset) */ partial = offset % dp->bytes; if(partial){ - ataxfer(dp, pp, Cread, offset-partial, dp->bytes, buf); + if(dp->atapi) + atapirwio(c, buf, dp->bytes, offset-partial, Cread2); + else + ataxfer(dp, pp, Cread, offset-partial, dp->bytes, buf); if(partial+n > dp->bytes) rv = dp->bytes - partial; else rv = n; memmove(buf+partial, aa, rv); - ataxfer(dp, pp, Cwrite, offset-partial, dp->bytes, buf); + if(dp->atapi) + atapirwio(c, buf, dp->bytes, offset-partial, Cwrite2); + else + ataxfer(dp, pp, Cwrite, offset-partial, dp->bytes, buf); } else rv = 0; @@ -736,7 +754,10 @@ atawrite(Chan *c, void *a, long n, ulong offset) if(i > Maxxfer) i = Maxxfer; memmove(buf, aa+rv, i); - i = ataxfer(dp, pp, Cwrite, offset+rv, i, buf); + if(dp->atapi) + i = atapirwio(c, buf, i, offset+rv, Cwrite2); + else + i = ataxfer(dp, pp, Cwrite, offset+rv, i, buf); if(i == 0) break; } @@ -747,9 +768,15 @@ atawrite(Chan *c, void *a, long n, ulong offset) * it out. */ if(partial){ - ataxfer(dp, pp, Cread, offset+rv, dp->bytes, buf); + if(dp->atapi) + atapirwio(c, buf, dp->bytes, offset+rv, Cread2); + else + ataxfer(dp, pp, Cread, offset+rv, dp->bytes, buf); memmove(buf, aa+rv, partial); - ataxfer(dp, pp, Cwrite, offset+rv, dp->bytes, buf); + if(dp->atapi) + atapirwio(c, buf, dp->bytes, offset+rv, Cwrite2); + else + ataxfer(dp, pp, Cwrite, offset+rv, dp->bytes, buf); rv += partial; } @@ -1101,6 +1128,8 @@ retryatapi: dp->bytes = 2048; if((ip->config & 0x0060) == 0x0020) dp->drqintr = 1; + if((ip->config & 0x1F00) == 0x0000) + dp->atapi = 2; } if(dp->spindown && (ip->capabilities & (1<<13))) dp->spindown /= 5; @@ -1672,7 +1701,7 @@ atapiexec(Drive *dp) } static long -atapiio(Drive *dp, char *a, ulong len, ulong offset) +atapiio(Drive *dp, uchar *a, ulong len, ulong offset, int cmd) { ulong bn, n, o, m; Controller *cp; @@ -1681,7 +1710,10 @@ atapiio(Drive *dp, char *a, ulong len, ulong offset) cp = dp->cp; - buf = smalloc(Maxxfer); + if(cmd == Cread2) + buf = smalloc(Maxxfer); + else + buf = 0; qlock(cp->ctlrlock); retrycount = 2; retry: @@ -1695,12 +1727,16 @@ retry: } } cp->dp = 0; - free(buf); + if(cmd == Cread2) + free(buf); qunlock(cp->ctlrlock); nexterror(); } - cp->buf = buf; + if(cmd == Cread2) + cp->buf = buf; + else + cp->buf = a; cp->dp = dp; cp->len = dp->bytes; @@ -1714,7 +1750,7 @@ retry: if(m > n) m = n; memset(cp->cmdblk, 0, 12); - cp->cmdblk[0] = Cread2; + cp->cmdblk[0] = cmd; cp->cmdblk[2] = bn >> 24; cp->cmdblk[3] = bn >> 16; cp->cmdblk[4] = bn >> 8; @@ -1732,14 +1768,15 @@ retry: a += m; } poperror(); - free(buf); + if(cmd == Cread2) + free(buf); cp->dp = 0; qunlock(cp->ctlrlock); return len-n; } static long -atapirwio(Chan *c, char *a, ulong len, ulong offset) +atapirwio(Chan *c, uchar *a, ulong len, ulong offset, int cmd) { Drive *dp; ulong vers; @@ -1757,7 +1794,7 @@ atapirwio(Chan *c, char *a, ulong len, ulong offset) c->qid.vers = dp->vers; if(vers && vers != dp->vers) error(Eio); - rv = atapiio(dp, a, len, offset); + rv = atapiio(dp, a, len, offset, cmd); poperror(); qunlock(dp); @@ -1860,9 +1897,6 @@ atapiintr(Controller *cp) DPRINT("%s: atapiintr %uX\n", cp->dp->vol, cause); switch(cause){ - case 0: /* data out */ - cp->status |= Serr; - /*FALLTHROUGH*/ case 1: /* command */ if(cp->status & Serr){ cp->lastcmd = cp->cmd; @@ -1874,6 +1908,7 @@ atapiintr(Controller *cp) outss(pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); break; + case 0: /* data out */ case 2: /* data in */ addr = cp->buf; if(addr == 0){ @@ -1904,7 +1939,10 @@ atapiintr(Controller *cp) count = inb(pbase+Pcyllsb)|(inb(pbase+Pcylmsb)<<8); if (count > Maxxfer) count = Maxxfer; - inss(pbase+Pdata, addr, count/2); + if(cause == 0) + outss(pbase+Pdata, addr, count/2); + else + inss(pbase+Pdata, addr, count/2); cp->count = count; cp->lastcmd = cp->cmd; break;