| plan 9 kernel history: overview | file list | diff list |
1992/1006/pc/devfloppy.c (diff list | history)
| 1992/1003/sys/src/9/pc/devfloppy.c:37,42 – 1992/1006/sys/src/9/pc/devfloppy.c:37,43 (short | long | prev | next) | ||
| 1991/0924 | Freadid= 0x4a, /* read track id */ Fspec= 0x03, /* set hold times */ Fwrite= 0x45, /* write cmd */ | |
| 1992/1006 | Fformat= 0x4d, /* format cmd */ | |
| 1991/0924 | Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */ Fdumpreg= 0x0e, /* dump internal registers */ | |
| 1991/0727 | ||
| 1992/1003/sys/src/9/pc/devfloppy.c:60,70 – 1992/1006/sys/src/9/pc/devfloppy.c:61,84 | ||
| 1991/0727 | }; /* | |
| 1992/1006 | * types of drive (from PC equipment byte) */ enum { Tnone= 0, T360kb= 1, T1200kb= 2, T720kb= 3, T1440kb= 4, }; /* | |
| 1992/1003 | * floppy types (all MFM encoding) | |
| 1991/0727 | */ struct Type { char *name; | |
| 1992/1006 | int dt; /* compatible drive type */ | |
| 1991/0727 | int bytes; /* bytes/sector */ int sectors; /* sectors/track */ int heads; /* number of heads */ | |
| 1992/1003/sys/src/9/pc/devfloppy.c:84,95 – 1992/1006/sys/src/9/pc/devfloppy.c:98,109 | ||
| 1991/0727 | }; Type floppytype[] = { | |
| 1992/1003 |
| |
| 1992/1006 | { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, }, { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, }, { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, }, | |
| 1991/0727 | }; | |
| 1991/0731 | #define NTYPES (sizeof(floppytype)/sizeof(Type)) | |
| 1992/1003/sys/src/9/pc/devfloppy.c:118,128 – 1992/1006/sys/src/9/pc/devfloppy.c:132,143 | ||
| 1991/0727 | */ struct Drive { | |
| 1992/1006 | Type *t; /* floppy type */ int dt; /* drive type */ | |
| 1991/0727 | int dev; ulong lasttouched; /* time last touched */ | |
| 1992/1003 |
| |
| 1992/1006 | int cyl; /* current arm position */ | |
| 1991/0924 | int confused; /* needs to be recalibrated */ | |
| 1991/0925 | int vers; | |
| 1991/0727 | ||
| 1992/1003/sys/src/9/pc/devfloppy.c:179,184 – 1992/1006/sys/src/9/pc/devfloppy.c:194,200 | ||
| 1991/0924 | static int floppysense(void); static void floppywait(void); | |
| 1991/0802 | static long floppyxfer(Drive*, int, void*, long, long); | |
| 1992/1006 | static int floppyformat(Chan*, Drive*, int, char); | |
| 1991/1006 | static long floppythrice(Drive*, int, void*, long, long); | |
| 1991/0924 | static int cmddone(void*); void Xdelay(int); | |
| 1992/1003/sys/src/9/pc/devfloppy.c:195,205 – 1992/1006/sys/src/9/pc/devfloppy.c:211,238 | ||
| 1991/0802 | }; | |
| 1991/0811 | #define NFDIR 2 /* directory entries/drive */ | |
| 1991/0731 | ||
| 1992/1006 | /* * set floppy drive to its default type */ static void setdef(Drive *dp) { Type *t; for(t = floppytype; t < &floppytype[NTYPES]; t++) if(dp->dt == t->dt){ dp->t = t; floppydir[NFDIR*dp->dev].length = dp->t->cap; break; } } | |
| 1991/0731 | void floppyreset(void) { Drive *dp; | |
| 1991/0802 | Type *t; | |
| 1992/1006 | uchar equip; | |
| 1991/0731 | ||
| 1991/0802 | /* * init dependent parameters | |
| 1992/1003/sys/src/9/pc/devfloppy.c:229,237 – 1992/1006/sys/src/9/pc/devfloppy.c:262,270 | ||
| 1991/0924 | */ for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ dp->dev = dp - fl.d; | |
| 1991/0731 |
| |
| 1991/0811 |
| |
| 1992/1003 |
| |
| 1992/1006 | dp->dt = T1440kb; setdef(dp); dp->cyl = -1; /* because we don't know */ | |
| 1992/0625 | dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 0); | |
| 1991/0924 | dp->ccyl = -1; | |
| 1991/0925 | dp->vers = 1; | |
| 1992/1003/sys/src/9/pc/devfloppy.c:238,243 – 1992/1006/sys/src/9/pc/devfloppy.c:271,289 | ||
| 1991/0731 | } | |
| 1991/0809 | /* | |
| 1992/1006 | * read nvram for types of floppies 0 & 1 */ equip = nvramread(0x10); if(conf.nfloppy > 0){ fl.d[0].dt = (equip >> 4) & 0xf; setdef(&fl.d[0]); } if(conf.nfloppy > 1){ fl.d[1].dt = equip & 0xf; setdef(&fl.d[1]); } /* | |
| 1991/0924 | * first operation will recalibrate | |
| 1991/0809 | */ | |
| 1991/0924 | fl.confused = 1; | |
| 1992/1003/sys/src/9/pc/devfloppy.c:336,344 – 1992/1006/sys/src/9/pc/devfloppy.c:382,392 | ||
| 1991/0925 | ulong old; | |
| 1991/1003 | if(inb(Pdir)&Fchange){ | |
| 1992/1006 | setdef(dp); | |
| 1991/0925 | dp->vers++; | |
| 1992/1003 |
| |
| 1992/1006 | dp->confused = 1; floppyon(dp); if(dp->cyl) | |
| 1992/1002 | floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize); | |
| 1991/0925 | else | |
| 1992/1003 | floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, | |
| 1992/1003/sys/src/9/pc/devfloppy.c:427,432 – 1992/1006/sys/src/9/pc/devfloppy.c:475,482 | ||
| 1991/0731 | Drive *dp; long rv, i; | |
| 1991/0924 | char *aa = a; | |
| 1992/1006 | char *f[3]; char ctlmsg[64]; | |
| 1991/0731 | ||
| 1991/0802 | rv = 0; | |
| 1991/0924 | dp = &fl.d[c->qid.path & ~Qmask]; | |
| 1992/1003/sys/src/9/pc/devfloppy.c:444,451 – 1992/1006/sys/src/9/pc/devfloppy.c:494,500 | ||
| 1991/0924 | floppypos(dp, c->offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; | |
| 1991/1006 |
| |
| 1991/0924 |
| |
| 1992/1006 | i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, n-rv); | |
| 1991/1006 | if(i < 0) | |
| 1991/0802 | break; | |
| 1991/1006 | if(i == 0) | |
| 1992/1003/sys/src/9/pc/devfloppy.c:456,470 – 1992/1006/sys/src/9/pc/devfloppy.c:505,523 | ||
| 1991/0802 | break; | |
| 1991/0924 | case Qctl: | |
| 1991/0925 | qlock(&fl); | |
| 1991/0924 |
| |
| 1992/1006 | if(n >= sizeof(ctlmsg)) n = sizeof(ctlmsg) - 1; memmove(ctlmsg, aa, n); ctlmsg[n] = 0; if(SNCMP(ctlmsg, "eject") == 0){ | |
| 1991/0924 | floppyeject(dp); | |
| 1992/1006 | } else if(SNCMP(ctlmsg, "reset") == 0){ | |
| 1991/0925 | fl.confused = 1; | |
| 1991/0924 | floppyon(dp); | |
| 1991/1029 |
| |
| 1992/1006 | } else if(SNCMP(ctlmsg, "format") == 0){ if(getfields(ctlmsg, f, 3, ' ') != 3) error(Ebadarg); rv = n*floppyformat(c, dp, atoi(f[1]), *f[2]); | |
| 1991/0924 | } | |
| 1991/0925 | qunlock(&fl); | |
| 1991/0924 | break; | |
| 1992/1003/sys/src/9/pc/devfloppy.c:693,701 – 1992/1006/sys/src/9/pc/devfloppy.c:746,754 | ||
| 1991/0727 | dp->confused = 1; return -1; } | |
| 1992/1003 |
| |
| 1992/1006 | dp->cyl = fl.stat[1]; if(dp->cyl != 0){ DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl); | |
| 1991/0727 | dp->confused = 1; return -1; } | |
| 1992/1003/sys/src/9/pc/devfloppy.c:743,749 – 1992/1006/sys/src/9/pc/devfloppy.c:796,802 | ||
| 1991/0924 | floppyseek(Drive *dp, long off) | |
| 1991/0727 | { | |
| 1991/0924 | floppypos(dp, off); | |
| 1992/1003 |
| |
| 1992/1006 | if(dp->cyl == dp->tcyl) | |
| 1992/1003 | return dp->tcyl; | |
| 1991/0727 | ||
| 1992/0901 | DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); | |
| 1992/1003/sys/src/9/pc/devfloppy.c:767,773 – 1992/1006/sys/src/9/pc/devfloppy.c:820,826 | ||
| 1991/0727 | return -1; } | |
| 1992/1003 |
| |
| 1992/1006 | dp->cyl = dp->tcyl; | |
| 1992/1003 | return dp->tcyl; | |
| 1991/0727 | } | |
| 1992/1003/sys/src/9/pc/devfloppy.c:790,797 – 1992/1006/sys/src/9/pc/devfloppy.c:843,856 | ||
| 1992/1003 | /* walk through the compatible types */ if(tries == 3){ | |
| 1992/1006 | while(++dp->t){ if(dp->t == &floppytype[NTYPES]) dp->t = floppytype; if(dp->dt == Tnone) break; if(dp->dt == dp->t->dt) break; } | |
| 1992/1003 | floppydir[NFDIR*dp->dev].length = dp->t->cap; if(dp->t == start) nexterror(); | |
| 1992/1003/sys/src/9/pc/devfloppy.c:838,844 – 1992/1006/sys/src/9/pc/devfloppy.c:897,903 | ||
| 1991/0924 | fl.ncmd = 0; fl.cmd[fl.ncmd++] = cmd; fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; | |
| 1992/1006 | fl.cmd[fl.ncmd++] = dp->tcyl; | |
| 1991/0924 | fl.cmd[fl.ncmd++] = dp->thead; fl.cmd[fl.ncmd++] = dp->tsec; fl.cmd[fl.ncmd++] = dp->t->bcode; | |
| 1992/1003/sys/src/9/pc/devfloppy.c:876,882 – 1992/1006/sys/src/9/pc/devfloppy.c:935,941 | ||
| 1991/0924 | /* * check for correct cylinder */ | |
| 1992/1003 |
| |
| 1992/1006 | offset = fl.stat[3] * dp->t->heads + fl.stat[4]; | |
| 1991/0924 | offset = offset*dp->t->sectors + fl.stat[5] - 1; offset = offset * c2b[fl.stat[6]]; | |
| 1991/0802 | if(offset != off+dp->len){ | |
| 1992/1003/sys/src/9/pc/devfloppy.c:889,894 – 1992/1006/sys/src/9/pc/devfloppy.c:948,1033 | ||
| 1991/0727 | return dp->len; } | |
| 1992/1006 | /* * format a track */ static int floppyformat(Chan *c, Drive *dp, int track, char filler) { int cyl, h, sec; uchar *buf, *bp; Type *t; t = dp->t; cyl = track/t->heads; h = track % t->heads; if(track >= t->tracks * t->heads) return 0; buf = smalloc(t->sectors*4); qlock(&fl); if(waserror()){ qunlock(&fl); free(buf); nexterror(); } floppyon(dp); changed(c, dp); if(floppyseek(dp, track*t->tsize) < 0) error(Eio); /* * set up the dma (dp->len may be trimmed) */ bp = buf; for(sec = 1; sec <= t->sectors; sec++){ *bp++ = cyl; *bp++ = h; *bp++ = sec; *bp++ = t->bcode; } dmasetup(DMAchan, buf, bp-buf, 0); /* * start operation */ fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fformat; fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; fl.cmd[fl.ncmd++] = t->bcode; fl.cmd[fl.ncmd++] = t->sectors; fl.cmd[fl.ncmd++] = t->fgpl; fl.cmd[fl.ncmd++] = filler; if(floppycmd() < 0){ DPRINT("xfer cmd failed\n"); error(Eio); } /* * give bus to DMA, floppyintr() will read result */ floppywait(); dmaend(DMAchan); /* * check for errors */ if(fl.nstat < 7){ DPRINT("format result failed %lux\n", inb(Pmsr)); fl.confused = 1; error(Eio); } if((fl.stat[0]&Codemask)!=0 || fl.stat[1] || fl.stat[2]){ DPRINT("format failed %lux %lux %lux\n", fl.stat[0], fl.stat[1], fl.stat[2]); dp->confused = 1; error(Eio); } qunlock(&fl); free(buf); return 1; } | |
| 1991/0925 | static void floppyintr(Ureg *ur) | |
| 1991/0727 | { | |
| 1992/1003/sys/src/9/pc/devfloppy.c:896,904 – 1992/1006/sys/src/9/pc/devfloppy.c:1035,1041 | ||
| 1991/0924 | switch(fl.cmd[0]&~Fmulti){ case Fread: case Fwrite: | |
| 1992/1006 | case Fformat: | |
| 1991/0924 | floppyresult(); break; case Fseek: | |