| plan 9 kernel history: overview | file list | diff list |
1991/0925/pc/devfloppy.c (diff list | history)
| 1991/0924/sys/src/9/pc/devfloppy.c:39,45 – 1991/0925/sys/src/9/pc/devfloppy.c:39,46 (short | long | prev | next) | ||
| 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: | |