| plan 9 kernel history: overview | file list | diff list |
2002/0316/port/devsd.c (diff list | history)
| 2002/0109/sys/src/9/port/devsd.c:16,28 – 2002/0316/sys/src/9/port/devsd.c:16,28 (short | long | prev | next) | ||
| 2000/0506 | extern SDifc* sdifc[]; | |
| 2001/0905 | typedef struct { | |
| 2002/0316 | SDev* dt_dev; int dt_nunits; /* num units in dev */ | |
| 2001/0905 | } dev_t; | |
| 2000/0506 | ||
| 2001/0905 |
| |
| 2002/0316 | static dev_t* devs; /* all devices */ static QLock devslock; /* insertion and removal of devices */ static int ndevs; /* total number of devices in the system */ | |
| 2001/0905 | ||
| 2000/0506 | enum { Rawcmd, | |
| 2002/0109/sys/src/9/port/devsd.c:68,74 – 2002/0316/sys/src/9/port/devsd.c:68,74 | ||
| 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 |
| |
| 2002/0316 | #define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK) | |
| 2001/0905 | #define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\ ((p)<<PartSHIFT)|((t)<<TypeSHIFT)) | |
| 2000/0506 | ||
| 2002/0109/sys/src/9/port/devsd.c:221,227 – 2002/0316/sys/src/9/port/devsd.c:221,227 | ||
| 1994/0913 | return 1; } | |
| 2001/0905 |
| |
| 2002/0316 | static SDev* | |
| 2001/0905 | sdgetdev(int idno) { SDev *sdev; | |
| 2002/0109/sys/src/9/port/devsd.c:228,240 – 2002/0316/sys/src/9/port/devsd.c:228,240 | ||
| 2001/0905 | int i; qlock(&devslock); | |
| 2002/0316 | for(i = 0; i != ndevs; i++) | |
| 2001/0905 | if (devs[i].dt_dev->idno == idno) break; | |
| 2002/0316 | if(i == ndevs) | |
| 2001/0905 | sdev = nil; | |
| 2002/0316 | else{ | |
| 2001/0905 | sdev = devs[i].dt_dev; incref(&sdev->r); } | |
| 2002/0109/sys/src/9/port/devsd.c:255,261 – 2002/0316/sys/src/9/port/devsd.c:255,261 | ||
| 2000/0506 | * successfully accessed. */ | |
| 2001/0905 | qlock(&sdev->unitlock); | |
| 2002/0316 | if(subno > sdev->nunit){ | |
| 2001/0905 | qunlock(&sdev->unitlock); return nil; } | |
| 2002/0109/sys/src/9/port/devsd.c:323,336 – 2002/0316/sys/src/9/port/devsd.c:323,336 | ||
| 2000/0506 | tail->next = sdev; else sdlist = sdev; | |
| 2001/0907 |
| |
| 2002/0316 | for(tail = sdev; tail->next != nil; tail = tail->next){ tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*)); tail->unitflg = (int*)malloc(tail->nunit * sizeof(int)); | |
| 2001/0907 | assert(tail->unit && tail->unitflg); | |
| 2001/0905 | ndevs++; | |
| 2001/0907 | } | |
| 2002/0316 | tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*)); tail->unitflg = (int*)malloc(tail->nunit * sizeof(int)); | |
| 2001/0905 | ndevs++; | |
| 2000/0506 | } | |
| 2001/0905 | ||
| 2002/0109/sys/src/9/port/devsd.c:359,368 – 2002/0316/sys/src/9/port/devsd.c:359,368 | ||
| 2001/0905 | * The IDs have been set, unlink the sdlist and copy the spec to * the devtab. */ | |
| 2002/0316 | devs = (dev_t*)malloc(ndevs * sizeof(dev_t)); | |
| 2001/0905 | memset(devs, 0, ndevs * sizeof(dev_t)); i = 0; | |
| 2002/0316 | while(sdlist != nil){ | |
| 2001/0905 | devs[i].dt_dev = sdlist; devs[i].dt_nunits = sdlist->nunit; sdlist = sdlist->next; | |
| 2002/0109/sys/src/9/port/devsd.c:457,463 – 2002/0316/sys/src/9/port/devsd.c:457,463 | ||
| 2001/0905 | SDev *sdev; | |
| 2000/0506 | switch(TYPE(c->qid)){ | |
| 2001/0905 |
| |
| 2002/0316 | case Qtopdir: | |
| 2000/0506 | if(s == DEVDOTDOT){ | |
| 2001/0905 | mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); | |
| 2001/0527 | sprint(up->genbuf, "#%C", sddevtab.dc); | |
| 2002/0109/sys/src/9/port/devsd.c:465,488 – 2002/0316/sys/src/9/port/devsd.c:465,488 | ||
| 2000/0506 | return 1; | |
| 1994/0913 | } | |
| 2001/0905 |
| |
| 2002/0316 | if(s == 0 || s == 1) | |
| 2001/0905 | return sd1gen(c, s + Qtopbase, dp); s -= 2; qlock(&devslock); | |
| 2002/0316 | for(i = 0; i != ndevs; i++){ | |
| 2001/0905 | if (s < devs[i].dt_nunits) break; s -= devs[i].dt_nunits; | |
| 2000/0506 | } | |
| 2001/0905 |
| |
| 2002/0316 | if(i == ndevs){ | |
| 2001/0905 | /* Run of the end of the list */ qunlock(&devslock); return -1; } | |
| 2002/0316 | if ((sdev = devs[i].dt_dev) == nil){ | |
| 2001/0905 | qunlock(&devslock); return 0; } | |
| 2002/0109/sys/src/9/port/devsd.c:491,497 – 2002/0316/sys/src/9/port/devsd.c:491,497 | ||
| 2001/0905 | qunlock(&devslock); if((unit = sdev->unit[s]) == nil) | |
| 2002/0316 | if((unit = sdgetunit(sdev, s)) == nil){ | |
| 2001/0905 | decref(&sdev->r); return 0; } | |
| 2002/0109/sys/src/9/port/devsd.c:502,508 – 2002/0316/sys/src/9/port/devsd.c:502,507 | ||
| 2001/0905 | devdir(c, q, unit->name, 0, unit->user, unit->perm, dp); decref(&sdev->r); return 1; | |
| 2000/0506 | case Qunitdir: if(s == DEVDOTDOT){ | |
| 2002/0109/sys/src/9/port/devsd.c:512,518 – 2002/0316/sys/src/9/port/devsd.c:511,517 | ||
| 2000/0506 | return 1; } | |
| 2001/0905 |
| |
| 2002/0316 | if((sdev = sdgetdev(DEV(c->qid))) == nil){ | |
| 2001/0905 | devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } | |
| 2002/0109/sys/src/9/port/devsd.c:562,568 – 2002/0316/sys/src/9/port/devsd.c:561,567 | ||
| 2000/0506 | case Qraw: case Qctl: case Qpart: | |
| 2001/0905 |
| |
| 2002/0316 | if((sdev = sdgetdev(DEV(c->qid))) == nil){ | |
| 2001/0905 | devdir(c, q, "unavailable", 0, eve, 0, dp); return 1; } | |
| 2002/0109/sys/src/9/port/devsd.c:608,614 – 2002/0316/sys/src/9/port/devsd.c:607,613 | ||
| 2001/0905 | if ((sdev = devs[i].dt_dev) != nil && sdev->idno == idno) | |
| 2000/0506 | break; | |
| 2001/0905 |
| |
| 2002/0316 | if(i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil){ | |
| 2001/0905 | qunlock(&devslock); | |
| 2000/0506 | error(Enonexist); | |
| 2001/0905 | } | |
| 2002/0109/sys/src/9/port/devsd.c:643,653 – 2002/0316/sys/src/9/port/devsd.c:642,652 | ||
| 2001/0905 | uchar tp; | |
| 2000/0506 | c = devopen(c, omode, 0, 0, sdgen); | |
| 2001/0905 |
| |
| 2002/0316 | if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart) | |
| 2001/0905 | return c; sdev = sdgetdev(DEV(c->qid)); | |
| 2002/0316 | if(sdev == nil) | |
| 2001/0905 | error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2002/0109/sys/src/9/port/devsd.c:717,726 – 2002/0316/sys/src/9/port/devsd.c:716,725 | ||
| 2000/0506 | ulong bno, max, nb, offset; | |
| 1998/0319 | ||
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); | |
| 2002/0316 | if(sdev == nil) | |
| 2001/0905 | error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2002/0316 | if(unit == nil) | |
| 2001/0905 | error(Enonexist); | |
| 1994/0913 | ||
| 2000/0617 | nchange = 0; | |
| 2002/0109/sys/src/9/port/devsd.c:804,810 – 2002/0316/sys/src/9/port/devsd.c:803,809 | ||
| 2000/0506 | else if(len > l - offset) len = l - offset; } | |
| 2002/0316 | else{ | |
| 2000/0524 | l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) | |
| 2000/0506 | error(Eio); | |
| 2002/0109/sys/src/9/port/devsd.c:885,894 – 2002/0316/sys/src/9/port/devsd.c:884,893 | ||
| 2001/0905 | assert(p); e = p + READSTR; qlock(&devslock); | |
| 2002/0316 | for(i = 0; i != ndevs; i++){ | |
| 2001/0905 | SDev *sdev = devs[i].dt_dev; | |
| 2002/0316 | if(sdev->ifc->stat) | |
| 2001/0905 | p = sdev->ifc->stat(sdev, p, e); else p = seprint(e, "%s; no statistics available\n", sdev->name); | |
| 2002/0109/sys/src/9/port/devsd.c:978,994 – 2002/0316/sys/src/9/port/devsd.c:977,993 | ||
| 1994/0913 | } | |
| 2001/0905 | typedef struct { | |
| 2002/0316 | int o_on; char* o_spec; | |
| 2001/0905 | DevConf o_cf; } confdata_t; static void | |
| 2002/0316 | parse_switch(confdata_t* cd, char* option) | |
| 2001/0905 | { | |
| 2002/0316 | if(!strcmp("on", option)) | |
| 2001/0905 | cd->o_on = 1; | |
| 2002/0316 | else if(!strcmp("off", option)) | |
| 2001/0905 | cd->o_on = 0; else error(Ebadarg); | |
| 2002/0109/sys/src/9/port/devsd.c:995,1014 – 2002/0316/sys/src/9/port/devsd.c:994,1013 | ||
| 2001/0905 | } static void | |
| 2002/0316 | parse_spec(confdata_t* cd, char* option) | |
| 2001/0905 | { | |
| 2002/0316 | if(strlen(option) > 1) | |
| 2001/0905 | error(Ebadarg); cd->o_spec = option; } | |
| 2002/0316 | static port_t* getnewport(DevConf* dc) | |
| 2001/0905 | { port_t *p; p = (port_t *)malloc((dc->nports + 1) * sizeof(port_t)); | |
| 2002/0316 | if(dc->nports > 0){ | |
| 2001/0905 | memmove(p, dc->ports, dc->nports * sizeof(port_t)); free(dc->ports); } | |
| 2002/0109/sys/src/9/port/devsd.c:1020,1081 – 2002/0316/sys/src/9/port/devsd.c:1019,1083 | ||
| 2001/0905 | } static void | |
| 2002/0316 | parse_port(confdata_t* cd, char* option) | |
| 2001/0905 | { char *e; port_t *p; | |
| 2002/0316 | if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].port != (ulong)-1) p = getnewport(&cd->o_cf); else p = &cd->o_cf.ports[cd->o_cf.nports-1]; | |
| 2001/0905 | p->port = strtol(option, &e, 0); | |
| 2002/0316 | if(e == nil || *e != '\0') | |
| 2001/0905 | error(Ebadarg); } static void | |
| 2002/0316 | parse_size(confdata_t* cd, char* option) | |
| 2001/0905 | { char *e; port_t *p; | |
| 2002/0316 | if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].size != -1) p = getnewport(&cd->o_cf); else p = &cd->o_cf.ports[cd->o_cf.nports-1]; p->size = (int)strtol(option, &e, 0); if(e == nil || *e != '\0') | |
| 2001/0905 | error(Ebadarg); } static void | |
| 2002/0316 | parse_irq(confdata_t* cd, char* option) | |
| 2001/0905 | { char *e; cd->o_cf.interrupt = strtoul(option, &e, 0); | |
| 2002/0316 | if(e == nil || *e != '\0') | |
| 2001/0905 | error(Ebadarg); } static void | |
| 2002/0316 | parse_type(confdata_t* cd, char* option) | |
| 2001/0905 | { cd->o_cf.type = option; } static struct { | |
| 2002/0316 | char *option; void (*parse)(confdata_t*, char*); | |
| 2001/0905 | } options[] = { | |
| 2002/0316 | { "switch", parse_switch, }, | |
| 2001/0905 | { "spec", parse_spec, }, { "port", parse_port, }, { "size", parse_size, }, | |
| 2002/0316 | { "irq", parse_irq, }, | |
| 2001/0905 | { "type", parse_type, }, }; | |
| 1994/0913 | static long | |
| 2000/0506 |
| |
| 2002/0316 | sdwrite(Chan* c, void* a, long n, vlong off) | |
| 1994/0913 | { | |
| 2000/0506 | Cmdbuf *cb; SDreq *req; | |
| 2002/0109/sys/src/9/port/devsd.c:1101,1133 – 2002/0316/sys/src/9/port/devsd.c:1103,1135 | ||
| 2001/0905 | memset(&cd.o_cf, 0, sizeof(DevConf)); | |
| 2001/1117 | nf = tokenize(buf, field, Ncmd); | |
| 2001/0905 |
| |
| 2002/0316 | for(i = 0; i < nf; i++){ | |
| 2001/0905 | char *opt = field[i++]; | |
| 2002/0316 | if(i >= nf) | |
| 2001/0905 | error(Ebadarg); | |
| 2002/0316 | for(j = 0; j != nelem(options); j++) if(!strcmp(opt, options[j].option)) | |
| 2001/0905 | break; | |
| 2002/0316 | if(j == nelem(options)) | |
| 2001/0905 | error(Ebadarg); options[j].parse(&cd, field[i]); } | |
| 2002/0316 | if(cd.o_on < 0) | |
| 2001/0905 | error(Ebadarg); | |
| 2002/0316 | if(cd.o_on){ if(cd.o_spec == '\0' || cd.o_cf.nports == 0 || | |
| 2001/0905 | cd.o_cf.interrupt == 0 || cd.o_cf.type == nil) error(Ebadarg); } | |
| 2002/0316 | else{ if(cd.o_spec == '\0') | |
| 2001/0905 | error(Ebadarg); } | |
| 2002/0316 | if(sddevtab.config == nil) | |
| 2001/0905 | error("No configuration function"); sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); break; | |
| 2002/0109/sys/src/9/port/devsd.c:1177,1183 – 2002/0316/sys/src/9/port/devsd.c:1179,1185 | ||
| 2000/0526 | ||
| 2000/0506 | case Qraw: | |
| 2001/0905 | sdev = sdgetdev(DEV(c->qid)); | |
| 2002/0316 | if(sdev == nil) | |
| 2001/0905 | error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; | |
| 2000/1129 | qlock(&unit->raw); | |
| 2002/0109/sys/src/9/port/devsd.c:1291,1305 – 2002/0316/sys/src/9/port/devsd.c:1293,1307 | ||
| 2001/0905 | static char getspec(char base) { | |
| 2002/0316 | while(1){ | |
| 2001/0905 | int i; SDev *sdev; | |
| 2002/0316 | for(i = 0; i != ndevs; i++) if((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base) | |
| 2001/0905 | break; | |
| 2002/0316 | if(i == ndevs) | |
| 2001/0905 | return base; base++; } | |
| 2002/0109/sys/src/9/port/devsd.c:1307,1321 – 2002/0316/sys/src/9/port/devsd.c:1309,1323 | ||
| 2001/0905 | } static int | |
| 2002/0316 | configure(char* spec, DevConf* cf) | |
| 2001/0905 | { ISAConf isa; dev_t *_devs; | |
| 2002/0316 | SDev *tail, *sdev, *(*probe)(DevConf*); | |
| 2001/0905 | char *p, name[32]; int i, added_devs; | |
| 2002/0316 | if((p = strchr(cf->type, '/')) != nil) | |
| 2001/0905 | *p++ = '\0'; for(i = 0; sdifc[i] != nil; i++) | |
| 2002/0109/sys/src/9/port/devsd.c:1322,1334 – 2002/0316/sys/src/9/port/devsd.c:1324,1336 | ||
| 2001/0905 | if(!strcmp(sdifc[i]->name, cf->type)) break; | |
| 2002/0316 | if(sdifc[i] == nil) | |
| 2001/0905 | error("type not found"); | |
| 2002/0316 | if((probe = sdifc[i]->probe) == nil) | |
| 2001/0905 | error("No probe function"); | |
| 2002/0316 | if(p){ | |
| 2001/0905 | /* 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)); | |
| 2002/0109/sys/src/9/port/devsd.c:1335,1379 – 2002/0316/sys/src/9/port/devsd.c:1337,1381 | ||
| 2001/0905 | isa.port = cf->ports[0].port; isa.irq = cf->interrupt; | |
| 2002/0316 | if(pcmspecial(p, &isa) < 0) | |
| 2001/0905 | error("Cannot find controller"); } qlock(&devslock); | |
| 2002/0316 | if(waserror()){ | |
| 2001/0905 | qunlock(&devslock); nexterror(); } | |
| 2002/0316 | for(i = 0; i != ndevs; i++) if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) | |
| 2001/0905 | break; | |
| 2002/0316 | if(i != ndevs) | |
| 2001/0905 | error(Eexist); | |
| 2002/0316 | if((sdev = (*probe)(cf)) == nil) | |
| 2001/0905 | error("Cannot probe controller"); poperror(); added_devs = 0; tail = sdev; | |
| 2002/0316 | while(tail){ | |
| 2001/0905 | added_devs++; tail = tail->next; } | |
| 2002/0316 | _devs = (dev_t*)malloc((ndevs + added_devs) * sizeof(dev_t)); | |
| 2001/0905 | memmove(_devs, devs, ndevs * sizeof(dev_t)); free(devs); devs = _devs; | |
| 2002/0316 | while(sdev){ | |
| 2001/0905 | /* Assign `spec' to the device */ *spec = getspec(*spec); snprint(name, sizeof(name), "sd%c", *spec); kstrdup(&sdev->name, name); sdev->idno = *spec; | |
| 2001/0911 |
| |
| 2002/0316 | sdev->unit = (SDunit **)malloc(sdev->nunit * sizeof(SDunit*)); | |
| 2001/0911 | sdev->unitflg = (int *)malloc(sdev->nunit * sizeof(int)); assert(sdev->unit && sdev->unitflg); | |
| 2001/0905 | ||
| 2002/0109/sys/src/9/port/devsd.c:1389,1417 – 2002/0316/sys/src/9/port/devsd.c:1391,1420 | ||
| 2001/0905 | } static int | |
| 2002/0316 | unconfigure(char* spec) | |
| 2001/0905 | { int i; SDev *sdev; qlock(&devslock); | |
| 2002/0316 | if(waserror()){ | |
| 2001/0905 | qunlock(&devslock); nexterror(); } | |
| 2002/0316 | sdev = nil; for(i = 0; i != ndevs; i++) if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) | |
| 2001/0905 | break; | |
| 2002/0316 | if(i == ndevs) | |
| 2001/0905 | error(Enonexist); | |
| 2002/0316 | if(sdev->r.ref) | |
| 2001/0905 | error(Einuse); /* make sure no interrupts arrive anymore before removing resources */ | |
| 2002/0316 | if(sdev->enabled && sdev->ifc->disable) | |
| 2001/0905 | sdev->ifc->disable(sdev); /* we're alone and the device tab is locked; make the device unavailable */ | |
| 2002/0109/sys/src/9/port/devsd.c:1422,1429 – 2002/0316/sys/src/9/port/devsd.c:1425,1432 | ||
| 2001/0905 | qunlock(&devslock); poperror(); | |
| 2002/0316 | for(i = 0; i != sdev->nunit; i++) if(sdev->unit[i]){ | |
| 2001/0905 | SDunit *unit = sdev->unit[i]; free(unit->name); | |
| 2002/0109/sys/src/9/port/devsd.c:1431,1445 – 2002/0316/sys/src/9/port/devsd.c:1434,1450 | ||
| 2001/0905 | free(unit); } | |
| 2002/0316 | if(sdev->ifc->clear) | |
| 2001/0905 | sdev->ifc->clear(sdev); return 0; } static int | |
| 2002/0316 | sdconfig(int on, char* spec, DevConf* cf) | |
| 2001/0905 | { | |
| 2002/0316 | if(on) return configure(spec, cf); return unconfigure(spec); | |
| 2001/0905 | } | |
| 2000/0506 | Dev sddevtab = { | |