sd63xxesb.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120
  1. /*
  2. * intel 63[12]?esb ahci sata controller
  3. * copyright © 2007 coraid, inc.
  4. */
  5. #include "u.h"
  6. #include "../port/lib.h"
  7. #include "mem.h"
  8. #include "dat.h"
  9. #include "fns.h"
  10. #include "io.h"
  11. #include "../port/error.h"
  12. #include "../port/sd.h"
  13. #include "ahci.h"
  14. #define dprint(...) if(debug == 1) iprint(__VA_ARGS__); else USED(debug)
  15. #define idprint(...) if(prid == 1) print(__VA_ARGS__); else USED(prid)
  16. #define aprint(...) if(datapi == 1) iprint(__VA_ARGS__); else USED(datapi);
  17. enum{
  18. NCtlr = 4,
  19. NCtlrdrv= 32,
  20. NDrive = NCtlr*NCtlrdrv,
  21. Read = 0,
  22. Write,
  23. };
  24. /* pci space configurtion */
  25. enum{
  26. Pmap = 0x90,
  27. Ppcs = 0x91,
  28. Prev = 0xa8,
  29. };
  30. enum{
  31. Dnull,
  32. Dmissing,
  33. Dnew,
  34. Dready,
  35. Derror,
  36. Dreset,
  37. Doffline,
  38. Dportreset,
  39. Dlast,
  40. };
  41. static char *diskstates[Dlast] = {
  42. "null",
  43. "missing",
  44. "new",
  45. "ready",
  46. "error",
  47. "reset",
  48. "offline",
  49. "portreset",
  50. };
  51. extern SDifc sd63xxesbifc;
  52. typedef struct Ctlr Ctlr;
  53. enum{
  54. DMautoneg,
  55. DMsatai,
  56. DMsataii,
  57. };
  58. static char *modename[] = {
  59. "auto",
  60. "satai",
  61. "sataii",
  62. };
  63. static char *flagname[] = {
  64. "llba",
  65. "smart",
  66. "power",
  67. "nop",
  68. "atapi",
  69. "atapi16",
  70. };
  71. typedef struct{
  72. Lock;
  73. Ctlr *ctlr;
  74. SDunit *unit;
  75. char name[10];
  76. Aport *port;
  77. Aportm portm;
  78. Aportc portc; /* redundant ptr to port and portm. */
  79. uchar mediachange;
  80. uchar state;
  81. uchar smartrs;
  82. uvlong sectors;
  83. ulong intick;
  84. int wait;
  85. uchar mode; /* DMautoneg, satai or sataii. */
  86. uchar active;
  87. char serial[20+1];
  88. char firmware[8+1];
  89. char model[40+1];
  90. ushort info[0x200];
  91. int driveno; /* ctlr*NCtlrdrv + unit */
  92. /* ctlr port # != driveno when not all ports are enabled */
  93. int portno;
  94. }Drive;
  95. struct Ctlr{
  96. Lock;
  97. int irq;
  98. int tbdf;
  99. int enabled;
  100. SDev *sdev;
  101. Pcidev *pci;
  102. uchar *mmio;
  103. ulong *lmmio;
  104. Ahba *hba;
  105. Drive rawdrive[NCtlrdrv];
  106. Drive* drive[NCtlrdrv];
  107. int ndrive;
  108. };
  109. static Ctlr iactlr[NCtlr];
  110. static SDev sdevs[NCtlr];
  111. static int niactlr;
  112. static Drive *iadrive[NDrive];
  113. static int niadrive;
  114. static int debug;
  115. static int prid = 1;
  116. static int datapi = 1;
  117. static char stab[] = {
  118. [0] 'i', 'm',
  119. [8] 't', 'c', 'p', 'e',
  120. [16] 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
  121. };
  122. static void
  123. serrstr(ulong r, char *s, char *e)
  124. {
  125. int i;
  126. e -= 3;
  127. for(i = 0; i < nelem(stab) && s < e; i++)
  128. if((r & (1<<i)) && stab[i]){
  129. *s++ = stab[i];
  130. if(SerrBad & (1<<i))
  131. *s++ = '*';
  132. }
  133. *s = 0;
  134. }
  135. static char ntab[] = "0123456789abcdef";
  136. static void
  137. preg(uchar *reg, int n)
  138. {
  139. int i;
  140. char buf[25*3+1], *e;
  141. e = buf;
  142. for(i = 0; i < n; i++){
  143. *e++ = ntab[reg[i]>>4];
  144. *e++ = ntab[reg[i]&0xf];
  145. *e++ = ' ';
  146. }
  147. *e++ = '\n';
  148. *e = 0;
  149. dprint(buf);
  150. }
  151. static void
  152. dreg(char *s, Aport *p)
  153. {
  154. dprint("%stask=%ux; cmd=%ux; ci=%ux; is=%ux\n", s, p->task, p->cmd,
  155. p->ci, p->isr);
  156. }
  157. static void
  158. esleep(int ms)
  159. {
  160. if(waserror())
  161. return;
  162. tsleep(&up->sleep, return0, 0, ms);
  163. poperror();
  164. }
  165. typedef struct{
  166. Aport *p;
  167. int i;
  168. }Asleep;
  169. static int
  170. ahciclear(void *v)
  171. {
  172. Asleep *s;
  173. s = v;
  174. return (s->p->ci & s->i) == 0;
  175. }
  176. static void
  177. aesleep(Aportm *m, Asleep *a, int ms)
  178. {
  179. if(waserror())
  180. return;
  181. tsleep(m, ahciclear, a, ms);
  182. poperror();
  183. }
  184. static int
  185. ahciwait(Aportc *c, int ms)
  186. {
  187. Asleep as;
  188. Aport *p;
  189. p = c->p;
  190. p->ci = 1;
  191. as.p = p;
  192. as.i = 1;
  193. aesleep(c->m, &as, ms);
  194. if((p->task&1) == 0 && p->ci == 0)
  195. return 0;
  196. dreg("ahciwait timeout ", c->p);
  197. return -1;
  198. }
  199. static int
  200. nop(Aportc *pc)
  201. {
  202. uchar *c;
  203. Actab *t;
  204. Alist *l;
  205. if((pc->m->feat&Dnop) == 0)
  206. return -1;
  207. t = pc->m->ctab;
  208. c = t->cfis;
  209. memset(c, 0, 0x20);
  210. c[0] = 0x27;
  211. c[1] = 0x80;
  212. c[2] = 0x00;
  213. c[7] = 0xa0; /* obsolete device bits */
  214. l = pc->m->list;
  215. l->flags = Lwrite|0x5;
  216. l->len = 0;
  217. l->ctab = PCIWADDR(t);
  218. l->ctabhi = 0;
  219. return ahciwait(pc, 3*1000);
  220. }
  221. static int
  222. setfeatures(Aportc *pc, uchar f)
  223. {
  224. uchar *c;
  225. Actab *t;
  226. Alist *l;
  227. t = pc->m->ctab;
  228. c = t->cfis;
  229. memset(c, 0, 0x20);
  230. c[0] = 0x27;
  231. c[1] = 0x80;
  232. c[2] = 0xef;
  233. c[3] = f;
  234. c[7] = 0xa0; /* obsolete device bits */
  235. l = pc->m->list;
  236. l->flags = Lwrite|0x5;
  237. l->len = 0;
  238. l->ctab = PCIWADDR(t);
  239. l->ctabhi = 0;
  240. return ahciwait(pc, 3*1000);
  241. }
  242. static int
  243. setudmamode(Aportc *pc, uchar f)
  244. {
  245. uchar *c;
  246. Actab *t;
  247. Alist *l;
  248. t = pc->m->ctab;
  249. c = t->cfis;
  250. memset(c, 0, 0x20);
  251. c[0] = 0x27;
  252. c[1] = 0x80;
  253. c[2] = 0xef;
  254. c[3] = 3; /* set transfer mode */
  255. c[7] = 0xa0; /* obsolete device bits */
  256. c[12] = 0x40|f; /* sector count */
  257. l = pc->m->list;
  258. l->flags = Lwrite|0x5;
  259. l->len = 0;
  260. l->ctab = PCIWADDR(t);
  261. l->ctabhi = 0;
  262. return ahciwait(pc, 3*1000);
  263. }
  264. static void
  265. asleep(int ms)
  266. {
  267. if(up == nil)
  268. delay(ms);
  269. else
  270. esleep(ms);
  271. }
  272. static int
  273. ahciportreset(Aportc *c)
  274. {
  275. u32int *cmd, i;
  276. Aport *p;
  277. p = c->p;
  278. cmd = &p->cmd;
  279. *cmd &= ~(Afre|Ast);
  280. for(i = 0; i < 500; i += 25){
  281. if((*cmd & Acr) == 0)
  282. break;
  283. asleep(25);
  284. }
  285. p->sctl = 1 | (p->sctl & ~7);
  286. delay(1);
  287. p->sctl &= ~7;
  288. return 0;
  289. }
  290. static int
  291. smart(Aportc *pc, int n)
  292. {
  293. uchar *c;
  294. Actab *t;
  295. Alist *l;
  296. if((pc->m->feat&Dsmart) == 0)
  297. return -1;
  298. t = pc->m->ctab;
  299. c = t->cfis;
  300. memset(c, 0, 0x20);
  301. c[0] = 0x27;
  302. c[1] = 0x80;
  303. c[2] = 0xb0;
  304. c[3] = 0xd8+n; /* able smart */
  305. c[5] = 0x4f;
  306. c[6] = 0xc2;
  307. c[7] = 0xa0;
  308. l = pc->m->list;
  309. l->flags = Lwrite | 0x5;
  310. l->len = 0;
  311. l->ctab = PCIWADDR(t);
  312. l->ctabhi = 0;
  313. if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){
  314. dprint("smart fail %ux\n", pc->p->task);
  315. // preg(pc->m->fis.r, 20);
  316. return -1;
  317. }
  318. if(n)
  319. return 0;
  320. return 1;
  321. }
  322. static int
  323. smartrs(Aportc *pc)
  324. {
  325. uchar *c;
  326. Actab *t;
  327. Alist *l;
  328. t = pc->m->ctab;
  329. c = t->cfis;
  330. memset(c, 0, 0x20);
  331. c[0] = 0x27;
  332. c[1] = 0x80;
  333. c[2] = 0xb0;
  334. c[3] = 0xda; /* return smart status */
  335. c[5] = 0x4f;
  336. c[6] = 0xc2;
  337. c[7] = 0xa0;
  338. l = pc->m->list;
  339. l->flags = Lwrite | 0x5;
  340. l->len = 0;
  341. l->ctab = PCIWADDR(t);
  342. l->ctabhi = 0;
  343. c = pc->m->fis.r;
  344. if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){
  345. dprint("smart fail %ux\n", pc->p->task);
  346. preg(c, 20);
  347. return -1;
  348. }
  349. if(c[5] == 0x4f && c[6] == 0xc2)
  350. return 1;
  351. return 0;
  352. }
  353. static int
  354. flushcache(Aportc *pc)
  355. {
  356. uchar *c, llba;
  357. Actab *t;
  358. Alist *l;
  359. static uchar tab[2] = {0xe7, 0xea};
  360. llba = pc->m->feat & Dllba? 1: 0;
  361. t = pc->m->ctab;
  362. c = t->cfis;
  363. memset(c, 0, 0x20);
  364. c[0] = 0x27;
  365. c[1] = 0x80;
  366. c[2] = tab[llba];
  367. c[7] = 0xa0;
  368. l = pc->m->list;
  369. l->flags = Lwrite | 0x5;
  370. l->len = 0;
  371. l->ctab = PCIWADDR(t);
  372. l->ctabhi = 0;
  373. if(ahciwait(pc, 60000) == -1 || pc->p->task & (1|32)){
  374. dprint("flushcache fail %ux\n", pc->p->task);
  375. // preg( pc->m->fis.r, 20);
  376. return -1;
  377. }
  378. return 0;
  379. }
  380. static ushort
  381. gbit16(void *a)
  382. {
  383. ushort j;
  384. uchar *i;
  385. i = a;
  386. j = i[1] << 8;
  387. j |= i[0];
  388. return j;
  389. }
  390. static u32int
  391. gbit32(void *a)
  392. {
  393. uchar *i;
  394. u32int j;
  395. i = a;
  396. j = i[3] << 24;
  397. j |= i[2] << 16;
  398. j |= i[1] << 8;
  399. j |= i[0];
  400. return j;
  401. }
  402. static uvlong
  403. gbit64(void *a)
  404. {
  405. uchar *i;
  406. i = a;
  407. return (uvlong)gbit32(i+4) << 32 | gbit32(a);
  408. }
  409. static int
  410. ahciidentify0(Aportc *pc, void *id, int atapi)
  411. {
  412. uchar *c;
  413. Actab *t;
  414. Alist *l;
  415. Aprdt *p;
  416. static uchar tab[] = {0xec, 0xa1};
  417. t = pc->m->ctab;
  418. c = t->cfis;
  419. memset(c, 0, 0x20);
  420. c[0] = 0x27;
  421. c[1] = 0x80;
  422. c[2] = tab[atapi];
  423. c[7] = 0xa0; /* obsolete device bits */
  424. l = pc->m->list;
  425. l->flags = 1<<16 | 0x5;
  426. l->len = 0;
  427. l->ctab = PCIWADDR(t);
  428. l->ctabhi = 0;
  429. memset(id, 0, 0x100);
  430. p = &t->prdt;
  431. p->dba = PCIWADDR(id);
  432. p->dbahi = 0;
  433. p->count = 1<<31 | (0x200-2) | 1;
  434. return ahciwait(pc, 3*1000);
  435. }
  436. static vlong
  437. ahciidentify(Aportc *pc, ushort *id)
  438. {
  439. int i, sig;
  440. vlong s;
  441. Aportm *m;
  442. m = pc->m;
  443. m->feat = 0;
  444. m->smart = 0;
  445. i = 0;
  446. sig = pc->p->sig >> 16;
  447. if(sig == 0xeb14 || sig == 0x9669){
  448. m->feat |= Datapi;
  449. i = 1;
  450. }
  451. if(ahciidentify0(pc, id, i) == -1)
  452. return -1;
  453. i = gbit16(id+83) | gbit16(id+86);
  454. if(i & (1<<10)){
  455. m->feat |= Dllba;
  456. s = gbit64(id+100);
  457. }else
  458. s = gbit32(id+60);
  459. if(m->feat&Datapi){
  460. i = gbit16(id+0);
  461. if(i&1)
  462. m->feat |= Datapi16;
  463. }
  464. i = gbit16(id+83);
  465. if((i>>14) == 1) {
  466. if(i & (1<<3))
  467. m->feat |= Dpower;
  468. i = gbit16(id+82);
  469. if(i & 1)
  470. m->feat |= Dsmart;
  471. if(i & (1<<14))
  472. m->feat |= Dnop;
  473. }
  474. return s;
  475. }
  476. static int
  477. ahciquiet(Aport *a)
  478. {
  479. u32int *p, i;
  480. p = &a->cmd;
  481. *p &= ~Ast;
  482. for(i = 0; i < 500; i += 50){
  483. if((*p & Acr) == 0)
  484. goto stop;
  485. asleep(50);
  486. }
  487. return -1;
  488. stop:
  489. if((a->task & (ASdrq|ASbsy)) == 0){
  490. *p |= Ast;
  491. return 0;
  492. }
  493. *p |= Aclo;
  494. for(i = 0; i < 500; i += 50){
  495. if((*p & Aclo) == 0)
  496. goto stop1;
  497. asleep(50);
  498. }
  499. return -1;
  500. stop1:
  501. /* extra check */
  502. dprint("clo clear %x\n", a->task);
  503. if(a->task & ASbsy)
  504. return -1;
  505. *p |= Ast;
  506. return 0;
  507. }
  508. static int
  509. ahcicomreset(Aportc *pc)
  510. {
  511. Actab *t;
  512. Alist *l;
  513. uchar *c;
  514. dprint("ahcicomreset\n");
  515. dreg("comreset ", pc->p);
  516. if(ahciquiet(pc->p) == -1){
  517. dprint("ahciquiet fails\n");
  518. return -1;
  519. }
  520. dreg("comreset ", pc->p);
  521. t = pc->m->ctab;
  522. c = t->cfis;
  523. memset(c, 0, 0x20);
  524. c[0] = 0x27;
  525. c[1] = 0x00;
  526. c[7] = 0xa0; /* obsolete device bits */
  527. c[15] = 1<<2; /* srst */
  528. l = pc->m->list;
  529. l->flags = Lclear | Lreset | 0x5;
  530. l->len = 0;
  531. l->ctab = PCIWADDR(t);
  532. l->ctabhi = 0;
  533. if(ahciwait(pc, 500) == -1){
  534. dprint("first command in comreset fails\n");
  535. return -1;
  536. }
  537. microdelay(250);
  538. dreg("comreset ", pc->p);
  539. memset(c, 0, 0x20);
  540. c[0] = 0x27;
  541. c[1] = 0x00;
  542. c[7] = 0xa0; /* obsolete device bits */
  543. l = pc->m->list;
  544. l->flags = Lwrite | 0x5;
  545. l->len = 0;
  546. l->ctab = PCIWADDR(t);
  547. l->ctabhi = 0;
  548. if(ahciwait(pc, 150) == -1){
  549. dprint("second command in comreset fails\n");
  550. return -1;
  551. }
  552. dreg("comreset ", pc->p);
  553. return 0;
  554. }
  555. static int
  556. ahciidle(Aport *port)
  557. {
  558. u32int *p, i, r;
  559. p = &port->cmd;
  560. if((*p&Arun) == 0)
  561. return 0;
  562. *p &= ~Ast;
  563. r = 0;
  564. for(i = 0; i < 500; i += 25){
  565. if((*p & Acr) == 0)
  566. goto stop;
  567. asleep(25);
  568. }
  569. r = -1;
  570. stop:
  571. if((*p & Afre) == 0)
  572. return r;
  573. *p &= ~Afre;
  574. for(i = 0; i < 500; i += 25){
  575. if((*p & Afre) == 0)
  576. return 0;
  577. asleep(25);
  578. }
  579. return -1;
  580. }
  581. /*
  582. * § 6.2.2.1 first part; comreset handled by reset disk.
  583. * - remainder is handled by configdisk.
  584. * - ahcirecover is a quick recovery from a failed command.
  585. */
  586. int
  587. ahciswreset(Aportc *pc)
  588. {
  589. int i;
  590. i = ahciidle(pc->p);
  591. pc->p->cmd |= Afre;
  592. if(i == -1)
  593. return -1;
  594. if(pc->p->task & (ASdrq|ASbsy))
  595. return -1;
  596. return 0;
  597. }
  598. int
  599. ahcirecover(Aportc *pc)
  600. {
  601. ahciswreset(pc);
  602. pc->p->cmd |= Ast;
  603. if(setudmamode(pc, 5) == -1)
  604. return -1;
  605. return 0;
  606. }
  607. static void*
  608. malign(int size, int align)
  609. {
  610. void *v;
  611. v = xspanalloc(size, align, 0);
  612. memset(v, 0, size);
  613. return v;
  614. }
  615. static void
  616. setupfis(Afis *f)
  617. {
  618. f->base = malign(0x100, 0x100);
  619. f->d = f->base + 0;
  620. f->p = f->base + 0x20;
  621. f->r = f->base + 0x40;
  622. f->u = f->base + 0x60;
  623. f->devicebits = (u32int*)(f->base + 0x58);
  624. }
  625. static int
  626. ahciconfigdrive(Ahba *h, Aportc *c, int mode)
  627. {
  628. Aportm *m;
  629. Aport *p;
  630. p = c->p;
  631. m = c->m;
  632. if(m->list == 0){
  633. setupfis(&m->fis);
  634. m->list = malign(sizeof *m->list, 1024);
  635. m->ctab = malign(sizeof *m->ctab, 128);
  636. }
  637. if(p->sstatus & 3 && h->cap & Hsss){
  638. dprint("configdrive: spinning up ... [%ux]\n", p->sstatus);
  639. p->cmd |= Apod | Asud;
  640. asleep(1400);
  641. }
  642. p->serror = SerrAll;
  643. p->list = PCIWADDR(m->list);
  644. p->listhi = 0;
  645. p->fis = PCIWADDR(m->fis.base);
  646. p->fishi = 0;
  647. p->cmd |= Afre | Ast;
  648. /* disable power managment sequence from book. */
  649. p->sctl = (3*Aipm) | (mode*Aspd) | 0*Adet;
  650. p->cmd &= ~Aalpe;
  651. p->ie = IEM;
  652. return 0;
  653. }
  654. static int
  655. ahcienable(Ahba *h)
  656. {
  657. h->ghc |= Hie;
  658. return 0;
  659. }
  660. static int
  661. ahcidisable(Ahba *h)
  662. {
  663. h->ghc &= ~Hie;
  664. return 0;
  665. }
  666. static int
  667. countbits(ulong u)
  668. {
  669. int i, n;
  670. n = 0;
  671. for(i = 0; i < 32; i++)
  672. if(u & (1<<i))
  673. n++;
  674. return n;
  675. }
  676. static int
  677. ahciconf(Ctlr *c)
  678. {
  679. Ahba *h;
  680. u32int u;
  681. h = c->hba = (Ahba*)c->mmio;
  682. u = h->cap;
  683. if((u&Hsam) == 0)
  684. h->ghc |= Hae;
  685. print("ahci hba sss %d; ncs %d; coal %d; mports %d; led %d; clo %d; ems %d;\n",
  686. (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1,
  687. (u>>24) & 1, (u>>6) & 1);
  688. return countbits(h->pi);
  689. }
  690. static int
  691. ahcihbareset(Ahba *h)
  692. {
  693. int wait;
  694. h->ghc |= 1;
  695. for(wait = 0; wait < 1000; wait += 100){
  696. if(h->ghc == 0)
  697. return 0;
  698. delay(100);
  699. }
  700. return -1;
  701. }
  702. static void
  703. idmove(char *p, ushort *a, int n)
  704. {
  705. int i;
  706. char *op, *e;
  707. op = p;
  708. for(i = 0; i < n/2; i++){
  709. *p++ = a[i] >> 8;
  710. *p++ = a[i];
  711. }
  712. *p = 0;
  713. while(p > op && *--p == ' ')
  714. *p = 0;
  715. e = p;
  716. p = op;
  717. while(*p == ' ')
  718. p++;
  719. memmove(op, p, n - (e - p));
  720. }
  721. static int
  722. identify(Drive *d)
  723. {
  724. u16int *id;
  725. vlong osectors, s;
  726. uchar oserial[21];
  727. SDunit *u;
  728. id = d->info;
  729. s = ahciidentify(&d->portc, id);
  730. if(s == -1){
  731. d->state = Derror;
  732. return -1;
  733. }
  734. osectors = d->sectors;
  735. memmove(oserial, d->serial, sizeof d->serial);
  736. d->sectors = s;
  737. d->smartrs = 0;
  738. idmove(d->serial, id + 10, 20);
  739. idmove(d->firmware, id + 23, 8);
  740. idmove(d->model, id + 27, 40);
  741. u = d->unit;
  742. memset(u->inquiry, 0, sizeof u->inquiry);
  743. u->inquiry[2] = 2;
  744. u->inquiry[3] = 2;
  745. u->inquiry[4] = sizeof u->inquiry-4;
  746. memmove(u->inquiry+8, d->model, 40);
  747. if ((osectors == 0 || osectors != s) &&
  748. memcmp(oserial, d->serial, sizeof oserial) != 0){
  749. d->mediachange = 1;
  750. u->sectors = 0;
  751. }
  752. return 0;
  753. }
  754. static void
  755. clearci(Aport *p)
  756. {
  757. if((p->cmd & Ast) == 0)
  758. return;
  759. p->cmd &= ~Ast;
  760. p->cmd |= Ast;
  761. }
  762. static void
  763. updatedrive(Drive *d)
  764. {
  765. u32int cause, serr, s0, pr, ewake;
  766. char *name;
  767. Aport *p;
  768. static u32int last;
  769. pr = 1;
  770. ewake = 0;
  771. p = d->port;
  772. cause = p->isr;
  773. serr = p->serror;
  774. p->isr = cause;
  775. name = "??";
  776. if(d->unit && d->unit->name)
  777. name = d->unit->name;
  778. if(p->ci == 0){
  779. d->portm.flag |= Fdone;
  780. wakeup(&d->portm);
  781. pr = 0;
  782. }else if(cause&Adps)
  783. pr = 0;
  784. if(cause&Ifatal){
  785. ewake = 1;
  786. dprint("Fatal\n");
  787. }
  788. if(cause&Adhrs){
  789. if(p->task&33){
  790. dprint("Adhrs cause = %ux; serr = %ux; task=%ux\n",
  791. cause, serr, p->task);
  792. d->portm.flag |= Ferror;
  793. ewake = 1;
  794. }
  795. pr = 0;
  796. }
  797. // if(p->task & 1 && last != cause)
  798. // dprint("err ca %ux serr %ux task %ux sstat %ux\n",
  799. // cause, serr, p->task, p->sstatus);
  800. if(pr)
  801. dprint("%s: upd %ux ta %ux\n", name, cause, p->task);
  802. if(cause & (Aprcs|Aifs)){
  803. s0 = d->state;
  804. switch(p->sstatus & 7){
  805. case 0:
  806. d->state = Dmissing;
  807. break;
  808. case 1:
  809. d->state = Derror;
  810. break;
  811. case 3:
  812. /* power mgnt crap for suprise removal */
  813. p->ie |= Aprcs | Apcs; /* is this required? */
  814. d->state = Dreset;
  815. break;
  816. case 4:
  817. d->state = Doffline;
  818. break;
  819. }
  820. dprint("%s: %s → %s [Apcrs] %ux\n", name, diskstates[s0],
  821. diskstates[d->state], p->sstatus);
  822. /* print pulled message here. */
  823. if(d->state != Dready)
  824. d->portm.flag |= Ferror;
  825. ewake = 1;
  826. }
  827. p->serror = serr;
  828. if(ewake){
  829. clearci(p);
  830. wakeup(&d->portm);
  831. }
  832. last = cause;
  833. }
  834. static void
  835. pstatus(Drive *d, ulong s)
  836. {
  837. /*
  838. * bogus code because the first interrupt is currently dropped.
  839. * likely my fault. serror is may be cleared at the wrong time.
  840. */
  841. switch(s){
  842. case 0:
  843. d->state = Dmissing;
  844. break;
  845. case 2: /* should this be missing? need testcase. */
  846. dprint("pstatus 2\n");
  847. /* FALLTHROUGH */
  848. case 3:
  849. d->wait = 0;
  850. d->state = Dnew;
  851. break;
  852. case 4:
  853. d->state = Doffline;
  854. break;
  855. }
  856. }
  857. static int
  858. configdrive(Drive *d)
  859. {
  860. if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
  861. return -1;
  862. ilock(d);
  863. pstatus(d, d->port->sstatus & 7);
  864. iunlock(d);
  865. return 0;
  866. }
  867. static void
  868. resetdisk(Drive *d)
  869. {
  870. uint state, det, stat;
  871. Aport *p;
  872. p = d->port;
  873. det = p->sctl & 7;
  874. stat = p->sstatus & 7;
  875. state = (p->cmd >> 28) & 0xf;
  876. dprint("resetdisk: icc %ux det %d sdet %d\n", state, det, stat);
  877. if(stat != 3){
  878. ilock(d);
  879. d->state = Dportreset;
  880. iunlock(d);
  881. return;
  882. }
  883. ilock(d);
  884. state = d->state;
  885. if(d->state != Dready || d->state != Dnew)
  886. d->portm.flag |= Ferror;
  887. clearci(p); /* satisfy sleep condition */
  888. wakeup(&d->portm);
  889. iunlock(d);
  890. qlock(&d->portm);
  891. if(p->cmd & Ast && ahciswreset(&d->portc) == -1){
  892. ilock(d);
  893. d->state = Dportreset; /* get a bigger stick */
  894. iunlock(d);
  895. } else {
  896. ilock(d);
  897. d->state = Dmissing;
  898. iunlock(d);
  899. configdrive(d);
  900. }
  901. dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]);
  902. qunlock(&d->portm);
  903. }
  904. static int
  905. newdrive(Drive *d)
  906. {
  907. char *name, *s;
  908. Aportc *c;
  909. Aportm *m;
  910. c = &d->portc;
  911. m = &d->portm;
  912. name = d->unit->name;
  913. if(name == 0)
  914. name = "??";
  915. if(d->port->task == 0x80)
  916. return -1;
  917. qlock(c->m);
  918. if(setudmamode(c, 5) == -1){
  919. dprint("%s: can't set udma mode\n", name);
  920. goto loose;
  921. }
  922. if(identify(d) == -1){
  923. dprint("%s: identify failure\n", name);
  924. goto loose;
  925. }
  926. if(m->feat &Dpower && setfeatures(c, 0x85) == -1){
  927. m->feat &= ~Dpower;
  928. if(ahcirecover(c) == -1)
  929. goto loose;
  930. }
  931. ilock(d);
  932. d->state = Dready;
  933. iunlock(d);
  934. qunlock(c->m);
  935. s = "";
  936. if(m->feat & Dllba)
  937. s = "L";
  938. idprint("%s: %sLBA %,lld sectors\n", d->unit->name, s, d->sectors);
  939. idprint(" %s %s %s %s\n", d->model, d->firmware, d->serial,
  940. d->mediachange?"[mediachange]":"");
  941. return 0;
  942. loose:
  943. qunlock(&d->portm);
  944. return -1;
  945. }
  946. enum{
  947. Nms = 256,
  948. Mphywait = 2*1024/Nms - 1,
  949. Midwait = 16*1024/Nms - 1,
  950. Mcomrwait = 64*1024/Nms - 1,
  951. };
  952. static void
  953. westerndigitalhung(Drive *d)
  954. {
  955. if ((d->portm.feat & Datapi) == 0 && d->active &&
  956. TK2MS(MACHP(0)->ticks-d->intick) > 5000){
  957. dprint("%s: drive hung; resetting [%ux] ci=%x\n",
  958. d->unit->name, d->port->task, d->port->ci);
  959. d->state = Dreset;
  960. }
  961. }
  962. static ushort olds[NCtlr*NCtlrdrv];
  963. static int
  964. doportreset(Drive *d)
  965. {
  966. int i;
  967. i = -1;
  968. qlock(&d->portm);
  969. if(ahciportreset(&d->portc) == -1)
  970. dprint("ahciportreset fails\n");
  971. else
  972. i = 0;
  973. qunlock(&d->portm);
  974. dprint("portreset → %s [task %ux]\n", diskstates[d->state],
  975. d->port->task);
  976. return i;
  977. }
  978. static void
  979. checkdrive(Drive *d, int i)
  980. {
  981. ushort s;
  982. char *name;
  983. ilock(d);
  984. name = d->unit->name;
  985. s = d->port->sstatus;
  986. if(s != olds[i]){
  987. dprint("%s: status: %04ux -> %04ux: %s\n", name, olds[i], s,
  988. diskstates[d->state]);
  989. olds[i] = s;
  990. d->wait = 0;
  991. }
  992. westerndigitalhung(d);
  993. switch(d->state){
  994. case Dnull:
  995. break;
  996. case Dmissing:
  997. case Dnew:
  998. switch(s & 0x107){
  999. case 0:
  1000. case 1:
  1001. break;
  1002. default:
  1003. dprint("%s: unknown status %04ux\n", name, s);
  1004. case 0x100:
  1005. if(++d->wait & Mphywait)
  1006. break;
  1007. reset:
  1008. if(++d->mode > DMsataii)
  1009. d->mode = 0;
  1010. if(d->mode == DMsatai){ /* we tried everything */
  1011. d->state = Dportreset;
  1012. goto portreset;
  1013. }
  1014. dprint("%s: reset; new mode %s\n", name,
  1015. modename[d->mode]);
  1016. iunlock(d);
  1017. resetdisk(d);
  1018. ilock(d);
  1019. break;
  1020. case 0x103:
  1021. if((++d->wait & Midwait) == 0){
  1022. dprint("%s: slow reset %04ux task=%ux; %d\n",
  1023. name, s, d->port->task, d->wait);
  1024. goto reset;
  1025. }
  1026. s = d->port->task & 0xff;
  1027. if(s == 0x7f || (s & ~0x17) != (1<<6))
  1028. break;
  1029. iunlock(d);
  1030. newdrive(d);
  1031. ilock(d);
  1032. }
  1033. break;
  1034. case Dready:
  1035. break;
  1036. case Doffline:
  1037. if(d->wait++ & Mcomrwait)
  1038. break;
  1039. case Derror:
  1040. case Dreset:
  1041. dprint("%s: reset [%s]: mode %d; status %04ux\n", name,
  1042. diskstates[d->state], d->mode, s);
  1043. iunlock(d);
  1044. resetdisk(d);
  1045. ilock(d);
  1046. break;
  1047. case Dportreset:
  1048. portreset:
  1049. dprint("%s: portreset [%s]: mode %d; status %04ux\n", name,
  1050. diskstates[d->state], d->mode, s);
  1051. d->portm.flag |= Ferror;
  1052. clearci(d->port);
  1053. wakeup(&d->portm);
  1054. if((s & 7) == 0){
  1055. d->state = Dmissing;
  1056. break;
  1057. }
  1058. iunlock(d);
  1059. doportreset(d);
  1060. ilock(d);
  1061. break;
  1062. }
  1063. iunlock(d);
  1064. }
  1065. static void
  1066. satakproc(void*)
  1067. {
  1068. int i;
  1069. memset(olds, 0xff, sizeof olds);
  1070. for (; ; ){
  1071. tsleep(&up->sleep, return0, 0, Nms);
  1072. for(i = 0; i < niadrive; i++)
  1073. checkdrive(iadrive[i], i);
  1074. }
  1075. }
  1076. static void
  1077. iainterrupt(Ureg*, void *a)
  1078. {
  1079. int i;
  1080. ulong cause, m;
  1081. Ctlr *c;
  1082. Drive *d;
  1083. c = a;
  1084. ilock(c);
  1085. cause = c->hba->isr;
  1086. for(i = 0; i < c->ndrive; i++){
  1087. m = 1<<i;
  1088. if((cause & m) == 0)
  1089. continue;
  1090. d = c->rawdrive+i;
  1091. ilock(d);
  1092. if(d->port->isr && c->hba->pi & m)
  1093. updatedrive(d);
  1094. c->hba->isr = m;
  1095. iunlock(d);
  1096. }
  1097. iunlock(c);
  1098. }
  1099. static int
  1100. iaverify(SDunit *u)
  1101. {
  1102. Ctlr *c;
  1103. Drive *d;
  1104. c = u->dev->ctlr;
  1105. d = c->drive[u->subno];
  1106. ilock(c);
  1107. ilock(d);
  1108. d->unit = u;
  1109. iunlock(d);
  1110. iunlock(c);
  1111. return 1;
  1112. }
  1113. static int
  1114. iaenable(SDev *s)
  1115. {
  1116. char name[32];
  1117. Ctlr *c;
  1118. static int once;
  1119. c = s->ctlr;
  1120. ilock(c);
  1121. if(!c->enabled) {
  1122. if(once++ == 0)
  1123. kproc("iasata", satakproc, 0);
  1124. pcisetbme(c->pci);
  1125. snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name);
  1126. intrenable(c->irq, iainterrupt, c, c->tbdf, name);
  1127. /* supposed to squelch leftover interrupts here. */
  1128. ahcienable(c->hba);
  1129. }
  1130. c->enabled = 1;
  1131. iunlock(c);
  1132. return 1;
  1133. }
  1134. static int
  1135. iadisable(SDev *s)
  1136. {
  1137. char name[32];
  1138. Ctlr *c;
  1139. c = s->ctlr;
  1140. ilock(c);
  1141. ahcidisable(c->hba);
  1142. snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name);
  1143. intrdisable(c->irq, iainterrupt, c, c->tbdf, name);
  1144. c->enabled = 0;
  1145. iunlock(c);
  1146. return 1;
  1147. }
  1148. static int
  1149. iaonline(SDunit *unit)
  1150. {
  1151. ulong r;
  1152. Ctlr *c;
  1153. Drive *d;
  1154. c = unit->dev->ctlr;
  1155. d = c->drive[unit->subno];
  1156. r = 0;
  1157. if((d->portm.feat & Datapi) && d->mediachange){
  1158. r = scsionline(unit);
  1159. if(r > 0)
  1160. d->mediachange = 0;
  1161. return r;
  1162. }
  1163. ilock(d);
  1164. if(d->mediachange){
  1165. r = 2;
  1166. d->mediachange = 0;
  1167. /* devsd resets this after online is called; why? */
  1168. unit->sectors = d->sectors;
  1169. unit->secsize = 512;
  1170. } else if(d->state == Dready)
  1171. r = 1;
  1172. iunlock(d);
  1173. return r;
  1174. }
  1175. /* returns locked list! */
  1176. static Alist*
  1177. ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba)
  1178. {
  1179. uchar *c, acmd, dir, llba;
  1180. Actab *t;
  1181. Alist *l;
  1182. Aprdt *p;
  1183. static uchar tab[2][2] = {0xc8, 0x25, 0xca, 0x35};
  1184. dir = *cmd != 0x28;
  1185. llba = m->feat & Dllba? 1: 0;
  1186. acmd = tab[dir][llba];
  1187. qlock(m);
  1188. l = m->list;
  1189. t = m->ctab;
  1190. c = t->cfis;
  1191. c[0] = 0x27;
  1192. c[1] = 0x80;
  1193. c[2] = acmd;
  1194. c[3] = 0;
  1195. c[4] = lba; /* sector lba low 7:0 */
  1196. c[5] = lba >> 8; /* cylinder low lba mid 15:8 */
  1197. c[6] = lba >> 16; /* cylinder hi lba hi 23:16 */
  1198. c[7] = 0xa0 | 0x40; /* obsolete device bits + lba */
  1199. if(llba == 0)
  1200. c[7] |= (lba >> 24) & 7;
  1201. c[8] = lba >> 24; /* sector (exp) lba 31:24 */
  1202. c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */
  1203. c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */
  1204. c[11] = 0; /* features (exp); */
  1205. c[12] = n; /* sector count */
  1206. c[13] = n >> 8; /* sector count (exp) */
  1207. c[14] = 0; /* r */
  1208. c[15] = 0; /* control */
  1209. *(ulong*)(c + 16) = 0;
  1210. l->flags = 1<<16 | Lpref | 0x5; /* Lpref ?? */
  1211. if(dir == Write)
  1212. l->flags |= Lwrite;
  1213. l->len = 0;
  1214. l->ctab = PCIWADDR(t);
  1215. l->ctabhi = 0;
  1216. p = &t->prdt;
  1217. p->dba = PCIWADDR(data);
  1218. p->dbahi = 0;
  1219. p->count = 1<<31 | (512*n - 2) | 1;
  1220. return l;
  1221. }
  1222. static Alist*
  1223. ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
  1224. {
  1225. int fill, len;
  1226. uchar *c;
  1227. Actab *t;
  1228. Alist *l;
  1229. Aprdt *p;
  1230. qlock(m);
  1231. l = m->list;
  1232. t = m->ctab;
  1233. c = t->cfis;
  1234. fill = m->feat & Datapi16? 16: 12;
  1235. if((len = r->clen) > fill)
  1236. len = fill;
  1237. memmove(t->atapi, r->cmd, len);
  1238. memset(t->atapi+len, 0, fill-len);
  1239. c[0] = 0x27;
  1240. c[1] = 0x80;
  1241. c[2] = 0xa0;
  1242. if(n != 0)
  1243. c[3] = 1; /* dma */
  1244. else
  1245. c[3] = 0; /* features (exp); */
  1246. c[4] = 0; /* sector lba low 7:0 */
  1247. c[5] = n; /* cylinder low lba mid 15:8 */
  1248. c[6] = n >> 8; /* cylinder hi lba hi 23:16 */
  1249. c[7] = 0xa0; /* obsolete device bits */
  1250. *(ulong*)(c + 8) = 0;
  1251. // c[8] = lba >> 24; /* sector (exp) lba 31:24 */
  1252. // c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */
  1253. // c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */
  1254. // c[11] = 0;
  1255. *(ulong*)(c + 12) = 0;
  1256. *(ulong*)(c + 16) = 0;
  1257. l->flags = 1<<16 | Lpref | Latapi | 0x5;
  1258. if(r->write != 0)
  1259. l->flags |= Lwrite;
  1260. l->len = 0;
  1261. l->ctab = PCIWADDR(t);
  1262. l->ctabhi = 0;
  1263. p = &t->prdt;
  1264. p->dba = PCIWADDR(data);
  1265. p->dbahi = 0;
  1266. p->count = 1<<31 | (n-2) | 1;
  1267. return l;
  1268. }
  1269. static int
  1270. waitready(Drive *d)
  1271. {
  1272. u32int s, t, i;
  1273. for(i = 0; i < 120; i++){
  1274. ilock(d);
  1275. s = d->port->sstatus;
  1276. t = d->port->task;
  1277. iunlock(d);
  1278. if((s & 0x100) == 0)
  1279. return -1;
  1280. if(d->state == Dready && (s & 7) == 3)
  1281. return 0;
  1282. if((i+1) % 30 == 0)
  1283. print("%s: waitready: [%s] task=%ux sstat=%ux\n",
  1284. d->unit->name, diskstates[d->state], t, s);
  1285. esleep(1000);
  1286. }
  1287. print("%s: not responding; offline\n", d->unit->name);
  1288. ilock(d);
  1289. d->state = Doffline;
  1290. iunlock(d);
  1291. return -1;
  1292. }
  1293. static int
  1294. iariopkt(SDreq *r, Drive *d)
  1295. {
  1296. int n, count, try, max, flag, task;
  1297. char *name;
  1298. uchar *cmd, *data;
  1299. Aport *p;
  1300. Asleep as;
  1301. cmd = r->cmd;
  1302. name = d->unit->name;
  1303. p = d->port;
  1304. aprint("%02ux %02ux\n", cmd[0], cmd[2]);
  1305. if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
  1306. return sdmodesense(r, cmd, d->info, sizeof d->info);
  1307. r->rlen = 0;
  1308. count = r->dlen;
  1309. max = 65536;
  1310. try = 0;
  1311. retry:
  1312. if(waitready(d) == -1)
  1313. return SDeio;
  1314. data = r->data;
  1315. n = count;
  1316. if(n > max)
  1317. n = max;
  1318. d->active++;
  1319. ahcibuildpkt(&d->portm, r, data, n);
  1320. ilock(d);
  1321. d->portm.flag = 0;
  1322. iunlock(d);
  1323. p->ci = 1;
  1324. as.p = p;
  1325. as.i = 1;
  1326. d->intick = MACHP(0)->ticks;
  1327. while(waserror())
  1328. ;
  1329. sleep(&d->portm, ahciclear, &as);
  1330. poperror();
  1331. ilock(d);
  1332. flag = d->portm.flag;
  1333. task = d->port->task;
  1334. iunlock(d);
  1335. if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
  1336. d->port->ci = 0; /* @? */
  1337. ahcirecover(&d->portc);
  1338. task = d->port->task;
  1339. }
  1340. d->active--;
  1341. qunlock(&d->portm);
  1342. if(flag == 0){
  1343. if(++try == 10){
  1344. print("%s: bad disk\n", name);
  1345. r->status = SDcheck;
  1346. return SDcheck;
  1347. }
  1348. iprint("%s: retry\n", name);
  1349. esleep(1000);
  1350. goto retry;
  1351. }
  1352. if(flag&Ferror){
  1353. iprint("%s: i/o error %ux\n", name, task);
  1354. r->status = SDcheck;
  1355. return SDcheck;
  1356. }
  1357. data += n;
  1358. r->rlen = data - (uchar*)r->data;
  1359. r->status = SDok;
  1360. return SDok;
  1361. }
  1362. static int
  1363. iario(SDreq *r)
  1364. {
  1365. int i, n, count, try, max, flag, task;
  1366. vlong lba;
  1367. char *name;
  1368. uchar *cmd, *data;
  1369. Aport *p;
  1370. Asleep as;
  1371. Ctlr *c;
  1372. Drive *d;
  1373. SDunit *unit;
  1374. unit = r->unit;
  1375. c = unit->dev->ctlr;
  1376. d = c->drive[unit->subno];
  1377. if(d->portm.feat & Datapi)
  1378. return iariopkt(r, d);
  1379. cmd = r->cmd;
  1380. name = d->unit->name;
  1381. p = d->port;
  1382. if(r->cmd[0] == 0x35){
  1383. qlock(&d->portm);
  1384. i = flushcache(&d->portc);
  1385. qunlock(&d->portm);
  1386. if(i == 0)
  1387. return sdsetsense(r, SDok, 0, 0, 0);
  1388. return sdsetsense(r, SDcheck, 3, 0xc, 2);
  1389. }
  1390. if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
  1391. r->status = i;
  1392. return i;
  1393. }
  1394. if(*cmd != 0x28 && *cmd != 0x2a){
  1395. print("%s: bad cmd 0x%.2ux\n", name, cmd[0]);
  1396. r->status = SDcheck;
  1397. return SDcheck;
  1398. }
  1399. lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
  1400. count = cmd[7]<<8 | cmd[8];
  1401. if(r->data == nil)
  1402. return SDok;
  1403. if(r->dlen < count*unit->secsize)
  1404. count = r->dlen/unit->secsize;
  1405. max = 128;
  1406. try = 0;
  1407. retry:
  1408. if(waitready(d) == -1)
  1409. return SDeio;
  1410. data = r->data;
  1411. while(count > 0){
  1412. n = count;
  1413. if(n > max)
  1414. n = max;
  1415. d->active++;
  1416. ahcibuild(&d->portm, cmd, data, n, lba);
  1417. ilock(d);
  1418. d->portm.flag = 0;
  1419. iunlock(d);
  1420. p->ci = 1;
  1421. as.p = p;
  1422. as.i = 1;
  1423. d->intick = MACHP(0)->ticks;
  1424. while(waserror())
  1425. ;
  1426. sleep(&d->portm, ahciclear, &as);
  1427. poperror();
  1428. ilock(d);
  1429. flag = d->portm.flag;
  1430. task = d->port->task;
  1431. iunlock(d);
  1432. if (task & (Efatal<<8) || task & (ASbsy|ASdrq) &&
  1433. d->state == Dready){
  1434. d->port->ci = 0; /* @? */
  1435. ahcirecover(&d->portc);
  1436. task = d->port->task;
  1437. }
  1438. d->active--;
  1439. qunlock(&d->portm);
  1440. if(flag == 0){
  1441. if(++try == 10){
  1442. print("%s: bad disk\n", name);
  1443. r->status = SDeio;
  1444. return SDeio;
  1445. }
  1446. iprint("%s: retry %lld\n", name, lba);
  1447. esleep(1000);
  1448. goto retry;
  1449. }
  1450. if(flag & Ferror){
  1451. iprint("%s: i/o error %ux @%,lld\n", name, task, lba);
  1452. r->status = SDeio;
  1453. return SDeio;
  1454. }
  1455. count -= n;
  1456. lba += n;
  1457. data += n * unit->secsize;
  1458. }
  1459. r->rlen = data - (uchar*)r->data;
  1460. r->status = SDok;
  1461. return SDok;
  1462. }
  1463. /*
  1464. * configure drives 0-5 as ahci sata (c.f. errata)
  1465. */
  1466. static int
  1467. iaahcimode(Pcidev *p)
  1468. {
  1469. dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91), pcicfgr8(p, 92),
  1470. pcicfgr8(p, 93));
  1471. pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf); /* ports 0-3 */
  1472. // pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3); /* ports 4-5 */
  1473. return 0;
  1474. }
  1475. static void
  1476. iasetupahci(Ctlr *c)
  1477. {
  1478. /* disable cmd block decoding. */
  1479. pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
  1480. pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
  1481. c->lmmio[0x4/4] |= 1<<31; /* enable ahci mode (ghc register) */
  1482. c->lmmio[0xc/4] = (1<<6)-1; /* 5 ports (supposedly ro pi reg) */
  1483. /* enable ahci mode. */
  1484. // pcicfgw8(c->pci, 0x90, 0x40);
  1485. pcicfgw16(c->pci, 0x90, 1<<6 | 1<<5); /* pedanticly proper for ich9 */
  1486. }
  1487. static SDev*
  1488. iapnp(void)
  1489. {
  1490. int i, n, nunit;
  1491. ulong io;
  1492. Ctlr *c;
  1493. Drive *d;
  1494. Pcidev *p;
  1495. SDev *head, *tail, *s;
  1496. static int done;
  1497. if(done++)
  1498. return nil;
  1499. p = nil;
  1500. head = nil;
  1501. tail = nil;
  1502. loop:
  1503. while((p = pcimatch(p, 0x8086, 0)) != nil){
  1504. if ((p->did&0xfffc) != 0x2680 && /* esb */
  1505. (p->did&0xfffe) != 0x27c4) /* 82801g[bh]m */
  1506. continue;
  1507. if(niactlr == NCtlr){
  1508. print("iapnp: too many controllers\n");
  1509. break;
  1510. }
  1511. c = iactlr + niactlr;
  1512. s = sdevs + niactlr;
  1513. memset(c, 0, sizeof *c);
  1514. memset(s, 0, sizeof *s);
  1515. io = p->mem[Abar].bar & ~0xf;
  1516. c->mmio = vmap(io, p->mem[0].size);
  1517. if(c->mmio == 0){
  1518. print("iapnp: address 0x%luX in use did=%x\n", io,
  1519. p->did);
  1520. continue;
  1521. }
  1522. c->lmmio = (ulong*)c->mmio;
  1523. c->pci = p;
  1524. if(p->did != 0x2681)
  1525. iasetupahci(c);
  1526. nunit = ahciconf(c);
  1527. /* ahcihbareset((Ahba*)c->mmio); */
  1528. if(iaahcimode(p) == -1)
  1529. break;
  1530. if(nunit < 1){
  1531. vunmap(c->mmio, p->mem[0].size);
  1532. continue;
  1533. }
  1534. i = (c->hba->cap >> 21) & 1;
  1535. print("intel 63[12]xesb: sata-%s ports with %d ports\n",
  1536. "I\0II" + i*2, nunit);
  1537. s->ifc = &sd63xxesbifc;
  1538. s->ctlr = c;
  1539. s->nunit = nunit;
  1540. s->idno = 'E';
  1541. c->sdev = s;
  1542. c->irq = p->intl;
  1543. c->tbdf = p->tbdf;
  1544. c->ndrive = nunit;
  1545. /* map the drives -- they don't all need to be enabled. */
  1546. memset(c->rawdrive, 0, sizeof c->rawdrive);
  1547. n = 0;
  1548. for(i = 0; i < NCtlrdrv; i++) {
  1549. d = c->rawdrive+i;
  1550. d->portno = i;
  1551. d->driveno = -1;
  1552. d->sectors = 0;
  1553. d->ctlr = c;
  1554. if((c->hba->pi & (1 << i)) == 0)
  1555. continue;
  1556. d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
  1557. d->portc.p = d->port;
  1558. d->portc.m = &d->portm;
  1559. d->driveno = n++;
  1560. c->drive[i] = d;
  1561. iadrive[d->driveno] = d;
  1562. }
  1563. for(i = 0; i < n; i++)
  1564. if(ahciidle(c->drive[i]->port) == -1){
  1565. dprint("intel 63[12]xesb: port %d wedged; abort\n",
  1566. i);
  1567. goto loop;
  1568. }
  1569. for(i = 0; i < n; i++){
  1570. c->drive[i]->mode = DMsatai;
  1571. configdrive(c->drive[i]);
  1572. }
  1573. niadrive += nunit;
  1574. if(head)
  1575. tail->next = s;
  1576. else
  1577. head = s;
  1578. tail = s;
  1579. }
  1580. return head;
  1581. }
  1582. static char* smarttab[] = {
  1583. "unset",
  1584. "error",
  1585. "threshold exceeded",
  1586. "normal"
  1587. };
  1588. static char *
  1589. pflag(char *s, char *e, uchar f)
  1590. {
  1591. uchar i, m;
  1592. for(i = 0; i < 8; i++){
  1593. m = 1 << i;
  1594. if(f & m)
  1595. s = seprint(s, e, "%s ", flagname[i]);
  1596. }
  1597. return seprint(s, e, "\n");
  1598. }
  1599. static int
  1600. iarctl(SDunit *u, char *p, int l)
  1601. {
  1602. char *e, *op;
  1603. char buf[32];
  1604. Aport *o;
  1605. Ctlr *c;
  1606. Drive *d;
  1607. if((c = u->dev->ctlr) == nil)
  1608. return 0;
  1609. d = c->drive[u->subno];
  1610. o = d->port;
  1611. e = p+l;
  1612. op = p;
  1613. if(d->state == Dready){
  1614. p = seprint(p, e, "model\t%s\n", d->model);
  1615. p = seprint(p, e, "serial\t%s\n", d->serial);
  1616. p = seprint(p, e, "firm\t%s\n", d->firmware);
  1617. if(d->smartrs == 0xff)
  1618. p = seprint(p, e, "smart\tenable error\n");
  1619. else if(d->smartrs == 0)
  1620. p = seprint(p, e, "smart\tdisabled\n");
  1621. else
  1622. p = seprint(p, e, "smart\t%s\n",
  1623. smarttab[d->portm.smart]);
  1624. p = seprint(p, e, "flag\t");
  1625. p = pflag(p, e, d->portm.feat);
  1626. }else
  1627. p = seprint(p, e, "no disk present [%s]\n", diskstates[d->state]);
  1628. serrstr(o->serror, buf, buf + sizeof buf - 1);
  1629. p = seprint(p, e, "reg\ttask %ux cmd %ux serr %ux %s ci %ux is %ux; sig %ux\n",
  1630. o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig);
  1631. p = seprint(p, e, "geometry %llud 512\n", d->sectors);
  1632. return p-op;
  1633. }
  1634. static void
  1635. runflushcache(Drive *d)
  1636. {
  1637. long t0;
  1638. t0 = MACHP(0)->ticks;
  1639. qlock(&d->portm);
  1640. flushcache(&d->portc);
  1641. qunlock(&d->portm);
  1642. dprint("flush in %ldms\n", TK2MS(MACHP(0)->ticks - t0));
  1643. }
  1644. static void
  1645. forcemode(Drive *d, char *mode)
  1646. {
  1647. int i;
  1648. for(i = 0; i < nelem(modename); i++)
  1649. if(strcmp(mode, modename[i]) == 0)
  1650. break;
  1651. if(i == nelem(modename))
  1652. i = 0;
  1653. ilock(d);
  1654. d->mode = i;
  1655. iunlock(d);
  1656. }
  1657. static void
  1658. runsmartable(Drive *d, int i)
  1659. {
  1660. if(waserror()){
  1661. qunlock(&d->portm);
  1662. d->smartrs = 0;
  1663. nexterror();
  1664. }
  1665. qlock(&d->portm);
  1666. d->smartrs = smart(&d->portc, i);
  1667. d->portm.smart = 0;
  1668. qunlock(&d->portm);
  1669. poperror();
  1670. }
  1671. static void
  1672. forcestate(Drive *d, char *state)
  1673. {
  1674. int i;
  1675. for(i = 0; i < nelem(diskstates); i++)
  1676. if(strcmp(state, diskstates[i]) == 0)
  1677. break;
  1678. if(i == nelem(diskstates))
  1679. i = 0;
  1680. ilock(d);
  1681. d->state = i;
  1682. if(i == Dnull){
  1683. d->mediachange = 1;
  1684. d->unit->sectors = 0; /* force disk to disappear */
  1685. }
  1686. iunlock(d);
  1687. }
  1688. static int
  1689. iawctl(SDunit *u, Cmdbuf *cmd)
  1690. {
  1691. char **f;
  1692. Ctlr *c;
  1693. Drive *d;
  1694. c = u->dev->ctlr;
  1695. d = c->drive[u->subno];
  1696. f = cmd->f;
  1697. if(strcmp(f[0], "flushcache") == 0)
  1698. runflushcache(d);
  1699. else if(strcmp(f[0], "identify") == 0){
  1700. uint i;
  1701. i = strtoul(f[1]? f[1]: "0", 0, 0);
  1702. if(i > 0xff)
  1703. i = 0;
  1704. dprint("%04d %ux\n", i, d->info[i]);
  1705. }else if(strcmp(f[0], "mode") == 0)
  1706. forcemode(d, f[1]? f[1]: "satai");
  1707. else if(strcmp(f[0], "nop") == 0){
  1708. if((d->portm.feat & Dnop) == 0){
  1709. cmderror(cmd, "nop command not supported");
  1710. return -1;
  1711. }
  1712. if(waserror()){
  1713. qunlock(&d->portm);
  1714. nexterror();
  1715. }
  1716. qlock(&d->portm);
  1717. nop(&d->portc);
  1718. qunlock(&d->portm);
  1719. poperror();
  1720. }else if(strcmp(f[0], "reset") == 0)
  1721. forcestate(d, "reset");
  1722. else if(strcmp(f[0], "smart") == 0){
  1723. if(d->smartrs == 0){
  1724. cmderror(cmd, "smart not enabled");
  1725. return -1;
  1726. }
  1727. if(waserror()){
  1728. qunlock(&d->portm);
  1729. d->smartrs = 0;
  1730. nexterror();
  1731. }
  1732. qlock(&d->portm);
  1733. d->portm.smart = 2 + smartrs(&d->portc);
  1734. qunlock(&d->portm);
  1735. poperror();
  1736. }else if(strcmp(f[0], "smartdisable") == 0)
  1737. runsmartable(d, 1);
  1738. else if(strcmp(f[0], "smartenable") == 0)
  1739. runsmartable(d, 0);
  1740. else if(strcmp(f[0], "state") == 0)
  1741. forcestate(d, f[1]? f[1]: "null");
  1742. else{
  1743. cmderror(cmd, Ebadctl);
  1744. return -1;
  1745. }
  1746. return 0;
  1747. }
  1748. static char *
  1749. portr(char *p, char *e, uint x)
  1750. {
  1751. int i, a;
  1752. p[0] = 0;
  1753. a = -1;
  1754. for(i = 0; i < 32; i++){
  1755. if((x & (1 << i)) == 0){
  1756. if(a != -1 && i - 1 != a)
  1757. p = seprint(p, e, "-%d", i - 1);
  1758. a = -1;
  1759. continue;
  1760. }
  1761. if(a == -1){
  1762. if(i > 0)
  1763. p = seprint(p, e, ", ");
  1764. p = seprint(p, e, "%d", a = i);
  1765. }
  1766. }
  1767. if(a != -1 && i - 1 != a)
  1768. p = seprint(p, e, "-%d", i - 1);
  1769. return p;
  1770. }
  1771. #define has(x, s) if(u & (x)) p = seprint(p, e, (s))
  1772. static char*
  1773. iartopctl(SDev *s, char *p, char *e)
  1774. {
  1775. u32int u;
  1776. char name[10], pr[25];
  1777. Ahba *h;
  1778. Ctlr *c;
  1779. c = s->ctlr;
  1780. snprint(name, sizeof name, "sd%c", s->idno);
  1781. p = seprint(p, e, "%s ahci ", name);
  1782. u = c->hba->cap;
  1783. has(Hs64a, "64a ");
  1784. has(Hsncq, "ncq ");
  1785. has(Hssntf, "ntf ");
  1786. has(Hsmps, "mps ");
  1787. has(Hsss, "ss ");
  1788. has(Hsalp, "alp ");
  1789. has(Hsal, "led ");
  1790. has(Hsclo, "clo ");
  1791. has(Hsam, "am ");
  1792. has(Hspm, "pm ");
  1793. has(Hssc, "slum ");
  1794. has(Hpsc, "pslum ");
  1795. has(Hcccs, "coal ");
  1796. has(Hems, "ems ");
  1797. has(Hsxs, "sxs ");
  1798. p = seprint(p, e, "\n");
  1799. p = seprint(p, e, "%s iss %d ncs %d np %d\n", name, (u >> 20) & 0xf,
  1800. (u >> 8) & 0x1f, 1 + (u & 0x1f));
  1801. h = c->hba;
  1802. portr(pr, pr+sizeof pr, h->pi);
  1803. p = seprint(p, e, "%s ghc %ux isr %ux pi %ux %s ver %ux\n",
  1804. name, h->ghc, h->isr, h->pi, pr, h->ver);
  1805. return p;
  1806. }
  1807. static int
  1808. iawtopctl(SDev *, Cmdbuf *cmd)
  1809. {
  1810. char **f;
  1811. int *v;
  1812. f = cmd->f;
  1813. v = 0;
  1814. if(strcmp(f[0], "debug") == 0)
  1815. v = &debug;
  1816. else if(strcmp(f[0], "idprint") == 0)
  1817. v = &prid;
  1818. else if(strcmp(f[0], "aprint") == 0)
  1819. v = &datapi;
  1820. else
  1821. cmderror(cmd, Ebadctl);
  1822. switch(cmd->nf){
  1823. default:
  1824. cmderror(cmd, Ebadarg);
  1825. case 1:
  1826. *v ^= 1;
  1827. break;
  1828. case 2:
  1829. if(strcmp(f[1], "on") == 0)
  1830. *v = 1;
  1831. else
  1832. *v = 0;
  1833. break;
  1834. }
  1835. return 0;
  1836. }
  1837. SDifc sd63xxesbifc = {
  1838. "iahci",
  1839. iapnp,
  1840. nil, /* legacy */
  1841. iaenable,
  1842. iadisable,
  1843. iaverify,
  1844. iaonline,
  1845. iario,
  1846. iarctl,
  1847. iawctl,
  1848. scsibio,
  1849. nil, /* probe */
  1850. nil, /* clear */
  1851. iartopctl,
  1852. iawtopctl,
  1853. };