sdaoe.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * aoe sd bootstrap driver, copyright © 2007 coraid
  3. */
  4. #include "u.h"
  5. #include "mem.h"
  6. #include "lib.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "sd.h"
  11. #include "aoe.h"
  12. #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
  13. enum {
  14. Nctlr = 4,
  15. };
  16. enum {
  17. /* sync with ahci.h */
  18. Dllba = 1<<0,
  19. Dsmart = 1<<1,
  20. Dpower = 1<<2,
  21. Dnop = 1<<3,
  22. Datapi = 1<<4,
  23. Datapi16= 1<<5,
  24. };
  25. enum {
  26. Tfree = -1,
  27. Tmgmt,
  28. };
  29. typedef struct Ctlr Ctlr;
  30. struct Ctlr{
  31. Ctlr *next;
  32. SDunit *unit;
  33. int ctlrno;
  34. int major;
  35. int minor;
  36. uchar ea[Eaddrlen];
  37. ushort lasttag;
  38. ulong vers;
  39. uchar mediachange;
  40. uchar flag;
  41. uchar smart;
  42. uchar smartrs;
  43. uchar feat;
  44. uvlong sectors;
  45. char serial[20+1];
  46. char firmware[8+1];
  47. char model[40+1];
  48. char ident[0x100];
  49. };
  50. static Ctlr *head;
  51. static Ctlr *tail;
  52. static int aoeether[10];
  53. SDifc sdaoeifc;
  54. static void
  55. hnputs(uchar *p, ushort i)
  56. {
  57. p[0] = i >> 8;
  58. p[1] = i;
  59. }
  60. static void
  61. hnputl(uchar *p, ulong i)
  62. {
  63. p[0] = i >> 24;
  64. p[1] = i >> 16;
  65. p[2] = i >> 8;
  66. p[3] = i;
  67. }
  68. static ushort
  69. nhgets(uchar *p)
  70. {
  71. return *p<<8 | p[1];
  72. }
  73. static ulong
  74. nhgetl(uchar *p)
  75. {
  76. return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
  77. }
  78. static int
  79. newtag(Ctlr *d)
  80. {
  81. int t;
  82. for(;;){
  83. t = ++d->lasttag << 16;
  84. t |= m->ticks & 0xffff;
  85. switch(t) {
  86. case Tfree:
  87. case Tmgmt:
  88. break;
  89. default:
  90. return t;
  91. }
  92. }
  93. }
  94. static int
  95. hset(Ctlr *d, Aoehdr *h, int cmd)
  96. {
  97. int tag;
  98. memmove(h->dst, d->ea, Eaddrlen);
  99. hnputs(h->type, Aoetype);
  100. h->verflag = Aoever << 4;
  101. hnputs(h->major, d->major);
  102. h->minor = d->minor;
  103. h->cmd = cmd;
  104. hnputl(h->tag, tag = newtag(d));
  105. return tag;
  106. }
  107. static void
  108. idmove(char *p, ushort *a, int n)
  109. {
  110. int i;
  111. char *op, *e;
  112. op = p;
  113. for(i = 0; i < n / 2; i++){
  114. *p++ = a[i] >> 8;
  115. *p++ = a[i];
  116. }
  117. *p = 0;
  118. while(p > op && *--p == ' ')
  119. *p = 0;
  120. e = p;
  121. p = op;
  122. while(*p == ' ')
  123. p++;
  124. memmove(op, p, n - (e - p));
  125. }
  126. static ushort
  127. gbit16(void *a)
  128. {
  129. uchar *i;
  130. i = a;
  131. return i[1]<<8 | i[0];
  132. }
  133. static ulong
  134. gbit32(void *a)
  135. {
  136. uchar *i;
  137. ulong j;
  138. i = a;
  139. j = i[3] << 24;
  140. j |= i[2] << 16;
  141. j |= i[1] << 8;
  142. j |= i[0];
  143. return j;
  144. }
  145. static uvlong
  146. gbit64(void *a)
  147. {
  148. uchar *i;
  149. i = a;
  150. return (uvlong)gbit32(i+4) << 32 | gbit32(a);
  151. }
  152. static int
  153. ataidentify(Ctlr *c, ushort *id)
  154. {
  155. vlong s;
  156. int i;
  157. i = gbit16(id+83) | gbit16(id+86);
  158. if(i & (1 << 10)){
  159. c->feat |= Dllba;
  160. s = gbit64(id+100);
  161. }else
  162. s = gbit32(id+60);
  163. idmove(c->serial, id+10, 20);
  164. idmove(c->firmware, id+23, 8);
  165. idmove(c->model, id+27, 40);
  166. print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
  167. c->sectors = s;
  168. c->mediachange = 1;
  169. return 0;
  170. }
  171. static void
  172. identifydump(Aoeata *a)
  173. {
  174. print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
  175. a->dst, a->src, nhgets(a->type), a->verflag, a->error,
  176. nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
  177. print(" aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
  178. a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
  179. }
  180. static int
  181. idpkt(Ctlr *c, Aoeata *a)
  182. {
  183. memset(a, 0, sizeof *a);
  184. a->cmdstat = Cid;
  185. a->scnt = 1;
  186. a->lba[3] = 0xa0;
  187. return hset(c, a, ACata);
  188. }
  189. static int
  190. chktag(int *out, int nout, int tag)
  191. {
  192. int j;
  193. for(j = 0; j <= nout; j++)
  194. if(out[j] == tag)
  195. return 0;
  196. print("wrong tag\n");
  197. for(j = 0; j <= nout; j++)
  198. print("%.8ux != %.8ux\n", out[j], tag);
  199. return -1;
  200. }
  201. /*
  202. * ignore the tag for identify. better than ignoring
  203. * a response to the wrong identify request
  204. */
  205. static int
  206. identify(Ctlr *c)
  207. {
  208. int tag[5], i, n;
  209. Aoeata *a;
  210. Etherpkt p;
  211. memset(&p, 0, sizeof p);
  212. a = (Aoeata*)&p;
  213. i = 0;
  214. do {
  215. if(i == 5){
  216. print("aoe: identify timeout\n");
  217. return -1;
  218. }
  219. tag[i] = idpkt(c, a);
  220. ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
  221. memset(&p, 0, sizeof p);
  222. next:
  223. n = etherrxpkt(c->ctlrno, &p, 125);
  224. if(n == 0){
  225. i++;
  226. continue;
  227. }
  228. if(nhgets(a->type) != Aoetype)
  229. goto next;
  230. if(nhgets(a->major) != c->major || a->minor != c->minor){
  231. print("wrong device %d.%d want %d.%d; %d\n",
  232. nhgets(a->major), a->minor,
  233. c->major, c->minor, n);
  234. goto next;
  235. }
  236. if(chktag(tag, i, nhgetl(a->tag)) == -1)
  237. goto next;
  238. if(a->cmdstat & 0xa9){
  239. print("aoe: ata error on identify: %2ux\n", a->cmdstat);
  240. return -1;
  241. }
  242. } while (a->scnt != 1);
  243. c->feat = 0;
  244. ataidentify(c, (ushort*)(a+1));
  245. return 0;
  246. }
  247. static Ctlr*
  248. ctlrlookup(int major, int minor)
  249. {
  250. Ctlr *c;
  251. for(c = head; c; c = c->next)
  252. if(c->major == major && c->minor == minor)
  253. break;
  254. return c;
  255. }
  256. static Ctlr*
  257. newctlr(Etherpkt *p)
  258. {
  259. int major, minor;
  260. Aoeqc *q;
  261. Ctlr *c;
  262. q = (Aoeqc*)p;
  263. if(nhgets(q->type) != Aoetype)
  264. return 0;
  265. major = nhgets(q->major);
  266. minor = q->minor;
  267. if(major == 0xffff || minor == 0xff)
  268. return 0;
  269. if(ctlrlookup(major, minor)){
  270. print("duplicate shelf.slot\n");
  271. return 0;
  272. }
  273. if((c = malloc(sizeof *c)) == 0)
  274. return 0;
  275. c->major = major;
  276. c->minor = minor;
  277. memmove(c->ea, q->src, Eaddrlen);
  278. if(head != 0)
  279. tail->next = c;
  280. else
  281. head = c;
  282. tail = c;
  283. return c;
  284. }
  285. static void
  286. discover(int major, int minor)
  287. {
  288. int i;
  289. Aoehdr *h;
  290. Etherpkt p;
  291. for(i = 0; i < nelem(aoeether); i++){
  292. if(aoeether[i] == 0)
  293. continue;
  294. memset(&p, 0, ETHERMINTU);
  295. h = (Aoehdr*)&p;
  296. memset(h->dst, 0xff, sizeof h->dst);
  297. hnputs(h->type, Aoetype);
  298. h->verflag = Aoever << 4;
  299. hnputs(h->major, major);
  300. h->minor = minor;
  301. h->cmd = ACconfig;
  302. ethertxpkt(i, &p, ETHERMINTU, 0);
  303. }
  304. }
  305. static int
  306. rxany(Etherpkt *p, int t)
  307. {
  308. int i, n;
  309. for(i = 0; i < nelem(aoeether); i++){
  310. if(aoeether[i] == 0)
  311. continue;
  312. while ((n = etherrxpkt(i, p, t)) != 0)
  313. if(nhgets(p->type) == Aoetype)
  314. return n;
  315. }
  316. return 0;
  317. }
  318. static int
  319. aoeprobe(int major, int minor, SDev *s)
  320. {
  321. Ctlr *ctlr;
  322. Etherpkt p;
  323. int n, i;
  324. for(i = 0;; i += 200){
  325. if(i > 8000)
  326. return -1;
  327. discover(major, minor);
  328. again:
  329. n = rxany(&p, 100);
  330. if(n > 0 && (ctlr = newctlr(&p)))
  331. break;
  332. if(n > 0)
  333. goto again;
  334. }
  335. s->ctlr = ctlr;
  336. s->ifc = &sdaoeifc;
  337. s->nunit = 1;
  338. return 0;
  339. }
  340. static char *probef[32];
  341. static int nprobe;
  342. int
  343. pnpprobeid(char *s)
  344. {
  345. int id;
  346. if(strlen(s) < 2)
  347. return 0;
  348. id = 'e';
  349. if(s[1] == '!')
  350. id = s[0];
  351. return id;
  352. }
  353. int
  354. tokenize(char *s, char **args, int maxargs)
  355. {
  356. int nargs;
  357. for(nargs = 0; nargs < maxargs; nargs++){
  358. while(*s != '\0' && strchr("\t\n ", *s) != nil)
  359. s++;
  360. if(*s == '\0')
  361. break;
  362. args[nargs] = s;
  363. while(*s != '\0' && strchr("\t\n ", *s) == nil)
  364. s++;
  365. if(*s != '\0')
  366. *s++ = 0;
  367. }
  368. return nargs;
  369. }
  370. int
  371. aoepnp0(void)
  372. {
  373. int i;
  374. char *p, c;
  375. if((p = getconf("aoeif")) == nil)
  376. return 0;
  377. print("aoeif = %s\n", p);
  378. nprobe = tokenize(p, probef, nelem(probef));
  379. for(i = 0; i < nprobe; i++){
  380. if(strncmp(probef[i], "ether", 5) != 0)
  381. continue;
  382. c = probef[i][5];
  383. if(c > '9' || c < '0')
  384. continue;
  385. aoeether[c - '0'] = 1;
  386. }
  387. if((p = getconf("aoedev")) == nil)
  388. return 0;
  389. return nprobe = tokenize(p, probef, nelem(probef));
  390. }
  391. int
  392. probeshelf(char *s, int *shelf, int *slot)
  393. {
  394. int a, b;
  395. char *r;
  396. for(r = s + strlen(s) - 1; r > s; r--)
  397. if((*r < '0' || *r > '9') && *r != '.'){
  398. r++;
  399. break;
  400. }
  401. a = strtoul(r, &r, 10);
  402. if(*r++ != '.')
  403. return -1;
  404. b = strtoul(r, 0, 10);
  405. *shelf = a;
  406. *slot = b;
  407. print(" shelf=%d.%d\n", a, b);
  408. return 0;
  409. }
  410. Ctlr*
  411. pnpprobe(SDev *sd)
  412. {
  413. int shelf, slot;
  414. char *p;
  415. static int i;
  416. if(i >= nprobe)
  417. return 0;
  418. p = probef[i++];
  419. if(strlen(p) < 2)
  420. return 0;
  421. if(p[1] == '!'){
  422. sd->idno = p[0];
  423. p += 2;
  424. }
  425. if(probeshelf(p, &shelf, &slot) == -1 ||
  426. aoeprobe(shelf, slot, sd) == -1 ||
  427. identify(sd->ctlr) == -1)
  428. return 0;
  429. return sd->ctlr;
  430. }
  431. /*
  432. * we may need to pretend we found something
  433. */
  434. SDev*
  435. aoepnp(void)
  436. {
  437. int n, i, id;
  438. char *p;
  439. SDev *h, *t, *s;
  440. p = getconf("aoeif");
  441. if (p)
  442. print("aoepnp: aoeif=%s\n", p);
  443. if((n = aoepnp0()) == 0)
  444. n = 2;
  445. t = h = 0;
  446. for(i = 0; i < n; i++){
  447. id = 'e';
  448. s = malloc(sizeof *s);
  449. if(s == 0)
  450. break;
  451. s->ctlr = 0;
  452. s->idno = id;
  453. s->ifc = &sdaoeifc;
  454. s->nunit = 1;
  455. pnpprobe(s);
  456. if(h)
  457. t->next = s;
  458. else
  459. h = s;
  460. t = s;
  461. }
  462. return h;
  463. }
  464. static int
  465. aoeverify(SDunit *u)
  466. {
  467. Ctlr *c;
  468. SDev *s;
  469. s = u->dev;
  470. c = s->ctlr;
  471. if(c == 0){
  472. aoepnp0();
  473. if((s->ctlr = c = pnpprobe(s)) == nil)
  474. return 0;
  475. }
  476. c->mediachange = 1;
  477. return 1;
  478. }
  479. static int
  480. aoeonline(SDunit *u)
  481. {
  482. int r;
  483. Ctlr *c;
  484. c = u->dev->ctlr;
  485. if(c->mediachange){
  486. r = 2;
  487. c->mediachange = 0;
  488. u->sectors = c->sectors;
  489. u->secsize = 512;
  490. } else
  491. r = 1;
  492. return r;
  493. }
  494. static int
  495. rio(Ctlr *c, Aoeata *a, int n, int scnt)
  496. {
  497. int i, tag, cmd;
  498. for(i = 0; i < 5; i++){
  499. tag = hset(c, a, ACata);
  500. cmd = a->cmdstat;
  501. ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
  502. memset(a, 0, sizeof *a);
  503. again:
  504. n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
  505. if(n == 0)
  506. continue;
  507. if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
  508. nhgets(a->major) != c->major || a->minor != c->minor)
  509. goto again;
  510. if(a->cmdstat & 0xa9){
  511. print("aoe: ata rio error: %2ux\n", a->cmdstat);
  512. return 0;
  513. }
  514. switch(cmd){
  515. case Crd:
  516. case Crdext:
  517. if(n - sizeof *a < scnt * 512){
  518. print("aoe: runt expect %d got %d\n",
  519. scnt*512 + sizeof *a, n);
  520. return 0;
  521. }
  522. return n - sizeof *a;
  523. case Cwr:
  524. case Cwrext:
  525. return scnt * 512;
  526. default:
  527. print("unknown cmd %ux\n", cmd);
  528. break;
  529. }
  530. }
  531. print("aoe: rio timeout\n");
  532. return 0;
  533. }
  534. static void
  535. putlba(Aoeata *a, vlong lba)
  536. {
  537. uchar *c;
  538. c = a->lba;
  539. c[0] = lba;
  540. c[1] = lba >> 8;
  541. c[2] = lba >> 16;
  542. c[3] = lba >> 24;
  543. c[4] = lba >> 32;
  544. c[5] = lba >> 40;
  545. }
  546. /*
  547. * you'll need to loop if you want to read more than 2 sectors. for now
  548. * i'm cheeting and not bothering with a loop.
  549. */
  550. static uchar pktbuf[1024 + sizeof(Aoeata)];
  551. static int
  552. aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
  553. {
  554. int n;
  555. Aoeata *a;
  556. memset(pktbuf, 0, sizeof pktbuf);
  557. a = (Aoeata*)pktbuf;
  558. hset(c, a, ACata);
  559. putlba(a, lba);
  560. a->cmdstat = 0x20;
  561. if(c->flag & Dllba){
  562. a->aflag |= AAFext;
  563. a->cmdstat |= 4;
  564. }else{
  565. a->lba[3] &= 0xf;
  566. a->lba[3] |= 0xe0; /* LBA bit+obsolete 0xa0 */
  567. }
  568. n = scnt;
  569. if(n > 2)
  570. n = 2;
  571. a->scnt = n;
  572. switch(*cmd){
  573. case 0x2a:
  574. a->aflag |= AAFwrite;
  575. a->cmdstat |= 10;
  576. memmove(a+1, data, n*512);
  577. n = sizeof *a + n*512;
  578. break;
  579. case 0x28:
  580. n = sizeof *a;
  581. break;
  582. default:
  583. print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
  584. return -1;
  585. }
  586. return n;
  587. }
  588. static int
  589. aoerio(SDreq *r)
  590. {
  591. int size, nsec, n;
  592. vlong lba;
  593. char *data;
  594. uchar *cmd;
  595. Aoeata *a;
  596. Ctlr *c;
  597. SDunit *unit;
  598. unit = r->unit;
  599. c = unit->dev->ctlr;
  600. if(r->data == nil)
  601. return SDok;
  602. cmd = r->cmd;
  603. lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; /* sic. */
  604. nsec = cmd[7]<<8 | cmd[8];
  605. a = (Aoeata*)pktbuf;
  606. data = r->data;
  607. r->rlen = 0;
  608. for(; nsec > 0; nsec -= n){
  609. // print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
  610. size = aoebuild(c, cmd, data, lba, nsec);
  611. if(size < 0){
  612. r->status = SDcheck;
  613. return SDcheck;
  614. }
  615. n = a->scnt;
  616. r->rlen += rio(c, a, size, n);
  617. if(*cmd == 0x28)
  618. memmove(r->data, a + 1, n * 512);
  619. data += n * 512;
  620. lba += n;
  621. }
  622. r->status = SDok;
  623. return SDok;
  624. }
  625. SDifc sdaoeifc = {
  626. "aoe",
  627. aoepnp,
  628. nil, /* legacy */
  629. nil, /* id */
  630. nil, /* enable */
  631. nil, /* disable */
  632. aoeverify,
  633. aoeonline,
  634. aoerio,
  635. nil,
  636. nil,
  637. scsibio,
  638. };