📄 devsd.c
字号:
} if(sdev == nil || sdgetunit(sdev, subno) == nil) error(Enonexist); c = devattach(sddevtab.dc, spec); c->qid = (Qid){QID(sdev->index+subno, 0, Qunitdir)|CHDIR, 0}; c->dev = sdev->index+subno; return c;}static Chan*sdclone(Chan* c, Chan* nc){ return devclone(c, nc);}static intsdwalk(Chan* c, char* name){ return devwalk(c, name, nil, 0, sdgen);}static voidsdstat(Chan* c, char* db){ devstat(c, db, nil, 0, sdgen);}static Chan*sdopen(Chan* c, int omode){ SDpart *pp; SDunit *unit; c = devopen(c, omode, 0, 0, sdgen); switch(TYPE(c->qid)){ default: break; case Qraw: unit = sdunit[UNIT(c->qid)]; if(!canlock(&unit->rawinuse)){ c->flag &= ~COPEN; error(Einuse); } unit->state = Rawcmd; break; case Qpart: unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); c->flag &= ~COPEN; nexterror(); } if(unit->changed) error(Eio); pp = &unit->part[PART(c->qid)]; pp->nopen++; unit->nopen++; qunlock(&unit->ctl); poperror(); break; } return c;}static voidsdclose(Chan* c){ SDpart *pp; SDunit *unit; if(c->qid.path & CHDIR) return; if(!(c->flag & COPEN)) return; switch(TYPE(c->qid)){ default: break; case Qraw: unit = sdunit[UNIT(c->qid)]; unlock(&unit->rawinuse); break; case Qpart: unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); c->flag &= ~COPEN; nexterror(); } pp = &unit->part[PART(c->qid)]; pp->nopen--; unit->nopen--; if(unit->nopen == 0) unit->changed = 0; qunlock(&unit->ctl); poperror(); break; }}static longsdbio(Chan* c, int write, char* a, long len, vlong off){ long l; uchar *b; SDpart *pp; SDunit *unit; ulong bno, max, nb, offset; unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); nexterror(); } if(unit->changed) error(Eio); /* * Check the request is within bounds. * Removeable drives are locked throughout the I/O * in case the media changes unexpectedly. * Non-removeable drives are not locked during the I/O * to allow the hardware to optimise if it can; this is * a little fast and loose. * It's assumed that non-removeable media parameters * (sectors, secsize) can't change once the drive has * been brought online. */ pp = &unit->part[PART(c->qid)]; bno = (off/unit->secsize) + pp->start; nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno; max = SDmaxio/unit->secsize; if(nb > max) nb = max; if(bno+nb > pp->end) nb = pp->end - bno; if(bno >= pp->end || nb == 0){ if(write) error(Eio); qunlock(&unit->ctl); poperror(); return 0; } if(!(unit->inquiry[1] & 0x80)){ qunlock(&unit->ctl); poperror(); } b = sdmalloc(nb*unit->secsize); if(b == nil) error(Enomem); if(waserror()){ sdfree(b); nexterror(); } offset = off%unit->secsize; if(write){ if(offset || (len%unit->secsize)){ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) error(Eio); if(l < (nb*unit->secsize)){ nb = l/unit->secsize; l = nb*unit->secsize - offset; if(len > l) len = l; } } memmove(b+offset, a, len); l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno); if(l < 0) error(Eio); if(l < offset) len = 0; else if(len > l - offset) len = l - offset; } else { l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) error(Eio); if(l < offset) len = 0; else if(len > l - offset) len = l - offset; memmove(a, b+offset, len); } sdfree(b); poperror(); if(unit->inquiry[1] & 0x80){ qunlock(&unit->ctl); poperror(); } return len;}static longsdrio(SDreq* r, void* a, long n){ void *data; if(n >= SDmaxio || n < 0) error(Etoobig); data = nil; if(n){ if((data = sdmalloc(n)) == nil) error(Enomem); if(r->write) memmove(data, a, n); } r->data = data; r->dlen = n; if(waserror()){ if(data != nil){ sdfree(data); r->data = nil; } nexterror(); } if(r->unit->dev->ifc->rio(r) != SDok) error(Eio); if(!r->write && r->rlen > 0) memmove(a, data, r->rlen); if(data != nil){ sdfree(data); r->data = nil; } poperror(); return r->rlen;}static longsdread(Chan *c, void *a, long n, vlong off){ char *p; SDpart *pp; SDunit *unit; ulong offset; int i, l, status; offset = off; switch(TYPE(c->qid)){ default: error(Eperm); case Qtopdir: case Qunitdir: return devdirread(c, a, n, 0, 0, sdgen); case Qctl: unit = sdunit[UNIT(c->qid)]; p = malloc(READSTR); l = snprint(p, READSTR, "inquiry %.48s\n", (char*)unit->inquiry+8); qlock(&unit->ctl); /* * If there's a device specific routine it must * provide all information pertaining to night geometry * and the garscadden trains. */ if(unit->dev->ifc->rctl) l += unit->dev->ifc->rctl(unit, p+l, READSTR-l); if(!unit->changed && unit->sectors){ if(unit->dev->ifc->rctl == nil) l += snprint(p+l, READSTR-l, "geometry %ld %ld\n", unit->sectors, unit->secsize); pp = unit->part; for(i = 0; i < SDnpart; i++){ if(pp->valid) l += snprint(p+l, READSTR-l, "part %.*s %lud %lud\n", NAMELEN, pp->name, pp->start, pp->end); pp++; } } qunlock(&unit->ctl); l = readstr(offset, a, n, p); free(p); return l; case Qraw: unit = sdunit[UNIT(c->qid)]; if(unit->state == Rawdata){ unit->state = Rawstatus; return sdrio(unit->req, a, n); } else if(unit->state == Rawstatus){ status = unit->req->status; unit->state = Rawcmd; free(unit->req); unit->req = nil; return readnum(0, a, n, status, NUMSIZE); } break; case Qpart: return sdbio(c, 0, a, n, off); } return 0;}static longsdwrite(Chan *c, void *a, long n, vlong off){ Cmdbuf *cb; SDreq *req; SDunit *unit; ulong end, start; switch(TYPE(c->qid)){ default: error(Eperm); case Qctl: cb = parsecmd(a, n); unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); free(cb); nexterror(); } if(unit->changed) error(Eio); if(cb->nf < 1) error(Ebadctl); if(strcmp(cb->f[0], "part") == 0){ if(cb->nf != 4 || unit->npart >= SDnpart) error(Ebadctl); if(unit->sectors == 0 && !sdinitpart(unit)) error(Eio); start = strtoul(cb->f[2], 0, 0); end = strtoul(cb->f[3], 0, 0); sdaddpart(unit, cb->f[1], start, end); } else if(strcmp(cb->f[0], "delpart") == 0){ if(cb->nf != 2 || unit->part == nil) error(Ebadctl); sddelpart(unit, cb->f[1]); } else if(unit->dev->ifc->wctl) unit->dev->ifc->wctl(unit, cb); else error(Ebadctl); qunlock(&unit->ctl); poperror(); free(cb); break; case Qraw: unit = sdunit[UNIT(c->qid)]; switch(unit->state){ case Rawcmd: if(n < 6 || n > sizeof(req->cmd)) error(Ebadarg); if((req = malloc(sizeof(SDreq))) == nil) error(Enomem); req->unit = unit; memmove(req->cmd, a, n); req->clen = n; req->flags = SDnosense; req->status = ~0; unit->req = req; unit->state = Rawdata; break; case Rawstatus: unit->state = Rawcmd; free(unit->req); unit->req = nil; error(Ebadusefd); case Rawdata: if(unit->state != Rawdata) error(Ebadusefd); unit->state = Rawstatus; unit->req->write = 1; return sdrio(unit->req, a, n); } break; case Qpart: return sdbio(c, 1, a, n, off); } return n;}static voidsdwstat(Chan* c, char* dp){ Dir d; SDpart *pp; SDunit *unit; if((c->qid.path & CHDIR) || TYPE(c->qid) != Qpart) error(Eperm); unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); nexterror(); } if(unit->changed) error(Enonexist); pp = &unit->part[PART(c->qid)]; if(!pp->valid) error(Enonexist); if(strncmp(up->user, pp->user, NAMELEN) && !iseve()) error(Eperm); convM2D(dp, &d); strncpy(pp->user, d.uid, NAMELEN); pp->perm = d.mode&0777; qunlock(&unit->ctl); poperror();}Dev sddevtab = { 'S', "sd", sdreset, devinit, sdattach, sdclone, sdwalk, sdstat, sdopen, devcreate, sdclose, sdread, devbread, sdwrite, devbwrite, devremove, sdwstat,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -