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