/* * seek to the target cylinder * * interrupt, no results */ static vlong pcfloppyseek(FDrive *dp, vlong off) { floppypos(dp, off); if(dp->cyl == dp->tcyl) { dp->offset = off; return off; } dp->cyl = -1; 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) return -1; floppywait(1); if(fl.nstat < 2) { DPRINT("seek: confused\n"); fl.confused = 1; return -1; } if((fl.stat[0] & (Codemask|Seekend)) != Seekend) { DPRINT("seek: failed\n"); dp->confused = 1; return -1; } dp->cyl = dp->tcyl; dp->offset = off; DPRINT("seek to %d succeeded\n", dp->offset); return dp->offset; }
long floppyread(Fs *fs, void *a, long n) { FDrive *dp; long rv, offset; int sec, head, cyl; long len; uchar *aa; aa = a; dp = &fl.d[fs->dev]; offset = dp->offset; floppyon(dp); if(changed(dp)) return -1; for(rv = 0; rv < n; rv += len) { /* * all xfers come out of the track cache */ dp->len = n - rv; floppypos(dp, offset+rv); cyl = dp->tcyl; head = dp->thead; len = dp->len; sec = dp->tsec; if(readtrack(dp, cyl, head) < 0) break; memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); } dp->offset = offset+rv; return rv; }
/* * seek to the target cylinder * * interrupt, no results */ static long floppyseek(FDrive *dp, long off) { floppypos(dp, off); if(dp->cyl == dp->tcyl) return dp->tcyl; dp->cyl = -1; 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) return -1; floppywait(1); if(fl.nstat < 2){ DPRINT("seek: confused\n"); fl.confused = 1; return -1; } if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ DPRINT("seek: failed\n"); dp->confused = 1; return -1; } dp->cyl = dp->tcyl; return dp->tcyl; }
static long floppyread(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv; int sec, head, cyl; long len; uchar *aa; ulong offset = off; if(c->qid.type & QTDIR) return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen); rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: islegal(offset, n, dp); aa = a; qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); for(rv = 0; rv < n; rv += len){ /* * all xfers come out of the track cache */ dp->len = n - rv; floppypos(dp, offset+rv); cyl = dp->tcyl; head = dp->thead; len = dp->len; sec = dp->tsec; if(readtrack(dp, cyl, head) < 0) break; memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); } qunlock(&fl); poperror(); break; case Qctl: return readstr(offset, a, n, dp->t->name); default: panic("floppyread: bad qid"); } return rv; }
static long floppywrite(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv, i; char *aa = a; Cmdbuf *cb; Cmdtab *ct; ulong offset = off; rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: islegal(offset, n, dp); qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); for(rv = 0; rv < n; rv += i){ floppypos(dp, offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); if(i < 0) break; if(i == 0) error(Eio); } qunlock(&fl); poperror(); break; case Qctl: rv = n; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); switch(ct->index){ case CMeject: floppyeject(dp); break; case CMformat: floppyformat(dp, cb); break; case CMreset: fl.confused = 1; floppyon(dp); break; case CMdebug: floppydebug = 1; break; case CMnodebug: floppydebug = 0; break; } poperror(); qunlock(&fl); poperror(); free(cb); break; default: panic("floppywrite: bad qid"); } return rv; }