devi82365.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "error.h"
  7. #include "io.h"
  8. /*
  9. * Support for up to 4 Slot card slots. Generalizing above that is hard
  10. * since addressing is not obvious. - presotto
  11. *
  12. * WARNING: This has never been tried with more than one card slot.
  13. */
  14. /*
  15. * Intel 82365SL PCIC controller for the PCMCIA or
  16. * Cirrus Logic PD6710/PD6720 which is mostly register compatible
  17. */
  18. enum
  19. {
  20. /*
  21. * registers indices
  22. */
  23. Rid= 0x0, /* identification and revision */
  24. Ris= 0x1, /* interface status */
  25. Rpc= 0x2, /* power control */
  26. Foutena= (1<<7), /* output enable */
  27. Fautopower= (1<<5), /* automatic power switching */
  28. Fcardena= (1<<4), /* PC card enable */
  29. Rigc= 0x3, /* interrupt and general control */
  30. Fiocard= (1<<5), /* I/O card (vs memory) */
  31. Fnotreset= (1<<6), /* reset if not set */
  32. FSMIena= (1<<4), /* enable change interrupt on SMI */
  33. Rcsc= 0x4, /* card status change */
  34. Rcscic= 0x5, /* card status change interrupt config */
  35. Fchangeena= (1<<3), /* card changed */
  36. Fbwarnena= (1<<1), /* card battery warning */
  37. Fbdeadena= (1<<0), /* card battery dead */
  38. Rwe= 0x6, /* address window enable */
  39. Fmem16= (1<<5), /* use A23-A12 to decode address */
  40. Rio= 0x7, /* I/O control */
  41. Fwidth16= (1<<0), /* 16 bit data width */
  42. Fiocs16= (1<<1), /* IOCS16 determines data width */
  43. Fzerows= (1<<2), /* zero wait state */
  44. Ftiming= (1<<3), /* timing register to use */
  45. Riobtm0lo= 0x8, /* I/O address 0 start low byte */
  46. Riobtm0hi= 0x9, /* I/O address 0 start high byte */
  47. Riotop0lo= 0xa, /* I/O address 0 stop low byte */
  48. Riotop0hi= 0xb, /* I/O address 0 stop high byte */
  49. Riobtm1lo= 0xc, /* I/O address 1 start low byte */
  50. Riobtm1hi= 0xd, /* I/O address 1 start high byte */
  51. Riotop1lo= 0xe, /* I/O address 1 stop low byte */
  52. Riotop1hi= 0xf, /* I/O address 1 stop high byte */
  53. Rmap= 0x10, /* map 0 */
  54. /*
  55. * CL-PD67xx extension registers
  56. */
  57. Rmisc1= 0x16, /* misc control 1 */
  58. F5Vdetect= (1<<0),
  59. Fvcc3V= (1<<1),
  60. Fpmint= (1<<2),
  61. Fpsirq= (1<<3),
  62. Fspeaker= (1<<4),
  63. Finpack= (1<<7),
  64. Rfifo= 0x17, /* fifo control */
  65. Fflush= (1<<7), /* flush fifo */
  66. Rmisc2= 0x1E, /* misc control 2 */
  67. Flowpow= (1<<1), /* low power mode */
  68. Rchipinfo= 0x1F, /* chip information */
  69. Ratactl= 0x26, /* ATA control */
  70. /*
  71. * offsets into the system memory address maps
  72. */
  73. Mbtmlo= 0x0, /* System mem addr mapping start low byte */
  74. Mbtmhi= 0x1, /* System mem addr mapping start high byte */
  75. F16bit= (1<<7), /* 16-bit wide data path */
  76. Mtoplo= 0x2, /* System mem addr mapping stop low byte */
  77. Mtophi= 0x3, /* System mem addr mapping stop high byte */
  78. Ftimer1= (1<<6), /* timer set 1 */
  79. Mofflo= 0x4, /* Card memory offset address low byte */
  80. Moffhi= 0x5, /* Card memory offset address high byte */
  81. Fregactive= (1<<6), /* attribute memory */
  82. Mbits= 13, /* msb of Mchunk */
  83. Mchunk= 1<<Mbits, /* logical mapping granularity */
  84. Nmap= 4, /* max number of maps to use */
  85. /*
  86. * configuration registers - they start at an offset in attribute
  87. * memory found in the CIS.
  88. */
  89. Rconfig= 0,
  90. Creset= (1<<7), /* reset device */
  91. Clevel= (1<<6), /* level sensitive interrupt line */
  92. Maxctab= 8, /* maximum configuration table entries */
  93. };
  94. static int pcmcia_pcmspecial(char *, ISAConf *);
  95. static void pcmcia_pcmspecialclose(int);
  96. #define MAP(x,o) (Rmap + (x)*0x8 + o)
  97. typedef struct I82365 I82365;
  98. typedef struct Slot Slot;
  99. typedef struct Conftab Conftab;
  100. typedef struct Cisdat Cisdat;
  101. /* a controller */
  102. enum
  103. {
  104. Ti82365,
  105. Tpd6710,
  106. Tpd6720,
  107. Tvg46x,
  108. };
  109. struct I82365
  110. {
  111. int type;
  112. int dev;
  113. int nslot;
  114. int xreg; /* index register address */
  115. int dreg; /* data register address */
  116. int irq;
  117. };
  118. static I82365 *controller[4];
  119. static int ncontroller;
  120. /* configuration table entry */
  121. struct Conftab
  122. {
  123. int index;
  124. ushort irqs; /* legal irqs */
  125. uchar irqtype;
  126. uchar bit16; /* true for 16 bit access */
  127. struct {
  128. ulong start;
  129. ulong len;
  130. } io[16];
  131. int nio;
  132. uchar vpp1;
  133. uchar vpp2;
  134. uchar memwait;
  135. ulong maxwait;
  136. ulong readywait;
  137. ulong otherwait;
  138. };
  139. /* cis memory walking */
  140. struct Cisdat
  141. {
  142. uchar *cisbase;
  143. int cispos;
  144. int cisskip;
  145. int cislen;
  146. };
  147. /* a card slot */
  148. struct Slot
  149. {
  150. Lock;
  151. int ref;
  152. I82365 *cp; /* controller for this slot */
  153. long memlen; /* memory length */
  154. uchar base; /* index register base */
  155. uchar slotno; /* slot number */
  156. /* status */
  157. uchar special; /* in use for a special device */
  158. uchar already; /* already inited */
  159. uchar occupied;
  160. uchar battery;
  161. uchar wrprot;
  162. uchar powered;
  163. uchar configed;
  164. uchar enabled;
  165. uchar busy;
  166. /* cis info */
  167. char verstr[512]; /* version string */
  168. uchar cpresent; /* config registers present */
  169. ulong caddr; /* relative address of config registers */
  170. int nctab; /* number of config table entries */
  171. Conftab ctab[Maxctab];
  172. Conftab *def; /* default conftab */
  173. /* for walking through cis */
  174. Cisdat;
  175. /* memory maps */
  176. Lock mlock; /* lock down the maps */
  177. int time;
  178. PCMmap mmap[Nmap]; /* maps, last is always for the kernel */
  179. };
  180. static Slot *slot;
  181. static Slot *lastslot;
  182. static nslot;
  183. static void cisread(Slot*);
  184. static void i82365intr(Ureg*, void*);
  185. static void i82365reset(void);
  186. static int pcmio(int, ISAConf*);
  187. static long pcmread(int, int, void*, long, vlong);
  188. static long pcmwrite(int, int, void*, long, vlong);
  189. static void i82365dump(Slot*);
  190. void
  191. devi82365link(void)
  192. {
  193. static int already;
  194. if(already)
  195. return;
  196. already = 1;
  197. if (_pcmspecial)
  198. return;
  199. _pcmspecial = pcmcia_pcmspecial;
  200. _pcmspecialclose = pcmcia_pcmspecialclose;
  201. }
  202. /*
  203. * reading and writing card registers
  204. */
  205. static uchar
  206. rdreg(Slot *pp, int index)
  207. {
  208. outb(pp->cp->xreg, pp->base + index);
  209. return inb(pp->cp->dreg);
  210. }
  211. static void
  212. wrreg(Slot *pp, int index, uchar val)
  213. {
  214. outb(pp->cp->xreg, pp->base + index);
  215. outb(pp->cp->dreg, val);
  216. }
  217. /*
  218. * get info about card
  219. */
  220. static void
  221. slotinfo(Slot *pp)
  222. {
  223. uchar isr;
  224. isr = rdreg(pp, Ris);
  225. pp->occupied = (isr & (3<<2)) == (3<<2);
  226. pp->powered = isr & (1<<6);
  227. pp->battery = (isr & 3) == 3;
  228. pp->wrprot = isr & (1<<4);
  229. pp->busy = isr & (1<<5);
  230. }
  231. static int
  232. vcode(int volt)
  233. {
  234. switch(volt){
  235. case 5:
  236. return 1;
  237. case 12:
  238. return 2;
  239. default:
  240. return 0;
  241. }
  242. }
  243. /*
  244. * enable the slot card
  245. */
  246. static void
  247. slotena(Slot *pp)
  248. {
  249. if(pp->enabled)
  250. return;
  251. /* power up and unreset, wait's are empirical (???) */
  252. wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
  253. delay(300);
  254. wrreg(pp, Rigc, 0);
  255. delay(100);
  256. wrreg(pp, Rigc, Fnotreset);
  257. delay(500);
  258. /* get configuration */
  259. slotinfo(pp);
  260. if(pp->occupied){
  261. cisread(pp);
  262. pp->enabled = 1;
  263. } else
  264. wrreg(pp, Rpc, Fautopower);
  265. }
  266. /*
  267. * disable the slot card
  268. */
  269. static void
  270. slotdis(Slot *pp)
  271. {
  272. wrreg(pp, Rpc, 0); /* turn off card power */
  273. wrreg(pp, Rwe, 0); /* no windows */
  274. pp->enabled = 0;
  275. }
  276. /*
  277. * status change interrupt
  278. */
  279. static void
  280. i82365intr(Ureg *, void *)
  281. {
  282. uchar csc, was;
  283. Slot *pp;
  284. if(slot == 0)
  285. return;
  286. for(pp = slot; pp < lastslot; pp++){
  287. csc = rdreg(pp, Rcsc);
  288. was = pp->occupied;
  289. slotinfo(pp);
  290. if(csc & (1<<3) && was != pp->occupied){
  291. if(!pp->occupied)
  292. slotdis(pp);
  293. }
  294. }
  295. }
  296. enum
  297. {
  298. Mshift= 12,
  299. Mgran= (1<<Mshift), /* granularity of maps */
  300. Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
  301. };
  302. /*
  303. * get a map for pc card region, return corrected len
  304. */
  305. PCMmap*
  306. pcmmap(int slotno, ulong offset, int len, int attr)
  307. {
  308. Slot *pp;
  309. uchar we, bit;
  310. PCMmap *m, *nm;
  311. int i;
  312. ulong e;
  313. pp = slot + slotno;
  314. lock(&pp->mlock);
  315. /* convert offset to granularity */
  316. if(len <= 0)
  317. len = 1;
  318. e = ROUND(offset+len, Mgran);
  319. offset &= Mmask;
  320. len = e - offset;
  321. /* look for a map that covers the right area */
  322. we = rdreg(pp, Rwe);
  323. bit = 1;
  324. nm = 0;
  325. for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
  326. if((we & bit))
  327. if(m->attr == attr)
  328. if(offset >= m->ca && e <= m->cea){
  329. m->ref++;
  330. unlock(&pp->mlock);
  331. return m;
  332. }
  333. bit <<= 1;
  334. if(nm == 0 && m->ref == 0)
  335. nm = m;
  336. }
  337. m = nm;
  338. if(m == 0){
  339. unlock(&pp->mlock);
  340. return 0;
  341. }
  342. /* if isa space isn't big enough, free it and get more */
  343. if(m->len < len){
  344. if(m->isa){
  345. umbfree(m->isa, m->len);
  346. m->len = 0;
  347. }
  348. m->isa = PADDR(umbmalloc(0, len, Mgran));
  349. if(m->isa == 0){
  350. print("pcmmap %d: out of isa space\n", len);
  351. unlock(&pp->mlock);
  352. return 0;
  353. }
  354. m->len = len;
  355. }
  356. /* set up new map */
  357. m->ca = offset;
  358. m->cea = m->ca + m->len;
  359. m->attr = attr;
  360. i = m-pp->mmap;
  361. bit = 1<<i;
  362. wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
  363. wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
  364. wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
  365. wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
  366. wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
  367. offset -= m->isa;
  368. offset &= (1<<25)-1;
  369. offset >>= Mshift;
  370. wrreg(pp, MAP(i, Mofflo), offset);
  371. wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
  372. wrreg(pp, Rwe, we | bit); /* enable map */
  373. m->ref = 1;
  374. unlock(&pp->mlock);
  375. return m;
  376. }
  377. void
  378. pcmunmap(int slotno, PCMmap* m)
  379. {
  380. Slot *pp;
  381. pp = slot + slotno;
  382. lock(&pp->mlock);
  383. m->ref--;
  384. unlock(&pp->mlock);
  385. }
  386. static void
  387. increfp(Slot *pp)
  388. {
  389. lock(pp);
  390. if(pp->ref++ == 0)
  391. slotena(pp);
  392. unlock(pp);
  393. }
  394. static void
  395. decrefp(Slot *pp)
  396. {
  397. lock(pp);
  398. if(pp->ref-- == 1)
  399. slotdis(pp);
  400. unlock(pp);
  401. }
  402. /*
  403. * look for a card whose version contains 'idstr'
  404. */
  405. static int
  406. pcmcia_pcmspecial(char *idstr, ISAConf *isa)
  407. {
  408. Slot *pp;
  409. extern char *strstr(char*, char*);
  410. int enabled;
  411. i82365reset();
  412. for(pp = slot; pp < lastslot; pp++){
  413. if(pp->special)
  414. continue; /* already taken */
  415. enabled = 0;
  416. /* make sure we don't power on cards when we already know what's
  417. * in them. We'll reread every two minutes if necessary
  418. */
  419. if (pp->verstr[0] == '\0') {
  420. increfp(pp);
  421. enabled++;
  422. }
  423. if(pp->occupied) {
  424. if(strstr(pp->verstr, idstr)) {
  425. if (!enabled)
  426. increfp(pp);
  427. if(isa == 0 || pcmio(pp->slotno, isa) == 0){
  428. pp->special = 1;
  429. return pp->slotno;
  430. }
  431. }
  432. } else
  433. pp->special = 1;
  434. if (enabled)
  435. decrefp(pp);
  436. }
  437. return -1;
  438. }
  439. static void
  440. pcmcia_pcmspecialclose(int slotno)
  441. {
  442. Slot *pp;
  443. print("pcmspecialclose called\n");
  444. if(slotno >= nslot)
  445. panic("pcmspecialclose");
  446. pp = slot + slotno;
  447. pp->special = 0;
  448. decrefp(pp);
  449. }
  450. static char *chipname[] =
  451. {
  452. [Ti82365] "Intel 82365SL",
  453. [Tpd6710] "Cirrus Logic PD6710",
  454. [Tpd6720] "Cirrus Logic PD6720",
  455. [Tvg46x] "Vadem VG-46x",
  456. };
  457. static I82365*
  458. i82365probe(int x, int d, int dev)
  459. {
  460. uchar c, id;
  461. I82365 *cp;
  462. ISAConf isa;
  463. int i, nslot;
  464. outb(x, Rid + (dev<<7));
  465. id = inb(d);
  466. if((id & 0xf0) != 0x80)
  467. return 0; /* not this family */
  468. cp = xalloc(sizeof(I82365));
  469. cp->xreg = x;
  470. cp->dreg = d;
  471. cp->dev = dev;
  472. cp->type = Ti82365;
  473. cp->nslot = 2;
  474. switch(id){
  475. case 0x82:
  476. case 0x83:
  477. case 0x84:
  478. /* could be a cirrus */
  479. outb(x, Rchipinfo + (dev<<7));
  480. outb(d, 0);
  481. c = inb(d);
  482. if((c & 0xc0) != 0xc0)
  483. break;
  484. c = inb(d);
  485. if((c & 0xc0) != 0x00)
  486. break;
  487. if(c & 0x20){
  488. cp->type = Tpd6720;
  489. } else {
  490. cp->type = Tpd6710;
  491. cp->nslot = 1;
  492. }
  493. /* low power mode */
  494. outb(x, Rmisc2 + (dev<<7));
  495. c = inb(d);
  496. outb(d, c & ~Flowpow);
  497. break;
  498. }
  499. if(cp->type == Ti82365){
  500. outb(x, 0x0E + (dev<<7));
  501. outb(x, 0x37 + (dev<<7));
  502. outb(x, 0x3A + (dev<<7));
  503. c = inb(d);
  504. outb(d, c|0xC0);
  505. outb(x, Rid + (dev<<7));
  506. c = inb(d);
  507. if(c != id && !(c & 0x08))
  508. print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
  509. if(c & 0x08)
  510. cp->type = Tvg46x;
  511. outb(x, 0x3A + (dev<<7));
  512. c = inb(d);
  513. outb(d, c & ~0xC0);
  514. }
  515. memset(&isa, 0, sizeof(ISAConf));
  516. if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
  517. cp->irq = isa.irq;
  518. else
  519. cp->irq = VectorPCMCIA - VectorPIC;
  520. for(i = 0; i < isa.nopt; i++){
  521. if(cistrncmp(isa.opt[i], "nslot=", 6))
  522. continue;
  523. nslot = strtol(&isa.opt[i][6], nil, 0);
  524. if(nslot > 0 && nslot <= 2)
  525. cp->nslot = nslot;
  526. }
  527. controller[ncontroller++] = cp;
  528. return cp;
  529. }
  530. static void
  531. i82365dump(Slot *pp)
  532. {
  533. int i;
  534. for(i = 0; i < 0x40; i++){
  535. if((i&0x0F) == 0)
  536. print("\n%2.2uX: ", i);
  537. if(((i+1) & 0x0F) == 0x08)
  538. print(" - ");
  539. print("%2.2uX ", rdreg(pp, i));
  540. }
  541. print("\n");
  542. }
  543. /*
  544. * set up for slot cards
  545. */
  546. static void
  547. i82365reset(void)
  548. {
  549. static int already;
  550. int i, j;
  551. I82365 *cp;
  552. Slot *pp;
  553. if(already)
  554. return;
  555. already = 1;
  556. /* look for controllers */
  557. i82365probe(0x3E0, 0x3E1, 0);
  558. i82365probe(0x3E0, 0x3E1, 1);
  559. i82365probe(0x3E2, 0x3E3, 0);
  560. i82365probe(0x3E2, 0x3E3, 1);
  561. for(i = 0; i < ncontroller; i++)
  562. nslot += controller[i]->nslot;
  563. slot = xalloc(nslot * sizeof(Slot));
  564. /* if the card is there turn on 5V power to keep its battery alive */
  565. lastslot = slot;
  566. for(i = 0; i < ncontroller; i++){
  567. cp = controller[i];
  568. print("#y%d: %d slot %s: port 0x%uX irq %d\n",
  569. i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
  570. for(j = 0; j < cp->nslot; j++){
  571. pp = lastslot++;
  572. pp->slotno = pp - slot;
  573. pp->memlen = 64*MB;
  574. pp->base = (cp->dev<<7) | (j<<6);
  575. pp->cp = cp;
  576. slotdis(pp);
  577. /* interrupt on status change */
  578. wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
  579. rdreg(pp, Rcsc);
  580. }
  581. /* for card management interrupts */
  582. setvec(cp->irq+VectorPIC, i82365intr, 0);
  583. }
  584. }
  585. /*
  586. * configure the Slot for IO. We assume very heavily that we can read
  587. * configuration info from the CIS. If not, we won't set up correctly.
  588. */
  589. static int
  590. pcmio(int slotno, ISAConf *isa)
  591. {
  592. uchar we, x, *p;
  593. Slot *pp;
  594. Conftab *ct, *et, *t;
  595. PCMmap *m;
  596. int i, index, irq;
  597. char *cp;
  598. irq = isa->irq;
  599. if(irq == 2)
  600. irq = 9;
  601. if(slotno > nslot)
  602. return -1;
  603. pp = slot + slotno;
  604. if(!pp->occupied)
  605. return -1;
  606. et = &pp->ctab[pp->nctab];
  607. ct = 0;
  608. for(i = 0; i < isa->nopt; i++){
  609. if(strncmp(isa->opt[i], "index=", 6))
  610. continue;
  611. index = strtol(&isa->opt[i][6], &cp, 0);
  612. if(cp == &isa->opt[i][6] || index >= pp->nctab)
  613. return -1;
  614. ct = &pp->ctab[index];
  615. }
  616. if(ct == 0){
  617. /* assume default is right */
  618. if(pp->def)
  619. ct = pp->def;
  620. else
  621. ct = pp->ctab;
  622. /* try for best match */
  623. if(ct->nio == 0
  624. || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
  625. for(t = pp->ctab; t < et; t++)
  626. if(t->nio
  627. && t->io[0].start == isa->port
  628. && ((1<<irq) & t->irqs)){
  629. ct = t;
  630. break;
  631. }
  632. }
  633. if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
  634. for(t = pp->ctab; t < et; t++)
  635. if(t->nio && ((1<<irq) & t->irqs)){
  636. ct = t;
  637. break;
  638. }
  639. }
  640. if(ct->nio == 0){
  641. for(t = pp->ctab; t < et; t++)
  642. if(t->nio){
  643. ct = t;
  644. break;
  645. }
  646. }
  647. }
  648. if(ct == et || ct->nio == 0)
  649. return -1;
  650. if(isa->port == 0 && ct->io[0].start == 0)
  651. return -1;
  652. /* route interrupts */
  653. isa->irq = irq;
  654. wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
  655. /* set power and enable device */
  656. x = vcode(ct->vpp1);
  657. wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
  658. /* 16-bit data path */
  659. if(ct->bit16)
  660. x = Ftiming|Fiocs16|Fwidth16;
  661. else
  662. x = Ftiming;
  663. if(ct->nio == 2 && ct->io[1].start)
  664. x |= x<<4;
  665. wrreg(pp, Rio, x);
  666. /* enable io port map 0 */
  667. if(isa->port == 0)
  668. isa->port = ct->io[0].start;
  669. we = rdreg(pp, Rwe);
  670. wrreg(pp, Riobtm0lo, isa->port);
  671. wrreg(pp, Riobtm0hi, isa->port>>8);
  672. i = isa->port+ct->io[0].len-1;
  673. wrreg(pp, Riotop0lo, i);
  674. wrreg(pp, Riotop0hi, i>>8);
  675. we |= 1<<6;
  676. if(ct->nio == 2 && ct->io[1].start){
  677. wrreg(pp, Riobtm1lo, ct->io[1].start);
  678. wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
  679. i = ct->io[1].start+ct->io[1].len-1;
  680. wrreg(pp, Riotop1lo, i);
  681. wrreg(pp, Riotop1hi, i>>8);
  682. we |= 1<<7;
  683. }
  684. wrreg(pp, Rwe, we);
  685. /* only touch Rconfig if it is present */
  686. if(pp->cpresent & (1<<Rconfig)){
  687. /* Reset adapter */
  688. m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
  689. p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);
  690. /* set configuration and interrupt type */
  691. x = ct->index;
  692. if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
  693. x |= Clevel;
  694. *p = x;
  695. delay(5);
  696. pcmunmap(slotno, m);
  697. }
  698. return 0;
  699. }
  700. /*
  701. * read and crack the card information structure enough to set
  702. * important parameters like power
  703. */
  704. static void tcfig(Slot*, Cisdat*, int);
  705. static void tentry(Slot*, Cisdat*, int);
  706. static void tvers1(Slot*, Cisdat*, int);
  707. struct {
  708. int n;
  709. void (*parse)(Slot*, Cisdat*, int);
  710. } cistab[] = {
  711. 0x15, tvers1,
  712. 0x1A, tcfig,
  713. 0x1B, tentry,
  714. };
  715. static int
  716. readc(Cisdat *pp, uchar *x)
  717. {
  718. if(pp->cispos >= pp->cislen)
  719. return 0;
  720. *x = pp->cisbase[pp->cisskip*pp->cispos];
  721. pp->cispos++;
  722. return 1;
  723. }
  724. static int
  725. xcistuple(int slotno, int tuple, void *v, int nv, int attr)
  726. {
  727. PCMmap *m;
  728. Cisdat cis;
  729. int i, l;
  730. uchar *p;
  731. uchar type, link;
  732. int this;
  733. m = pcmmap(slotno, 0, 0, attr);
  734. if(m == 0) {
  735. if(debug) print("could not map\n");
  736. return -1;
  737. }
  738. cis.cisbase = KADDR(m->isa);
  739. cis.cispos = 0;
  740. cis.cisskip = attr ? 2 : 1;
  741. cis.cislen = Mchunk;
  742. if(debug) print("cis %d %d #%lux srch %x...", attr, cis.cisskip, cis.cisbase, tuple);
  743. /* loop through all the tuples */
  744. for(i = 0; i < 1000; i++){
  745. this = cis.cispos;
  746. if(readc(&cis, &type) != 1)
  747. break;
  748. if(debug) print("%2ux...", type);
  749. if(type == 0xFF)
  750. break;
  751. if(readc(&cis, &link) != 1)
  752. break;
  753. if(link == 0xFF)
  754. break;
  755. if(type == tuple) {
  756. p = v;
  757. for(l=0; l<nv && l<link; l++)
  758. if(readc(&cis, p++) != 1)
  759. break;
  760. pcmunmap(slotno, m);
  761. if(debug) print("pcm find %2.2ux %d %d\n", type, link, l);
  762. return l;
  763. }
  764. cis.cispos = this + (2+link);
  765. }
  766. pcmunmap(slotno, m);
  767. return -1;
  768. }
  769. int
  770. pcmcistuple(int slotno, int tuple, void *v, int nv)
  771. {
  772. int n;
  773. /* try attribute space, then memory */
  774. if((n = xcistuple(slotno, tuple, v, nv, 1)) >= 0)
  775. return n;
  776. return xcistuple(slotno, tuple, v, nv, 0);
  777. }
  778. static void
  779. cisread(Slot *pp)
  780. {
  781. uchar v[256];
  782. int i, nv;
  783. Cisdat cis;
  784. memset(pp->ctab, 0, sizeof(pp->ctab));
  785. pp->caddr = 0;
  786. pp->cpresent = 0;
  787. pp->configed = 0;
  788. pp->nctab = 0;
  789. for(i = 0; i < nelem(cistab); i++) {
  790. if((nv = pcmcistuple(pp->slotno, cistab[i].n, v, sizeof(v))) >= 0) {
  791. cis.cisbase = v;
  792. cis.cispos = 0;
  793. cis.cisskip = 1;
  794. cis.cislen = nv;
  795. (*cistab[i].parse)(pp, &cis, cistab[i].n);
  796. }
  797. }
  798. }
  799. static ulong
  800. getlong(Cisdat *cis, int size)
  801. {
  802. uchar c;
  803. int i;
  804. ulong x;
  805. x = 0;
  806. for(i = 0; i < size; i++){
  807. if(readc(cis, &c) != 1)
  808. break;
  809. x |= c<<(i*8);
  810. }
  811. return x;
  812. }
  813. static void
  814. tcfig(Slot *pp, Cisdat *cis, int )
  815. {
  816. uchar size, rasize, rmsize;
  817. uchar last;
  818. if(readc(cis, &size) != 1)
  819. return;
  820. rasize = (size&0x3) + 1;
  821. rmsize = ((size>>2)&0xf) + 1;
  822. if(readc(cis, &last) != 1)
  823. return;
  824. pp->caddr = getlong(cis, rasize);
  825. pp->cpresent = getlong(cis, rmsize);
  826. }
  827. static ulong vexp[8] =
  828. {
  829. 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
  830. };
  831. static ulong vmant[16] =
  832. {
  833. 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
  834. };
  835. static ulong
  836. microvolt(Cisdat *cis)
  837. {
  838. uchar c;
  839. ulong microvolts;
  840. ulong exp;
  841. if(readc(cis, &c) != 1)
  842. return 0;
  843. exp = vexp[c&0x7];
  844. microvolts = vmant[(c>>3)&0xf]*exp;
  845. while(c & 0x80){
  846. if(readc(cis, &c) != 1)
  847. return 0;
  848. switch(c){
  849. case 0x7d:
  850. break; /* high impedence when sleeping */
  851. case 0x7e:
  852. case 0x7f:
  853. microvolts = 0; /* no connection */
  854. break;
  855. default:
  856. exp /= 10;
  857. microvolts += exp*(c&0x7f);
  858. }
  859. }
  860. return microvolts;
  861. }
  862. static ulong
  863. nanoamps(Cisdat *cis)
  864. {
  865. uchar c;
  866. ulong nanoamps;
  867. if(readc(cis, &c) != 1)
  868. return 0;
  869. nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
  870. while(c & 0x80){
  871. if(readc(cis, &c) != 1)
  872. return 0;
  873. if(c == 0x7d || c == 0x7e || c == 0x7f)
  874. nanoamps = 0;
  875. }
  876. return nanoamps;
  877. }
  878. /*
  879. * only nominal voltage is important for config
  880. */
  881. static ulong
  882. power(Cisdat *cis)
  883. {
  884. uchar feature;
  885. ulong mv;
  886. mv = 0;
  887. if(readc(cis, &feature) != 1)
  888. return 0;
  889. if(feature & 1)
  890. mv = microvolt(cis);
  891. if(feature & 2)
  892. microvolt(cis);
  893. if(feature & 4)
  894. microvolt(cis);
  895. if(feature & 8)
  896. nanoamps(cis);
  897. if(feature & 0x10)
  898. nanoamps(cis);
  899. if(feature & 0x20)
  900. nanoamps(cis);
  901. if(feature & 0x40)
  902. nanoamps(cis);
  903. return mv/1000000;
  904. }
  905. static ulong mantissa[16] =
  906. { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
  907. static ulong exponent[8] =
  908. { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
  909. static ulong
  910. ttiming(Cisdat *cis, int scale)
  911. {
  912. uchar unscaled;
  913. ulong nanosecs;
  914. if(readc(cis, &unscaled) != 1)
  915. return 0;
  916. nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
  917. nanosecs = nanosecs * vexp[scale];
  918. return nanosecs;
  919. }
  920. static void
  921. timing(Cisdat *cis, Conftab *ct)
  922. {
  923. uchar c, i;
  924. if(readc(cis, &c) != 1)
  925. return;
  926. i = c&0x3;
  927. if(i != 3)
  928. ct->maxwait = ttiming(cis, i); /* max wait */
  929. i = (c>>2)&0x7;
  930. if(i != 7)
  931. ct->readywait = ttiming(cis, i); /* max ready/busy wait */
  932. i = (c>>5)&0x7;
  933. if(i != 7)
  934. ct->otherwait = ttiming(cis, i); /* reserved wait */
  935. }
  936. static void
  937. iospaces(Cisdat *cis, Conftab *ct)
  938. {
  939. uchar c;
  940. int i, nio;
  941. ct->nio = 0;
  942. if(readc(cis, &c) != 1)
  943. return;
  944. ct->bit16 = ((c>>5)&3) >= 2;
  945. if(!(c & 0x80)){
  946. ct->io[0].start = 0;
  947. ct->io[0].len = 1<<(c&0x1f);
  948. ct->nio = 1;
  949. return;
  950. }
  951. if(readc(cis, &c) != 1)
  952. return;
  953. nio = (c&0xf)+1;
  954. for(i = 0; i < nio; i++){
  955. ct->io[i].start = getlong(cis, (c>>4)&0x3);
  956. ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
  957. }
  958. ct->nio = nio;
  959. }
  960. static void
  961. irq(Cisdat *cis, Conftab *ct)
  962. {
  963. uchar c;
  964. if(readc(cis, &c) != 1)
  965. return;
  966. ct->irqtype = c & 0xe0;
  967. if(c & 0x10)
  968. ct->irqs = getlong(cis, 2);
  969. else
  970. ct->irqs = 1<<(c&0xf);
  971. ct->irqs &= 0xDEB8; /* levels available to card */
  972. }
  973. static void
  974. memspace(Cisdat *cis, int asize, int lsize, int host)
  975. {
  976. ulong haddress, address, len;
  977. len = getlong(cis, lsize)*256;
  978. address = getlong(cis, asize)*256;
  979. USED(len, address);
  980. if(host){
  981. haddress = getlong(cis, asize)*256;
  982. USED(haddress);
  983. }
  984. }
  985. static void
  986. tentry(Slot *pp, Cisdat *cis, int )
  987. {
  988. uchar c, i, feature;
  989. Conftab *ct;
  990. if(pp->nctab >= Maxctab)
  991. return;
  992. if(readc(cis, &c) != 1)
  993. return;
  994. ct = &pp->ctab[pp->nctab++];
  995. /* copy from last default config */
  996. if(pp->def)
  997. *ct = *pp->def;
  998. ct->index = c & 0x3f;
  999. /* is this the new default? */
  1000. if(c & 0x40)
  1001. pp->def = ct;
  1002. /* memory wait specified? */
  1003. if(c & 0x80){
  1004. if(readc(cis, &i) != 1)
  1005. return;
  1006. if(i&0x80)
  1007. ct->memwait = 1;
  1008. }
  1009. if(readc(cis, &feature) != 1)
  1010. return;
  1011. switch(feature&0x3){
  1012. case 1:
  1013. ct->vpp1 = ct->vpp2 = power(cis);
  1014. break;
  1015. case 2:
  1016. power(cis);
  1017. ct->vpp1 = ct->vpp2 = power(cis);
  1018. break;
  1019. case 3:
  1020. power(cis);
  1021. ct->vpp1 = power(cis);
  1022. ct->vpp2 = power(cis);
  1023. break;
  1024. default:
  1025. break;
  1026. }
  1027. if(feature&0x4)
  1028. timing(cis, ct);
  1029. if(feature&0x8)
  1030. iospaces(cis, ct);
  1031. if(feature&0x10)
  1032. irq(cis, ct);
  1033. switch((feature>>5)&0x3){
  1034. case 1:
  1035. memspace(cis, 0, 2, 0);
  1036. break;
  1037. case 2:
  1038. memspace(cis, 2, 2, 0);
  1039. break;
  1040. case 3:
  1041. if(readc(cis, &c) != 1)
  1042. return;
  1043. for(i = 0; i <= (c&0x7); i++)
  1044. memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
  1045. break;
  1046. }
  1047. pp->configed++;
  1048. }
  1049. static void
  1050. tvers1(Slot *pp, Cisdat *cis, int )
  1051. {
  1052. uchar c, major, minor;
  1053. int i;
  1054. if(readc(cis, &major) != 1)
  1055. return;
  1056. if(readc(cis, &minor) != 1)
  1057. return;
  1058. for(i = 0; i < sizeof(pp->verstr)-1; i++){
  1059. if(readc(cis, &c) != 1)
  1060. return;
  1061. if(c == 0)
  1062. c = '\n';
  1063. if(c == 0xff)
  1064. break;
  1065. pp->verstr[i] = c;
  1066. }
  1067. pp->verstr[i] = 0;
  1068. }