sdiahci.c 40 KB

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