sdaoe.c (9903B)
1 /* 2 * aoe sd driver, copyright © 2007 coraid 3 */ 4 5 #include "u.h" 6 #include "lib.h" 7 #include "mem.h" 8 #include "dat.h" 9 #include "fns.h" 10 #include "io.h" 11 #include "error.h" 12 #include "sd.h" 13 #include "netif.h" 14 #include "aoe.h" 15 16 extern char Echange[]; 17 extern char Enotup[]; 18 19 #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__); 20 21 enum { 22 Nctlr = 32, 23 Maxpath = 128, 24 }; 25 26 enum { 27 /* sync with ahci.h */ 28 Dllba = 1<<0, 29 Dsmart = 1<<1, 30 Dpower = 1<<2, 31 Dnop = 1<<3, 32 Datapi = 1<<4, 33 Datapi16= 1<<5, 34 }; 35 36 static char *flagname[] = { 37 "llba", 38 "smart", 39 "power", 40 "nop", 41 "atapi", 42 "atapi16", 43 }; 44 45 typedef struct Ctlr Ctlr; 46 struct Ctlr{ 47 QLock qlock; 48 49 Ctlr *next; 50 SDunit *unit; 51 52 char path[Maxpath]; 53 Chan *c; 54 55 ulong vers; 56 uchar mediachange; 57 uchar flag; 58 uchar smart; 59 uchar smartrs; 60 uchar feat; 61 62 uvlong sectors; 63 char serial[20+1]; 64 char firmware[8+1]; 65 char model[40+1]; 66 char ident[0x100]; 67 }; 68 69 static Lock ctlrlock; 70 static Ctlr *head; 71 static Ctlr *tail; 72 73 SDifc sdaoeifc; 74 75 static void 76 idmove(char *p, ushort *a, int n) 77 { 78 int i; 79 char *op, *e; 80 81 op = p; 82 for(i = 0; i < n/2; i++){ 83 *p++ = a[i] >> 8; 84 *p++ = a[i]; 85 } 86 *p = 0; 87 while(p > op && *--p == ' ') 88 *p = 0; 89 e = p; 90 p = op; 91 while(*p == ' ') 92 p++; 93 memmove(op, p, n - (e - p)); 94 } 95 96 static ushort 97 gbit16(void *a) 98 { 99 uchar *i; 100 101 i = a; 102 return i[1] << 8 | i[0]; 103 } 104 105 static ulong 106 gbit32(void *a) 107 { 108 ulong j; 109 uchar *i; 110 111 i = a; 112 j = i[3] << 24; 113 j |= i[2] << 16; 114 j |= i[1] << 8; 115 j |= i[0]; 116 return j; 117 } 118 119 static uvlong 120 gbit64(void *a) 121 { 122 uchar *i; 123 124 i = a; 125 return (uvlong)gbit32(i+4)<<32 | gbit32(i); 126 } 127 128 static int 129 identify(Ctlr *c, ushort *id) 130 { 131 int i; 132 uchar oserial[21]; 133 uvlong osectors, s; 134 135 osectors = c->sectors; 136 memmove(oserial, c->serial, sizeof c->serial); 137 138 c->feat &= ~(Dllba|Dpower|Dsmart|Dnop); 139 i = gbit16(id+83) | gbit16(id+86); 140 if(i & (1<<10)){ 141 c->feat |= Dllba; 142 s = gbit64(id+100); 143 }else 144 s = gbit32(id+60); 145 146 i = gbit16(id+83); 147 if((i>>14) == 1) { 148 if(i & (1<<3)) 149 c->feat |= Dpower; 150 i = gbit16(id+82); 151 if(i & 1) 152 c->feat |= Dsmart; 153 if(i & (1<<14)) 154 c->feat |= Dnop; 155 } 156 157 idmove(c->serial, id+10, 20); 158 idmove(c->firmware, id+23, 8); 159 idmove(c->model, id+27, 40); 160 161 if((osectors == 0 || osectors != s) && 162 memcmp(oserial, c->serial, sizeof oserial) != 0){ 163 c->sectors = s; 164 c->mediachange = 1; 165 c->vers++; 166 } 167 return 0; 168 } 169 170 /* must call with d qlocked */ 171 static int 172 aoeidentify(Ctlr *d, SDunit *u) 173 { 174 Chan *c; 175 176 c = nil; 177 if(waserror()){ 178 if(c) 179 cclose(c); 180 iprint("aoeidentify: %s\n", up->errstr); 181 nexterror(); 182 } 183 184 uprint("%s/ident", d->path); 185 c = namec(up->genbuf, Aopen, OREAD, 0); 186 devtab[c->type]->read(c, d->ident, sizeof d->ident, 0); 187 188 poperror(); 189 cclose(c); 190 191 d->feat = 0; 192 d->smart = 0; 193 identify(d, (ushort*)d->ident); 194 195 memset(u->inquiry, 0, sizeof u->inquiry); 196 u->inquiry[2] = 2; 197 u->inquiry[3] = 2; 198 u->inquiry[4] = sizeof u->inquiry - 4; 199 memmove(u->inquiry+8, d->model, 40); 200 201 return 0; 202 } 203 204 static Ctlr* 205 ctlrlookup(char *path) 206 { 207 Ctlr *c; 208 209 lock(&ctlrlock); 210 for(c = head; c; c = c->next) 211 if(strcmp(c->path, path) == 0) 212 break; 213 unlock(&ctlrlock); 214 return c; 215 } 216 217 static Ctlr* 218 newctlr(char *path) 219 { 220 Ctlr *c; 221 222 /* race? */ 223 if(ctlrlookup(path)) 224 error(Eexist); 225 226 if((c = malloc(sizeof *c)) == nil) 227 return 0; 228 kstrcpy(c->path, path, sizeof c->path); 229 lock(&ctlrlock); 230 if(head != nil) 231 tail->next = c; 232 else 233 head = c; 234 tail = c; 235 unlock(&ctlrlock); 236 return c; 237 } 238 239 static void 240 delctlr(Ctlr *c) 241 { 242 Ctlr *x, *prev; 243 244 lock(&ctlrlock); 245 246 for(prev = 0, x = head; x; prev = x, x = c->next) 247 if(strcmp(c->path, x->path) == 0) 248 break; 249 if(x == 0){ 250 unlock(&ctlrlock); 251 error(Enonexist); 252 } 253 254 if(prev) 255 prev->next = x->next; 256 else 257 head = x->next; 258 if(x->next == nil) 259 tail = prev; 260 unlock(&ctlrlock); 261 262 if(x->c) 263 cclose(x->c); 264 free(x); 265 } 266 267 static SDev* 268 aoeprobe(char *path, SDev *s) 269 { 270 int n, i; 271 char *p; 272 Chan *c; 273 Ctlr *ctlr; 274 275 if((p = strrchr(path, '/')) == 0) 276 error(Ebadarg); 277 *p = 0; 278 uprint("%s/ctl", path); 279 *p = '/'; 280 281 c = namec(up->genbuf, Aopen, OWRITE, 0); 282 if(waserror()) { 283 cclose(c); 284 nexterror(); 285 } 286 n = uprint("discover %s", p+1); 287 devtab[c->type]->write(c, up->genbuf, n, 0); 288 poperror(); 289 cclose(c); 290 291 for(i = 0;; i += 200){ 292 if(i > 8000 || waserror()) 293 error(Etimedout); 294 tsleep(&up->sleep, return0, 0, 200); 295 poperror(); 296 297 uprint("%s/ident", path); 298 if(waserror()) 299 continue; 300 c = namec(up->genbuf, Aopen, OREAD, 0); 301 poperror(); 302 cclose(c); 303 304 ctlr = newctlr(path); 305 break; 306 } 307 308 if(s == nil && (s = malloc(sizeof *s)) == nil) 309 return nil; 310 s->ctlr = ctlr; 311 s->ifc = &sdaoeifc; 312 s->nunit = 1; 313 return s; 314 } 315 316 static char *probef[32]; 317 static int nprobe; 318 319 static int 320 pnpprobeid(char *s) 321 { 322 int id; 323 324 if(strlen(s) < 2) 325 return 0; 326 id = 'e'; 327 if(s[1] == '!') 328 id = s[0]; 329 return id; 330 } 331 332 static SDev* 333 aoepnp(void) 334 { 335 int i, id; 336 char *p; 337 SDev *h, *t, *s; 338 339 // if((p = getconf("aoedev")) == 0) 340 if(1) 341 return 0; 342 nprobe = tokenize(p, probef, nelem(probef)); 343 h = t = 0; 344 for(i = 0; i < nprobe; i++){ 345 id = pnpprobeid(probef[i]); 346 if(id == 0) 347 continue; 348 s = malloc(sizeof *s); 349 if(s == nil) 350 break; 351 s->ctlr = 0; 352 s->idno = id; 353 s->ifc = &sdaoeifc; 354 s->nunit = 1; 355 356 if(h) 357 t->next = s; 358 else 359 h = s; 360 t = s; 361 } 362 return h; 363 } 364 365 static Ctlr* 366 pnpprobe(SDev *sd) 367 { 368 int j; 369 char *p; 370 static int i; 371 372 if(i > nprobe) 373 return 0; 374 p = probef[i++]; 375 if(strlen(p) < 2) 376 return 0; 377 if(p[1] == '!') 378 p += 2; 379 380 for(j = 0;; j += 200){ 381 if(j > 8000){ 382 print("#æ: pnpprobe: %s: %s\n", probef[i-1], up->errstr); 383 return 0; 384 } 385 if(waserror()){ 386 tsleep(&up->sleep, return0, 0, 200); 387 continue; 388 } 389 sd = aoeprobe(p, sd); 390 poperror(); 391 break; 392 } 393 print("#æ: pnpprobe establishes %sin %dms\n", probef[i-1], j); 394 return sd->ctlr; 395 } 396 397 398 static int 399 aoeverify(SDunit *u) 400 { 401 SDev *s; 402 Ctlr *c; 403 404 s = u->dev; 405 c = s->ctlr; 406 if(c == nil && (s->ctlr = c = pnpprobe(s)) == nil) 407 return 0; 408 c->mediachange = 1; 409 return 1; 410 } 411 412 static int 413 aoeconnect(SDunit *u, Ctlr *c) 414 { 415 QLOCK(c); 416 if(waserror()){ 417 QUNLOCK(c); 418 return -1; 419 } 420 421 aoeidentify(u->dev->ctlr, u); 422 if(c->c) 423 cclose(c->c); 424 c->c = 0; 425 uprint("%s/data", c->path); 426 c->c = namec(up->genbuf, Aopen, ORDWR, 0); 427 QUNLOCK(c); 428 poperror(); 429 430 return 0; 431 } 432 433 static int 434 aoeonline(SDunit *u) 435 { 436 Ctlr *c; 437 int r; 438 439 c = u->dev->ctlr; 440 r = 0; 441 442 if((c->feat&Datapi) && c->mediachange){ 443 if(aoeconnect(u, c) == 0 && (r = scsionline(u)) > 0) 444 c->mediachange = 0; 445 return r; 446 } 447 448 if(c->mediachange){ 449 if(aoeconnect(u, c) == -1) 450 return 0; 451 r = 2; 452 c->mediachange = 0; 453 u->sectors = c->sectors; 454 u->secsize = Aoesectsz; 455 } else 456 r = 1; 457 458 return r; 459 } 460 461 static int 462 aoerio(SDreq *r) 463 { 464 int i, count; 465 uvlong lba; 466 char *name; 467 uchar *cmd; 468 long (*rio)(Chan*, void*, long, vlong); 469 Ctlr *c; 470 SDunit *unit; 471 472 unit = r->unit; 473 c = unit->dev->ctlr; 474 // if(c->feat & Datapi) 475 // return aoeriopkt(r, d); 476 477 cmd = r->cmd; 478 name = unit->perm.name; 479 480 if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ 481 // QLOCK(c); 482 // i = flushcache(); 483 // QUNLOCK(c); 484 // if(i == 0) 485 // return sdsetsense(r, SDok, 0, 0, 0); 486 return sdsetsense(r, SDcheck, 3, 0xc, 2); 487 } 488 489 if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){ 490 r->status = i; 491 return i; 492 } 493 494 switch(*cmd){ 495 case 0x88: 496 case 0x28: 497 rio = devtab[c->c->type]->read; 498 break; 499 case 0x8a: 500 case 0x2a: 501 rio = devtab[c->c->type]->write; 502 break; 503 default: 504 print("%s: bad cmd %#.2ux\n", name, cmd[0]); 505 r->status = SDcheck; 506 return SDcheck; 507 } 508 509 if(r->data == nil) 510 return SDok; 511 512 if(r->clen == 16){ 513 if(cmd[2] || cmd[3]) 514 return sdsetsense(r, SDcheck, 3, 0xc, 2); 515 lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32; 516 lba |= cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9]; 517 count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13]; 518 }else{ 519 lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; 520 count = cmd[7]<<8 | cmd[8]; 521 } 522 523 count *= Aoesectsz; 524 525 if(r->dlen < count) 526 count = r->dlen & ~0x1ff; 527 528 if(waserror()){ 529 if(strcmp(up->errstr, Echange) == 0 || 530 strcmp(up->errstr, Enotup) == 0) 531 unit->sectors = 0; 532 nexterror(); 533 } 534 r->rlen = rio(c->c, r->data, count, Aoesectsz * lba); 535 poperror(); 536 r->status = SDok; 537 return SDok; 538 } 539 540 static char *smarttab[] = { 541 "unset", 542 "error", 543 "threshold exceeded", 544 "normal" 545 }; 546 547 static char * 548 pflag(char *s, char *e, uchar f) 549 { 550 uchar i, m; 551 552 for(i = 0; i < 8; i++){ 553 m = 1 << i; 554 if(f & m) 555 s = seprint(s, e, "%s ", flagname[i]); 556 } 557 return seprint(s, e, "\n"); 558 } 559 560 static int 561 aoerctl(SDunit *u, char *p, int l) 562 { 563 Ctlr *c; 564 char *e, *op; 565 566 if((c = u->dev->ctlr) == nil) 567 return 0; 568 e = p+l; 569 op = p; 570 571 p = seprint(p, e, "model\t%s\n", c->model); 572 p = seprint(p, e, "serial\t%s\n", c->serial); 573 p = seprint(p, e, "firm %s\n", c->firmware); 574 if(c->smartrs == 0xff) 575 p = seprint(p, e, "smart\tenable error\n"); 576 else if(c->smartrs == 0) 577 p = seprint(p, e, "smart\tdisabled\n"); 578 else 579 p = seprint(p, e, "smart\t%s\n", smarttab[c->smart]); 580 p = seprint(p, e, "flag "); 581 p = pflag(p, e, c->feat); 582 p = seprint(p, e, "geometry %llud %d\n", c->sectors, Aoesectsz); 583 return p-op; 584 } 585 586 static int 587 aoewctl(SDunit *d1, Cmdbuf *cmd) 588 { 589 cmderror(cmd, Ebadarg); 590 return 0; 591 } 592 593 static SDev* 594 aoeprobew(DevConf *c) 595 { 596 char *p; 597 598 p = strchr(c->type, '/'); 599 if(p == nil || strlen(p) > Maxpath - 11) 600 error(Ebadarg); 601 if(p[1] == '#') 602 p++; /* hack */ 603 if(ctlrlookup(p)) 604 error(Einuse); 605 return aoeprobe(p, 0); 606 } 607 608 static void 609 aoeclear(SDev *s) 610 { 611 delctlr((Ctlr *)s->ctlr); 612 } 613 614 static char* 615 aoertopctl(SDev *s, char *p, char *e) 616 { 617 Ctlr *c; 618 619 c = s->ctlr; 620 return seprint(p, e, "%s aoe %s\n", s->name, c->path); 621 } 622 623 static int 624 aoewtopctl(SDev *d1, Cmdbuf *cmd) 625 { 626 switch(cmd->nf){ 627 default: 628 cmderror(cmd, Ebadarg); 629 } 630 return 0; 631 } 632 633 SDifc sdaoeifc = { 634 "aoe", 635 636 aoepnp, 637 nil, /* legacy */ 638 nil, /* enable */ 639 nil, /* disable */ 640 641 aoeverify, 642 aoeonline, 643 aoerio, 644 aoerctl, 645 aoewctl, 646 647 scsibio, 648 aoeprobew, /* probe */ 649 aoeclear, /* clear */ 650 aoertopctl, 651 aoewtopctl, 652 };