| plan 9 kernel history: overview | file list | diff list |
1999/0714/pc/devfloppy.c (diff list | history)
| 1991/0727/sys/src/9/pc/devfloppy.c:29,43 – 1991/0728/sys/src/9/pc/devfloppy.c:29,38 (short | long) | ||
| 1991/0727 | Fwrite= 0x47, /* write cmd */ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ | |
| 1991/0728 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0727 | /* sector size encodings */ S128= 0, S256= 1, | |
| 1991/0727/sys/src/9/pc/devfloppy.c:48,53 – 1991/0728/sys/src/9/pc/devfloppy.c:43,53 | ||
| 1991/0727 | Drivemask= 3<<0, Seekend= 1<<5, Codemask= (3<<6)|(3<<3), | |
| 1991/0728 | /* file types */ Qdir= 0, Qdata= 16, Qstruct= 32, | |
| 1991/0727 | }; /* | |
| 1991/0727/sys/src/9/pc/devfloppy.c:117,123 – 1991/0728/sys/src/9/pc/devfloppy.c:117,123 | ||
| 1991/0727 | int confused; }; | |
| 1991/0728 | Controller floppy; | |
| 1991/0727 | /* * start a floppy drive's motor. set an alarm for 1 second later to | |
| 1991/0727/sys/src/9/pc/devfloppy.c:151,158 – 1991/0728/sys/src/9/pc/devfloppy.c:151,156 | ||
| 1991/0727 | { int cmd; | |
| 1991/0727/sys/src/9/pc/devfloppy.c:162,175 – 1991/0728/sys/src/9/pc/devfloppy.c:160,172 | ||
| 1991/0727 | { Drive *dp; | |
| 1991/0728 | if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(dp)){ | |
| 1991/0727 | floppystop(dp); | |
| 1991/0728 | qunlock(dp); } | |
| 1991/0727 | } | |
| 1991/0727/sys/src/9/pc/devfloppy.c:341,358 – 1991/0728/sys/src/9/pc/devfloppy.c:338,360 | ||
| 1991/0727 | } void | |
| 1991/0728 | floppyreset(void) | |
| 1991/0727 | { Drive *dp; for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ | |
| 1991/0728 | dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ | |
| 1991/0727 | dp->motoron = 1; | |
| 1991/0728 | dp->cyl = -1; | |
| 1991/0727 | floppystop(dp); } | |
| 1991/0728 | } void floppyinit(void) { kproc(floppykproc, 0); | |
| 1991/0727 | } void | |
| 1991/0728/sys/src/9/pc/devfloppy.c:163,169 – 1991/0729/sys/src/9/pc/devfloppy.c:163,170 (short | long) | ||
| 1991/0727 | for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){ | |
| 1991/0728 | if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(dp)){ | |
| 1991/0727 |
| |
| 1991/0729 | if(TK2SEC(m->ticks - dp->lasttouched) > 5) floppystop(dp); | |
| 1991/0728 | qunlock(dp); } | |
| 1991/0727 | } | |
| 1991/0729/sys/src/9/pc/devfloppy.c:253,273 – 1991/0730/sys/src/9/pc/devfloppy.c:253,258 (short | long) | ||
| 1991/0727 | dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes] *dp->t->sectors; } | |
| 1991/0730/sys/src/9/pc/devfloppy.c:29,35 – 1991/0731/sys/src/9/pc/devfloppy.c:29,35 (short | long) | ||
| 1991/0727 | Fwrite= 0x47, /* write cmd */ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ | |
| 1991/0731 | Ndrive= 4, /* floppies/controller */ | |
| 1991/0727 | ||
| 1991/0728 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0730/sys/src/9/pc/devfloppy.c:46,53 – 1991/0731/sys/src/9/pc/devfloppy.c:46,53 | ||
| 1991/0728 | /* file types */ Qdir= 0, | |
| 1991/0731 | Qdata= 1, Qstruct= 2, | |
| 1991/0727 | }; /* | |
| 1991/0730/sys/src/9/pc/devfloppy.c:62,84 – 1991/0731/sys/src/9/pc/devfloppy.c:62,102 | ||
| 1991/0727 | int steps; /* steps per cylinder */ int tracks; /* tracks/disk */ int gpl; /* intersector gap length for read/write */ | |
| 1991/0731 | 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 */ | |
| 1991/0727 | long cap; /* drive capacity in bytes */ }; Type floppytype[] = { | |
| 1991/0731 | { "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, }, | |
| 1991/0727 | }; | |
| 1991/0731 | #define NTYPES (sizeof(floppytype)/sizeof(Type)) /* * bytes/sector encoding for the controller, index is (bytes per sector/128) */ static int b2c[] = | |
| 1991/0727 | { | |
| 1991/0731 | [1] 0, [2] 1, [4] 2, [8] 3, }; static int c2b[] = { | |
| 1991/0727 | 128, 256, 512, | |
| 1991/0731 | 1024, | |
| 1991/0727 | }; /* | |
| 1991/0730/sys/src/9/pc/devfloppy.c:86,92 – 1991/0731/sys/src/9/pc/devfloppy.c:104,111 | ||
| 1991/0727 | */ struct Drive { | |
| 1991/0731 | QLock; /* exclusive access to the drive */ | |
| 1991/0727 | Type *t; int dev; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:99,108 – 1991/0731/sys/src/9/pc/devfloppy.c:118,127 | ||
| 1991/0727 | int tcyl; /* target cylinder */ int thead; /* target head */ int tsec; /* target sector */ | |
| 1991/0731 | long len; /* size of xfer */ | |
| 1991/0727 | int busy; /* true if drive is seeking */ | |
| 1991/0731 | Rendez r; /* waiting here for motor to spin up */ | |
| 1991/0727 | }; /* | |
| 1991/0730/sys/src/9/pc/devfloppy.c:110,139 – 1991/0731/sys/src/9/pc/devfloppy.c:129,261 | ||
| 1991/0727 | */ struct Controller { | |
| 1991/0731 | QLock; /* exclusive access to the contoller */ Drive d[Ndrive]; /* the floppy drives */ | |
| 1991/0727 | int busy; /* true if a read or write in progress */ uchar stat[8]; /* status of an operation */ int confused; | |
| 1991/0731 | int intr; /* true if interrupt occured */ Rendez r; /* wait here for command termination */ | |
| 1991/0727 | }; | |
| 1991/0728 | Controller floppy; | |
| 1991/0727 | /* | |
| 1991/0731 | * 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; } /* | |
| 1991/0727 | * 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. */ | |
| 1991/0731 | static void motoron(Drive *dp) | |
| 1991/0727 | { int cmd; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:146,153 – 1991/0731/sys/src/9/pc/devfloppy.c:268,275 | ||
| 1991/0727 | /* * stop the floppy if it hasn't been used in 5 seconds */ | |
| 1991/0731 | static void motoroff(Drive *dp) | |
| 1991/0727 | { int cmd; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:155,176 – 1991/0731/sys/src/9/pc/devfloppy.c:277,301 | ||
| 1991/0727 | outb(Fmotor, cmd); dp->motoron = 0; } | |
| 1991/0731 | static void floppykproc(void *a) | |
| 1991/0727 | { Drive *dp; | |
| 1991/0731 | for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ | |
| 1991/0728 | if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(dp)){ | |
| 1991/0729 | if(TK2SEC(m->ticks - dp->lasttouched) > 5) | |
| 1991/0731 | motoroff(dp); | |
| 1991/0728 | qunlock(dp); } | |
| 1991/0727 | } } | |
| 1991/0731 | /* * send a byte to the floppy */ static int | |
| 1991/0727 | floppysend(int data) { int tries; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:193,199 – 1991/0731/sys/src/9/pc/devfloppy.c:318,327 | ||
| 1991/0727 | return -1; } | |
| 1991/0731 | /* * get a byte from the floppy */ static int | |
| 1991/0727 | floppyrcv(void) { int tries; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:215,222 – 1991/0731/sys/src/9/pc/devfloppy.c:343,353 | ||
| 1991/0727 | return -1; } | |
| 1991/0731 | /* * read a command result message from the floppy */ static int floppyresult(int n) | |
| 1991/0727 | { int i; int c; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:230,243 – 1991/0731/sys/src/9/pc/devfloppy.c:361,379 | ||
| 1991/0727 | return 0; } | |
| 1991/0731 | /* * 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) | |
| 1991/0727 | { int lsec; int end; int cyl; | |
| 1991/0731 | lsec = dp->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/0730/sys/src/9/pc/devfloppy.c:246,261 – 1991/0731/sys/src/9/pc/devfloppy.c:382,401 | ||
| 1991/0727 | * can't read across cylinder boundaries. * if so, decrement the bytes to be read. */ | |
| 1991/0731 | lsec = (dp->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; dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes | |
| 1991/0727 | *dp->t->sectors; } } | |
| 1991/0731 | /* * get the interrupt cause from the floppy. we need to do this * after seeks and recalibrations since they don't return results. */ static int | |
| 1991/0727 | floppysense(Drive *dp) { /* | |
| 1991/0730/sys/src/9/pc/devfloppy.c:265,271 – 1991/0731/sys/src/9/pc/devfloppy.c:405,411 | ||
| 1991/0727 | floppy.confused = 1; return -1; } | |
| 1991/0731 | if(floppyresult(2) < 0){ | |
| 1991/0727 | floppy.confused = 1; dp->confused = 1; return -1; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:282,288 – 1991/0731/sys/src/9/pc/devfloppy.c:422,440 | ||
| 1991/0727 | return 0; } | |
| 1991/0731 | /* * 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 | |
| 1991/0727 | floppyrecal(Drive *dp) { floppy.intr = 0; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:291,297 – 1991/0731/sys/src/9/pc/devfloppy.c:443,449 | ||
| 1991/0727 | floppy.confused = 0; return -1; } | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | /* * get return values | |
| 1991/0730/sys/src/9/pc/devfloppy.c:323,355 – 1991/0731/sys/src/9/pc/devfloppy.c:475,491 | ||
| 1991/0727 | return 0; } | |
| 1991/0731 | /* * if the controller or a specific drive is in a confused state, * reset it and get back to a kown state */ | |
| 1991/0727 | void | |
| 1991/0728 |
| |
| 1991/0731 | floppyrevive(void) | |
| 1991/0727 | { Drive *dp; | |
| 1991/0728 |
| |
| 1991/0727 |
| |
| 1991/0728 |
| |
| 1991/0727 |
| |
| 1991/0728 |
| |
| 1991/0727 |
| |
| 1991/0731 | * reset the floppy if it's confused | |
| 1991/0727 | */ if(floppy.confused){ /* reset controller and turn all motors off */ | |
| 1991/0730/sys/src/9/pc/devfloppy.c:359,369 – 1991/0731/sys/src/9/pc/devfloppy.c:495,505 | ||
| 1991/0727 | delay(1); outb(Fmotor, Fintena|Fena); spllo(); | |
| 1991/0731 | for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){ | |
| 1991/0727 | dp->motoron = 0; dp->confused = 1; } | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | floppy.confused = 0; } | |
| 1991/0730/sys/src/9/pc/devfloppy.c:370,376 – 1991/0731/sys/src/9/pc/devfloppy.c:506,512 | ||
| 1991/0727 | /* * recalibrate any confused drives */ | |
| 1991/0731 | for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Ndrive]; dp++){ | |
| 1991/0727 | if(dp->confused == 0) floppyrecal(dp); | |
| 1991/0730/sys/src/9/pc/devfloppy.c:378,396 – 1991/0731/sys/src/9/pc/devfloppy.c:514,522 | ||
| 1991/0727 | } | |
| 1991/0731 | static long floppyseek(Drive *dp) | |
| 1991/0727 | { | |
| 1991/0730/sys/src/9/pc/devfloppy.c:400,406 – 1991/0731/sys/src/9/pc/devfloppy.c:526,532 | ||
| 1991/0727 | * tell floppy to seek */ if(floppysend(Fseek) < 0 | |
| 1991/0731 | || floppysend((dp->thead<<2) | dp->dev) < 0 | |
| 1991/0727 | || floppysend(dp->tcyl * dp->t->steps) < 0){ print("seek cmd failed\n"); floppy.confused = 1; | |
| 1991/0730/sys/src/9/pc/devfloppy.c:410,416 – 1991/0731/sys/src/9/pc/devfloppy.c:536,542 | ||
| 1991/0727 | /* * wait for interrupt */ | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | /* * get floppy status | |
| 1991/0730/sys/src/9/pc/devfloppy.c:441,482 – 1991/0731/sys/src/9/pc/devfloppy.c:567,613 | ||
| 1991/0727 | return dp->offset; } | |
| 1991/0731 | static long | |
| 1991/0727 | floppyxfer(Drive *dp, int cmd, void *a, long n) { | |
| 1991/0731 | qlock(&floppy); qlock(dp); if(waserror){ qunlock(&floppy); qunlock(dp); } | |
| 1991/0727 | /* | |
| 1991/0731 | * get floppy reset and spinning | |
| 1991/0727 | */ | |
| 1991/0731 | if(floppy.confused || dp->confused) floppyrevive(); if(!dp->motoron) motoron(dp); | |
| 1991/0727 | ||
| 1991/0731 | /* * calculate new position and seek to it (dp->len may be trimmed) */ | |
| 1991/0727 | dp->len = n; | |
| 1991/0731 | floppypos(dp); if(floppyseek(dp) < 0) errors("seeking floppy"); | |
| 1991/0727 |
| |
| 1991/0731 | print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", | |
| 1991/0727 | dp->tcyl, dp->thead, dp->tsec, addr, n);/**/ /* | |
| 1991/0731 | * set up the dma (dp->len may be trimmed) | |
| 1991/0727 | */ | |
| 1991/0731 | dp->len = dmasetup(2, a, dp->len, cmd==Fread); | |
| 1991/0727 | /* | |
| 1991/0731 | * start operation | |
| 1991/0727 | */ cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); if(floppysend(cmd) < 0 | |
| 1991/0730/sys/src/9/pc/devfloppy.c:484,507 – 1991/0731/sys/src/9/pc/devfloppy.c:615,638 | ||
| 1991/0727 | || floppysend(dp->tcyl * dp->t->steps) < 0 || floppysend(dp->thead) < 0 || floppysend(dp->tsec) < 0 | |
| 1991/0731 | || floppysend(dp->t->bcode) < 0 | |
| 1991/0727 | || floppysend(dp->t->sectors) < 0 || floppysend(dp->t->gpl) < 0 || floppysend(0xFF) < 0){ print("xfer cmd failed\n"); floppy.confused = 1; | |
| 1991/0731 | errors("floppy command failed"); | |
| 1991/0727 | } | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | /* * get status */ | |
| 1991/0731 | if(floppyresult(7) < 0){ print("xfer status failed\n"); | |
| 1991/0727 | floppy.confused = 1; | |
| 1991/0731 | errors("floppy result failed"); | |
| 1991/0727 | } if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){ | |
| 1991/0730/sys/src/9/pc/devfloppy.c:508,547 – 1991/0731/sys/src/9/pc/devfloppy.c:639,667 | ||
| 1991/0727 | print("xfer failed %lux %lux %lux\n", floppy.stat[0], floppy.stat[1], floppy.stat[2]); dp->confused = 1; | |
| 1991/0731 | errors("floppy drive lost"); | |
| 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 | if(offset != dp->offset+n){ | |
| 1991/0731 | print("new offset %d instead of %d\n", offset, dp->offset+dp->len); | |
| 1991/0727 | dp->confused = 1; | |
| 1991/0731 | errors("floppy drive lost"); | |
| 1991/0727 | } | |
| 1991/0731 | qunlock(&floppy); qunlock(dp); poperror(); | |
| 1991/0727 | dp->offset += dp->len; return dp->len; } | |
| 1991/0731 | static void | |
| 1991/0727 | floppyintr(Ureg *ur) { floppy.intr = 1; | |
| 1991/0731 | wakeup(&floppy.r); | |
| 1991/0727 | } | |
| 1991/0731/sys/src/9/pc/devfloppy.c:4,14 – 1991/0802/sys/src/9/pc/devfloppy.c:4,14 (short | long) | ||
| 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 |
| |
| 1991/0802/sys/src/9/pc/devfloppy.c:367,372 – 1991/0803/sys/src/9/pc/devfloppy.c:367,373 (short | long) | ||
| 1991/0731 | floppykproc(void *a) | |
| 1991/0727 | { Drive *dp; | |
| 1991/0803 | int disp = 0; | |
| 1991/0727 | ||
| 1991/0802 | waserror(); for(;;){ | |
| 1991/0802/sys/src/9/pc/devfloppy.c:378,384 – 1991/0803/sys/src/9/pc/devfloppy.c:379,391 | ||
| 1991/0802 | qunlock(dp); } | |
| 1991/0728 | } | |
| 1991/0803 | disp++; if(owl(disp&1) < 0) print("owl failed\n"); if(mail((disp>>1)&1) < 0) print("mail failed\n"); | |
| 1991/0802 | tsleep(&floppy.kr, return0, 0, 5*1000); | |
| 1991/0803 | ||
| 1991/0727 | } } | |
| 1991/0803/sys/src/9/pc/devfloppy.c:754,759 – 1991/0806/sys/src/9/pc/devfloppy.c:754,760 (short | long) | ||
| 1991/0731 | static void | |
| 1991/0727 | floppyintr(Ureg *ur) { | |
| 1991/0806 | print("floppy intr\n"); | |
| 1991/0727 | floppy.intr = 1; | |
| 1991/0731 | wakeup(&floppy.r); | |
| 1991/0727 | } | |
| 1991/0806/sys/src/9/pc/devfloppy.c:29,36 – 1991/0809/sys/src/9/pc/devfloppy.c:29,34 (short | long) | ||
| 1991/0727 | Fwrite= 0x47, /* write cmd */ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ | |
| 1991/0731 |
| |
| 1991/0727 | ||
| 1991/0728 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0727 | /* sector size encodings */ | |
| 1991/0806/sys/src/9/pc/devfloppy.c:123,128 – 1991/0809/sys/src/9/pc/devfloppy.c:121,129 | ||
| 1991/0731 | long len; /* size of xfer */ | |
| 1991/0727 | ||
| 1991/0731 | Rendez r; /* waiting here for motor to spin up */ | |
| 1991/0809 | uchar *ccache; /* cylinder cache (always read a whole cyl) */ int ccyl; /* number of cached cylinder */ | |
| 1991/0727 | }; /* | |
| 1991/0806/sys/src/9/pc/devfloppy.c:132,138 – 1991/0809/sys/src/9/pc/devfloppy.c:133,139 | ||
| 1991/0727 | { | |
| 1991/0731 | QLock; /* exclusive access to the contoller */ | |
| 1991/0809 | Drive *d; /* the floppy drives */ | |
| 1991/0727 | uchar stat[8]; /* status of an operation */ int confused; | |
| 1991/0731 | int intr; /* true if interrupt occured */ | |
| 1991/0806/sys/src/9/pc/devfloppy.c:173,178 – 1991/0809/sys/src/9/pc/devfloppy.c:174,180 | ||
| 1991/0802 | }; #define NFDIR (sizeof(floppydir)/sizeof(Dirtab)) | |
| 1991/0731 | ||
| 1991/0809 | #define k64(x) (((ulong)(x))>>16) | |
| 1991/0731 | void floppyreset(void) { | |
| 1991/0806/sys/src/9/pc/devfloppy.c:188,196 – 1991/0809/sys/src/9/pc/devfloppy.c:190,203 | ||
| 1991/0802 | } /* | |
| 1991/0809 | * allocate the drive storage */ floppy.d = ialloc(conf.nfloppy*sizeof(Drive), 0); /* | |
| 1991/0802 | * stop the motors */ | |
| 1991/0731 |
| |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0731 | dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ | |
| 1991/0802 | floppydir[2*dp->dev].length = dp->t->cap; | |
| 1991/0806/sys/src/9/pc/devfloppy.c:198,203 – 1991/0809/sys/src/9/pc/devfloppy.c:205,220 | ||
| 1991/0802 | dp->cyl = -1; /* because we don't know */ | |
| 1991/0731 | motoroff(dp); } | |
| 1991/0809 | /* * 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; } | |
| 1991/0731 | setvec(Floppyvec, floppyintr); } | |
| 1991/0806/sys/src/9/pc/devfloppy.c:272,282 – 1991/0809/sys/src/9/pc/devfloppy.c:289,304 | ||
| 1991/0802 | a[3] = x; } | |
| 1991/0809 | /* * the floppy is so slow, we always read a cylinder * at a time and cache the extra bytes. */ | |
| 1991/0731 | long floppyread(Chan *c, void *a, long n) { Drive *dp; | |
| 1991/0809 | long rv, nn, len, cyl; int sec; | |
| 1991/0731 | uchar *aa = a; | |
| 1991/0802 | if(c->qid.path == CHDIR) | |
| 1991/0806/sys/src/9/pc/devfloppy.c:286,295 – 1991/0809/sys/src/9/pc/devfloppy.c:308,338 | ||
| 1991/0802 | dp = &floppy.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0809 | 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); | |
| 1991/0802 | } break; case Qstruct: | |
| 1991/0806/sys/src/9/pc/devfloppy.c:371,377 – 1991/0809/sys/src/9/pc/devfloppy.c:414,420 | ||
| 1991/0727 | ||
| 1991/0802 | waserror(); for(;;){ | |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0802 | if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(dp)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) | |
| 1991/0806/sys/src/9/pc/devfloppy.c:382,389 – 1991/0809/sys/src/9/pc/devfloppy.c:425,430 | ||
| 1991/0803 | disp++; if(owl(disp&1) < 0) print("owl failed\n"); | |
| 1991/0802 | tsleep(&floppy.kr, return0, 0, 5*1000); | |
| 1991/0803 | ||
| 1991/0727 | } | |
| 1991/0806/sys/src/9/pc/devfloppy.c:592,598 – 1991/0809/sys/src/9/pc/devfloppy.c:633,639 | ||
| 1991/0727 | delay(1); outb(Fmotor, Fintena|Fena); spllo(); | |
| 1991/0731 |
| |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0727 | dp->motoron = 0; dp->confused = 1; } | |
| 1991/0806/sys/src/9/pc/devfloppy.c:603,609 – 1991/0809/sys/src/9/pc/devfloppy.c:644,650 | ||
| 1991/0727 | /* * recalibrate any confused drives */ | |
| 1991/0731 |
| |
| 1991/0809 | for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0727 | if(dp->confused == 0) floppyrecal(dp); | |
| 1991/0809/sys/src/9/pc/devfloppy.c:180,185 – 1991/0810/sys/src/9/pc/devfloppy.c:180,186 (short | long) | ||
| 1991/0731 | { Drive *dp; | |
| 1991/0802 | Type *t; | |
| 1991/0810 | int n; | |
| 1991/0731 | ||
| 1991/0802 | /* * init dependent parameters | |
| 1991/0809/sys/src/9/pc/devfloppy.c:211,218 – 1991/0810/sys/src/9/pc/devfloppy.c:212,220 | ||
| 1991/0809 | */ for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ do { | |
| 1991/0810 | n = 512 * 18 * 2; /* MF2HD cylinder size */ dp->ccache = ialloc(n, 1); } while(k64(dp->ccache) != k64(dp->ccache+n)); | |
| 1991/0809 | dp->ccyl = -1; } | |
| 1991/0731 | setvec(Floppyvec, floppyintr); | |
| 1991/0810/sys/src/9/pc/devfloppy.c:172,178 – 1991/0811/sys/src/9/pc/devfloppy.c:172,178 (short | long) | ||
| 1991/0802 | "fd3data", {Qdata + 3}, 0, 0600, "fd3struct", {Qstruct + 3}, 8, 0600, }; | |
| 1991/0811 | #define NFDIR 2 /* directory entries/drive */ | |
| 1991/0731 | ||
| 1991/0809 | #define k64(x) (((ulong)(x))>>16) | |
| 1991/0731 | void | |
| 1991/0810/sys/src/9/pc/devfloppy.c:201,207 – 1991/0811/sys/src/9/pc/devfloppy.c:201,207 | ||
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0731 | dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ | |
| 1991/0802 |
| |
| 1991/0811 | floppydir[NFDIR*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); | |
| 1991/0810/sys/src/9/pc/devfloppy.c:244,262 – 1991/0811/sys/src/9/pc/devfloppy.c:244,262 | ||
| 1991/0802 | int floppywalk(Chan *c, char *name) { | |
| 1991/0811 | return devwalk(c, name, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | } void floppystat(Chan *c, char *dp) { | |
| 1991/0811 | devstat(c, dp, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | } Chan* floppyopen(Chan *c, int omode) { | |
| 1991/0811 | return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | } void | |
| 1991/0810/sys/src/9/pc/devfloppy.c:304,310 – 1991/0811/sys/src/9/pc/devfloppy.c:304,310 | ||
| 1991/0731 | uchar *aa = a; | |
| 1991/0802 | if(c->qid.path == CHDIR) | |
| 1991/0811 | return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | rv = 0; dp = &floppy.d[c->qid.path & ~Qmask]; | |
| 1991/0811/sys/src/9/pc/devfloppy.c:31,42 – 1991/0823/sys/src/9/pc/devfloppy.c:31,36 (short | long) | ||
| 1991/0727 | ||
| 1991/0728 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0727 |
| |
| 1991/0811/sys/src/9/pc/devfloppy.c:45,51 – 1991/0823/sys/src/9/pc/devfloppy.c:39,44 | ||
| 1991/0728 | /* file types */ Qdir= 0, | |
| 1991/0802 | Qdata= (1<<2), | |
| 1991/0727 | }; | |
| 1991/0811/sys/src/9/pc/devfloppy.c:163,176 – 1991/0823/sys/src/9/pc/devfloppy.c:156,165 | ||
| 1991/0731 | static void floppyintr(Ureg*); | |
| 1991/0802 | Dirtab floppydir[]={ | |
| 1991/0823 | "fd0disk", {Qdata + 0}, 0, 0600, "fd1disk", {Qdata + 1}, 0, 0600, "fd2disk", {Qdata + 2}, 0, 0600, "fd3disk", {Qdata + 3}, 0, 0600, | |
| 1991/0802 | }; | |
| 1991/0811 | #define NFDIR 2 /* directory entries/drive */ | |
| 1991/0731 | ||
| 1991/0811/sys/src/9/pc/devfloppy.c:337,351 – 1991/0823/sys/src/9/pc/devfloppy.c:326,331 | ||
| 1991/0809 | memmove(aa+rv, dp->ccache + (sec-1)*dp->t->bytes, len); | |
| 1991/0802 | } break; | |
| 1991/0731 | } | |
| 1991/0811/sys/src/9/pc/devfloppy.c:369,377 – 1991/0823/sys/src/9/pc/devfloppy.c:349,354 | ||
| 1991/0802 | break; } break; | |
| 1991/0731 | } | |
| 1991/0811/sys/src/9/pc/devfloppy.c:733,739 – 1991/0823/sys/src/9/pc/devfloppy.c:710,716 | ||
| 1991/0731 | if(floppyseek(dp) < 0) errors("seeking floppy"); | |
| 1991/0727 | ||
| 1991/0731 |
| |
| 1991/0823 | /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", | |
| 1991/0727 | dp->tcyl, dp->thead, dp->tsec, addr, n);/**/ /* | |
| 1991/0811/sys/src/9/pc/devfloppy.c:797,803 – 1991/0823/sys/src/9/pc/devfloppy.c:774,780 | ||
| 1991/0731 | static void | |
| 1991/0727 | floppyintr(Ureg *ur) { | |
| 1991/0806 |
| |
| 1991/0823 | /*print("floppy intr\n");/**/ | |
| 1991/0727 | floppy.intr = 1; | |
| 1991/0731 | wakeup(&floppy.r); | |
| 1991/0727 | } | |
| 1991/0823/sys/src/9/pc/devfloppy.c:26,34 – 1991/0831/sys/src/9/pc/devfloppy.c:26,37 (short | long) | ||
| 1991/0727 | Fseek= 0xf, /* seek cmd */ Fsense= 0x8, /* sense cmd */ Fread= 0x66, /* read cmd */ | |
| 1991/0831 | Fwrite= 0x45, /* write cmd */ | |
| 1991/0727 | Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ | |
| 1991/0831 | Fchanged= 0x3F7, /* disk changed register */ Fchange= 0x80, /* disk has changed */ | |
| 1991/0728 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0727 | /* status 0 byte */ | |
| 1991/0823/sys/src/9/pc/devfloppy.c:281,286 – 1991/0831/sys/src/9/pc/devfloppy.c:284,301 | ||
| 1991/0802 | } | |
| 1991/0809 | /* | |
| 1991/0831 | * look for a floppy change */ void floppychange(Drive *dp) { if((inb(Fchanged) & Fchange) == 0) return; } /* | |
| 1991/0809 | * the floppy is so slow, we always read a cylinder * at a time and cache the extra bytes. */ | |
| 1991/0823/sys/src/9/pc/devfloppy.c:299,304 – 1991/0831/sys/src/9/pc/devfloppy.c:314,320 | ||
| 1991/0802 | dp = &floppy.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0831 | floppychanged(dp); | |
| 1991/0809 | if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) | |
| 1991/0823/sys/src/9/pc/devfloppy.c:343,348 – 1991/0831/sys/src/9/pc/devfloppy.c:359,366 | ||
| 1991/0802 | dp = &floppy.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0831 | floppychanged(dp); dp->ccyl = -1; | |
| 1991/0802 | for(rv = 0; rv < n; rv += i){ i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv); if(i <= 0) | |
| 1991/0831/sys/src/9/pc/devfloppy.c:287,293 – 1991/0902/sys/src/9/pc/devfloppy.c:287,293 (short | long) | ||
| 1991/0831 | * look for a floppy change */ void | |
| 1991/0902 | floppychanged(Drive *dp) | |
| 1991/0831 | { if((inb(Fchanged) & Fchange) == 0) return; | |
| 1991/0902/sys/src/9/pc/devfloppy.c:700,710 – 1991/0906/sys/src/9/pc/devfloppy.c:700,707 (short | long) | ||
| 1991/0731 | static long | |
| 1991/0802 | floppyxfer(Drive *dp, int cmd, void *a, long off, long n) | |
| 1991/0727 | { | |
| 1991/0731 | qlock(&floppy); qlock(dp); | |
| 1991/0802 | if(waserror()){ | |
| 1991/0902/sys/src/9/pc/devfloppy.c:728,735 – 1991/0906/sys/src/9/pc/devfloppy.c:725,733 | ||
| 1991/0731 | if(floppyseek(dp) < 0) errors("seeking floppy"); | |
| 1991/0727 | ||
| 1991/0906 | ||
| 1991/0823 | /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", | |
| 1991/0727 |
| |
| 1991/0906 | dp->tcyl, dp->thead, dp->tsec, a, n);/**/ | |
| 1991/0727 | /* | |
| 1991/0731 | * set up the dma (dp->len may be trimmed) | |
| 1991/0906/sys/src/9/pc/devfloppy.c:420,427 – 1991/0913/sys/src/9/pc/devfloppy.c:420,425 (short | long) | ||
| 1991/0802 | } | |
| 1991/0728 | } | |
| 1991/0803 | disp++; | |
| 1991/0802 | tsleep(&floppy.kr, return0, 0, 5*1000); | |
| 1991/0803 | ||
| 1991/0727 | } | |
| 1991/0913/sys/src/9/pc/devfloppy.c:409,415 – 1991/0919/sys/src/9/pc/devfloppy.c:409,416 (short | long) | ||
| 1991/0727 | Drive *dp; | |
| 1991/0803 | int disp = 0; | |
| 1991/0727 | ||
| 1991/0802 |
| |
| 1991/0919 | while(waserror()) ; | |
| 1991/0802 | for(;;){ | |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0802 | if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5 | |
| 1991/0919/sys/src/9/pc/devfloppy.c:6,11 – 1991/0920/sys/src/9/pc/devfloppy.c:6,13 (short | long) | ||
| 1991/0727 | #include "io.h" | |
| 1991/0802 | #include "errno.h" | |
| 1991/0727 | ||
| 1991/0920 | /* NEC PD765A (8272A compatible) floppy controller */ | |
| 1991/0802 | typedef struct Drive Drive; | |
| 1991/0727 | typedef struct Controller Controller; | |
| 1991/0802 | typedef struct Type Type; | |
| 1991/0919/sys/src/9/pc/devfloppy.c:42,47 – 1991/0920/sys/src/9/pc/devfloppy.c:44,50 | ||
| 1991/0728 | /* file types */ Qdir= 0, | |
| 1991/0802 | Qdata= (1<<2), | |
| 1991/0920 | Qctl= (2<<2), | |
| 1991/0802 | Qmask= (3<<2), | |
| 1991/0727 | }; | |
| 1991/0919/sys/src/9/pc/devfloppy.c:160,168 – 1991/0920/sys/src/9/pc/devfloppy.c:163,175 | ||
| 1991/0731 | ||
| 1991/0802 | Dirtab floppydir[]={ | |
| 1991/0823 | "fd0disk", {Qdata + 0}, 0, 0600, | |
| 1991/0920 | "fd0ctl", {Qctl + 0}, 0, 0600, | |
| 1991/0823 | "fd1disk", {Qdata + 1}, 0, 0600, | |
| 1991/0920 | "fd1ctl", {Qctl + 1}, 0, 0600, | |
| 1991/0823 | "fd2disk", {Qdata + 2}, 0, 0600, | |
| 1991/0920 | "fd2ctl", {Qctl + 2}, 0, 0600, | |
| 1991/0823 | "fd3disk", {Qdata + 3}, 0, 0600, | |
| 1991/0920 | "fd3ctl", {Qctl + 3}, 0, 0600, | |
| 1991/0802 | }; | |
| 1991/0811 | #define NFDIR 2 /* directory entries/drive */ | |
| 1991/0731 | ||
| 1991/0919/sys/src/9/pc/devfloppy.c:215,229 – 1991/0920/sys/src/9/pc/devfloppy.c:222,241 | ||
| 1991/0731 | void floppyinit(void) { | |
| 1991/0802 |
| |
| 1991/0731 | } | |
| 1991/0802 | Chan* floppyattach(char *spec) { | |
| 1991/0920 | static int kstarted; if(kstarted == 0){ /* * watchdog to turn off the motors */ kstarted = 1; kproc("floppy", floppykproc, 0); } | |
| 1991/0802 | return devattach('f', spec); } | |
| 1991/0919/sys/src/9/pc/devfloppy.c:274,288 – 1991/0920/sys/src/9/pc/devfloppy.c:286,291 | ||
| 1991/0802 | error(Eperm); } | |
| 1991/0809 | /* | |
| 1991/0831 | * look for a floppy change */ | |
| 1991/0919/sys/src/9/pc/devfloppy.c:292,298 – 1991/0920/sys/src/9/pc/devfloppy.c:295,301 | ||
| 1991/0831 | if((inb(Fchanged) & Fchange) == 0) return; | |
| 1991/0920 | print("floppy has changed\n"); | |
| 1991/0831 | } /* | |
| 1991/0920/sys/src/9/pc/devfloppy.c:110,116 – 1991/0921/sys/src/9/pc/devfloppy.c:110,115 (short | long) | ||
| 1991/0727 | int dev; ulong lasttouched; /* time last touched */ | |
| 1991/0920/sys/src/9/pc/devfloppy.c:137,142 – 1991/0921/sys/src/9/pc/devfloppy.c:136,142 | ||
| 1991/0727 | int confused; | |
| 1991/0731 | int intr; /* true if interrupt occured */ Rendez r; /* wait here for command termination */ | |
| 1991/0921 | int motor; | |
| 1991/0802 | Rendez kr; /* for motor watcher */ | |
| 1991/0727 | }; | |
| 1991/0920/sys/src/9/pc/devfloppy.c:143,148 – 1991/0921/sys/src/9/pc/devfloppy.c:143,150 | ||
| 1991/0727 | ||
| 1991/0728 | Controller floppy; | |
| 1991/0727 | ||
| 1991/0921 | #define MOTORBIT(i) (1<<((i)+4)) | |
| 1991/0727 | /* | |
| 1991/0731 | * predeclared */ | |
| 1991/0920/sys/src/9/pc/devfloppy.c:201,207 – 1991/0921/sys/src/9/pc/devfloppy.c:203,209 | ||
| 1991/0731 | dp->dev = dp - floppy.d; dp->t = &floppytype[0]; /* default type */ | |
| 1991/0811 | floppydir[NFDIR*dp->dev].length = dp->t->cap; | |
| 1991/0731 |
| |
| 1991/0921 | floppy.motor |= MOTORBIT(dp->dev); | |
| 1991/0802 | dp->cyl = -1; /* because we don't know */ | |
| 1991/0731 | motoroff(dp); } | |
| 1991/0920/sys/src/9/pc/devfloppy.c:376,412 – 1991/0921/sys/src/9/pc/devfloppy.c:378,384 | ||
| 1991/0731 | return rv; } | |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0731 | static void | |
| 1991/0727 |
| |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0727 | { Drive *dp; | |
| 1991/0920/sys/src/9/pc/devfloppy.c:416,422 – 1991/0921/sys/src/9/pc/devfloppy.c:388,395 | ||
| 1991/0919 | ; | |
| 1991/0802 | for(;;){ | |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0802 |
| |
| 1991/0921 | if((floppy.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5 | |
| 1991/0802 | && canqlock(dp)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) motoroff(dp); | |
| 1991/0920/sys/src/9/pc/devfloppy.c:429,435 – 1991/0921/sys/src/9/pc/devfloppy.c:402,448 | ||
| 1991/0727 | } } | |
| 1991/0921 | static void driveselect(Drive *dp) { int cmd; cmd = floppy.motor | Fintena | Fena | dp->dev; outb(Fmotor, cmd); } | |
| 1991/0731 | /* | |
| 1991/0921 | * 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); } /* | |
| 1991/0731 | * send a byte to the floppy */ static int | |
| 1991/0920/sys/src/9/pc/devfloppy.c:633,641 – 1991/0921/sys/src/9/pc/devfloppy.c:646,654 | ||
| 1991/0727 | outb(Fmotor, Fintena|Fena); spllo(); | |
| 1991/0809 | for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){ | |
| 1991/0727 |
| |
| 1991/0921 | floppy.motor = 0; | |
| 1991/0731 | sleep(&floppy.r, interrupted, 0); | |
| 1991/0727 | floppy.confused = 0; } | |
| 1991/0920/sys/src/9/pc/devfloppy.c:716,723 – 1991/0921/sys/src/9/pc/devfloppy.c:729,735 | ||
| 1991/0727 | */ | |
| 1991/0731 | if(floppy.confused || dp->confused) floppyrevive(); | |
| 1991/0921 | motoron(dp); | |
| 1991/0727 | ||
| 1991/0731 | /* * calculate new position and seek to it (dp->len may be trimmed) | |
| 1991/0921/sys/src/9/pc/devfloppy.c:6,41 – 1991/0924/sys/src/9/pc/devfloppy.c:6,47 (short | long) | ||
| 1991/0727 | #include "io.h" | |
| 1991/0802 | #include "errno.h" | |
| 1991/0727 | ||
| 1991/0920 |
| |
| 1991/0924 | /* Intel 82077A (8272A compatible) floppy controller */ | |
| 1991/0920 | ||
| 1991/0802 | typedef struct Drive Drive; | |
| 1991/0727 | typedef struct Controller Controller; | |
| 1991/0802 | typedef struct Type Type; | |
| 1991/0727 | ||
| 1991/0924 | /* bits in the registers */ | |
| 1991/0727 | enum { | |
| 1991/0924 | /* digital output register */ Pdor= 0x3f2, Fintena= 0x8, /* enable floppy interrupt */ Fena= 0x4, /* 0 == reset controller */ | |
| 1991/0727 |
| |
| 1991/0924 | /* main status register */ Pmsr= 0x3f4, Fready= 0x80, /* ready to be touched */ Ffrom= 0x40, /* data from controller */ Fbusy= 0x10, /* operation not over */ | |
| 1991/0727 |
| |
| 1991/0831 |
| |
| 1991/0727 |
| |
| 1991/0924 | /* 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 */ | |
| 1991/0727 | ||
| 1991/0831 |
| |
| 1991/0924 | /* digital input register */ Pdir= 0x3F7, /* disk changed port */ Fchange= 0x80, /* disk has changed */ | |
| 1991/0831 | ||
| 1991/0728 |
| |
| 1991/0727 | /* status 0 byte */ Drivemask= 3<<0, Seekend= 1<<5, | |
| 1991/0921/sys/src/9/pc/devfloppy.c:46,51 – 1991/0924/sys/src/9/pc/devfloppy.c:52,59 | ||
| 1991/0802 | Qdata= (1<<2), | |
| 1991/0920 | Qctl= (2<<2), | |
| 1991/0802 | Qmask= (3<<2), | |
| 1991/0924 | DMAchan= 2, /* floppy dma channel */ | |
| 1991/0727 | }; /* | |
| 1991/0921/sys/src/9/pc/devfloppy.c:68,78 – 1991/0924/sys/src/9/pc/devfloppy.c:76,88 | ||
| 1991/0731 | */ int bcode; /* coded version of bytes for the controller */ | |
| 1991/0727 | long cap; /* drive capacity in bytes */ | |
| 1991/0924 | long tsize; /* track size in bytes */ | |
| 1991/0727 | }; Type floppytype[] = { | |
| 1991/0731 | { "MF2HD", 512, 18, 2, 1, 80, 0x1B, 0x54, }, | |
| 1991/0924 | { "MF1DD", 512, 9, 2, 1, 80, 0x1B, 0x54, }, { "MF4HD", 1024, 18, 2, 1, 80, 0x1B, 0x54, }, | |
| 1991/0731 | { "F2HD", 512, 15, 2, 1, 80, 0x2A, 0x50, }, { "F2DD", 512, 8, 2, 2, 40, 0x2A, 0x50, }, { "F1DD", 512, 8, 1, 2, 40, 0x2A, 0x50, }, | |
| 1991/0921/sys/src/9/pc/devfloppy.c:111,117 – 1991/0924/sys/src/9/pc/devfloppy.c:121,127 | ||
| 1991/0727 | ulong lasttouched; /* time last touched */ int cyl; /* current cylinder */ | |
| 1991/0924 | int confused; /* needs to be recalibrated */ | |
| 1991/0727 | int tcyl; /* target cylinder */ int thead; /* target head */ | |
| 1991/0921/sys/src/9/pc/devfloppy.c:118,131 – 1991/0924/sys/src/9/pc/devfloppy.c:128,142 | ||
| 1991/0727 | int tsec; /* target sector */ | |
| 1991/0731 | long len; /* size of xfer */ | |
| 1991/0727 | ||
| 1991/0731 |
| |
| 1991/0924 | uchar *cache; /* track cache */ int ccyl; int chead; | |
| 1991/0809 |
| |
| 1991/0924 | Rendez r; /* waiting here for motor to spin up */ | |
| 1991/0727 | }; /* | |
| 1991/0924 | * controller for 4 floppys | |
| 1991/0727 | */ struct Controller { | |
| 1991/0921/sys/src/9/pc/devfloppy.c:132,147 – 1991/0924/sys/src/9/pc/devfloppy.c:143,159 | ||
| 1991/0731 | QLock; /* exclusive access to the contoller */ | |
| 1991/0809 | Drive *d; /* the floppy drives */ | |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0924 | uchar cmd[14]; /* command */ int ncmd; /* # command bytes */ uchar stat[14]; /* command status */ int nstat; /* # status bytes */ int confused; /* controler needs to be reset */ | |
| 1991/0731 | Rendez r; /* wait here for command termination */ | |
| 1991/0921 |
| |
| 1991/0802 | ||
| 1991/0924 | int motor; /* bit mask of spinning disks */ | |
| 1991/0802 | Rendez kr; /* for motor watcher */ | |
| 1991/0727 | }; | |
| 1991/0728 |
| |
| 1991/0924 | Controller fl; | |
| 1991/0727 | ||
| 1991/0921 | #define MOTORBIT(i) (1<<((i)+4)) | |
| 1991/0921/sys/src/9/pc/devfloppy.c:148,167 – 1991/0924/sys/src/9/pc/devfloppy.c:160,180 | ||
| 1991/0727 | /* | |
| 1991/0731 | * predeclared */ | |
| 1991/0924 | static int floppycmd(void); static void floppyeject(Drive*); | |
| 1991/0731 | static void floppykproc(void*); | |
| 1991/0924 | static void floppyon(Drive*); static void floppyoff(Drive*); | |
| 1991/0802 | static void floppypos(Drive*,long); | |
| 1991/0731 |
| |
| 1991/0924 | static int floppyresult(void); | |
| 1991/0731 | static void floppyrevive(void); | |
| 1991/0924 | static long floppyseek(Drive*, long); static int floppysense(void); static void floppywait(void); | |
| 1991/0802 | static long floppyxfer(Drive*, int, void*, long, long); | |
| 1991/0731 |
| |
| 1991/0924 | static int cmddone(void*); void Xdelay(int); | |
| 1991/0731 | ||
| 1991/0802 | Dirtab floppydir[]={ | |
| 1991/0823 | "fd0disk", {Qdata + 0}, 0, 0600, | |
| 1991/0921/sys/src/9/pc/devfloppy.c:175,181 – 1991/0924/sys/src/9/pc/devfloppy.c:188,193 | ||
| 1991/0802 | }; | |
| 1991/0811 | #define NFDIR 2 /* directory entries/drive */ | |
| 1991/0731 | ||
| 1991/0809 |
| |
| 1991/0731 | void floppyreset(void) { | |
| 1991/0921/sys/src/9/pc/devfloppy.c:182,187 – 1991/0924/sys/src/9/pc/devfloppy.c:194,201 | ||
| 1991/0731 | Drive *dp; | |
| 1991/0802 | Type *t; | |
| 1991/0810 | int n; | |
| 1991/0924 | ulong p; long l; | |
| 1991/0731 | ||
| 1991/0802 | /* * init dependent parameters | |
| 1991/0921/sys/src/9/pc/devfloppy.c:189,224 – 1991/0924/sys/src/9/pc/devfloppy.c:203,240 | ||
| 1991/0802 | for(t = floppytype; t < &floppytype[NTYPES]; t++){ t->cap = t->bytes * t->heads * t->sectors * t->tracks; t->bcode = b2c[t->bytes/128]; | |
| 1991/0924 | t->tsize = t->bytes * t->sectors; | |
| 1991/0802 | } /* | |
| 1991/0809 | * allocate the drive storage */ | |
| 1991/0924 | fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0); | |
| 1991/0809 | /* | |
| 1991/0802 | * stop the motors */ | |
| 1991/0809 |
| |
| 1991/0731 |
| |
| 1991/0924 | 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; | |
| 1991/0731 | dp->t = &floppytype[0]; /* default type */ | |
| 1991/0811 | floppydir[NFDIR*dp->dev].length = dp->t->cap; | |
| 1991/0921 |
| |
| 1991/0802 | dp->cyl = -1; /* because we don't know */ | |
| 1991/0731 |
| |
| 1991/0924 | dp->cache = (uchar*)ialloc(dp->t->tsize, 1); dp->ccyl = -1; | |
| 1991/0731 | } | |
| 1991/0809 | /* | |
| 1991/0924 | * first operation will recalibrate | |
| 1991/0809 | */ | |
| 1991/0810 |
| |
| 1991/0809 |
| |
| 1991/0731 |
| |
| 1991/0924 | fl.confused = 1; | |
| 1991/0731 | } void | |
| 1991/0921/sys/src/9/pc/devfloppy.c:288,380 – 1991/0924/sys/src/9/pc/devfloppy.c:304,419 | ||
| 1991/0802 | error(Eperm); } | |
| 1991/0809 |
| |
| 1991/0831 |
| |
| 1991/0902 |
| |
| 1991/0831 |
| |
| 1991/0920 |
| |
| 1991/0831 |
| |
| 1991/0809 |
| |
| 1991/0731 | long floppyread(Chan *c, void *a, long n) { Drive *dp; | |
| 1991/0809 |
| |
| 1991/0731 |
| |
| 1991/0924 | long rv, i; int nn, sec, head, cyl; long len; long noff; uchar *aa; | |
| 1991/0731 | ||
| 1991/0802 | if(c->qid.path == CHDIR) | |
| 1991/0811 | return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/0802 | switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0831 |
| |
| 1991/0809 | if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) errors("bad len"); | |
| 1991/0924 | aa = a; nn = dp->t->tsize; | |
| 1991/0809 | for(rv = 0; rv < n; rv += len){ /* | |
| 1991/0924 | * truncate xfer at track boundary | |
| 1991/0809 | */ dp->len = n - rv; floppypos(dp, c->offset+rv); cyl = dp->tcyl; | |
| 1991/0924 | head = dp->thead; | |
| 1991/0809 | len = dp->len; | |
| 1991/0924 | sec = dp->tsec; | |
| 1991/0809 | /* | |
| 1991/0924 | * read the track | |
| 1991/0809 | */ | |
| 1991/0924 | if(dp->ccyl!=cyl || dp->chead!=head){ | |
| 1991/0809 | dp->ccyl = -1; | |
| 1991/0924 | i = floppyxfer(dp, Fread, dp->cache, (cyl*dp->t->heads+head)*nn, nn); if(i != nn){ if(i == 0) break; | |
| 1991/0809 | errors("floppy read err"); | |
| 1991/0924 | } | |
| 1991/0809 | dp->ccyl = cyl; | |
| 1991/0924 | dp->chead = head; | |
| 1991/0809 | } | |
| 1991/0924 | memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); | |
| 1991/0802 | } break; | |
| 1991/0924 | case Qctl: break; | |
| 1991/0802 | default: panic("floppyread: bad qid"); | |
| 1991/0731 | } | |
| 1991/0924 | ||
| 1991/0731 | return rv; } | |
| 1991/0924 | #define SNCMP(a, b) strncmp(a, b, sizeof(b)-1) | |
| 1991/0731 | long floppywrite(Chan *c, void *a, long n) { Drive *dp; long rv, i; | |
| 1991/0924 | char *aa = a; int dev; | |
| 1991/0731 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/0802 | switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0831 |
| |
| 1991/0924 | if(c->offset % dp->t->bytes) errors("bad offset"); if(n % dp->t->bytes) errors("bad len"); | |
| 1991/0802 | for(rv = 0; rv < n; rv += i){ | |
| 1991/0924 | floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv); | |
| 1991/0802 | if(i <= 0) break; } break; | |
| 1991/0924 | 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; | |
| 1991/0802 | default: panic("floppywrite: bad qid"); | |
| 1991/0731 | } | |
| 1991/0924 | ||
| 1991/0731 | return rv; } | |
| 1991/0921/sys/src/9/pc/devfloppy.c:382,434 – 1991/0924/sys/src/9/pc/devfloppy.c:421,473 | ||
| 1991/0731 | floppykproc(void *a) | |
| 1991/0727 | { Drive *dp; | |
| 1991/0803 |
| |
| 1991/0924 | int i; static int last; | |
| 1991/0727 | ||
| 1991/0919 | while(waserror()) ; | |
| 1991/0802 | for(;;){ | |
| 1991/0809 |
| |
| 1991/0921 |
| |
| 1991/0924 | 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)) | |
| 1991/0921 | && TK2SEC(m->ticks - dp->lasttouched) > 5 | |
| 1991/0802 | && canqlock(dp)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) | |
| 1991/0924 | floppyoff(dp); | |
| 1991/0802 | qunlock(dp); } | |
| 1991/0728 | } | |
| 1991/0803 |
| |
| 1991/0802 |
| |
| 1991/0803 | ||
| 1991/0924 | tsleep(&fl.kr, return0, 0, 5*100); | |
| 1991/0727 | } } | |
| 1991/0921 |
| |
| 1991/0731 | /* | |
| 1991/0921 |
| |
| 1991/0924 | * start a floppy drive's motor. | |
| 1991/0921 | */ static void | |
| 1991/0924 | floppyon(Drive *dp) | |
| 1991/0921 | { int alreadyon; | |
| 1991/0924 | int tries; | |
| 1991/0921 |
| |
| 1991/0924 | 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); | |
| 1991/0921 | if(!alreadyon) tsleep(&dp->r, return0, 0, 750); | |
| 1991/0924 | /* get drive to a known cylinder */ if(dp->confused) for(tries = 0; tries < 4; tries++) if(floppyrecal(dp) >= 0) break; | |
| 1991/0921 | dp->lasttouched = m->ticks; } | |
| 1991/0921/sys/src/9/pc/devfloppy.c:436,584 – 1991/0924/sys/src/9/pc/devfloppy.c:475,613 | ||
| 1991/0921 | * stop the floppy if it hasn't been used in 5 seconds */ static void | |
| 1991/0924 | floppyoff(Drive *dp) | |
| 1991/0921 | { | |
| 1991/0924 | fl.motor &= ~MOTORBIT(dp->dev); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); | |
| 1991/0921 | } /* | |
| 1991/0731 |
| |
| 1991/0924 | * eject disk ( unknown on safari ) | |
| 1991/0731 | */ | |
| 1991/0727 |
| |
| 1991/0924 | static void floppyeject(Drive *dp) | |
| 1991/0727 | { | |
| 1991/0924 | floppyon(dp); floppyoff(dp); | |
| 1991/0727 | } | |
| 1991/0731 | /* | |
| 1991/0924 | * send a command to the floppy | |
| 1991/0731 | */ static int | |
| 1991/0727 |
| |
| 1991/0924 | floppycmd(void) | |
| 1991/0727 | { | |
| 1991/0924 | int i; | |
| 1991/0727 | int tries; | |
| 1991/0924 | 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]); | |
| 1991/0727 | } | |
| 1991/0924 | return 0; | |
| 1991/0727 | } | |
| 1991/0731 | /* | |
| 1991/0924 | * get a command result from the floppy * * when the controller goes ready waiting for a command * (instead of sending results), we're done * | |
| 1991/0731 | */ static int | |
| 1991/0924 | floppyresult(void) | |
| 1991/0727 | { | |
| 1991/0924 | int i, s; int tries; | |
| 1991/0727 |
| |
| 1991/0924 | 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); | |
| 1991/0727 | } | |
| 1991/0924 | fl.nstat = i; return i; | |
| 1991/0727 | } | |
| 1991/0731 | /* * calculate physical address of a logical byte offset into the disk * | |
| 1991/0924 | * truncate dp->length if it crosses a track boundary | |
| 1991/0731 | */ static void | |
| 1991/0802 | floppypos(Drive *dp, long off) | |
| 1991/0727 | { int lsec; | |
| 1991/0924 | int ltrack; | |
| 1991/0727 | int end; int cyl; | |
| 1991/0924 | int track; | |
| 1991/0727 | ||
| 1991/0802 | lsec = off/dp->t->bytes; | |
| 1991/0727 |
| |
| 1991/0924 | ltrack = lsec/dp->t->sectors; dp->tcyl = ltrack/dp->t->heads; | |
| 1991/0727 | dp->tsec = (lsec % dp->t->sectors) + 1; dp->thead = (lsec/dp->t->sectors) % dp->t->heads; /* | |
| 1991/0924 | * can't read across track boundaries. | |
| 1991/0727 | * if so, decrement the bytes to be read. */ | |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | end = (ltrack+1)*dp->t->sectors*dp->t->bytes; if(off+dp->len > end) dp->len = end - off; | |
| 1991/0727 | } | |
| 1991/0731 | /* | |
| 1991/0924 | * get the interrupt cause from the floppy. | |
| 1991/0731 | */ static int | |
| 1991/0727 |
| |
| 1991/0924 | floppysense(void) | |
| 1991/0727 | { | |
| 1991/0924 | fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fsense; if(floppycmd() < 0) | |
| 1991/0727 | return -1; | |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | if(floppyresult() < 2){ print("can't read sense response\n"); fl.confused = 1; | |
| 1991/0727 | return -1; } | |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0924 | static int cmddone(void *a) { return fl.ncmd == 0; } | |
| 1991/0731 | /* | |
| 1991/0924 | * wait for a floppy interrupt | |
| 1991/0731 | */ | |
| 1991/0924 | static void floppywait(void) | |
| 1991/0731 | { | |
| 1991/0924 | tsleep(&fl.r, cmddone, 0, 2000); | |
| 1991/0731 | } /* | |
| 1991/0921/sys/src/9/pc/devfloppy.c:587,621 – 1991/0924/sys/src/9/pc/devfloppy.c:616,641 | ||
| 1991/0731 | static int | |
| 1991/0727 | floppyrecal(Drive *dp) { | |
| 1991/0731 |
| |
| 1991/0924 | int type; | |
| 1991/0727 |
| |
| 1991/0924 | dp->ccyl = -1; | |
| 1991/0727 |
| |
| 1991/0924 | 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){ | |
| 1991/0727 | dp->confused = 1; return -1; } | |
| 1991/0924 | dp->cyl = fl.stat[1]/dp->t->steps; if(dp->cyl != 0){ | |
| 1991/0727 | print("recalibrate went to wrong cylinder %d\n", dp->cyl); dp->confused = 1; return -1; | |
| 1991/0921/sys/src/9/pc/devfloppy.c:635,714 – 1991/0924/sys/src/9/pc/devfloppy.c:655,714 | ||
| 1991/0727 | Drive *dp; /* | |
| 1991/0731 |
| |
| 1991/0924 | * reset the controller if it's confused | |
| 1991/0727 | */ | |
| 1991/0924 | if(fl.confused){ | |
| 1991/0727 | /* reset controller and turn all motors off */ | |
| 1991/0924 | fl.cmd[0] = 0; outb(Pdor, 0); | |
| 1991/0727 | delay(1); | |
| 1991/0924 | outb(Pdor, Fintena|Fena); | |
| 1991/0727 | spllo(); | |
| 1991/0809 |
| |
| 1991/0924 | for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++) | |
| 1991/0727 | dp->confused = 1; | |
| 1991/0921 |
| |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | fl.motor = 0; floppywait(); fl.confused = 0; /* devp->dsr = 0; devp->ccr = 0; /**/ | |
| 1991/0727 | } | |
| 1991/0809 |
| |
| 1991/0727 |
| |
| 1991/0924 | /* * seek to the target cylinder * * interrupt, no results */ | |
| 1991/0731 | static long | |
| 1991/0924 | floppyseek(Drive *dp, long off) | |
| 1991/0727 | { | |
| 1991/0924 | floppyon(dp); floppypos(dp, off); | |
| 1991/0802 | if(dp->cyl == dp->tcyl) return dp->cyl; | |
| 1991/0727 |
| |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | /* 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){ | |
| 1991/0727 | print("seek cmd failed\n"); | |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | floppywait(); if(fl.nstat < 2){ fl.confused = 1; | |
| 1991/0727 | return -1; | |
| 1991/0924 | } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ | |
| 1991/0727 | print("seek failed\n"); dp->confused = 1; return -1; } | |
| 1991/0924 | dp->cyl = dp->tcyl; | |
| 1991/0802 | return dp->cyl; | |
| 1991/0727 | } | |
| 1991/0921/sys/src/9/pc/devfloppy.c:716,800 – 1991/0924/sys/src/9/pc/devfloppy.c:716,812 | ||
| 1991/0802 | floppyxfer(Drive *dp, int cmd, void *a, long off, long n) | |
| 1991/0727 | { long offset; | |
| 1991/0924 | ulong up; | |
| 1991/0727 | ||
| 1991/0731 |
| |
| 1991/0924 | if(off >= dp->t->cap) return 0; if(off + n > dp->t->cap) n = dp->t->cap - off; qlock(&fl); | |
| 1991/0731 | qlock(dp); | |
| 1991/0802 | if(waserror()){ | |
| 1991/0731 |
| |
| 1991/0924 | dmaend(DMAchan); qunlock(&fl); | |
| 1991/0731 | qunlock(dp); | |
| 1991/0924 | fl.confused = 1; nexterror(); | |
| 1991/0731 | } | |
| 1991/0727 | /* | |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0921 |
| |
| 1991/0727 | ||
| 1991/0731 |
| |
| 1991/0727 | dp->len = n; | |
| 1991/0802 |
| |
| 1991/0731 |
| |
| 1991/0924 | if(floppyseek(dp, off) < 0) | |
| 1991/0731 | errors("seeking floppy"); | |
| 1991/0727 | ||
| 1991/0906 | ||
| 1991/0823 | /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", | |
| 1991/0906 |
| |
| 1991/0924 | dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/ | |
| 1991/0727 | /* | |
| 1991/0731 | * set up the dma (dp->len may be trimmed) | |
| 1991/0727 | */ | |
| 1991/0731 |
| |
| 1991/0924 | dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread); | |
| 1991/0727 | /* | |
| 1991/0731 | * start operation | |
| 1991/0727 | */ | |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0802 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | /* 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(); | |
| 1991/0727 | print("xfer cmd failed\n"); | |
| 1991/0731 | errors("floppy command failed"); | |
| 1991/0727 | } | |
| 1991/0731 |
| |
| 1991/0727 | /* | |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | * 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; | |
| 1991/0731 | errors("floppy result failed"); | |
| 1991/0727 | } | |
| 1991/0731 |
| |
| 1991/0924 | 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]++; | |
| 1991/0727 | } | |
| 1991/0731 |
| |
| 1991/0924 | /* * 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]]; | |
| 1991/0802 | if(offset != off+dp->len){ | |
| 1991/0924 | 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 |
| |
| 1991/0924 | qunlock(&fl); | |
| 1991/0731 | qunlock(dp); poperror(); | |
| 1991/0921/sys/src/9/pc/devfloppy.c:801,810 – 1991/0924/sys/src/9/pc/devfloppy.c:813,835 | ||
| 1991/0727 | return dp->len; } | |
| 1991/0731 |
| |
| 1991/0727 |
| |
| 1991/0924 | void floppyintr(void) | |
| 1991/0727 | { | |
| 1991/0823 |
| |
| 1991/0727 |
| |
| 1991/0731 |
| |
| 1991/0924 | 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); | |
| 1991/0727 | } | |
| 1991/0924/sys/src/9/pc/devfloppy.c:39,45 – 1991/0925/sys/src/9/pc/devfloppy.c:39,46 (short | long) | ||
| 1991/0924 | Fdumpreg= 0x0e, /* dump internal registers */ | |
| 1991/0727 | ||
| 1991/0924 | /* digital input register */ | |
| 1991/0925 | Pdir= 0x3F7, /* disk changed port (read only) */ Pdsr= 0x3F7, /* data rate select port (write only) */ | |
| 1991/0924 | Fchange= 0x80, /* disk has changed */ | |
| 1991/0831 | ||
| 1991/0727 | /* status 0 byte */ | |
| 1991/0924/sys/src/9/pc/devfloppy.c:114,121 – 1991/0925/sys/src/9/pc/devfloppy.c:115,120 | ||
| 1991/0727 | */ struct Drive { | |
| 1991/0731 |
| |
| 1991/0727 | Type *t; int dev; | |
| 1991/0924/sys/src/9/pc/devfloppy.c:122,127 – 1991/0925/sys/src/9/pc/devfloppy.c:121,127 | ||
| 1991/0727 | ulong lasttouched; /* time last touched */ int cyl; /* current cylinder */ | |
| 1991/0924 | int confused; /* needs to be recalibrated */ | |
| 1991/0925 | int vers; | |
| 1991/0727 | int tcyl; /* target cylinder */ int thead; /* target head */ | |
| 1991/0924/sys/src/9/pc/devfloppy.c:143,148 – 1991/0925/sys/src/9/pc/devfloppy.c:143,149 | ||
| 1991/0731 | QLock; /* exclusive access to the contoller */ | |
| 1991/0809 | Drive *d; /* the floppy drives */ | |
| 1991/0925 | Drive *selected; | |
| 1991/0924 | uchar cmd[14]; /* command */ int ncmd; /* # command bytes */ uchar stat[14]; /* command status */ | |
| 1991/0924/sys/src/9/pc/devfloppy.c:162,167 – 1991/0925/sys/src/9/pc/devfloppy.c:163,169 | ||
| 1991/0731 | */ | |
| 1991/0924 | static int floppycmd(void); static void floppyeject(Drive*); | |
| 1991/0925 | static void floppyintr(Ureg*); | |
| 1991/0731 | static void floppykproc(void*); | |
| 1991/0924 | static void floppyon(Drive*); static void floppyoff(Drive*); | |
| 1991/0924/sys/src/9/pc/devfloppy.c:210,215 – 1991/0925/sys/src/9/pc/devfloppy.c:212,218 | ||
| 1991/0809 | * allocate the drive storage */ | |
| 1991/0924 | fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0); | |
| 1991/0925 | fl.selected = fl.d; | |
| 1991/0809 | /* | |
| 1991/0802 | * stop the motors | |
| 1991/0924/sys/src/9/pc/devfloppy.c:229,234 – 1991/0925/sys/src/9/pc/devfloppy.c:232,238 | ||
| 1991/0802 | dp->cyl = -1; /* because we don't know */ | |
| 1991/0924 | dp->cache = (uchar*)ialloc(dp->t->tsize, 1); dp->ccyl = -1; | |
| 1991/0925 | dp->vers = 1; | |
| 1991/0731 | } | |
| 1991/0809 | /* | |
| 1991/0924/sys/src/9/pc/devfloppy.c:235,240 – 1991/0925/sys/src/9/pc/devfloppy.c:239,245 | ||
| 1991/0924 | * first operation will recalibrate | |
| 1991/0809 | */ | |
| 1991/0924 | fl.confused = 1; | |
| 1991/0925 | setvec(Floppyvec, floppyintr); | |
| 1991/0731 | } void | |
| 1991/0924/sys/src/9/pc/devfloppy.c:278,284 – 1991/0925/sys/src/9/pc/devfloppy.c:283,289 | ||
| 1991/0802 | Chan* floppyopen(Chan *c, int omode) { | |
| 1991/0811 |
| |
| 1991/0925 | devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); | |
| 1991/0802 | } void | |
| 1991/0924/sys/src/9/pc/devfloppy.c:304,309 – 1991/0925/sys/src/9/pc/devfloppy.c:309,348 | ||
| 1991/0802 | error(Eperm); } | |
| 1991/0925 | 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"); } } | |
| 1991/0731 | long floppyread(Chan *c, void *a, long n) { | |
| 1991/0924/sys/src/9/pc/devfloppy.c:319,333 – 1991/0925/sys/src/9/pc/devfloppy.c:358,376 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/0802 | switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0809 |
| |
| 1991/0925 | islegal(c, n, dp); | |
| 1991/0924 | aa = a; nn = dp->t->tsize; | |
| 1991/0925 | qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); | |
| 1991/0809 | for(rv = 0; rv < n; rv += len){ /* | |
| 1991/0924 | * truncate xfer at track boundary | |
| 1991/0924/sys/src/9/pc/devfloppy.c:356,361 – 1991/0925/sys/src/9/pc/devfloppy.c:399,407 | ||
| 1991/0809 | } | |
| 1991/0924 | memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); | |
| 1991/0802 | } | |
| 1991/0925 | qunlock(&fl); poperror(); | |
| 1991/0802 | break; | |
| 1991/0924 | case Qctl: break; | |
| 1991/0924/sys/src/9/pc/devfloppy.c:377,389 – 1991/0925/sys/src/9/pc/devfloppy.c:423,438 | ||
| 1991/0731 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/0802 | switch ((int)(c->qid.path & Qmask)) { case Qdata: | |
| 1991/0924 |
| |
| 1991/0925 | islegal(c, n, dp); qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); | |
| 1991/0802 | for(rv = 0; rv < n; rv += i){ | |
| 1991/0924 | floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) | |
| 1991/0924/sys/src/9/pc/devfloppy.c:393,414 – 1991/0925/sys/src/9/pc/devfloppy.c:442,459 | ||
| 1991/0802 | if(i <= 0) break; } | |
| 1991/0925 | qunlock(&fl); poperror(); | |
| 1991/0802 | break; | |
| 1991/0924 | case Qctl: | |
| 1991/0925 | qlock(&fl); | |
| 1991/0924 | if(SNCMP(aa, "eject") == 0){ floppyeject(dp); | |
| 1991/0925 | fl.confused = 1; | |
| 1991/0924 | floppyon(dp); } | |
| 1991/0925 | qunlock(&fl); | |
| 1991/0924 | break; | |
| 1991/0802 | default: panic("floppywrite: bad qid"); | |
| 1991/0924/sys/src/9/pc/devfloppy.c:421,446 – 1991/0925/sys/src/9/pc/devfloppy.c:466,485 | ||
| 1991/0731 | floppykproc(void *a) | |
| 1991/0727 | { Drive *dp; | |
| 1991/0924 |
| |
| 1991/0727 | ||
| 1991/0919 | while(waserror()) ; | |
| 1991/0802 | for(;;){ | |
| 1991/0924 |
| |
| 1991/0921 | && TK2SEC(m->ticks - dp->lasttouched) > 5 | |
| 1991/0802 |
| |
| 1991/0925 | && canqlock(&fl)){ | |
| 1991/0802 | if(TK2SEC(m->ticks - dp->lasttouched) > 5) | |
| 1991/0924 | floppyoff(dp); | |
| 1991/0802 |
| |
| 1991/0925 | qunlock(&fl); | |
| 1991/0802 | } | |
| 1991/0728 | } | |
| 1991/0924 |
| |
| 1991/0925 | tsleep(&fl.kr, return0, 0, 1000); | |
| 1991/0727 | } } | |
| 1991/0924/sys/src/9/pc/devfloppy.c:469,474 – 1991/0925/sys/src/9/pc/devfloppy.c:508,514 | ||
| 1991/0924 | if(floppyrecal(dp) >= 0) break; | |
| 1991/0921 | dp->lasttouched = m->ticks; | |
| 1991/0925 | fl.selected = dp; | |
| 1991/0921 | } /* | |
| 1991/0924/sys/src/9/pc/devfloppy.c:479,484 – 1991/0925/sys/src/9/pc/devfloppy.c:519,525 | ||
| 1991/0921 | { | |
| 1991/0924 | fl.motor &= ~MOTORBIT(dp->dev); outb(Pdor, fl.motor | Fintena | Fena | dp->dev); | |
| 1991/0925 | fl.selected = dp; | |
| 1991/0921 | } /* | |
| 1991/0924/sys/src/9/pc/devfloppy.c:488,493 – 1991/0925/sys/src/9/pc/devfloppy.c:529,535 | ||
| 1991/0924 | floppyeject(Drive *dp) | |
| 1991/0727 | { | |
| 1991/0924 | floppyon(dp); | |
| 1991/0925 | dp->vers++; | |
| 1991/0924 | floppyoff(dp); | |
| 1991/0727 | } | |
| 1991/0924/sys/src/9/pc/devfloppy.c:670,677 – 1991/0925/sys/src/9/pc/devfloppy.c:712,718 | ||
| 1991/0924 | fl.motor = 0; floppywait(); fl.confused = 0; | |
| 1991/0925 | outb(Pdsr, 0); | |
| 1991/0727 | } } | |
| 1991/0924/sys/src/9/pc/devfloppy.c:683,689 – 1991/0925/sys/src/9/pc/devfloppy.c:724,729 | ||
| 1991/0731 | static long | |
| 1991/0924 | floppyseek(Drive *dp, long off) | |
| 1991/0727 | { | |
| 1991/0924 |
| |
| 1991/0802 | if(dp->cyl == dp->tcyl) return dp->cyl; | |
| 1991/0924/sys/src/9/pc/devfloppy.c:723,738 – 1991/0925/sys/src/9/pc/devfloppy.c:763,768 | ||
| 1991/0924 | if(off + n > dp->t->cap) n = dp->t->cap - off; | |
| 1991/0731 |
| |
| 1991/0802 |
| |
| 1991/0924 |
| |
| 1991/0731 |
| |
| 1991/0924 |
| |
| 1991/0731 |
| |
| 1991/0727 | /* | |
| 1991/0731 | * calculate new position and seek to it (dp->len may be trimmed) */ | |
| 1991/0924/sys/src/9/pc/devfloppy.c:739,745 – 1991/0925/sys/src/9/pc/devfloppy.c:769,775 | ||
| 1991/0727 | dp->len = n; | |
| 1991/0924 | if(floppyseek(dp, off) < 0) | |
| 1991/0731 | errors("seeking floppy"); | |
| 1991/0906 | ||
| 1991/0925 | ||
| 1991/0823 | /*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", | |
| 1991/0924 | dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/ | |
| 1991/0727 | ||
| 1991/0924/sys/src/9/pc/devfloppy.c:751,757 – 1991/0925/sys/src/9/pc/devfloppy.c:781,787 | ||
| 1991/0727 | /* | |
| 1991/0731 | * start operation | |
| 1991/0727 | */ | |
| 1991/0924 |
| |
| 1991/0925 | cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); | |
| 1991/0924 | fl.ncmd = 0; fl.cmd[fl.ncmd++] = cmd; fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; | |
| 1991/0924/sys/src/9/pc/devfloppy.c:783,796 – 1991/0925/sys/src/9/pc/devfloppy.c:813,823 | ||
| 1991/0731 | errors("floppy result failed"); | |
| 1991/0727 | } | |
| 1991/0924 | if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ | |
| 1991/0925 | 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"); | |
| 1991/0727 | } | |
| 1991/0924 | /* | |
| 1991/0924/sys/src/9/pc/devfloppy.c:801,820 – 1991/0925/sys/src/9/pc/devfloppy.c:828,844 | ||
| 1991/0924 | offset = offset * c2b[fl.stat[6]]; | |
| 1991/0802 | if(offset != off+dp->len){ | |
| 1991/0924 | print("new offset %d instead of %d\n", offset, off+dp->len); | |
| 1991/0925 | print(" %d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]); | |
| 1991/0727 | dp->confused = 1; | |
| 1991/0731 | errors("floppy drive lost"); | |
| 1991/0727 | } | |
| 1991/0802 | dp->lasttouched = m->ticks; | |
| 1991/0924 |
| |
| 1991/0731 |
| |
| 1991/0727 | return dp->len; } | |
| 1991/0924 |
| |
| 1991/0925 | static void floppyintr(Ureg *ur) | |
| 1991/0727 | { | |
| 1991/0924 | switch(fl.cmd[0]&~Fmulti){ case Fread: | |
| 1991/0925/sys/src/9/pc/devfloppy.c:420,425 – 1991/0927/sys/src/9/pc/devfloppy.c:420,426 (short | long) | ||
| 1991/0731 | long rv, i; | |
| 1991/0924 | char *aa = a; int dev; | |
| 1991/0927 | extern void vgaset(char*); | |
| 1991/0731 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/0925/sys/src/9/pc/devfloppy.c:452,457 – 1991/0927/sys/src/9/pc/devfloppy.c:453,460 | ||
| 1991/0924 | } else if(SNCMP(aa, "reset") == 0){ | |
| 1991/0925 | fl.confused = 1; | |
| 1991/0924 | floppyon(dp); | |
| 1991/0927 | } else if(SNCMP(aa, "v") == 0){ vgaset(aa+1); | |
| 1991/0924 | } | |
| 1991/0925 | qunlock(&fl); | |
| 1991/0924 | break; | |
| 1991/0927/sys/src/9/pc/devfloppy.c:792,798 – 1991/1001/sys/src/9/pc/devfloppy.c:792,798 (short | long) | ||
| 1991/0924 | fl.cmd[fl.ncmd++] = dp->thead; fl.cmd[fl.ncmd++] = dp->tsec; fl.cmd[fl.ncmd++] = dp->t->bcode; | |
| 1991/1001 | fl.cmd[fl.ncmd++] = dp->t->sectors; | |
| 1991/0924 | fl.cmd[fl.ncmd++] = dp->t->gpl; fl.cmd[fl.ncmd++] = 0xFF; if(floppycmd() < 0){ | |
| 1991/1001/sys/src/9/pc/devfloppy.c:329,346 – 1991/1003/sys/src/9/pc/devfloppy.c:329,346 (short | long) | ||
| 1991/0925 | { ulong old; | |
| 1991/1003 | if(inb(Pdir)&Fchange){ | |
| 1991/0925 | dp->vers++; | |
| 1991/1003 | old = c->qid.vers; c->qid.vers = dp->vers; if(old && old!=dp->vers) errors("disk changed"); | |
| 1991/0925 | } | |
| 1991/0731 | long | |
| 1991/1003/sys/src/9/pc/devfloppy.c:633,639 – 1991/1005/sys/src/9/pc/devfloppy.c:633,639 (short | long) | ||
| 1991/0924 | if(floppycmd() < 0) | |
| 1991/0727 | return -1; | |
| 1991/0924 | if(floppyresult() < 2){ | |
| 1991/1005 | /*print("can't read sense response\n");/**/ | |
| 1991/0924 | fl.confused = 1; | |
| 1991/0727 | return -1; } | |
| 1991/1005/sys/src/9/pc/devfloppy.c:175,180 – 1991/1006/sys/src/9/pc/devfloppy.c:175,181 (short | long) | ||
| 1991/0924 | static int floppysense(void); static void floppywait(void); | |
| 1991/0802 | static long floppyxfer(Drive*, int, void*, long, long); | |
| 1991/1006 | static long floppythrice(Drive*, int, void*, long, long); | |
| 1991/0924 | static int cmddone(void*); void Xdelay(int); | |
| 1991/0731 | ||
| 1991/1005/sys/src/9/pc/devfloppy.c:387,393 – 1991/1006/sys/src/9/pc/devfloppy.c:388,394 | ||
| 1991/0809 | */ | |
| 1991/0924 | if(dp->ccyl!=cyl || dp->chead!=head){ | |
| 1991/0809 | dp->ccyl = -1; | |
| 1991/0924 |
| |
| 1991/1006 | i = floppythrice(dp, Fread, dp->cache, | |
| 1991/0924 | (cyl*dp->t->heads+head)*nn, nn); if(i != nn){ if(i == 0) | |
| 1991/1005/sys/src/9/pc/devfloppy.c:420,426 – 1991/1006/sys/src/9/pc/devfloppy.c:421,426 | ||
| 1991/0731 | long rv, i; | |
| 1991/0924 | char *aa = a; int dev; | |
| 1991/0927 |
| |
| 1991/0731 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1991/1005/sys/src/9/pc/devfloppy.c:438,447 – 1991/1006/sys/src/9/pc/devfloppy.c:438,449 | ||
| 1991/0924 | floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; | |
| 1991/1006 | i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, | |
| 1991/0924 | n-rv); | |
| 1991/0802 |
| |
| 1991/1006 | if(i < 0) | |
| 1991/0802 | break; | |
| 1991/1006 | if(i == 0) error(Eio); | |
| 1991/0802 | } | |
| 1991/0925 | qunlock(&fl); poperror(); | |
| 1991/1005/sys/src/9/pc/devfloppy.c:453,460 – 1991/1006/sys/src/9/pc/devfloppy.c:455,460 | ||
| 1991/0924 | } else if(SNCMP(aa, "reset") == 0){ | |
| 1991/0925 | fl.confused = 1; | |
| 1991/0924 | floppyon(dp); | |
| 1991/0927 |
| |
| 1991/0924 | } | |
| 1991/0925 | qunlock(&fl); | |
| 1991/0924 | break; | |
| 1991/1005/sys/src/9/pc/devfloppy.c:755,761 – 1991/1006/sys/src/9/pc/devfloppy.c:755,782 | ||
| 1991/0802 | return dp->cyl; | |
| 1991/0727 | } | |
| 1991/1006 | /* * since floppies are so flakey, try 3 times before giving up */ | |
| 1991/0731 | static long | |
| 1991/1006 | 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 | |
| 1991/0802 | floppyxfer(Drive *dp, int cmd, void *a, long off, long n) | |
| 1991/0727 | { long offset; | |
| 1991/1005/sys/src/9/pc/devfloppy.c:830,837 – 1991/1006/sys/src/9/pc/devfloppy.c:851,856 | ||
| 1991/0924 | offset = offset*dp->t->sectors + fl.stat[5] - 1; offset = offset * c2b[fl.stat[6]]; | |
| 1991/0802 | if(offset != off+dp->len){ | |
| 1991/0924 |
| |
| 1991/0925 |
| |
| 1991/0727 | dp->confused = 1; | |
| 1991/0731 | errors("floppy drive lost"); | |
| 1991/0727 | } | |
| Too many diffs (26 > 25). Stopping. | ||