| plan 9 kernel history: overview | file list | diff list |
1991/0802/pc/devfloppy.c (diff list | history)
| 1991/0731/sys/src/9/pc/devfloppy.c:4,14 – 1991/0802/sys/src/9/pc/devfloppy.c:4,14 (short | long | prev | next) | ||
| 1991/0727 | #include "dat.h" #include "fns.h" #include "io.h" | |
| 1991/0802 | #include "errno.h" | |
| 1991/0727 |
| |
| 1991/0802 | typedef struct Drive Drive; | |
| 1991/0727 | typedef struct Controller Controller; | |
| 1991/0802 | typedef struct Type Type; | |
| 1991/0727 | enum { | |
| 1991/0731/sys/src/9/pc/devfloppy.c:46,53 – 1991/0802/sys/src/9/pc/devfloppy.c:46,54 | ||
| 1991/0728 | /* file types */ Qdir= 0, | |
| 1991/0731 |
| |
| 1991/0802 | Qdata= (1<<2), Qstruct= (2<<2), Qmask= (3<<2), | |
| 1991/0727 | }; /* | |
| 1991/0731/sys/src/9/pc/devfloppy.c:82,88 – 1991/0802/sys/src/9/pc/devfloppy.c:83,91 | ||
| 1991/0731 | #define NTYPES (sizeof(floppytype)/sizeof(Type)) /* | |
| 1991/0802 | * bytes per sector encoding for the controller. * - index for b2c is is (bytes per sector/128). * - index for c2b is code from b2c | |
| 1991/0731 | */ static int b2c[] = | |
| 1991/0727 | { | |
| 1991/0731/sys/src/9/pc/devfloppy.c:112,118 – 1991/0802/sys/src/9/pc/devfloppy.c:115,120 | ||
| 1991/0727 | ulong lasttouched; /* time last touched */ int motoron; /* motor is on */ int cyl; /* current cylinder */ | |
| 1991/0731/sys/src/9/pc/devfloppy.c:120,126 – 1991/0802/sys/src/9/pc/devfloppy.c:122,127 | ||
| 1991/0727 | int tsec; /* target sector */ | |
| 1991/0731 | long len; /* size of xfer */ | |
| 1991/0727 |
| |
| 1991/0731 | Rendez r; /* waiting here for motor to spin up */ | |
| 1991/0727 | }; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:132,142 – 1991/0802/sys/src/9/pc/devfloppy.c:133,144 | ||
| 1991/0731 | QLock; /* exclusive access to the contoller */ Drive d[Ndrive]; /* the floppy drives */ | |
| 1991/0727 |
| |
| 1991/0731 | int intr; /* true if interrupt occured */ Rendez r; /* wait here for command termination */ | |
| 1991/0802 | Rendez kr; /* for motor watcher */ | |
| 1991/0727 | }; | |
| 1991/0728 | Controller floppy; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:150,195 – 1991/0802/sys/src/9/pc/devfloppy.c:152,201 | ||
| 1991/0731 | static int floppysend(int); static int floppyrcv(void); static int floppyresult(int); | |
| 1991/0802 | static void floppypos(Drive*,long); | |
| 1991/0731 | static int floppysense(Drive*); static int interrupted(void*); static int floppyrecal(Drive*); static void floppyrevive(void); static long floppyseek(Drive*); | |
| 1991/0802 | static long floppyxfer(Drive*, int, void*, long, long); | |
| 1991/0731 | static void floppyintr(Ureg*); | |
| 1991/0802 | 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)) | |
| 1991/0731 |
| |
| 1991/0802 | Type *t; | |
| 1991/0731 | ||
| 1991/0802 | /* * 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 */ | |
| 1991/0731 | for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ | |
| 1991/0802 | floppydir[2*dp->dev].length = dp->t->cap; | |
| 1991/0731 | dp->motoron = 1; | |
| 1991/0802 | dp->cyl = -1; /* because we don't know */ | |
| 1991/0731 | motoroff(dp); } setvec(Floppyvec, floppyintr); | |
| 1991/0731/sys/src/9/pc/devfloppy.c:198,218 – 1991/0802/sys/src/9/pc/devfloppy.c:204,277 | ||
| 1991/0731 | void floppyinit(void) { | |
| 1991/0802 | kproc("floppy", floppykproc, 0); | |
| 1991/0731 | } | |
| 1991/0802 | 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; } | |
| 1991/0731 | long floppyread(Chan *c, void *a, long n) { | |
| 1991/0731/sys/src/9/pc/devfloppy.c:220,230 – 1991/0802/sys/src/9/pc/devfloppy.c:279,308 | ||
| 1991/0731 | long rv, i; uchar *aa = a; | |
| 1991/0802 | 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"); | |
| 1991/0731 | } return rv; } | |
| 1991/0731/sys/src/9/pc/devfloppy.c:236,252 – 1991/0802/sys/src/9/pc/devfloppy.c:314,340 | ||
| 1991/0731 | long rv, i; uchar *aa = a; | |
| 1991/0802 | 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"); | |
| 1991/0731 | } return rv; } /* | |
| 1991/0727 |
| |
| 1991/0802 | * start a floppy drive's motor. set an alarm for .75 second later to | |
| 1991/0727 | * mark it as started (we get no interrupt to tell us). * * assume the caller qlocked the drive. | |
| 1991/0731/sys/src/9/pc/devfloppy.c:258,267 – 1991/0802/sys/src/9/pc/devfloppy.c:346,353 | ||
| 1991/0727 | cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev; outb(Fmotor, cmd); | |
| 1991/0802 | tsleep(&dp->r, return0, 0, 750); | |
| 1991/0727 | dp->motoron = 1; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:282,294 – 1991/0802/sys/src/9/pc/devfloppy.c:368,384 | ||
| 1991/0727 | { Drive *dp; | |
| 1991/0731 |
| |
| 1991/0728 |
| |
| 1991/0729 |
| |
| 1991/0731 |
| |
| 1991/0728 |
| |
| 1991/0802 | 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); } | |
| 1991/0728 | } | |
| 1991/0802 | tsleep(&floppy.kr, return0, 0, 5*1000); | |
| 1991/0727 | } } | |
| 1991/0731/sys/src/9/pc/devfloppy.c:367,379 – 1991/0802/sys/src/9/pc/devfloppy.c:457,469 | ||
| 1991/0731 | * truncate dp->length if it crosses a cylinder boundary */ static void | |
| 1991/0802 | floppypos(Drive *dp, long off) | |
| 1991/0727 | { int lsec; int end; int cyl; | |
| 1991/0731 |
| |
| 1991/0802 | lsec = off/dp->t->bytes; | |
| 1991/0727 | 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; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:382,388 – 1991/0802/sys/src/9/pc/devfloppy.c:472,478 | ||
| 1991/0727 | * can't read across cylinder boundaries. * if so, decrement the bytes to be read. */ | |
| 1991/0731 |
| |
| 1991/0802 | lsec = (off+dp->len)/dp->t->bytes; | |
| 1991/0727 | cyl = lsec/(dp->t->sectors*dp->t->heads); if(cyl != dp->tcyl){ | |
| 1991/0731 | dp->len -= (lsec % dp->t->sectors)*dp->t->bytes; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:414,420 – 1991/0802/sys/src/9/pc/devfloppy.c:504,510 | ||
| 1991/0727 | /* * make sure it's the right drive */ | |
| 1991/0802 | if((floppy.stat[0] & Drivemask) != dp->dev){ | |
| 1991/0727 | print("sense failed\n"); dp->confused = 1; return -1; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:517,530 – 1991/0802/sys/src/9/pc/devfloppy.c:607,620 | ||
| 1991/0731 | static long floppyseek(Drive *dp) | |
| 1991/0727 | { | |
| 1991/0802 | if(dp->cyl == dp->tcyl) return dp->cyl; | |
| 1991/0727 | /* * tell floppy to seek */ | |
| 1991/0802 | floppy.intr = 0; dp->cyl = -1; /* once the seek starts it could end anywhere */ | |
| 1991/0727 | if(floppysend(Fseek) < 0 | |
| 1991/0731 | || floppysend((dp->thead<<2) | dp->dev) < 0 | |
| 1991/0727 | || floppysend(dp->tcyl * dp->t->steps) < 0){ | |
| 1991/0731/sys/src/9/pc/devfloppy.c:532,541 – 1991/0802/sys/src/9/pc/devfloppy.c:622,627 | ||
| 1991/0727 | floppy.confused = 1; return -1; } | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | /* | |
| 1991/0731/sys/src/9/pc/devfloppy.c:563,574 – 1991/0802/sys/src/9/pc/devfloppy.c:649,659 | ||
| 1991/0727 | return -1; } | |
| 1991/0802 | return dp->cyl; | |
| 1991/0727 | } | |
| 1991/0731 | static long | |
| 1991/0727 |
| |
| 1991/0802 | floppyxfer(Drive *dp, int cmd, void *a, long off, long n) | |
| 1991/0727 | { ulong addr; long offset; | |
| 1991/0731/sys/src/9/pc/devfloppy.c:577,583 – 1991/0802/sys/src/9/pc/devfloppy.c:662,668 | ||
| 1991/0727 | ||
| 1991/0731 | qlock(&floppy); qlock(dp); | |
| 1991/0802 | if(waserror()){ | |
| 1991/0731 | qunlock(&floppy); qunlock(dp); } | |
| 1991/0731/sys/src/9/pc/devfloppy.c:594,600 – 1991/0802/sys/src/9/pc/devfloppy.c:679,685 | ||
| 1991/0731 | * calculate new position and seek to it (dp->len may be trimmed) */ | |
| 1991/0727 | dp->len = n; | |
| 1991/0731 |
| |
| 1991/0802 | floppypos(dp, off); | |
| 1991/0731 | if(floppyseek(dp) < 0) errors("seeking floppy"); | |
| 1991/0727 | ||
| 1991/0731/sys/src/9/pc/devfloppy.c:609,617 – 1991/0802/sys/src/9/pc/devfloppy.c:694,703 | ||
| 1991/0727 | /* | |
| 1991/0731 | * start operation | |
| 1991/0727 | */ | |
| 1991/0802 | floppy.intr = 0; | |
| 1991/0727 | cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); if(floppysend(cmd) < 0 | |
| 1991/0802 | || floppysend((dp->thead<<2) | dp->dev) < 0 | |
| 1991/0727 | || floppysend(dp->tcyl * dp->t->steps) < 0 || floppysend(dp->thead) < 0 || floppysend(dp->tsec) < 0 | |
| 1991/0731/sys/src/9/pc/devfloppy.c:623,629 – 1991/0802/sys/src/9/pc/devfloppy.c:709,714 | ||
| 1991/0727 | floppy.confused = 1; | |
| 1991/0731 | errors("floppy command failed"); | |
| 1991/0727 | } | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | /* | |
| 1991/0731/sys/src/9/pc/devfloppy.c:645,661 – 1991/0802/sys/src/9/pc/devfloppy.c:730,746 | ||
| 1991/0727 | offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4]; offset = offset*dp->t->sectors + floppy.stat[5] - 1; | |
| 1991/0731 | offset = offset * c2b[floppy.stat[6]]; | |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0802 | if(offset != off+dp->len){ print("new offset %d instead of %d\n", offset, off+dp->len); | |
| 1991/0727 | dp->confused = 1; | |
| 1991/0731 | errors("floppy drive lost"); | |
| 1991/0727 | } | |
| 1991/0802 | dp->lasttouched = m->ticks; | |
| 1991/0731 | qunlock(&floppy); qunlock(dp); poperror(); | |
| 1991/0727 |
| |