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