sdaoe.c 11 KB

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