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