## diffname pc/devfloppy.c 1991/0727 ## diff -e /dev/null /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" typedef struct Drive Drive; typedef struct Controller Controller; typedef struct Type Type; enum { Fmotor= 0x3f2, /* motor port */ Fintena= 0x4, /* enable floppy interrupt */ Fena= 0x8, /* 0 == reset controller */ Fstatus= 0x3f4, /* controller main status port */ Fready= 0x80, /* ready to be touched */ Ffrom= 0x40, /* data from controller */ Fbusy= 0x10, /* operation not over */ Fdata= 0x3f5, /* controller data port */ Frecal= 0x7, /* recalibrate cmd */ Fseek= 0xf, /* seek cmd */ Fsense= 0x8, /* sense cmd */ Fread= 0x66, /* read cmd */ 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 */ /* sector size encodings */ S128= 0, S256= 1, S512= 2, S1024= 3, /* status 0 byte */ Drivemask= 3<<0, Seekend= 1<<5, Codemask= (3<<6)|(3<<3), }; /* * floppy types */ struct Type { char *name; int bytes; /* bytes/sector */ int sectors; /* sectors/track */ int heads; /* number of heads */ int steps; /* steps per cylinder */ int tracks; /* tracks/disk */ int gpl; /* intersector gap length for read/write */ int fgpl; /* intersector gap length for format */ long cap; /* drive capacity in bytes */ }; Type floppytype[] = { { "MF2HD", S512, 18, 2, 1, 80, 0x1B, 0x54, 512*2*18*80 }, { "MF2DD", S512, 9, 2, 1, 80, 0x1B, 0x54, 512*2*9*80 }, { "F2HD", S512, 15, 2, 1, 80, 0x2A, 0x50, 512*15*2*80 }, { "F2DD", S512, 8, 2, 1, 40, 0x2A, 0x50, 512*8*2*40 }, { "F1DD", S512, 8, 1, 1, 40, 0x2A, 0x50, 512*8*1*40 }, }; static int secbytes[] = { 128, 256, 512, 1024 }; /* * a floppy drive */ struct Drive { QLock; Type *t; int dev; 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 */ int thead; /* target head */ int tsec; /* target sector */ long len; int busy; /* true if drive is seeking */ Rendez r; /* waiting for operation termination */ }; /* * NEC PD765A controller for 4 floppys */ struct Controller { QLock; Drive d[Nfloppy]; /* the floppy drives */ int busy; /* true if a read or write in progress */ uchar stat[8]; /* status of an operation */ int confused; }; Controller floppy[1]; /* * start a floppy drive's motor. set an alarm for 1 second later to * mark it as started (we get no interrupt to tell us). * * assume the caller qlocked the drive. */ void floppystart(Drive *dp) { int cmd; dp->lasttouched = m->ticks; if(dp->motoron) return; cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev; outb(Fmotor, cmd); dp->busy = 1; tsleep(&dp->r, noreturn, 0, 1000); dp->motoron = 1; dp->busy = 0; dp->lasttouched = m->ticks; } /* * stop the floppy if it hasn't been used in 5 seconds */ void floppystop(Drive *dp) { int cmd; if(!canqlock(dp)) return; cmd = Fintena | Fena | dp->dev; outb(Fmotor, cmd); dp->motoron = 0; } void 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) floppystop(dp); } alarm(5*1000, floppyalarm, 0); cancel(a); } int floppysend(int data) { int tries; uchar c; for(tries = 0; tries < 100; tries++){ /* * see if its ready for data */ c = inb(Fstatus); if((c&(Ffrom|Fready)) != Fready) continue; /* * send the data */ outb(Fdata, data); return 0; } return -1; } int floppyrcv(void) { int tries; uchar c; for(tries = 0; tries < 100; tries++){ /* * see if its ready for data */ c = inb(Fstatus); if((c&(Ffrom|Fready)) != (Ffrom|Fready)) continue; /* * get data */ return inb(Fdata)&0xff; } return -1; } int floppyrdstat(int n) { int i; int c; for(i = 0; i < n; i++){ c = floppyrcv(); if(c < 0) return -1; floppy.stat[i] = c; } return 0; } void floppypos(Drive *dp, long off) { int lsec; int end; int cyl; lsec = off/secbytes[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; /* * can't read across cylinder boundaries. * if so, decrement the bytes to be read. */ lsec = (off+dp->len)/secbytes[dp->t->bytes]; cyl = lsec/(dp->t->sectors*dp->t->heads); if(cyl != dp->tcyl){ dp->len -= (lsec % dp->t->sectors)*secbytes[dp->t->bytes]; dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes] *dp->t->sectors; } dp->lasttouched = m->ticks; floppy.intr = 0; } void floppywait(void) { int tries; for(tries = 0; tries < 100 && floppy.intr == 0; tries++) delay(5); if(tries >= 100) print("tired floopy\n"); floppy.intr = 0; } int floppysense(Drive *dp) { /* * ask for floppy status */ if(floppysend(Fsense) < 0){ floppy.confused = 1; return -1; } if(floppyrdstat(2) < 0){ floppy.confused = 1; dp->confused = 1; return -1; } /* * make sure it's the right drive */ if((floppy.stat[0] & Drivemask) != dp-floppy.d){ print("sense failed\n"); dp->confused = 1; return -1; } return 0; } int floppyrecal(Drive *dp) { floppy.intr = 0; if(floppysend(Frecal) < 0 || floppysend(dp - floppy.d) < 0){ floppy.confused = 0; return -1; } floppywait(); /* * get return values */ if(floppysense(dp) < 0) return -1; /* * see if it worked */ if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){ print("recalibrate failed\n"); dp->confused = 1; return -1; } /* * see what cylinder we got to */ dp->tcyl = 0; dp->cyl = floppy.stat[1]/dp->t->steps; if(dp->cyl != dp->tcyl){ print("recalibrate went to wrong cylinder %d\n", dp->cyl); dp->confused = 1; return -1; } dp->confused = 0; return 0; } void floppyinit(void) { Drive *dp; for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ dp->t = &floppytype[0]; dp->cyl = -1; dp->motoron = 1; floppystop(dp); } setvec(22, floppyintr); alarm(5*1000, floppyalarm, (void *)0); } void floppyreset(void) { Drive *dp; /* * reset the floppy if'n it's confused */ if(floppy.confused){ /* reset controller and turn all motors off */ floppy.intr = 0; splhi(); outb(Fmotor, 0); delay(1); outb(Fmotor, Fintena|Fena); spllo(); for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ dp->motoron = 0; dp->confused = 1; } floppywait(); floppy.confused = 0; } /* * recalibrate any confused drives */ for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Nfloppy]; dp++){ if(dp->confused == 0) floppyrecal(dp); } } long floppyseek(int dev, long off) { Drive *dp; dp = &floppy.d[dev]; if(floppy.confused || dp->confused) floppyreset(); floppystart(dp); floppypos(dp, off); if(dp->cyl == dp->tcyl){ dp->offset = off; return off; } /* * tell floppy to seek */ if(floppysend(Fseek) < 0 || floppysend((dp->thead<<2) | dev) < 0 || floppysend(dp->tcyl * dp->t->steps) < 0){ print("seek cmd failed\n"); floppy.confused = 1; return -1; } /* * wait for interrupt */ floppywait(); /* * get floppy status */ if(floppysense(dp) < 0) return -1; /* * see if it worked */ if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){ print("seek failed\n"); dp->confused = 1; return -1; } /* * see what cylinder we got to */ dp->cyl = floppy.stat[1]/dp->t->steps; if(dp->cyl != dp->tcyl){ print("seek went to wrong cylinder %d instead of %d\n", dp->cyl, dp->tcyl); dp->confused = 1; return -1; } dp->offset = off; return dp->offset; } long floppyxfer(Drive *dp, int cmd, void *a, long n) { int dev; ulong addr; long offset; addr = (ulong)a; dev = dp - floppy.d; /* * dma can't cross 64 k boundaries */ if((addr & 0xffff0000) != ((addr+n) & 0xffff0000)) n -= (addr+n)&0xffff; dp->len = n; floppyseek(dev, dp->offset); /* print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", dp->tcyl, dp->thead, dp->tsec, addr, n);/**/ /* * set up the dma */ outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a); outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a); outb(DMAaddr, addr); outb(DMAaddr, addr>>8); outb(DMAtop, addr>>16); outb(DMAcount, n-1); outb(DMAcount, (n-1)>>8); outb(DMAinit, 2); /* * tell floppy to go */ cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); if(floppysend(cmd) < 0 || floppysend((dp->thead<<2) | dev) < 0 || floppysend(dp->tcyl * dp->t->steps) < 0 || floppysend(dp->thead) < 0 || floppysend(dp->tsec) < 0 || floppysend(dp->t->bytes) < 0 || floppysend(dp->t->sectors) < 0 || floppysend(dp->t->gpl) < 0 || floppysend(0xFF) < 0){ print("xfer cmd failed\n"); floppy.confused = 1; return -1; } floppywait(); /* * get status */ if(floppyrdstat(7) < 0){ print("xfer status failed\n"); floppy.confused = 1; return -1; } if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){ print("xfer failed %lux %lux %lux\n", floppy.stat[0], floppy.stat[1], floppy.stat[2]); dp->confused = 1; return -1; } offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4]; offset = offset*dp->t->sectors + floppy.stat[5] - 1; offset = offset * secbytes[floppy.stat[6]]; if(offset != dp->offset+n){ print("new offset %d instead of %d\n", offset, dp->offset+dp->len); dp->confused = 1; return -1;/**/ } dp->offset += dp->len; return dp->len; } long floppyread(int dev, void *a, long n) { Drive *dp; long rv, i; uchar *aa = a; dp = &floppy.d[dev]; for(rv = 0; rv < n; rv += i){ i = floppyxfer(dp, Fread, aa+rv, n-rv); if(i <= 0) break; } return rv; } void floppyintr(Ureg *ur) { floppy.intr = 1; } . ## diffname pc/devfloppy.c 1991/0728 ## diff -e /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c 354,355c } void floppyinit(void) { kproc(floppykproc, 0); . 351a dp->cyl = -1; . 349,350c dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ . 344c floppyreset(void) . 170,172d 168a qunlock(dp); } . 167c if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(dp)){ . 165d 154,155d 120c Controller floppy; . 50a /* file types */ Qdir= 0, Qdata= 16, Qstruct= 32, . 40a DMAchan= 2, /* floppy dma channel */ . 32,38d ## diffname pc/devfloppy.c 1991/0729 ## diff -e /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c 166c if(TK2SEC(m->ticks - dp->lasttouched) > 5) floppystop(dp); . ## diffname pc/devfloppy.c 1991/0730 ## diff -e /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c 256,270d ## diffname pc/devfloppy.c 1991/0731 ## diff -e /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c 546a wakeup(&floppy.r); . 527,543c static void . 522a qunlock(&floppy); qunlock(dp); poperror(); . 520c errors("floppy drive lost"); . 518c print("new offset %d instead of %d\n", offset, dp->offset+dp->len); . 516c offset = offset * c2b[floppy.stat[6]]; . 511c errors("floppy drive lost"); . 504c errors("floppy result failed"); . 501,502c if(floppyresult(7) < 0){ print("xfer status failed\n"); . 496c sleep(&floppy.r, interrupted, 0); . 493c errors("floppy command failed"); . 487c || floppysend(dp->t->bcode) < 0 . 479c * start operation . 469,476c dp->len = dmasetup(2, a, dp->len, cmd==Fread); . 467c * set up the dma (dp->len may be trimmed) . 463c print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", . 461c floppypos(dp); if(floppyseek(dp) < 0) errors("seeking floppy"); . 459a /* * calculate new position and seek to it (dp->len may be trimmed) */ . 457,458c if(floppy.confused || dp->confused) floppyrevive(); if(!dp->motoron) motoron(dp); . 455c * get floppy reset and spinning . 453a qlock(&floppy); qlock(dp); if(waserror){ qunlock(&floppy); qunlock(dp); } . 452d 447d 444c static long . 413c sleep(&floppy.r, interrupted, 0); . 403c || floppysend((dp->thead<<2) | dp->dev) < 0 . 384,393d 381,382c static long floppyseek(Drive *dp) . 373c for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Ndrive]; dp++){ . 366c sleep(&floppy.r, interrupted, 0); . 362c for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ . 352c * reset the floppy if it's confused . 331,350d 327c floppyrevive(void) . 325a /* * if the controller or a specific drive is in a confused state, * reset it and get back to a kown state */ . 294c sleep(&floppy.r, interrupted, 0); . 285c /* * return true if interrupt occurred */ static int interrupted(void *a) { return floppy.intr; } /* * we've lost the floppy position, go to cylinder 0. */ static int . 268c if(floppyresult(2) < 0){ . 258c /* * get the interrupt cause from the floppy. we need to do this * after seeks and recalibrations since they don't return results. */ static int . 252,253c dp->len -= (lsec % dp->t->sectors)*dp->t->bytes; dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes . 249c lsec = (dp->off+dp->len)/dp->t->bytes; . 240c lsec = dp->off/dp->t->bytes; . 233,234c /* * calculate physical address of a logical byte offset into the disk * * truncate dp->length if it crosses a cylinder boundary */ static void floppypos(Drive *dp) . 218,219c /* * read a command result message from the floppy */ static int floppyresult(int n) . 196c /* * get a byte from the floppy */ static int . 173c /* * send a byte to the floppy */ static int . 167c motoroff(dp); . 163c for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ . 158,159c static void floppykproc(void *a) . 149,150c static void motoroff(Drive *dp) . 133,136d 128,129c static void motoron(Drive *dp) . 122a * predeclared */ static void motoron(Drive*); static void motoroff(Drive*); static void floppykproc(void*); static int floppysend(int); static int floppyrcv(void); static int floppyresult(int); static void floppypos(Drive*); 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 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; } void floppyreset(void) { Drive *dp; for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ dp->motoron = 1; dp->cyl = -1; motoroff(dp); } setvec(Floppyvec, floppyintr); } 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); } long floppyread(Chan *c, void *a, long n) { Drive *dp; 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; } return rv; } long floppywrite(Chan *c, void *a, long n) { Drive *dp; 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; } return rv; } /* . 117a int intr; /* true if interrupt occured */ Rendez r; /* wait here for command termination */ . 113,114c QLock; /* exclusive access to the contoller */ Drive d[Ndrive]; /* the floppy drives */ . 105c Rendez r; /* waiting here for motor to spin up */ . 102c long len; /* size of xfer */ . 89c QLock; /* exclusive access to the drive */ . 81c 1024, . 77a [1] 0, [2] 1, [4] 2, [8] 3, }; static int c2b[] = { . 76c #define NTYPES (sizeof(floppytype)/sizeof(Type)) /* * bytes/sector encoding for the controller, index is (bytes per sector/128) */ static int b2c[] = . 70,74c { "MF2HD", 512, 18, 2, 1, 80, 0x1B, 0x54, }, { "MF2DD", 512, 9, 2, 1, 80, 0x1B, 0x54, }, { "F2HD", 512, 15, 2, 1, 80, 0x2A, 0x50, }, { "F2DD", 512, 8, 2, 2, 40, 0x2A, 0x50, }, { "F1DD", 512, 8, 1, 2, 40, 0x2A, 0x50, }, . 65c int fgpl; /* intersector gap length for format */ /* * these depend on previous entries and are set filled in * by floppyinit */ int bcode; /* coded version of bytes for the controller */ . 49,50c Qdata= 1, Qstruct= 2, . 32c Ndrive= 4, /* floppies/controller */ . ## diffname pc/devfloppy.c 1991/0802 ## diff -e /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c 658d 653a dp->lasttouched = m->ticks; . 648,649c if(offset != off+dp->len){ print("new offset %d instead of %d\n", offset, off+dp->len); . 626d 614c || floppysend((dp->thead<<2) | dp->dev) < 0 . 611a floppy.intr = 0; . 597c floppypos(dp, off); . 580c if(waserror()){ . 571c floppyxfer(Drive *dp, int cmd, void *a, long off, long n) . 566,567c return dp->cyl; . 535,538d 527a floppy.intr = 0; dp->cyl = -1; /* once the seek starts it could end anywhere */ . 520,523c if(dp->cyl == dp->tcyl) return dp->cyl; . 417c if((floppy.stat[0] & Drivemask) != dp->dev){ . 385c lsec = (off+dp->len)/dp->t->bytes; . 376c lsec = off/dp->t->bytes; . 370c floppypos(Drive *dp, long off) . 291a tsleep(&floppy.kr, return0, 0, 5*1000); . 285,290c 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); } . 264d 261,262c tsleep(&dp->r, return0, 0, 750); . 249c * start a floppy drive's motor. set an alarm for .75 second later to . 239,243c 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"); . 223,227c 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"); . 215a 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; } . 214c kproc("floppy", floppykproc, 0); . 204,211d 201,202d 192c dp->cyl = -1; /* because we don't know */ . 190a floppydir[2*dp->dev].length = dp->t->cap; . 187a /* * 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 */ . 186a Type *t; . 168,182d 162,166c 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)) . 159c static long floppyxfer(Drive*, int, void*, long, long); . 153c static void floppypos(Drive*,long); . 139a Rendez kr; /* for motor watcher */ . 135d 123d 115d 85c * bytes per sector encoding for the controller. * - index for b2c is is (bytes per sector/128). * - index for c2b is code from b2c . 49,50c Qdata= (1<<2), Qstruct= (2<<2), Qmask= (3<<2), . 11c typedef struct Type Type; . 9c typedef struct Drive Drive; . 7c #include "errno.h" . ## diffname pc/devfloppy.c 1991/0803 ## diff -e /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c 381a . 380a disp++; if(owl(disp&1) < 0) print("owl failed\n"); if(mail((disp>>1)&1) < 0) print("mail failed\n"); . 369a int disp = 0; . ## diffname pc/devfloppy.c 1991/0806 ## diff -e /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c 756a print("floppy intr\n"); . ## diffname pc/devfloppy.c 1991/0809 ## diff -e /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c 606c for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[conf.nfloppy]; dp++){ . 595c for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ . 385,386d 374c for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ . 289,292c if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) errors("bad len"); nn = dp->t->bytes * dp->t->sectors * dp->t->heads; for(rv = 0; rv < n; rv += len){ /* * truncate xfer at cylinder boundary */ dp->len = n - rv; floppypos(dp, c->offset+rv); cyl = dp->tcyl; len = dp->len; sec = dp->tsec + dp->thead * dp->t->sectors; /* * read the cylinder */ if(dp->ccyl != cyl){ dp->ccyl = -1; if(floppyxfer(dp, Fread, dp->ccache, cyl * nn, nn) != nn) errors("floppy read err"); dp->ccyl = cyl; } memmove(aa+rv, dp->ccache + (sec-1)*dp->t->bytes, len); . 279c long rv, nn, len, cyl; int sec; . 274a /* * the floppy is so slow, we always read a cylinder * at a time and cache the extra bytes. */ . 200a /* * allocate cylinder caches that don't cross 64k boundaries */ for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ do { dp->ccache = ialloc(dp->t->cap, 1); } while(k64(dp->ccache) != k64(dp->ccache+dp->t->cap)); dp->ccyl = -1; } . 193c for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ . 190a * allocate the drive storage */ floppy.d = ialloc(conf.nfloppy*sizeof(Drive), 0); /* . 175a #define k64(x) (((ulong)(x))>>16) . 135c Drive *d; /* the floppy drives */ . 125a uchar *ccache; /* cylinder cache (always read a whole cyl) */ int ccyl; /* number of cached cylinder */ . 32,33d ## diffname pc/devfloppy.c 1991/0810 ## diff -e /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c 214,215c n = 512 * 18 * 2; /* MF2HD cylinder size */ dp->ccache = ialloc(n, 1); } while(k64(dp->ccache) != k64(dp->ccache+n)); . 182a int n; . ## diffname pc/devfloppy.c 1991/0811 ## diff -e /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c 307c return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen); . 259c return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); . 253c devstat(c, dp, floppydir, conf.nfloppy*NFDIR, devgen); . 247c return devwalk(c, name, floppydir, conf.nfloppy*NFDIR, devgen); . 204c floppydir[NFDIR*dp->dev].length = dp->t->cap; . 175c #define NFDIR 2 /* directory entries/drive */ . ## diffname pc/devfloppy.c 1991/0823 ## diff -e /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c 800c /*print("floppy intr\n");/**/ . 736c /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", . 372,374d 340,348d 166,173c "fd0disk", {Qdata + 0}, 0, 0600, "fd1disk", {Qdata + 1}, 0, 0600, "fd2disk", {Qdata + 2}, 0, 0600, "fd3disk", {Qdata + 3}, 0, 0600, . 48d 34,39d ## diffname pc/devfloppy.c 1991/0831 ## diff -e /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c 345a floppychanged(dp); dp->ccyl = -1; . 301a floppychanged(dp); . 283a * look for a floppy change */ void floppychange(Drive *dp) { if((inb(Fchanged) & Fchange) == 0) return; } /* . 31a Fchanged= 0x3F7, /* disk changed register */ Fchange= 0x80, /* disk has changed */ . 29c Fwrite= 0x45, /* write cmd */ . ## diffname pc/devfloppy.c 1991/0902 ## diff -e /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c 290c floppychanged(Drive *dp) . ## diffname pc/devfloppy.c 1991/0906 ## diff -e /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c 732c dp->tcyl, dp->thead, dp->tsec, a, n);/**/ . 730a . 706,707d 703d ## diffname pc/devfloppy.c 1991/0913 ## diff -e /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c 423,424d ## diffname pc/devfloppy.c 1991/0919 ## diff -e /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c 412c while(waserror()) ; . ## diffname pc/devfloppy.c 1991/0920 ## diff -e /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c 295c print("floppy has changed\n"); . 277,285d 226a static int kstarted; if(kstarted == 0){ /* * watchdog to turn off the motors */ kstarted = 1; kproc("floppy", floppykproc, 0); } . 218,221d 165a "fd3ctl", {Qctl + 3}, 0, 0600, . 164a "fd2ctl", {Qctl + 2}, 0, 0600, . 163a "fd1ctl", {Qctl + 1}, 0, 0600, . 162a "fd0ctl", {Qctl + 0}, 0, 0600, . 44a Qctl= (2<<2), . 8a /* NEC PD765A (8272A compatible) floppy controller */ . ## diffname pc/devfloppy.c 1991/0921 ## diff -e /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c 719,720c motoron(dp); . 638a floppy.motor = 0; . 636d 432a * 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. * * this also selects the drive for subsequent operations */ static void motoron(Drive *dp) { int alreadyon; alreadyon = floppy.motor & MOTORBIT(dp->dev); floppy.motor |= MOTORBIT(dp->dev); driveselect(dp); if(!alreadyon) tsleep(&dp->r, return0, 0, 750); dp->lasttouched = m->ticks; } /* * stop the floppy if it hasn't been used in 5 seconds */ static void motoroff(Drive *dp) { floppy.motor &= ~MOTORBIT(dp->dev); driveselect(dp); } /* . 431a static void driveselect(Drive *dp) { int cmd; cmd = floppy.motor | Fintena | Fena | dp->dev; outb(Fmotor, cmd); } . 419c if((floppy.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5 . 386,409d 379,384d 204c floppy.motor |= MOTORBIT(dp->dev); . 145a #define MOTORBIT(i) (1<<((i)+4)) . 139a int motor; . 113d ## diffname pc/devfloppy.c 1991/0924 ## diff -e /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c 807,809c switch(fl.cmd[0]&~Fmulti){ case Fread: case Fwrite: floppyresult(); break; case Freadid: floppyresult(); break; case Fseek: case Frecal: default: floppysense(); /* to clear interrupt */ break; } fl.ncmd = 0; wakeup(&fl.r); . 804,805c void floppyintr(void) . 797c qunlock(&fl); . 791c print("new offset %d instead of %d\n", offset, off+dp->len); . 787,789c /* * check for correct cylinder */ offset = (fl.stat[3]/dp->t->steps) * dp->t->heads + fl.stat[4]; offset = offset*dp->t->sectors + fl.stat[5] - 1; offset = offset * c2b[fl.stat[6]]; . 779,784c if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ if(fl.stat[1] != 0x80){ print("xfer failed %lux %lux %lux\n", fl.stat[0], fl.stat[1], fl.stat[2]); print("offset %lud len %d\n", off, dp->len); dp->confused = 1; errors("floppy drive lost"); } else fl.stat[5]++; . 772,776c * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); /* * check for errors */ if(fl.nstat < 7){ print("xfer result failed %lux\n", inb(Pmsr)); fl.confused = 1; . 769d 766d 754,764c /* cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/ fl.ncmd = 0; fl.cmd[fl.ncmd++] = cmd; fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps; fl.cmd[fl.ncmd++] = dp->thead; fl.cmd[fl.ncmd++] = dp->tsec; fl.cmd[fl.ncmd++] = dp->t->bcode; fl.cmd[fl.ncmd++] = dp->tsec + dp->len/dp->t->bytes - 1; fl.cmd[fl.ncmd++] = dp->t->gpl; fl.cmd[fl.ncmd++] = 0xFF; if(floppycmd() < 0){ spllo(); . 749c dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread); . 744c dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/ . 741d 738,739c if(floppyseek(dp, off) < 0) . 728,734d 724a fl.confused = 1; nexterror(); . 723c dmaend(DMAchan); qunlock(&fl); . 720c if(off >= dp->t->cap) return 0; if(off + n > dp->t->cap) n = dp->t->cap - off; qlock(&fl); . 718a ulong up; . 702,711c dp->cyl = dp->tcyl; . 692,696c } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ . 685,690c floppywait(); if(fl.nstat < 2){ fl.confused = 1; . 682d 673,680c /* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/ 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){ . 669a floppyon(dp); floppypos(dp, off); . 668c floppyseek(Drive *dp, long off) . 666a /* * seek to the target cylinder * * interrupt, no results */ . 655,664d 650,653c fl.motor = 0; floppywait(); fl.confused = 0; /* devp->dsr = 0; devp->ccr = 0; /**/ . 648c for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++) . 646c outb(Pdor, Fintena|Fena); . 644c fl.cmd[0] = 0; outb(Pdor, 0); . 642d 640c if(fl.confused){ . 638c * reset the controller if it's confused . 612,618c dp->cyl = fl.stat[1]/dp->t->steps; if(dp->cyl != 0){ . 604,608c fl.ncmd = 0; fl.cmd[fl.ncmd++] = Frecal; fl.cmd[fl.ncmd++] = dp->dev; if(floppycmd() < 0) return -1; floppywait(); if(fl.nstat < 2){ fl.confused = 1; return -1; } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ . 598,602c dp->ccyl = -1; . 590,596c int type; . 581c tsleep(&fl.r, cmddone, 0, 2000); . 578,579c static void floppywait(void) . 576c * wait for a floppy interrupt . 574a static int cmddone(void *a) { return fl.ncmd == 0; } . 563,571d 557,560c if(floppyresult() < 2){ print("can't read sense response\n"); fl.confused = 1; . 551,555c fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fsense; if(floppycmd() < 0) . 549c floppysense(void) . 545,546c * get the interrupt cause from the floppy. . 535,541c end = (ltrack+1)*dp->t->sectors*dp->t->bytes; if(off+dp->len > end) dp->len = end - off; . 532c * can't read across track boundaries. . 527c ltrack = lsec/dp->t->sectors; dp->tcyl = ltrack/dp->t->heads; . 524a int track; . 522a int ltrack; . 517c * truncate dp->length if it crosses a track boundary . 511c fl.nstat = i; return i; . 505,509c for(i = 0; i < sizeof(fl.stat); i++){ for(tries = 0; ; tries++){ if(tries > 1000){ fl.confused = 1; return -1; } s = inb(Pmsr)&(Ffrom|Fready); if(s == Fready){ fl.nstat = i; return i; } if(s == (Ffrom|Fready)) break; } fl.stat[i] = inb(Pdata); . 502,503c int i, s; int tries; . 500c floppyresult(void) . 497c * get a command result from the floppy * * when the controller goes ready waiting for a command * (instead of sending results), we're done * . 493c return 0; . 480,491c for(i = 0; i < fl.ncmd; i++){ for(tries = 0; ; tries++){ if(tries > 1000){ print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr)); fl.confused = 1; return -1; } if((inb(Pmsr)&(Ffrom|Fready)) == Fready) break; } outb(Pdata, fl.cmd[i]); . 478d 476a int i; . 475c floppycmd(void) . 472c * send a command to the floppy . 451,468c floppyon(dp); floppyoff(dp); . 448,449c static void floppyeject(Drive *dp) . 446c * eject disk ( unknown on safari ) . 441,442c fl.motor &= ~MOTORBIT(dp->dev); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); . 439c floppyoff(Drive *dp) . 431a /* get drive to a known cylinder */ if(dp->confused) for(tries = 0; tries < 4; tries++) if(floppyrecal(dp) >= 0) break; . 427,429c if(fl.confused) floppyrevive(); /* start motor and select drive */ alreadyon = fl.motor & MOTORBIT(dp->dev); fl.motor |= MOTORBIT(dp->dev); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); . 425a int tries; . 423c floppyon(Drive *dp) . 415,420c * start a floppy drive's motor. . 405,413d 399,401c tsleep(&fl.kr, return0, 0, 5*100); . 395c floppyoff(dp); . 390,391c i = inb(Pdir) & 0x80; if(i != last) print("fromn %d to %d\n", last, i); last = i; for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ if((fl.motor&MOTORBIT(dp->dev)) . 385c int i; static int last; . 377a . 374a case Qctl: if(SNCMP(aa, "eject") == 0){ floppyeject(dp); } else if(SNCMP(aa, "seek") == 0){ aa += 5; floppyseek(dp, strtoul(aa, 0, 0)); } else if(SNCMP(aa, "den") == 0){ aa += 4; i = strtoul(aa, 0, 0); USED(i); /* devp->dsr = i; devp->ccr = i;/**/ } else if(SNCMP(aa, "reset") == 0){ floppyon(dp); } break; . 370c floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv); . 367,368c if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) errors("bad len"); . 364c dp = &fl.d[c->qid.path & ~Qmask]; . 361c char *aa = a; int dev; . 355a #define SNCMP(a, b) strncmp(a, b, sizeof(b)-1) . 352a . 349a case Qctl: break; . 347c memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); . 345a dp->chead = head; . 344a } . 343c i = floppyxfer(dp, Fread, dp->cache, (cyl*dp->t->heads+head)*nn, nn); if(i != nn){ if(i == 0) break; . 341c if(dp->ccyl!=cyl || dp->chead!=head){ . 339c * read the track . 336c sec = dp->tsec; . 334a head = dp->thead; . 330c * truncate xfer at track boundary . 327c aa = a; nn = dp->t->tsize; . 322d 319c dp = &fl.d[c->qid.path & ~Qmask]; . 311,313c long rv, i; int nn, sec, head, cyl; long len; long noff; uchar *aa; . 291,306d 214,221c fl.confused = 1; . 212c * first operation will recalibrate . 208c dp->cache = (uchar*)ialloc(dp->t->tsize, 1); dp->ccyl = -1; . 206d 202,203c fl.motor = 0; delay(10); outb(Pdor, fl.motor | Fintena | Fena); delay(10); /* * init drives */ for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ dp->dev = dp - fl.d; . 197c fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0); . 191a t->tsize = t->bytes * t->sectors; . 184a ulong p; long l; . 178d 164c static int cmddone(void*); void Xdelay(int); . 162c static long floppyseek(Drive*, long); static int floppysense(void); static void floppywait(void); . 160a static int floppyresult(void); . 158,159d 154,156c static void floppyon(Drive*); static void floppyoff(Drive*); . 151,152c static int floppycmd(void); static void floppyeject(Drive*); . 144c Controller fl; . 139,140c int motor; /* bit mask of spinning disks */ . 135,137c uchar cmd[14]; /* command */ int ncmd; /* # command bytes */ uchar stat[14]; /* command status */ int nstat; /* # status bytes */ int confused; /* controler needs to be reset */ . 128c * controller for 4 floppys . 123,124c Rendez r; /* waiting here for motor to spin up */ . 121c uchar *cache; /* track cache */ int ccyl; int chead; . 114c int confused; /* needs to be recalibrated */ . 75c { "MF1DD", 512, 9, 2, 1, 80, 0x1B, 0x54, }, { "MF4HD", 1024, 18, 2, 1, 80, 0x1B, 0x54, }, . 70a long tsize; /* track size in bytes */ . 48a DMAchan= 2, /* floppy dma channel */ . 37,38d 34,35c /* digital input register */ Pdir= 0x3F7, /* disk changed port */ Fchange= 0x80, /* disk has changed */ . 26,32c /* data register */ Pdata= 0x3f5, Frecal= 0x07, /* recalibrate cmd */ Fseek= 0x0f, /* seek cmd */ Fsense= 0x08, /* sense cmd */ Fread= 0x66, /* read cmd */ Freadid= 0x4a, /* read track id */ Fspec= 0x03, /* set hold times */ Fwrite= 0x45, /* write cmd */ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ Fdumpreg= 0x0e, /* dump internal registers */ . 21,24c /* main status register */ Pmsr= 0x3f4, Fready= 0x80, /* ready to be touched */ Ffrom= 0x40, /* data from controller */ Fbusy= 0x10, /* operation not over */ . 17,19c /* digital output register */ Pdor= 0x3f2, Fintena= 0x8, /* enable floppy interrupt */ Fena= 0x4, /* 0 == reset controller */ . 14a /* bits in the registers */ . 9c /* Intel 82077A (8272A compatible) floppy controller */ . ## diffname pc/devfloppy.c 1991/0925 ## diff -e /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c 816,817c static void floppyintr(Ureg *ur) . 809,812d 803a print(" %d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]); . 786,793c print("xfer failed %lux %lux %lux\n", fl.stat[0], fl.stat[1], fl.stat[2]); print("offset %lud len %d\n", off, dp->len); dp->confused = 1; errors("floppy drive lost"); . 754c cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); . 742c . 726,735d 686d 673,674c outb(Pdsr, 0); . 490a dp->vers++; . 481a fl.selected = dp; . 471a fl.selected = dp; . 443c tsleep(&fl.kr, return0, 0, 1000); . 440c qunlock(&fl); . 437c && canqlock(&fl)){ . 430,433d 424,425d 411a qunlock(&fl); . 409a fl.confused = 1; . 400,408d 397a qlock(&fl); . 395a qunlock(&fl); poperror(); . 383,386c islegal(c, n, dp); qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); . 380d 358a qunlock(&fl); poperror(); . 330a qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); . 325,328c islegal(c, n, dp); . 322d 306a static void islegal(Chan *c, long n, Drive *dp) { if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) errors("bad len"); } /* * check if the floppy has been replaced under foot * * a seek and a read clears the condition. this was determined experimentally, * there has to be a better way. */ static void changed(Chan *c, Drive *dp) { ulong old; if(inb(Pdir)&Fchange) dp->vers++; old = c->qid.vers; c->qid.vers = dp->vers; if(old && old!=dp->vers){ dp->ccyl = -1; if(dp->cyl) floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); else floppyxfer(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize); errors("disk changed"); } } . 281c devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); . 237a setvec(Floppyvec, floppyintr); . 231a dp->vers = 1; . 212a fl.selected = fl.d; . 164a static void floppyintr(Ureg*); . 145a Drive *selected; . 124a int vers; . 117,118d 42c Pdir= 0x3F7, /* disk changed port (read only) */ Pdsr= 0x3F7, /* data rate select port (write only) */ . ## diffname pc/devfloppy.c 1991/0927 ## diff -e /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c 454a } else if(SNCMP(aa, "v") == 0){ vgaset(aa+1); . 422a extern void vgaset(char*); . ## diffname pc/devfloppy.c 1991/1001 ## diff -e /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c 795c fl.cmd[fl.ncmd++] = dp->t->sectors; . ## diffname pc/devfloppy.c 1991/1003 ## diff -e /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c 343a old = c->qid.vers; c->qid.vers = dp->vers; if(old && old!=dp->vers) errors("disk changed"); . 342d 334,336d 332c if(inb(Pdir)&Fchange){ . ## diffname pc/devfloppy.c 1991/1005 ## diff -e /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c 636c /*print("can't read sense response\n");/**/ . ## diffname pc/devfloppy.c 1991/1006 ## diff -e /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c 833,834d 758a floppythrice(Drive *dp, int cmd, void *a, long off, long n) { int tries; long rv; for(tries = 0; ; tries++){ if(waserror()){ if(strcmp(u->error, errstrtab[Eintr])==0 || tries > 3) nexterror(); } else { rv = floppyxfer(dp, cmd, a, off, n); poperror(); return rv; } } } static long . 757a /* * since floppies are so flakey, try 3 times before giving up */ . 456,457d 444a if(i == 0) error(Eio); . 443c if(i < 0) . 441c i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, . 423d 390c i = floppythrice(dp, Fread, dp->cache, . 177a static long floppythrice(Drive*, int, void*, long, long); . ## diffname pc/devfloppy.c 1991/1029 ## diff -e /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c 457a } else if(SNCMP(aa, "fast") == 0){ cpuspeed(1); } else if(SNCMP(aa, "slow") == 0){ cpuspeed(0); . ## diffname pc/devfloppy.c 1991/1112 ## diff -e /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c 183,190c "fd0disk", {Qdata + 0}, 0, 0666, "fd0ctl", {Qctl + 0}, 0, 0666, "fd1disk", {Qdata + 1}, 0, 0666, "fd1ctl", {Qctl + 1}, 0, 0666, "fd2disk", {Qdata + 2}, 0, 0666, "fd2ctl", {Qctl + 2}, 0, 0666, "fd3disk", {Qdata + 3}, 0, 0666, "fd3ctl", {Qctl + 3}, 0, 0666, . ## diffname pc/devfloppy.c 1991/1203 ## diff -e /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c 287c return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); . ## diffname pc/devfloppy.c 1992/0111 ## diff -e /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c 773c if(strcmp(u->error, Eintr)==0 || tries > 3) . 7c #include "../port/error.h" . ## diffname pc/devfloppy.c 1992/0114 ## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c 859c error(Eio); . 848c error(Eio); . 841c error(Eio); . 826c error(Eio); . 799c error(Eio); . 396c error(Eio); . 344c error(Eio); . 319c error(Ebadarg); . 317c error(Ebadarg); . ## diffname pc/devfloppy.c 1992/0321 ## diff -e /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c 2c #include "../port/lib.h" . ## diffname pc/devfloppy.c 1992/0625 ## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c 234c dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 0); . 215c fl.d = xalloc(conf.nfloppy*sizeof(Drive)); . ## diffname pc/devfloppy.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0711/sys/src/9/safari/devfloppy.c 868a USED(ur); . 787d 668,669d 649a USED(a); . 611,612d 476a USED(a); . 423d 354d 309a USED(c, dp); . 303a USED(c); . 298a USED(c); . 292a USED(c, name, omode, perm); . 199,201d ## diffname pc/devfloppy.c 1992/0829 ## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c 835c /* print("xfer result failed %lux\n", inb(Pmsr));/**/ . 821c /* print("xfer cmd failed\n");/**/ . ## diffname pc/devfloppy.c 1992/0901 ## diff -e /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c 842c DPRINT("offset %lud len %d\n", off, dp->len); . 840c DPRINT("xfer failed %lux %lux %lux\n", fl.stat[0], . 835c DPRINT("xfer result failed %lux\n", inb(Pmsr)); . 821c DPRINT("xfer cmd failed\n"); . 797,798c DPRINT("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", dp->tcyl, dp->thead, dp->tsec, a, dp->len); . 750c DPRINT("seek failed\n"); . 741c DPRINT("seek cmd failed\n"); . 735c DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); . 685c DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl); . 638c DPRINT("can't read sense response\n"); . 555c DPRINT("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr)); . 14a #define DPRINT if(0)print . ## diffname pc/devfloppy.c 1992/1002 ## diff -e /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c 762c * since floppies are so flakey, automaticly retry failed attempts. * every 3 tries switch to a different density . 342c floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize); . 340c floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize); . 326c * check if the floppy has been replaced under foot. cause a read error if it has. . 86,91c [0] { "MF2HD", 512, 18, 2, 1, 80, 0x1B, 0x54, 1, }, [1] { "MF1DD", 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, [2] { "MF4HD", 1024, 18, 2, 1, 80, 0x1B, 0x54, 0, }, [3] { "F2HD", 512, 15, 2, 1, 80, 0x2A, 0x50, 4, }, [4] { "F2DD", 512, 8, 2, 2, 40, 0x2A, 0x50, 5, }, [5] { "F1DD", 512, 8, 1, 2, 40, 0x2A, 0x50, 3, }, . 74a int ring; /* ring of compatible floppy types */ . ## diffname pc/devfloppy.c 1992/1003 ## diff -e /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c 857a DPRINT("xfer ends on wrong cyl\n"); . 854c offset = ((fl.stat[3]+dp->t->steps-1)/dp->t->steps) * dp->t->heads + fl.stat[4]; . 775a /* walk through the compatible types */ if(tries == 3){ if(++dp->t == &floppytype[NTYPES]) dp->t = floppytype; floppydir[NFDIR*dp->dev].length = dp->t->cap; if(dp->t == start) nexterror(); tries = 0; floppyon(dp); } . 774c if(cmd != Fread || strcmp(u->error, Eintr)==0) . 771a start = dp->t; . 770a Type *start; . 758,759c dp->arm = dp->tcyl*dp->t->steps; return dp->tcyl; . 748a DPRINT("seek cmd confused\n"); . 735,736c if(dp->arm*dp->t->steps == dp->tcyl) return dp->tcyl; . 722a fl.rate = 0; . 686,688c dp->arm = fl.stat[1]; if(dp->arm != 0){ DPRINT("recalibrate went to wrong cylinder %d\n", dp->arm); . 514a /* set transfer rate */ if(fl.rate != dp->t->rate){ fl.rate = dp->t->rate; outb(Pdsr, fl.rate); } . 399c len = 0; continue; . 387a nn = dp->t->tsize; . 369d 348a } . 347c if(old && old!=dp->vers){ . 343c floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize); . 340c if(dp->arm) . 233c dp->arm = -1; /* because we don't know */ . 149a int rate; /* current rate selected */ . 125c int arm; /* current arm position */ . 87,92c { "3½HD", 512, 18, 2, 1, 80, 0x1B, 0x54, 0, }, { "3½DD", 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, { "5¼HD", 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, { "5¼DD2", 512, 9, 2, 2, 40, 0x2A, 0x50, 2, }, { "5¼DD1", 512, 9, 2, 2, 40, 0x2A, 0x50, 1, }, { "3½ED", 1024, 18, 2, 1, 80, 0x1B, 0x54, 3, }, . 75c int rate; /* rate code */ . 63c * floppy types (all MFM encoding) . ## diffname pc/devfloppy.c 1992/1006 ## diff -e /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c 899,901c case Fformat: . 891a /* * format a track */ static int floppyformat(Chan *c, Drive *dp, int track, char filler) { int cyl, h, sec; uchar *buf, *bp; Type *t; t = dp->t; cyl = track/t->heads; h = track % t->heads; if(track >= t->tracks * t->heads) return 0; buf = smalloc(t->sectors*4); qlock(&fl); if(waserror()){ qunlock(&fl); free(buf); nexterror(); } floppyon(dp); changed(c, dp); if(floppyseek(dp, track*t->tsize) < 0) error(Eio); /* * 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; } dmasetup(DMAchan, buf, bp-buf, 0); /* * 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++] = filler; if(floppycmd() < 0){ DPRINT("xfer cmd failed\n"); error(Eio); } /* * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); /* * check for errors */ if(fl.nstat < 7){ DPRINT("format result failed %lux\n", inb(Pmsr)); fl.confused = 1; error(Eio); } if((fl.stat[0]&Codemask)!=0 || fl.stat[1] || fl.stat[2]){ DPRINT("format failed %lux %lux %lux\n", fl.stat[0], fl.stat[1], fl.stat[2]); dp->confused = 1; error(Eio); } qunlock(&fl); free(buf); return 1; } . 879c offset = fl.stat[3] * dp->t->heads + fl.stat[4]; . 841c fl.cmd[fl.ncmd++] = dp->tcyl; . 793,794c while(++dp->t){ if(dp->t == &floppytype[NTYPES]) dp->t = floppytype; if(dp->dt == Tnone) break; if(dp->dt == dp->t->dt) break; } . 770c dp->cyl = dp->tcyl; . 746c if(dp->cyl == dp->tcyl) . 696,698c dp->cyl = fl.stat[1]; if(dp->cyl != 0){ DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl); . 464,467c } else if(SNCMP(ctlmsg, "format") == 0){ if(getfields(ctlmsg, f, 3, ' ') != 3) error(Ebadarg); rv = n*floppyformat(c, dp, atoi(f[1]), *f[2]); . 461c } else if(SNCMP(ctlmsg, "reset") == 0){ . 459c if(n >= sizeof(ctlmsg)) n = sizeof(ctlmsg) - 1; memmove(ctlmsg, aa, n); ctlmsg[n] = 0; if(SNCMP(ctlmsg, "eject") == 0){ . 447,448c i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, n-rv); . 429a char *f[3]; char ctlmsg[64]; . 340,341c dp->confused = 1; floppyon(dp); if(dp->cyl) . 338a setdef(dp); . 240a * read nvram for types of floppies 0 & 1 */ equip = nvramread(0x10); if(conf.nfloppy > 0){ fl.d[0].dt = (equip >> 4) & 0xf; setdef(&fl.d[0]); } if(conf.nfloppy > 1){ fl.d[1].dt = equip & 0xf; setdef(&fl.d[1]); } /* . 232,234c dp->dt = T1440kb; setdef(dp); dp->cyl = -1; /* because we don't know */ . 202a uchar equip; . 197a /* * set floppy drive to its default type */ static void setdef(Drive *dp) { Type *t; for(t = floppytype; t < &floppytype[NTYPES]; t++) if(dp->dt == t->dt){ dp->t = t; floppydir[NFDIR*dp->dev].length = dp->t->cap; break; } } . 181a static int floppyformat(Chan*, Drive*, int, char); . 125c int cyl; /* current arm position */ . 121c Type *t; /* floppy type */ int dt; /* drive type */ . 87,92c { "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, }, { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, }, . 67a int dt; /* compatible drive type */ . 62a * types of drive (from PC equipment byte) */ enum { Tnone= 0, T360kb= 1, T1200kb= 2, T720kb= 3, T1440kb= 4, }; /* . 39a Fformat= 0x4d, /* format cmd */ . ## diffname pc/devfloppy.c 1992/1007 ## diff -e /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c 1027a poperror(); . 1026d 974,977c if(!waserror()){ floppyon(dp); poperror(); } floppyseek(dp, track*t->tsize); dp->cyl = cyl; dp->confused = 0; . 970d 967,968d 965a setdef(dp); . 955c floppyformat(Drive *dp, ulong track, ulong filler) . 521a poperror(); . 520c rv = n*floppyformat(dp, strtoul(f[1], 0, 0), strtoul(f[2], 0, 0)); . 507a if(waserror()){ qunlock(&fl); nexterror(); } . 463c return readstr(offset, a, n, dp->t->name); . 197c static int floppyformat(Drive*, ulong, ulong); . ## diffname pc/devfloppy.c 1992/1009 ## diff -e /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c 1034d 1026,1031d 1018,1024c /* * seek to track, ignore errors */ if(!waserror()){ floppyon(dp); poperror(); } 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; } dmasetup(DMAchan, buf, bp-buf, 0); /* * 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){ DPRINT("xfer cmd failed\n"); error(Eio); } /* * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); /* * check for errors */ if(fl.nstat < 7){ DPRINT("format result failed %lux\n",inb(Pmsr)); fl.confused = 1; error(Eio); } if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){ DPRINT("format failed %lux %lux %lux\n", fl.stat[0], fl.stat[1], fl.stat[2]); dp->confused = 1; error(Eio); } . 1015,1016c for(track = 0; track < t->tracks*t->heads; track++){ cyl = track/t->heads; h = track % t->heads; . 1013c * format a track at time . 1000,1009c buf = smalloc(t->sectors*4); if(waserror()){ free(buf); nexterror(); . 998c * buffer for per track info . 995d 988,993c if(getfields(params, f, 3, ' ') > 1){ for(t = floppytype; t < &floppytype[NTYPES]; t++) if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){ dp->t = t; floppydir[NFDIR*dp->dev].length = dp->t->cap; break; } } else { setdef(dp); t = dp->t; . 986c * set the type . 966,984d 964a char *f[3]; . 962a ulong track; . 959,960c static void floppyformat(Drive *dp, char *params) . 522,524c floppyformat(dp, ctlmsg); . 506a rv = n; . 497c i = floppythrice(dp, Fwrite, aa+rv, offset+rv, n-rv); . 494c floppypos(dp, offset+rv); . 485c islegal(offset, n, dp); . 478d 473c floppywrite(Chan *c, void *a, long n, ulong offset) . 433c floppypos(dp, offset+rv); . 418c islegal(offset, n, dp); . 403c floppyread(Chan *c, void *a, long n, ulong offset) . 367c if(offset % dp->t->bytes) . 365c islegal(ulong offset, long n, Drive *dp) . 197c static void floppyformat(Drive*, char*); . 7a #include "devtab.h" . ## diffname pc/devfloppy.c 1992/1013 ## diff -e /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c 1057a dp->confused = 1; . 1040a poperror(); . 1018a if(waserror()){ dmaend(DMAchan); nexterror(); } . 949a poperror(); . 921a poperror(); . 894a if(waserror()){ dmaend(DMAchan); nexterror(); } . 882,884c /* retry on error 3 times */ while(waserror()) if(tries++ >= 3) nexterror(); . 875a int tries = 0; . 836,872d 832,833c * read or write to floppy. try up to three times. . 755a dp->cyl = -1; . 497c i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); . 446c i = floppyxfer(dp, Fread, dp->cache, . 400d 398c if(old && old != dp->vers) . 395a . 390,394c floppyseek(dp, dp->t->heads*dp->t->tsize); while(waserror()){ while(++dp->t){ if(dp->t == &floppytype[NTYPES]) dp->t = floppytype; if(dp->dt == dp->t->dt) break; } floppydir[NFDIR*dp->dev].length = dp->t->cap; if(dp->t == start) nexterror(); floppyon(dp); } floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); poperror(); . 388c setdef(dp); start = dp->t; dp->confused = 1; /* make floppyon recal */ . 385,386c /* * if floppy has changed or first time through */ if((inb(Pdir)&Fchange) || dp->vers == 0){ . 383a Type *start; . 377,378c * 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. . 375c * check if the floppy has been replaced under foot. cause * an error if it has. . 199d ## diffname pc/devfloppy.c 1992/1016 ## diff -e /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c 1047c DPRINT("format: failed %lux %lux %lux\n", . 1042c DPRINT("format: confused\n"); . 1029d 1026,1027c if(floppycmd() < 0) . 992,995d 981a /* force a recalibrate to cylinder 0 */ dp->confused = 1; if(!waserror()){ floppyon(dp); poperror(); } . 936c DPRINT("xfer: ends on wrong cyl\n"); . 922c DPRINT("xfer: failed %lux %lux %lux\n", fl.stat[0], . 917c DPRINT("xfer: confused\n"); . 904d 900,902c if(floppycmd() < 0) . 874c DPRINT("floppyxfer: tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", . 872a } . 871c if(floppyseek(dp, off) < 0){ DPRINT("xfer: seek failed\n"); dp->confused = 1; . 868a } . 866c tries = 0; while(waserror()){ DPRINT("floppyxfer: retrying\n"); . 858c int tries; . 842c DPRINT("seek: failed\n"); . 837c DPRINT("seek: confused\n"); . 834d 831,832c if(floppycmd() < 0) . 826c DPRINT("seek: tcyl %d, thead %d\n", dp->tcyl, dp->thead); . 824a dp->cyl = -1; . 774c DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl); . 768a DPRINT("recalibrate: failed\n"); . 764a DPRINT("recalibrate: confused\n"); . 756a dp->cyl = -1; . 644c DPRINT("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr)); . 640a fl.nstat = 0; . 542a } else if(SNCMP(ctlmsg, "debug") == 0){ floppydebug = 1; . 410a DPRINT("changed: trying %s\n", dp->t->name); . 16c #define DPRINT if(floppydebug)print int floppydebug; . ## diffname pc/devfloppy.c 1992/1113 ## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c 269c dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 64*1024); . ## diffname pc/devfloppy.c 1992/1120 ## diff -e /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c 819c fl.rate = -1; . 772c DPRINT("recalibrate: confused %ux\n", inb(Pmsr)); . 648c if(tries > 10000){ . ## diffname pc/devfloppy.c 1992/1216 ## diff -e /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c 819c fl.rate = 0; DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir)); . 805a DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir)); . 764a DPRINT("floppyrecal: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir)); . 753a if(!cmddone(0)) floppyintr(0); . 411d 408a floppyon(dp); . 394a DPRINT("changed: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir)); . ## diffname pc/devfloppy.c 1992/1217 ## diff -e /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c 893,895d 842d 825c DPRINT("floppyrevive out\n"); fldump(); . 822a floppywait(); /* mark all drives in an unknown state */ for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++) dp->confused = 1; /* set rate to a known value */ . 821d 818,819d 812a fl.ncmd = 1; . 810c DPRINT("floppyrevive in\n"); fldump(); . 768d 754c tsleep(&fl.r, cmddone, 0, 5000); . 749c * 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. . 734a fldump(); . 692,693c fl.nstat = sizeof(fl.stat); return fl.nstat; . 685c return fl.nstat; . 678a DPRINT("floppyresult: %d stats\n", i); fldump(); . 676a /* wait for status byte */ . 675a /* get the result of the operation */ . 649,652c 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(); . 599a /* clear any pending interrupts */ floppysense(); } . 597c if(!alreadyon){ /* wait for drive to spin up */ . 413d 410a DPRINT("changed: trying %s\n", dp->t->name); fldump(); . 395c DPRINT("changed\n"); fldump(); . 383c * possibilities for this drive. . 214a static void fldump(void) { DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb), inb(Pdor), inb(Pmsr), inb(Pdir)); } . 21a /* status registers a & b */ Psra= 0x3f0, Psrb= 0x3f1, . 16c #define DPRINT if(floppydebug)kprint . ## diffname pc/devfloppy.c 1992/1218 ## diff -e /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c 846a delay(10); . 845c delay(10); . 784a fl.confused = 1; } . 783c if(!cmddone(0)){ . 614a setvec(Floppyvec, floppyintr); . 280c dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024); . 255a if(maxtsize < t->tsize) maxtsize = t->tsize; . 251a maxtsize = 0; . 247a ulong maxtsize; . ## diffname pc/devfloppy.c 1993/0219 ## diff -e /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c 619d ## diffname pc/devfloppy.c 1993/0410 ## diff -e /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c 112a { "ATT3B1", T360kb, 512, 8, 2, 1, 48, 0x2A, 0x50, 2, }, . ## diffname pc/devfloppy.c 1993/0430 ## diff -e /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c 113d 111a { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, }, . ## diffname pc/devfloppy.c 1993/0915 ## diff -e /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c 479,496c if(readtrack(dp, cyl, head) < 0) break; . 471c * all xfers come out of the track cache . 447,448c long rv; int sec, head, cyl; . 442a static int readtrack(Drive *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; } . ## diffname pc/devfloppy.c 1993/1124 ## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c 1124c USED(ur, arg); . 1122c floppyintr(Ureg *ur, void *arg) . 794c floppyintr(0, 0); . 307c setvec(Floppyvec, floppyintr, 0); . 192c static void floppyintr(Ureg*, void*); . ## diffname pc/devfloppy.c 1994/1017 ## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c 377,378c Dirtab *dt; Dir d; if(!iseve()) error(Eperm); if(CHDIR & c->qid.path) error(Eperm); convM2D(dp, &d); d.mode &= 0x666; dt = &floppydir[2 * (c->qid.path & ~Qmask)]; dt[0].perm = dt[1].perm = d.mode; . 209,216c "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, . ## diffname pc/devfloppy.c 1995/0105 ## diff -e /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c 16c #define DPRINT if(floppydebug)print . ## diffname pc/devfloppy.c 1995/0108 ## diff -e /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c 589a } long floppybwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); . 526a Block* floppybread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } . ## diffname pc/devfloppy.c 1995/0117 ## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c 1045c if(getfields(params, f, 3, " ") > 1){ . ## diffname pc/devfloppy.c 1995/0218 ## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c 1051a } if(t >= &floppytype[NTYPES]) error(Ebadarg); . 1046c for(t = floppytype; t < &floppytype[NTYPES]; t++){ . 240a } . 239c return; . 235c for(t = floppytype; t < &floppytype[NTYPES]; t++){ . ## diffname pc/devfloppy.c 1995/0726 ## diff -e /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c 358d 356c floppycreate(Chan*, char*, int, ulong) . ## diffname pc/devfloppy.c 1995/0728 ## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c 978c fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0); . 976c cmd = cmd; . 953c if(tries++ > 20) . 949c /* retry on error */ . ## diffname pc/devfloppy.c 1995/0818 ## diff -e /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c 1009c if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun) DPRINT("DMA overrun: retry\n"); else dp->confused = 1; . 59a /* status 1 byte */ Overrun= 0x10, . 58a Cmdexec= 1<<6, . ## diffname pc/devfloppy.c 1995/1121 ## diff -e /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c 866c static void . ## diffname pc/devfloppy.c 1996/0223 ## diff -e /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c 8d ## diffname pc/devfloppy.c 1996/0315 ## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c 1051c if(parsefields(params, f, 3, " ") > 1){ . ## diffname pc/devfloppy.c 1997/0327 ## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c 1170a Dev floppydevtab = { floppyreset, devinit, floppyattach, devclone, floppywalk, floppystat, floppyopen, devcreate, floppyclose, floppyread, devbread, floppywrite, devbwrite, devremove, devwstat, }; . 1159a case Fdumpreg: . 1155c USED(ur); . 1153c floppyintr(Ureg *ur) . 1124a /* Poll ready bits and transfer data */ floppyexec((char *)buf, bp-buf, 0); . 1062c floppysetdef(dp); . 1059c if(t >= &floppytype[nelem(floppytype)]) . 1052c for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ . 1045c FType *t; . 1040c floppyformat(FDrive *dp, char *params) . 1014c } else . 1012c if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){ . 992a /* Poll ready bits and transfer data */ floppyexec((char*)a, dp->len, cmd==Fread); . 979d 957a DPRINT("floppyxfer: retrying\n"); /*floppyon(dp);*/ . 955d 952c /* retry on error (until it gets ridiculous) */ . 942c floppyxfer(FDrive *dp, int cmd, void *a, long off, long n) . 909c floppyseek(FDrive *dp, long off) . 891c for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++) . 868c FDrive *dp; . 828c floppyrecal(FDrive *dp) . 819c floppyintr(0); . 761c floppypos(FDrive *dp, long off) . 749c fl.stat[i] = inb(Pfdata); . 747a if(tries > 1000){ DPRINT("floppyresult: %d stats\n", i); fldump(); fl.confused = 1; return -1; } microdelay(8); /* for machine independence */ . 735,740d 713c outb(Pfdata, fl.cmd[i]); . 710,711c microdelay(8); /* for machine independence */ . 701a if((inb(Pmsr)&(Ffrom|Fready)) == Fready) break; . 680,690d 676d 672c floppyoff(FDrive *dp) . 633c floppyon(FDrive *dp) . 616c for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ . 610c FDrive *dp; . 601,606d 590c } else error(Ebadctl); . 540c FDrive *dp; . 537c static long . 530,535d 487c return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen); . 480c FDrive *dp; . 477c static long . 457c readtrack(FDrive *dp, int cyl, int head) . 434c if(dp->t == &floppytype[nelem(floppytype)]) . 427c floppysetdef(dp); . 418c FType *start; . 415c changed(Chan *c, FDrive *dp) . 395c islegal(ulong offset, long n, FDrive *dp) . 370,393d 358,364c static void . 355c return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen); . 352c static Chan* . 349c devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen); . 346c static void . 343c return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen); . 334,340c static int . 319c static Chan* . 314,316c floppysetup1(&fl); . 311,312d 295,307d 287c floppysetdef(dp); . 284c for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ . 270c fl.d = xalloc(fl.ndrive*sizeof(FDrive)); . 259c for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ . 253a floppysetup0(&fl); . 250,252c FDrive *dp; FType *t; . 247c static void . 244d 242c break; . 238c for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++) . 236c FType *t; . 234c floppysetdef(FDrive *dp) . 212,219c "fd0disk", {Qdata + 0}, 0, 0666, "fd0ctl", {Qctl + 0}, 0, 0666, "fd1disk", {Qdata + 1}, 0, 0666, "fd1ctl", {Qctl + 1}, 0, 0666, "fd2disk", {Qdata + 2}, 0, 0666, "fd2ctl", {Qctl + 2}, 0, 0666, "fd3disk", {Qdata + 3}, 0, 0666, "fd3ctl", {Qctl + 3}, 0, 0666, . 206,209c static long floppyxfer(FDrive*, int, void*, long, long); . 203c static long floppyseek(FDrive*, long); . 197,200c static void floppypos(FDrive*,long); static int floppyrecal(FDrive*); . 193,195c static int cmddone(void*); static void floppyformat(FDrive*, char*); . 149,187d 140,147c FController fl; . 118d 89,109d 84,87c FType floppytype[] = . 71a #define DPRINT if(floppydebug)iprint int floppydebug; . 64c Qdir= 0, . 15,62c enum { . 11,13c /* This module expects the following functions to be defined * elsewhere: * * inb() * outb() * floppyexec() * floppyeject() * floppysetup0() * floppysetup1() * 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. */ . 8a #include "floppy.h" . ## diffname pc/devfloppy.c 1997/0404 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c 933c if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) error(Eio); . 795a if(dp->len < 0) error(Eio); . 145a dmainit(DMAchan); . 21a * dmainit() . ## diffname pc/devfloppy.c 1997/0408 ## diff -e /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c 1005a 'f', "floppy", . ## diffname pc/devfloppy.c 1997/0910 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c 107,114c "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, . ## diffname pc/devfloppy.c 1998/0120 ## diff -e /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c 188c dp->vers = 0; . 41,42c #define DPRINT if(floppydebug)print int floppydebug = 1; . ## diffname pc/devfloppy.c 1998/0213 ## diff -e /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c 42c int floppydebug = 0; . ## diffname pc/devfloppy.c 1998/0319 ## diff -e /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c 987d 985c floppyintr(Ureg *) . 627d 625c cmddone(void *) . 445d 441c floppykproc(void *) . 381a ulong offset = off; . 376c floppywrite(Chan *c, void *a, long n, vlong off) . 328a ulong offset = off; . 322c floppyread(Chan *c, void *a, long n, vlong off) . 235d 233c floppyclose(Chan *) . ## diffname pc/devfloppy.c 1998/0825 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c 972c DPRINT("format: failed %ux %ux %ux\n", . 838c DPRINT("offset %lud len %ld\n", off, dp->len); . 836c DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0], . ## diffname pc/devfloppy.c 1999/0403 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c 162a dmainit(DMAchan, maxtsize); . 147,148d ## diffname pc/devfloppy.c 1999/0507 ## diff -e /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c 685c * reset it and get back to a known state . ## diffname pc/devfloppy.c 1999/0714 ## diff -e /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c 202a if(fl.ndrive == 0) error(Enodev); . 148a if(fl.ndrive == 0) return; . ## diffname pc/devfloppy.c 2000/0308 ## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c 883c if(getfields(params, f, 3, 1, " ") > 1){ . ## diffname pc/devfloppy.c 2000/0813 ## diff -e /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c 964c floppywait(1); . 828c floppywait(0); . 785d 782c if(tries++ >= dp->maxtries) . 749c floppywait(1); . 715c floppywait(0); . 665c floppywait(1); . 644c tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000); . 642c floppywait(int slow) . 503a /* return -1 if this didn't work */ if(dp->confused) return -1; return 0; . 470c static int . 295a dp->maxtries = 20; . 293a /* if the read succeeds, we've got the density right */ . 288c /* floppyon will fail if there's a controller but no drive */ if(floppyon(dp) < 0) error(Eio); . 280a /* * if first attempt doesn't reset changed bit, there's * no floppy there */ if(inb(Pdir)&Fchange) nexterror(); . 278c if(floppyon(dp) < 0) error(Eio); /* seek to the first track */ . 276a dp->maxtries = 3; /* limit it when we're probing */ /* floppyon will fail if there's a controller but no drive */ . 275d 103c static void floppywait(int); . ## diffname pc/devfloppy.c 2001/0527 ## diff -e /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c 1038d 354c if(c->qid.type & QTDIR) . 228c return devstat(c, dp, n, floppydir, fl.ndrive*NFDIR, devgen); . 225,226c static int floppystat(Chan *c, uchar *dp, int n) . 222c return devwalk(c, nc, name, nname, floppydir, fl.ndrive*NFDIR, devgen); . 219,220c static Walkqid* floppywalk(Chan *c, Chan *nc, char **name, int nname) . 106a ".", {Qdir, 0, QTDIR}, 0, 0550, . ## diffname pc/devfloppy.c 2001/0716 ## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c 911c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . 356c return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen); . 300c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . 235c return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen); . 229c return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen); . 223c return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen); . 137c floppydir[1+NFDIR*dp->dev].length = dp->t->cap; . ## diffname pc/devfloppy.c 2001/1117 ## diff -e /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c 907c if(tokenize(params, f, 3) > 1){ . ## diffname pc/devfloppy.c 2001/1120 ## diff -e /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c 919a } else { cmderror(cb, "invalid floppy format command"); SET(t); . 917c } else if(cb->nf == 1){ . 909c if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){ . 907c if(cb->nf == 2){ . 902d 896c floppyformat(FDrive *dp, Cmdbuf *cb) . 457a poperror(); free(cb); . 454,455c break; } . 450,452c break; case CMdebug: . 447c break; case CMformat: floppyformat(dp, cb); break; case CMreset: . 441,445c ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); switch(ct->index){ case CMeject: . 435a cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } . 406c Cmdbuf *cb; Cmdtab *ct; . 399d 118a enum { CMdebug, CMeject, CMformat, CMreset, }; static Cmdtab floppyctlmsg[] = { CMdebug, "debug", 1, CMeject, "eject", 1, CMformat, "format", 0, CMreset, "reset", 1, }; . 95c static void floppyformat(FDrive*, Cmdbuf*); . ## diffname pc/devfloppy.c 2002/0109 ## diff -e /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c 1063a devshutdown, . ## diffname pc/devfloppy.c 2003/0325 ## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c 475a break; case CMnodebug: floppydebug = 0; . 129a CMnodebug, "nodebug", 1, . 121a CMnodebug, . ## diffname pc/devfloppy.c 2003/0407 ## diff -e /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0407/sys/src/9/pc/devfloppy.c 534c tsleep(&up->sleep, return0, 0, 750); . 512c tsleep(&up->sleep, return0, 0, 1000); .