## diffname alphapc/devfloppy.c 1999/0415 ## diff -e /dev/null /n/emeliedump/1999/0415/sys/src/brazil/alphapc/devfloppy.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "floppy.h" /* Intel 82077A (8272A compatible) floppy controller */ /* This module expects the following functions to be defined * elsewhere: * * inb() * outb() * floppyexec() * floppyeject() * floppysetup0() * floppysetup1() * dmainit() * dmasetup() * dmaend() * * On DMA systems, floppyexec() should be an empty function; * on non-DMA systems, dmaend() should be an empty function; * dmasetup() may enforce maximum transfer sizes. */ enum { /* file types */ Qdir= 0, Qdata= (1<<2), Qctl= (2<<2), Qmask= (3<<2), DMAchan= 2, /* floppy dma channel */ }; #define DPRINT if(floppydebug)print int floppydebug = 0; /* * types of drive (from PC equipment byte) */ enum { Tnone= 0, T360kb= 1, T1200kb= 2, T720kb= 3, T1440kb= 4, }; FType floppytype[] = { { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, }, { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, }, { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, }, { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, }, }; /* * 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[] = { [1] 0, [2] 1, [4] 2, [8] 3, }; static int c2b[] = { 128, 256, 512, 1024, }; FController fl; #define MOTORBIT(i) (1<<((i)+4)) /* * predeclared */ static int cmddone(void*); static void floppyformat(FDrive*, char*); static void floppykproc(void*); static void floppypos(FDrive*,long); static int floppyrecal(FDrive*); static int floppyresult(void); static void floppyrevive(void); static long floppyseek(FDrive*, long); static int floppysense(void); static void floppywait(void); static long floppyxfer(FDrive*, int, void*, long, long); Dirtab floppydir[]={ "fd0disk", {Qdata + 0}, 0, 0660, "fd0ctl", {Qctl + 0}, 0, 0660, "fd1disk", {Qdata + 1}, 0, 0660, "fd1ctl", {Qctl + 1}, 0, 0660, "fd2disk", {Qdata + 2}, 0, 0660, "fd2ctl", {Qctl + 2}, 0, 0660, "fd3disk", {Qdata + 3}, 0, 0660, "fd3ctl", {Qctl + 3}, 0, 0660, }; #define NFDIR 2 /* directory entries/drive */ static void fldump(void) { mb(); DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb), inb(Pdor), inb(Pmsr), inb(Pdir)); mb(); } /* * set floppy drive to its default type */ static void floppysetdef(FDrive *dp) { FType *t; for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++) if(dp->dt == t->dt){ dp->t = t; floppydir[NFDIR*dp->dev].length = dp->t->cap; break; } } static void floppyreset(void) { FDrive *dp; FType *t; ulong maxtsize; dmainit(DMAchan); floppysetup0(&fl); /* * init dependent parameters */ maxtsize = 0; for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ t->cap = t->bytes * t->heads * t->sectors * t->tracks; t->bcode = b2c[t->bytes/128]; t->tsize = t->bytes * t->sectors; if(maxtsize < t->tsize) maxtsize = t->tsize; } /* * allocate the drive storage */ fl.d = xalloc(fl.ndrive*sizeof(FDrive)); fl.selected = fl.d; /* * stop the motors */ fl.motor = 0; delay(10); mb(); outb(Pdor, fl.motor | Fintena | Fena); mb(); delay(10); /* * init drives */ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ dp->dev = dp - fl.d; dp->dt = T1440kb; floppysetdef(dp); dp->cyl = -1; /* because we don't know */ dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024); dp->ccyl = -1; dp->vers = 0; } /* * first operation will recalibrate */ fl.confused = 1; floppysetup1(&fl); } static Chan* floppyattach(char *spec) { static int kstarted; if(kstarted == 0){ /* * watchdog to turn off the motors */ kstarted = 1; kproc("floppy", floppykproc, 0); } return devattach('f', spec); } static int floppywalk(Chan *c, char *name) { return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen); } static void floppystat(Chan *c, char *dp) { devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen); } static Chan* floppyopen(Chan *c, int omode) { return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen); } static void floppyclose(Chan *) { } static void islegal(ulong offset, long n, FDrive *dp) { if(offset % dp->t->bytes) error(Ebadarg); if(n % dp->t->bytes) error(Ebadarg); } /* * check if the floppy has been replaced under foot. cause * an error if it has. * * a seek and a read clears the condition. this was determined * experimentally, there has to be a better way. * * if the read fails, cycle through the possible floppy * density till one works or we've cycled through all * possibilities for this drive. */ static void changed(Chan *c, FDrive *dp) { ulong old; FType *start; /* * if floppy has changed or first time through */ mb(); if((inb(Pdir)&Fchange) || dp->vers == 0){ mb(); DPRINT("changed\n"); fldump(); dp->vers++; floppysetdef(dp); start = dp->t; dp->confused = 1; /* make floppyon recal */ DPRINT("b4 floppyon:\n"); fldump(); floppyon(dp); DPRINT("after floppyon:\n"); fldump(); floppyseek(dp, dp->t->heads*dp->t->tsize); DPRINT("after floppyseek:\n"); fldump(); while(waserror()){ while(++dp->t){ if(dp->t == &floppytype[nelem(floppytype)]) dp->t = floppytype; if(dp->dt == dp->t->dt) break; } floppydir[NFDIR*dp->dev].length = dp->t->cap; floppyon(dp); DPRINT("changed: trying %s\n", dp->t->name); fldump(); if(dp->t == start) nexterror(); } floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); poperror(); } old = c->qid.vers; c->qid.vers = dp->vers; if(old && old != dp->vers) error(Eio); } static int readtrack(FDrive *dp, int cyl, int head) { int i, nn, sofar; ulong pos; nn = dp->t->tsize; if(dp->ccyl==cyl && dp->chead==head) return nn; pos = (cyl*dp->t->heads+head) * nn; for(sofar = 0; sofar < nn; sofar += i){ dp->ccyl = -1; i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar); if(i <= 0) return -1; } dp->ccyl = cyl; dp->chead = head; return nn; } static long floppyread(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv; int sec, head, cyl; long len; uchar *aa; ulong offset = off; if(c->qid.path == CHDIR) return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen); rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: islegal(offset, n, dp); aa = a; qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); for(rv = 0; rv < n; rv += len){ /* * all xfers come out of the track cache */ dp->len = n - rv; floppypos(dp, offset+rv); cyl = dp->tcyl; head = dp->thead; len = dp->len; sec = dp->tsec; if(readtrack(dp, cyl, head) < 0) break; memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); } qunlock(&fl); poperror(); break; case Qctl: return readstr(offset, a, n, dp->t->name); default: panic("floppyread: bad qid"); } return rv; } #define SNCMP(a, b) strncmp(a, b, sizeof(b)-1) static long floppywrite(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv, i; char *aa = a; char ctlmsg[64]; ulong offset = off; rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: islegal(offset, n, dp); qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); for(rv = 0; rv < n; rv += i){ floppypos(dp, offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); if(i < 0) break; if(i == 0) error(Eio); } qunlock(&fl); poperror(); break; case Qctl: rv = n; qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } if(n >= sizeof(ctlmsg)) n = sizeof(ctlmsg) - 1; memmove(ctlmsg, aa, n); ctlmsg[n] = 0; if(SNCMP(ctlmsg, "eject") == 0){ floppyeject(dp); } else if(SNCMP(ctlmsg, "reset") == 0){ fl.confused = 1; floppyon(dp); } else if(SNCMP(ctlmsg, "format") == 0){ floppyformat(dp, ctlmsg); } else if(SNCMP(ctlmsg, "debug") == 0){ floppydebug = 1; } else error(Ebadctl); poperror(); qunlock(&fl); break; default: panic("floppywrite: bad qid"); } return rv; } static void floppykproc(void *) { FDrive *dp; while(waserror()) ; for(;;){ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(&fl)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) floppyoff(dp); qunlock(&fl); } } tsleep(&fl.kr, return0, 0, 1000); } } /* * start a floppy drive's motor. */ static void floppyon(FDrive *dp) { int alreadyon; int tries; if(fl.confused) floppyrevive(); /* start motor and select drive */ alreadyon = fl.motor & MOTORBIT(dp->dev); fl.motor |= MOTORBIT(dp->dev); mb(); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); mb(); if(!alreadyon){ /* wait for drive to spin up */ tsleep(&dp->r, return0, 0, 750); /* clear any pending interrupts */ floppysense(); } /* set transfer rate */ if(fl.rate != dp->t->rate){ fl.rate = dp->t->rate; mb(); outb(Pdsr, fl.rate); mb(); } /* get drive to a known cylinder */ if(dp->confused) for(tries = 0; tries < 4; tries++) if(floppyrecal(dp) >= 0) break; dp->lasttouched = m->ticks; fl.selected = dp; } /* * stop the floppy if it hasn't been used in 5 seconds */ static void floppyoff(FDrive *dp) { fl.motor &= ~MOTORBIT(dp->dev); mb(); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); mb(); } /* * send a command to the floppy */ static int floppycmd(void) { int i; int tries; fl.nstat = 0; for(i = 0; i < fl.ncmd; i++){ for(tries = 0; ; tries++){ mb(); if((inb(Pmsr)&(Ffrom|Fready)) == Fready) break; mb(); if(tries > 1000){ DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i); fldump(); /* empty fifo, might have been a bad command */ floppyresult(); return -1; } microdelay(8); /* for machine independence */ } mb(); outb(Pfdata, fl.cmd[i]); mb(); } return 0; } /* * get a command result from the floppy * * when the controller goes ready waiting for a command * (instead of sending results), we're done * */ static int floppyresult(void) { int i, s; int tries; /* get the result of the operation */ for(i = 0; i < sizeof(fl.stat); i++){ /* wait for status byte */ for(tries = 0; ; tries++){ mb(); s = inb(Pmsr)&(Ffrom|Fready); mb(); if(s == Fready){ fl.nstat = i; return fl.nstat; } if(s == (Ffrom|Fready)) break; if(tries > 1000){ DPRINT("floppyresult: %d stats\n", i); fldump(); fl.confused = 1; return -1; } microdelay(8); /* for machine independence */ } mb(); fl.stat[i] = inb(Pfdata); mb(); // print("stat[%d]: %.2ux\n", i, fl.stat[i]); } fl.nstat = sizeof(fl.stat); return fl.nstat; } /* * calculate physical address of a logical byte offset into the disk * * truncate dp->length if it crosses a track boundary */ static void floppypos(FDrive *dp, long off) { int lsec; int ltrack; int end; lsec = off/dp->t->bytes; ltrack = lsec/dp->t->sectors; dp->tcyl = ltrack/dp->t->heads; dp->tsec = (lsec % dp->t->sectors) + 1; dp->thead = (lsec/dp->t->sectors) % dp->t->heads; /* * can't read across track boundaries. * if so, decrement the bytes to be read. */ end = (ltrack+1)*dp->t->sectors*dp->t->bytes; if(off+dp->len > end) dp->len = end - off; } /* * get the interrupt cause from the floppy. */ static int floppysense(void) { fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fsense; if(floppycmd() < 0) return -1; if(floppyresult() < 2){ DPRINT("can't read sense response\n"); fldump(); fl.confused = 1; return -1; } return 0; } static int cmddone(void *) { return fl.ncmd == 0; } /* * Wait for a floppy interrupt. If none occurs in 5 seconds, we * may have missed one. This only happens on some portables which * do power management behind our backs. Call the interrupt * routine to try to clear any conditions. */ static void floppywait(void) { tsleep(&fl.r, cmddone, 0, 5000); if(!cmddone(0)){ floppyintr(0); fl.confused = 1; } } /* * we've lost the floppy position, go to cylinder 0. */ static int floppyrecal(FDrive *dp) { dp->ccyl = -1; dp->cyl = -1; fl.ncmd = 0; fl.cmd[fl.ncmd++] = Frecal; fl.cmd[fl.ncmd++] = dp->dev; if(floppycmd() < 0) return -1; floppywait(); if(fl.nstat < 2){ mb(); DPRINT("recalibrate: confused %ux\n", inb(Pmsr)); mb(); fl.confused = 1; return -1; } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ DPRINT("recalibrate: failed\n"); dp->confused = 1; return -1; } dp->cyl = fl.stat[1]; if(dp->cyl != 0){ DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl); dp->cyl = -1; dp->confused = 1; return -1; } dp->confused = 0; return 0; } /* * if the controller or a specific drive is in a confused state, * reset it and get back to a kown state */ static void floppyrevive(void) { FDrive *dp; /* * reset the controller if it's confused */ if(fl.confused){ DPRINT("floppyrevive in\n"); fldump(); /* reset controller and turn all motors off */ splhi(); fl.ncmd = 1; fl.cmd[0] = 0; mb(); outb(Pdor, 0); mb(); delay(10); mb(); outb(Pdor, Fintena|Fena); mb(); delay(10); spllo(); fl.motor = 0; fl.confused = 0; floppywait(); /* mark all drives in an unknown state */ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++) dp->confused = 1; /* set rate to a known value */ mb(); outb(Pdsr, 0); mb(); fl.rate = 0; DPRINT("floppyrevive out\n"); fldump(); } } /* * seek to the target cylinder * * interrupt, no results */ static long floppyseek(FDrive *dp, long off) { floppypos(dp, off); if(dp->cyl == dp->tcyl) return dp->tcyl; dp->cyl = -1; fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fseek; fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps; if(floppycmd() < 0) return -1; floppywait(); if(fl.nstat < 2){ DPRINT("seek: confused\n"); fl.confused = 1; return -1; } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ DPRINT("seek: failed\n"); dp->confused = 1; return -1; } dp->cyl = dp->tcyl; return dp->tcyl; } /* * read or write to floppy. try up to three times. */ static long floppyxfer(FDrive *dp, int cmd, void *a, long off, long n) { long offset; int tries; if(off >= dp->t->cap) return 0; if(off + n > dp->t->cap) n = dp->t->cap - off; /* retry on error (until it gets ridiculous) */ tries = 0; while(waserror()){ if(tries++ > 20) nexterror(); DPRINT("floppyxfer: retrying\n"); /*floppyon(dp);*/ } dp->len = n; if(floppyseek(dp, off) < 0){ DPRINT("xfer: seek failed\n"); dp->confused = 1; error(Eio); } /* * set up the dma (dp->len may be trimmed) */ if(waserror()){ dmaend(DMAchan); nexterror(); } dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread); if(dp->len < 0) error(Eio); /* * start operation */ fl.ncmd = 0; fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0); fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; fl.cmd[fl.ncmd++] = dp->tcyl; fl.cmd[fl.ncmd++] = dp->thead; fl.cmd[fl.ncmd++] = dp->tsec; fl.cmd[fl.ncmd++] = dp->t->bcode; fl.cmd[fl.ncmd++] = dp->t->sectors; fl.cmd[fl.ncmd++] = dp->t->gpl; fl.cmd[fl.ncmd++] = 0xFF; if(floppycmd() < 0) error(Eio); /* Poll ready bits and transfer data */ floppyexec((char*)a, dp->len, cmd==Fread); /* * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); poperror(); /* * check for errors */ if(fl.nstat < 7){ DPRINT("xfer: confused\n"); fl.confused = 1; error(Eio); } if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0], fl.stat[1], fl.stat[2]); DPRINT("offset %lud len %ld\n", off, dp->len); if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){ DPRINT("DMA overrun: retry\n"); } else dp->confused = 1; error(Eio); } /* * check for correct cylinder */ offset = fl.stat[3] * dp->t->heads + fl.stat[4]; offset = offset*dp->t->sectors + fl.stat[5] - 1; offset = offset * c2b[fl.stat[6]]; if(offset != off+dp->len){ DPRINT("xfer: ends on wrong cyl\n"); dp->confused = 1; error(Eio); } poperror(); dp->lasttouched = m->ticks; return dp->len; } /* * format a track */ static void floppyformat(FDrive *dp, char *params) { int cyl, h, sec; ulong track; uchar *buf, *bp; FType *t; char *f[3]; /* * set the type */ if(parsefields(params, f, 3, " ") > 1){ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){ dp->t = t; floppydir[NFDIR*dp->dev].length = dp->t->cap; break; } } if(t >= &floppytype[nelem(floppytype)]) error(Ebadarg); } else { floppysetdef(dp); t = dp->t; } /* * buffer for per track info */ buf = smalloc(t->sectors*4); if(waserror()){ free(buf); nexterror(); } /* force a recalibrate to cylinder 0 */ dp->confused = 1; if(!waserror()){ floppyon(dp); poperror(); } /* * format a track at time */ for(track = 0; track < t->tracks*t->heads; track++){ cyl = track/t->heads; h = track % t->heads; /* * seek to track, ignore errors */ floppyseek(dp, track*t->tsize); dp->cyl = cyl; dp->confused = 0; /* * set up the dma (dp->len may be trimmed) */ bp = buf; for(sec = 1; sec <= t->sectors; sec++){ *bp++ = cyl; *bp++ = h; *bp++ = sec; *bp++ = t->bcode; } if(waserror()){ dmaend(DMAchan); nexterror(); } if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) error(Eio); /* * start operation */ fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fformat; fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; fl.cmd[fl.ncmd++] = t->bcode; fl.cmd[fl.ncmd++] = t->sectors; fl.cmd[fl.ncmd++] = t->fgpl; fl.cmd[fl.ncmd++] = 0x5a; if(floppycmd() < 0) error(Eio); /* Poll ready bits and transfer data */ floppyexec((char *)buf, bp-buf, 0); /* * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); poperror(); /* * check for errors */ if(fl.nstat < 7){ DPRINT("format: confused\n"); fl.confused = 1; error(Eio); } if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){ DPRINT("format: failed %ux %ux %ux\n", fl.stat[0], fl.stat[1], fl.stat[2]); dp->confused = 1; error(Eio); } } free(buf); dp->confused = 1; poperror(); } static void floppyintr(Ureg *) { switch(fl.cmd[0]&~Fmulti){ case Fread: case Fwrite: case Fformat: case Fdumpreg: floppyresult(); break; case Fseek: case Frecal: default: floppysense(); /* to clear interrupt */ break; } fl.ncmd = 0; wakeup(&fl.r); } Dev floppydevtab = { 'f', "floppy", floppyreset, devinit, floppyattach, devclone, floppywalk, floppystat, floppyopen, devcreate, floppyclose, floppyread, devbread, floppywrite, devbwrite, devremove, devwstat, }; . ## diffname alphapc/devfloppy.c 1999/0423 ## diff -e /n/emeliedump/1999/0415/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/1999/0423/sys/src/brazil/alphapc/devfloppy.c 752d 750d 738d 736d 734d 732d 691d 689d 598,599d 596d 581d 579d 557d 555d 544d 541d 526d 524d 505d 503d 491d 489d 285,286d 282,283d 279,280d 272d 270d 179d 177d 165a dmainit(DMAchan, maxtsize); . 149,150d 124d 121d ## diffname alphapc/devfloppy.c 1999/0501 ## diff -e /n/emeliedump/1999/0423/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/1999/0501/sys/src/brazil/alphapc/devfloppy.c 822a delay(10); print("msr 0x%2.2uX\n", inb(Pmsr)); . 777c if(tries++ > 2/*0*/) . 685c * reset it and get back to a known state . 682a static void specify(void) { fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fspec; fl.cmd[fl.ncmd++] = 0; fl.cmd[fl.ncmd++] = 1; if(floppycmd() < 0) return; floppywait(); fldump(); } . 639a t1 = fastticks(nil); print("wait %lld ticks\n", t1-t0); . 638a vlong t0, t1; t0 = fastticks(nil); . 535a microdelay(8); /* for machine independence */ . 64a */ . 58a /* . 42c int floppydebug = 1; . ## diffname alphapc/devfloppy.c 1999/0504 ## diff -e /n/emeliedump/1999/0501/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/1999/0504/sys/src/brazil/alphapc/devfloppy.c 844a xdmastatus(DMAchan); . ## diffname alphapc/devfloppy.c 1999/0506 ## diff -e /n/emeliedump/1999/0504/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/1999/0506/sys/src/brazil/alphapc/devfloppy.c 843,845d 797c if(tries++ > 20) . 690a dumpreg(void) { int i; fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fdumpreg; if(floppycmd() < 0) return; floppywait(); if(fl.nstat < 0){ print("dumpreg bad %d\n", fl.nstat); fldump(); return; } for(i = 0; i < fl.nstat; i++) print(" %2.2uX", fl.stat[i]); print("\n"); } static void . 645,646d 642,643d 538d 109c // "fd0disk", {Qdata + 0}, 0, 0660, "fd0disk", {Qdata + 0}, 0, 0666, . 42c int floppydebug = 0; . ## diffname alphapc/devfloppy.c 1999/0507 ## diff -e /n/emeliedump/1999/0506/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/1999/0507/sys/src/brazil/alphapc/devfloppy.c 808a if(cmd == Fread) memset(a, 0x55, n); . 66d 59d ## diffname alphapc/devfloppy.c 2000/0308 ## diff -e /n/emeliedump/1999/0507/sys/src/brazil/alphapc/devfloppy.c /n/emeliedump/2000/0308/sys/src/9/alphapc/devfloppy.c 914c if(getfields(params, f, 3, 1, " ") > 1){ . ## diffname alphapc/devfloppy.c 2001/0727 ## diff -e /n/emeliedump/2000/0308/sys/src/9/alphapc/devfloppy.c /n/emeliedump/2001/0727/sys/src/9/alphapc/devfloppy.c 1046d 918c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . 331,332c if(c->qid.type & QTDIR) return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen); . 283c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . 230c return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen); . 224c return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen); . 221,222c static int floppystat(Chan *c, uchar *dp, int n) . 218c return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen); . 215,216c static Walkqid* floppywalk(Chan *c, Chan *nc, char **name, int nname) . 137c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . 107c ".", {Qdir, 0, QTDIR}, 0, 0550, . ## diffname alphapc/devfloppy.c 2001/1117 ## diff -e /n/emeliedump/2001/0727/sys/src/9/alphapc/devfloppy.c /n/emeliedump/2001/1117/sys/src/9/alphapc/devfloppy.c 914c if(tokenize(params, f, 3) > 1){ . ## diffname alphapc/devfloppy.c 2001/1122 ## diff -e /n/emeliedump/2001/1117/sys/src/9/alphapc/devfloppy.c /n/emeliedump/2001/1122/sys/src/9/alphapc/devfloppy.c 995c floppywait(1); . 926a } else { cmderror(cb, "invalid floppy format command"); SET(t); . 924c } else if(cb->nf == 1){ . 916c if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){ . 914c if(cb->nf == 2){ . 909d 903c floppyformat(FDrive *dp, Cmdbuf *cb) . 859c floppywait(0); . 816d 813c if(tries++ >= dp->maxtries) . 807,808d 778c floppywait(1); . 744c floppywait(0); . 684,716d 661c floppywait(1); . 640c tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000); . 638c floppywait(int slow) . 499a /* return -1 if this didn't work */ if(dp->confused) return -1; return 0; . 466c static int . 433a poperror(); free(cb); . 430,431c break; } . 426,428c break; case CMdebug: . 423c break; case CMformat: floppyformat(dp, cb); break; case CMreset: . 417,421c ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); switch(ct->index){ case CMeject: . 411a cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } . 382c Cmdbuf *cb; Cmdtab *ct; . 375d 291a dp->maxtries = 20; . 289a /* if the read succeeds, we've got the density right */ . 284c /* floppyon will fail if there's a controller but no drive */ if(floppyon(dp) < 0) error(Eio); . 276a /* * if first attempt doesn't reset changed bit, there's * no floppy there */ if(inb(Pdir)&Fchange) nexterror(); . 274c if(floppyon(dp) < 0) error(Eio); /* seek to the first track */ . 272a dp->maxtries = 3; /* limit it when we're probing */ /* floppyon will fail if there's a controller but no drive */ . 271d 204a if(fl.ndrive == 0) error(Enodev); . 149a if(fl.ndrive == 0) return; . 118a enum { CMdebug, CMeject, CMformat, CMreset, }; static Cmdtab floppyctlmsg[] = { CMdebug, "debug", 1, CMeject, "eject", 1, CMformat, "format", 0, CMreset, "reset", 1, }; . 108c "fd0disk", {Qdata + 0}, 0, 0660, . 103c static void floppywait(int); . 95c static void floppyformat(FDrive*, Cmdbuf*); . ## diffname alphapc/devfloppy.c 2001/1211 ## diff -e /n/emeliedump/2001/1122/sys/src/9/alphapc/devfloppy.c /n/emeliedump/2001/1211/sys/src/9/alphapc/devfloppy.c 1,1076c #include "../pc/devfloppy.c" .