pcmcia.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. #include <u.h>
  2. #include <libc.h>
  3. enum
  4. {
  5. End = 0xff,
  6. };
  7. int fd;
  8. int pos;
  9. void tdevice(int, int);
  10. void tcfig(int, int);
  11. void tentry(int, int);
  12. void tvers1(int, int);
  13. void (*parse[256])(int, int) =
  14. {
  15. [1] tdevice,
  16. [0x15] tvers1,
  17. [0x17] tdevice,
  18. [0x1A] tcfig,
  19. [0x1B] tentry,
  20. };
  21. int hex;
  22. void
  23. fatal(char *fmt, ...)
  24. {
  25. va_list arg;
  26. char buf[512];
  27. va_start(arg, fmt);
  28. vseprint(buf, buf+sizeof(buf), fmt, arg);
  29. va_end(arg);
  30. fprint(2, "pcmcia: %s\n", buf);
  31. exits(buf);
  32. }
  33. int
  34. readc(void *x)
  35. {
  36. int rv;
  37. seek(fd, 2*pos, 0);
  38. pos++;
  39. rv = read(fd, x, 1);
  40. if(hex)
  41. print("%2.2ux ", *(uchar*)x);
  42. return rv;
  43. }
  44. int
  45. tuple(int next)
  46. {
  47. uchar link;
  48. uchar type;
  49. pos = next;
  50. if(readc(&type) != 1)
  51. return -1;
  52. if(type == 0xff)
  53. return -1;
  54. if(readc(&link) != 1)
  55. return -1;
  56. if(parse[type])
  57. (*parse[type])(type, link);
  58. if(link == 0xff)
  59. next = -1;
  60. else
  61. next = next+2+link;
  62. return next;
  63. }
  64. void
  65. main(int argc, char *argv[])
  66. {
  67. char *file;
  68. int next;
  69. ARGBEGIN{
  70. case 'x':
  71. hex = 1;
  72. }ARGEND;
  73. if(argc == 0)
  74. file = "#y/pcm0attr";
  75. else
  76. file = argv[0];
  77. fd = open(file, OREAD);
  78. if(fd < 0)
  79. fatal("opening %s: %r", file);
  80. for(next = 0; next >= 0;)
  81. next = tuple(next);
  82. }
  83. ulong speedtab[16] =
  84. {
  85. [1] 250,
  86. [2] 200,
  87. [3] 150,
  88. [4] 100,
  89. };
  90. ulong mantissa[16] =
  91. {
  92. [1] 10,
  93. [2] 12,
  94. [3] 13,
  95. [4] 15,
  96. [5] 20,
  97. [6] 25,
  98. [7] 30,
  99. [8] 35,
  100. [9] 40,
  101. [0xa] 45,
  102. [0xb] 50,
  103. [0xc] 55,
  104. [0xd] 60,
  105. [0xe] 70,
  106. [0xf] 80,
  107. };
  108. ulong exponent[8] =
  109. {
  110. [0] 1,
  111. [1] 10,
  112. [2] 100,
  113. [3] 1000,
  114. [4] 10000,
  115. [5] 100000,
  116. [6] 1000000,
  117. [7] 10000000,
  118. };
  119. char *typetab[256] =
  120. {
  121. [1] "Masked ROM",
  122. [2] "PROM",
  123. [3] "EPROM",
  124. [4] "EEPROM",
  125. [5] "FLASH",
  126. [6] "SRAM",
  127. [7] "DRAM",
  128. [0xD] "IO+MEM",
  129. };
  130. ulong
  131. getlong(int size)
  132. {
  133. uchar c;
  134. int i;
  135. ulong x;
  136. x = 0;
  137. for(i = 0; i < size; i++){
  138. if(readc(&c) != 1)
  139. break;
  140. x |= c<<(i*8);
  141. }
  142. return x;
  143. }
  144. void
  145. tdevice(int ttype, int len)
  146. {
  147. uchar id;
  148. uchar type;
  149. uchar speed, aespeed;
  150. uchar size;
  151. ulong bytes, ns;
  152. char *tname, *ttname;
  153. while(len > 0){
  154. if(readc(&id) != 1)
  155. return;
  156. len--;
  157. if(id == End)
  158. return;
  159. speed = id & 0x7;
  160. if(speed == 0xE){
  161. if(readc(&speed) != 1)
  162. return;
  163. len--;
  164. if(speed & 0x80){
  165. if(readc(&aespeed) != 1)
  166. return;
  167. ns = 0;
  168. } else
  169. ns = (mantissa[(speed>>3)&0xf]*exponent[speed&7])/10;
  170. } else
  171. ns = speedtab[speed];
  172. type = id>>4;
  173. if(type == 0xE){
  174. if(readc(&type) != 1)
  175. return;
  176. len--;
  177. }
  178. tname = typetab[type];
  179. if(tname == 0)
  180. tname = "unknown";
  181. if(readc(&size) != 1)
  182. return;
  183. len--;
  184. bytes = ((size>>3)+1) * 512 * (1<<(2*(size&0x7)));
  185. if(ttype == 1)
  186. ttname = "device";
  187. else
  188. ttname = "attr device";
  189. print("%s %ld bytes of %ldns %s\n", ttname, bytes, ns, tname);
  190. }
  191. }
  192. void
  193. tvers1(int ttype, int len)
  194. {
  195. uchar c, major, minor;
  196. int i;
  197. char string[512];
  198. USED(ttype);
  199. if(readc(&major) != 1)
  200. return;
  201. len--;
  202. if(readc(&minor) != 1)
  203. return;
  204. len--;
  205. print("version %d.%d\n", major, minor);
  206. while(len > 0){
  207. for(i = 0; len > 0 && i < sizeof(string); i++){
  208. if(readc(&string[i]) != 1)
  209. return;
  210. len--;
  211. c = string[i];
  212. if(c == 0)
  213. break;
  214. if(c == 0xff){
  215. if(i != 0){
  216. string[i] = 0;
  217. print("\t%s<missing null>\n", string);
  218. }
  219. return;
  220. }
  221. }
  222. string[i] = 0;
  223. print("\t%s\n", string);
  224. }
  225. }
  226. void
  227. tcfig(int ttype, int len)
  228. {
  229. uchar size, rasize, rmsize;
  230. uchar last;
  231. ulong caddr;
  232. ulong cregs;
  233. int i;
  234. USED(ttype, len);
  235. if(readc(&size) != 1)
  236. return;
  237. rasize = (size&0x3) + 1;
  238. rmsize = ((size>>2)&0xf) + 1;
  239. if(readc(&last) != 1)
  240. return;
  241. caddr = getlong(rasize);
  242. cregs = getlong(rmsize);
  243. print("configuration registers at");
  244. for(i = 0; i < 16; i++)
  245. if((1<<i) & cregs)
  246. print(" (%d)0x%lux", i, caddr + i*2);
  247. print("\n");
  248. }
  249. char *intrname[16] =
  250. {
  251. [0] "memory",
  252. [1] "I/O",
  253. [4] "Custom 0",
  254. [5] "Custom 1",
  255. [6] "Custom 2",
  256. [7] "Custom 3",
  257. };
  258. ulong vexp[8] =
  259. {
  260. 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
  261. };
  262. ulong vmant[16] =
  263. {
  264. 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
  265. };
  266. void
  267. volt(char *name)
  268. {
  269. uchar c;
  270. ulong microv;
  271. ulong exp;
  272. if(readc(&c) != 1)
  273. return;
  274. exp = vexp[c&0x7];
  275. microv = vmant[(c>>3)&0xf]*exp;
  276. while(c & 0x80){
  277. if(readc(&c) != 1)
  278. return;
  279. switch(c){
  280. case 0x7d:
  281. break; /* high impedence when sleeping */
  282. case 0x7e:
  283. case 0x7f:
  284. microv = 0; /* no connection */
  285. break;
  286. default:
  287. exp /= 10;
  288. microv += exp*(c&0x7f);
  289. }
  290. }
  291. print(" V%s %lduV", name, microv);
  292. }
  293. void
  294. amps(char *name)
  295. {
  296. uchar c;
  297. ulong amps;
  298. if(readc(&c) != 1)
  299. return;
  300. amps = vexp[c&0x7]*vmant[(c>>3)&0xf];
  301. while(c & 0x80){
  302. if(readc(&c) != 1)
  303. return;
  304. if(c == 0x7d || c == 0x7e || c == 0x7f)
  305. amps = 0;
  306. }
  307. if(amps >= 1000000)
  308. print(" I%s %ldmA", name, amps/100000);
  309. else if(amps >= 1000)
  310. print(" I%s %lduA", name, amps/100);
  311. else
  312. print(" I%s %ldnA", name, amps*10);
  313. }
  314. void
  315. power(char *name)
  316. {
  317. uchar feature;
  318. print("\t%s: ", name);
  319. if(readc(&feature) != 1)
  320. return;
  321. if(feature & 1)
  322. volt("nominal");
  323. if(feature & 2)
  324. volt("min");
  325. if(feature & 4)
  326. volt("max");
  327. if(feature & 8)
  328. amps("static");
  329. if(feature & 0x10)
  330. amps("avg");
  331. if(feature & 0x20)
  332. amps("peak");
  333. if(feature & 0x40)
  334. amps("powerdown");
  335. print("\n");
  336. }
  337. void
  338. ttiming(char *name, int scale)
  339. {
  340. uchar unscaled;
  341. ulong scaled;
  342. if(readc(&unscaled) != 1)
  343. return;
  344. scaled = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
  345. scaled = scaled * vexp[scale];
  346. print("\t%s %ldns\n", name, scaled);
  347. }
  348. void
  349. timing(void)
  350. {
  351. uchar c, i;
  352. if(readc(&c) != 1)
  353. return;
  354. i = c&0x3;
  355. if(i != 3)
  356. ttiming("max wait", i);
  357. i = (c>>2)&0x7;
  358. if(i != 7)
  359. ttiming("max ready/busy wait", i);
  360. i = (c>>5)&0x7;
  361. if(i != 7)
  362. ttiming("reserved wait", i);
  363. }
  364. void
  365. range(int asize, int lsize)
  366. {
  367. ulong address, len;
  368. address = getlong(asize);
  369. len = getlong(lsize);
  370. print("\t\t%lux - %lux\n", address, address+len);
  371. }
  372. char *ioaccess[4] =
  373. {
  374. " no access",
  375. " 8bit access only",
  376. " 8bit or 16bit access",
  377. " selectable 8bit or 8&16bit access",
  378. };
  379. int
  380. iospace(uchar c)
  381. {
  382. int i;
  383. print("\tIO space %d address lines%s\n", c&0x1f, ioaccess[(c>>5)&3]);
  384. if((c & 0x80) == 0)
  385. return -1;
  386. if(readc(&c) != 1)
  387. return -1;
  388. for(i = (c&0xf)+1; i; i--)
  389. range((c>>4)&0x3, (c>>6)&0x3);
  390. return 0;
  391. }
  392. void
  393. iospaces(void)
  394. {
  395. uchar c;
  396. if(readc(&c) != 1)
  397. return;
  398. iospace(c);
  399. }
  400. void
  401. irq(void)
  402. {
  403. uchar c;
  404. uchar irq1, irq2;
  405. ushort i, irqs;
  406. if(readc(&c) != 1)
  407. return;
  408. if(c & 0x10){
  409. if(readc(&irq1) != 1)
  410. return;
  411. if(readc(&irq2) != 1)
  412. return;
  413. irqs = irq1|(irq2<<8);
  414. } else
  415. irqs = 1<<(c&0xf);
  416. print("\tinterrupts%s%s%s", (c&0x20)?":level":"", (c&0x40)?":pulse":"",
  417. (c&0x80)?":shared":"");
  418. for(i = 0; i < 16; i++)
  419. if(irqs & (1<<i))
  420. print(", %d", i);
  421. print("\n");
  422. }
  423. void
  424. memspace(int asize, int lsize, int host)
  425. {
  426. ulong haddress, address, len;
  427. len = getlong(lsize)*256;
  428. address = getlong(asize)*256;
  429. if(host){
  430. haddress = getlong(asize)*256;
  431. print("\tmemory address range 0x%lux - 0x%lux hostaddr 0x%lux\n",
  432. address, address+len, haddress);
  433. } else
  434. print("\tmemory address range 0x%lux - 0x%lux\n", address, address+len);
  435. }
  436. void
  437. misc(void)
  438. {
  439. }
  440. void
  441. tentry(int ttype, int len)
  442. {
  443. uchar c, i, feature;
  444. char *tname;
  445. char buf[16];
  446. USED(ttype, len);
  447. if(readc(&c) != 1)
  448. return;
  449. print("configuration %d%s\n", c&0x3f, (c&0x40)?" (default)":"");
  450. if(c & 0x80){
  451. if(readc(&i) != 1)
  452. return;
  453. tname = intrname[i & 0xf];
  454. if(tname == 0){
  455. tname = buf;
  456. sprint(buf, "type %d", i & 0xf);
  457. }
  458. print("\t%s device, %s%s%s%s\n", tname,
  459. (i&0x10)?" Battery status active":"",
  460. (i&0x20)?" Write Protect active":"",
  461. (i&0x40)?" Ready/Busy active":"",
  462. (i&0x80)?" Memory Wait required":"");
  463. }
  464. if(readc(&feature) != 1)
  465. return;
  466. switch(feature&0x3){
  467. case 1:
  468. power("Vcc");
  469. break;
  470. case 2:
  471. power("Vcc");
  472. power("Vpp");
  473. break;
  474. case 3:
  475. power("Vcc");
  476. power("Vpp1");
  477. power("Vpp2");
  478. break;
  479. }
  480. if(feature&0x4)
  481. timing();
  482. if(feature&0x8)
  483. iospaces();
  484. if(feature&0x10)
  485. irq();
  486. switch((feature>>5)&0x3){
  487. case 1:
  488. memspace(0, 2, 0);
  489. break;
  490. case 2:
  491. memspace(2, 2, 0);
  492. break;
  493. case 3:
  494. if(readc(&c) != 1)
  495. return;
  496. for(i = 0; i <= (c&0x7); i++)
  497. memspace((c>>5)&0x3, (c>>3)&0x3, c&0x80);
  498. break;
  499. }
  500. if(feature&0x80)
  501. misc();
  502. }