AHCI: get it to build and almost work.
[akaros.git] / kern / drivers / dev / sd.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 /*
11  * Storage Device.
12  */
13
14 #include <vfs.h>
15
16 #include <assert.h>
17 #include <cpio.h>
18 #include <error.h>
19 #include <ip.h>
20 #include <kfs.h>
21 #include <kmalloc.h>
22 #include <kref.h>
23 #include <pmap.h>
24 #include <slab.h>
25 #include <smp.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include <sd.h>
30
31 extern struct dev sddevtab;
32 struct sdifc sdiahciifc;
33
34 /* In Plan 9, this array is auto-generated. That's almost certainly not
35  * necessary;
36  * we can use linker sets at some point, as we do elsewhere in Akaros. */
37 struct sdifc *sdifc[] = {
38     &sdiahciifc, NULL,
39 };
40
41 static const char Echange[] = "media or partition has changed";
42
43 static const char devletters[] =
44     "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
45
46 static struct sdev *devs[sizeof(devletters) - 1];
47
48 static qlock_t devslock = QLOCK_INITIALIZER(devslock);
49
50 enum {
51         Rawcmd,
52         Rawdata,
53         Rawstatus,
54 };
55
56 enum {
57         Qtopdir = 1, /* top level directory */
58         Qtopbase,
59         Qtopctl = Qtopbase,
60
61         Qunitdir, /* directory per unit */
62         Qunitbase,
63         Qctl = Qunitbase,
64         Qraw,
65         Qpart,
66
67         TypeLOG = 4,
68         NType = (1 << TypeLOG),
69         TypeMASK = (NType - 1),
70         TypeSHIFT = 0,
71
72         PartLOG = 8,
73         NPart = (1 << PartLOG),
74         PartMASK = (NPart - 1),
75         PartSHIFT = TypeLOG,
76
77         UnitLOG = 8,
78         NUnit = (1 << UnitLOG),
79         UnitMASK = (NUnit - 1),
80         UnitSHIFT = (PartLOG + TypeLOG),
81
82         DevLOG = 8,
83         NDev = (1 << DevLOG),
84         DevMASK = (NDev - 1),
85         DevSHIFT = (UnitLOG + PartLOG + TypeLOG),
86
87         Ncmd = 20,
88 };
89
90 #define TYPE(q) ((((uint32_t)(q).path) >> TypeSHIFT) & TypeMASK)
91 #define PART(q) ((((uint32_t)(q).path) >> PartSHIFT) & PartMASK)
92 #define UNIT(q) ((((uint32_t)(q).path) >> UnitSHIFT) & UnitMASK)
93 #define DEV(q) ((((uint32_t)(q).path) >> DevSHIFT) & DevMASK)
94 #define QID(d, u, p, t)                                                        \
95         (((d) << DevSHIFT) | ((u) << UnitSHIFT) | ((p) << PartSHIFT) |             \
96          ((t) << TypeSHIFT))
97
98 void sdaddpart(struct sdunit *unit, char *name, uint64_t start, uint64_t end)
99 {
100         struct sdpart *pp;
101         int i, partno;
102
103         /*
104          * Check name not already used
105          * and look for a free slot.
106          */
107         if (unit->part != NULL) {
108                 partno = -1;
109                 for (i = 0; i < unit->npart; i++) {
110                         pp = &unit->part[i];
111                         if (!pp->valid) {
112                                 if (partno == -1)
113                                         partno = i;
114                                 break;
115                         }
116                         if (strcmp(name, pp->sdperm.name) == 0) {
117                                 if (pp->start == start && pp->end == end)
118                                         return;
119                                 error(EINVAL, "%s: '%s' is not valid", __func__, name);
120                         }
121                 }
122         } else {
123                 unit->part = kzmalloc(sizeof(struct sdpart) * SDnpart, 0);
124                 if (unit->part == NULL)
125                         error(ENOMEM, "%s: can't allocate %d bytes", __func__,
126                               sizeof(struct sdpart) * SDnpart);
127                 unit->npart = SDnpart;
128                 partno = 0;
129         }
130
131         /*
132          * If no free slot found then increase the
133          * array size (can't get here with unit->part == NULL).
134          */
135         if (partno == -1) {
136                 if (unit->npart >= NPart)
137                         error(ENOMEM, "%s: no memory", __func__);
138                 pp = kzmalloc(sizeof(struct sdpart) * (unit->npart + SDnpart), 0);
139                 if (pp == NULL)
140                         error(ENOMEM, "%s: Can't allocate space for %d partitions",
141                               unit->npart + SDnpart);
142                 memmove(pp, unit->part, sizeof(struct sdpart) * unit->npart);
143                 kfree(unit->part);
144                 unit->part = pp;
145                 partno = unit->npart;
146                 unit->npart += SDnpart;
147         }
148
149         /*
150          * Check size and extent are valid.
151          */
152         if (start > end)
153                 error(EINVAL, "%s: start %d > end %d", __func__, start, end);
154         if (end > unit->sectors)
155                 error(EINVAL, "%s: end %d > number of sectors %d", __func__, end,
156                       unit->sectors);
157         pp = &unit->part[partno];
158         pp->start = start;
159         pp->end = end;
160         kstrdup(&pp->sdperm.name, name);
161         kstrdup(&pp->sdperm.user, eve);
162         pp->sdperm.perm = 0640;
163         pp->valid = 1;
164 }
165
166 static void sddelpart(struct sdunit *unit, char *name)
167 {
168         int i;
169         struct sdpart *pp;
170         /*
171          * Look for the partition to delete.
172          * Can't delete if someone still has it open.
173          */
174         pp = unit->part;
175         for (i = 0; i < unit->npart; i++) {
176                 if (strcmp(name, pp->sdperm.name) == 0)
177                         break;
178                 pp++;
179         }
180         if (i >= unit->npart)
181                 error(EINVAL, "%s: %d > npart %d", __func__, i, unit->npart);
182
183         /* TODO: Implement permission checking and raise errors as appropriate. */
184         // if (strcmp(up->user, pp->SDperm.user) && !iseve())
185                 // error(Eperm);
186
187         pp->valid = 0;
188         pp->vers++;
189 }
190
191 static void sdincvers(struct sdunit *unit)
192 {
193         int i;
194
195         unit->vers++;
196         if (unit->part) {
197                 for (i = 0; i < unit->npart; i++) {
198                         unit->part[i].valid = 0;
199                         unit->part[i].vers++;
200                 }
201         }
202 }
203
204 static int sdinitpart(struct sdunit *unit)
205 {
206 #if 0
207         Mach *m;
208         int nf;
209         uint64_t start, end;
210         char *f[4], *p, *q, buf[10];
211
212         m = machp();
213 #endif
214         if (unit->sectors > 0) {
215                 unit->sectors = unit->secsize = 0;
216                 sdincvers(unit);
217         }
218
219         /* device must be connected or not; other values are trouble */
220         if (unit->inquiry[0] & 0xC0) /* see SDinq0periphqual */
221                 return 0;
222         switch (unit->inquiry[0] & SDinq0periphtype) {
223         case SDperdisk:
224         case SDperworm:
225         case SDpercd:
226         case SDpermo:
227                 break;
228         default:
229                 return 0;
230         }
231
232         if (unit->dev->ifc->online)
233                 unit->dev->ifc->online(unit);
234         if (unit->sectors) {
235                 sdincvers(unit);
236                 sdaddpart(unit, "data", 0, unit->sectors);
237
238 /*
239  * Use partitions passed from boot program,
240  * e.g.
241  *      sdC0part=dos 63 123123/plan9 123123 456456
242  * This happens before /boot sets hostname so the
243  * partitions will have the null-string for user.
244  * The gen functions patch it up.
245  */
246 #if 0
247                 snprintf(buf, sizeof(buf), "%spart", unit->sdperm.name);
248                 for (p = getconf(buf); p != NULL; p = q) {
249                         q = strchr(p, '/');
250                         if (q)
251                                 *q++ = '\0';
252                         nf = tokenize(p, f, ARRAY_SIZE(f));
253                         if (nf < 3)
254                                 continue;
255
256                         start = strtoull(f[1], 0, 0);
257                         end = strtoull(f[2], 0, 0);
258                         if(!waserror()){
259                                 sdaddpart(unit, f[0], start, end);
260                                 poperror();
261                         }
262                 }
263 #endif
264         }
265
266         return 1;
267 }
268
269 static int sdindex(int idno)
270 {
271         char *p;
272
273         p = strchr(devletters, idno);
274         if (p == NULL)
275                 return -1;
276         return p - devletters;
277 }
278
279 static struct sdev *sdgetdev(int idno)
280 {
281         struct sdev *sdev;
282         int i;
283
284         if ((i = sdindex(idno)) < 0)
285                 return NULL;
286
287         qlock(&devslock);
288         sdev = devs[i];
289         if (sdev)
290                 kref_get(&sdev->r, 1);
291         qunlock(&devslock);
292         return sdev;
293 }
294
295 static struct sdunit *sdgetunit(struct sdev *sdev, int subno)
296 {
297         struct sdunit *unit;
298         char buf[32];
299
300         /*
301          * Associate a unit with a given device and sub-unit
302          * number on that device.
303          * The device will be probed if it has not already been
304          * successfully accessed.
305          */
306         qlock(&sdev->unitlock);
307         if (subno > sdev->nunit) {
308                 qunlock(&sdev->unitlock);
309                 return NULL;
310         }
311
312         unit = sdev->unit[subno];
313         if (unit == NULL) {
314                 /*
315                  * Probe the unit only once. This decision
316                  * may be a little severe and reviewed later.
317                  */
318                 if (sdev->unitflg[subno]) {
319                         qunlock(&sdev->unitlock);
320                         return NULL;
321                 }
322                 unit = kzmalloc(sizeof(struct sdunit), 0);
323                 if (unit == NULL) {
324                         qunlock(&sdev->unitlock);
325                         return NULL;
326                 }
327                 sdev->unitflg[subno] = 1;
328
329                 snprintf(buf, sizeof(buf), "%s%d", sdev->name, subno);
330                 kstrdup(&unit->sdperm.name, buf);
331                 kstrdup(&unit->sdperm.user, eve);
332                 unit->sdperm.perm = 0555;
333                 unit->subno = subno;
334                 unit->dev = sdev;
335                 qlock_init(&unit->ctl);
336
337                 if (sdev->enabled == 0 && sdev->ifc->enable)
338                         sdev->ifc->enable(sdev);
339                 sdev->enabled = 1;
340
341                 /*
342                  * No need to lock anything here as this is only
343                  * called before the unit is made available in the
344                  * sdunit[] array.
345                  */
346                 if (unit->dev->ifc->verify(unit) == 0) {
347                         qunlock(&sdev->unitlock);
348                         kfree(unit);
349                         return NULL;
350                 }
351                 sdev->unit[subno] = unit;
352         }
353         qunlock(&sdev->unitlock);
354         return unit;
355 }
356
357 static void sdreset(void)
358 {
359         int i;
360         struct sdev *sdev;
361
362         /*
363          * Probe all known controller types and register any devices found.
364          */
365         for (i = 0; sdifc[i] != NULL; i++) {
366                 if (sdifc[i]->pnp == NULL)
367                         continue;
368                 sdev = sdifc[i]->pnp();
369                 if (sdev == NULL)
370                         continue;
371                 sdadddevs(sdev);
372         }
373 }
374
375 void sdadddevs(struct sdev *sdev)
376 {
377         int i, j, id;
378         struct sdev *next;
379
380         for (; sdev; sdev = next) {
381                 next = sdev->next;
382
383                 sdev->unit = (struct sdunit **)kzmalloc(
384                     sdev->nunit * sizeof(struct sdunit *), 0);
385                 sdev->unitflg = (int *)kzmalloc(sdev->nunit * sizeof(int), 0);
386                 if (sdev->unit == NULL || sdev->unitflg == NULL) {
387                         printd("sdadddevs: out of memory\n");
388                 giveup:
389                         kfree(sdev->unit);
390                         kfree(sdev->unitflg);
391                         if (sdev->ifc->clear)
392                                 sdev->ifc->clear(sdev);
393                         kfree(sdev);
394                         continue;
395                 }
396                 id = sdindex(sdev->idno);
397                 if (id == -1) {
398                         printd("sdadddevs: bad id number %d (%C)\n", id, id);
399                         goto giveup;
400                 }
401                 qlock(&devslock);
402                 for (i = 0; i < ARRAY_SIZE(devs); i++) {
403                         j = (id + i) % ARRAY_SIZE(devs);
404                         if (devs[j] == NULL) {
405                                 sdev->idno = devletters[j];
406                                 devs[j] = sdev;
407                                 snprintf(sdev->name, sizeof(sdev->name), "sd%c", devletters[j]);
408                                 break;
409                         }
410                 }
411                 qunlock(&devslock);
412                 if (i == ARRAY_SIZE(devs)) {
413                         printd("sdadddevs: out of device letters\n");
414                         goto giveup;
415                 }
416         }
417 }
418
419 void sdaddallconfs(void (*addconf)(struct sdunit *))
420 {
421         int i, u;
422         struct sdev *sdev;
423
424         for (i = 0; i < ARRAY_SIZE(devs); i++) /* each controller */
425                 for (sdev = devs[i]; sdev; sdev = sdev->next)
426                         for (u = 0; u < sdev->nunit; u++) /* each drive */
427                                 (*addconf)(sdev->unit[u]);
428 }
429
430 static int sd2gen(struct chan *c, int i, struct dir *dp)
431 {
432         struct qid q;
433         uint64_t l;
434         struct sdpart *pp;
435         struct sdperm *perm;
436         struct sdunit *unit;
437         struct sdev *sdev;
438         int rv;
439
440         sdev = sdgetdev(DEV(c->qid));
441         assert(sdev);
442         unit = sdev->unit[UNIT(c->qid)];
443
444         rv = -1;
445         switch (i) {
446         case Qctl:
447                 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
448                       unit->vers, QTFILE);
449                 perm = &unit->ctlperm;
450                 if (emptystr(perm->user)) {
451                         kstrdup(&perm->user, eve);
452                         perm->perm = 0644; /* nothing secret in ctl */
453                 }
454                 devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
455                 rv = 1;
456                 break;
457
458         case Qraw:
459                 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
460                       unit->vers, QTFILE);
461                 perm = &unit->rawperm;
462                 if (emptystr(perm->user)) {
463                         kstrdup(&perm->user, eve);
464                         perm->perm = DMEXCL | 0600;
465                 }
466                 devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
467                 rv = 1;
468                 break;
469
470         case Qpart:
471                 pp = &unit->part[PART(c->qid)];
472                 l = (pp->end - pp->start) * unit->secsize;
473                 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
474                       unit->vers + pp->vers, QTFILE);
475                 if (emptystr(pp->sdperm.user))
476                         kstrdup(&pp->sdperm.user, eve);
477                 devdir(c, q, pp->sdperm.name, l, pp->sdperm.user, pp->sdperm.perm, dp);
478                 rv = 1;
479                 break;
480         }
481
482         kref_put(&sdev->r);
483         return rv;
484 }
485
486 static int sd1gen(struct chan *c, int i, struct dir *dp)
487 {
488         struct qid q;
489
490         switch (i) {
491         case Qtopctl:
492                 mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
493                 devdir(c, q, "sdctl", 0, eve, 0644, dp); /* no secrets */
494                 return 1;
495         }
496         return -1;
497 }
498
499 static int sdgen(struct chan *c, char *d, struct dirtab *dir, int j, int s,
500                  struct dir *dp)
501 {
502         struct qid q = {};
503         int64_t l;
504         int i, r;
505         struct sdpart *pp;
506         struct sdunit *unit;
507         struct sdev *sdev;
508
509         switch (TYPE(c->qid)) {
510         case Qtopdir:
511                 if (s == DEVDOTDOT) {
512                         mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
513                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#%s", sddevtab.name);
514                         devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
515                         return 1;
516                 }
517
518                 if (s + Qtopbase < Qunitdir)
519                         return sd1gen(c, s + Qtopbase, dp);
520                 s -= (Qunitdir - Qtopbase);
521
522                 qlock(&devslock);
523                 for (i = 0; i < ARRAY_SIZE(devs); i++) {
524                         if (devs[i]) {
525                                 if (s < devs[i]->nunit)
526                                         break;
527                                 s -= devs[i]->nunit;
528                         }
529                 }
530
531                 if (i == ARRAY_SIZE(devs)) {
532                         /* Run off the end of the list */
533                         qunlock(&devslock);
534                         return -1;
535                 }
536
537                 sdev = devs[i];
538                 if (sdev == NULL) {
539                         qunlock(&devslock);
540                         return 0;
541                 }
542
543                 kref_get(&sdev->r, 1);
544                 qunlock(&devslock);
545
546                 unit = sdev->unit[s];
547                 if (unit == NULL)
548                         unit = sdgetunit(sdev, s);
549                 if (unit == NULL) {
550                         kref_put(&sdev->r);
551                         return 0;
552                 }
553
554                 mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
555                 if (emptystr(unit->sdperm.user))
556                         kstrdup(&unit->sdperm.user, eve);
557                 devdir(c, q, unit->sdperm.name, 0, unit->sdperm.user, unit->sdperm.perm,
558                        dp);
559                 kref_put(&sdev->r);
560                 return 1;
561
562         case Qunitdir:
563                 if (s == DEVDOTDOT) {
564                         mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
565                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#%s", sddevtab.name);
566                         devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
567                         return 1;
568                 }
569
570                 sdev = sdgetdev(DEV(c->qid));
571                 if (sdev == NULL) {
572                         devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
573                         return 1;
574                 }
575
576                 unit = sdev->unit[UNIT(c->qid)];
577                 qlock(&unit->ctl);
578
579                 /*
580                  * Check for media change.
581                  * If one has already been detected, sectors will be zero.
582                  * If there is one waiting to be detected, online
583                  * will return > 1.
584                  * Online is a bit of a large hammer but does the job.
585                  */
586                 if (unit->sectors == 0 ||
587                     (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
588                         sdinitpart(unit);
589
590                 i = s + Qunitbase;
591                 if (i < Qpart) {
592                         r = sd2gen(c, i, dp);
593                         qunlock(&unit->ctl);
594                         kref_put(&sdev->r);
595                         return r;
596                 }
597                 i -= Qpart;
598                 if (unit->part == NULL || i >= unit->npart) {
599                         qunlock(&unit->ctl);
600                         kref_put(&sdev->r);
601                         break;
602                 }
603                 pp = &unit->part[i];
604                 if (!pp->valid) {
605                         qunlock(&unit->ctl);
606                         kref_put(&sdev->r);
607                         return 0;
608                 }
609                 l = (pp->end - pp->start) * (int64_t)unit->secsize;
610                 mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
611                       unit->vers + pp->vers, QTFILE);
612                 if (emptystr(pp->sdperm.user))
613                         kstrdup(&pp->sdperm.user, eve);
614                 devdir(c, q, pp->sdperm.name, l, pp->sdperm.user, pp->sdperm.perm, dp);
615                 qunlock(&unit->ctl);
616                 kref_put(&sdev->r);
617                 return 1;
618         case Qraw:
619         case Qctl:
620         case Qpart:
621                 sdev = sdgetdev(DEV(c->qid));
622                 if (sdev == NULL) {
623                         devdir(c, q, "unavailable", 0, eve, 0, dp);
624                         return 1;
625                 }
626                 unit = sdev->unit[UNIT(c->qid)];
627                 qlock(&unit->ctl);
628                 r = sd2gen(c, TYPE(c->qid), dp);
629                 qunlock(&unit->ctl);
630                 kref_put(&sdev->r);
631                 return r;
632         case Qtopctl:
633                 return sd1gen(c, TYPE(c->qid), dp);
634         default:
635                 break;
636         }
637
638         return -1;
639 }
640
641 static struct chan *sdattach(char *spec)
642 {
643         struct chan *c;
644         char *p;
645         struct sdev *sdev;
646         int idno, subno;
647
648         if (*spec == '\0') {
649                 c = devattach(sddevtab.name, spec);
650                 mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
651                 return c;
652         }
653
654         if (spec[0] != 's' || spec[1] != 'd')
655                 error(EINVAL, "First two characters of spec must be 'sd', not %c%c",
656                       spec[0], spec[1]);
657         idno = spec[2];
658         subno = strtol(&spec[3], &p, 0);
659         if (p == &spec[3])
660                 error(EINVAL, "subno '%s' is not a number", &spec[3]);
661
662         sdev = sdgetdev(idno);
663         if (sdev == NULL)
664                 error(ENOENT, "No such unit %d", idno);
665         if (sdgetunit(sdev, subno) == NULL) {
666                 kref_put(&sdev->r);
667                 error(ENOENT, "No such subno %d", subno);
668         }
669
670         c = devattach(sddevtab.name, spec);
671         mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
672         c->dev = (sdev->idno << UnitLOG) + subno;
673         kref_put(&sdev->r);
674         return c;
675 }
676
677 static struct walkqid *sdwalk(struct chan *c, struct chan *nc, char **name,
678                               int nname)
679 {
680         return devwalk(c, nc, name, nname, NULL, 0, sdgen);
681 }
682
683 static int32_t sdstat(struct chan *c, uint8_t *db, int32_t n)
684 {
685         return devstat(c, db, n, NULL, 0, sdgen);
686 }
687
688 static struct chan *sdopen(struct chan *c, int omode)
689 {
690         ERRSTACK(1);
691         struct sdpart *pp;
692         struct sdunit *unit;
693         struct sdev *sdev;
694         uint8_t tp;
695
696         c = devopen(c, omode, 0, 0, sdgen);
697         if ((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
698                 return c;
699
700         sdev = sdgetdev(DEV(c->qid));
701         if (sdev == NULL)
702                 error(ENOENT, "No such device");
703
704         unit = sdev->unit[UNIT(c->qid)];
705
706         switch (TYPE(c->qid)) {
707         case Qctl:
708                 c->qid.vers = unit->vers;
709                 break;
710         case Qraw:
711                 c->qid.vers = unit->vers;
712                 if (test_and_set_bit(0, (unsigned long *)&unit->rawinuse) !=
713                     0) {
714                         c->flag &= ~COPEN;
715                         kref_put(&sdev->r);
716                         error(EBUSY, "In use");
717                 }
718                 unit->state = Rawcmd;
719                 break;
720         case Qpart:
721                 qlock(&unit->ctl);
722                 if (waserror()) {
723                         qunlock(&unit->ctl);
724                         c->flag &= ~COPEN;
725                         kref_put(&sdev->r);
726                         nexterror();
727                 }
728                 pp = &unit->part[PART(c->qid)];
729                 c->qid.vers = unit->vers + pp->vers;
730                 qunlock(&unit->ctl);
731                 poperror();
732                 break;
733         }
734         kref_put(&sdev->r);
735         return c;
736 }
737
738 static void sdclose(struct chan *c)
739 {
740         struct sdunit *unit;
741         struct sdev *sdev;
742
743         if (c->qid.type & QTDIR)
744                 return;
745         if (!(c->flag & COPEN))
746                 return;
747
748         switch (TYPE(c->qid)) {
749         default:
750                 break;
751         case Qraw:
752                 sdev = sdgetdev(DEV(c->qid));
753                 if (sdev) {
754                         unit = sdev->unit[UNIT(c->qid)];
755                         unit->rawinuse = 0;
756                         kref_put(&sdev->r);
757                 }
758                 break;
759         }
760 }
761
762 static int32_t sdbio(struct chan *c, int write, char *a, int32_t len,
763                      int64_t off)
764 {
765         ERRSTACK(2);
766         int nchange;
767         uint8_t *b;
768         struct sdpart *pp;
769         struct sdunit *unit;
770         struct sdev *sdev;
771         int64_t bno;
772         int32_t l, max, nb, offset;
773
774         sdev = sdgetdev(DEV(c->qid));
775         if (sdev == NULL) {
776                 kref_put(&sdev->r);
777                 error(ENOENT, "No such file or directory");
778         }
779         unit = sdev->unit[UNIT(c->qid)];
780         if (unit == NULL)
781                 error(ENOENT, "No such file or directory");
782
783         nchange = 0;
784         qlock(&unit->ctl);
785         while (waserror()) {
786                 /* notification of media change; go around again */
787                 /* Meta-comment: I'm leaving commented-out code in place,
788                  * which originally contained a strcmp of the error string to
789                  * a value, to remind us: plan 9 is a distributed system. It's
790                  * possible in principle to have the storage device on this
791                  * machine use an sdi{ata,ahci} on another machine, and it all
792                  * works. Nobody is going to do that, now, so get_errno() it is.
793                  * if (strcmp(up->errstr, Eio) == 0 ... */
794                 if ((get_errno() == EIO) && (unit->sectors == 0) && (nchange++ == 0)) {
795                         sdinitpart(unit);
796                         continue;
797                 }
798
799                 /* other errors; give up */
800                 qunlock(&unit->ctl);
801                 kref_put(&sdev->r);
802                 nexterror();
803         }
804         pp = &unit->part[PART(c->qid)];
805         if (unit->vers + pp->vers != c->qid.vers)
806                 error(EIO, "disk changed");
807
808         /*
809          * Check the request is within bounds.
810          * Removeable drives are locked throughout the I/O
811          * in case the media changes unexpectedly.
812          * Non-removeable drives are not locked during the I/O
813          * to allow the hardware to optimise if it can; this is
814          * a little fast and loose.
815          * It's assumed that non-removeable media parameters
816          * (sectors, secsize) can't change once the drive has
817          * been brought online.
818          */
819         bno = (off / unit->secsize) + pp->start;
820         nb = ((off + len + unit->secsize - 1) / unit->secsize) + pp->start - bno;
821         max = SDmaxio / unit->secsize;
822         if (nb > max)
823                 nb = max;
824         if (bno + nb > pp->end)
825                 nb = pp->end - bno;
826         if (bno >= pp->end || nb == 0) {
827                 if (write)
828                         error(EIO, "bno(%d) >= pp->end(%d) or nb(%d) == 0", bno, pp->end,
829                               nb);
830                 qunlock(&unit->ctl);
831                 kref_put(&sdev->r);
832                 poperror();
833                 return 0;
834         }
835         if (!(unit->inquiry[1] & SDinq1removable)) {
836                 qunlock(&unit->ctl);
837                 poperror();
838         }
839
840         b = kzmalloc(nb * unit->secsize, MEM_WAIT);
841         if (b == NULL)
842                 error(ENOMEM, "%s: could not allocate %d bytes", nb * unit->secsize);
843         if (waserror()) {
844                 kfree(b);
845                 if (!(unit->inquiry[1] & SDinq1removable))
846                         kref_put(&sdev->r); /* gadverdamme! */
847                 nexterror();
848         }
849
850         offset = off % unit->secsize;
851         if (offset + len > nb * unit->secsize)
852                 len = nb * unit->secsize - offset;
853         if (write) {
854                 if (offset || (len % unit->secsize)) {
855                         l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
856                         if (l < 0)
857                                 error(EIO, "IO Error");
858                         if (l < (nb * unit->secsize)) {
859                                 nb = l / unit->secsize;
860                                 l = nb * unit->secsize - offset;
861                                 if (len > l)
862                                         len = l;
863                         }
864                 }
865                 memmove(b + offset, a, len);
866                 l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
867                 if (l < 0)
868                         error(EIO, "IO Error");
869                 if (l < offset)
870                         len = 0;
871                 else if (len > l - offset)
872                         len = l - offset;
873         } else {
874                 l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
875                 if (l < 0)
876                         error(EIO, "IO Error");
877                 if (l < offset)
878                         len = 0;
879                 else if (len > l - offset)
880                         len = l - offset;
881                 memmove(a, b + offset, len);
882         }
883         kfree(b);
884         poperror();
885
886         if (unit->inquiry[1] & SDinq1removable) {
887                 qunlock(&unit->ctl);
888                 poperror();
889         }
890
891         kref_put(&sdev->r);
892         return len;
893 }
894
895 static int32_t sdrio(struct sdreq *r, void *a, int32_t n)
896 {
897         ERRSTACK(2);
898         void *data;
899
900         if (n >= SDmaxio || n < 0)
901                 error(EINVAL, "%d is < 0 or > SDmaxio", n);
902
903         data = NULL;
904         if (n) {
905                 data = kzmalloc(n, MEM_WAIT);
906                 if (data == NULL)
907                         error(ENOMEM, "Alloc of %d bytes failed", n);
908                 if (r->write)
909                         memmove(data, a, n);
910         }
911         r->data = data;
912         r->dlen = n;
913
914         if (waserror()) {
915                 kfree(data);
916                 r->data = NULL;
917                 nexterror();
918         }
919
920         if (r->unit->dev->ifc->rio(r) != SDok)
921                 error(EIO, "IO Error");
922
923         if (!r->write && r->rlen > 0)
924                 memmove(a, data, r->rlen);
925         kfree(data);
926         r->data = NULL;
927         poperror();
928
929         return r->rlen;
930 }
931
932 /*
933  * SCSI simulation for non-SCSI devices
934  */
935 int sdsetsense(struct sdreq *r, int status, int key, int asc, int ascq)
936 {
937         int len;
938         struct sdunit *unit;
939
940         unit = r->unit;
941         unit->sense[2] = key;
942         unit->sense[12] = asc;
943         unit->sense[13] = ascq;
944
945         r->status = status;
946         if (status == SDcheck && !(r->flags & SDnosense)) {
947                 /* request sense case from sdfakescsi */
948                 len = sizeof unit->sense;
949                 if (len > sizeof(r->sense) - 1)
950                         len = sizeof(r->sense) - 1;
951                 memmove(r->sense, unit->sense, len);
952                 unit->sense[2] = 0;
953                 unit->sense[12] = 0;
954                 unit->sense[13] = 0;
955                 r->flags |= SDvalidsense;
956                 return SDok;
957         }
958         return status;
959 }
960
961 int sdmodesense(struct sdreq *r, uint8_t *cmd, void *info, int ilen)
962 {
963         int len;
964         uint8_t *data;
965
966         /*
967          * Fake a vendor-specific request with page code 0,
968          * return the drive info.
969          */
970         if ((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
971                 return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
972         len = (cmd[7] << 8) | cmd[8];
973         if (len == 0)
974                 return SDok;
975         if (len < 8 + ilen)
976                 return sdsetsense(r, SDcheck, 0x05, 0x1A, 0);
977         if (r->data == NULL || r->dlen < len)
978                 return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
979         data = r->data;
980         memset(data, 0, 8);
981         data[0] = ilen >> 8;
982         data[1] = ilen;
983         if (ilen)
984                 memmove(data + 8, info, ilen);
985         r->rlen = 8 + ilen;
986         return sdsetsense(r, SDok, 0, 0, 0);
987 }
988
989 int sdfakescsi(struct sdreq *r, void *info, int ilen)
990 {
991         uint8_t *cmd, *p;
992         uint64_t len;
993         struct sdunit *unit;
994
995         cmd = r->cmd;
996         r->rlen = 0;
997         unit = r->unit;
998
999         /*
1000          * Rewrite read(6)/write(6) into read(10)/write(10).
1001          */
1002         switch (cmd[0]) {
1003         case 0x08: /* read */
1004         case 0x0A: /* write */
1005                 cmd[9] = 0;
1006                 cmd[8] = cmd[4];
1007                 cmd[7] = 0;
1008                 cmd[6] = 0;
1009                 cmd[5] = cmd[3];
1010                 cmd[4] = cmd[2];
1011                 cmd[3] = cmd[1] & 0x0F;
1012                 cmd[2] = 0;
1013                 cmd[1] &= 0xE0;
1014                 cmd[0] |= 0x20;
1015                 break;
1016         }
1017
1018         /*
1019          * Map SCSI commands into ATA commands for discs.
1020          * Fail any command with a LUN except INQUIRY which
1021          * will return 'logical unit not supported'.
1022          */
1023         if ((cmd[1] >> 5) && cmd[0] != 0x12)
1024                 return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
1025
1026         switch (cmd[0]) {
1027         default:
1028                 return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
1029
1030         case 0x00: /* test unit ready */
1031                 return sdsetsense(r, SDok, 0, 0, 0);
1032
1033         case 0x03: /* request sense */
1034                 if (cmd[4] < sizeof unit->sense)
1035                         len = cmd[4];
1036                 else
1037                         len = sizeof unit->sense;
1038                 if (r->data && r->dlen >= len) {
1039                         memmove(r->data, unit->sense, len);
1040                         r->rlen = len;
1041                 }
1042                 return sdsetsense(r, SDok, 0, 0, 0);
1043
1044         case 0x12: /* inquiry */
1045                 if (cmd[4] < sizeof unit->inquiry)
1046                         len = cmd[4];
1047                 else
1048                         len = sizeof unit->inquiry;
1049                 if (r->data && r->dlen >= len) {
1050                         memmove(r->data, unit->inquiry, len);
1051                         r->rlen = len;
1052                 }
1053                 return sdsetsense(r, SDok, 0, 0, 0);
1054
1055         case 0x1B: /* start/stop unit */
1056                 /*
1057                  * nop for now, can use power management later.
1058                  */
1059                 return sdsetsense(r, SDok, 0, 0, 0);
1060
1061         case 0x25: /* read capacity */
1062                 if ((cmd[1] & 0x01) || cmd[2] || cmd[3])
1063                         return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1064                 if (r->data == NULL || r->dlen < 8)
1065                         return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1066
1067                 /*
1068                  * Read capacity returns the LBA of the last sector.
1069                  */
1070                 len = unit->sectors - 1;
1071                 p = r->data;
1072                 *p++ = len >> 24;
1073                 *p++ = len >> 16;
1074                 *p++ = len >> 8;
1075                 *p++ = len;
1076                 len = 512;
1077                 *p++ = len >> 24;
1078                 *p++ = len >> 16;
1079                 *p++ = len >> 8;
1080                 *p++ = len;
1081                 r->rlen = p - (uint8_t *)r->data;
1082                 return sdsetsense(r, SDok, 0, 0, 0);
1083
1084         case 0x9E: /* long read capacity */
1085                 if ((cmd[1] & 0x01) || cmd[2] || cmd[3])
1086                         return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
1087                 if (r->data == NULL || r->dlen < 8)
1088                         return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
1089                 /*
1090                  * Read capcity returns the LBA of the last sector.
1091                  */
1092                 len = unit->sectors - 1;
1093                 p = r->data;
1094                 *p++ = len >> 56;
1095                 *p++ = len >> 48;
1096                 *p++ = len >> 40;
1097                 *p++ = len >> 32;
1098                 *p++ = len >> 24;
1099                 *p++ = len >> 16;
1100                 *p++ = len >> 8;
1101                 *p++ = len;
1102                 len = 512;
1103                 *p++ = len >> 24;
1104                 *p++ = len >> 16;
1105                 *p++ = len >> 8;
1106                 *p++ = len;
1107                 r->rlen = p - (uint8_t *)r->data;
1108                 return sdsetsense(r, SDok, 0, 0, 0);
1109
1110         case 0x5A: /* mode sense */
1111                 return sdmodesense(r, cmd, info, ilen);
1112
1113         case 0x28: /* read */
1114         case 0x2A: /* write */
1115         case 0x88: /* read16 */
1116         case 0x8a: /* write16 */
1117                 return SDnostatus;
1118         }
1119 }
1120
1121 static long sdread(struct chan *c, void *a, long n, int64_t off)
1122 {
1123         ERRSTACK(2);
1124         char *p, *e, *buf;
1125         struct sdpart *pp;
1126         struct sdunit *unit;
1127         struct sdev *sdev;
1128         int32_t offset;
1129         int i, l, mm, status;
1130
1131         offset = off;
1132         switch (TYPE(c->qid)) {
1133         default:
1134                 error(EPERM, "Permission denied");
1135         case Qtopctl:
1136                 mm = 64 * 1024; /* room for register dumps */
1137                 p = buf = kzmalloc(mm, 0);
1138                 if (p == NULL)
1139                         error(ENOMEM, "Alloc of %d bytes failed", mm);
1140                 e = p + mm;
1141                 qlock(&devslock);
1142                 for (i = 0; i < ARRAY_SIZE(devs); i++) {
1143                         sdev = devs[i];
1144                         if (sdev && sdev->ifc->rtopctl)
1145                                 p = sdev->ifc->rtopctl(sdev, p, e);
1146                 }
1147                 qunlock(&devslock);
1148                 n = readstr(offset, a, n, buf);
1149                 kfree(buf);
1150                 return n;
1151
1152         case Qtopdir:
1153         case Qunitdir:
1154                 return devdirread(c, a, n, 0, 0, sdgen);
1155
1156         case Qctl:
1157                 sdev = sdgetdev(DEV(c->qid));
1158                 if (sdev == NULL)
1159                         error(ENOENT, "No such device");
1160
1161                 unit = sdev->unit[UNIT(c->qid)];
1162                 mm = 16 * 1024; /* room for register dumps */
1163                 p = kzmalloc(mm, 0);
1164                 if (p == NULL)
1165                         error(ENOMEM, "Alloc of %d bytes failed", mm);
1166                 l = snprintf(p, mm, "inquiry %.48s\n", (char *)unit->inquiry + 8);
1167                 qlock(&unit->ctl);
1168                 /*
1169                  * If there's a device specific routine it must
1170                  * provide all information pertaining to night geometry
1171                  * and the garscadden trains.
1172                  */
1173                 if (unit->dev->ifc->rctl)
1174                         l += unit->dev->ifc->rctl(unit, p + l, mm - l);
1175                 if (unit->sectors == 0)
1176                         sdinitpart(unit);
1177                 if (unit->sectors) {
1178                         if (unit->dev->ifc->rctl == NULL)
1179                                 l += snprintf(p + l, mm - l, "geometry %llu %lu\n",
1180                                               unit->sectors, unit->secsize);
1181                         pp = unit->part;
1182                         for (i = 0; i < unit->npart; i++) {
1183                                 if (pp->valid)
1184                                         l += snprintf(p + l, mm - l, "part %s %llu %llu\n",
1185                                                       pp->sdperm.name, pp->start, pp->end);
1186                                 pp++;
1187                         }
1188                 }
1189                 qunlock(&unit->ctl);
1190                 kref_put(&sdev->r);
1191                 l = readstr(offset, a, n, p);
1192                 kfree(p);
1193                 return l;
1194
1195         case Qraw:
1196                 sdev = sdgetdev(DEV(c->qid));
1197                 if (sdev == NULL)
1198                         error(ENOENT, "No such file or directory");
1199
1200                 unit = sdev->unit[UNIT(c->qid)];
1201                 qlock(&unit->raw);
1202                 if (waserror()) {
1203                         qunlock(&unit->raw);
1204                         kref_put(&sdev->r);
1205                         nexterror();
1206                 }
1207                 if (unit->state == Rawdata) {
1208                         unit->state = Rawstatus;
1209                         i = sdrio(unit->req, a, n);
1210                 } else if (unit->state == Rawstatus) {
1211                         status = unit->req->status;
1212                         unit->state = Rawcmd;
1213                         kfree(unit->req);
1214                         unit->req = NULL;
1215                         i = readnum(0, a, n, status, NUMSIZE);
1216                 } else
1217                         i = 0;
1218                 qunlock(&unit->raw);
1219                 kref_put(&sdev->r);
1220                 poperror();
1221                 return i;
1222
1223         case Qpart:
1224                 return sdbio(c, 0, a, n, off);
1225         }
1226 }
1227
1228 static void legacytopctl(struct cmdbuf *);
1229
1230 static long sdwrite(struct chan *c, void *a, long n, int64_t off)
1231 {
1232         ERRSTACK(2);
1233         char *f0;
1234         int i;
1235         uint64_t end, start;
1236         struct cmdbuf *cb;
1237         struct sdifc *ifc;
1238         struct sdreq *req;
1239         struct sdunit *unit;
1240         struct sdev *sdev;
1241
1242         switch (TYPE(c->qid)) {
1243         default:
1244                 error(EPERM, "Permission denied");
1245         case Qtopctl:
1246                 cb = parsecmd(a, n);
1247                 if (waserror()) {
1248                         kfree(cb);
1249                         nexterror();
1250                 }
1251                 if (cb->nf == 0)
1252                         error(EINVAL, "empty control message");
1253                 f0 = cb->f[0];
1254                 cb->f++;
1255                 cb->nf--;
1256                 if (strcmp(f0, "config") == 0) {
1257                         /* wormhole into ugly legacy interface */
1258                         legacytopctl(cb);
1259                         poperror();
1260                         kfree(cb);
1261                         break;
1262                 }
1263                 /*
1264                  * "ata arg..." invokes sdifc[i]->wtopctl(NULL, cb),
1265                  * where sdifc[i]->sdperm.name=="ata" and cb contains the args.
1266                  */
1267                 ifc = NULL;
1268                 sdev = NULL;
1269                 for (i = 0; sdifc[i]; i++) {
1270                         if (strcmp(sdifc[i]->name, f0) == 0) {
1271                                 ifc = sdifc[i];
1272                                 sdev = NULL;
1273                                 goto subtopctl;
1274                         }
1275                 }
1276                 /*
1277                  * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
1278                  * where sdifc[i] and sdev match controller letter "1",
1279                  * and cb contains the args.
1280                  */
1281                 if (f0[0] == 's' && f0[1] == 'd' && f0[2] && f0[3] == 0) {
1282                         sdev = sdgetdev(f0[2]);
1283                         if (sdev != NULL) {
1284                                 ifc = sdev->ifc;
1285                                 goto subtopctl;
1286                         }
1287                 }
1288                 error(EINVAL, "unknown interface");
1289
1290         subtopctl:
1291                 if (waserror()) {
1292                         if (sdev)
1293                                 kref_put(&sdev->r);
1294                         nexterror();
1295                 }
1296                 if (ifc->wtopctl)
1297                         ifc->wtopctl(sdev, cb);
1298                 else
1299                         error(EINVAL, "Bad control");
1300                 poperror();
1301                 poperror();
1302                 if (sdev)
1303                         kref_put(&sdev->r);
1304                 kfree(cb);
1305                 break;
1306
1307         case Qctl:
1308                 cb = parsecmd(a, n);
1309                 sdev = sdgetdev(DEV(c->qid));
1310                 if (sdev == NULL)
1311                         error(ENOENT, "No such file or directory");
1312                 unit = sdev->unit[UNIT(c->qid)];
1313
1314                 qlock(&unit->ctl);
1315                 if (waserror()) {
1316                         qunlock(&unit->ctl);
1317                         kref_put(&sdev->r);
1318                         kfree(cb);
1319                         nexterror();
1320                 }
1321                 if (unit->vers != c->qid.vers)
1322                         error(EIO, "Unit changed");
1323
1324                 if (cb->nf < 1)
1325                         error(EINVAL, "%s requires at least one argument", cb->f[0]);
1326                 if (strcmp(cb->f[0], "part") == 0) {
1327                         if (cb->nf != 4)
1328                                 error(EINVAL, "Part got %d arguments, requires 4", cb->nf);
1329                         if (unit->sectors == 0)
1330                                 error(EINVAL, "unit->sectors was 0");
1331                         if (!sdinitpart(unit))
1332                                 error(EIO, "sdinitpart failed");
1333                         start = strtoul(cb->f[2], 0, 0);
1334                         end = strtoul(cb->f[3], 0, 0);
1335                         sdaddpart(unit, cb->f[1], start, end);
1336                 } else if (strcmp(cb->f[0], "delpart") == 0) {
1337                         if (cb->nf != 2)
1338                                 error(EINVAL, "delpart got %d args, 2 required");
1339                         if (unit->part == NULL)
1340                                 error(EIO, "partition was NULL");
1341                         sddelpart(unit, cb->f[1]);
1342                 } else if (unit->dev->ifc->wctl)
1343                         unit->dev->ifc->wctl(unit, cb);
1344                 else
1345                         error(EINVAL, "Bad control %s", cb->f[0]);
1346                 qunlock(&unit->ctl);
1347                 kref_put(&sdev->r);
1348                 poperror();
1349                 kfree(cb);
1350                 break;
1351
1352         case Qraw:
1353                 sdev = sdgetdev(DEV(c->qid));
1354                 if (sdev == NULL)
1355                         error(ENOENT, "No such file or directory");
1356                 unit = sdev->unit[UNIT(c->qid)];
1357                 qlock(&unit->raw);
1358                 if (waserror()) {
1359                         qunlock(&unit->raw);
1360                         kref_put(&sdev->r);
1361                         nexterror();
1362                 }
1363                 switch (unit->state) {
1364                 case Rawcmd:
1365                         if (n < 6 || n > sizeof(req->cmd))
1366                                 error(EINVAL, "%d is < 6 or > %d", n, sizeof(req->cmd));
1367                         req = kzmalloc(sizeof(struct sdreq), 0);
1368                         if (req == NULL)
1369                                 error(ENOMEM, "Can't allocate an sdreq");
1370                         req->unit = unit;
1371                         memmove(req->cmd, a, n);
1372                         req->clen = n;
1373                         req->flags = SDnosense;
1374                         req->status = ~0;
1375
1376                         unit->req = req;
1377                         unit->state = Rawdata;
1378                         break;
1379
1380                 case Rawstatus:
1381                         unit->state = Rawcmd;
1382                         kfree(unit->req);
1383                         unit->req = NULL;
1384                         error(EINVAL, "Bad use of rawstatus");
1385
1386                 case Rawdata:
1387                         unit->state = Rawstatus;
1388                         unit->req->write = 1;
1389                         n = sdrio(unit->req, a, n);
1390                 }
1391                 qunlock(&unit->raw);
1392                 kref_put(&sdev->r);
1393                 poperror();
1394                 break;
1395         case Qpart:
1396                 return sdbio(c, 1, a, n, off);
1397         }
1398
1399         return n;
1400 }
1401
1402 static int32_t sdwstat(struct chan *c, uint8_t *dp, int32_t n)
1403 {
1404         ERRSTACK(2);
1405         struct dir *d;
1406         struct sdpart *pp;
1407         struct sdperm *perm;
1408         struct sdunit *unit;
1409         struct sdev *sdev;
1410
1411         if (c->qid.type & QTDIR)
1412                 error(EPERM, "Not a directory");
1413
1414         sdev = sdgetdev(DEV(c->qid));
1415         if (sdev == NULL)
1416                 error(ENOENT, "No such file or device");
1417         unit = sdev->unit[UNIT(c->qid)];
1418         qlock(&unit->ctl);
1419         d = NULL;
1420         if (waserror()) {
1421                 kfree(d);
1422                 qunlock(&unit->ctl);
1423                 kref_put(&sdev->r);
1424                 nexterror();
1425         }
1426
1427         switch (TYPE(c->qid)) {
1428         default:
1429                 error(EPERM, "Permission denied");
1430         case Qctl:
1431                 perm = &unit->ctlperm;
1432                 break;
1433         case Qraw:
1434                 perm = &unit->rawperm;
1435                 break;
1436         case Qpart:
1437                 pp = &unit->part[PART(c->qid)];
1438                 if (unit->vers + pp->vers != c->qid.vers)
1439                         error(ENOENT, "No such file or directory");
1440                 perm = &pp->sdperm;
1441                 break;
1442         }
1443
1444         /* TODO: Implement permissions checking and raise errors as appropriate. */
1445         // if (strcmp(up->user, perm->user) && !iseve())
1446                 // error(Eperm);
1447
1448         d = kzmalloc(sizeof(struct dir) + n, 0);
1449         n = convM2D(dp, n, &d[0], (char *)&d[1]);
1450         if (n == 0)
1451                 error(EIO, "Short status");
1452         if (!emptystr(d[0].uid))
1453                 kstrdup(&perm->user, d[0].uid);
1454         if (d[0].mode != (uint32_t)~0UL)
1455                 perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
1456
1457         kfree(d);
1458         qunlock(&unit->ctl);
1459         kref_put(&sdev->r);
1460         poperror();
1461         return n;
1462 }
1463
1464 static int configure(char *spec, struct devconf *cf)
1465 {
1466         struct sdev *s, *sdev;
1467         char *p;
1468         int i;
1469
1470         if (sdindex(*spec) < 0)
1471                 error(EINVAL, "bad sd spec '%s'", spec);
1472
1473         p = strchr(cf->type, '/');
1474         if (p != NULL)
1475                 *p++ = '\0';
1476
1477         for (i = 0; sdifc[i] != NULL; i++)
1478                 if (strcmp(sdifc[i]->name, cf->type) == 0)
1479                         break;
1480         if (sdifc[i] == NULL)
1481                 error(ENOENT, "sd type not found");
1482         if (p)
1483                 *(p - 1) = '/';
1484
1485         if (sdifc[i]->probe == NULL)
1486                 error(EIO, "sd type cannot probe");
1487
1488         sdev = sdifc[i]->probe(cf);
1489         for (s = sdev; s; s = s->next)
1490                 s->idno = *spec;
1491         sdadddevs(sdev);
1492         return 0;
1493 }
1494
1495 static int unconfigure(char *spec)
1496 {
1497         int i;
1498         struct sdev *sdev;
1499         struct sdunit *unit;
1500
1501         if ((i = sdindex(*spec)) < 0)
1502                 error(ENOENT, "No such file or directory '%s'", spec);
1503
1504         qlock(&devslock);
1505         sdev = devs[i];
1506         if (sdev == NULL) {
1507                 qunlock(&devslock);
1508                 error(ENOENT, "No such file or directory at index %d", i);
1509         }
1510         if (kref_refcnt(&sdev->r)) {
1511                 qunlock(&devslock);
1512                 error(EBUSY, "%s is busy", spec);
1513         }
1514         devs[i] = NULL;
1515         qunlock(&devslock);
1516
1517         /* make sure no interrupts arrive anymore before removing resources */
1518         if (sdev->enabled && sdev->ifc->disable)
1519                 sdev->ifc->disable(sdev);
1520
1521         for (i = 0; i != sdev->nunit; i++) {
1522                 unit = sdev->unit[i];
1523                 if (unit) {
1524                         kfree(unit->sdperm.name);
1525                         kfree(unit->sdperm.user);
1526                         kfree(unit);
1527                 }
1528         }
1529
1530         if (sdev->ifc->clear)
1531                 sdev->ifc->clear(sdev);
1532         kfree(sdev);
1533         return 0;
1534 }
1535
1536 static int sdconfig(int on, char *spec, struct devconf *cf)
1537 {
1538         if (on)
1539                 return configure(spec, cf);
1540         return unconfigure(spec);
1541 }
1542
1543 struct dev sddevtab __devtab = {
1544     .name = "sd",
1545
1546     .reset = sdreset,
1547     .init = devinit,
1548     .shutdown = devshutdown,
1549     .attach = sdattach,
1550     .walk = sdwalk,
1551     .stat = sdstat,
1552     .open = sdopen,
1553     .create = devcreate,
1554     .close = sdclose,
1555     .read = sdread,
1556     .bread = devbread,
1557     .write = sdwrite,
1558     .bwrite = devbwrite,
1559     .remove = devremove,
1560     .wstat = sdwstat,
1561     .power = devpower,
1562 };
1563
1564 /*
1565  * This is wrong for so many reasons.  This code must go.
1566  */
1567 struct confdata {
1568         int on;
1569         char *spec;
1570         struct devconf cf;
1571 };
1572
1573 static void parseswitch(struct confdata *cd, char *option)
1574 {
1575         if (!strcmp("on", option))
1576                 cd->on = 1;
1577         else if (!strcmp("off", option))
1578                 cd->on = 0;
1579         else
1580                 error(EINVAL, "Got %s, must be on or off", option);
1581 }
1582
1583 static void parsespec(struct confdata *cd, char *option)
1584 {
1585         if (strlen(option) > 1)
1586                 error(EINVAL, "spec is %d bytes, must be 1", strlen(option));
1587         cd->spec = option;
1588 }
1589
1590 static struct devport *getnewport(struct devconf *dc)
1591 {
1592         struct devport *p;
1593
1594         p = (struct devport *)kzmalloc((dc->nports + 1) * sizeof(struct devport),
1595                                        0);
1596         if (p == NULL)
1597                 error(ENOMEM, "Can't allocate %d bytes for %d ports", dc->nports,
1598                       (dc->nports + 1) * sizeof(struct devport));
1599         if (dc->nports > 0) {
1600                 memmove(p, dc->ports, dc->nports * sizeof(struct devport));
1601                 kfree(dc->ports);
1602         }
1603         dc->ports = p;
1604         p = &dc->ports[dc->nports++];
1605         p->size = -1;
1606         p->port = (uint32_t)-1;
1607         return p;
1608 }
1609
1610 static void parseport(struct confdata *cd, char *option)
1611 {
1612         char *e;
1613         struct devport *p;
1614
1615         if ((cd->cf.nports == 0) ||
1616             (cd->cf.ports[cd->cf.nports - 1].port != (uint32_t)-1))
1617                 p = getnewport(&cd->cf);
1618         else
1619                 p = &cd->cf.ports[cd->cf.nports - 1];
1620         p->port = strtol(option, &e, 0);
1621         if (e == NULL || *e != '\0')
1622                 error(EINVAL, "option %s is not a number", option);
1623 }
1624
1625 static void parsesize(struct confdata *cd, char *option)
1626 {
1627         char *e;
1628         struct devport *p;
1629
1630         if (cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports - 1].size != -1)
1631                 p = getnewport(&cd->cf);
1632         else
1633                 p = &cd->cf.ports[cd->cf.nports - 1];
1634         p->size = (int)strtol(option, &e, 0);
1635         if (e == NULL || *e != '\0')
1636                 error(EINVAL, "%s is not a number", option);
1637 }
1638
1639 static void parseirq(struct confdata *cd, char *option)
1640 {
1641         char *e;
1642
1643         cd->cf.intnum = strtoul(option, &e, 0);
1644         if (e == NULL || *e != '\0')
1645                 error(EINVAL, "%s is not a number", option);
1646 }
1647
1648 static void parsetype(struct confdata *cd, char *option)
1649 {
1650         cd->cf.type = option;
1651 }
1652
1653 static struct {
1654         char *name;
1655         void (*parse)(struct confdata *, char *unused_char_p_t);
1656 } options[] = {
1657     {"switch", parseswitch},
1658     {"spec", parsespec},
1659     {"port", parseport},
1660     {"size", parsesize},
1661     {"irq", parseirq},
1662     {"type", parsetype},
1663 };
1664
1665 static void legacytopctl(struct cmdbuf *cb)
1666 {
1667         char *opt;
1668         int i, j;
1669         struct confdata cd;
1670
1671         memset(&cd, 0, sizeof(cd));
1672         cd.on = -1;
1673         for (i = 0; i < cb->nf; i += 2) {
1674                 if (i + 2 > cb->nf)
1675                         error(EINVAL, "FIX ME. I don't know what this means");
1676                 opt = cb->f[i];
1677                 for (j = 0; j < ARRAY_SIZE(options); j++)
1678                         if (strcmp(opt, options[j].name) == 0) {
1679                                 options[j].parse(&cd, cb->f[i + 1]);
1680                                 break;
1681                         }
1682                 if (j == ARRAY_SIZE(options))
1683                         error(EINVAL, "FIX ME");
1684         }
1685         /* this has been rewritten to accommodate sdaoe */
1686         if (cd.on < 0 || cd.spec == 0)
1687                 error(EINVAL, "cd.on(%d) < 0 or cd.spec == 0", cd.on);
1688         if (cd.on && cd.cf.type == NULL)
1689                 error(EINVAL, "cd.on non-zero and cd.cf.type == NULL");
1690         sdconfig(cd.on, cd.spec, &cd.cf);
1691 }