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);
297 if((unit = malloc(sizeof(SDunit))) == nil){
298 qunlock(&sdev->unitlock);
301 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)
310 sdev->enabled = sdev->ifc->enable == nil || sdev->ifc->enable(sdev);
313 * No need to lock anything here as this is only
314 * called before the unit is made available in the
317 if(sdev->enabled == 0 || unit->dev->ifc->verify(unit) == 0){
318 qunlock(&sdev->unitlock);
324 sdev->unit[subno] = unit;
326 qunlock(&sdev->unitlock);
336 * Probe all known controller types and register any devices found.
338 for(i = 0; sdifc[i] != nil; i++){
339 if(sdifc[i]->pnp == nil)
341 sdadddevs(sdifc[i]->pnp());
346 sdadddevs(SDev *sdev)
351 for(; sdev; sdev=next){
354 sdev->unit = malloc(sdev->nunit * sizeof(SDunit*));
355 sdev->unitflg = malloc(sdev->nunit * sizeof(int));
356 if(sdev->unit == nil || sdev->unitflg == nil){
357 print("sdadddevs: out of memory\n");
362 sdev->ifc->clear(sdev);
366 id = sdindex(sdev->idno);
368 print("sdadddevs: bad id number %d (%C)\n", id, id);
372 for(i=0; i<nelem(devs); i++){
373 if(devs[j = (id+i)%nelem(devs)] == nil){
374 sdev->idno = devletters[j];
376 snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]);
381 if(i == nelem(devs)){
382 print("sdadddevs: out of device letters\n");
389 // sdrmdevs(SDev *sdev)
393 // snprint(buf, sizeof buf, "%c", sdev->idno);
398 sd2gen(Chan* c, int i, Dir* dp)
409 sdev = sdgetdev(DEV(c->qid));
411 unit = sdev->unit[UNIT(c->qid)];
416 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
418 perm = &unit->ctlperm;
419 if(emptystr(perm->user)){
420 kstrdup(&perm->user, eve);
423 devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
428 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
430 perm = &unit->rawperm;
431 if(emptystr(perm->user)){
432 kstrdup(&perm->user, eve);
433 perm->perm = DMEXCL|0600;
435 devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
440 pp = &unit->part[PART(c->qid)];
441 l = (pp->end - pp->start) * unit->secsize;
442 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
443 unit->vers+pp->vers, QTFILE);
444 if(emptystr(pp->user))
445 kstrdup(&pp->user, eve);
446 devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
451 if(t >= unit->nefile)
453 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qextra),
456 if(emptystr(e->user))
457 kstrdup(&e->user, eve);
458 devdir(c, q, e->name, 0, e->user, e->perm, dp);
468 sd1gen(Chan* c, int i, Dir* dp)
475 mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
476 qlock(&topctlunit.ctl);
477 p = &topctlunit.ctlperm;
478 if(p->user == nil || p->user[0] == 0){
479 kstrdup(&p->name, "sdctl");
480 kstrdup(&p->user, eve);
483 devdir(c, q, p->name, 0, p->user, p->perm, dp);
484 qunlock(&topctlunit.ctl);
491 efilegen(Chan *c, SDunit *unit, int i, Dir *dp)
497 if(unit->nefile == 0 || i >= unit->nefile)
502 if(emptystr(e->user))
503 kstrdup(&e->user, eve);
504 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qextra),
506 devdir(c, q, e->name, 0, e->user, e->perm, dp);
511 sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
520 switch(TYPE(c->qid)){
523 mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
524 sprint(up->genbuf, "#%C", sddevtab.dc);
525 devdir(c, q, up->genbuf, 0, eve, 0555, dp);
529 if(s+Qtopbase < Qunitdir)
530 return sd1gen(c, s+Qtopbase, dp);
531 s -= (Qunitdir-Qtopbase);
534 for(i=0; i<nelem(devs); i++){
536 if(s < devs[i]->nunit)
542 if(i == nelem(devs)){
543 /* Run off the end of the list */
548 if((sdev = devs[i]) == nil){
556 if((unit = sdev->unit[s]) == nil)
557 if((unit = sdgetunit(sdev, s)) == nil){
562 mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
563 if(emptystr(unit->user))
564 kstrdup(&unit->user, eve);
565 devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
571 mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
572 sprint(up->genbuf, "#%C", sddevtab.dc);
573 devdir(c, q, up->genbuf, 0, eve, 0555, dp);
577 if((sdev = sdgetdev(DEV(c->qid))) == nil){
578 devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
582 unit = sdev->unit[UNIT(c->qid)];
586 * Check for media change.
587 * If one has already been detected, sectors will be zero.
588 * If there is one waiting to be detected, online
590 * Online is a bit of a large hammer but does the job.
592 if(unit->sectors == 0
593 || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
598 r = sd2gen(c, i, dp);
604 if(unit->part == nil || i >= unit->npart){
605 r = efilegen(c, unit, i, dp);
611 if(!pp->valid || unit->sectors == 0){
616 l = (pp->end - pp->start) * (uvlong)unit->secsize;
617 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
618 unit->vers+pp->vers, QTFILE);
619 if(emptystr(pp->user))
620 kstrdup(&pp->user, eve);
621 devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
629 if((sdev = sdgetdev(DEV(c->qid))) == nil){
630 devdir(c, q, "unavailable", 0, eve, 0, dp);
633 unit = sdev->unit[UNIT(c->qid)];
635 r = sd2gen(c, TYPE(c->qid), dp);
640 return sd1gen(c, TYPE(c->qid), dp);
657 c = devattach(sddevtab.dc, spec);
658 mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
662 if(spec[0] != 's' || spec[1] != 'd')
665 subno = strtol(&spec[3], &p, 0);
669 if((sdev=sdgetdev(idno)) == nil)
671 if(sdgetunit(sdev, subno) == nil){
676 c = devattach(sddevtab.dc, spec);
677 mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
678 c->dev = (sdev->idno << UnitLOG) + subno;
684 sdwalk(Chan* c, Chan* nc, char** name, int nname)
686 return devwalk(c, nc, name, nname, nil, 0, sdgen);
690 sdstat(Chan* c, uchar* db, int n)
692 return devstat(c, db, n, nil, 0, sdgen);
696 sdopen(Chan* c, int omode)
703 c = devopen(c, omode, 0, 0, sdgen);
704 if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
707 sdev = sdgetdev(DEV(c->qid));
711 unit = sdev->unit[UNIT(c->qid)];
713 switch(TYPE(c->qid)){
715 c->qid.vers = unit->vers;
718 c->qid.vers = unit->vers;
719 if(tas(&unit->rawinuse) != 0){
724 unit->state = Rawcmd;
734 pp = &unit->part[PART(c->qid)];
735 c->qid.vers = unit->vers+pp->vers;
750 if(c->qid.type & QTDIR)
752 if(!(c->flag & COPEN))
755 switch(TYPE(c->qid)){
759 sdev = sdgetdev(DEV(c->qid));
761 unit = sdev->unit[UNIT(c->qid)];
769 #define iskaddr(a) ((uintptr)(a) > KZERO)
772 sdbio(Chan* c, int write, char* a, long len, uvlong off)
774 int nchange, hard, allocd, locked;
780 ulong max, nb, offset;
783 sdev = sdgetdev(DEV(c->qid));
788 unit = sdev->unit[UNIT(c->qid)];
795 /* notification of media change; go around again */
796 if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
801 /* other errors; give up */
806 pp = &unit->part[PART(c->qid)];
807 if(unit->vers+pp->vers != c->qid.vers)
811 * Check the request is within bounds.
812 * Removeable drives are locked throughout the I/O
813 * in case the media changes unexpectedly.
814 * Non-removeable drives are not locked during the I/O
815 * to allow the hardware to optimise if it can; this is
816 * a little fast and loose.
817 * It's assumed that non-removeable media parameters
818 * (sectors, secsize) can't change once the drive has
819 * been brought online.
821 bno = (off/unit->secsize) + pp->start;
822 nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
823 max = SDmaxio/unit->secsize;
828 if(bno >= pp->end || nb == 0){
836 locked = (unit->inquiry[1] & 0x80) != 0;
842 offset = off%unit->secsize;
843 if(offset+len > nb*unit->secsize)
844 len = nb*unit->secsize - offset;
845 hard = offset || write && len%unit->secsize;
847 if(iskaddr(a) && ((uintptr)a & (BY2PG-1))==0 && !hard) {
851 while((b = sdmalloc(nb*unit->secsize)) == nil){
853 resrcwait("no memory for sdbio");
863 decref(&sdev->r); /* gadverdamme! */
869 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
872 if(l < (nb*unit->secsize)){
873 nb = l/unit->secsize;
874 l = nb*unit->secsize - offset;
880 memmove(b+offset, a, len);
881 l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
886 else if(len > l - offset)
890 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
895 else if(len > l - offset)
898 memmove(a, b+offset, len);
914 sdrio(SDreq* r, void* a, long n)
922 if(n >= SDmaxio || n < 0)
925 if(u->haversense && r->cmd[0] == 0x03){
927 r->rlen = sizeof u->rsense;
930 memmove(a, u->rsense, r->rlen);
936 while(n > 0 && (data = sdmalloc(n)) == nil){
938 resrcwait("no memory for sdrio");
947 if(r->write && n > 0)
952 if(r->proto == SData){
953 f = u->dev->ifc->ataio;
956 f = u->dev->ifc->rio;
962 if(r->flags & SDvalidsense){
963 memmove(u->rsense, r->sense, sizeof u->rsense);
969 if(!r->write && r->rlen > 0)
970 memmove(a, data, r->rlen);
979 * SCSI simulation for non-SCSI devices
981 * see /sys/src/cmd/scuzz/sense.c for information on key.
982 * see /sys/lib/scsicodes for asc:ascq codes
985 sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
991 unit->sense[0] = 0x80 | 0x70; /* valid; fixed-format */
992 unit->sense[2] = key;
993 unit->sense[12] = asc;
994 unit->sense[13] = ascq;
997 if(status == SDcheck && !(r->flags & SDnosense)){
998 /* request sense case from sdfakescsi */
999 len = sizeof unit->sense;
1000 if(len > sizeof r->sense-1)
1001 len = sizeof r->sense-1;
1002 memmove(r->sense, unit->sense, len);
1004 unit->sense[12] = 0;
1005 unit->sense[13] = 0;
1006 r->flags |= SDvalidsense;
1013 sdfakescsi(SDreq *r)
1024 * Map SCSI commands into ATA commands for discs.
1025 * Fail any command with a LUN except INQUIRY which
1026 * will return 'logical unit not supported'.
1028 if((cmd[1]>>5) && cmd[0] != 0x12)
1029 return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
1033 return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1035 case 0x00: /* test unit ready */
1036 return sdsetsense(r, SDok, 0, 0, 0);
1038 case 0x03: /* request sense */
1039 if(cmd[4] < sizeof unit->sense)
1042 len = sizeof unit->sense;
1043 if(r->data && r->dlen >= len){
1044 memmove(r->data, unit->sense, len);
1047 return sdsetsense(r, SDok, 0, 0, 0);
1049 case 0x12: /* inquiry */
1050 if(cmd[4] < sizeof unit->inquiry)
1053 len = sizeof unit->inquiry;
1054 if(r->data && r->dlen >= len){
1055 memmove(r->data, unit->inquiry, len);
1058 return sdsetsense(r, SDok, 0, 0, 0);
1060 case 0x1B: /* start/stop unit */
1062 * nop for now, can use power management later.
1064 return sdsetsense(r, SDok, 0, 0, 0);
1066 case 0x25: /* read capacity */
1067 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1068 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1069 if(r->data == nil || r->dlen < 8)
1070 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1073 * Read capacity returns the LBA of the last sector.
1075 len = unit->sectors;
1076 if(len >= 0xffffffff)
1085 len = unit->secsize;
1090 r->rlen = p - (uchar*)r->data;
1091 return sdsetsense(r, SDok, 0, 0, 0);
1093 case 0x9E: /* long read capacity */
1094 if((cmd[1] & 0x01) || cmd[2] || cmd[3])
1095 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1096 if(r->data == nil || r->dlen < 8)
1097 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1099 * Read capcity returns the LBA of the last sector.
1101 len = unit->sectors;
1113 len = unit->secsize;
1118 r->rlen = p - (uchar*)r->data;
1119 return sdsetsense(r, SDok, 0, 0, 0);
1121 case 0x35: /* synchronize cache */
1123 return sdsetsense(r, SDok, 0, 0, 0);
1125 case 0x08: /* read6 */
1126 case 0x0a: /* write6 */
1127 case 0x28: /* read10 */
1128 case 0x2a: /* write10 */
1129 case 0xa8: /* read12 */
1130 case 0xaa: /* write12 */
1131 case 0x88: /* read16 */
1132 case 0x8a: /* write16 */
1138 sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
1146 if((c[0] & 0xf) == 0xa)
1149 case 0x08: /* read6 */
1151 lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3];
1154 case 0x28: /* read10 */
1156 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1157 count = c[7]<<8 | c[8];
1159 case 0xa8: /* read12 */
1161 lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
1162 count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1164 case 0x88: /* read16 */
1166 /* ata commands only go to 48-bit lba */
1168 return sdsetsense(r, SDcheck, 3, 0xc, 2);
1169 lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32;
1170 lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
1171 count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13];
1174 print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]);
1175 r->status = sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1180 if(r->dlen < count * r->unit->secsize)
1181 count = r->dlen/r->unit->secsize;
1190 extrarw(int write, Chan *c, void *a, long n, vlong off)
1197 sdev = sdgetdev(DEV(c->qid));
1204 unit = sdev->unit[UNIT(c->qid)];
1205 if(unit->vers != c->qid.vers)
1207 unit = sdev->unit[UNIT(c->qid)];
1209 if(i >= unit->nefile)
1211 f = unit->efile[i].r;
1213 f = unit->efile[i].w;
1214 if(i >= unit->nefile || f == nil)
1216 n = f(unit, c, a, n, off);
1223 deftopctl(SDev *s, char *p, char *e)
1225 return seprint(p, e, "sd%c %s %d units\n", s->idno, s->ifc->name, s->nunit);
1229 sdread(Chan *c, void *a, long n, vlong off)
1237 int i, l, m, status;
1240 switch(TYPE(c->qid)){
1244 m = 64*1024; /* room for register dumps */
1245 p = buf = smalloc(m);
1248 for(i = 0; i < nelem(devs); i++){
1250 if(sdev && sdev->ifc->rtopctl)
1251 p = sdev->ifc->rtopctl(sdev, p, e);
1253 p = deftopctl(sdev, p, e);
1256 n = readstr(off, a, n, buf);
1262 return devdirread(c, a, n, 0, 0, sdgen);
1265 sdev = sdgetdev(DEV(c->qid));
1269 unit = sdev->unit[UNIT(c->qid)];
1270 m = 16*1024; /* room for register dumps */
1272 l = snprint(p, m, "inquiry %.48s\n",
1273 (char*)unit->inquiry+8);
1276 * If there's a device specific routine it must
1277 * provide all information pertaining to night geometry
1278 * and the garscadden trains.
1280 if(unit->dev->ifc->rctl)
1281 l += unit->dev->ifc->rctl(unit, p+l, m-l);
1282 if(unit->sectors == 0)
1285 if(unit->dev->ifc->rctl == nil)
1286 l += snprint(p+l, m-l,
1287 "geometry %llud %lud\n",
1288 unit->sectors, unit->secsize);
1290 for(i = 0; i < unit->npart; i++){
1292 l += snprint(p+l, m-l,
1293 "part %s %llud %llud\n",
1294 pp->name, pp->start, pp->end);
1298 qunlock(&unit->ctl);
1300 l = readstr(offset, a, n, p);
1305 sdev = sdgetdev(DEV(c->qid));
1309 unit = sdev->unit[UNIT(c->qid)];
1312 qunlock(&unit->raw);
1316 if(unit->state == Rawdata){
1317 unit->state = Rawstatus;
1321 else if(unit->state == Rawstatus){
1324 unit->state = Rawcmd;
1326 if(r->proto == SData){
1334 memmove(p + Ahdrsz, r->cmd, i - Ahdrsz);
1336 i = readnum(0, a, n, status, NUMSIZE);
1341 qunlock(&unit->raw);
1346 return sdbio(c, 0, a, n, off);
1348 return extrarw(0, c, a, n, off);
1352 static void legacytopctl(Cmdbuf*);
1355 sdwrite(Chan* c, void* a, long n, vlong off)
1358 int i, atacdb, proto, ataproto;
1367 switch(TYPE(c->qid)){
1371 cb = parsecmd(a, n);
1377 error("empty control message");
1381 if(strcmp(f0, "config") == 0){
1382 /* wormhole into ugly legacy interface */
1389 * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
1390 * where sdifc[i]->name=="ata" and cb contains the args.
1394 for(i=0; sdifc[i]; i++){
1395 if(strcmp(sdifc[i]->name, f0) == 0){
1402 * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
1403 * where sdifc[i] and sdev match controller letter "1",
1404 * and cb contains the args.
1406 if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
1407 if((sdev = sdgetdev(f0[2])) != nil){
1412 error("unknown interface");
1421 ifc->wtopctl(sdev, cb);
1432 cb = parsecmd(a, n);
1433 sdev = sdgetdev(DEV(c->qid));
1436 unit = sdev->unit[UNIT(c->qid)];
1440 qunlock(&unit->ctl);
1445 if(unit->vers != c->qid.vers)
1450 if(strcmp(cb->f[0], "part") == 0){
1453 if(unit->sectors == 0 && !sdinitpart(unit))
1455 start = strtoull(cb->f[2], 0, 0);
1456 end = strtoull(cb->f[3], 0, 0);
1457 sdaddpart(unit, cb->f[1], start, end);
1459 else if(strcmp(cb->f[0], "delpart") == 0){
1460 if(cb->nf != 2 || unit->part == nil)
1462 sddelpart(unit, cb->f[1]);
1464 else if(unit->dev->ifc->wctl)
1465 unit->dev->ifc->wctl(unit, cb);
1468 qunlock(&unit->ctl);
1478 sdev = sdgetdev(DEV(c->qid));
1481 unit = sdev->unit[UNIT(c->qid)];
1484 qunlock(&unit->raw);
1488 switch(unit->state){
1490 /* sneaky ata commands */
1492 if(n > 1 && *u == 0xff){
1499 if(n < 6 || n > sizeof(req->cmd))
1501 req = smalloc(sizeof(SDreq));
1507 memmove(req->cmd, a, n);
1510 /* req->flags = SDnosense; */
1513 req->ataproto = ataproto;
1515 unit->state = Rawdata;
1520 unit->state = Rawcmd;
1526 unit->state = Rawstatus;
1529 n = sdrio(req, a, n);
1532 qunlock(&unit->raw);
1536 return sdbio(c, 1, a, n, off);
1538 return extrarw(1, c, a, n, off);
1545 sdwstat(Chan* c, uchar* dp, int n)
1553 if(c->qid.type & QTDIR)
1555 if(TYPE(c->qid) == Qtopctl){
1559 sdev = sdgetdev(DEV(c->qid));
1562 unit = sdev->unit[UNIT(c->qid)];
1568 qunlock(&unit->ctl);
1575 switch(TYPE(c->qid)){
1580 perm = &unit->ctlperm;
1583 perm = &unit->rawperm;
1586 pp = &unit->part[PART(c->qid)];
1587 if(unit->vers+pp->vers != c->qid.vers)
1593 if(strcmp(up->user, perm->user) && !iseve())
1596 d = smalloc(sizeof(Dir)+n);
1597 n = convM2D(dp, n, &d[0], (char*)&d[1]);
1600 if(d->atime != ~0 || d->mtime != ~0 || d->length != ~0)
1602 if(!emptystr(d[0].muid) || !emptystr(d[0].name))
1604 if(!emptystr(d[0].uid))
1605 kstrdup(&perm->user, d[0].uid);
1606 if(!emptystr(d[0].gid) && strcmp(d[0].gid, eve) != 0)
1608 if(d[0].mode != ~0UL)
1609 perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
1611 qunlock(&unit->ctl);
1619 configure(char* spec, DevConf* cf)
1625 if(sdindex(*spec) < 0)
1626 error("bad sd spec");
1628 if((p = strchr(cf->type, '/')) != nil)
1631 for(i = 0; sdifc[i] != nil; i++)
1632 if(strcmp(sdifc[i]->name, cf->type) == 0)
1635 error("sd type not found");
1639 if(sdifc[i]->probe == nil)
1640 error("sd type cannot probe");
1642 sdev = sdifc[i]->probe(cf);
1643 for(s=sdev; s; s=s->next)
1650 unconfigure(char* spec)
1656 if((i = sdindex(*spec)) < 0)
1660 if((sdev = devs[i]) == nil){
1671 /* make sure no interrupts arrive anymore before removing resources */
1672 if(sdev->enabled && sdev->ifc->disable)
1673 sdev->ifc->disable(sdev);
1675 for(i = 0; i != sdev->nunit; i++){
1676 if(unit = sdev->unit[i]){
1683 if(sdev->ifc->clear)
1684 sdev->ifc->clear(sdev);
1690 sdconfig(int on, char* spec, DevConf* cf)
1693 return configure(spec, cf);
1694 return unconfigure(spec);
1698 sdaddfile(SDunit *unit, char *s, int perm, char *u, SDrw *r, SDrw *w)
1707 for(i = 0; i < unit->nefile; i++)
1708 if(strcmp(unit->efile[i].name, s) == 0)
1710 if(i >= nelem(unit->efile)){
1714 if(i >= unit->nefile)
1715 unit->nefile = i + 1;
1716 e = unit->efile + i;
1718 kstrdup(&e->name, s);
1720 kstrdup(&e->user, u);
1734 for(i = 0; i < nelem(devs); i++){
1738 if(sd->ifc->disable == nil){
1739 print("#S/sd%c: no disable function\n", devletters[i]);
1742 sd->ifc->disable(sd);
1770 * This is wrong for so many reasons. This code must go.
1772 typedef struct Confdata Confdata;
1780 parseswitch(Confdata* cd, char* option)
1782 if(!strcmp("on", option))
1784 else if(!strcmp("off", option))
1791 parsespec(Confdata* cd, char* option)
1793 if(strlen(option) > 1)
1799 getnewport(DevConf* dc)
1803 p = malloc((dc->nports + 1) * sizeof(Devport));
1805 panic("sd: no memory for Devport");
1807 memmove(p, dc->ports, dc->nports * sizeof(Devport));
1811 p = &dc->ports[dc->nports++];
1813 p->port = (ulong)-1;
1818 parseport(Confdata* cd, char* option)
1823 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1)
1824 p = getnewport(&cd->cf);
1826 p = &cd->cf.ports[cd->cf.nports-1];
1827 p->port = strtol(option, &e, 0);
1828 if(e == nil || *e != '\0')
1833 parsesize(Confdata* cd, char* option)
1838 if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
1839 p = getnewport(&cd->cf);
1841 p = &cd->cf.ports[cd->cf.nports-1];
1842 p->size = (int)strtol(option, &e, 0);
1843 if(e == nil || *e != '\0')
1848 parseirq(Confdata* cd, char* option)
1852 cd->cf.intnum = strtoul(option, &e, 0);
1853 if(e == nil || *e != '\0')
1858 parsetype(Confdata* cd, char* option)
1860 cd->cf.type = option;
1865 void (*parse)(Confdata*, char*);
1867 "switch", parseswitch,
1876 legacytopctl(Cmdbuf *cb)
1882 memset(&cd, 0, sizeof cd);
1884 for(i=0; i<cb->nf; i+=2){
1888 for(j=0; j<nelem(options); j++)
1889 if(strcmp(opt, options[j].name) == 0){
1890 options[j].parse(&cd, cb->f[i+1]);
1893 if(j == nelem(options))
1896 if(cd.on < 0 || cd.spec == 0)
1898 if(cd.on && cd.cf.type == nil)
1900 sdconfig(cd.on, cd.spec, &cd.cf);