📄 devsd.c
字号:
return n; case Qtopdir: case Qunitdir: return devdirread(c, a, n, 0, 0, sdgen); case Qctl: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; m = 16*1024; /* room for register dumps */ p = malloc(m); l = snprint(p, m, "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, m-l); if(unit->sectors == 0) sdinitpart(unit); if(unit->sectors){ if(unit->dev->ifc->rctl == nil) l += snprint(p+l, m-l, "geometry %llud %lud\n", unit->sectors, unit->secsize); pp = unit->part; for(i = 0; i < unit->npart; i++){ if(pp->valid) l += snprint(p+l, m-l, "part %s %llud %llud\n", pp->perm.name, pp->start, pp->end); pp++; } } qunlock(&unit->ctl); decref(&sdev->r); l = readstr(offset, a, n, p); free(p); return l; case Qraw: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); decref(&sdev->r); nexterror(); } if(unit->state == Rawdata){ unit->state = Rawstatus; i = sdrio(unit->req, a, n); } else if(unit->state == Rawstatus){ status = unit->req->status; unit->state = Rawcmd; free(unit->req); unit->req = nil; i = readnum(0, a, n, status, NUMSIZE); } else i = 0; qunlock(&unit->raw); decref(&sdev->r); poperror(); return i; case Qpart: return sdbio(c, 0, a, n, off); }}static void legacytopctl(Cmdbuf*);static longsdwrite(Chan* c, void* a, long n, vlong off){ char *f0; int i; uvlong end, start; Cmdbuf *cb; SDifc *ifc; SDreq *req; SDunit *unit; SDev *sdev; switch(TYPE(c->qid)){ default: error(Eperm); case Qtopctl: cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf == 0) error("empty control message"); f0 = cb->f[0]; cb->f++; cb->nf--; if(strcmp(f0, "config") == 0){ /* wormhole into ugly legacy interface */ legacytopctl(cb); poperror(); free(cb); break; } /* * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb), * where sdifc[i]->name=="ata" and cb contains the args. */ ifc = nil; sdev = nil; for(i=0; sdifc[i]; i++){ if(strcmp(sdifc[i]->name, f0) == 0){ ifc = sdifc[i]; sdev = nil; goto subtopctl; } } /* * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb), * where sdifc[i] and sdev match controller letter "1", * and cb contains the args. */ if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){ if((sdev = sdgetdev(f0[2])) != nil){ ifc = sdev->ifc; goto subtopctl; } } error("unknown interface"); subtopctl: if(waserror()){ if(sdev) decref(&sdev->r); nexterror(); } if(ifc->wtopctl) ifc->wtopctl(sdev, cb); else error(Ebadctl); poperror(); poperror(); if (sdev) decref(&sdev->r); free(cb); break; case Qctl: cb = parsecmd(a, n); sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); decref(&sdev->r); free(cb); nexterror(); } if(unit->vers != c->qid.vers) error(Echange); if(cb->nf < 1) error(Ebadctl); if(strcmp(cb->f[0], "part") == 0){ if(cb->nf != 4) error(Ebadctl); if(unit->sectors == 0 && !sdinitpart(unit)) error(Eio); start = strtoull(cb->f[2], 0, 0); end = strtoull(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); decref(&sdev->r); poperror(); free(cb); break; case Qraw: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); decref(&sdev->r); nexterror(); } 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: unit->state = Rawstatus; unit->req->write = 1; n = sdrio(unit->req, a, n); } qunlock(&unit->raw); decref(&sdev->r); poperror(); break; case Qpart: return sdbio(c, 1, a, n, off); } return n;}static intsdwstat(Chan* c, uchar* dp, int n){ Dir *d; SDpart *pp; SDperm *perm; SDunit *unit; SDev *sdev; if(c->qid.type & QTDIR) error(Eperm); sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); d = nil; if(waserror()){ free(d); qunlock(&unit->ctl); decref(&sdev->r); nexterror(); } switch(TYPE(c->qid)){ default: error(Eperm); case Qctl: perm = &unit->ctlperm; break; case Qraw: perm = &unit->rawperm; break; case Qpart: pp = &unit->part[PART(c->qid)]; if(unit->vers+pp->vers != c->qid.vers) error(Enonexist); perm = &pp->perm; break; } if(strcmp(up->user, perm->user) && !iseve()) error(Eperm); d = smalloc(sizeof(Dir)+n); n = convM2D(dp, n, &d[0], (char*)&d[1]); if(n == 0) error(Eshortstat); if(!emptystr(d[0].uid)) kstrdup(&perm->user, d[0].uid); if(d[0].mode != ~0UL) perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777); free(d); qunlock(&unit->ctl); decref(&sdev->r); poperror(); return n;}static intconfigure(char* spec, DevConf* cf){ SDev *s, *sdev; char *p; int i; if(sdindex(*spec) < 0) error("bad sd spec"); if((p = strchr(cf->type, '/')) != nil) *p++ = '\0'; for(i = 0; sdifc[i] != nil; i++) if(strcmp(sdifc[i]->name, cf->type) == 0) break; if(sdifc[i] == nil) error("sd type not found"); if(p) *(p-1) = '/'; if(sdifc[i]->probe == nil) error("sd type cannot probe"); sdev = sdifc[i]->probe(cf); for(s=sdev; s; s=s->next) s->idno = *spec; sdadddevs(sdev); return 0;}static intunconfigure(char* spec){ int i; SDev *sdev; SDunit *unit; if((i = sdindex(*spec)) < 0) error(Enonexist); qlock(&devslock); if((sdev = devs[i]) == nil){ qunlock(&devslock); error(Enonexist); } if(sdev->r.ref){ qunlock(&devslock); error(Einuse); } devs[i] = nil; qunlock(&devslock); /* make sure no interrupts arrive anymore before removing resources */ if(sdev->enabled && sdev->ifc->disable) sdev->ifc->disable(sdev); for(i = 0; i != sdev->nunit; i++){ if((unit = sdev->unit[i])){ free(unit->perm.name); free(unit->perm.user); free(unit); } } if(sdev->ifc->clear) sdev->ifc->clear(sdev); free(sdev); return 0;}static intsdconfig(int on, char* spec, DevConf* cf){ if(on) return configure(spec, cf); return unconfigure(spec);}Dev sddevtab = { 'S', "sd", sdreset, devinit, devshutdown, sdattach, sdwalk, sdstat, sdopen, devcreate, sdclose, sdread, devbread, sdwrite, devbwrite, devremove, sdwstat, devpower, sdconfig,};/* * This is wrong for so many reasons. This code must go. */typedef struct Confdata Confdata;struct Confdata { int on; char* spec; DevConf cf;};static voidparseswitch(Confdata* cd, char* option){ if(!strcmp("on", option)) cd->on = 1; else if(!strcmp("off", option)) cd->on = 0; else error(Ebadarg);}static voidparsespec(Confdata* cd, char* option){ if(strlen(option) > 1) error(Ebadarg); cd->spec = option;}static Devport*getnewport(DevConf* dc){ Devport *p; p = (Devport *)malloc((dc->nports + 1) * sizeof(Devport)); if(dc->nports > 0){ memmove(p, dc->ports, dc->nports * sizeof(Devport)); free(dc->ports); } dc->ports = p; p = &dc->ports[dc->nports++]; p->size = -1; p->port = (ulong)-1; return p;}static voidparseport(Confdata* cd, char* option){ char *e; Devport *p; if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1) p = getnewport(&cd->cf); else p = &cd->cf.ports[cd->cf.nports-1]; p->port = strtol(option, &e, 0); if(e == nil || *e != '\0') error(Ebadarg);}static voidparsesize(Confdata* cd, char* option){ char *e; Devport *p; if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1) p = getnewport(&cd->cf); else p = &cd->cf.ports[cd->cf.nports-1]; p->size = (int)strtol(option, &e, 0); if(e == nil || *e != '\0') error(Ebadarg);}static voidparseirq(Confdata* cd, char* option){ char *e; cd->cf.intnum = strtoul(option, &e, 0); if(e == nil || *e != '\0') error(Ebadarg);}static voidparsetype(Confdata* cd, char* option){ cd->cf.type = option;}static struct { char *name; void (*parse)(Confdata*, char*);} options[] = { "switch", parseswitch, "spec", parsespec, "port", parseport, "size", parsesize, "irq", parseirq, "type", parsetype,};static voidlegacytopctl(Cmdbuf *cb){ char *opt; int i, j; Confdata cd; memset(&cd, 0, sizeof cd); cd.on = -1; for(i=0; i<cb->nf; i+=2){ if(i+2 > cb->nf) error(Ebadarg); opt = cb->f[i]; for(j=0; j<nelem(options); j++) if(strcmp(opt, options[j].name) == 0){ options[j].parse(&cd, cb->f[i+1]); break; } if(j == nelem(options)) error(Ebadarg); } /* this has been rewritten to accomodate sdaoe */ if(cd.on < 0 || cd.spec == 0) error(Ebadarg); if(cd.on && cd.cf.type == nil) error(Ebadarg); sdconfig(cd.on, cd.spec, &cd.cf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -