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