| plan 9 kernel history: overview | file list | diff list |
2001/0905/port/devsd.c (diff list | history)
| 2001/0613/sys/src/9/port/devsd.c:15,26 – 2001/0905/sys/src/9/port/devsd.c:15,29 (short | long | prev | next) | ||
| 2000/0506 | extern Dev sddevtab; extern SDifc* sdifc[]; | |
| 2001/0905 | typedef struct { SDev *dt_dev; int dt_nunits; /* num units in dev */ } dev_t; | |
| 2000/0506 | ||
| 2001/0905 | static dev_t *devs; /* all devices */ static QLock devslock; /* insertion and removal of devices */ static int ndevs; /* total number of devices in the system */ | |
| 2000/0506 | enum { Rawcmd, Rawdata, | |
| 2001/0613/sys/src/9/port/devsd.c:30,35 – 2001/0905/sys/src/9/port/devsd.c:33,40 | ||
| 2000/0506 | enum { Qtopdir = 1, /* top level directory */ Qtopbase, | |
| 2001/0905 | Qtopctl = Qtopbase, Qtopstat, | |
| 1994/0913 | ||
| 2000/0506 | Qunitdir, /* directory per unit */ Qunitbase, | |
| 2001/0613/sys/src/9/port/devsd.c:51,63 – 2001/0905/sys/src/9/port/devsd.c:56,78 | ||
| 2001/0613 | NUnit = (1<<UnitLOG), UnitMASK = (NUnit-1), UnitSHIFT = (PartLOG+TypeLOG), | |
| 2001/0905 | DevLOG = 8, NDev = (1 << DevLOG), DevMASK = (NDev-1), DevSHIFT = (UnitLOG+PartLOG+TypeLOG), Ncmd = 20, | |
| 1994/0913 | }; | |
| 2001/0613 | #define TYPE(q) ((((ulong)(q).path)>>TypeSHIFT) & TypeMASK) #define PART(q) ((((ulong)(q).path)>>PartSHIFT) & PartMASK) #define UNIT(q) ((((ulong)(q).path)>>UnitSHIFT) & UnitMASK) | |
| 2001/0905 | #define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK) #define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\ ((p)<<PartSHIFT)|((t)<<TypeSHIFT)) | |
| 2000/0506 | ||
| 2001/0905 | ||
| 2000/0506 | static void sdaddpart(SDunit* unit, char* name, ulong start, ulong end) | |
| 1994/0913 | { | |
| 2001/0613/sys/src/9/port/devsd.c:206,215 – 2001/0905/sys/src/9/port/devsd.c:221,250 | ||
| 1994/0913 | return 1; } | |
| 2001/0905 | static SDev * sdgetdev(int idno) { SDev *sdev; int i; qlock(&devslock); for (i = 0; i != ndevs; i++) if (devs[i].dt_dev->idno == idno) break; if (i == ndevs) sdev = nil; else { sdev = devs[i].dt_dev; incref(&sdev->r); } qunlock(&devslock); return sdev; } | |
| 2000/0506 | static SDunit* sdgetunit(SDev* sdev, int subno) | |
| 1994/0913 | { | |
| 2000/0506 |
| |
| 2001/0527 | char buf[32]; | |
| 1994/0913 | ||
| 2001/0613/sys/src/9/port/devsd.c:219,241 – 2001/0905/sys/src/9/port/devsd.c:254,280 | ||
| 2000/0506 | * The device will be probed if it has not already been * successfully accessed. */ | |
| 2001/0905 | qlock(&sdev->unitlock); if (subno > sdev->nunit) { qunlock(&sdev->unitlock); return nil; } unit = sdev->unit[subno]; | |
| 2000/0506 | if(unit == nil){ | |
| 1995/0405 | /* | |
| 2000/0506 | * Probe the unit only once. This decision * may be a little severe and reviewed later. | |
| 1995/0405 | */ | |
| 2000/0506 |
| |
| 2001/0905 | if(sdev->unitflg[subno]){ qunlock(&sdev->unitlock); | |
| 2000/0506 | return nil; } if((unit = malloc(sizeof(SDunit))) == nil){ | |
| 2001/0905 | qunlock(&sdev->unitlock); | |
| 2000/0506 | return nil; } | |
| 2001/0905 | sdev->unitflg[subno] = 1; | |
| 1995/0329 | ||
| 2000/0506 | if(sdev->enabled == 0 && sdev->ifc->enable) sdev->ifc->enable(sdev); | |
| 2001/0613/sys/src/9/port/devsd.c:254,295 – 2001/0905/sys/src/9/port/devsd.c:293,313 | ||
| 2000/0506 | * sdunit[] array. */ if(unit->dev->ifc->verify(unit) == 0){ | |
| 2001/0905 | qunlock(&sdev->unitlock); | |
| 2000/0506 | free(unit); return nil; } | |
| 2001/0905 | sdev->unit[subno] = unit; | |
| 2000/0506 | } | |
| 1998/0930 | ||
| 2001/0905 | qunlock(&sdev->unitlock); | |
| 2000/0506 | return unit; } | |
| 1994/0913 | ||
| 2000/0506 |
| |
| 1994/0913 | ||
| 2000/0506 |
| |
| 1995/0403 | ||
| 2000/0506 |
| |
| 1995/0403 | ||
| 2000/0506 |
| |
| 1995/0403 | ||
| 2000/0506 | static void sdreset(void) { int i; | |
| 2001/0905 | SDev *sdev, *tail, *sdlist; | |
| 2000/0506 | /* * Probe all configured controllers and make a list | |
| 2001/0613/sys/src/9/port/devsd.c:297,303 – 2001/0905/sys/src/9/port/devsd.c:315,321 | ||
| 2000/0506 | * of units attached and marking each device with an index * into the linear top-level directory array of units. */ | |
| 2001/0905 | tail = sdlist = nil; | |
| 2000/0506 | for(i = 0; sdifc[i] != nil; i++){ if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil) continue; | |
| 2001/0613/sys/src/9/port/devsd.c:305,318 – 2001/0905/sys/src/9/port/devsd.c:323,333 | ||
| 2000/0506 | tail->next = sdev; else sdlist = sdev; | |
| 1994/0913 |
| |
| 2000/0506 |
| |
| 2001/0905 | for(tail = sdev; tail->next != nil; tail = tail->next) ndevs++; ndevs++; | |
| 2000/0506 | } | |
| 1994/0913 | ||
| 2001/0905 | ||
| 2000/0506 | /* * Legacy and option code goes here. This will be hard... */ | |
| 2001/0613/sys/src/9/port/devsd.c:323,339 – 2001/0905/sys/src/9/port/devsd.c:338,345 | ||
| 2000/0506 | * probed and structures allocated when attached. * Allocate controller names for the different types. */ | |
| 2001/0905 | if(ndevs == 0) | |
| 2000/0506 | return; | |
| 2001/0613 |
| |
| 2000/0506 |
| |
| 2000/0515 | /* * BUG: no check is made here or later when a | |
| 2001/0613/sys/src/9/port/devsd.c:342,347 – 2001/0905/sys/src/9/port/devsd.c:348,368 | ||
| 2000/0506 | if(sdifc[i]->id) sdifc[i]->id(sdlist); } | |
| 2001/0905 | /* * The IDs have been set, unlink the sdlist and copy the spec to * the devtab. */ devs = (dev_t *)malloc(ndevs * sizeof(dev_t)); memset(devs, 0, ndevs * sizeof(dev_t)); i = 0; while (sdlist != nil) { devs[i].dt_dev = sdlist; devs[i].dt_nunits = sdlist->nunit; sdlist = sdlist->next; devs[i].dt_dev->next = nil; i++; } | |
| 2000/0506 | } static int | |
| 2001/0613/sys/src/9/port/devsd.c:352,362 – 2001/0905/sys/src/9/port/devsd.c:373,390 | ||
| 2000/0506 | SDpart *pp; | |
| 2000/0706 | SDperm *perm; | |
| 2000/0506 | SDunit *unit; | |
| 2001/0905 | SDev *sdev; int rv; | |
| 2000/0506 | ||
| 2000/0617 |
| |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); assert(sdev); unit = sdev->unit[UNIT(c->qid)]; rv = -1; | |
| 2000/0506 | switch(i){ case Qctl: | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl), unit->vers, QTFILE); | |
| 2000/0706 | perm = &unit->ctlperm; | |
| 2001/0527 | if(emptystr(perm->user)){ kstrdup(&perm->user, eve); | |
| 2001/0613/sys/src/9/port/devsd.c:363,371 – 2001/0905/sys/src/9/port/devsd.c:391,402 | ||
| 2000/0706 | perm->perm = 0640; } devdir(c, q, "ctl", 0, perm->user, perm->perm, dp); | |
| 2000/0506 |
| |
| 2001/0905 | rv = 1; break; | |
| 2000/0506 | case Qraw: | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw), unit->vers, QTFILE); | |
| 2000/0706 | perm = &unit->rawperm; | |
| 2001/0527 | if(emptystr(perm->user)){ kstrdup(&perm->user, eve); | |
| 2001/0613/sys/src/9/port/devsd.c:372,396 – 2001/0905/sys/src/9/port/devsd.c:403,441 | ||
| 2001/0527 | perm->perm = DMEXCL|0600; | |
| 2000/0706 | } devdir(c, q, "raw", 0, perm->user, perm->perm, dp); | |
| 2000/0506 |
| |
| 2001/0905 | rv = 1; break; | |
| 2000/0506 | case Qpart: pp = &unit->part[PART(c->qid)]; l = (pp->end - pp->start) * (vlong)unit->secsize; | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers, QTFILE); | |
| 2001/0527 | if(emptystr(pp->user)) kstrdup(&pp->user, eve); | |
| 2000/0506 | devdir(c, q, pp->name, l, pp->user, pp->perm, dp); | |
| 2001/0905 | rv = 1; break; } decref(&sdev->r); return rv; | |
| 2000/0506 | } static int | |
| 2001/0905 | sd1gen(Chan* c, int i, Dir* dp) | |
| 2000/0506 | { | |
| 2001/0905 | Qid q; | |
| 2000/0506 | switch(i){ | |
| 2001/0905 | case Qtopctl: mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE); devdir(c, q, "sdctl", 0, eve, 0640, dp); return 1; case Qtopstat: mkqid(&q, QID(0, 0, 0, Qtopstat), 0, QTFILE); devdir(c, q, "sdstat", 0, eve, 0640, dp); return 1; | |
| 2000/0506 | } return -1; } | |
| 2001/0613/sys/src/9/port/devsd.c:403,438 – 2001/0905/sys/src/9/port/devsd.c:448,517 | ||
| 2000/0506 | int i, r; SDpart *pp; SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | switch(TYPE(c->qid)){ | |
| 2001/0905 | case Qtopdir: { | |
| 2000/0506 | if(s == DEVDOTDOT){ | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); | |
| 2001/0527 | sprint(up->genbuf, "#%C", sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); | |
| 2000/0506 | return 1; | |
| 1994/0913 | } | |
| 2000/0506 |
| |
| 2000/0706 |
| |
| 2001/0527 |
| |
| 2000/0706 |
| |
| 2000/0506 |
| |
| 2001/0905 | if (s == 0 || s == 1) return sd1gen(c, s + Qtopbase, dp); s -= 2; qlock(&devslock); for (i = 0; i != ndevs; i++) { if (s < devs[i].dt_nunits) break; s -= devs[i].dt_nunits; | |
| 2000/0506 | } | |
| 2001/0905 | if (i == ndevs) { /* Run of the end of the list */ qunlock(&devslock); return -1; } if ((sdev = devs[i].dt_dev) == nil) { qunlock(&devslock); return 0; } incref(&sdev->r); qunlock(&devslock); if((unit = sdev->unit[s]) == nil) if((unit = sdgetunit(sdev, s)) == nil) { decref(&sdev->r); return 0; } mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR); if(emptystr(unit->user)) kstrdup(&unit->user, eve); devdir(c, q, unit->name, 0, unit->user, unit->perm, dp); decref(&sdev->r); return 1; } | |
| 2000/0506 | case Qunitdir: if(s == DEVDOTDOT){ | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); | |
| 2001/0527 | sprint(up->genbuf, "#%C", sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); | |
| 2000/0506 | return 1; } | |
| 2001/0905 | if ((sdev = sdgetdev(DEV(c->qid))) == nil) { devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/0506 | qlock(&unit->ctl); | |
| 2000/0617 | /* | |
| 2001/0613/sys/src/9/port/devsd.c:450,481 – 2001/0905/sys/src/9/port/devsd.c:529,570 | ||
| 2000/0506 | if(i < Qpart){ r = sd2gen(c, i, dp); qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return r; } i -= Qpart; | |
| 2000/0809 | if(unit->part == nil || i >= unit->npart){ | |
| 2000/0506 | qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | break; } pp = &unit->part[i]; | |
| 2000/0617 | if(!pp->valid){ | |
| 2000/0506 | qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return 0; } l = (pp->end - pp->start) * (vlong)unit->secsize; | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart), unit->vers+pp->vers, QTFILE); | |
| 2001/0527 | if(emptystr(pp->user)) kstrdup(&pp->user, eve); | |
| 2000/0506 | devdir(c, q, pp->name, l, pp->user, pp->perm, dp); qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return 1; case Qraw: case Qctl: case Qpart: | |
| 2001/0905 | if ((sdev = sdgetdev(DEV(c->qid))) == nil) { devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/0506 | qlock(&unit->ctl); r = sd2gen(c, TYPE(c->qid), dp); qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return r; default: break; | |
| 2001/0613/sys/src/9/port/devsd.c:490,500 – 2001/0905/sys/src/9/port/devsd.c:579,589 | ||
| 2000/0506 | Chan *c; char *p; SDev *sdev; | |
| 2001/0905 | int idno, subno, i; | |
| 1994/0913 | ||
| 2000/0506 |
| |
| 2001/0905 | if(ndevs == 0 || *spec == '\0'){ | |
| 2000/0506 | c = devattach(sddevtab.dc, spec); | |
| 2001/0527 |
| |
| 2001/0905 | mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR); | |
| 2000/0506 | return c; | |
| 1996/0607 | } | |
| 1998/0512 | ||
| 2001/0613/sys/src/9/port/devsd.c:504,519 – 2001/0905/sys/src/9/port/devsd.c:593,615 | ||
| 2000/0506 | subno = strtol(&spec[3], &p, 0); if(p == &spec[3]) error(Ebadspec); | |
| 2001/0905 | qlock(&devslock); for (sdev = nil, i = 0; i != ndevs; i++) if ((sdev = devs[i].dt_dev) != nil && sdev->idno == idno) | |
| 2000/0506 | break; | |
| 2001/0905 | if (i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil) { qunlock(&devslock); | |
| 2000/0506 | error(Enonexist); | |
| 2001/0905 | } incref(&sdev->r); qunlock(&devslock); | |
| 2000/0506 | c = devattach(sddevtab.dc, spec); | |
| 2001/0527 |
| |
| 2000/0506 |
| |
| 2001/0905 | mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR); c->dev = (sdev->idno << UnitLOG) + subno; decref(&sdev->r); | |
| 2000/0506 | return c; | |
| 1994/0913 | } | |
| 2001/0613/sys/src/9/port/devsd.c:534,550 – 2001/0905/sys/src/9/port/devsd.c:630,652 | ||
| 1994/0913 | { | |
| 2000/0506 | SDpart *pp; SDunit *unit; | |
| 2001/0905 | SDev *sdev; uchar tp; | |
| 2000/0506 | c = devopen(c, omode, 0, 0, sdgen); | |
| 2001/0905 | if ((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart) return c; sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/0506 | switch(TYPE(c->qid)){ | |
| 2000/0617 | case Qctl: | |
| 2000/0526 | case Qraw: | |
| 2000/0617 | c->qid.vers = unit->vers; | |
| 2000/0531 | if(!canlock(&unit->rawinuse)){ c->flag &= ~COPEN; | |
| 2001/0613/sys/src/9/port/devsd.c:553,559 – 2001/0905/sys/src/9/port/devsd.c:655,660 | ||
| 2000/0526 | unit->state = Rawcmd; break; | |
| 2000/0506 | case Qpart: | |
| 2001/0613/sys/src/9/port/devsd.c:566,571 – 2001/0905/sys/src/9/port/devsd.c:667,673 | ||
| 2000/0506 | poperror(); break; } | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return c; | |
| 1994/0913 | } | |
| 2001/0613/sys/src/9/port/devsd.c:573,578 – 2001/0905/sys/src/9/port/devsd.c:675,681 | ||
| 2000/0506 | sdclose(Chan* c) | |
| 1994/0913 | { | |
| 2000/0506 | SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 1994/0913 | ||
| 2001/0527 | if(c->qid.type & QTDIR) | |
| 1994/0913 | return; | |
| 2001/0613/sys/src/9/port/devsd.c:583,590 – 2001/0905/sys/src/9/port/devsd.c:686,697 | ||
| 2000/0506 | default: break; case Qraw: | |
| 2000/0526 |
| |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev) { unit = sdev->unit[UNIT(c->qid)]; unlock(&unit->rawinuse); decref(&sdev->r); } | |
| 2000/0506 | break; | |
| 1996/0607 | } | |
| 1994/0913 | } | |
| 2001/0613/sys/src/9/port/devsd.c:597,605 – 2001/0905/sys/src/9/port/devsd.c:704,718 | ||
| 2000/0506 | uchar *b; SDpart *pp; SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | ulong bno, max, nb, offset; | |
| 1998/0319 | ||
| 2000/0506 |
| |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; if (unit == nil) error(Enonexist); | |
| 1994/0913 | ||
| 2000/0617 | nchange = 0; | |
| 2000/0506 | qlock(&unit->ctl); | |
| 2001/0613/sys/src/9/port/devsd.c:612,617 – 2001/0905/sys/src/9/port/devsd.c:725,731 | ||
| 2000/0617 | /* other errors; give up */ | |
| 2000/0506 | qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | nexterror(); } | |
| 2000/0617 | pp = &unit->part[PART(c->qid)]; | |
| 2001/0613/sys/src/9/port/devsd.c:640,645 – 2001/0905/sys/src/9/port/devsd.c:754,760 | ||
| 2000/0506 | if(write) error(Eio); qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | poperror(); return 0; } | |
| 2001/0613/sys/src/9/port/devsd.c:653,658 – 2001/0905/sys/src/9/port/devsd.c:768,775 | ||
| 2000/0506 | error(Enomem); if(waserror()){ sdfree(b); | |
| 2001/0905 | if(!(unit->inquiry[1] & 0x80)) decref(&sdev->r); /* gadverdamme! */ | |
| 2000/0506 | nexterror(); } | |
| 1996/0607 | ||
| 2001/0613/sys/src/9/port/devsd.c:696,701 – 2001/0905/sys/src/9/port/devsd.c:813,819 | ||
| 2000/0506 | poperror(); } | |
| 1997/0408 | ||
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | return len; } | |
| 1994/0913 | ||
| 2001/0613/sys/src/9/port/devsd.c:742,750 – 2001/0905/sys/src/9/port/devsd.c:860,869 | ||
| 2000/0506 | static long sdread(Chan *c, void *a, long n, vlong off) { | |
| 2001/0905 | char *p, *e, *buf; | |
| 2000/0506 | SDpart *pp; SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | ulong offset; int i, l, status; | |
| 1994/0913 | ||
| 2001/0613/sys/src/9/port/devsd.c:752,762 – 2001/0905/sys/src/9/port/devsd.c:871,904 | ||
| 2000/0506 | switch(TYPE(c->qid)){ default: error(Eperm); | |
| 2001/0905 | case Qtopstat: p = buf = malloc(READSTR); assert(p); e = p + READSTR; qlock(&devslock); for (i = 0; i != ndevs; i++) { SDev *sdev = devs[i].dt_dev; if (sdev->ifc->stat) p = sdev->ifc->stat(sdev, p, e); else p = seprint(e, "%s; no statistics available\n", sdev->name); } qunlock(&devslock); n = readstr(off, a, n, buf); free(buf); return n; | |
| 2000/0506 | case Qtopdir: case Qunitdir: return devdirread(c, a, n, 0, 0, sdgen); | |
| 2001/0905 | ||
| 2000/0506 | case Qctl: | |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/0506 | p = malloc(READSTR); l = snprint(p, READSTR, "inquiry %.48s\n", (char*)unit->inquiry+8); | |
| 2001/0613/sys/src/9/port/devsd.c:785,798 – 2001/0905/sys/src/9/port/devsd.c:927,947 | ||
| 2000/0506 | } | |
| 2000/0104 | } | |
| 2000/0506 | qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | l = readstr(offset, a, n, p); free(p); return l; | |
| 2001/0905 | ||
| 2000/0506 | case Qraw: | |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/1129 | qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/1129 | nexterror(); } | |
| 2000/0506 | if(unit->state == Rawdata){ | |
| 2001/0613/sys/src/9/port/devsd.c:808,815 – 2001/0905/sys/src/9/port/devsd.c:957,966 | ||
| 2000/1129 | } else i = 0; qunlock(&unit->raw); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/1129 | poperror(); return i; | |
| 2001/0905 | ||
| 2000/0506 | case Qpart: return sdbio(c, 0, a, n, off); | |
| 1994/0913 | } | |
| 2001/0613/sys/src/9/port/devsd.c:817,822 – 2001/0905/sys/src/9/port/devsd.c:968,1070 | ||
| 2000/0506 | return 0; | |
| 1994/0913 | } | |
| 2001/0905 | typedef struct { int o_on; char *o_spec; DevConf o_cf; } confdata_t; static void parse_switch(confdata_t *cd, char *option) { if (!strcmp("on", option)) cd->o_on = 1; else if (!strcmp("off", option)) cd->o_on = 0; else error(Ebadarg); } static void parse_spec(confdata_t *cd, char *option) { if (strlen(option) > 1) error(Ebadarg); cd->o_spec = option; } static port_t * getnewport(DevConf *dc) { port_t *p; p = (port_t *)malloc((dc->nports + 1) * sizeof(port_t)); if (dc->nports > 0) { memmove(p, dc->ports, dc->nports * sizeof(port_t)); free(dc->ports); } dc->ports = p; p = &dc->ports[dc->nports++]; p->size = -1; p->port = (ulong)-1; return p; } static void parse_port(confdata_t *cd, char *option) { char *e; port_t *p; p = (cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports -1].port != (ulong)-1)? getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; p->port = strtol(option, &e, 0); if (e == nil || *e != '\0') error(Ebadarg); } static void parse_size(confdata_t *cd, char *option) { char *e; port_t *p; p = (cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports -1].size != -1)? getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; p->size = (int)strtol(option, &e, 0); if (e == nil || *e != '\0') error(Ebadarg); } static void parse_irq(confdata_t *cd, char *option) { char *e; cd->o_cf.interrupt = strtoul(option, &e, 0); if (e == nil || *e != '\0') error(Ebadarg); } static void parse_type(confdata_t *cd, char *option) { cd->o_cf.type = option; } static struct { char *option; void (*parse)(confdata_t *, char *); } options[] = { { "switch", parse_switch, }, { "spec", parse_spec, }, { "port", parse_port, }, { "size", parse_size, }, { "irq", parse_irq, }, { "type", parse_type, }, }; | |
| 1994/0913 | static long | |
| 2000/0506 | sdwrite(Chan *c, void *a, long n, vlong off) | |
| 1994/0913 | { | |
| 2001/0613/sys/src/9/port/devsd.c:823,840 – 2001/0905/sys/src/9/port/devsd.c:1071,1139 | ||
| 2000/0506 | Cmdbuf *cb; SDreq *req; SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | ulong end, start; | |
| 1994/0913 | ||
| 2000/0506 | switch(TYPE(c->qid)){ default: error(Eperm); | |
| 2001/0905 | case Qtopctl: { confdata_t cd; char buf[256], *field[Ncmd]; int nf, i, j; memset(&cd, 0, sizeof(confdata_t)); if(n > sizeof(buf)-1) n = sizeof(buf)-1; memmove(buf, a, n); buf[n] = '\0'; cd.o_on = -1; cd.o_spec = '\0'; memset(&cd.o_cf, 0, sizeof(DevConf)); nf = getfields(buf, field, Ncmd, 1, " \t\n"); for (i = 0; i < nf; i++) { char *opt = field[i++]; if (i >= nf) error(Ebadarg); for (j = 0; j != nelem(options); j++) if (!strcmp(opt, options[j].option)) break; if (j == nelem(options)) error(Ebadarg); options[j].parse(&cd, field[i]); } if (cd.o_on < 0) error(Ebadarg); if (cd.o_on) { if (cd.o_spec == '\0' || cd.o_cf.nports == 0 || cd.o_cf.interrupt == 0 || cd.o_cf.type == nil) error(Ebadarg); } else { if (cd.o_spec == '\0') error(Ebadarg); } if (sddevtab.config == nil) error("No configuration function"); sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); break; } | |
| 2000/0506 | case Qctl: cb = parsecmd(a, n); | |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 1995/0403 | ||
| 2000/0506 | qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | free(cb); nexterror(); } | |
| 2001/0613/sys/src/9/port/devsd.c:862,876 – 2001/0905/sys/src/9/port/devsd.c:1161,1180 | ||
| 2000/0506 | else error(Ebadctl); qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | poperror(); free(cb); break; | |
| 2000/0526 | ||
| 2000/0506 | case Qraw: | |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/1129 | qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/1129 | nexterror(); } | |
| 2000/0526 | switch(unit->state){ | |
| 2001/0613/sys/src/9/port/devsd.c:904,909 – 2001/0905/sys/src/9/port/devsd.c:1208,1214 | ||
| 2000/1129 | n = sdrio(unit->req, a, n); | |
| 1996/0607 | } | |
| 2000/1129 | qunlock(&unit->raw); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/1129 | poperror(); | |
| 2001/0527 | break; | |
| 2000/0506 | case Qpart: | |
| 2001/0613/sys/src/9/port/devsd.c:920,933 – 2001/0905/sys/src/9/port/devsd.c:1225,1243 | ||
| 2000/0506 | SDpart *pp; | |
| 2000/0706 | SDperm *perm; | |
| 2000/0506 | SDunit *unit; | |
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | ||
| 2001/0527 | if(c->qid.type & QTDIR) | |
| 2000/0506 |
| |
| 2001/0905 | error(Eperm); | |
| 2000/0506 |
| |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/0506 | qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | nexterror(); | |
| 1994/0913 | } | |
| 1996/0607 | ||
| 2001/0613/sys/src/9/port/devsd.c:957,966 – 2001/0905/sys/src/9/port/devsd.c:1267,1428 | ||
| 2001/0527 | perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777); | |
| 2000/0506 | qunlock(&unit->ctl); | |
| 2001/0905 | decref(&sdev->r); | |
| 2000/0506 | poperror(); | |
| 2001/0527 | return n; | |
| 1994/0913 | } | |
| 2000/0506 | ||
| 2001/0905 | static char getspec(char base) { while (1) { int i; SDev *sdev; for (i = 0; i != ndevs; i++) if ((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base) break; if (i == ndevs) return base; base++; } return '\0'; } static int configure(char *spec, DevConf *cf) { ISAConf isa; dev_t *_devs; SDev *tail, *sdev, *(*probe)(DevConf *); char *p, name[32]; int i, added_devs; if ((p = strchr(cf->type, '/')) != nil) *p++ = '\0'; for(i = 0; sdifc[i] != nil; i++) if(!strcmp(sdifc[i]->name, cf->type)) break; if (sdifc[i] == nil) error("type not found"); if ((probe = sdifc[i]->probe) == nil) error("No probe function"); if (p) { /* Try to find the card on the ISA bus. This code really belongs in sdata and I'll move it later. Really! */ memset(&isa, 0, sizeof(isa)); isa.port = cf->ports[0].port; isa.irq = cf->interrupt; if (pcmspecial(p, &isa) < 0) error("Cannot find controller"); } qlock(&devslock); if (waserror()) { qunlock(&devslock); nexterror(); } for (i = 0; i != ndevs; i++) if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) break; if (i != ndevs) error(Eexist); if ((sdev = (*probe)(cf)) == nil) error("Cannot probe controller"); poperror(); added_devs = 0; tail = sdev; while (tail) { added_devs++; tail = tail->next; } _devs = (dev_t *)malloc((ndevs + added_devs) * sizeof(dev_t)); memmove(_devs, devs, ndevs * sizeof(dev_t)); free(devs); devs = _devs; while (sdev) { /* Assign `spec' to the device */ *spec = getspec(*spec); snprint(name, sizeof(name), "sd%c", *spec); kstrdup(&sdev->name, name); sdev->idno = *spec; devs[ndevs].dt_dev = sdev; devs[ndevs].dt_nunits = sdev->nunit; sdev = sdev->next; devs[ndevs].dt_dev->next = nil; ndevs++; } qunlock(&devslock); return 0; } static int unconfigure(char *spec) { int i; SDev *sdev; qlock(&devslock); if (waserror()) { qunlock(&devslock); nexterror(); } for (sdev = nil, i = 0; i != ndevs; i++) if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) break; if (i == ndevs) error(Enonexist); if (sdev->r.ref) error(Einuse); /* make sure no interrupts arrive anymore before removing resources */ if (sdev->enabled && sdev->ifc->disable) sdev->ifc->disable(sdev); /* we're alone and the device tab is locked; make the device unavailable */ memmove(&devs[i], &devs[ndevs - 1], sizeof(dev_t)); memset(&devs[ndevs - 1], 0, sizeof(dev_t)); ndevs--; qunlock(&devslock); poperror(); for (i = 0; i != sdev->nunit; i++) if (sdev->unit[i]) { SDunit *unit = sdev->unit[i]; free(unit->name); free(unit->user); free(unit); } if (sdev->ifc->clear) sdev->ifc->clear(sdev); return 0; } static int sdconfig(int on, char *spec, DevConf *cf) { return on? configure(spec, cf): unconfigure(spec); } | |
| 2000/0506 | Dev sddevtab = { 'S', "sd", | |
| 2001/0613/sys/src/9/port/devsd.c:979,982 – 2001/0905/sys/src/9/port/devsd.c:1441,1446 | ||
| 2000/0506 | devbwrite, devremove, sdwstat, | |
| 2001/0905 | devpower, sdconfig, | |
| 2000/0506 | }; | |