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) && !hard) {
850 b = sdmalloc(nb*unit->secsize);
859 decref(&sdev->r); /* gadverdamme! */
865 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
868 if(l < (nb*unit->secsize)){
869 nb = l/unit->secsize;
870 l = nb*unit->secsize - offset;
876 memmove(b+offset, a, len);
877 l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
882 else if(len > l - offset)
886 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
891 else if(len > l - offset)
894 memmove(a, b+offset, len);
910 sdrio(SDreq* r, void* a, long n)
918 if(n >= SDmaxio || n < 0)
921 if(u->haversense && r->cmd[0] == 0x03){
923 r->rlen = sizeof u->rsense;
926 memmove(a, u->rsense, r->rlen);
932 if(n > 0 && (data = sdmalloc(n)) == nil)
939 if(r->write && n > 0)
944 if(r->proto == SData){
945 f = u->dev->ifc->ataio;
948 f = u->dev->ifc->rio;
954 if(r->flags & SDvalidsense){
955 memmove(u->rsense, r->sense, sizeof u->rsense);
961 if(!r->write && r->rlen > 0)
962 memmove(a, data, r->rlen);
971 * SCSI simulation for non-SCSI devices
973 * see /sys/src/cmd/scuzz/sense.c for information on key.
974 * see /sys/lib/scsicodes for asc:ascq codes
977 sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
983 unit->sense[2] = key;
984 unit->sense[12] = asc;
985 unit->sense[13] = ascq;
988 if(status == SDcheck && !(r->flags & SDnosense)){
989 /* request sense case from sdfakescsi */
990 len = sizeof unit->sense;
991 if(len > sizeof r->sense-1)
992 len = sizeof r->sense-1;
993 memmove(r->sense, unit->sense, len);
997 r->flags |= SDvalidsense;
1004 sdfakescsi(SDreq *r)
1015 * Map SCSI commands into ATA commands for discs.
1016 * Fail any command with a LUN except INQUIRY which
1017 * will return 'logical unit not supported'.
1019 if((cmd[1]>>5) && cmd[0] != 0x12)
1020 return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
1024 return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1026 case 0x00: /* test unit ready */
1027 return sdsetsense(r, SDok, 0, 0, 0);
1029 case 0x03: /* request sense */
1030 if(cmd[4] < sizeof unit->sense)
1033 len = sizeof unit->sense;
1034 if(r->data && r->dlen >= len){
1035 memmove(r->data, unit->sense, len);
1038 return sdsetsense(r, SDok, 0, 0, 0);
1040 case 0x12: /* inquiry */
1041 if(cmd[4] < sizeof unit->inquiry)
1044 len = sizeof unit->inquiry;
1045 if(r->data && r->dlen >= len){
1046 memmove(r->data, unit->inquiry, len);
1049 return sdsetsense(r, SDok, 0, 0, 0);
1051 case 0x1B: /* start/stop unit */
1053 * nop for now, can use power management later.
1055 return sdsetsense(r, SDok, 0, 0, 0);
1057 case 0x25: /* read capacity */
1058 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1059 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1060 if(r->data == nil || r->dlen < 8)
1061 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1064 * Read capacity returns the LBA of the last sector.
1066 len = unit->sectors;
1074 len = unit->secsize;
1079 r->rlen = p - (uchar*)r->data;
1080 return sdsetsense(r, SDok, 0, 0, 0);
1082 case 0x9E: /* long read capacity */
1083 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1084 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1085 if(r->data == nil || r->dlen < 8)
1086 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1088 * Read capcity returns the LBA of the last sector.
1090 len = unit->sectors;
1102 len = unit->secsize;
1107 r->rlen = p - (uchar*)r->data;
1108 return sdsetsense(r, SDok, 0, 0, 0);
1109 case 0x08: /* read6 */
1110 case 0x0a: /* write6 */
1111 case 0x28: /* read10 */
1112 case 0x2a: /* write10 */
1113 case 0xa8: /* read12 */
1114 case 0xaa: /* write12 */
1115 case 0x88: /* read16 */
1116 case 0x8a: /* write16 */
1122 sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
1130 if((c[0] & 0xf) == 0xa)
1133 case 0x08: /* read6 */
1135 lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3];
1138 case 0x28: /* read10 */
1140 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1141 count = c[7]<<8 | c[8];
1143 case 0xa8: /* read12 */
1145 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1146 count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1148 case 0x88: /* read16 */
1150 /* ata commands only go to 48-bit lba */
1152 return sdsetsense(r, SDcheck, 3, 0xc, 2);
1153 lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32;
1154 lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1155 count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13];
1158 print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]);
1159 r->status = sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1164 if(r->dlen < count * r->unit->secsize)
1165 count = r->dlen/r->unit->secsize;
1174 extrarw(int write, Chan *c, void *a, long n, vlong off)
1181 sdev = sdgetdev(DEV(c->qid));
1188 unit = sdev->unit[UNIT(c->qid)];
1189 if(unit->vers != c->qid.vers)
1191 unit = sdev->unit[UNIT(c->qid)];
1193 if(i >= unit->nefile)
1195 f = unit->efile[i].r;
1197 f = unit->efile[i].w;
1198 if(i >= unit->nefile || f == nil)
1200 n = f(unit, c, a, n, off);
1207 deftopctl(SDev *s, char *p, char *e)
1209 return seprint(p, e, "sd%c %s %d units\n", s->idno, s->ifc->name, s->nunit);
1213 sdread(Chan *c, void *a, long n, vlong off)
1221 int i, l, m, status;
1224 switch(TYPE(c->qid)){
1228 m = 64*1024; /* room for register dumps */
1229 p = buf = smalloc(m);
1232 for(i = 0; i < nelem(devs); i++){
1234 if(sdev && sdev->ifc->rtopctl)
1235 p = sdev->ifc->rtopctl(sdev, p, e);
1237 p = deftopctl(sdev, p, e);
1240 n = readstr(off, a, n, buf);
1246 return devdirread(c, a, n, 0, 0, sdgen);
1249 sdev = sdgetdev(DEV(c->qid));
1253 unit = sdev->unit[UNIT(c->qid)];
1254 m = 16*1024; /* room for register dumps */
1256 l = snprint(p, m, "inquiry %.48s\n",
1257 (char*)unit->inquiry+8);
1260 * If there's a device specific routine it must
1261 * provide all information pertaining to night geometry
1262 * and the garscadden trains.
1264 if(unit->dev->ifc->rctl)
1265 l += unit->dev->ifc->rctl(unit, p+l, m-l);
1266 if(unit->sectors == 0)
1269 if(unit->dev->ifc->rctl == nil)
1270 l += snprint(p+l, m-l,
1271 "geometry %llud %lud\n",
1272 unit->sectors, unit->secsize);
1274 for(i = 0; i < unit->npart; i++){
1276 l += snprint(p+l, m-l,
1277 "part %s %llud %llud\n",
1278 pp->name, pp->start, pp->end);
1282 qunlock(&unit->ctl);
1284 l = readstr(offset, a, n, p);
1289 sdev = sdgetdev(DEV(c->qid));
1293 unit = sdev->unit[UNIT(c->qid)];
1296 qunlock(&unit->raw);
1300 if(unit->state == Rawdata){
1301 unit->state = Rawstatus;
1306 else if(unit->state == Rawstatus){
1309 unit->state = Rawcmd;
1311 if(r->proto == SData){
1319 memmove(p + Ahdrsz, r->cmd, i - Ahdrsz);
1321 i = readnum(0, a, n, status, NUMSIZE);
1326 qunlock(&unit->raw);
1331 return sdbio(c, 0, a, n, off);
1333 return extrarw(0, c, a, n, off);
1337 static void legacytopctl(Cmdbuf*);
1340 sdwrite(Chan* c, void* a, long n, vlong off)
1343 int i, atacdb, proto, ataproto;
1352 switch(TYPE(c->qid)){
1356 cb = parsecmd(a, n);
1362 error("empty control message");
1366 if(strcmp(f0, "config") == 0){
1367 /* wormhole into ugly legacy interface */
1374 * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
1375 * where sdifc[i]->name=="ata" and cb contains the args.
1379 for(i=0; sdifc[i]; i++){
1380 if(strcmp(sdifc[i]->name, f0) == 0){
1387 * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
1388 * where sdifc[i] and sdev match controller letter "1",
1389 * and cb contains the args.
1391 if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
1392 if((sdev = sdgetdev(f0[2])) != nil){
1397 error("unknown interface");
1406 ifc->wtopctl(sdev, cb);
1417 cb = parsecmd(a, n);
1418 sdev = sdgetdev(DEV(c->qid));
1421 unit = sdev->unit[UNIT(c->qid)];
1425 qunlock(&unit->ctl);
1430 if(unit->vers != c->qid.vers)
1435 if(strcmp(cb->f[0], "part") == 0){
1438 if(unit->sectors == 0 && !sdinitpart(unit))
1440 start = strtoull(cb->f[2], 0, 0);
1441 end = strtoull(cb->f[3], 0, 0);
1442 sdaddpart(unit, cb->f[1], start, end);
1444 else if(strcmp(cb->f[0], "delpart") == 0){
1445 if(cb->nf != 2 || unit->part == nil)
1447 sddelpart(unit, cb->f[1]);
1449 else if(unit->dev->ifc->wctl)
1450 unit->dev->ifc->wctl(unit, cb);
1453 qunlock(&unit->ctl);
1463 sdev = sdgetdev(DEV(c->qid));
1466 unit = sdev->unit[UNIT(c->qid)];
1469 qunlock(&unit->raw);
1473 switch(unit->state){
1475 /* sneaky ata commands */
1477 if(n > 1 && *u == 0xff){
1484 if(n < 6 || n > sizeof(req->cmd))
1486 if((req = malloc(sizeof(SDreq))) == nil)
1493 memmove(req->cmd, a, n);
1496 /* req->flags = SDnosense; */
1499 req->ataproto = ataproto;
1501 unit->state = Rawdata;
1506 unit->state = Rawcmd;
1512 unit->state = Rawstatus;
1515 n = sdrio(req, a, n);
1518 qunlock(&unit->raw);
1522 return sdbio(c, 1, a, n, off);
1524 return extrarw(1, c, a, n, off);
1531 sdwstat(Chan* c, uchar* dp, int n)
1539 if(c->qid.type & QTDIR)
1541 if(TYPE(c->qid) == Qtopctl){
1545 sdev = sdgetdev(DEV(c->qid));
1548 unit = sdev->unit[UNIT(c->qid)];
1555 qunlock(&unit->ctl);
1561 switch(TYPE(c->qid)){
1566 perm = &unit->ctlperm;
1569 perm = &unit->rawperm;
1572 pp = &unit->part[PART(c->qid)];
1573 if(unit->vers+pp->vers != c->qid.vers)
1579 if(strcmp(up->user, perm->user) && !iseve())
1582 d = smalloc(sizeof(Dir)+n);
1583 n = convM2D(dp, n, &d[0], (char*)&d[1]);
1586 if(d->atime != ~0 || d->mtime != ~0 || d->length != ~0)
1588 if(!emptystr(d[0].muid) || !emptystr(d[0].name))
1590 if(!emptystr(d[0].uid))
1591 kstrdup(&perm->user, d[0].uid);
1592 if(!emptystr(d[0].gid) && strcmp(d[0].gid, eve) != 0)
1594 if(d[0].mode != ~0UL)
1595 perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
1599 qunlock(&unit->ctl);
1607 configure(char* spec, DevConf* cf)
1613 if(sdindex(*spec) < 0)
1614 error("bad sd spec");
1616 if((p = strchr(cf->type, '/')) != nil)
1619 for(i = 0; sdifc[i] != nil; i++)
1620 if(strcmp(sdifc[i]->name, cf->type) == 0)
1623 error("sd type not found");
1627 if(sdifc[i]->probe == nil)
1628 error("sd type cannot probe");
1630 sdev = sdifc[i]->probe(cf);
1631 for(s=sdev; s; s=s->next)
1638 unconfigure(char* spec)
1644 if((i = sdindex(*spec)) < 0)
1648 if((sdev = devs[i]) == nil){
1659 /* make sure no interrupts arrive anymore before removing resources */
1660 if(sdev->enabled && sdev->ifc->disable)
1661 sdev->ifc->disable(sdev);
1663 for(i = 0; i != sdev->nunit; i++){
1664 if(unit = sdev->unit[i]){
1671 if(sdev->ifc->clear)
1672 sdev->ifc->clear(sdev);
1678 sdconfig(int on, char* spec, DevConf* cf)
1681 return configure(spec, cf);
1682 return unconfigure(spec);
1686 sdaddfile(SDunit *unit, char *s, int perm, char *u, SDrw *r, SDrw *w)
1695 for(i = 0; i < unit->nefile; i++)
1696 if(strcmp(unit->efile[i].name, s) == 0)
1698 if(i >= nelem(unit->efile)){
1702 if(i >= unit->nefile)
1703 unit->nefile = i + 1;
1704 e = unit->efile + i;
1706 kstrdup(&e->name, s);
1708 kstrdup(&e->user, u);
1722 for(i = 0; i < nelem(devs); i++){
1726 if(sd->ifc->disable == nil){
1727 print("#S/sd%c: no disable function\n", devletters[i]);
1730 sd->ifc->disable(sd);
1758 * This is wrong for so many reasons. This code must go.
1760 typedef struct Confdata Confdata;
1768 parseswitch(Confdata* cd, char* option)
1770 if(!strcmp("on", option))
1772 else if(!strcmp("off", option))
1779 parsespec(Confdata* cd, char* option)
1781 if(strlen(option) > 1)
1787 getnewport(DevConf* dc)
1791 p = malloc((dc->nports + 1) * sizeof(Devport));
1793 panic("sd: no memory for Devport");
1795 memmove(p, dc->ports, dc->nports * sizeof(Devport));
1799 p = &dc->ports[dc->nports++];
1801 p->port = (ulong)-1;
1806 parseport(Confdata* cd, char* option)
1811 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1)
1812 p = getnewport(&cd->cf);
1814 p = &cd->cf.ports[cd->cf.nports-1];
1815 p->port = strtol(option, &e, 0);
1816 if(e == nil || *e != '\0')
1821 parsesize(Confdata* cd, char* option)
1826 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
1827 p = getnewport(&cd->cf);
1829 p = &cd->cf.ports[cd->cf.nports-1];
1830 p->size = (int)strtol(option, &e, 0);
1831 if(e == nil || *e != '\0')
1836 parseirq(Confdata* cd, char* option)
1840 cd->cf.intnum = strtoul(option, &e, 0);
1841 if(e == nil || *e != '\0')
1846 parsetype(Confdata* cd, char* option)
1848 cd->cf.type = option;
1853 void (*parse)(Confdata*, char*);
1855 "switch", parseswitch,
1864 legacytopctl(Cmdbuf *cb)
1870 memset(&cd, 0, sizeof cd);
1872 for(i=0; i<cb->nf; i+=2){
1876 for(j=0; j<nelem(options); j++)
1877 if(strcmp(opt, options[j].name) == 0){
1878 options[j].parse(&cd, cb->f[i+1]);
1881 if(j == nelem(options))
1884 if(cd.on < 0 || cd.spec == 0)
1886 if(cd.on && cd.cf.type == nil)
1888 sdconfig(cd.on, cd.spec, &cd.cf);