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;
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 if(!(unit->inquiry[1] & 0x80)){
840 offset = off%unit->secsize;
841 if(offset+len > nb*unit->secsize)
842 len = nb*unit->secsize - offset;
843 hard = offset || write && len%unit->secsize;
845 if(iskaddr(a) && !hard) {
849 b = sdmalloc(nb*unit->secsize);
857 if(!(unit->inquiry[1] & 0x80))
858 decref(&sdev->r); /* gadverdamme! */
864 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
867 if(l < (nb*unit->secsize)){
868 nb = l/unit->secsize;
869 l = nb*unit->secsize - offset;
875 memmove(b+offset, a, len);
876 l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
881 else if(len > l - offset)
885 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
890 else if(len > l - offset)
893 memmove(a, b+offset, len);
899 if(unit->inquiry[1] & 0x80){
909 sdrio(SDreq* r, void* a, long n)
917 if(n >= SDmaxio || n < 0)
920 if(u->haversense && r->cmd[0] == 0x03){
922 r->rlen = sizeof u->rsense;
925 memmove(a, u->rsense, r->rlen);
931 if(n > 0 && (data = sdmalloc(n)) == nil)
938 if(r->write && n > 0)
943 if(r->proto == SData){
944 f = u->dev->ifc->ataio;
947 f = u->dev->ifc->rio;
953 if(r->flags & SDvalidsense){
954 memmove(u->rsense, r->sense, sizeof u->rsense);
960 if(!r->write && r->rlen > 0)
961 memmove(a, data, r->rlen);
970 * SCSI simulation for non-SCSI devices
972 * see /sys/src/cmd/scuzz/sense.c for information on key.
973 * see /sys/lib/scsicodes for asc:ascq codes
976 sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
982 unit->sense[2] = key;
983 unit->sense[12] = asc;
984 unit->sense[13] = ascq;
987 if(status == SDcheck && !(r->flags & SDnosense)){
988 /* request sense case from sdfakescsi */
989 len = sizeof unit->sense;
990 if(len > sizeof r->sense-1)
991 len = sizeof r->sense-1;
992 memmove(r->sense, unit->sense, len);
996 r->flags |= SDvalidsense;
1003 sdfakescsi(SDreq *r)
1014 * Map SCSI commands into ATA commands for discs.
1015 * Fail any command with a LUN except INQUIRY which
1016 * will return 'logical unit not supported'.
1018 if((cmd[1]>>5) && cmd[0] != 0x12)
1019 return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
1023 return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1025 case 0x00: /* test unit ready */
1026 return sdsetsense(r, SDok, 0, 0, 0);
1028 case 0x03: /* request sense */
1029 if(cmd[4] < sizeof unit->sense)
1032 len = sizeof unit->sense;
1033 if(r->data && r->dlen >= len){
1034 memmove(r->data, unit->sense, len);
1037 return sdsetsense(r, SDok, 0, 0, 0);
1039 case 0x12: /* inquiry */
1040 if(cmd[4] < sizeof unit->inquiry)
1043 len = sizeof unit->inquiry;
1044 if(r->data && r->dlen >= len){
1045 memmove(r->data, unit->inquiry, len);
1048 return sdsetsense(r, SDok, 0, 0, 0);
1050 case 0x1B: /* start/stop unit */
1052 * nop for now, can use power management later.
1054 return sdsetsense(r, SDok, 0, 0, 0);
1056 case 0x25: /* read capacity */
1057 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1058 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1059 if(r->data == nil || r->dlen < 8)
1060 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1063 * Read capacity returns the LBA of the last sector.
1065 len = unit->sectors;
1073 len = unit->secsize;
1078 r->rlen = p - (uchar*)r->data;
1079 return sdsetsense(r, SDok, 0, 0, 0);
1081 case 0x9E: /* long read capacity */
1082 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1083 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1084 if(r->data == nil || r->dlen < 8)
1085 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1087 * Read capcity returns the LBA of the last sector.
1089 len = unit->sectors;
1101 len = unit->secsize;
1106 r->rlen = p - (uchar*)r->data;
1107 return sdsetsense(r, SDok, 0, 0, 0);
1108 case 0x08: /* read6 */
1109 case 0x0a: /* write6 */
1110 case 0x28: /* read10 */
1111 case 0x2a: /* write10 */
1112 case 0xa8: /* read12 */
1113 case 0xaa: /* write12 */
1114 case 0x88: /* read16 */
1115 case 0x8a: /* write16 */
1121 sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
1129 if((c[0] & 0xf) == 0xa)
1132 case 0x08: /* read6 */
1134 lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3];
1137 case 0x28: /* read10 */
1139 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1140 count = c[7]<<8 | c[8];
1142 case 0xa8: /* read12 */
1144 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1145 count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1147 case 0x88: /* read16 */
1149 /* ata commands only go to 48-bit lba */
1151 return sdsetsense(r, SDcheck, 3, 0xc, 2);
1152 lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32;
1153 lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1154 count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13];
1157 print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]);
1158 r->status = sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1163 if(r->dlen < count * r->unit->secsize)
1164 count = r->dlen/r->unit->secsize;
1173 extrarw(int write, Chan *c, void *a, long n, vlong off)
1180 sdev = sdgetdev(DEV(c->qid));
1187 unit = sdev->unit[UNIT(c->qid)];
1188 if(unit->vers != c->qid.vers)
1190 unit = sdev->unit[UNIT(c->qid)];
1192 if(i >= unit->nefile)
1194 f = unit->efile[i].r;
1196 f = unit->efile[i].w;
1197 if(i >= unit->nefile || f == nil)
1199 n = f(unit, c, a, n, off);
1206 deftopctl(SDev *s, char *p, char *e)
1208 return seprint(p, e, "sd%c %s %d units\n", s->idno, s->ifc->name, s->nunit);
1212 sdread(Chan *c, void *a, long n, vlong off)
1220 int i, l, m, status;
1223 switch(TYPE(c->qid)){
1227 m = 64*1024; /* room for register dumps */
1228 p = buf = smalloc(m);
1231 for(i = 0; i < nelem(devs); i++){
1233 if(sdev && sdev->ifc->rtopctl)
1234 p = sdev->ifc->rtopctl(sdev, p, e);
1236 p = deftopctl(sdev, p, e);
1239 n = readstr(off, a, n, buf);
1245 return devdirread(c, a, n, 0, 0, sdgen);
1248 sdev = sdgetdev(DEV(c->qid));
1252 unit = sdev->unit[UNIT(c->qid)];
1253 m = 16*1024; /* room for register dumps */
1255 l = snprint(p, m, "inquiry %.48s\n",
1256 (char*)unit->inquiry+8);
1259 * If there's a device specific routine it must
1260 * provide all information pertaining to night geometry
1261 * and the garscadden trains.
1263 if(unit->dev->ifc->rctl)
1264 l += unit->dev->ifc->rctl(unit, p+l, m-l);
1265 if(unit->sectors == 0)
1268 if(unit->dev->ifc->rctl == nil)
1269 l += snprint(p+l, m-l,
1270 "geometry %llud %lud\n",
1271 unit->sectors, unit->secsize);
1273 for(i = 0; i < unit->npart; i++){
1275 l += snprint(p+l, m-l,
1276 "part %s %llud %llud\n",
1277 pp->name, pp->start, pp->end);
1281 qunlock(&unit->ctl);
1283 l = readstr(offset, a, n, p);
1288 sdev = sdgetdev(DEV(c->qid));
1292 unit = sdev->unit[UNIT(c->qid)];
1295 qunlock(&unit->raw);
1299 if(unit->state == Rawdata){
1300 unit->state = Rawstatus;
1305 else if(unit->state == Rawstatus){
1308 unit->state = Rawcmd;
1310 if(r->proto == SData){
1318 memmove(p + Ahdrsz, r->cmd, i - Ahdrsz);
1320 i = readnum(0, a, n, status, NUMSIZE);
1325 qunlock(&unit->raw);
1330 return sdbio(c, 0, a, n, off);
1332 return extrarw(0, c, a, n, off);
1336 static void legacytopctl(Cmdbuf*);
1339 sdwrite(Chan* c, void* a, long n, vlong off)
1342 int i, atacdb, proto, ataproto;
1351 switch(TYPE(c->qid)){
1355 cb = parsecmd(a, n);
1361 error("empty control message");
1365 if(strcmp(f0, "config") == 0){
1366 /* wormhole into ugly legacy interface */
1373 * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
1374 * where sdifc[i]->name=="ata" and cb contains the args.
1378 for(i=0; sdifc[i]; i++){
1379 if(strcmp(sdifc[i]->name, f0) == 0){
1386 * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
1387 * where sdifc[i] and sdev match controller letter "1",
1388 * and cb contains the args.
1390 if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
1391 if((sdev = sdgetdev(f0[2])) != nil){
1396 error("unknown interface");
1405 ifc->wtopctl(sdev, cb);
1416 cb = parsecmd(a, n);
1417 sdev = sdgetdev(DEV(c->qid));
1420 unit = sdev->unit[UNIT(c->qid)];
1424 qunlock(&unit->ctl);
1429 if(unit->vers != c->qid.vers)
1434 if(strcmp(cb->f[0], "part") == 0){
1437 if(unit->sectors == 0 && !sdinitpart(unit))
1439 start = strtoull(cb->f[2], 0, 0);
1440 end = strtoull(cb->f[3], 0, 0);
1441 sdaddpart(unit, cb->f[1], start, end);
1443 else if(strcmp(cb->f[0], "delpart") == 0){
1444 if(cb->nf != 2 || unit->part == nil)
1446 sddelpart(unit, cb->f[1]);
1448 else if(unit->dev->ifc->wctl)
1449 unit->dev->ifc->wctl(unit, cb);
1452 qunlock(&unit->ctl);
1462 sdev = sdgetdev(DEV(c->qid));
1465 unit = sdev->unit[UNIT(c->qid)];
1468 qunlock(&unit->raw);
1472 switch(unit->state){
1474 /* sneaky ata commands */
1476 if(n > 1 && *u == 0xff){
1483 if(n < 6 || n > sizeof(req->cmd))
1485 if((req = malloc(sizeof(SDreq))) == nil)
1492 memmove(req->cmd, a, n);
1495 /* req->flags = SDnosense; */
1498 req->ataproto = ataproto;
1500 unit->state = Rawdata;
1505 unit->state = Rawcmd;
1511 unit->state = Rawstatus;
1514 n = sdrio(req, a, n);
1517 qunlock(&unit->raw);
1521 return sdbio(c, 1, a, n, off);
1523 return extrarw(1, c, a, n, off);
1530 sdwstat(Chan* c, uchar* dp, int n)
1538 if(c->qid.type & QTDIR)
1540 if(TYPE(c->qid) == Qtopctl){
1544 sdev = sdgetdev(DEV(c->qid));
1547 unit = sdev->unit[UNIT(c->qid)];
1554 qunlock(&unit->ctl);
1560 switch(TYPE(c->qid)){
1565 perm = &unit->ctlperm;
1568 perm = &unit->rawperm;
1571 pp = &unit->part[PART(c->qid)];
1572 if(unit->vers+pp->vers != c->qid.vers)
1578 if(strcmp(up->user, perm->user) && !iseve())
1581 d = smalloc(sizeof(Dir)+n);
1582 n = convM2D(dp, n, &d[0], (char*)&d[1]);
1585 if(d->atime != ~0 || d->mtime != ~0 || d->length != ~0)
1587 if(!emptystr(d[0].muid) || !emptystr(d[0].name))
1589 if(!emptystr(d[0].uid))
1590 kstrdup(&perm->user, d[0].uid);
1591 if(!emptystr(d[0].gid) && strcmp(d[0].gid, eve) != 0)
1593 if(d[0].mode != ~0UL)
1594 perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
1598 qunlock(&unit->ctl);
1606 configure(char* spec, DevConf* cf)
1612 if(sdindex(*spec) < 0)
1613 error("bad sd spec");
1615 if((p = strchr(cf->type, '/')) != nil)
1618 for(i = 0; sdifc[i] != nil; i++)
1619 if(strcmp(sdifc[i]->name, cf->type) == 0)
1622 error("sd type not found");
1626 if(sdifc[i]->probe == nil)
1627 error("sd type cannot probe");
1629 sdev = sdifc[i]->probe(cf);
1630 for(s=sdev; s; s=s->next)
1637 unconfigure(char* spec)
1643 if((i = sdindex(*spec)) < 0)
1647 if((sdev = devs[i]) == nil){
1658 /* make sure no interrupts arrive anymore before removing resources */
1659 if(sdev->enabled && sdev->ifc->disable)
1660 sdev->ifc->disable(sdev);
1662 for(i = 0; i != sdev->nunit; i++){
1663 if(unit = sdev->unit[i]){
1670 if(sdev->ifc->clear)
1671 sdev->ifc->clear(sdev);
1677 sdconfig(int on, char* spec, DevConf* cf)
1680 return configure(spec, cf);
1681 return unconfigure(spec);
1685 sdaddfile(SDunit *unit, char *s, int perm, char *u, SDrw *r, SDrw *w)
1694 for(i = 0; i < unit->nefile; i++)
1695 if(strcmp(unit->efile[i].name, s) == 0)
1697 if(i >= nelem(unit->efile)){
1701 if(i >= unit->nefile)
1702 unit->nefile = i + 1;
1703 e = unit->efile + i;
1705 kstrdup(&e->name, s);
1707 kstrdup(&e->user, u);
1721 for(i = 0; i < nelem(devs); i++){
1725 if(sd->ifc->disable == nil){
1726 print("#S/sd%c: no disable function\n", devletters[i]);
1729 sd->ifc->disable(sd);
1757 * This is wrong for so many reasons. This code must go.
1759 typedef struct Confdata Confdata;
1767 parseswitch(Confdata* cd, char* option)
1769 if(!strcmp("on", option))
1771 else if(!strcmp("off", option))
1778 parsespec(Confdata* cd, char* option)
1780 if(strlen(option) > 1)
1786 getnewport(DevConf* dc)
1790 p = malloc((dc->nports + 1) * sizeof(Devport));
1792 panic("sd: no memory for Devport");
1794 memmove(p, dc->ports, dc->nports * sizeof(Devport));
1798 p = &dc->ports[dc->nports++];
1800 p->port = (ulong)-1;
1805 parseport(Confdata* cd, char* option)
1810 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1)
1811 p = getnewport(&cd->cf);
1813 p = &cd->cf.ports[cd->cf.nports-1];
1814 p->port = strtol(option, &e, 0);
1815 if(e == nil || *e != '\0')
1820 parsesize(Confdata* cd, char* option)
1825 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
1826 p = getnewport(&cd->cf);
1828 p = &cd->cf.ports[cd->cf.nports-1];
1829 p->size = (int)strtol(option, &e, 0);
1830 if(e == nil || *e != '\0')
1835 parseirq(Confdata* cd, char* option)
1839 cd->cf.intnum = strtoul(option, &e, 0);
1840 if(e == nil || *e != '\0')
1845 parsetype(Confdata* cd, char* option)
1847 cd->cf.type = option;
1852 void (*parse)(Confdata*, char*);
1854 "switch", parseswitch,
1863 legacytopctl(Cmdbuf *cb)
1869 memset(&cd, 0, sizeof cd);
1871 for(i=0; i<cb->nf; i+=2){
1875 for(j=0; j<nelem(options); j++)
1876 if(strcmp(opt, options[j].name) == 0){
1877 options[j].parse(&cd, cb->f[i+1]);
1880 if(j == nelem(options))
1883 if(cd.on < 0 || cd.spec == 0)
1885 if(cd.on && cd.cf.type == nil)
1887 sdconfig(cd.on, cd.spec, &cd.cf);