devpccard.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. /*
  2. cardbus and pcmcia (grmph) support.
  3. */
  4. #include "u.h"
  5. #include "lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "error.h"
  10. #include "io.h"
  11. extern int pciscan(int, Pcidev **);
  12. extern ulong pcibarsize(Pcidev *, int);
  13. int (*_pcmspecial)(char *, ISAConf *);
  14. void (*_pcmspecialclose)(int);
  15. int
  16. pcmspecial(char *idstr, ISAConf *isa)
  17. {
  18. return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
  19. }
  20. void
  21. pcmspecialclose(int a)
  22. {
  23. if (_pcmspecialclose != nil)
  24. _pcmspecialclose(a);
  25. }
  26. static ulong
  27. ioreserve(ulong, int size, int align, char *)
  28. {
  29. static ulong isaend = 0x400; /*0xfd00*/
  30. ulong ioaddr;
  31. if (align)
  32. isaend = ((isaend + align - 1) / align) * align;
  33. ioaddr = isaend;
  34. isaend += size;
  35. return ioaddr;
  36. }
  37. #define MAP(x,o) (Rmap + (x)*0x8 + o)
  38. enum {
  39. TI_vid = 0x104c,
  40. TI_1131_did = 0xAC15,
  41. TI_1250_did = 0xAC16,
  42. TI_1450_did = 0xAC1B,
  43. TI_1251A_did = 0xAC1D,
  44. TI_1420_did = 0xAC51,
  45. Ricoh_vid = 0x1180,
  46. Ricoh_475_did = 0x0475,
  47. Ricoh_476_did = 0x0476,
  48. Ricoh_478_did = 0x0478,
  49. O2_vid = 0x1217,
  50. O2_OZ711M3_did = 0x7134,
  51. Nslots = 4, /* Maximum number of CardBus slots to use */
  52. K = 1024,
  53. M = K * K,
  54. LegacyAddr = 0x3e0,
  55. NUMEVENTS = 10,
  56. TI1131xSC = 0x80, // system control
  57. TI122X_SC_INTRTIE = 1 << 29,
  58. TI12xxIM = 0x8c, //
  59. TI1131xCC = 0x91, // card control
  60. TI113X_CC_RIENB = 1 << 7,
  61. TI113X_CC_ZVENABLE = 1 << 6,
  62. TI113X_CC_PCI_IRQ_ENA = 1 << 5,
  63. TI113X_CC_PCI_IREQ = 1 << 4,
  64. TI113X_CC_PCI_CSC = 1 << 3,
  65. TI113X_CC_SPKROUTEN = 1 << 1,
  66. TI113X_CC_IFG = 1 << 0,
  67. TI1131xDC = 0x92, // device control
  68. };
  69. typedef struct Variant Variant;
  70. struct Variant {
  71. ushort vid;
  72. ushort did;
  73. char *name;
  74. };
  75. static Variant variant[] = {
  76. { Ricoh_vid, Ricoh_475_did, "Ricoh 475 PCI/Cardbus bridge", },
  77. { Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", },
  78. { Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", },
  79. { TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", },
  80. { TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", },
  81. { TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", },
  82. { TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", },
  83. { TI_vid, TI_1420_did, "TI PCI-1420 Cardbus Controller", },
  84. { O2_vid, O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
  85. };
  86. /* Cardbus registers */
  87. enum {
  88. SocketEvent = 0,
  89. SE_CCD = 3 << 1,
  90. SE_POWER = 1 << 3,
  91. SocketMask = 1,
  92. SocketState = 2,
  93. SS_CCD = 3 << 1,
  94. SS_POWER = 1 << 3,
  95. SS_PC16 = 1 << 4,
  96. SS_CBC = 1 << 5,
  97. SS_NOTCARD = 1 << 7,
  98. SS_BADVCC = 1 << 9,
  99. SS_5V = 1 << 10,
  100. SS_3V = 1 << 11,
  101. SocketForce = 3,
  102. SocketControl = 4,
  103. SC_5V = 0x22,
  104. SC_3V = 0x33,
  105. };
  106. enum {
  107. PciPCR_IO = 1 << 0,
  108. PciPCR_MEM = 1 << 1,
  109. PciPCR_Master = 1 << 2,
  110. PciPMC = 0xa4,
  111. Nbars = 6,
  112. Ncmd = 10,
  113. CBIRQ = 9,
  114. PC16,
  115. PC32,
  116. };
  117. enum {
  118. Ti82365,
  119. Tpd6710,
  120. Tpd6720,
  121. Tvg46x,
  122. };
  123. /*
  124. * Intel 82365SL PCIC controller for the PCMCIA or
  125. * Cirrus Logic PD6710/PD6720 which is mostly register compatible
  126. */
  127. enum
  128. {
  129. /*
  130. * registers indices
  131. */
  132. Rid= 0x0, /* identification and revision */
  133. Ris= 0x1, /* interface status */
  134. Rpc= 0x2, /* power control */
  135. Foutena= (1<<7), /* output enable */
  136. Fautopower= (1<<5), /* automatic power switching */
  137. Fcardena= (1<<4), /* PC card enable */
  138. Rigc= 0x3, /* interrupt and general control */
  139. Fiocard= (1<<5), /* I/O card (vs memory) */
  140. Fnotreset= (1<<6), /* reset if not set */
  141. FSMIena= (1<<4), /* enable change interrupt on SMI */
  142. Rcsc= 0x4, /* card status change */
  143. Rcscic= 0x5, /* card status change interrupt config */
  144. Fchangeena= (1<<3), /* card changed */
  145. Fbwarnena= (1<<1), /* card battery warning */
  146. Fbdeadena= (1<<0), /* card battery dead */
  147. Rwe= 0x6, /* address window enable */
  148. Fmem16= (1<<5), /* use A23-A12 to decode address */
  149. Rio= 0x7, /* I/O control */
  150. Fwidth16= (1<<0), /* 16 bit data width */
  151. Fiocs16= (1<<1), /* IOCS16 determines data width */
  152. Fzerows= (1<<2), /* zero wait state */
  153. Ftiming= (1<<3), /* timing register to use */
  154. Riobtm0lo= 0x8, /* I/O address 0 start low byte */
  155. Riobtm0hi= 0x9, /* I/O address 0 start high byte */
  156. Riotop0lo= 0xa, /* I/O address 0 stop low byte */
  157. Riotop0hi= 0xb, /* I/O address 0 stop high byte */
  158. Riobtm1lo= 0xc, /* I/O address 1 start low byte */
  159. Riobtm1hi= 0xd, /* I/O address 1 start high byte */
  160. Riotop1lo= 0xe, /* I/O address 1 stop low byte */
  161. Riotop1hi= 0xf, /* I/O address 1 stop high byte */
  162. Rmap= 0x10, /* map 0 */
  163. /*
  164. * CL-PD67xx extension registers
  165. */
  166. Rmisc1= 0x16, /* misc control 1 */
  167. F5Vdetect= (1<<0),
  168. Fvcc3V= (1<<1),
  169. Fpmint= (1<<2),
  170. Fpsirq= (1<<3),
  171. Fspeaker= (1<<4),
  172. Finpack= (1<<7),
  173. Rfifo= 0x17, /* fifo control */
  174. Fflush= (1<<7), /* flush fifo */
  175. Rmisc2= 0x1E, /* misc control 2 */
  176. Flowpow= (1<<1), /* low power mode */
  177. Rchipinfo= 0x1F, /* chip information */
  178. Ratactl= 0x26, /* ATA control */
  179. /*
  180. * offsets into the system memory address maps
  181. */
  182. Mbtmlo= 0x0, /* System mem addr mapping start low byte */
  183. Mbtmhi= 0x1, /* System mem addr mapping start high byte */
  184. F16bit= (1<<7), /* 16-bit wide data path */
  185. Mtoplo= 0x2, /* System mem addr mapping stop low byte */
  186. Mtophi= 0x3, /* System mem addr mapping stop high byte */
  187. Ftimer1= (1<<6), /* timer set 1 */
  188. Mofflo= 0x4, /* Card memory offset address low byte */
  189. Moffhi= 0x5, /* Card memory offset address high byte */
  190. Fregactive= (1<<6), /* attribute memory */
  191. /*
  192. * configuration registers - they start at an offset in attribute
  193. * memory found in the CIS.
  194. */
  195. Rconfig= 0,
  196. Creset= (1<<7), /* reset device */
  197. Clevel= (1<<6), /* level sensitive interrupt line */
  198. };
  199. /*
  200. * read and crack the card information structure enough to set
  201. * important parameters like power
  202. */
  203. /* cis memory walking */
  204. typedef struct Cisdat Cisdat;
  205. struct Cisdat {
  206. uchar *cisbase;
  207. int cispos;
  208. int cisskip;
  209. int cislen;
  210. };
  211. typedef struct Pcminfo Pcminfo;
  212. struct Pcminfo {
  213. char verstr[512]; /* Version string */
  214. PCMmap mmap[4]; /* maps, last is always for the kernel */
  215. ulong conf_addr; /* Config address */
  216. uchar conf_present; /* Config register present */
  217. int nctab; /* In use configuration tables */
  218. PCMconftab ctab[8]; /* Configuration tables */
  219. PCMconftab *defctab; /* Default conftab */
  220. int port; /* Actual port usage */
  221. int irq; /* Actual IRQ usage */
  222. };
  223. typedef struct Cardbus Cardbus;
  224. struct Cardbus {
  225. Lock;
  226. Variant *variant; /* Which CardBus chipset */
  227. Pcidev *pci; /* The bridge itself */
  228. ulong *regs; /* Cardbus registers */
  229. int ltype; /* Legacy type */
  230. int lindex; /* Legacy port index address */
  231. int ldata; /* Legacy port data address */
  232. int lbase; /* Base register for this socket */
  233. int state; /* Current state of card */
  234. int type; /* Type of card */
  235. Pcminfo linfo; /* PCMCIA slot info */
  236. int special; /* card is allocated to a driver */
  237. int refs; /* Number of refs to slot */
  238. Lock refslock; /* inc/dev ref lock */
  239. };
  240. enum {
  241. Mshift= 12,
  242. Mgran= (1<<Mshift), /* granularity of maps */
  243. Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
  244. };
  245. static Cardbus cbslots[Nslots];
  246. static int nslots;
  247. static ulong exponent[8] = {
  248. 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
  249. };
  250. static ulong vmant[16] = {
  251. 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
  252. };
  253. static ulong mantissa[16] = {
  254. 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
  255. };
  256. static void cbint(Ureg *, void *);
  257. static int powerup(Cardbus *);
  258. static void configure(Cardbus *);
  259. static void managecard(Cardbus *);
  260. static void cardmanager(void *);
  261. static void eject(Cardbus *);
  262. static void interrupt(Ureg *, void *);
  263. static void powerdown(Cardbus *cb);
  264. static void unconfigure(Cardbus *cb);
  265. static void i82365probe(Cardbus *cb, int lindex, int ldata);
  266. static void i82365configure(Cardbus *cb);
  267. static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
  268. static void isaunmap(PCMmap* m);
  269. static uchar rdreg(Cardbus *cb, int index);
  270. static void wrreg(Cardbus *cb, int index, uchar val);
  271. static int readc(Cisdat *cis, uchar *x);
  272. static void tvers1(Cardbus *cb, Cisdat *cis, int );
  273. static void tcfig(Cardbus *cb, Cisdat *cis, int );
  274. static void tentry(Cardbus *cb, Cisdat *cis, int );
  275. static int vcode(int volt);
  276. static int pccard_pcmspecial(char *idstr, ISAConf *isa);
  277. static void pccard_pcmspecialclose(int slotno);
  278. enum {
  279. CardDetected,
  280. CardPowered,
  281. CardEjected,
  282. CardConfigured,
  283. };
  284. static char *messages[] = {
  285. [CardDetected] "CardDetected",
  286. [CardPowered] "CardPowered",
  287. [CardEjected] "CardEjected",
  288. [CardConfigured] "CardConfigured",
  289. };
  290. enum {
  291. SlotEmpty,
  292. SlotFull,
  293. SlotPowered,
  294. SlotConfigured,
  295. };
  296. static char *states[] = {
  297. [SlotEmpty] "SlotEmpty",
  298. [SlotFull] "SlotFull",
  299. [SlotPowered] "SlotPowered",
  300. [SlotConfigured] "SlotConfigured",
  301. };
  302. static void
  303. engine(Cardbus *cb, int message)
  304. {
  305. // print("engine(%d): %s(%s)\n",
  306. // (int)(cb - cbslots), states[cb->state], messages[message]);
  307. switch (cb->state) {
  308. case SlotEmpty:
  309. switch (message) {
  310. case CardDetected:
  311. cb->state = SlotFull;
  312. powerup(cb);
  313. break;
  314. case CardEjected:
  315. break;
  316. default:
  317. //print("#Y%d: Invalid message %s in SlotEmpty state\n",
  318. // (int)(cb - cbslots), messages[message]);
  319. break;
  320. }
  321. break;
  322. case SlotFull:
  323. switch (message) {
  324. case CardPowered:
  325. cb->state = SlotPowered;
  326. configure(cb);
  327. break;
  328. case CardEjected:
  329. cb->state = SlotEmpty;
  330. powerdown(cb);
  331. break;
  332. default:
  333. //print("#Y%d: Invalid message %s in SlotFull state\n",
  334. // (int)(cb - cbslots), messages[message]);
  335. break;
  336. }
  337. break;
  338. case SlotPowered:
  339. switch (message) {
  340. case CardConfigured:
  341. cb->state = SlotConfigured;
  342. break;
  343. case CardEjected:
  344. cb->state = SlotEmpty;
  345. unconfigure(cb);
  346. powerdown(cb);
  347. break;
  348. default:
  349. print("#Y%d: Invalid message %s in SlotPowered state\n",
  350. (int)(cb - cbslots), messages[message]);
  351. break;
  352. }
  353. break;
  354. case SlotConfigured:
  355. switch (message) {
  356. case CardEjected:
  357. cb->state = SlotEmpty;
  358. unconfigure(cb);
  359. powerdown(cb);
  360. break;
  361. default:
  362. //print("#Y%d: Invalid message %s in SlotConfigured state\n",
  363. // (int)(cb - cbslots), messages[message]);
  364. break;
  365. }
  366. break;
  367. }
  368. }
  369. void
  370. devpccardlink(void)
  371. {
  372. static int initialized;
  373. Pcidev *pci;
  374. int i;
  375. char *p;
  376. if (initialized)
  377. return;
  378. initialized = 1;
  379. if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
  380. return;
  381. if(_pcmspecial)
  382. return;
  383. /* Allocate legacy space */
  384. if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
  385. print("#Y: WARNING: Cannot allocate legacy ports\n");
  386. /* Find all CardBus controllers */
  387. pci = nil;
  388. while ((pci = pcimatch(pci, 0, 0)) != nil) {
  389. ulong baddr;
  390. uchar pin;
  391. Cardbus *cb;
  392. int slot;
  393. if(pci->ccrb != 6 || pci->ccru != 7)
  394. continue;
  395. for (i = 0; i != nelem(variant); i++)
  396. if (pci->vid == variant[i].vid && pci->did == variant[i].did)
  397. break;
  398. if (i == nelem(variant))
  399. continue;
  400. /* initialize this slot */
  401. slot = nslots++;
  402. cb = &cbslots[slot];
  403. cb->pci = pci;
  404. cb->variant = &variant[i];
  405. // Set up PCI bus numbers if needed.
  406. if (pcicfgr8(pci, PciSBN) == 0) {
  407. static int busbase = 0x20;
  408. pcicfgw8(pci, PciSBN, busbase);
  409. pcicfgw8(pci, PciUBN, busbase + 2);
  410. busbase += 3;
  411. }
  412. // Patch up intl if needed.
  413. if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
  414. (pci->intl == 0xff || pci->intl == 0)) {
  415. pci->intl = pciipin(nil, pin);
  416. pcicfgw8(pci, PciINTL, pci->intl);
  417. if (pci->intl == 0xff || pci->intl == 0)
  418. print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
  419. }
  420. // Don't you love standards!
  421. if (pci->vid == TI_vid) {
  422. if (pci->did <= TI_1131_did) {
  423. uchar cc;
  424. cc = pcicfgr8(pci, TI1131xCC);
  425. cc &= ~(TI113X_CC_PCI_IRQ_ENA |
  426. TI113X_CC_PCI_IREQ |
  427. TI113X_CC_PCI_CSC |
  428. TI113X_CC_ZVENABLE);
  429. cc |= TI113X_CC_PCI_IRQ_ENA |
  430. TI113X_CC_PCI_IREQ |
  431. TI113X_CC_SPKROUTEN;
  432. pcicfgw8(pci, TI1131xCC, cc);
  433. // PCI interrupts only
  434. pcicfgw8(pci, TI1131xDC,
  435. pcicfgr8(pci, TI1131xDC) & ~6);
  436. // CSC ints to PCI bus.
  437. wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
  438. }
  439. else if (pci->did == TI_1250_did) {
  440. print("No support yet for the TI_1250_did, prod pb\n");
  441. }
  442. else if (pci->did == TI_1420_did) {
  443. // Disable Vcc protection
  444. pcicfgw32(cb->pci, 0x80,
  445. pcicfgr32(cb->pci, 0x80) | (1 << 21));
  446. }
  447. pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
  448. }
  449. if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
  450. int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
  451. baddr = upamalloc(baddr, size, size);
  452. pcicfgw32(cb->pci, PciBAR0, baddr);
  453. cb->regs = (ulong *)KADDR(baddr);
  454. }
  455. else
  456. cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
  457. cb->state = SlotEmpty;
  458. /* Don't really know what to do with this... */
  459. i82365probe(cb, LegacyAddr, LegacyAddr + 1);
  460. print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
  461. variant[i].name, baddr, pci->intl);
  462. }
  463. if (nslots == 0)
  464. return;
  465. _pcmspecial = pccard_pcmspecial;
  466. _pcmspecialclose = pccard_pcmspecialclose;
  467. for (i = 0; i != nslots; i++) {
  468. Cardbus *cb = &cbslots[i];
  469. if ((cb->regs[SocketState] & SE_CCD) == 0)
  470. engine(cb, CardDetected);
  471. }
  472. delay(500); /* Allow time for power up */
  473. for (i = 0; i != nslots; i++) {
  474. Cardbus *cb = &cbslots[i];
  475. if (cb->regs[SocketState] & SE_POWER)
  476. engine(cb, CardPowered);
  477. /* Ack and enable interrupts on all events */
  478. //cb->regs[SocketEvent] = cb->regs[SocketEvent];
  479. //cb->regs[SocketMask] |= 0xF;
  480. //wrreg(cb, Rcscic, 0xC);
  481. }
  482. }
  483. static int
  484. powerup(Cardbus *cb)
  485. {
  486. ulong state;
  487. ushort bcr;
  488. state = cb->regs[SocketState];
  489. if (state & SS_PC16) {
  490. // print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
  491. cb->type = PC16;
  492. memset(&cb->linfo, 0, sizeof(Pcminfo));
  493. /* power up and unreset, wait's are empirical (???) */
  494. wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
  495. delay(300);
  496. wrreg(cb, Rigc, 0);
  497. delay(100);
  498. wrreg(cb, Rigc, Fnotreset);
  499. delay(500);
  500. return 1;
  501. }
  502. if (state & SS_CCD)
  503. return 0;
  504. if (state & SS_NOTCARD) {
  505. print("#Y%ld: No card inserted\n", cb - cbslots);
  506. return 0;
  507. }
  508. if (state & SS_BADVCC) {
  509. print("#Y%ld: Bad VCC request to card, powering down card!\n",
  510. cb - cbslots);
  511. cb->regs[SocketControl] = 0;
  512. return 0;
  513. }
  514. if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
  515. print("#Y%ld: Unsupported voltage, powering down card!\n",
  516. cb - cbslots);
  517. cb->regs[SocketControl] = 0;
  518. return 0;
  519. }
  520. //print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
  521. // (state & SS_POWER)? "": "not ",
  522. // (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
  523. /* Power up the card
  524. * and make sure the secondary bus is not in reset.
  525. */
  526. cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
  527. delay(50);
  528. bcr = pcicfgr16(cb->pci, PciBCR);
  529. bcr &= ~0x40;
  530. pcicfgw16(cb->pci, PciBCR, bcr);
  531. delay(100);
  532. cb->type = PC32;
  533. return 1;
  534. }
  535. static void
  536. powerdown(Cardbus *cb)
  537. {
  538. ushort bcr;
  539. if (cb->type == PC16) {
  540. wrreg(cb, Rpc, 0); /* turn off card power */
  541. wrreg(cb, Rwe, 0); /* no windows */
  542. cb->type = -1;
  543. return;
  544. }
  545. bcr = pcicfgr16(cb->pci, PciBCR);
  546. bcr |= 0x40;
  547. pcicfgw16(cb->pci, PciBCR, bcr);
  548. cb->regs[SocketControl] = 0;
  549. cb->type = -1;
  550. }
  551. static void
  552. configure(Cardbus *cb)
  553. {
  554. Pcidev *pci;
  555. ulong size, bar;
  556. int i, ioindex, memindex, r;
  557. //print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
  558. if (cb->state == SlotConfigured)
  559. return;
  560. engine(cb, CardConfigured);
  561. delay(50); /* Emperically established */
  562. if (cb->type == PC16) {
  563. i82365configure(cb);
  564. return;
  565. }
  566. /* Scan the CardBus for new PCI devices */
  567. pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
  568. pci = cb->pci->bridge;
  569. while (pci) {
  570. r = pcicfgr16(pci, PciPCR);
  571. r &= ~(PciPCR_IO|PciPCR_MEM);
  572. pcicfgw16(pci, PciPCR, r);
  573. /*
  574. * Treat the found device as an ordinary PCI card.
  575. * It seems that the CIS is not always present in
  576. * CardBus cards.
  577. * XXX, need to support multifunction cards
  578. */
  579. memindex = ioindex = 0;
  580. for (i = 0; i != Nbars; i++) {
  581. if (pci->mem[i].size == 0)
  582. continue;
  583. if (pci->mem[i].bar & 1) {
  584. // Allocate I/O space
  585. if (ioindex > 1) {
  586. print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
  587. continue;
  588. }
  589. bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
  590. pci->mem[i].bar = bar | 1;
  591. pcicfgw32(pci, PciBAR0 + i * sizeof(ulong),
  592. pci->mem[i].bar);
  593. pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
  594. pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8,
  595. bar + pci->mem[i].size - 1);
  596. //print("ioindex[%d] %.8uX (%d)\n",
  597. // ioindex, bar, pci->mem[i].size);
  598. ioindex++;
  599. continue;
  600. }
  601. // Allocating memory space
  602. if (memindex > 1) {
  603. print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
  604. continue;
  605. }
  606. bar = upamalloc(0, pci->mem[i].size, BY2PG);
  607. pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
  608. pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
  609. pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
  610. pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
  611. bar + pci->mem[i].size - 1);
  612. if (pci->mem[i].bar & 0x80) {
  613. /* Enable prefetch */
  614. r = pcicfgr16(cb->pci, PciBCR);
  615. r |= 1 << (8 + memindex);
  616. pcicfgw16(cb->pci, PciBCR, r);
  617. }
  618. //print("memindex[%d] %.8uX (%d)\n",
  619. // memindex, bar, pci->mem[i].size);
  620. memindex++;
  621. }
  622. if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
  623. if (memindex > 1)
  624. print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
  625. cb - cbslots);
  626. else {
  627. pci->rom.bar = upamalloc(0, size, BY2PG);
  628. pci->rom.size = size;
  629. pcicfgw32(pci, PciEBAR0, pci->rom.bar);
  630. pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
  631. pci->rom.bar);
  632. pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
  633. pci->rom.bar + pci->rom.size - 1);
  634. }
  635. }
  636. /* Set the basic PCI registers for the device */
  637. pci->pcr = pcicfgr16(pci, PciPCR);
  638. pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
  639. pci->cls = 8;
  640. pci->ltr = 64;
  641. pcicfgw16(pci, PciPCR, pci->pcr);
  642. pcicfgw8(pci, PciCLS, pci->cls);
  643. pcicfgw8(pci, PciLTR, pci->ltr);
  644. if (pcicfgr8(pci, PciINTP)) {
  645. pci->intl = pcicfgr8(cb->pci, PciINTL);
  646. pcicfgw8(pci, PciINTL, pci->intl);
  647. /* Route interrupts to INTA#/B# */
  648. pcicfgw16(cb->pci, PciBCR,
  649. pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
  650. }
  651. pci = pci->list;
  652. }
  653. }
  654. static void
  655. unconfigure(Cardbus *cb)
  656. {
  657. Pcidev *pci;
  658. int i, ioindex, memindex, r;
  659. if (cb->type == PC16) {
  660. print("#Y%d: Don't know how to unconfigure a PC16 card\n",
  661. (int)(cb - cbslots));
  662. memset(&cb->linfo, 0, sizeof(Pcminfo));
  663. return;
  664. }
  665. pci = cb->pci->bridge;
  666. if (pci == nil)
  667. return; /* Not configured */
  668. cb->pci->bridge = nil;
  669. memindex = ioindex = 0;
  670. while (pci) {
  671. Pcidev *_pci;
  672. for (i = 0; i != Nbars; i++) {
  673. if (pci->mem[i].size == 0)
  674. continue;
  675. if (pci->mem[i].bar & 1) {
  676. iofree(pci->mem[i].bar & ~1);
  677. pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
  678. (ushort)-1);
  679. pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
  680. ioindex++;
  681. continue;
  682. }
  683. upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
  684. pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
  685. pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
  686. r = pcicfgr16(cb->pci, PciBCR);
  687. r &= ~(1 << (8 + memindex));
  688. pcicfgw16(cb->pci, PciBCR, r);
  689. memindex++;
  690. }
  691. if (pci->rom.bar && memindex < 2) {
  692. upafree(pci->rom.bar & ~0xF, pci->rom.size);
  693. pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
  694. pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
  695. memindex++;
  696. }
  697. _pci = pci->list;
  698. free(_pci);
  699. pci = _pci;
  700. }
  701. }
  702. static void
  703. i82365configure(Cardbus *cb)
  704. {
  705. int this;
  706. Cisdat cis;
  707. PCMmap *m;
  708. uchar type, link;
  709. /*
  710. * Read all tuples in attribute space.
  711. */
  712. m = isamap(cb, 0, 0, 1);
  713. if(m == 0)
  714. return;
  715. cis.cisbase = KADDR(m->isa);
  716. cis.cispos = 0;
  717. cis.cisskip = 2;
  718. cis.cislen = m->len;
  719. /* loop through all the tuples */
  720. for(;;){
  721. this = cis.cispos;
  722. if(readc(&cis, &type) != 1)
  723. break;
  724. if(type == 0xFF)
  725. break;
  726. if(readc(&cis, &link) != 1)
  727. break;
  728. switch(type){
  729. default:
  730. break;
  731. case 0x15:
  732. tvers1(cb, &cis, type);
  733. break;
  734. case 0x1A:
  735. tcfig(cb, &cis, type);
  736. break;
  737. case 0x1B:
  738. tentry(cb, &cis, type);
  739. break;
  740. }
  741. if(link == 0xFF)
  742. break;
  743. cis.cispos = this + (2+link);
  744. }
  745. isaunmap(m);
  746. }
  747. /*
  748. * look for a card whose version contains 'idstr'
  749. */
  750. static int
  751. pccard_pcmspecial(char *idstr, ISAConf *isa)
  752. {
  753. int i, irq;
  754. PCMconftab *ct, *et;
  755. Pcminfo *pi;
  756. Cardbus *cb;
  757. uchar x, we, *p;
  758. cb = nil;
  759. for (i = 0; i != nslots; i++) {
  760. cb = &cbslots[i];
  761. lock(cb);
  762. if (cb->state == SlotConfigured &&
  763. cb->type == PC16 &&
  764. !cb->special &&
  765. strstr(cb->linfo.verstr, idstr))
  766. break;
  767. unlock(cb);
  768. }
  769. if (i == nslots) {
  770. // print("#Y: %s not found\n", idstr);
  771. return -1;
  772. }
  773. pi = &cb->linfo;
  774. /*
  775. * configure the PCMslot for IO. We assume very heavily that we can read
  776. * configuration info from the CIS. If not, we won't set up correctly.
  777. */
  778. irq = isa->irq;
  779. if(irq == 2)
  780. irq = 9;
  781. et = &pi->ctab[pi->nctab];
  782. ct = nil;
  783. for(i = 0; i < isa->nopt; i++){
  784. int index;
  785. char *cp;
  786. if(strncmp(isa->opt[i], "index=", 6))
  787. continue;
  788. index = strtol(&isa->opt[i][6], &cp, 0);
  789. if(cp == &isa->opt[i][6] || index >= pi->nctab) {
  790. unlock(cb);
  791. print("#Y%d: Cannot find index %d in conf table\n",
  792. (int)(cb - cbslots), index);
  793. return -1;
  794. }
  795. ct = &pi->ctab[index];
  796. }
  797. if(ct == nil){
  798. PCMconftab *t;
  799. /* assume default is right */
  800. if(pi->defctab)
  801. ct = pi->defctab;
  802. else
  803. ct = pi->ctab;
  804. /* try for best match */
  805. if(ct->nio == 0
  806. || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
  807. for(t = pi->ctab; t < et; t++)
  808. if(t->nio
  809. && t->io[0].start == isa->port
  810. && ((1<<irq) & t->irqs)){
  811. ct = t;
  812. break;
  813. }
  814. }
  815. if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
  816. for(t = pi->ctab; t < et; t++)
  817. if(t->nio && ((1<<irq) & t->irqs)){
  818. ct = t;
  819. break;
  820. }
  821. }
  822. if(ct->nio == 0){
  823. for(t = pi->ctab; t < et; t++)
  824. if(t->nio){
  825. ct = t;
  826. break;
  827. }
  828. }
  829. }
  830. if(ct == et || ct->nio == 0) {
  831. unlock(cb);
  832. print("#Y%d: No configuration?\n", (int)(cb - cbslots));
  833. return -1;
  834. }
  835. if(isa->port == 0 && ct->io[0].start == 0) {
  836. unlock(cb);
  837. print("#Y%d: No part or start address\n", (int)(cb - cbslots));
  838. return -1;
  839. }
  840. cb->special = 1; /* taken */
  841. /* route interrupts */
  842. isa->irq = irq;
  843. wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
  844. /* set power and enable device */
  845. x = vcode(ct->vpp1);
  846. wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
  847. /* 16-bit data path */
  848. if(ct->bit16)
  849. x = Ftiming|Fiocs16|Fwidth16;
  850. else
  851. x = Ftiming;
  852. if(ct->nio == 2 && ct->io[1].start)
  853. x |= x<<4;
  854. wrreg(cb, Rio, x);
  855. /*
  856. * enable io port map 0
  857. * the 'top' register value includes the last valid address
  858. */
  859. if(isa->port == 0)
  860. isa->port = ct->io[0].start;
  861. we = rdreg(cb, Rwe);
  862. wrreg(cb, Riobtm0lo, isa->port);
  863. wrreg(cb, Riobtm0hi, isa->port>>8);
  864. i = isa->port+ct->io[0].len-1;
  865. wrreg(cb, Riotop0lo, i);
  866. wrreg(cb, Riotop0hi, i>>8);
  867. we |= 1<<6;
  868. if(ct->nio == 2 && ct->io[1].start){
  869. wrreg(cb, Riobtm1lo, ct->io[1].start);
  870. wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
  871. i = ct->io[1].start+ct->io[1].len-1;
  872. wrreg(cb, Riotop1lo, i);
  873. wrreg(cb, Riotop1hi, i>>8);
  874. we |= 1<<7;
  875. }
  876. wrreg(cb, Rwe, we);
  877. /* only touch Rconfig if it is present */
  878. if(pi->conf_present & (1<<Rconfig)){
  879. PCMmap *m;
  880. /* Reset adapter */
  881. m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
  882. p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
  883. /* set configuration and interrupt type */
  884. x = ct->index;
  885. if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
  886. x |= Clevel;
  887. *p = x;
  888. delay(5);
  889. isaunmap(m);
  890. }
  891. pi->port = isa->port;
  892. pi->irq = isa->irq;
  893. unlock(cb);
  894. print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
  895. return (int)(cb - cbslots);
  896. }
  897. static void
  898. pccard_pcmspecialclose(int slotno)
  899. {
  900. Cardbus *cb = &cbslots[slotno];
  901. wrreg(cb, Rwe, 0); /* no windows */
  902. cb->special = 0;
  903. }
  904. static int
  905. xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
  906. {
  907. PCMmap *m;
  908. Cisdat cis;
  909. int i, l;
  910. uchar *p;
  911. uchar type, link, n, c;
  912. int this, subtype;
  913. Cardbus *cb = &cbslots[slotno];
  914. m = isamap(cb, 0, 0, attr);
  915. if(m == 0)
  916. return -1;
  917. cis.cisbase = KADDR(m->isa);
  918. cis.cispos = 0;
  919. cis.cisskip = attr ? 2 : 1;
  920. cis.cislen = m->len;
  921. /* loop through all the tuples */
  922. for(i = 0; i < 1000; i++){
  923. this = cis.cispos;
  924. if(readc(&cis, &type) != 1)
  925. break;
  926. if(type == 0xFF)
  927. break;
  928. if(readc(&cis, &link) != 1)
  929. break;
  930. if(link == 0xFF)
  931. break;
  932. n = link;
  933. if (link > 1 && subtuple != -1) {
  934. if (readc(&cis, &c) != 1)
  935. break;
  936. subtype = c;
  937. n--;
  938. } else
  939. subtype = -1;
  940. if(type == tuple && subtype == subtuple) {
  941. p = v;
  942. for(l=0; l<nv && l<n; l++)
  943. if(readc(&cis, p++) != 1)
  944. break;
  945. isaunmap(m);
  946. return nv;
  947. }
  948. cis.cispos = this + (2+link);
  949. }
  950. isaunmap(m);
  951. return -1;
  952. }
  953. static PCMmap *
  954. isamap(Cardbus *cb, ulong offset, int len, int attr)
  955. {
  956. uchar we, bit;
  957. PCMmap *m, *nm;
  958. Pcminfo *pi;
  959. int i;
  960. ulong e;
  961. pi = &cb->linfo;
  962. /* convert offset to granularity */
  963. if(len <= 0)
  964. len = 1;
  965. e = ROUND(offset+len, Mgran);
  966. offset &= Mmask;
  967. len = e - offset;
  968. /* look for a map that covers the right area */
  969. we = rdreg(cb, Rwe);
  970. bit = 1;
  971. nm = 0;
  972. for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
  973. if((we & bit))
  974. if(m->attr == attr)
  975. if(offset >= m->ca && e <= m->cea){
  976. m->ref++;
  977. return m;
  978. }
  979. bit <<= 1;
  980. if(nm == 0 && m->ref == 0)
  981. nm = m;
  982. }
  983. m = nm;
  984. if(m == 0)
  985. return 0;
  986. /* if isa space isn't big enough, free it and get more */
  987. if(m->len < len){
  988. if(m->isa){
  989. umbfree(m->isa, m->len);
  990. m->len = 0;
  991. }
  992. m->isa = PADDR(umbmalloc(0, len, Mgran));
  993. if(m->isa == 0){
  994. print("isamap: out of isa space\n");
  995. return 0;
  996. }
  997. m->len = len;
  998. }
  999. /* set up new map */
  1000. m->ca = offset;
  1001. m->cea = m->ca + m->len;
  1002. m->attr = attr;
  1003. i = m - pi->mmap;
  1004. bit = 1<<i;
  1005. wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */
  1006. wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
  1007. wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
  1008. wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
  1009. wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
  1010. offset -= m->isa;
  1011. offset &= (1<<25)-1;
  1012. offset >>= Mshift;
  1013. wrreg(cb, MAP(i, Mofflo), offset);
  1014. wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
  1015. wrreg(cb, Rwe, we | bit); /* enable map */
  1016. m->ref = 1;
  1017. return m;
  1018. }
  1019. static void
  1020. isaunmap(PCMmap* m)
  1021. {
  1022. m->ref--;
  1023. }
  1024. /*
  1025. * reading and writing card registers
  1026. */
  1027. static uchar
  1028. rdreg(Cardbus *cb, int index)
  1029. {
  1030. outb(cb->lindex, cb->lbase + index);
  1031. return inb(cb->ldata);
  1032. }
  1033. static void
  1034. wrreg(Cardbus *cb, int index, uchar val)
  1035. {
  1036. outb(cb->lindex, cb->lbase + index);
  1037. outb(cb->ldata, val);
  1038. }
  1039. static int
  1040. readc(Cisdat *cis, uchar *x)
  1041. {
  1042. if(cis->cispos >= cis->cislen)
  1043. return 0;
  1044. *x = cis->cisbase[cis->cisskip*cis->cispos];
  1045. cis->cispos++;
  1046. return 1;
  1047. }
  1048. static ulong
  1049. getlong(Cisdat *cis, int size)
  1050. {
  1051. uchar c;
  1052. int i;
  1053. ulong x;
  1054. x = 0;
  1055. for(i = 0; i < size; i++){
  1056. if(readc(cis, &c) != 1)
  1057. break;
  1058. x |= c<<(i*8);
  1059. }
  1060. return x;
  1061. }
  1062. static void
  1063. tcfig(Cardbus *cb, Cisdat *cis, int )
  1064. {
  1065. uchar size, rasize, rmsize;
  1066. uchar last;
  1067. Pcminfo *pi;
  1068. if(readc(cis, &size) != 1)
  1069. return;
  1070. rasize = (size&0x3) + 1;
  1071. rmsize = ((size>>2)&0xf) + 1;
  1072. if(readc(cis, &last) != 1)
  1073. return;
  1074. pi = &cb->linfo;
  1075. pi->conf_addr = getlong(cis, rasize);
  1076. pi->conf_present = getlong(cis, rmsize);
  1077. }
  1078. static void
  1079. tvers1(Cardbus *cb, Cisdat *cis, int )
  1080. {
  1081. uchar c, major, minor, last;
  1082. int i;
  1083. Pcminfo *pi;
  1084. pi = &cb->linfo;
  1085. if(readc(cis, &major) != 1)
  1086. return;
  1087. if(readc(cis, &minor) != 1)
  1088. return;
  1089. last = 0;
  1090. for(i = 0; i < sizeof(pi->verstr) - 1; i++){
  1091. if(readc(cis, &c) != 1)
  1092. return;
  1093. if(c == 0)
  1094. c = ';';
  1095. if(c == '\n')
  1096. c = ';';
  1097. if(c == 0xff)
  1098. break;
  1099. if(c == ';' && last == ';')
  1100. continue;
  1101. pi->verstr[i] = c;
  1102. last = c;
  1103. }
  1104. pi->verstr[i] = 0;
  1105. }
  1106. static ulong
  1107. microvolt(Cisdat *cis)
  1108. {
  1109. uchar c;
  1110. ulong microvolts;
  1111. ulong exp;
  1112. if(readc(cis, &c) != 1)
  1113. return 0;
  1114. exp = exponent[c&0x7];
  1115. microvolts = vmant[(c>>3)&0xf]*exp;
  1116. while(c & 0x80){
  1117. if(readc(cis, &c) != 1)
  1118. return 0;
  1119. switch(c){
  1120. case 0x7d:
  1121. break; /* high impedence when sleeping */
  1122. case 0x7e:
  1123. case 0x7f:
  1124. microvolts = 0; /* no connection */
  1125. break;
  1126. default:
  1127. exp /= 10;
  1128. microvolts += exp*(c&0x7f);
  1129. }
  1130. }
  1131. return microvolts;
  1132. }
  1133. static ulong
  1134. nanoamps(Cisdat *cis)
  1135. {
  1136. uchar c;
  1137. ulong nanoamps;
  1138. if(readc(cis, &c) != 1)
  1139. return 0;
  1140. nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
  1141. while(c & 0x80){
  1142. if(readc(cis, &c) != 1)
  1143. return 0;
  1144. if(c == 0x7d || c == 0x7e || c == 0x7f)
  1145. nanoamps = 0;
  1146. }
  1147. return nanoamps;
  1148. }
  1149. /*
  1150. * only nominal voltage (feature 1) is important for config,
  1151. * other features must read card to stay in sync.
  1152. */
  1153. static ulong
  1154. power(Cisdat *cis)
  1155. {
  1156. uchar feature;
  1157. ulong mv;
  1158. mv = 0;
  1159. if(readc(cis, &feature) != 1)
  1160. return 0;
  1161. if(feature & 1)
  1162. mv = microvolt(cis);
  1163. if(feature & 2)
  1164. microvolt(cis);
  1165. if(feature & 4)
  1166. microvolt(cis);
  1167. if(feature & 8)
  1168. nanoamps(cis);
  1169. if(feature & 0x10)
  1170. nanoamps(cis);
  1171. if(feature & 0x20)
  1172. nanoamps(cis);
  1173. if(feature & 0x40)
  1174. nanoamps(cis);
  1175. return mv/1000000;
  1176. }
  1177. static ulong
  1178. ttiming(Cisdat *cis, int scale)
  1179. {
  1180. uchar unscaled;
  1181. ulong nanosecs;
  1182. if(readc(cis, &unscaled) != 1)
  1183. return 0;
  1184. nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
  1185. nanosecs = nanosecs * exponent[scale];
  1186. return nanosecs;
  1187. }
  1188. static void
  1189. timing(Cisdat *cis, PCMconftab *ct)
  1190. {
  1191. uchar c, i;
  1192. if(readc(cis, &c) != 1)
  1193. return;
  1194. i = c&0x3;
  1195. if(i != 3)
  1196. ct->maxwait = ttiming(cis, i); /* max wait */
  1197. i = (c>>2)&0x7;
  1198. if(i != 7)
  1199. ct->readywait = ttiming(cis, i); /* max ready/busy wait */
  1200. i = (c>>5)&0x7;
  1201. if(i != 7)
  1202. ct->otherwait = ttiming(cis, i); /* reserved wait */
  1203. }
  1204. static void
  1205. iospaces(Cisdat *cis, PCMconftab *ct)
  1206. {
  1207. uchar c;
  1208. int i, nio;
  1209. ct->nio = 0;
  1210. if(readc(cis, &c) != 1)
  1211. return;
  1212. ct->bit16 = ((c>>5)&3) >= 2;
  1213. if(!(c & 0x80)){
  1214. ct->io[0].start = 0;
  1215. ct->io[0].len = 1<<(c&0x1f);
  1216. ct->nio = 1;
  1217. return;
  1218. }
  1219. if(readc(cis, &c) != 1)
  1220. return;
  1221. /*
  1222. * For each of the range descriptions read the
  1223. * start address and the length (value is length-1).
  1224. */
  1225. nio = (c&0xf)+1;
  1226. for(i = 0; i < nio; i++){
  1227. ct->io[i].start = getlong(cis, (c>>4)&0x3);
  1228. ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
  1229. }
  1230. ct->nio = nio;
  1231. }
  1232. static void
  1233. irq(Cisdat *cis, PCMconftab *ct)
  1234. {
  1235. uchar c;
  1236. if(readc(cis, &c) != 1)
  1237. return;
  1238. ct->irqtype = c & 0xe0;
  1239. if(c & 0x10)
  1240. ct->irqs = getlong(cis, 2);
  1241. else
  1242. ct->irqs = 1<<(c&0xf);
  1243. ct->irqs &= 0xDEB8; /* levels available to card */
  1244. }
  1245. static void
  1246. memspace(Cisdat *cis, int asize, int lsize, int host)
  1247. {
  1248. ulong haddress, address, len;
  1249. len = getlong(cis, lsize)*256;
  1250. address = getlong(cis, asize)*256;
  1251. USED(len, address);
  1252. if(host){
  1253. haddress = getlong(cis, asize)*256;
  1254. USED(haddress);
  1255. }
  1256. }
  1257. static void
  1258. tentry(Cardbus *cb, Cisdat *cis, int )
  1259. {
  1260. uchar c, i, feature;
  1261. PCMconftab *ct;
  1262. Pcminfo *pi;
  1263. pi = &cb->linfo;
  1264. if(pi->nctab >= nelem(pi->ctab))
  1265. return;
  1266. if(readc(cis, &c) != 1)
  1267. return;
  1268. ct = &pi->ctab[pi->nctab++];
  1269. /* copy from last default config */
  1270. if(pi->defctab)
  1271. *ct = *pi->defctab;
  1272. ct->index = c & 0x3f;
  1273. /* is this the new default? */
  1274. if(c & 0x40)
  1275. pi->defctab = ct;
  1276. /* memory wait specified? */
  1277. if(c & 0x80){
  1278. if(readc(cis, &i) != 1)
  1279. return;
  1280. if(i&0x80)
  1281. ct->memwait = 1;
  1282. }
  1283. if(readc(cis, &feature) != 1)
  1284. return;
  1285. switch(feature&0x3){
  1286. case 1:
  1287. ct->vpp1 = ct->vpp2 = power(cis);
  1288. break;
  1289. case 2:
  1290. power(cis);
  1291. ct->vpp1 = ct->vpp2 = power(cis);
  1292. break;
  1293. case 3:
  1294. power(cis);
  1295. ct->vpp1 = power(cis);
  1296. ct->vpp2 = power(cis);
  1297. break;
  1298. default:
  1299. break;
  1300. }
  1301. if(feature&0x4)
  1302. timing(cis, ct);
  1303. if(feature&0x8)
  1304. iospaces(cis, ct);
  1305. if(feature&0x10)
  1306. irq(cis, ct);
  1307. switch((feature>>5)&0x3){
  1308. case 1:
  1309. memspace(cis, 0, 2, 0);
  1310. break;
  1311. case 2:
  1312. memspace(cis, 2, 2, 0);
  1313. break;
  1314. case 3:
  1315. if(readc(cis, &c) != 1)
  1316. return;
  1317. for(i = 0; i <= (c&0x7); i++)
  1318. memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
  1319. break;
  1320. }
  1321. }
  1322. static void
  1323. i82365probe(Cardbus *cb, int lindex, int ldata)
  1324. {
  1325. uchar c, id;
  1326. int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem
  1327. to be the same socket A (ditto for B). */
  1328. outb(lindex, Rid + (dev<<7));
  1329. id = inb(ldata);
  1330. if((id & 0xf0) != 0x80)
  1331. return; /* not a memory & I/O card */
  1332. if((id & 0x0f) == 0x00)
  1333. return; /* no revision number, not possible */
  1334. cb->lindex = lindex;
  1335. cb->ldata = ldata;
  1336. cb->ltype = Ti82365;
  1337. cb->lbase = (int)(cb - cbslots) * 0x40;
  1338. switch(id){
  1339. case 0x82:
  1340. case 0x83:
  1341. case 0x84:
  1342. /* could be a cirrus */
  1343. outb(cb->lindex, Rchipinfo + (dev<<7));
  1344. outb(cb->ldata, 0);
  1345. c = inb(cb->ldata);
  1346. if((c & 0xc0) != 0xc0)
  1347. break;
  1348. c = inb(cb->ldata);
  1349. if((c & 0xc0) != 0x00)
  1350. break;
  1351. if(c & 0x20){
  1352. cb->ltype = Tpd6720;
  1353. } else {
  1354. cb->ltype = Tpd6710;
  1355. }
  1356. break;
  1357. }
  1358. /* if it's not a Cirrus, it could be a Vadem... */
  1359. if(cb->ltype == Ti82365){
  1360. /* unlock the Vadem extended regs */
  1361. outb(cb->lindex, 0x0E + (dev<<7));
  1362. outb(cb->lindex, 0x37 + (dev<<7));
  1363. /* make the id register show the Vadem id */
  1364. outb(cb->lindex, 0x3A + (dev<<7));
  1365. c = inb(cb->ldata);
  1366. outb(cb->ldata, c|0xC0);
  1367. outb(cb->lindex, Rid + (dev<<7));
  1368. c = inb(cb->ldata);
  1369. if(c & 0x08)
  1370. cb->ltype = Tvg46x;
  1371. /* go back to Intel compatible id */
  1372. outb(cb->lindex, 0x3A + (dev<<7));
  1373. c = inb(cb->ldata);
  1374. outb(cb->ldata, c & ~0xC0);
  1375. }
  1376. }
  1377. static int
  1378. vcode(int volt)
  1379. {
  1380. switch(volt){
  1381. case 5:
  1382. return 1;
  1383. case 12:
  1384. return 2;
  1385. default:
  1386. return 0;
  1387. }
  1388. }