5 #include "../port/lib.h"
11 #include "../port/error.h"
13 #include "../port/sd.h"
16 extern SDifc* sdifc[];
18 static char Enoata[] = "raw ata commands not supported";
19 static char Enoscsi[] = "raw scsi commands not supported";
21 static char devletters[] = "0123456789"
22 "abcdefghijklmnopqrstuvwxyz"
23 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
25 static SDev *devs[sizeof devletters-1];
26 static QLock devslock;
27 static SDunit topctlunit;
40 Qtopdir = 1, /* top level directory */
44 Qunitdir, /* directory per unit */
64 UnitSHIFT = (PartLOG+TypeLOG),
69 DevSHIFT = (UnitLOG+PartLOG+TypeLOG),
74 #define TYPE(q) ((((ulong)(q).path)>>TypeSHIFT) & TypeMASK)
75 #define PART(q) ((((ulong)(q).path)>>PartSHIFT) & PartMASK)
76 #define UNIT(q) ((((ulong)(q).path)>>UnitSHIFT) & UnitMASK)
77 #define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK)
78 #define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\
79 ((p)<<PartSHIFT)|((t)<<TypeSHIFT))
83 sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
89 * Check name not already used
90 * and look for a free slot.
92 if(unit->part != nil){
94 for(i = 0; i < unit->npart; i++){
101 if(strcmp(name, pp->name) == 0){
102 if(pp->start == start && pp->end == end)
109 if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)
111 unit->npart = SDnpart;
116 * If no free slot found then increase the
117 * array size (can't get here with unit->part == nil).
120 if(unit->npart >= NPart)
122 if((pp = malloc(sizeof(SDpart)*(unit->npart+SDnpart))) == nil)
124 memmove(pp, unit->part, sizeof(SDpart)*unit->npart);
127 partno = unit->npart;
128 unit->npart += SDnpart;
132 * Check size and extent are valid.
134 if(start > end || end > unit->sectors)
136 pp = &unit->part[partno];
139 kstrdup(&pp->name, name);
140 kstrdup(&pp->user, eve);
146 sddelpart(SDunit* unit, char* name)
152 * Look for the partition to delete.
153 * Can't delete if someone still has it open.
156 for(i = 0; i < unit->npart; i++){
157 if(strcmp(name, pp->name) == 0)
163 if(strcmp(up->user, pp->user) && !iseve())
170 sdincvers(SDunit *unit)
176 for(i = 0; i < unit->npart; i++){
177 unit->part[i].valid = 0;
178 unit->part[i].vers++;
184 sdinitpart(SDunit* unit)
188 char *f[4], *p, *q, buf[10];
190 if(unit->sectors > 0){
191 unit->sectors = unit->secsize = 0;
195 if(unit->inquiry[0] & 0xC0)
197 switch(unit->inquiry[0] & 0x1F){
199 case 0x04: /* WORM */
200 case 0x05: /* CD-ROM */
207 if(unit->dev->ifc->online)
208 unit->dev->ifc->online(unit);
211 sdaddpart(unit, "data", 0, unit->sectors);
214 * Use partitions passed from boot program,
216 * sdC0part=dos 63 123123/plan9 123123 456456
217 * This happens before /boot sets hostname so the
218 * partitions will have the null-string for user.
219 * The gen functions patch it up.
221 snprint(buf, sizeof buf, "%spart", unit->name);
222 for(p = getconf(buf); p != nil; p = q){
223 if(q = strchr(p, '/'))
225 nf = tokenize(p, f, nelem(f));
229 start = strtoull(f[1], 0, 0);
230 end = strtoull(f[2], 0, 0);
232 sdaddpart(unit, f[0], start, end);
246 p = strchr(devletters, idno);
258 if((i = sdindex(idno)) < 0)
269 sdgetunit(SDev* sdev, int subno)
275 * Associate a unit with a given device and sub-unit
276 * number on that device.
277 * The device will be probed if it has not already been
278 * successfully accessed.
280 qlock(&sdev->unitlock);
281 if(subno > sdev->nunit){
282 qunlock(&sdev->unitlock);
286 unit = sdev->unit[subno];
289 * Probe the unit only once. This decision
290 * may be a little severe and reviewed later.
292 if(sdev->unitflg[subno]){
293 qunlock(&sdev->unitlock);
296 if((unit = malloc(sizeof(SDunit))) == nil){
297 qunlock(&sdev->unitlock);
300 sdev->unitflg[subno] = 1;
302 snprint(buf, sizeof buf, "%s%x", sdev->name, subno);
303 kstrdup(&unit->name, buf);
304 kstrdup(&unit->user, eve);
309 if(sdev->enabled == 0 && sdev->ifc->enable)
310 sdev->ifc->enable(sdev);
314 * No need to lock anything here as this is only
315 * called before the unit is made available in the
318 if(unit->dev->ifc->verify(unit) == 0){
319 qunlock(&sdev->unitlock);
323 sdev->unit[subno] = unit;
325 qunlock(&sdev->unitlock);
335 * Probe all known controller types and register any devices found.
337 for(i = 0; sdifc[i] != nil; i++){
338 if(sdifc[i]->pnp == nil)
340 sdadddevs(sdifc[i]->pnp());
345 sdadddevs(SDev *sdev)
350 for(; sdev; sdev=next){
353 sdev->unit = malloc(sdev->nunit * sizeof(SDunit*));
354 sdev->unitflg = malloc(sdev->nunit * sizeof(int));
355 if(sdev->unit == nil || sdev->unitflg == nil){
356 print("sdadddevs: out of memory\n");
361 sdev->ifc->clear(sdev);
365 id = sdindex(sdev->idno);
367 print("sdadddevs: bad id number %d (%C)\n", id, id);
371 for(i=0; i<nelem(devs); i++){
372 if(devs[j = (id+i)%nelem(devs)] == nil){
373 sdev->idno = devletters[j];
375 snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]);
380 if(i == nelem(devs)){
381 print("sdadddevs: out of device letters\n");
388 // sdrmdevs(SDev *sdev)
392 // snprint(buf, sizeof buf, "%c", sdev->idno);
397 sd2gen(Chan* c, int i, Dir* dp)
408 sdev = sdgetdev(DEV(c->qid));
410 unit = sdev->unit[UNIT(c->qid)];
415 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
417 perm = &unit->ctlperm;
418 if(emptystr(perm->user)){
419 kstrdup(&perm->user, eve);
422 devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
427 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
429 perm = &unit->rawperm;
430 if(emptystr(perm->user)){
431 kstrdup(&perm->user, eve);
432 perm->perm = DMEXCL|0600;
434 devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
439 pp = &unit->part[PART(c->qid)];
440 l = (pp->end - pp->start) * unit->secsize;
441 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
442 unit->vers+pp->vers, QTFILE);
443 if(emptystr(pp->user))
444 kstrdup(&pp->user, eve);
445 devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
450 if(t >= unit->nefile)
452 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qextra),
455 if(emptystr(e->user))
456 kstrdup(&e->user, eve);
457 devdir(c, q, e->name, 0, e->user, e->perm, dp);
467 sd1gen(Chan* c, int i, Dir* dp)
474 mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
475 qlock(&topctlunit.ctl);
476 p = &topctlunit.ctlperm;
477 if(p->user == nil || p->user[0] == 0){
478 kstrdup(&p->name, "sdctl");
479 kstrdup(&p->user, eve);
482 devdir(c, q, p->name, 0, p->user, p->perm, dp);
483 qunlock(&topctlunit.ctl);
490 efilegen(Chan *c, SDunit *unit, int i, Dir *dp)
496 if(unit->nefile == 0 || i >= unit->nefile)
501 if(emptystr(e->user))
502 kstrdup(&e->user, eve);
503 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qextra),
505 devdir(c, q, e->name, 0, e->user, e->perm, dp);
510 sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
519 switch(TYPE(c->qid)){
522 mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
523 sprint(up->genbuf, "#%C", sddevtab.dc);
524 devdir(c, q, up->genbuf, 0, eve, 0555, dp);
528 if(s+Qtopbase < Qunitdir)
529 return sd1gen(c, s+Qtopbase, dp);
530 s -= (Qunitdir-Qtopbase);
533 for(i=0; i<nelem(devs); i++){
535 if(s < devs[i]->nunit)
541 if(i == nelem(devs)){
542 /* Run off the end of the list */
547 if((sdev = devs[i]) == nil){
555 if((unit = sdev->unit[s]) == nil)
556 if((unit = sdgetunit(sdev, s)) == nil){
561 mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
562 if(emptystr(unit->user))
563 kstrdup(&unit->user, eve);
564 devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
570 mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
571 sprint(up->genbuf, "#%C", sddevtab.dc);
572 devdir(c, q, up->genbuf, 0, eve, 0555, dp);
576 if((sdev = sdgetdev(DEV(c->qid))) == nil){
577 devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
581 unit = sdev->unit[UNIT(c->qid)];
585 * Check for media change.
586 * If one has already been detected, sectors will be zero.
587 * If there is one waiting to be detected, online
589 * Online is a bit of a large hammer but does the job.
591 if(unit->sectors == 0
592 || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
597 r = sd2gen(c, i, dp);
603 if(unit->part == nil || i >= unit->npart){
604 r = efilegen(c, unit, i, dp);
610 if(!pp->valid || unit->sectors == 0){
615 l = (pp->end - pp->start) * (uvlong)unit->secsize;
616 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
617 unit->vers+pp->vers, QTFILE);
618 if(emptystr(pp->user))
619 kstrdup(&pp->user, eve);
620 devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
628 if((sdev = sdgetdev(DEV(c->qid))) == nil){
629 devdir(c, q, "unavailable", 0, eve, 0, dp);
632 unit = sdev->unit[UNIT(c->qid)];
634 r = sd2gen(c, TYPE(c->qid), dp);
639 return sd1gen(c, TYPE(c->qid), dp);
656 c = devattach(sddevtab.dc, spec);
657 mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
661 if(spec[0] != 's' || spec[1] != 'd')
664 subno = strtol(&spec[3], &p, 0);
668 if((sdev=sdgetdev(idno)) == nil)
670 if(sdgetunit(sdev, subno) == nil){
675 c = devattach(sddevtab.dc, spec);
676 mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
677 c->dev = (sdev->idno << UnitLOG) + subno;
683 sdwalk(Chan* c, Chan* nc, char** name, int nname)
685 return devwalk(c, nc, name, nname, nil, 0, sdgen);
689 sdstat(Chan* c, uchar* db, int n)
691 return devstat(c, db, n, nil, 0, sdgen);
695 sdopen(Chan* c, int omode)
702 c = devopen(c, omode, 0, 0, sdgen);
703 if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
706 sdev = sdgetdev(DEV(c->qid));
710 unit = sdev->unit[UNIT(c->qid)];
712 switch(TYPE(c->qid)){
714 c->qid.vers = unit->vers;
717 c->qid.vers = unit->vers;
718 if(tas(&unit->rawinuse) != 0){
723 unit->state = Rawcmd;
733 pp = &unit->part[PART(c->qid)];
734 c->qid.vers = unit->vers+pp->vers;
749 if(c->qid.type & QTDIR)
751 if(!(c->flag & COPEN))
754 switch(TYPE(c->qid)){
758 sdev = sdgetdev(DEV(c->qid));
760 unit = sdev->unit[UNIT(c->qid)];
768 #define iskaddr(a) ((uintptr)(a) > KZERO)
771 sdbio(Chan* c, int write, char* a, long len, uvlong off)
773 int nchange, hard, allocd, locked;
779 ulong max, nb, offset;
782 sdev = sdgetdev(DEV(c->qid));
787 unit = sdev->unit[UNIT(c->qid)];
794 /* notification of media change; go around again */
795 if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
800 /* other errors; give up */
805 pp = &unit->part[PART(c->qid)];
806 if(unit->vers+pp->vers != c->qid.vers)
810 * Check the request is within bounds.
811 * Removeable drives are locked throughout the I/O
812 * in case the media changes unexpectedly.
813 * Non-removeable drives are not locked during the I/O
814 * to allow the hardware to optimise if it can; this is
815 * a little fast and loose.
816 * It's assumed that non-removeable media parameters
817 * (sectors, secsize) can't change once the drive has
818 * been brought online.
820 bno = (off/unit->secsize) + pp->start;
821 nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
822 max = SDmaxio/unit->secsize;
827 if(bno >= pp->end || nb == 0){
835 locked = (unit->inquiry[1] & 0x80) != 0;
841 offset = off%unit->secsize;
842 if(offset+len > nb*unit->secsize)
843 len = nb*unit->secsize - offset;
844 hard = offset || write && len%unit->secsize;
846 if(iskaddr(a) && ((uintptr)a & (BY2PG-1))==0 && !hard) {
850 while((b = sdmalloc(nb*unit->secsize)) == nil){
852 resrcwait("no memory for sdbio");
862 decref(&sdev->r); /* gadverdamme! */
868 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
871 if(l < (nb*unit->secsize)){
872 nb = l/unit->secsize;
873 l = nb*unit->secsize - offset;
879 memmove(b+offset, a, len);
880 l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
885 else if(len > l - offset)
889 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
894 else if(len > l - offset)
897 memmove(a, b+offset, len);
913 sdrio(SDreq* r, void* a, long n)
921 if(n >= SDmaxio || n < 0)
924 if(u->haversense && r->cmd[0] == 0x03){
926 r->rlen = sizeof u->rsense;
929 memmove(a, u->rsense, r->rlen);
935 while(n > 0 && (data = sdmalloc(n)) == nil){
937 resrcwait("no memory for sdrio");
946 if(r->write && n > 0)
951 if(r->proto == SData){
952 f = u->dev->ifc->ataio;
955 f = u->dev->ifc->rio;
961 if(r->flags & SDvalidsense){
962 memmove(u->rsense, r->sense, sizeof u->rsense);
968 if(!r->write && r->rlen > 0)
969 memmove(a, data, r->rlen);
978 * SCSI simulation for non-SCSI devices
980 * see /sys/src/cmd/scuzz/sense.c for information on key.
981 * see /sys/lib/scsicodes for asc:ascq codes
984 sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
990 unit->sense[0] = 0x80 | 0x70; /* valid; fixed-format */
991 unit->sense[2] = key;
992 unit->sense[12] = asc;
993 unit->sense[13] = ascq;
996 if(status == SDcheck && !(r->flags & SDnosense)){
997 /* request sense case from sdfakescsi */
998 len = sizeof unit->sense;
999 if(len > sizeof r->sense-1)
1000 len = sizeof r->sense-1;
1001 memmove(r->sense, unit->sense, len);
1003 unit->sense[12] = 0;
1004 unit->sense[13] = 0;
1005 r->flags |= SDvalidsense;
1012 sdfakescsi(SDreq *r)
1023 * Map SCSI commands into ATA commands for discs.
1024 * Fail any command with a LUN except INQUIRY which
1025 * will return 'logical unit not supported'.
1027 if((cmd[1]>>5) && cmd[0] != 0x12)
1028 return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
1032 return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1034 case 0x00: /* test unit ready */
1035 return sdsetsense(r, SDok, 0, 0, 0);
1037 case 0x03: /* request sense */
1038 if(cmd[4] < sizeof unit->sense)
1041 len = sizeof unit->sense;
1042 if(r->data && r->dlen >= len){
1043 memmove(r->data, unit->sense, len);
1046 return sdsetsense(r, SDok, 0, 0, 0);
1048 case 0x12: /* inquiry */
1049 if(cmd[4] < sizeof unit->inquiry)
1052 len = sizeof unit->inquiry;
1053 if(r->data && r->dlen >= len){
1054 memmove(r->data, unit->inquiry, len);
1057 return sdsetsense(r, SDok, 0, 0, 0);
1059 case 0x1B: /* start/stop unit */
1061 * nop for now, can use power management later.
1063 return sdsetsense(r, SDok, 0, 0, 0);
1065 case 0x25: /* read capacity */
1066 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1067 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1068 if(r->data == nil || r->dlen < 8)
1069 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1072 * Read capacity returns the LBA of the last sector.
1074 len = unit->sectors;
1075 if(len >= 0xffffffff)
1084 len = unit->secsize;
1089 r->rlen = p - (uchar*)r->data;
1090 return sdsetsense(r, SDok, 0, 0, 0);
1092 case 0x9E: /* long read capacity */
1093 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1094 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1095 if(r->data == nil || r->dlen < 8)
1096 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1098 * Read capcity returns the LBA of the last sector.
1100 len = unit->sectors;
1112 len = unit->secsize;
1117 r->rlen = p - (uchar*)r->data;
1118 return sdsetsense(r, SDok, 0, 0, 0);
1119 case 0x08: /* read6 */
1120 case 0x0a: /* write6 */
1121 case 0x28: /* read10 */
1122 case 0x2a: /* write10 */
1123 case 0xa8: /* read12 */
1124 case 0xaa: /* write12 */
1125 case 0x88: /* read16 */
1126 case 0x8a: /* write16 */
1132 sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
1140 if((c[0] & 0xf) == 0xa)
1143 case 0x08: /* read6 */
1145 lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3];
1148 case 0x28: /* read10 */
1150 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1151 count = c[7]<<8 | c[8];
1153 case 0xa8: /* read12 */
1155 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1156 count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1158 case 0x88: /* read16 */
1160 /* ata commands only go to 48-bit lba */
1162 return sdsetsense(r, SDcheck, 3, 0xc, 2);
1163 lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32;
1164 lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1165 count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13];
1168 print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]);
1169 r->status = sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1174 if(r->dlen < count * r->unit->secsize)
1175 count = r->dlen/r->unit->secsize;
1184 extrarw(int write, Chan *c, void *a, long n, vlong off)
1191 sdev = sdgetdev(DEV(c->qid));
1198 unit = sdev->unit[UNIT(c->qid)];
1199 if(unit->vers != c->qid.vers)
1201 unit = sdev->unit[UNIT(c->qid)];
1203 if(i >= unit->nefile)
1205 f = unit->efile[i].r;
1207 f = unit->efile[i].w;
1208 if(i >= unit->nefile || f == nil)
1210 n = f(unit, c, a, n, off);
1217 deftopctl(SDev *s, char *p, char *e)
1219 return seprint(p, e, "sd%c %s %d units\n", s->idno, s->ifc->name, s->nunit);
1223 sdread(Chan *c, void *a, long n, vlong off)
1231 int i, l, m, status;
1234 switch(TYPE(c->qid)){
1238 m = 64*1024; /* room for register dumps */
1239 p = buf = smalloc(m);
1242 for(i = 0; i < nelem(devs); i++){
1244 if(sdev && sdev->ifc->rtopctl)
1245 p = sdev->ifc->rtopctl(sdev, p, e);
1247 p = deftopctl(sdev, p, e);
1250 n = readstr(off, a, n, buf);
1256 return devdirread(c, a, n, 0, 0, sdgen);
1259 sdev = sdgetdev(DEV(c->qid));
1263 unit = sdev->unit[UNIT(c->qid)];
1264 m = 16*1024; /* room for register dumps */
1266 l = snprint(p, m, "inquiry %.48s\n",
1267 (char*)unit->inquiry+8);
1270 * If there's a device specific routine it must
1271 * provide all information pertaining to night geometry
1272 * and the garscadden trains.
1274 if(unit->dev->ifc->rctl)
1275 l += unit->dev->ifc->rctl(unit, p+l, m-l);
1276 if(unit->sectors == 0)
1279 if(unit->dev->ifc->rctl == nil)
1280 l += snprint(p+l, m-l,
1281 "geometry %llud %lud\n",
1282 unit->sectors, unit->secsize);
1284 for(i = 0; i < unit->npart; i++){
1286 l += snprint(p+l, m-l,
1287 "part %s %llud %llud\n",
1288 pp->name, pp->start, pp->end);
1292 qunlock(&unit->ctl);
1294 l = readstr(offset, a, n, p);
1299 sdev = sdgetdev(DEV(c->qid));
1303 unit = sdev->unit[UNIT(c->qid)];
1306 qunlock(&unit->raw);
1310 if(unit->state == Rawdata){
1311 unit->state = Rawstatus;
1316 else if(unit->state == Rawstatus){
1319 unit->state = Rawcmd;
1321 if(r->proto == SData){
1329 memmove(p + Ahdrsz, r->cmd, i - Ahdrsz);
1331 i = readnum(0, a, n, status, NUMSIZE);
1336 qunlock(&unit->raw);
1341 return sdbio(c, 0, a, n, off);
1343 return extrarw(0, c, a, n, off);
1347 static void legacytopctl(Cmdbuf*);
1350 sdwrite(Chan* c, void* a, long n, vlong off)
1353 int i, atacdb, proto, ataproto;
1362 switch(TYPE(c->qid)){
1366 cb = parsecmd(a, n);
1372 error("empty control message");
1376 if(strcmp(f0, "config") == 0){
1377 /* wormhole into ugly legacy interface */
1384 * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
1385 * where sdifc[i]->name=="ata" and cb contains the args.
1389 for(i=0; sdifc[i]; i++){
1390 if(strcmp(sdifc[i]->name, f0) == 0){
1397 * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
1398 * where sdifc[i] and sdev match controller letter "1",
1399 * and cb contains the args.
1401 if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
1402 if((sdev = sdgetdev(f0[2])) != nil){
1407 error("unknown interface");
1416 ifc->wtopctl(sdev, cb);
1427 cb = parsecmd(a, n);
1428 sdev = sdgetdev(DEV(c->qid));
1431 unit = sdev->unit[UNIT(c->qid)];
1435 qunlock(&unit->ctl);
1440 if(unit->vers != c->qid.vers)
1445 if(strcmp(cb->f[0], "part") == 0){
1448 if(unit->sectors == 0 && !sdinitpart(unit))
1450 start = strtoull(cb->f[2], 0, 0);
1451 end = strtoull(cb->f[3], 0, 0);
1452 sdaddpart(unit, cb->f[1], start, end);
1454 else if(strcmp(cb->f[0], "delpart") == 0){
1455 if(cb->nf != 2 || unit->part == nil)
1457 sddelpart(unit, cb->f[1]);
1459 else if(unit->dev->ifc->wctl)
1460 unit->dev->ifc->wctl(unit, cb);
1463 qunlock(&unit->ctl);
1473 sdev = sdgetdev(DEV(c->qid));
1476 unit = sdev->unit[UNIT(c->qid)];
1479 qunlock(&unit->raw);
1483 switch(unit->state){
1485 /* sneaky ata commands */
1487 if(n > 1 && *u == 0xff){
1494 if(n < 6 || n > sizeof(req->cmd))
1496 req = smalloc(sizeof(SDreq));
1502 memmove(req->cmd, a, n);
1505 /* req->flags = SDnosense; */
1508 req->ataproto = ataproto;
1510 unit->state = Rawdata;
1515 unit->state = Rawcmd;
1521 unit->state = Rawstatus;
1524 n = sdrio(req, a, n);
1527 qunlock(&unit->raw);
1531 return sdbio(c, 1, a, n, off);
1533 return extrarw(1, c, a, n, off);
1540 sdwstat(Chan* c, uchar* dp, int n)
1548 if(c->qid.type & QTDIR)
1550 if(TYPE(c->qid) == Qtopctl){
1554 sdev = sdgetdev(DEV(c->qid));
1557 unit = sdev->unit[UNIT(c->qid)];
1563 qunlock(&unit->ctl);
1570 switch(TYPE(c->qid)){
1575 perm = &unit->ctlperm;
1578 perm = &unit->rawperm;
1581 pp = &unit->part[PART(c->qid)];
1582 if(unit->vers+pp->vers != c->qid.vers)
1588 if(strcmp(up->user, perm->user) && !iseve())
1591 d = smalloc(sizeof(Dir)+n);
1592 n = convM2D(dp, n, &d[0], (char*)&d[1]);
1595 if(d->atime != ~0 || d->mtime != ~0 || d->length != ~0)
1597 if(!emptystr(d[0].muid) || !emptystr(d[0].name))
1599 if(!emptystr(d[0].uid))
1600 kstrdup(&perm->user, d[0].uid);
1601 if(!emptystr(d[0].gid) && strcmp(d[0].gid, eve) != 0)
1603 if(d[0].mode != ~0UL)
1604 perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
1606 qunlock(&unit->ctl);
1614 configure(char* spec, DevConf* cf)
1620 if(sdindex(*spec) < 0)
1621 error("bad sd spec");
1623 if((p = strchr(cf->type, '/')) != nil)
1626 for(i = 0; sdifc[i] != nil; i++)
1627 if(strcmp(sdifc[i]->name, cf->type) == 0)
1630 error("sd type not found");
1634 if(sdifc[i]->probe == nil)
1635 error("sd type cannot probe");
1637 sdev = sdifc[i]->probe(cf);
1638 for(s=sdev; s; s=s->next)
1645 unconfigure(char* spec)
1651 if((i = sdindex(*spec)) < 0)
1655 if((sdev = devs[i]) == nil){
1666 /* make sure no interrupts arrive anymore before removing resources */
1667 if(sdev->enabled && sdev->ifc->disable)
1668 sdev->ifc->disable(sdev);
1670 for(i = 0; i != sdev->nunit; i++){
1671 if(unit = sdev->unit[i]){
1678 if(sdev->ifc->clear)
1679 sdev->ifc->clear(sdev);
1685 sdconfig(int on, char* spec, DevConf* cf)
1688 return configure(spec, cf);
1689 return unconfigure(spec);
1693 sdaddfile(SDunit *unit, char *s, int perm, char *u, SDrw *r, SDrw *w)
1702 for(i = 0; i < unit->nefile; i++)
1703 if(strcmp(unit->efile[i].name, s) == 0)
1705 if(i >= nelem(unit->efile)){
1709 if(i >= unit->nefile)
1710 unit->nefile = i + 1;
1711 e = unit->efile + i;
1713 kstrdup(&e->name, s);
1715 kstrdup(&e->user, u);
1729 for(i = 0; i < nelem(devs); i++){
1733 if(sd->ifc->disable == nil){
1734 print("#S/sd%c: no disable function\n", devletters[i]);
1737 sd->ifc->disable(sd);
1765 * This is wrong for so many reasons. This code must go.
1767 typedef struct Confdata Confdata;
1775 parseswitch(Confdata* cd, char* option)
1777 if(!strcmp("on", option))
1779 else if(!strcmp("off", option))
1786 parsespec(Confdata* cd, char* option)
1788 if(strlen(option) > 1)
1794 getnewport(DevConf* dc)
1798 p = malloc((dc->nports + 1) * sizeof(Devport));
1800 panic("sd: no memory for Devport");
1802 memmove(p, dc->ports, dc->nports * sizeof(Devport));
1806 p = &dc->ports[dc->nports++];
1808 p->port = (ulong)-1;
1813 parseport(Confdata* cd, char* option)
1818 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1)
1819 p = getnewport(&cd->cf);
1821 p = &cd->cf.ports[cd->cf.nports-1];
1822 p->port = strtol(option, &e, 0);
1823 if(e == nil || *e != '\0')
1828 parsesize(Confdata* cd, char* option)
1833 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
1834 p = getnewport(&cd->cf);
1836 p = &cd->cf.ports[cd->cf.nports-1];
1837 p->size = (int)strtol(option, &e, 0);
1838 if(e == nil || *e != '\0')
1843 parseirq(Confdata* cd, char* option)
1847 cd->cf.intnum = strtoul(option, &e, 0);
1848 if(e == nil || *e != '\0')
1853 parsetype(Confdata* cd, char* option)
1855 cd->cf.type = option;
1860 void (*parse)(Confdata*, char*);
1862 "switch", parseswitch,
1871 legacytopctl(Cmdbuf *cb)
1877 memset(&cd, 0, sizeof cd);
1879 for(i=0; i<cb->nf; i+=2){
1883 for(j=0; j<nelem(options); j++)
1884 if(strcmp(opt, options[j].name) == 0){
1885 options[j].parse(&cd, cb->f[i+1]);
1888 if(j == nelem(options))
1891 if(cd.on < 0 || cd.spec == 0)
1893 if(cd.on && cd.cf.type == nil)
1895 sdconfig(cd.on, cd.spec, &cd.cf);