Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4428 lines
92 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. tcicsup.c
  5. Abstract:
  6. This module supplies functions that control the Databook TCIC family
  7. of chips. In turn, these functions are abstracted out to the main PCMCIA
  8. support module.
  9. Author(s):
  10. (pcicsup.c - Source that this file was derived from)
  11. Bob Rinne (BobRi) 3-Aug-1994
  12. Jeff McLeman (mcleman@zso.dec.com)
  13. (tcicsup.c - this file)
  14. John Keys - Databook Inc. 7-Apr-1995
  15. Revisions:
  16. Overhaul for plug'n'play support
  17. Ravisankar Pudipeddi (ravisp) 8-Jan-1997
  18. new setpower and init routine interface
  19. Neil Sandlin (neilsa) 3-Mar-99
  20. --*/
  21. #include "pch.h"
  22. VOID
  23. TcicRegistryLookupScanLimits(
  24. PULONG Start,
  25. PULONG End
  26. );
  27. NTSTATUS
  28. TcicDetectSockets(
  29. IN PFDO_EXTENSION DeviceExtension,
  30. IN BOOLEAN LegacyDetection
  31. );
  32. BOOLEAN
  33. TcicInitializePcmciaSocket(
  34. IN PSOCKET SocketPtr
  35. );
  36. NTSTATUS
  37. TcicResetCard(
  38. IN PSOCKET SocketPtr,
  39. OUT PULONG pDelayTime
  40. );
  41. ULONG
  42. TcicReadCardMemory(
  43. IN PPDO_EXTENSION PdoExtension,
  44. IN MEMORY_SPACE MemorySpace,
  45. IN ULONG Offset,
  46. IN PUCHAR Buffer,
  47. IN ULONG Length
  48. );
  49. ULONG
  50. TcicWriteCardMemory(
  51. IN PPDO_EXTENSION PdoExtension,
  52. IN MEMORY_SPACE MemorySpace,
  53. IN ULONG Offset,
  54. IN PUCHAR Buffer,
  55. IN ULONG Length
  56. );
  57. BOOLEAN
  58. TcicDetectCardInSocket(
  59. IN PSOCKET SocketPtr
  60. );
  61. BOOLEAN
  62. TcicDetectCardChanged(
  63. IN PSOCKET SocketPtr
  64. );
  65. BOOLEAN
  66. TcicDetectReadyChanged(
  67. IN PSOCKET SocketPtr
  68. );
  69. NTSTATUS
  70. TcicGetPowerRequirements(
  71. IN PSOCKET Socket
  72. );
  73. BOOLEAN
  74. TcicProcessConfigureRequest(
  75. IN PSOCKET SocketPtr,
  76. IN PVOID ConfigRequest,
  77. IN PUCHAR Base
  78. );
  79. BOOLEAN
  80. TcicEnableDisableCardDetectEvent(
  81. IN PSOCKET SocketPtr,
  82. IN BOOLEAN Enable
  83. );
  84. VOID
  85. TcicDisableControllerInterrupt(
  86. IN PSOCKET socketPtr
  87. );
  88. BOOLEAN
  89. TcicPCCardReady(
  90. IN PSOCKET SocketPtr
  91. );
  92. VOID
  93. TcicGetRegisters(
  94. IN PFDO_EXTENSION DeviceExtension,
  95. IN PSOCKET SocketPtr,
  96. IN PUCHAR Buffer
  97. );
  98. ULONG
  99. TcicGetIrqMask(
  100. IN PFDO_EXTENSION deviceExtension
  101. );
  102. BOOLEAN
  103. TcicCardBusCardInSocket(
  104. IN PSOCKET SocketPtr
  105. );
  106. #if DBG
  107. VOID
  108. TcicDump(
  109. IN PSOCKET socketPtr
  110. );
  111. #endif
  112. #ifdef ALLOC_PRAGMA
  113. #pragma alloc_text(INIT,TcicDetect)
  114. #pragma alloc_text(PAGE,TcicFillInAdapter)
  115. #pragma alloc_text(PAGE,TcicGetAdapterInfo)
  116. #pragma alloc_text(PAGE,TcicAllocateMemRange)
  117. #pragma alloc_text(PAGE,TcicReservedBitsOK)
  118. #pragma alloc_text(PAGE,TcicChipID)
  119. #pragma alloc_text(PAGE,TcicCheckSkt)
  120. #pragma alloc_text(PAGE,TcicCheckAliasing)
  121. #pragma alloc_text(PAGE,TcicCheckAliasType)
  122. #pragma alloc_text(PAGE,TcicCheckXBufNeeded)
  123. #pragma alloc_text(PAGE,TcicSetMemWindow)
  124. #pragma alloc_text(PAGE,TcicGetPossibleIRQs)
  125. #pragma alloc_text(PAGE,TcicClockRate)
  126. #pragma alloc_text(PAGE,TcicGetIRQMap)
  127. #pragma alloc_text(PAGE,TcicGet5vVccVal)
  128. #pragma alloc_text(PAGE,TcicHasSktIRQPin)
  129. #pragma alloc_text(PAGE,TcicGetFlags)
  130. #pragma alloc_text(PAGE,TcicGetnMemWins)
  131. #pragma alloc_text(PAGE,TcicGetnIOWins)
  132. #pragma alloc_text(PAGE,TcicRegistryLookupScanLimits)
  133. #endif
  134. #define TCIC_LOW_ADDR_LIMIT 0x240
  135. #define TCIC_HIGH_ADDR_LIMIT 0x2ff
  136. /*
  137. || IRQ Tables -
  138. || Each table consists of 16 bytes. Each byte maps an IRQ level (implied by
  139. || table index) to a register value that will select that IRQ. For instance,
  140. || with table irqcaps_082, table[11] gives a value of 1, so using '1' as the
  141. || card status change IRQ value will cause IRQ11 to be fired.
  142. ||
  143. */
  144. /********************* 0 1 2 3 4 5 6 7 8 9 A B C D E F *****************/
  145. UCHAR irqcaps_082[] ={0,0,0,3,4,5,6,7,0, 0,10,1, 0, 0, 14,0};
  146. UCHAR irqcaps_082sw[] ={0,0,0,3,4,5,0,7,0, 6,10,1, 0, 0, 14,0};
  147. UCHAR irqcaps_072[] ={0,0,0,3,4,5,0,7,0, 0,10,1, 0, 0, 14,0};
  148. UCHAR irqcaps_072sw[] ={0,0,0,3,4,5,0,7,0,14,10,1, 0, 0, 0, 0};
  149. /* in the case of x84 parts, we determine 6,9,12,&15 at run time */
  150. UCHAR irqcaps_084[] ={0,0,0,3,4,5,0,7,0, 0,10,11,0, 0, 14,0};
  151. /* The Socket Services Public Power Table */
  152. unsigned short PubPwrTbl[] = {
  153. 3, /* number of Public Entries */
  154. SPWR_ALL_SUPPLY | SPWR_0p0V, /* Public entry */
  155. SPWR_ALL_SUPPLY | SPWR_5p0V, /* Public entry */
  156. SPWR_VPP_SUPPLY | SPWR_12p0V /* Public entry */
  157. };
  158. /* The corresponding Private Table for a TMI-140 type implementation */
  159. USHORT PwrTbl140[] = {
  160. 3, 0x0000, 0x0001, 0x0800, /* Private table */
  161. 0x0001 /* CtlBits for Vcc=5V */
  162. };
  163. /* The other Private Table for a DB86082/071/072 type implementation */
  164. USHORT PwrTbl082[] = {
  165. 3, 0x0000, 0x0809, 0x0100, /* Private table */
  166. 0x0001 /* CtlBits for Vcc=5V */
  167. };
  168. /* The corresponding Private Table for a DB86084/184 implementation */
  169. USHORT PwrTbl084[] ={
  170. 3, 0x0000, 0x0207, 0x0100, /* Private table */
  171. 0x0007 /* CtlBits for Vcc=5V */
  172. };
  173. /* Properties table - use this to bind possible capabilites to a Chip ID */
  174. CHIPPROPS ChipProperties[] = {
  175. {SILID_DB86082_1,
  176. PwrTbl082, 0, irqcaps_082, NUMSOCKETS, IR_IOWIN_NUM,
  177. IR_MWIN_NUM_082, (fEXTBUF_CHK | fSKTIRQPIN)},
  178. {SILID_DB86082A,
  179. PwrTbl082, 0, irqcaps_082, NUMSOCKETS, IR_IOWIN_NUM,
  180. IR_MWIN_NUM_082A, (fEXTBUF_CHK | fSKTIRQPIN)},
  181. {SILID_DB86082B,
  182. PwrTbl082, 0, irqcaps_082, NUMSOCKETS, IR_IOWIN_NUM,
  183. IR_MWIN_NUM_082B, (fEXTBUF_CHK | fSKTIRQPIN)},
  184. {SILID_DB86082B_ES,
  185. PwrTbl082, 0, irqcaps_082, NUMSOCKETS, IR_IOWIN_NUM,
  186. IR_MWIN_NUM_082B, (fEXTBUF_CHK | fSKTIRQPIN)},
  187. {SILID_DB86084_1,
  188. PwrTbl084, 0, irqcaps_084, NUMSOCKETS, IR_IOWIN_NUM,
  189. IR_MWIN_NUM_084, fIS_PNP},
  190. {SILID_DB86084A,
  191. PwrTbl084, 0, irqcaps_084, NUMSOCKETS, IR_IOWIN_NUM,
  192. IR_MWIN_NUM_084, fIS_PNP},
  193. {SILID_DB86184_1,
  194. PwrTbl084, 0, irqcaps_084, NUMSOCKETS, IR_IOWIN_NUM,
  195. IR_MWIN_NUM_184, fIS_PNP},
  196. {SILID_DB86072_1,
  197. PwrTbl082, 0, irqcaps_072, NUMSOCKETS, IR_IOWIN_NUM,
  198. IR_MWIN_NUM_072, fSKTIRQPIN},
  199. {SILID_DB86072_1_ES,
  200. PwrTbl082, 0, irqcaps_072, NUMSOCKETS, IR_IOWIN_NUM,
  201. IR_MWIN_NUM_072, fSKTIRQPIN},
  202. {0, NULL, 0, NULL, 0, 0, 0, 0}
  203. };
  204. #ifdef POOL_TAGGING
  205. #undef ExAllocatePool
  206. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'bdcP')
  207. #endif
  208. PUCHAR TcicCisBufferBase;
  209. ULONG TcicPhysicalBase;
  210. ULONG TcicStallCounter = 5000;
  211. ULONG TcicStallPower = 20000;
  212. PCMCIA_CTRL_BLOCK TcicSupportFns = {
  213. TcicInitializePcmciaSocket,
  214. TcicResetCard,
  215. TcicDetectCardInSocket,
  216. TcicDetectCardChanged,
  217. NULL, // DetectCardStatus
  218. TcicDetectReadyChanged,
  219. NULL, // GetPowerRequirements
  220. TcicProcessConfigureRequest,
  221. TcicEnableDisableCardDetectEvent,
  222. NULL, // EnableDisableWakeupEvent
  223. TcicGetIrqMask,
  224. TcicReadCardMemory,
  225. TcicWriteCardMemory,
  226. NULL, // ModifyMemoryWindow
  227. NULL, // SetVpp
  228. NULL // IsWriteProtected
  229. };
  230. VOID
  231. TcicGetControllerProperties(
  232. IN PSOCKET socketPtr,
  233. IN PUSHORT pIoPortBase,
  234. IN PUSHORT pIoPortSize
  235. )
  236. /*++
  237. Routine Description:
  238. Gets the Port base and range from the DBSOCKET pointer. The original code
  239. stored these values in the device extension, but this did not allow for
  240. multiple controller products such as the TMB-270.
  241. Arguments:
  242. socketPtr - pointer to our socket structure
  243. pIoPortBase - where to write the base address.
  244. pIoPortSize - where to write the range.
  245. Return Value:
  246. None
  247. --*/
  248. {
  249. PDBSOCKET pdb;
  250. if (Databook(socketPtr)) {
  251. pdb = (PDBSOCKET)socketPtr;
  252. *pIoPortBase = (USHORT)pdb->physPortAddr;
  253. *pIoPortSize = 16;
  254. }
  255. }
  256. ULONG
  257. TcicGetIrqMask(
  258. IN PFDO_EXTENSION deviceExtension
  259. )
  260. /*++
  261. Routine Description:
  262. Gets the IRQ mask from the DBSOCKET pointer. The original code
  263. had this mask hardcoded in PCMCIA.C but this did not provide the
  264. flexibility needed to correctly state the mask for Databook products.
  265. Arguments:
  266. deviceExtension - the root of the socket list
  267. Return Value:
  268. The compiled IRQ mask for the 1st socket in the list since this socket
  269. should be representative of all sockets on this controller.
  270. --*/
  271. {
  272. PDBSOCKET pdb = (PDBSOCKET)(deviceExtension->SocketList);
  273. ULONG mask = 0;
  274. int j;
  275. for (j = 0; j < 16; j++) {
  276. //
  277. // Changed the way the mask is constructed
  278. // The older (non-PnP) code put 0s for valid IRQs
  279. // and 1s for non-valid IRQs. Now it's flipped
  280. // (since the ControllerInterruptMask operates the same
  281. // way)
  282. //
  283. if (pdb->IRQMapTbl[j] != (UCHAR)0) {
  284. mask |= ((ULONG)1 << j);
  285. }
  286. }
  287. return (mask);
  288. }
  289. #if DBG
  290. #include "tcicregs.h"
  291. VOID
  292. TcicDump(
  293. IN PSOCKET socketPtr
  294. )
  295. /*++
  296. Routine Description:
  297. Debug routine to print the registers to the debugger.
  298. Arguments:
  299. socketPtr - provides base address information for the contoller to dump.
  300. Return Value:
  301. None
  302. --*/
  303. {
  304. TCIC tcic;
  305. ULONG origAddr;
  306. USHORT j;
  307. origAddr = TcicReadAddrReg(socketPtr);
  308. for (j = 0; j < 2; j++) {
  309. //
  310. // Select the socket
  311. //
  312. TcicSocketSelect(socketPtr, j);
  313. //
  314. // Read TCIC base registers for this socket
  315. //
  316. tcic.baseregs[j].sctrl = (UCHAR)TcicReadBaseReg(socketPtr, R_SCTRL);
  317. tcic.baseregs[j].sstat = (UCHAR)TcicReadBaseReg(socketPtr, R_SSTAT);
  318. tcic.baseregs[j].mode = (UCHAR)TcicReadBaseReg(socketPtr, R_MODE);
  319. tcic.baseregs[j].pwr = (UCHAR)TcicReadBaseReg(socketPtr, R_PWR);
  320. tcic.baseregs[j].edc = TcicReadBaseReg(socketPtr, R_EDC);
  321. tcic.baseregs[j].icsr = (UCHAR)TcicReadBaseReg(socketPtr, R_ICSR);
  322. tcic.baseregs[j].iena = (UCHAR)TcicReadBaseReg(socketPtr, R_IENA);
  323. //
  324. // Read TCIC aux regsiters for this socket
  325. //
  326. tcic.baseregs[j].wctl = TcicReadAuxReg(socketPtr, MODE_AR_WCTL);
  327. tcic.baseregs[j].syscfg = TcicReadAuxReg(socketPtr, MODE_AR_SYSCFG);
  328. tcic.baseregs[j].ilock = TcicReadAuxReg(socketPtr, MODE_AR_ILOCK);
  329. tcic.baseregs[j].test = TcicReadAuxReg(socketPtr, MODE_AR_TEST);
  330. //
  331. // Restore R_MODE - trashed by reading aux regs
  332. //
  333. TcicWriteBaseReg(socketPtr, R_MODE, tcic.baseregs[j].mode);
  334. }
  335. for (j = 0; j < 2; j++) {
  336. TcicReadIndirectRegs(socketPtr, IR_SCFG_S(j), 2, (PUSHORT)&tcic.sktregs[j]);
  337. }
  338. for (j = 0; j < 4; j++) {
  339. TcicReadIndirectRegs(socketPtr, IR_IOBASE_W(j), 2, (PUSHORT)&tcic.iowins[j]);
  340. }
  341. for (j = 0; j < 10; j++) {
  342. TcicReadIndirectRegs(socketPtr, IR_MBASE_W(j), 3, (PUSHORT)&tcic.memwins[j]);
  343. }
  344. TcicWriteAddrReg(socketPtr, origAddr);
  345. DebugPrint((PCMCIA_DUMP_SOCKET, "SCTRL\t%02X\t%02X\n",
  346. tcic.baseregs[0].sctrl, tcic.baseregs[1].sctrl));
  347. DebugPrint((PCMCIA_DUMP_SOCKET, "SSTAT\t%02X\t%02X\n",
  348. tcic.baseregs[0].sstat, tcic.baseregs[1].sstat));
  349. DebugPrint((PCMCIA_DUMP_SOCKET, "MODE \t%02X\t%02X\n",
  350. tcic.baseregs[0].mode, tcic.baseregs[1].mode));
  351. DebugPrint((PCMCIA_DUMP_SOCKET, "PWR \t%02X\t%02X\n",
  352. tcic.baseregs[0].pwr , tcic.baseregs[1].pwr ));
  353. DebugPrint((PCMCIA_DUMP_SOCKET, "EDC \t%04X\t%04X\n",
  354. tcic.baseregs[0].edc , tcic.baseregs[1].edc ));
  355. DebugPrint((PCMCIA_DUMP_SOCKET, "ICSR \t%02X\t%02X\n",
  356. tcic.baseregs[0].icsr , tcic.baseregs[1].icsr ));
  357. DebugPrint((PCMCIA_DUMP_SOCKET, "IENA \t%02X\t%02X\n",
  358. tcic.baseregs[0].iena , tcic.baseregs[1].iena ));
  359. DebugPrint((PCMCIA_DUMP_SOCKET, "WCTL \t%02X\t%02X\n",
  360. tcic.baseregs[0].wctl , tcic.baseregs[1].wctl ));
  361. DebugPrint((PCMCIA_DUMP_SOCKET, "SYSCFG\t%02X\t%02X\n",
  362. tcic.baseregs[0].syscfg, tcic.baseregs[1].syscfg));
  363. DebugPrint((PCMCIA_DUMP_SOCKET, "ILOCK\t%02X\t%02X\n",
  364. tcic.baseregs[0].ilock, tcic.baseregs[1].ilock));
  365. DebugPrint((PCMCIA_DUMP_SOCKET, "TEST \t%02X\t%02X\n",
  366. tcic.baseregs[0].test , tcic.baseregs[1].test ));
  367. for (j = 0; j < 2; j++ ) {
  368. DebugPrint((PCMCIA_DUMP_SOCKET,
  369. "SKT%d\tSCF1 %04X\tSCF2 %04X\n",
  370. j, tcic.sktregs[j].scfg1, tcic.sktregs[j].scfg2));
  371. }
  372. for (j = 0; j < 4; j++ ) {
  373. DebugPrint((PCMCIA_DUMP_SOCKET,
  374. "IOWIN%d\tIOBASE %04X\tIOCTL %04X\n",
  375. j, tcic.iowins[j].iobase, tcic.iowins[j].ioctl));
  376. }
  377. for (j = 0; j < 10; j++ ) {
  378. DebugPrint((PCMCIA_DUMP_SOCKET,
  379. "MEMWIN%d\tMBASE %04X\tMMAP %04X\tMCTL %04X\n",
  380. j, tcic.memwins[j].mbase,
  381. tcic.memwins[j].mmap,
  382. tcic.memwins[j].mctl));
  383. }
  384. }
  385. #endif
  386. BOOLEAN
  387. TcicEnableDisableCardDetectEvent(
  388. IN PSOCKET SocketPtr,
  389. IN BOOLEAN Enable
  390. )
  391. /*++
  392. Routine Description:
  393. Enable card detect interrupt.
  394. Arguments:
  395. SocketPtr - socket information
  396. Irq - the interrupt value to set if enable is true.
  397. Enable - if TRUE, CSC interrupt is enabled,
  398. if FALSE, it is disabled
  399. Return Value:
  400. None
  401. --*/
  402. {
  403. UCHAR mappedIrq;
  404. PDBSOCKET pdb = (PDBSOCKET)SocketPtr;
  405. BOOLEAN retVal;
  406. switch (Enable) {
  407. case TRUE:
  408. //
  409. // Validate the interrupt request. Only setup if the IRQ is valid
  410. // for this controller
  411. //
  412. if ((mappedIrq = pdb->IRQMapTbl[SocketPtr->FdoIrq]) != (UCHAR)0) {
  413. USHORT word;
  414. //
  415. // Mask status change conditions other than CD. The pcic code comments
  416. // claimed to setup CD and RDY/BSY notification, but the code itself
  417. // only allows for CD.
  418. //
  419. word = (USHORT)(IRSCF2_MLBAT1 | IRSCF2_MLBAT2 | IRSCF2_MRDY | IRSCF2_MWP);
  420. TcicWriteIndirectRegs(SocketPtr,
  421. IR_SCF2_S(SocketPtr->RegisterOffset),
  422. 1,
  423. &word);
  424. //
  425. // Set the correct IRQ value in the SYSCFG register
  426. //
  427. word = TcicReadAuxReg(SocketPtr, MODE_AR_SYSCFG);
  428. word &= ~SYSCFG_IRQ_MASK;
  429. word |= (USHORT)mappedIrq;
  430. TcicWriteAuxReg(SocketPtr, MODE_AR_SYSCFG, word);
  431. //
  432. // Set IRQ polarity and enable via R_IENA
  433. //
  434. TcicSocketSelect(SocketPtr, SocketPtr->RegisterOffset);
  435. TcicWriteBaseReg(SocketPtr, R_IENA, IENA_CDCHG | IENA_CFG_HIGH);
  436. PcmciaWait(TcicStallCounter);
  437. //
  438. // Clear ICSR - so future insertions/removals will generate interrupts
  439. //
  440. (VOID) TcicDetectCardChanged(SocketPtr);
  441. retVal = TRUE;
  442. } else {
  443. retVal = FALSE;
  444. }
  445. break;
  446. case FALSE:{
  447. retVal = FALSE;
  448. break;
  449. }
  450. }
  451. return retVal;
  452. }
  453. NTSTATUS
  454. TcicResetCard(
  455. IN PSOCKET SocketPtr,
  456. OUT PULONG pDelayTime
  457. )
  458. /*++
  459. Routine Description:
  460. Arguments:
  461. SocketPtr - socket information
  462. pDelayTime - specifies delay (msec) to occur after the current phase
  463. Return value:
  464. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  465. other status values terminate sequence
  466. --*/
  467. {
  468. NTSTATUS status;
  469. PDBSOCKET pdb = (PDBSOCKET)SocketPtr;
  470. USHORT ilock;
  471. PDBSOCKET dbskt = (PDBSOCKET)(SocketPtr->DeviceExtension->SocketList);
  472. switch(SocketPtr->CardResetPhase) {
  473. case 1:
  474. //
  475. // reset PCCARD
  476. //
  477. ilock = TcicReadAuxReg(SocketPtr, MODE_AR_ILOCK);
  478. ilock &= ~(ILOCK_CRESET | ILOCK_CRESENA | ILOCK_CWAIT);
  479. TcicWriteAuxReg(SocketPtr, MODE_AR_ILOCK, (USHORT)(ilock | ILOCK_CRESENA | ILOCK_CRESET));
  480. *pDelayTime = TcicStallCounter;
  481. SocketPtr->PowerData = (ULONG) ilock;
  482. status = STATUS_MORE_PROCESSING_REQUIRED;
  483. break;
  484. case 2:
  485. ilock = (USHORT) SocketPtr->PowerData;
  486. TcicWriteAuxReg(SocketPtr, MODE_AR_ILOCK, (USHORT)(ilock | ILOCK_CRESENA));
  487. *pDelayTime = TcicStallCounter;
  488. status = STATUS_MORE_PROCESSING_REQUIRED;
  489. break;
  490. case 3:
  491. ilock = TcicReadAuxReg(SocketPtr, MODE_AR_ILOCK);
  492. if (!(ilock & ILOCK_CWAITSNS)) {
  493. TcicWriteAuxReg(SocketPtr, MODE_AR_ILOCK, (USHORT)(ilock | ILOCK_CWAIT));
  494. }
  495. //
  496. // If not already started, start a timer to drive the BusyLED
  497. // Monitor routine.
  498. if (dbskt->timerStarted == FALSE) {
  499. IoInitializeTimer(pdb->skt.DeviceExtension->DeviceObject,
  500. TcicBusyLedRoutine, NULL);
  501. IoStartTimer(pdb->skt.DeviceExtension->DeviceObject);
  502. dbskt->timerStarted = TRUE;
  503. }
  504. status = STATUS_SUCCESS;
  505. break;
  506. default:
  507. ASSERT(FALSE);
  508. status = STATUS_UNSUCCESSFUL;
  509. }
  510. return status;
  511. }
  512. NTSTATUS
  513. TcicSetPower(
  514. IN PSOCKET socketPtr,
  515. IN BOOLEAN Enable,
  516. OUT PULONG pDelayTime
  517. )
  518. /*++
  519. Routine Description:
  520. Set power to the specified socket.
  521. Arguments:
  522. SocketPtr - the socket to set
  523. Enable - TRUE means to set power - FALSE is to turn it off.
  524. pDelayTime - specifies delay (msec) to occur after the current phase
  525. Return Value:
  526. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  527. other status values terminate sequence
  528. --*/
  529. {
  530. NTSTATUS status;
  531. //
  532. // Get the specified socket mapped into the TCIC registers
  533. //
  534. TcicSocketSelect(socketPtr, socketPtr->RegisterOffset);
  535. if (Enable) {
  536. PDBSOCKET pdb = (PDBSOCKET)socketPtr;
  537. switch(socketPtr->PowerPhase) {
  538. case 1:
  539. //
  540. // Turn on power
  541. //
  542. DebugPrint((PCMCIA_DEBUG_INFO, "TcicSetPower: Powering UP pccard socket\n"));
  543. TcicWriteBaseReg(socketPtr, R_PWR, pdb->dflt_vcc5v);
  544. //
  545. // Enable other strobes to socket
  546. //
  547. TcicWriteBaseReg(socketPtr, R_SCTRL, SCTRL_ENA);
  548. //
  549. // When power is enabled always stall to give the PCCARD
  550. // a chance to react.
  551. //
  552. *pDelayTime = TcicStallCounter;
  553. status = STATUS_MORE_PROCESSING_REQUIRED;
  554. break;
  555. case 2:
  556. if (!TcicPCCardReady(socketPtr)) {
  557. DebugPrint((PCMCIA_PCCARD_READY,
  558. "Tcic: PCCARD %x not ready after power\n",
  559. socketPtr->RegisterOffset));
  560. }
  561. status = STATUS_SUCCESS;
  562. break;
  563. default:
  564. ASSERT(FALSE);
  565. status = STATUS_UNSUCCESSFUL;
  566. }
  567. } else {
  568. //
  569. // Disable socket strobes
  570. //
  571. DebugPrint((PCMCIA_DEBUG_INFO, "TcicSetPower: Powering DOWN pccard socket\n"));
  572. TcicWriteBaseReg(socketPtr, R_SCTRL, 0);
  573. //
  574. // Diable power
  575. //
  576. TcicWriteBaseReg(socketPtr, R_PWR, 0);
  577. status = STATUS_SUCCESS;
  578. }
  579. return status;
  580. }
  581. BOOLEAN
  582. TcicInitializePcmciaSocket(
  583. PSOCKET SocketPtr
  584. )
  585. /*++
  586. Routine Description:
  587. This routine will setup the 82365 into a state where the pcmcia support
  588. module will be able to issue commands to read device tuples from the
  589. cards in the sockets.
  590. Arguments:
  591. SocketPtr - socket specific info
  592. Return Value:
  593. TRUE if successful
  594. FALSE if not successful
  595. --*/
  596. {
  597. PDBSOCKET pdb = (PDBSOCKET)SocketPtr;
  598. USHORT speedbits = WCTL_300NS;
  599. speedbits >>= pdb->clkdiv;
  600. //
  601. // If this is the first socket on this controller,
  602. // Reset the controller and do controller-wide initialization.
  603. //
  604. if (SocketPtr->RegisterOffset == 0) {
  605. USHORT words[4];
  606. int j;
  607. //
  608. // Reset Controller
  609. //
  610. TcicWriteBaseReg(SocketPtr, R_SCTRL, SCTRL_RESET);
  611. TcicWriteBaseReg(SocketPtr, R_SCTRL, 0);
  612. //
  613. // Initialize indirect socket regs
  614. //
  615. words[0] = pdb->dflt_scfg1;
  616. words[1] = (USHORT)(IRSCF2_MLBAT1 | IRSCF2_MLBAT2 | IRSCF2_MRDY | IRSCF2_MWP);
  617. TcicWriteIndirectRegs(SocketPtr, IR_SCFG_S(0), 2, words);
  618. TcicWriteIndirectRegs(SocketPtr, IR_SCFG_S(1), 2, words);
  619. //
  620. // Initialize indirect memwin regs
  621. //
  622. words[0] = words[1] = 0;
  623. words[2] = pdb->dflt_wrmctl;
  624. for (j = 0; j < pdb->nmemwins; j++) {
  625. TcicWriteIndirectRegs(SocketPtr, IR_MBASE_W(j), 3, words);
  626. }
  627. //
  628. // Initialize indirect iowin regs
  629. //
  630. for (j = 0; j < pdb->niowins; j++ ) {
  631. TcicWriteIndirectRegs(SocketPtr, IR_IOBASE_W(j), 2, words);
  632. }
  633. //
  634. // Initialize SYSCFG
  635. //
  636. TcicWriteAuxReg(SocketPtr, MODE_AR_SYSCFG, pdb->dflt_syscfg);
  637. }
  638. //
  639. // Get the specified Socket mapped into the TCIC registers
  640. //
  641. TcicSocketSelect(SocketPtr, SocketPtr->RegisterOffset);
  642. //
  643. // Per/socket we initialize the following base and aux regs:
  644. // WCTL & ILOCK
  645. //
  646. TcicWriteAuxReg(SocketPtr, MODE_AR_WCTL, (USHORT)(pdb->dflt_wctl | speedbits));
  647. TcicWriteAuxReg(SocketPtr, MODE_AR_ILOCK, pdb->dflt_ilock);
  648. //
  649. // Say card is there
  650. //
  651. return TRUE;
  652. }
  653. USHORT
  654. TcicReadBaseReg(
  655. IN PSOCKET SocketPtr,
  656. IN ULONG Register
  657. )
  658. /*++
  659. Routine Description:
  660. Reads the specified TCIC base register,
  661. Arguments:
  662. SocketPtr - instance data for this socket
  663. Register - index of register to read
  664. Return Value:
  665. register value read
  666. --*/
  667. {
  668. USHORT readData = 0;
  669. switch (Register) {
  670. case R_DATA:
  671. case R_ADDR:
  672. case R_ADDR2:
  673. case R_EDC:
  674. case R_AUX:
  675. readData = READ_PORT_USHORT((PUSHORT)(SocketPtr->AddressPort + Register));
  676. break;
  677. case R_SCTRL:
  678. case R_SSTAT:
  679. case R_MODE:
  680. case R_PWR:
  681. case R_ICSR:
  682. case R_IENA:
  683. readData = (USHORT)READ_PORT_UCHAR(SocketPtr->AddressPort + Register);
  684. break;
  685. }
  686. return readData;
  687. }
  688. VOID
  689. TcicWriteBaseReg(
  690. IN PSOCKET SocketPtr,
  691. IN ULONG Register,
  692. IN USHORT value
  693. )
  694. /*++
  695. Routine Description:
  696. Write a value to the specified TCIC base register
  697. Arguments:
  698. SocketPtr - instance data for this socket
  699. Register - index of register to write
  700. value - value to write to register
  701. Return Value:
  702. None
  703. --*/
  704. {
  705. USHORT readData = 0;
  706. switch (Register) {
  707. case R_DATA:
  708. case R_ADDR:
  709. case R_ADDR2:
  710. case R_EDC:
  711. case R_AUX:
  712. WRITE_PORT_USHORT((PUSHORT)(SocketPtr->AddressPort + Register), value);
  713. break;
  714. case R_SCTRL:
  715. case R_SSTAT:
  716. case R_MODE:
  717. case R_PWR:
  718. case R_ICSR:
  719. case R_IENA:
  720. WRITE_PORT_UCHAR(SocketPtr->AddressPort + Register, (UCHAR)value);
  721. break;
  722. }
  723. }
  724. ULONG
  725. TcicReadAddrReg(
  726. IN PSOCKET SocketPtr
  727. )
  728. /*++
  729. Routine Description:
  730. Read the current value of the TCIC address register
  731. Arguments:
  732. SocketPtr - instance data for this socket
  733. Return Value:
  734. Address read from register
  735. --*/
  736. {
  737. ULONG retaddr;
  738. retaddr = (ULONG)TcicReadBaseReg(SocketPtr, R_ADDR);
  739. retaddr |= ((ULONG)TcicReadBaseReg(SocketPtr, R_ADDR2) << 16);
  740. return (retaddr);
  741. }
  742. VOID
  743. TcicWriteAddrReg(
  744. IN PSOCKET SocketPtr,
  745. IN ULONG addr
  746. )
  747. /*++
  748. Routine Description:
  749. Write an address to the TCIC address register
  750. Arguments:
  751. SocketPtr - instance data for this socket
  752. addr - address to write to register
  753. Return Value:
  754. None
  755. --*/
  756. {
  757. TcicWriteBaseReg(SocketPtr, R_ADDR, (USHORT)(addr & 0x0000ffff));
  758. TcicWriteBaseReg(SocketPtr, R_ADDR2, (USHORT)(addr >> 16));
  759. }
  760. USHORT
  761. TcicReadAuxReg(
  762. IN PSOCKET SocketPtr,
  763. IN ULONG Register
  764. )
  765. /*++
  766. Routine Description:
  767. Read the specified TCIC AUX register
  768. Arguments:
  769. SocketPtr - instance data for this socket
  770. Register - MODE_AR_xxx justified index of AUX register to read
  771. Return Value:
  772. contents of specified AUX register
  773. --*/
  774. {
  775. USHORT readData = 0;
  776. USHORT OldMode;
  777. //
  778. // Get the current mode register value
  779. //
  780. OldMode = TcicReadBaseReg(SocketPtr, R_MODE);
  781. //
  782. // Mask out previous AUX register selection and add in new selection
  783. //
  784. TcicWriteBaseReg(SocketPtr, R_MODE,
  785. (USHORT)((OldMode & ~MODE_AUXSEL_MASK) | Register));
  786. //
  787. // Read the selected AUX register
  788. //
  789. readData = TcicReadBaseReg(SocketPtr, R_AUX);
  790. //
  791. // Restore the mode reg to its original state
  792. //
  793. TcicWriteBaseReg(SocketPtr, R_MODE, OldMode);
  794. return readData;
  795. }
  796. VOID
  797. TcicWriteAuxReg(
  798. IN PSOCKET SocketPtr,
  799. IN ULONG Register,
  800. IN USHORT value
  801. )
  802. /*++
  803. Routine Description:
  804. Write a value into the specified AUX register
  805. Arguments:
  806. SocketPtr - instance data for this socket
  807. Register - MODE_AR_xxx justified index of AUX register to write
  808. Return Value:
  809. None
  810. --*/
  811. {
  812. USHORT readData = 0;
  813. USHORT OldMode;
  814. //
  815. // Get the current mode register value
  816. //
  817. OldMode = TcicReadBaseReg(SocketPtr, R_MODE);
  818. //
  819. // Mask out previous AUX register selection and add in new selection
  820. //
  821. TcicWriteBaseReg(SocketPtr, R_MODE,
  822. (USHORT)((OldMode & ~MODE_AUXSEL_MASK) | Register));
  823. //
  824. // Write the data to the selected AUX register
  825. //
  826. TcicWriteBaseReg(SocketPtr, R_AUX, value);
  827. //
  828. // Restore the mode reg to its original state
  829. //
  830. TcicWriteBaseReg(SocketPtr, R_MODE, OldMode);
  831. }
  832. VOID
  833. TcicReadIndirectRegs(
  834. IN PSOCKET SocketPtr,
  835. IN ULONG StartRegister,
  836. IN USHORT numWords,
  837. IN PUSHORT ReadBuffer
  838. )
  839. /*++
  840. Routine Description:
  841. Read one or multiple TCIC indirect registers.
  842. Arguments:
  843. SocketPtr - instance data for this socket
  844. StartRegister - starting indirect register
  845. numWords - number of consecutive registers to read
  846. ReadBuffer - data buffer
  847. Return Value:
  848. None
  849. --*/
  850. {
  851. USHORT OldHaddr;
  852. USHORT OldLaddr;
  853. USHORT OldSctrl;
  854. USHORT j;
  855. //
  856. // Get the current TCIC state
  857. //
  858. if (numWords > 1) {
  859. //
  860. // We won't set AUTO-Inc if only 1 word
  861. //
  862. OldSctrl = TcicReadBaseReg(SocketPtr, R_SCTRL);
  863. }
  864. OldLaddr = TcicReadBaseReg(SocketPtr, R_ADDR);
  865. OldHaddr = TcicReadBaseReg(SocketPtr, R_ADDR2);
  866. //
  867. // Set the TCIC state required for reading the indirect registers
  868. //
  869. TcicWriteBaseReg(SocketPtr, R_ADDR2,
  870. (USHORT)(OldHaddr | ADR2_INDREG));
  871. TcicWriteBaseReg(SocketPtr, R_ADDR, (USHORT)StartRegister);
  872. if (numWords > 1) {
  873. TcicWriteBaseReg(SocketPtr, R_SCTRL, (USHORT)(OldSctrl | SCTRL_INCMODE_AUTO));
  874. }
  875. //
  876. // Read the Indirect registert requested
  877. //
  878. for (j = 0; j < numWords; j++) {
  879. *ReadBuffer++ = TcicReadBaseReg(SocketPtr, R_DATA);
  880. }
  881. //
  882. // Restore the original TCIC state
  883. //
  884. if (numWords > 1) {
  885. //
  886. // We didn't set AUTO-Inc if only 1 word
  887. //
  888. TcicWriteBaseReg(SocketPtr, R_SCTRL, OldSctrl);
  889. }
  890. TcicWriteBaseReg(SocketPtr, R_ADDR2, OldHaddr);
  891. TcicWriteBaseReg(SocketPtr, R_ADDR, OldLaddr);
  892. }
  893. VOID
  894. TcicWriteIndirectRegs(
  895. IN PSOCKET SocketPtr,
  896. IN ULONG StartRegister,
  897. IN USHORT numWords,
  898. IN PUSHORT WriteBuffer
  899. )
  900. /*++
  901. Routine Description:
  902. Write one or multiple TCIC indirect registers.
  903. Arguments:
  904. SocketPtr - instance data for this socket
  905. StartRegister - starting indirect register
  906. numWords - number of consecutive registers to write
  907. WriteBuffer - data buffer
  908. Return Value:
  909. None
  910. --*/
  911. {
  912. USHORT OldHaddr;
  913. USHORT OldLaddr;
  914. USHORT OldSctrl;
  915. USHORT j;
  916. //
  917. // Get the current TCIC state
  918. //
  919. if (numWords > 1) {
  920. //
  921. // We won't set AUTO-Inc if only 1 word
  922. //
  923. OldSctrl = TcicReadBaseReg(SocketPtr, R_SCTRL);
  924. }
  925. OldLaddr = TcicReadBaseReg(SocketPtr, R_ADDR);
  926. OldHaddr = TcicReadBaseReg(SocketPtr, R_ADDR2);
  927. //
  928. // Set the TCIC state required for reading the indirect registers
  929. //
  930. TcicWriteBaseReg(SocketPtr, R_ADDR2, (USHORT)(OldHaddr | (USHORT)ADR2_INDREG));
  931. TcicWriteBaseReg(SocketPtr, R_ADDR, (USHORT)StartRegister);
  932. if (numWords > 1) {
  933. TcicWriteBaseReg(SocketPtr, R_SCTRL, (USHORT)(OldSctrl | SCTRL_INCMODE_AUTO));
  934. }
  935. //
  936. // Read the Indirect registert requested
  937. //
  938. for (j = 0; j < numWords; j++) {
  939. TcicWriteBaseReg(SocketPtr, R_DATA, *WriteBuffer++);
  940. }
  941. //
  942. // Restore the original TCIC state
  943. //
  944. if (numWords > 1) {
  945. //
  946. // We didn't set AUTO-Inc if only 1 word
  947. //
  948. TcicWriteBaseReg(SocketPtr, R_SCTRL, OldSctrl);
  949. }
  950. TcicWriteBaseReg(SocketPtr, R_ADDR2, OldHaddr);
  951. TcicWriteBaseReg(SocketPtr, R_ADDR, OldLaddr);
  952. }
  953. USHORT
  954. TcicSocketSelect(
  955. IN PSOCKET SocketPtr,
  956. IN USHORT sktnum
  957. )
  958. /*++
  959. Routine Description:
  960. Map the specified socket registers into TCIC register space.
  961. Arguments:
  962. SocketPtr - instance data for this socket
  963. sktnum - socket number to map.
  964. Return Value:
  965. previous socket mapped.
  966. --*/
  967. {
  968. USHORT OldAddrHi;
  969. OldAddrHi = READ_PORT_USHORT((PUSHORT)(SocketPtr->AddressPort + R_ADDR2));
  970. WRITE_PORT_USHORT((PUSHORT)(SocketPtr->AddressPort + R_ADDR2),
  971. (USHORT)((OldAddrHi & ~TCIC_SS_MASK) | (USHORT)(sktnum << TCIC_SS_SHFT)));
  972. return (USHORT)((OldAddrHi & TCIC_SS_MASK) >> TCIC_SS_SHFT);
  973. }
  974. ULONG
  975. TcicReadCardMemory(
  976. IN PPDO_EXTENSION PdoExtension,
  977. IN MEMORY_SPACE MemorySpace,
  978. IN ULONG Offset,
  979. IN PUCHAR Buffer,
  980. IN ULONG Length
  981. )
  982. /*++
  983. Routine Description:
  984. This routine will set up the card to read attribute memory.
  985. Arguments:
  986. SocketPtr -- The socket info in for the card being read
  987. Offset -- Offset from which to read
  988. MemorySpace -- Attribute memory or Common Memory
  989. Buffer -- Pointer to buffer in which memory contents are returned
  990. Length -- No. of bytes to be returned
  991. Return Value:
  992. TRUE - if read was successful.
  993. --*/
  994. {
  995. PSOCKET SocketPtr = PdoExtension->Socket;
  996. ULONG size;
  997. ULONG tcicaddr;
  998. ULONG i;
  999. USHORT word;
  1000. //
  1001. // Make sure the card is ready
  1002. //
  1003. if (!TcicPCCardReady(SocketPtr)) {
  1004. DebugPrint((PCMCIA_PCCARD_READY,
  1005. "Tcic: PCCARD %x not ready for read attribute memory\n",
  1006. SocketPtr->RegisterOffset));
  1007. }
  1008. if (MemorySpace != PCCARD_ATTRIBUTE_MEMORY) {
  1009. return 0;
  1010. }
  1011. tcicaddr = ADDR_REG | (SocketPtr->RegisterOffset << ADDR_SS_SHFT);
  1012. TcicWriteAddrReg(SocketPtr, tcicaddr);
  1013. word = TcicReadBaseReg(SocketPtr, R_SCTRL);
  1014. word |= SCTRL_INCMODE_AUTO;
  1015. TcicWriteBaseReg(SocketPtr, R_SCTRL, word);
  1016. //
  1017. // Hardware needs to settle
  1018. //
  1019. PcmciaWait(50000);
  1020. //
  1021. // Skip up to the offset
  1022. //
  1023. for (i = 0; i < Offset; i++) {
  1024. (VOID)TcicReadBaseReg(SocketPtr, R_DATA);
  1025. }
  1026. //
  1027. // Read the attribute memory
  1028. //
  1029. for (i = 0; i < Length; i++) {
  1030. *Buffer++ = (UCHAR)TcicReadBaseReg(SocketPtr, R_DATA);
  1031. }
  1032. return Length;
  1033. }
  1034. ULONG
  1035. TcicWriteCardMemory(
  1036. IN PPDO_EXTENSION PdoExtension,
  1037. IN MEMORY_SPACE MemorySpace,
  1038. IN ULONG Offset,
  1039. IN PUCHAR Buffer,
  1040. IN ULONG Length
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. This routine will write into the configuration memory on the card
  1045. with the supplied buffer. This is provided as a service to certain
  1046. client drivers (netcard) which need to write to the attribute memory
  1047. (say) to set parameters etc.
  1048. Arguments:
  1049. SocketPtr -- The socket info in for the card being written to
  1050. MemorySpace -- indicates which space - attribute or common memory
  1051. Offset -- Offset in the memory to write to
  1052. Buffer -- Buffer contents being dumped to the card
  1053. Length -- Length of the buffer being written out
  1054. --*/
  1055. {
  1056. PSOCKET SocketPtr = PdoExtension->Socket;
  1057. #define TCIC_ATTRIBUTE_MEM_WINDOW_INDEX 5
  1058. PUCHAR memoryPtr;
  1059. ULONG index;
  1060. UCHAR memGran;
  1061. memGran = (MemorySpace == PCCARD_ATTRIBUTE_MEMORY)? 2 : 1;
  1062. memoryPtr=((PFDO_EXTENSION) (SocketPtr->DeviceExtension))->AttributeMemoryBase +
  1063. memGran * Offset;
  1064. TcicSetMemWin(SocketPtr,
  1065. (USHORT) (TCIC_ATTRIBUTE_MEM_WINDOW_INDEX+SocketPtr->SocketNumber),
  1066. 0,
  1067. SocketPtr->DeviceExtension->PhysicalBase.LowPart,
  1068. SocketPtr->DeviceExtension->AttributeMemorySize,
  1069. (UCHAR) (MemorySpace == PCCARD_ATTRIBUTE_MEMORY),
  1070. 0,
  1071. 0);
  1072. if (!TcicPCCardReady(SocketPtr)) {
  1073. DebugPrint((PCMCIA_PCCARD_READY,
  1074. "TCIC: PCCARD in socket %x not ready for write memory\n",
  1075. SocketPtr->RegisterOffset));
  1076. }
  1077. for (index=0; index < Length; index++) {
  1078. WRITE_REGISTER_UCHAR(memoryPtr, Buffer[index]);
  1079. memoryPtr += memGran;
  1080. }
  1081. TcicSetMemWin(SocketPtr,
  1082. (USHORT) (TCIC_ATTRIBUTE_MEM_WINDOW_INDEX+SocketPtr->SocketNumber),
  1083. 0,
  1084. 0,
  1085. 0,
  1086. 0,
  1087. 0,
  1088. 0);
  1089. return Length;
  1090. }
  1091. BOOLEAN
  1092. TcicProcessConfigureRequest(
  1093. IN PSOCKET socketPtr,
  1094. IN PCARD_REQUEST request,
  1095. IN PUCHAR Base
  1096. )
  1097. /*++
  1098. Routine Description:
  1099. Processes a configure or IRQ setup request.
  1100. Arguments:
  1101. socketPtr - instance data for this socket
  1102. ConfigRequest -- Socket config structure
  1103. Base - the I/O port base - not used
  1104. Return Value:
  1105. None
  1106. --*/
  1107. {
  1108. USHORT index, index2;
  1109. USHORT tmp;
  1110. ULONG ltmp;
  1111. USHORT words[3];
  1112. PDBSOCKET pdbs;
  1113. //
  1114. // Since all first entries in the config structure is a RequestType,
  1115. // cast the pointer comming in as a PREQUEST_CONFIG to get the proper
  1116. // RequestType
  1117. //
  1118. switch (request->RequestType) {
  1119. case IO_REQUEST:
  1120. //
  1121. // Set up I/O ranges on the controller
  1122. //
  1123. for (index = 0; index < request->u.Io.NumberOfRanges; index++) {
  1124. if (request->u.Io.IoEntry[index].BasePort != 0) {
  1125. TcicSetIoWin(socketPtr, index,
  1126. request->u.Io.IoEntry[index].BasePort,
  1127. request->u.Io.IoEntry[index].NumPorts,
  1128. request->u.Io.IoEntry[index].Attributes);
  1129. } else {
  1130. DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: Got an IO Configure Request with an invalid Port\n"));
  1131. break;
  1132. }
  1133. }
  1134. break;
  1135. case IRQ_REQUEST:
  1136. pdbs = (PDBSOCKET)socketPtr;
  1137. ltmp = ADDR_INDREG | (socketPtr->RegisterOffset << ADDR_SS_SHFT);
  1138. ltmp |= (ULONG)IR_SCFG_S(socketPtr->RegisterOffset);
  1139. TcicWriteAddrReg(socketPtr, ltmp);
  1140. TcicWriteBaseReg(socketPtr, R_SCTRL, SCTRL_ENA);
  1141. tmp = TcicReadBaseReg(socketPtr, R_DATA);
  1142. tmp &= ~IRSCFG_IRQ_MASK;
  1143. tmp |= pdbs->IRQMapTbl[request->u.Irq.AssignedIRQ];
  1144. TcicWriteBaseReg(socketPtr, R_DATA, tmp);
  1145. break;
  1146. case CONFIGURE_REQUEST:
  1147. //
  1148. // This is where we setup the card and get it ready for operation
  1149. //
  1150. if (!TcicPCCardReady(socketPtr)) {
  1151. DebugPrint((PCMCIA_PCCARD_READY,
  1152. "Tcic: PCCARD %x not ready for configuration index\n",
  1153. socketPtr));
  1154. return FALSE;
  1155. }
  1156. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_CONFIGURATION_INDEX) {
  1157. ltmp = request->u.Config.ConfigBase;
  1158. ltmp |= ADDR_REG | (socketPtr->RegisterOffset << ADDR_SS_SHFT);
  1159. TcicWriteAddrReg(socketPtr, ltmp);
  1160. TcicWriteBaseReg(socketPtr, R_SCTRL, SCTRL_ENA);
  1161. TcicWriteBaseReg(socketPtr, R_DATA, request->u.Config.ConfigIndex);
  1162. PcmciaWait(TcicStallCounter);
  1163. TcicWriteBaseReg(socketPtr, R_DATA,
  1164. (USHORT)(request->u.Config.ConfigIndex | 0x40));
  1165. PcmciaWait(TcicStallCounter);
  1166. }
  1167. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_CARD_CONFIGURATION) {
  1168. ltmp = request->u.Config.ConfigBase + 2;
  1169. ltmp |= ADDR_REG | (socketPtr->RegisterOffset << ADDR_SS_SHFT);
  1170. TcicWriteAddrReg(socketPtr, ltmp);
  1171. TcicWriteBaseReg(socketPtr, R_SCTRL, SCTRL_ENA);
  1172. tmp = TcicReadBaseReg(socketPtr, R_DATA);
  1173. tmp |= request->u.Config.CardConfiguration;
  1174. //
  1175. // turn off power control bit
  1176. //
  1177. tmp &= ~0x04;
  1178. TcicWriteBaseReg(socketPtr, R_DATA, tmp);
  1179. }
  1180. break;
  1181. case DECONFIGURE_REQUEST:
  1182. //
  1183. // Deregister the interrupt
  1184. //
  1185. pdbs = (PDBSOCKET)socketPtr;
  1186. ltmp = ADDR_INDREG | (socketPtr->RegisterOffset << ADDR_SS_SHFT);
  1187. ltmp |= (ULONG)IR_SCFG_S(socketPtr->RegisterOffset);
  1188. TcicWriteAddrReg(socketPtr, ltmp);
  1189. TcicWriteBaseReg(socketPtr, R_SCTRL, SCTRL_ENA);
  1190. tmp = TcicReadBaseReg(socketPtr, R_DATA);
  1191. tmp &= ~IRSCFG_IRQ_MASK;
  1192. TcicWriteBaseReg(socketPtr, R_DATA, tmp);
  1193. //
  1194. // Disable I/O, memory windows
  1195. //
  1196. break;
  1197. case MEM_REQUEST:
  1198. //
  1199. // Set up memory ranges on the controller.
  1200. //
  1201. for (index = 0; index < request->u.Memory.NumberOfRanges; index++) {
  1202. TcicSetMemWin(socketPtr,
  1203. index,
  1204. request->u.Memory.MemoryEntry[index].BaseAddress,
  1205. request->u.Memory.MemoryEntry[index].HostAddress,
  1206. request->u.Memory.MemoryEntry[index].WindowSize,
  1207. request->u.Memory.MemoryEntry[index].AttributeMemory,
  1208. request->u.Memory.AccessSpeed,
  1209. request->u.Memory.Attributes);
  1210. }
  1211. break;
  1212. default:
  1213. DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: ConfigRequest is INVALID!\n"));
  1214. }
  1215. return TRUE;
  1216. }
  1217. BOOLEAN
  1218. TcicDetectCardInSocket(
  1219. IN PSOCKET socketPtr
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. This routine will determine if a card is in the socket
  1224. Arguments:
  1225. SocketPtr -- Socket info.
  1226. Return Value:
  1227. TRUE if card is present.
  1228. --*/
  1229. {
  1230. //
  1231. // Get the specified socket mapped into the TCIC registers
  1232. //
  1233. TcicSocketSelect(socketPtr, socketPtr->RegisterOffset);
  1234. //
  1235. // Read the Tcic status register to see if the card is in there.
  1236. //
  1237. return (TcicReadBaseReg(socketPtr, R_SSTAT) & SSTAT_CD) ?TRUE :FALSE;
  1238. }
  1239. BOOLEAN
  1240. TcicDetectCardChanged(
  1241. IN PSOCKET socketPtr
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. This routine will determine if socket's card insertion status has changed.
  1246. Arguments:
  1247. socketPtr -- Socket info.
  1248. Return Value:
  1249. TRUE if card insertion status has changed.
  1250. --*/
  1251. {
  1252. BOOLEAN changed;
  1253. //
  1254. // Get the specified socket mapped into the TCIC registers
  1255. //
  1256. TcicSocketSelect(socketPtr, socketPtr->RegisterOffset);
  1257. //
  1258. // Read the Tcic ICSR register to see if CD's have changed.
  1259. //
  1260. changed = (TcicReadBaseReg(socketPtr, R_ICSR) & ICSR_CDCHG) ?TRUE :FALSE;
  1261. //
  1262. // Clear bits in ICSR
  1263. //
  1264. while (TcicReadBaseReg(socketPtr, R_ICSR)) {
  1265. TcicWriteBaseReg(socketPtr, R_ICSR, ICSR_JAM);
  1266. }
  1267. return (changed);
  1268. }
  1269. BOOLEAN
  1270. TcicDetectReadyChanged(
  1271. IN PSOCKET socketPtr
  1272. )
  1273. {
  1274. return FALSE;
  1275. }
  1276. BOOLEAN
  1277. TcicPCCardReady(
  1278. IN PSOCKET SocketPtr
  1279. )
  1280. /*++
  1281. Routine Description:
  1282. Loop for a reasonable amount of time waiting for the card status to
  1283. return ready.
  1284. Arguments:
  1285. SocketPtr - instance data for the socket to check.
  1286. Return Value:
  1287. TRUE - the card is ready.
  1288. FALSE - after a reasonable delay the card is still not ready.
  1289. --*/
  1290. {
  1291. ULONG index;
  1292. //
  1293. // Get the specified socket mapped into the TCIC registers
  1294. //
  1295. TcicSocketSelect(SocketPtr, SocketPtr->RegisterOffset);
  1296. for (index = 0;
  1297. index < 500000
  1298. && !(TcicReadBaseReg(SocketPtr, R_SSTAT) & SSTAT_RDY);
  1299. index++) {
  1300. PcmciaWait(20);
  1301. //
  1302. // Check if the card is still there: if not, we can return
  1303. //
  1304. if (!TcicDetectCardInSocket(SocketPtr)) {
  1305. return FALSE;
  1306. }
  1307. }
  1308. if (index < 500000) {
  1309. DebugPrint((PCMCIA_COUNTERS, "TcicPCCardReady: %d\n", index));
  1310. return TRUE;
  1311. }
  1312. return FALSE;
  1313. }
  1314. NTSTATUS
  1315. TcicDetect(
  1316. IN PFDO_EXTENSION DeviceExtension
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. Locate any PCMCIA sockets supported by this driver. This routine
  1321. will find the TCIC2 and compatible parts.
  1322. Arguments:
  1323. DeviceExtension - the root for the SocketList.
  1324. Return Value:
  1325. STATUS_SUCCESS if a socket is found - failure status otherwise.
  1326. --*/
  1327. {
  1328. ULONG ioPortBase = 0x100;
  1329. ULONG ioBaseIncrement = 0x10;
  1330. ULONG tcicLowAddr;
  1331. ULONG tcicHighAddr;
  1332. ULONG addressSpace;
  1333. BOOLEAN mapped;
  1334. PHYSICAL_ADDRESS cardAddress;
  1335. PHYSICAL_ADDRESS portAddress;
  1336. SOCKET locskt;
  1337. UCHAR socketNumber = 0;
  1338. static BOOLEAN foundOne = FALSE;
  1339. BOOLEAN resourcesAllocated = FALSE;
  1340. BOOLEAN conflict;
  1341. PCM_RESOURCE_LIST cmResourceList = NULL;
  1342. PCM_PARTIAL_RESOURCE_LIST cmPartialResourceList;
  1343. NTSTATUS status;
  1344. if (foundOne) {
  1345. //
  1346. // No support for multiple controllers currently..
  1347. // So we just give up if one controller was already reported
  1348. //
  1349. return STATUS_NO_MORE_ENTRIES;
  1350. }
  1351. DeviceExtension->Configuration.InterfaceType = Isa;
  1352. DeviceExtension->Configuration.BusNumber = 0x0;
  1353. TcicRegistryLookupScanLimits(&tcicLowAddr, &tcicHighAddr);
  1354. //
  1355. // Get the resources used for detection
  1356. //
  1357. cmResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
  1358. if (!cmResourceList) {
  1359. return STATUS_INSUFFICIENT_RESOURCES;
  1360. }
  1361. RtlZeroMemory(cmResourceList, sizeof(CM_RESOURCE_LIST));
  1362. cmResourceList->Count = 1;
  1363. cmResourceList->List[0].InterfaceType = Isa;
  1364. cmPartialResourceList = &(cmResourceList->List[0].PartialResourceList);
  1365. cmPartialResourceList->Version = 1;
  1366. cmPartialResourceList->Revision = 1;
  1367. cmPartialResourceList->Count = 1;
  1368. cmPartialResourceList->PartialDescriptors[0].Type = CmResourceTypePort;
  1369. cmPartialResourceList->PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
  1370. cmPartialResourceList->PartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_10_BIT_DECODE;
  1371. cmPartialResourceList->PartialDescriptors[0].u.Port.Length = 2;
  1372. for (ioPortBase = tcicLowAddr;
  1373. ioPortBase < tcicHighAddr;
  1374. ioPortBase += ioBaseIncrement) {
  1375. //
  1376. // Reset ioBaseIncrement to default value
  1377. //
  1378. ioBaseIncrement = 0x10;
  1379. addressSpace = 1; // port space
  1380. portAddress.LowPart = ioPortBase;
  1381. portAddress.HighPart = 0;
  1382. //
  1383. // Free up the allocated resources if any
  1384. //
  1385. if (resourcesAllocated) {
  1386. IoReportResourceForDetection(DeviceExtension->DriverObject,
  1387. NULL, 0, NULL, NULL, 0, &conflict);
  1388. }
  1389. resourcesAllocated = FALSE;
  1390. cmPartialResourceList->PartialDescriptors[0].u.Port.Start = portAddress;
  1391. status=IoReportResourceForDetection(
  1392. DeviceExtension->DriverObject,
  1393. cmResourceList,
  1394. sizeof(CM_RESOURCE_LIST),
  1395. NULL,
  1396. NULL,
  1397. 0,
  1398. &conflict);
  1399. if (!NT_SUCCESS(status) || conflict) {
  1400. continue;
  1401. }
  1402. resourcesAllocated = TRUE;
  1403. if (!HalTranslateBusAddress(Isa, 0, portAddress, &addressSpace,&cardAddress)) {
  1404. continue;
  1405. }
  1406. if (addressSpace) {
  1407. mapped = FALSE;
  1408. locskt.AddressPort = (PUCHAR)(cardAddress.QuadPart);
  1409. } else {
  1410. mapped = TRUE;
  1411. locskt.AddressPort = MmMapIoSpace(cardAddress, 0x10, FALSE);
  1412. }
  1413. locskt.RegisterOffset = 0;
  1414. //
  1415. // Sniff the address to see if it even resembles a TCIC chip
  1416. //
  1417. foundOne = TcicReservedBitsOK(&locskt);
  1418. if (mapped) {
  1419. MmUnmapIoSpace(locskt.AddressPort, 0x10);
  1420. }
  1421. //
  1422. // Found an adapter
  1423. //
  1424. if (foundOne) {
  1425. PcmciaSetControllerType(DeviceExtension, PcmciaDatabook);
  1426. break;
  1427. }
  1428. #if 0
  1429. //
  1430. // Now check for the aliases
  1431. //
  1432. switch (TcicCheckAliasType((PDBSOCKET)socketPtr)) {
  1433. case TCIC_IS140:
  1434. //
  1435. // TMI-140s decode 32 consecutive bytes, make
  1436. // sure we skip past the alias
  1437. //
  1438. ioBaseIncrement += 0x10;
  1439. break;
  1440. }
  1441. #endif
  1442. }
  1443. //
  1444. // Free up the allocated resources if any
  1445. //
  1446. if (resourcesAllocated) {
  1447. IoReportResourceForDetection(DeviceExtension->DriverObject,
  1448. NULL, 0, NULL, NULL, 0, &conflict);
  1449. }
  1450. //
  1451. // Free up allocated memory if any
  1452. //
  1453. if (cmResourceList) {
  1454. ExFreePool(cmResourceList);
  1455. }
  1456. return foundOne ? STATUS_SUCCESS : STATUS_NO_MORE_ENTRIES;
  1457. }
  1458. NTSTATUS
  1459. TcicBuildSocketList(
  1460. IN PFDO_EXTENSION DeviceExtension
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. Locate any PCMCIA sockets supported by this driver. This routine
  1465. will find the TCIC2 and compatible parts and construct DBSOCKET
  1466. structures to represent all sockets found.
  1467. Arguments:
  1468. DeviceExtension - the root for the SocketList.
  1469. Return Value:
  1470. STATUS_SUCCESS if a socket is found - failure status otherwise.
  1471. --*/
  1472. {
  1473. PSOCKET socketPtr = NULL;
  1474. PSOCKET previousSocketPtr;
  1475. SOCKET locskt;
  1476. static UCHAR socketNumber = 0;
  1477. previousSocketPtr = NULL;
  1478. locskt.RegisterOffset = 0;
  1479. locskt.AddressPort = (PUCHAR)DeviceExtension->Configuration.UntranslatedPortAddress;
  1480. //
  1481. // Sniff the address to see if it even resembles a TCIC chip
  1482. //
  1483. if (TcicReservedBitsOK(&locskt) == FALSE ) {
  1484. return STATUS_NO_MORE_ENTRIES;
  1485. }
  1486. //
  1487. // Found an adapter
  1488. //
  1489. TcicFillInAdapter(&locskt,
  1490. &socketPtr,
  1491. &previousSocketPtr,
  1492. DeviceExtension,
  1493. (ULONG)DeviceExtension->Configuration.UntranslatedPortAddress);
  1494. if (socketPtr == NULL) {
  1495. return STATUS_UNSUCCESSFUL;
  1496. }
  1497. socketPtr->SocketNumber = socketNumber++;
  1498. return STATUS_SUCCESS;
  1499. }
  1500. VOID
  1501. TcicFillInAdapter(
  1502. IN PSOCKET plocskt,
  1503. IN PSOCKET *psocketPtr,
  1504. IN PSOCKET *previousSocketPtr,
  1505. IN PFDO_EXTENSION DeviceExtension,
  1506. IN ULONG ioPortBase
  1507. )
  1508. /*++
  1509. Routine Description:
  1510. Fill in the DBSOCKET pointer info for the adapter just located by
  1511. TcicDetect(). This routine is not part of TcicDetect() so as to allow
  1512. for logic flow when dealing with multiple sockets or adapters.
  1513. Arguments:
  1514. plocskt - info regarding the socket just found
  1515. psocketPtr - current socket ptr from caller
  1516. previousSocketPtr - prev socket ptr form caller
  1517. DeviceExtension - head of socket list
  1518. ioPortBase - physical i/o addr for this controller
  1519. Return Value:
  1520. None
  1521. --*/
  1522. {
  1523. PDBSOCKET dbsocketPtr = ExAllocatePool(NonPagedPool, sizeof(DBSOCKET));
  1524. PAGED_CODE();
  1525. if (!dbsocketPtr) {
  1526. return;
  1527. }
  1528. RtlZeroMemory(dbsocketPtr, sizeof(DBSOCKET));
  1529. dbsocketPtr->physPortAddr = ioPortBase;
  1530. *psocketPtr = (PSOCKET)dbsocketPtr;
  1531. (*psocketPtr)->DeviceExtension = DeviceExtension;
  1532. (*psocketPtr)->RegisterOffset = 0;
  1533. (*psocketPtr)->AddressPort = plocskt->AddressPort;
  1534. (*psocketPtr)->SocketFnPtr = &TcicSupportFns;
  1535. if (*previousSocketPtr) {
  1536. (*previousSocketPtr)->NextSocket = *psocketPtr;
  1537. } else {
  1538. DeviceExtension->SocketList = *psocketPtr;
  1539. }
  1540. *previousSocketPtr = *psocketPtr;
  1541. DebugPrint((PCMCIA_DEBUG_DETECT,
  1542. "PCMCIA: TCIC Port %x\n",
  1543. plocskt->AddressPort));
  1544. //
  1545. // Fill in the rest of the adapter info here...
  1546. //
  1547. TcicGetAdapterInfo(dbsocketPtr);
  1548. //
  1549. // See if there is a second socket on this TCIC
  1550. //
  1551. if (TcicCheckSkt(plocskt, 1)) {
  1552. dbsocketPtr = ExAllocatePool(NonPagedPool, sizeof(DBSOCKET));
  1553. if (dbsocketPtr) {
  1554. RtlMoveMemory(dbsocketPtr, *psocketPtr, sizeof(DBSOCKET));
  1555. *psocketPtr = (PSOCKET)dbsocketPtr;
  1556. (*psocketPtr)->RegisterOffset = 1;
  1557. (*previousSocketPtr)->NextSocket = *psocketPtr;
  1558. *previousSocketPtr = *psocketPtr;
  1559. dbsocketPtr->dflt_vcc5v = TcicGet5vVccVal(dbsocketPtr);
  1560. }
  1561. }
  1562. }
  1563. VOID
  1564. TcicGetAdapterInfo(
  1565. IN PDBSOCKET dbsocketPtr
  1566. )
  1567. /*++
  1568. Routine Description:
  1569. Deterimine adapter specific information from detection heuristics.
  1570. Arguments:
  1571. dbsocketPtr - structure to fill in.
  1572. Return Value:
  1573. None
  1574. --*/
  1575. {
  1576. PAGED_CODE();
  1577. TcicChipID(dbsocketPtr);
  1578. dbsocketPtr->niowins = (UCHAR)TcicGetnIOWins(dbsocketPtr);
  1579. dbsocketPtr->nmemwins = (UCHAR)TcicGetnMemWins(dbsocketPtr);
  1580. dbsocketPtr->clkdiv = TcicClockRate(&dbsocketPtr->skt) - (USHORT)1;
  1581. dbsocketPtr->dflt_vcc5v = TcicGet5vVccVal(dbsocketPtr);
  1582. dbsocketPtr->dflt_wctl = (USHORT)((dbsocketPtr->clkdiv != 0)
  1583. ? (WAIT_BCLK | WAIT_RISING | WAIT_ASYNC)
  1584. : (WAIT_ASYNC | WAIT_RISING));
  1585. dbsocketPtr->dflt_syscfg = (USHORT)(SYSCFGMPSEL_EXTSEL | SYSCFG_MCSFULL);
  1586. if (TcicCheckXBufNeeded(&dbsocketPtr->skt)) {
  1587. dbsocketPtr->dflt_syscfg |= (USHORT)(SYSCFG_ICSXB | SYSCFG_MCSXB);
  1588. }
  1589. dbsocketPtr->dflt_ilock = (USHORT)ILOCK_HOLD_CCLK;
  1590. dbsocketPtr->dflt_wrmctl = (USHORT)0;
  1591. dbsocketPtr->dflt_scfg1 = (USHORT)IRSCFG_IOSTS;
  1592. TcicGetIRQMap(dbsocketPtr);
  1593. //
  1594. // Fiddle the map for all but 084/184 so that SKTIRQ (0bh) has
  1595. // the correct map code (1) (PNPFIX)
  1596. //
  1597. if (TcicHasSktIRQPin(dbsocketPtr) == TRUE && dbsocketPtr->IRQMapTbl[11] == 11) {
  1598. dbsocketPtr->IRQMapTbl[11] = 1;
  1599. }
  1600. }
  1601. PUCHAR
  1602. TcicAllocateMemRange(
  1603. IN PFDO_EXTENSION DeviceExtension,
  1604. IN PULONG Mapped,
  1605. IN PULONG Physical
  1606. )
  1607. /*++
  1608. Routine Description:
  1609. Search the 640K to 1MB region for an 8K open area to be used
  1610. for XBuffer checking.
  1611. Arguments:
  1612. DeviceExtension - head of socket list
  1613. Mapped - state info from caller to allow later release
  1614. Physical - state info from caller to allow later release
  1615. Return Value:
  1616. A physical address for the window to the card or zero meaning
  1617. there is no opening.
  1618. --*/
  1619. {
  1620. #define NUMBER_OF_TEST_BYTES 5
  1621. PHYSICAL_ADDRESS physicalMemoryAddress;
  1622. PHYSICAL_ADDRESS halMemoryAddress;
  1623. BOOLEAN translated;
  1624. ULONG untranslatedAddress;
  1625. PUCHAR memoryAddress;
  1626. PUCHAR bogus;
  1627. ULONG addressSpace;
  1628. ULONG index;
  1629. UCHAR memory[NUMBER_OF_TEST_BYTES];
  1630. PAGED_CODE();
  1631. *Mapped = FALSE;
  1632. if (DeviceExtension->PhysicalBase.QuadPart) {
  1633. untranslatedAddress = DeviceExtension->PhysicalBase.LowPart;
  1634. } else {
  1635. untranslatedAddress = 0xd0000;
  1636. }
  1637. for (/* nothing */; untranslatedAddress < 0xFF000; untranslatedAddress += TCIC_WINDOW_ALIGNMENT) {
  1638. if (untranslatedAddress == 0xc0000) {
  1639. //
  1640. // This is VGA. Keep this test if the for loop should
  1641. // ever change.
  1642. //
  1643. continue;
  1644. }
  1645. addressSpace = 0;
  1646. physicalMemoryAddress.LowPart = untranslatedAddress;
  1647. physicalMemoryAddress.HighPart = 0;
  1648. translated = HalTranslateBusAddress(Isa,
  1649. 0,
  1650. physicalMemoryAddress,
  1651. &addressSpace,
  1652. &halMemoryAddress);
  1653. if (!translated) {
  1654. //
  1655. // HAL doesn't like this translation
  1656. //
  1657. continue;
  1658. }
  1659. if (addressSpace) {
  1660. memoryAddress = (PUCHAR)(halMemoryAddress.QuadPart);
  1661. } else {
  1662. memoryAddress = MmMapIoSpace(halMemoryAddress, TCIC_WINDOW_SIZE, FALSE);
  1663. }
  1664. //
  1665. // Test the memory window to determine if it is a BIOS, video
  1666. // memory, or open memory. Only want to keep the window if it
  1667. // is not being used by something else.
  1668. //
  1669. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  1670. memory[index] = READ_REGISTER_UCHAR(memoryAddress + index);
  1671. if (index) {
  1672. if (memory[index] != memory[index - 1]) {
  1673. break;
  1674. }
  1675. }
  1676. }
  1677. if (index == NUMBER_OF_TEST_BYTES) {
  1678. //
  1679. // There isn't a BIOS here
  1680. //
  1681. UCHAR memoryPattern[NUMBER_OF_TEST_BYTES];
  1682. BOOLEAN changed = FALSE;
  1683. //
  1684. // Check for video memory - open memory should always remain
  1685. // the same regardless what the changes are. Change the
  1686. // pattern previously found.
  1687. //
  1688. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  1689. memoryPattern[index] = ~memory[index];
  1690. WRITE_REGISTER_UCHAR(memoryAddress + index,
  1691. memoryPattern[index]);
  1692. }
  1693. //
  1694. // See if the pattern in memory changed.
  1695. // Some system exhibit a problem where the memory pattern
  1696. // seems to be cached. If this code is debugged it will
  1697. // work as expected, but if it is run normally it will
  1698. // always return that the memory changed. This random
  1699. // wandering seems to remove this problem.
  1700. //
  1701. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  1702. memoryPattern[index] = 0;
  1703. }
  1704. bogus = ExAllocatePool(NonPagedPool, 64 * 1024);
  1705. if (bogus) {
  1706. for (index = 0; index < 64 * 1024; index++) {
  1707. bogus[index] = 0;
  1708. }
  1709. ExFreePool(bogus);
  1710. }
  1711. //
  1712. // Now go off and do the actual check to see if the memory
  1713. // changed.
  1714. //
  1715. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  1716. if ((memoryPattern[index] = READ_REGISTER_UCHAR(memoryAddress + index)) != memory[index]) {
  1717. //
  1718. // It changed - this is not an area of open memory
  1719. //
  1720. changed = TRUE;
  1721. }
  1722. WRITE_REGISTER_UCHAR(memoryAddress + index,
  1723. memory[index]);
  1724. }
  1725. if (!changed) {
  1726. //
  1727. // Area isn't a BIOS and didn't change when written.
  1728. // Use this region for the memory window to PCMCIA
  1729. // attribute memory.
  1730. //
  1731. *Mapped = addressSpace ? FALSE : TRUE;
  1732. *Physical = untranslatedAddress;
  1733. return memoryAddress;
  1734. }
  1735. }
  1736. if (!addressSpace) {
  1737. MmUnmapIoSpace(memoryAddress, TCIC_WINDOW_SIZE);
  1738. }
  1739. }
  1740. return NULL;
  1741. }
  1742. BOOLEAN
  1743. TcicReservedBitsOK(
  1744. IN PSOCKET pskt
  1745. )
  1746. /*++
  1747. Routine Description:
  1748. Various offsets from a base IO address are read and checked for
  1749. reasonable values (e.g., see that reserved bits are zero)
  1750. First the primary registers are checked, then if the mode
  1751. register is pointing at an aux register that has reserved bits,
  1752. then that value is checked as well.
  1753. If the TCIC is not in reset, then the programming timers
  1754. will have expired by the time this runs
  1755. Further, a read from the data register should change the
  1756. EDC register.
  1757. Note that these tests are as nondestructive as possible, e.g.
  1758. initially only read accesses are made to the IO range in question.
  1759. Arguments:
  1760. pskt - pointer to an Instance data to work from.
  1761. Return Value:
  1762. TRUE if all reserved bits are zero
  1763. --*/
  1764. {
  1765. USHORT i, j, bits;
  1766. PAGED_CODE();
  1767. //
  1768. // R_ADDR bits 30:28 have restricted range
  1769. //
  1770. i = (USHORT)((TcicReadBaseReg(pskt, R_ADDR2) & TCIC_SS_MASK) >> TCIC_SS_SHFT);
  1771. if ( i > 1) {
  1772. return FALSE;
  1773. }
  1774. //
  1775. // R_SCTRL bits 6,2,1 are reserved
  1776. //
  1777. if (TcicReadBaseReg(pskt, R_SCTRL) & ((~(SCTRL_ENA|SCTRL_INCMODE|SCTRL_EDCSUM|SCTRL_RESET)) & 0x00ff)) {
  1778. return FALSE;
  1779. }
  1780. //
  1781. // R_ICSR bit 2 must be same as bit 3
  1782. //
  1783. i = TcicReadBaseReg(pskt, R_ICSR);
  1784. i &= (ICSR_ILOCK | ICSR_STOPCPU);
  1785. if ((i != 0) && (i != (ICSR_ILOCK | ICSR_STOPCPU))) {
  1786. return FALSE;
  1787. }
  1788. //
  1789. // R_IENA bits 7,2 are reserved
  1790. //
  1791. if (TcicReadBaseReg(pskt, R_IENA) & ((~(IENA_CDCHG|IENA_PROGTIME|IENA_ILOCK|IENA_CFG_MASK)) & 0xff)) {
  1792. return FALSE;
  1793. }
  1794. //
  1795. // Some aux registers have reserved bits
  1796. // Which are we looking at?
  1797. //
  1798. i = (USHORT)(TcicReadBaseReg(pskt, R_MODE) & MODE_AUXSEL_MASK);
  1799. j = TcicReadBaseReg(pskt, R_AUX);
  1800. switch (i) {
  1801. case MODE_AR_SYSCFG:
  1802. if (INVALID_AR_SYSCFG(j)) {
  1803. return FALSE;
  1804. }
  1805. break;
  1806. case MODE_AR_ILOCK:
  1807. if (INVALID_AR_ILOCK(j)) {
  1808. return FALSE;
  1809. }
  1810. break;
  1811. case MODE_AR_TEST:
  1812. if (INVALID_AR_TEST(j)) {
  1813. return FALSE;
  1814. }
  1815. break;
  1816. }
  1817. //
  1818. // Various bits set or not depending if in RESET mode
  1819. //
  1820. i = TcicReadBaseReg(pskt, R_SCTRL);
  1821. if (i & SCTRL_RESET) {
  1822. //
  1823. // address bits must be 0 */
  1824. //
  1825. if ((TcicReadBaseReg(pskt, R_ADDR) != 0) || (TcicReadBaseReg(pskt, R_ADDR2) != 0)) {
  1826. return FALSE;
  1827. }
  1828. //
  1829. // EDC bits must be 0 */
  1830. //
  1831. if (TcicReadBaseReg(pskt, R_EDC) != 0) {
  1832. return FALSE;
  1833. }
  1834. //
  1835. // We're OK, so take it out of reset
  1836. // Note: we can write a 0 because RESET guarantees us that the
  1837. // other bits in SCTRL are 0.
  1838. //
  1839. TcicWriteBaseReg(pskt, R_SCTRL, 0);
  1840. } else {
  1841. //
  1842. // not in reset
  1843. // programming timers must be expired
  1844. //
  1845. i = TcicReadBaseReg(pskt, R_SSTAT);
  1846. if ((i & (SSTAT_6US | SSTAT_10US | SSTAT_PROGTIME)) != (SSTAT_6US | SSTAT_10US | SSTAT_PROGTIME)) {
  1847. return FALSE;
  1848. }
  1849. //
  1850. // EDC bits should change on read from data space
  1851. // as long as either EDC or the data are nonzero
  1852. //
  1853. if ((TcicReadBaseReg(pskt, R_ADDR2) & ADR2_INDREG) == 0) {
  1854. j = TcicReadBaseReg(pskt, R_EDC);
  1855. i = TcicReadBaseReg(pskt, R_DATA);
  1856. if ( i | j ) {
  1857. i = TcicReadBaseReg(pskt, R_EDC);
  1858. if (i==j) {
  1859. return FALSE;
  1860. }
  1861. }
  1862. }
  1863. j = TcicReadBaseReg(pskt, R_MODE);
  1864. i = (USHORT)(j ^ MODE_AUXSEL_MASK);
  1865. TcicWriteBaseReg(pskt, R_MODE, i);
  1866. if (TcicReadBaseReg(pskt, R_MODE) != i) {
  1867. return(FALSE);
  1868. }
  1869. TcicWriteBaseReg(pskt, R_MODE, j);
  1870. }
  1871. //
  1872. // All tests passed
  1873. //
  1874. return TRUE;
  1875. }
  1876. USHORT
  1877. TcicChipID(
  1878. IN PDBSOCKET pInst
  1879. )
  1880. /*++
  1881. Routine Description:
  1882. Read the silicon ID from a TCIC
  1883. Arguments:
  1884. pInst - pointer to an Instance data to work from.
  1885. Return Value:
  1886. The TCIC chip id.
  1887. --*/
  1888. {
  1889. USHORT id, oldtest;
  1890. PAGED_CODE();
  1891. oldtest = TcicReadAuxReg (&pInst->skt, MODE_AR_TEST);
  1892. TcicWriteAuxReg (&pInst->skt, MODE_AR_TEST, (USHORT)TEST_DIAG);
  1893. id = TcicReadAuxReg (&pInst->skt, MODE_AR_ILOCK);
  1894. TcicWriteAuxReg (&pInst->skt, MODE_AR_TEST, oldtest);
  1895. id &= ILOCKTEST_ID_MASK;
  1896. id >>= ILOCKTEST_ID_SHFT;
  1897. //
  1898. // clearn up IRQs inside TCIC
  1899. //
  1900. while (TcicReadBaseReg (&pInst->skt, R_ICSR)) {
  1901. TcicWriteBaseReg (&pInst->skt, R_ICSR, ICSR_JAM);
  1902. }
  1903. return (pInst->chipType = id);
  1904. }
  1905. BOOLEAN
  1906. TcicCheckSkt(
  1907. IN PSOCKET pInst,
  1908. IN int iSocket
  1909. )
  1910. /*++
  1911. Routine Description:
  1912. If R_SSTAT shows a card inserted, we're done already.
  1913. otherwise, we set up /CRDYBSY and /CWAIT such that if
  1914. there is a socket present, they will float high
  1915. Arguments:
  1916. pInst - pointer to an Instance data to work from.
  1917. iSocket - zero-based socket number
  1918. Return Value:
  1919. TRUE if given socket exists
  1920. --*/
  1921. {
  1922. USHORT old_addr2;
  1923. USHORT mode, pwr, sctrl;
  1924. BOOLEAN retval = FALSE;
  1925. BOOLEAN card_in = FALSE;
  1926. int j, rdy, wait;
  1927. USHORT save_pic;
  1928. PAGED_CODE();
  1929. //
  1930. // Socket number OK?
  1931. //
  1932. if (iSocket > 1) {
  1933. return FALSE;
  1934. }
  1935. //
  1936. // save current socket, look at requested
  1937. //
  1938. old_addr2 = TcicReadBaseReg(pInst, R_ADDR2);
  1939. TcicWriteBaseReg(pInst, R_ADDR2,
  1940. (USHORT)((old_addr2 & ~TCIC_SS_MASK) |
  1941. (iSocket << ADR2_SS_SHFT)));
  1942. //
  1943. // is there a card?
  1944. //
  1945. if (TcicReadBaseReg(pInst, R_SSTAT) & SSTAT_CD) {
  1946. //
  1947. // should set back address register before return.
  1948. //
  1949. TcicWriteBaseReg(pInst, R_ADDR2, old_addr2);
  1950. return TRUE;
  1951. } else {
  1952. //
  1953. // save mode, sctrl, and power for selected socket
  1954. //
  1955. mode = TcicReadBaseReg(pInst, (USHORT)R_MODE);
  1956. pwr = TcicReadBaseReg(pInst, (USHORT)R_PWR);
  1957. sctrl = TcicReadBaseReg(pInst, (USHORT)R_SCTRL);
  1958. //
  1959. // check if power is already on- in case someone has
  1960. // inadvertently turned on our power
  1961. //
  1962. if (pwr & 0x27) {
  1963. TcicWriteBaseReg(pInst, R_PWR, (UCHAR)(pwr & ~0x27));
  1964. }
  1965. //
  1966. // put chip into diagnostic mode, turn on VPP enables
  1967. //
  1968. TcicWriteAuxReg(pInst, MODE_AR_TEST,
  1969. (USHORT)(TEST_DIAG | TEST_VCTL));
  1970. //
  1971. // should see /CRDYBSY and /CWAIT low
  1972. //
  1973. if (!(TcicReadBaseReg(pInst, R_SSTAT) & SSTAT_RDY) &&
  1974. (TcicReadAuxReg(pInst, MODE_AR_ILOCK) & ILOCK_CWAITSNS)) {
  1975. //
  1976. // 5V power on */
  1977. //
  1978. if (TcicIsPnP ((PDBSOCKET)pInst)) {
  1979. TcicWriteBaseReg(pInst, R_PWR, (USHORT)(pwr | 0x27));
  1980. } else {
  1981. TcicWriteBaseReg(pInst, R_PWR,
  1982. (UCHAR)(pwr | (iSocket==0? 1 : 2)));
  1983. }
  1984. //
  1985. // should see /CRDYBSY and /CWAIT high within about 1.5 sec
  1986. //
  1987. for (j = 0; j < 75; j++) {
  1988. rdy = TcicReadBaseReg(pInst, R_SSTAT) & SSTAT_RDY;
  1989. wait = TcicReadAuxReg(pInst, MODE_AR_ILOCK) & ILOCK_CWAITSNS;
  1990. if (rdy && !wait) {
  1991. retval = TRUE;
  1992. break;
  1993. }
  1994. PcmciaWait(20000);
  1995. }
  1996. //
  1997. // Now be sure /CRDYBSY and /CWAIT drain
  1998. //
  1999. // turn power off
  2000. //
  2001. TcicWriteBaseReg(pInst, R_PWR, 0);
  2002. //
  2003. // force card enable */
  2004. //
  2005. TcicWriteAuxReg(pInst, MODE_AR_TEST,
  2006. (USHORT)(TEST_DIAG | TEST_VCTL | TEST_ENA) );
  2007. //
  2008. // turn on a bunch of bits for drain path
  2009. //
  2010. TcicWriteBaseReg(pInst, R_MODE,
  2011. MODE_PGMWR | MODE_PGMRD |
  2012. MODE_PGMCE | MODE_PGMWORD );
  2013. //
  2014. // enable the socket
  2015. //
  2016. TcicWriteBaseReg(pInst, R_SCTRL, 1);
  2017. //
  2018. // expect CRDYBSY to drain
  2019. //
  2020. for (j = 0; j < 75; j++) {
  2021. rdy = TcicReadBaseReg(pInst, R_SSTAT) & SSTAT_RDY;
  2022. if (!rdy) {
  2023. break;
  2024. }
  2025. PcmciaWait(20000);
  2026. }
  2027. //
  2028. // Wait for noise to settle
  2029. //
  2030. for (j = 0; j < 50; j++) {
  2031. PcmciaWait(20000);
  2032. }
  2033. }
  2034. //
  2035. // out of diag mode
  2036. //
  2037. TcicWriteAuxReg(pInst, MODE_AR_TEST, 0);
  2038. //
  2039. // clearn up IRQs inside TCIC
  2040. //
  2041. while (TcicReadBaseReg (pInst, R_ICSR)) {
  2042. TcicWriteBaseReg (pInst, R_ICSR, ICSR_JAM);
  2043. }
  2044. //
  2045. // restore original mode
  2046. //
  2047. TcicWriteBaseReg(pInst, R_MODE, mode);
  2048. //
  2049. // restore SCTRL
  2050. //
  2051. TcicWriteBaseReg(pInst, R_SCTRL, sctrl);
  2052. //
  2053. // set socket's power correctly
  2054. //
  2055. TcicWriteBaseReg(pInst, R_PWR, pwr);
  2056. //
  2057. // restore originally selected socket
  2058. //
  2059. TcicWriteBaseReg(pInst, R_ADDR2, old_addr2);
  2060. }
  2061. return retval;
  2062. }
  2063. USHORT
  2064. TcicCheckAliasing(
  2065. IN PDBSOCKET pdbskt,
  2066. IN USHORT offst
  2067. )
  2068. /*++
  2069. Routine Description:
  2070. For each of the 16 I/O locations in the TCIC, if any of
  2071. the corresponding locations |offst| bytes higher are different,
  2072. then aliasing is not occurring. Exceptions, if the chip is
  2073. active, may be found in R_DATA and R_SSTAT; accordingly, we
  2074. avoid these registers in this check.
  2075. If they all compare, then the R_MODE register is changed;
  2076. if the corresponding change occurs in the image,
  2077. then we have aliasing.
  2078. Arguments:
  2079. pInst - pointer to an Instance data to work from.
  2080. offst - offset to check for image of this TCIC at.
  2081. Return Value:
  2082. TCIC_NONE: no TCIC found
  2083. TCIC_NOALIAS: different TCIC found
  2084. TCIC_ALIAS: aliasing found
  2085. --*/
  2086. {
  2087. int j;
  2088. USHORT mode, flipmode;
  2089. SOCKET locskt;
  2090. USHORT retval;
  2091. PHYSICAL_ADDRESS cardAddress;
  2092. PHYSICAL_ADDRESS portAddress;
  2093. BOOLEAN mapped;
  2094. ULONG addressSpace;
  2095. PAGED_CODE();
  2096. //
  2097. // Check for TCIC at image location, returning NONE if none found:
  2098. //
  2099. addressSpace = 1; // port space
  2100. portAddress.LowPart = pdbskt->physPortAddr + offst;
  2101. portAddress.HighPart = 0;
  2102. if (!HalTranslateBusAddress(Isa, 0, portAddress, &addressSpace,&cardAddress)) {
  2103. return retval = TCIC_NONE;
  2104. }
  2105. if (addressSpace) {
  2106. mapped = FALSE;
  2107. locskt.AddressPort = (PUCHAR)(cardAddress.QuadPart);
  2108. } else {
  2109. mapped = TRUE;
  2110. locskt.AddressPort = MmMapIoSpace(cardAddress, 0x10, FALSE);
  2111. }
  2112. if (!TcicReservedBitsOK(&locskt)) {
  2113. if (mapped) {
  2114. MmUnmapIoSpace(locskt.AddressPort, 0x10);
  2115. }
  2116. return (retval = TCIC_NONE);
  2117. }
  2118. //
  2119. // Check the R_xxx range for differences
  2120. //
  2121. for (j = R_ADDR; j < 16; ++j) {
  2122. if (j != R_SSTAT) {
  2123. if (READ_PORT_UCHAR(pdbskt->skt.AddressPort + j) != READ_PORT_UCHAR((locskt.AddressPort + j))) {
  2124. if (mapped) {
  2125. MmUnmapIoSpace(locskt.AddressPort, 0x10);
  2126. }
  2127. return (retval = TCIC_NOALIAS);
  2128. }
  2129. }
  2130. }
  2131. //
  2132. // OK, flip the mode register and see if it changes in the
  2133. // aliased range
  2134. //
  2135. mode = TcicReadBaseReg(&pdbskt->skt, R_MODE) ^ 0xe0;
  2136. TcicWriteBaseReg(&pdbskt->skt, R_MODE, mode);
  2137. flipmode = TcicReadBaseReg(&pdbskt->skt, (USHORT)R_MODE + offst);
  2138. TcicWriteBaseReg(&pdbskt->skt, R_MODE, (USHORT)(mode ^ 0xe0));
  2139. if (flipmode == mode) {
  2140. retval = TCIC_ALIAS;
  2141. } else {
  2142. retval = TCIC_NOALIAS;
  2143. }
  2144. if (mapped) {
  2145. MmUnmapIoSpace(locskt.AddressPort, 0x10);
  2146. }
  2147. return retval;
  2148. }
  2149. USHORT
  2150. TcicCheckAliasType (
  2151. IN PDBSOCKET pInst
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. This function is useful for distinguishing among Databook
  2156. controller cards. For instance, the TMI-140 will be found
  2157. at its base address and again at the base address + 10h, while
  2158. the TMB-270 has two controllers separated by 400h, with aliases
  2159. at an offset of 800h.
  2160. Use TcicCheckAliasing to determine:
  2161. 1) Do we have a 270 (two non-identical TCICs appear, 400h
  2162. apart)?
  2163. 2) Do we have an "new-style" controller, with an image of
  2164. itself 800h away from the base address?
  2165. For more detail, see TcicCheckAliasing above.
  2166. Arguments:
  2167. pInst - socket instance info.
  2168. Return Value:
  2169. A value encoding the results found:
  2170. TCIC_IS270 : indicates 270 found
  2171. TCIC_ALIAS800 : indicates base+800h alias found
  2172. TCIC_IS140 : indicates base+10h alias found
  2173. TCIC_ALIAS400 : indicates base+400h alias found
  2174. --*/
  2175. {
  2176. USHORT retval = 0;
  2177. PAGED_CODE();
  2178. switch (TcicCheckAliasing (pInst, TCIC_OFFSET_400)) {
  2179. case TCIC_NOALIAS :
  2180. /* (indicating TCIC found, but not aliased) */
  2181. retval |= TCIC_IS270;
  2182. break;
  2183. case TCIC_ALIAS :
  2184. /* (indicating this TCIC appears again there) */
  2185. retval |= TCIC_ALIAS400;
  2186. break;
  2187. }
  2188. if (TcicCheckAliasing (pInst, TCIC_OFFSET_800) == TCIC_ALIAS) {
  2189. retval |= TCIC_ALIAS800;
  2190. }
  2191. if (TcicCheckAliasing (pInst, TCIC_ALIAS_OFFSET) == TCIC_ALIAS) {
  2192. retval |= TCIC_IS140;
  2193. }
  2194. return retval;
  2195. }
  2196. BOOLEAN
  2197. TcicCheckXBufNeeded(
  2198. IN PSOCKET pInst
  2199. )
  2200. /*++
  2201. Routine Description:
  2202. Two overlapping memory windows are set up, a 16 bit and
  2203. an 8 bit.
  2204. We make two accesses to the memory area: 1st one accesses
  2205. the 16-bit window, 2nd accesses the 8-bit window. They
  2206. MUST be done back-to-back so that MCS16# doesn't have time
  2207. to settle between the two accesses.
  2208. We then check the value from accessing win2. (We don't
  2209. care about the value from Win1, we just use it to make
  2210. sure that MSC16# was asserted.) It should either match
  2211. the value in PDATA or match the low byte in PDATA (082
  2212. mem window bug.) If it matches for all iterations of the
  2213. test, then we assume that external buffers are not
  2214. present.
  2215. Arguments:
  2216. pInst - pointer to an Instance data to work from.
  2217. Return Value:
  2218. TRUE if external buffering needs to be turned on.
  2219. --*/
  2220. {
  2221. PUCHAR winPhysAddr;
  2222. PUCHAR WinMappedAddr;
  2223. BOOLEAN ena_buffers = FALSE;
  2224. PUSHORT pfoo1, pfoo2;
  2225. USHORT foo1, foo2;
  2226. int j;
  2227. ULONG mapped;
  2228. PAGED_CODE();
  2229. //
  2230. // Alloc addr space for an 8K mem window
  2231. //
  2232. WinMappedAddr = TcicAllocateMemRange(pInst->DeviceExtension,
  2233. &mapped,
  2234. (PULONG)&winPhysAddr);
  2235. //
  2236. // If the alloc failed (WinLinear == NULL), there
  2237. // really is no point in doing the test
  2238. //
  2239. if (WinMappedAddr != NULL) {
  2240. //
  2241. // Set R_ADDR to 0 to make sure that socket 0 is selected
  2242. //
  2243. TcicWriteBaseReg(pInst, R_ADDR, 0);
  2244. TcicWriteBaseReg(pInst, R_ADDR2, 0);
  2245. //
  2246. // Turn on HA24-12 decoding
  2247. //
  2248. TcicWriteAuxReg(pInst, MODE_AR_SYSCFG, SYSCFG_MCSFULL);
  2249. //
  2250. // Setup a test value to drive into the mem windows
  2251. //
  2252. TcicWriteAuxReg(pInst, MODE_AR_PDATA, 0x5678);
  2253. //
  2254. // Set the window to USHORT regardless of CD states
  2255. //
  2256. TcicWriteAuxReg(pInst, MODE_AR_TEST, TEST_ENA | TEST_DRIVECDB);
  2257. //
  2258. // Make sure that PDATA is being driven to the windows
  2259. //
  2260. TcicWriteBaseReg(pInst, R_MODE, MODE_PGMDBW | MODE_PGMWORD);
  2261. //
  2262. // Enable the socket, set INCMODE for convenience
  2263. //
  2264. TcicWriteBaseReg(pInst, R_SCTRL, SCTRL_ENA | SCTRL_INCMODE_AUTO);
  2265. //
  2266. // cook the TCIC's idea of the base addr
  2267. //
  2268. ((ULONG_PTR)winPhysAddr) >>= MBASE_HA_SHFT;
  2269. //
  2270. // setup the two windows
  2271. //
  2272. TcicSetMemWindow(pInst, 0, (ULONG_PTR)winPhysAddr, 1, (USHORT)MCTL_ENA);
  2273. TcicSetMemWindow(pInst, 1, (ULONG_PTR)(winPhysAddr + 1), 1,
  2274. (USHORT)(MCTL_ENA | MCTL_B8));
  2275. //
  2276. // Now setup two pointers, one into each window.
  2277. // We'll set pfoo2 to point to the 1st USHORT of Win2 and
  2278. // pfoo1 to point to the last USHORT of Win1.
  2279. //
  2280. pfoo1 = pfoo2 = (PUSHORT)(WinMappedAddr + 0x1000);
  2281. pfoo1--;
  2282. //
  2283. // Now the test
  2284. //
  2285. for (j = 0; j < 100; j++) {
  2286. foo1 = READ_REGISTER_USHORT(pfoo1);
  2287. foo2 = READ_REGISTER_USHORT(pfoo2);
  2288. if (foo2 != 0x5678 && foo2 != 0x7878) {
  2289. ena_buffers = TRUE;
  2290. break;
  2291. }
  2292. }
  2293. //
  2294. // last, restore the TCIC to a sane condition
  2295. //
  2296. TcicSetMemWindow(pInst, 0, 0, 0, 0);
  2297. TcicSetMemWindow(pInst, 1, 0, 0, 0);
  2298. TcicWriteAuxReg(pInst, MODE_AR_SYSCFG, 0);
  2299. TcicWriteAuxReg(pInst, MODE_AR_PDATA, 0);
  2300. TcicWriteAuxReg(pInst, MODE_AR_TEST, 0);
  2301. TcicWriteBaseReg(pInst, R_MODE, 0);
  2302. TcicWriteBaseReg(pInst, R_SCTRL, 0);
  2303. }
  2304. if (WinMappedAddr != NULL && mapped) {
  2305. MmUnmapIoSpace(WinMappedAddr, TCIC_WINDOW_SIZE);
  2306. }
  2307. return ena_buffers;
  2308. }
  2309. VOID
  2310. TcicSetMemWindow(
  2311. IN PSOCKET pInst,
  2312. IN USHORT wnum,
  2313. IN ULONG_PTR base,
  2314. IN USHORT npages,
  2315. IN USHORT mctl
  2316. )
  2317. /*++
  2318. Routine Description:
  2319. Helper function for TcicCheckXBufNeeded()
  2320. Arguments:
  2321. pInst - pointer to an Instance data to work from.
  2322. wnum - window number (0 - n memwindows)
  2323. base - base Host addr to map to
  2324. npages- window size in 4k pages
  2325. mctl - window ctrl reg value
  2326. Return Value:
  2327. None
  2328. --*/
  2329. {
  2330. USHORT map;
  2331. USHORT winvals[3];
  2332. PAGED_CODE();
  2333. winvals[1] = (USHORT)(((short)base * -1) & 0x3fff);
  2334. winvals[0] = npages == 1 ? (USHORT)base | MBASE_4K :(USHORT)base;
  2335. winvals[2] = mctl;
  2336. TcicWriteIndirectRegs(pInst, (USHORT)IR_MBASE_W(wnum), 3, winvals);
  2337. }
  2338. VOID
  2339. TcicGetPossibleIRQs(
  2340. IN PDBSOCKET pInst,
  2341. IN UCHAR *ptbl
  2342. )
  2343. /*++
  2344. Routine Description:
  2345. The given array is filled in with the irqcaps data determined
  2346. from the chip properties.
  2347. If this is a Plug n Play chip, the IR_ADPTCFG register is
  2348. used to provide additional data
  2349. Arguments:
  2350. pInst - pointer to an Instance data to work from.
  2351. ptbl - pointer to list buffer to fill in.
  2352. Return Value:
  2353. None
  2354. --*/
  2355. {
  2356. int j;
  2357. CHIPPROPS *pcp;
  2358. UCHAR *pbtbl;
  2359. PAGED_CODE();
  2360. if ((pcp = TcicGetChipProperties(pInst)) == NULL) {
  2361. return;
  2362. }
  2363. //
  2364. // If we're using the 082 table, and we've got a divided clock,
  2365. // assume that IRQ6 and IRQ9 are crossed. Likewise, if we've got
  2366. // an 072 table and divided clock, assume that 9 and 14 are
  2367. // crossed.
  2368. //
  2369. pbtbl = pcp->irqcaps;
  2370. if (pInst->clkdiv != 0) {
  2371. if (pbtbl == irqcaps_082) {
  2372. pbtbl = irqcaps_082sw;
  2373. } else {
  2374. if (pbtbl == irqcaps_072) {
  2375. pbtbl = irqcaps_072sw;
  2376. }
  2377. }
  2378. }
  2379. for (j = 0; j < 16 ; j++) {
  2380. ptbl[j] = pbtbl[j];
  2381. }
  2382. /*
  2383. * If this chip is a PNP chip, then we need to consult the
  2384. * IR_ADPTCFG reg to see if additional IRQs are available
  2385. */
  2386. if (TcicIsPnP(pInst)) {
  2387. USHORT adptcfg;
  2388. long old_addr;
  2389. old_addr = TcicReadAddrReg(&pInst->skt);
  2390. TcicWriteAddrReg(&pInst->skt, ADDR_INDREG | IR_ADPTCFG0);
  2391. adptcfg = TcicReadBaseReg(&pInst->skt, R_DATA);
  2392. TcicWriteAddrReg(&pInst->skt, old_addr);
  2393. if (adptcfg & IRADPCF0_IRQ6) {
  2394. ptbl[6] = 6;
  2395. }
  2396. if (adptcfg & IRADPCF0_IRQ9) {
  2397. ptbl[9] = 9;
  2398. }
  2399. if (adptcfg & IRADPCF0_IRQ12) {
  2400. ptbl[12] = 12;
  2401. }
  2402. if (adptcfg & IRADPCF0_IRQ15) {
  2403. ptbl[15] = 15;
  2404. }
  2405. }
  2406. }
  2407. CHIPPROPS *
  2408. TcicGetChipProperties(
  2409. IN PDBSOCKET pInst
  2410. )
  2411. /*++
  2412. Routine Description:
  2413. Search the ChipProperties table for the matching entry
  2414. Arguments:
  2415. pInst - pointer to an Instance data to work from.
  2416. Return Value:
  2417. ptr to chip properties table entry.
  2418. --*/
  2419. {
  2420. int j;
  2421. for (j = 0; ChipProperties[j].chip_id != 0 ;j++) {
  2422. if (ChipProperties[j].chip_id == pInst->chipType) {
  2423. return &ChipProperties[j];
  2424. }
  2425. }
  2426. return (CHIPPROPS *)NULL;
  2427. }
  2428. BOOLEAN
  2429. TcicChipIDKnown(
  2430. IN PDBSOCKET pInst
  2431. )
  2432. /*++
  2433. Routine Description:
  2434. Determine if the chip id makes sense
  2435. Arguments:
  2436. pInst - pointer to an Instance data to work from.
  2437. Return Value:
  2438. TRUE if chip ID is sane.
  2439. --*/
  2440. {
  2441. return (TcicGetChipProperties(pInst) != NULL);
  2442. }
  2443. USHORT
  2444. TcicGetnIOWins(
  2445. IN PDBSOCKET pInst
  2446. )
  2447. /*++
  2448. Routine Description:
  2449. Get the I/O window count based on chip properties, or zero
  2450. if the chip is unidentified
  2451. Arguments:
  2452. pInst - pointer to an Instance data to work from.
  2453. Return Value:
  2454. number of io windows present.
  2455. --*/
  2456. {
  2457. CHIPPROPS *pcp = TcicGetChipProperties(pInst);
  2458. PAGED_CODE();
  2459. return (pcp ?pcp->niowins :0);
  2460. }
  2461. USHORT
  2462. TcicGetnMemWins(
  2463. IN PDBSOCKET pInst
  2464. )
  2465. /*++
  2466. Routine Description:
  2467. Get the memory window count based on chip properties, or zero
  2468. if the chip is unidentified
  2469. Arguments:
  2470. pInst - pointer to an Instance data to work from.
  2471. Return Value:
  2472. number of memory windows present.
  2473. --*/
  2474. {
  2475. CHIPPROPS *pcp = TcicGetChipProperties(pInst);
  2476. PAGED_CODE();
  2477. return (pcp ?pcp->nmemwins :0);
  2478. }
  2479. USHORT
  2480. TcicGetFlags(
  2481. IN PDBSOCKET pInst
  2482. )
  2483. /*++
  2484. Routine Description:
  2485. Get the properties flag bits for this model of TCIC
  2486. Arguments:
  2487. pInst - pointer to an Instance data to work from.
  2488. Return Value:
  2489. flag bits from chip properties table.
  2490. --*/
  2491. {
  2492. CHIPPROPS *pcp = TcicGetChipProperties (pInst);
  2493. PAGED_CODE();
  2494. return (pcp ? pcp->fprops : fINVALID);
  2495. }
  2496. BOOLEAN
  2497. TcicIsPnP(
  2498. IN PDBSOCKET pInst
  2499. )
  2500. /*++
  2501. Routine Description:
  2502. Determine if this chip is a Plug-n-Play chip
  2503. Arguments:
  2504. pInst - pointer to an Instance data to work from.
  2505. Return Value:
  2506. True if chip is PnP (084/184)
  2507. --*/
  2508. {
  2509. CHIPPROPS *pcp = TcicGetChipProperties(pInst);
  2510. return (pcp ?pcp->fprops & fIS_PNP :FALSE);
  2511. }
  2512. BOOLEAN
  2513. TcicHasSktIRQPin(
  2514. IN PDBSOCKET pInst
  2515. )
  2516. /*++
  2517. Routine Description:
  2518. Determine if this chip has a SKT IRQ pin.
  2519. Arguments:
  2520. pInst - pointer to an Instance data to work from.
  2521. Return Value:
  2522. TRUE if chip has the SktIRQ pin.
  2523. --*/
  2524. {
  2525. CHIPPROPS *pcp = TcicGetChipProperties(pInst);
  2526. PAGED_CODE();
  2527. return (pcp ?pcp->fprops & fSKTIRQPIN :FALSE);
  2528. }
  2529. USHORT
  2530. TcicGet5vVccVal(
  2531. IN PDBSOCKET pInst
  2532. )
  2533. /*++
  2534. Routine Description:
  2535. Get the correct R_PWR bits to establish 5V.
  2536. Arguments:
  2537. pInst - pointer to an Instance data to work from.
  2538. Return Value:
  2539. 5v Vcc R_PWR bits.
  2540. --*/
  2541. {
  2542. USHORT j;
  2543. USHORT pwr;
  2544. CHIPPROPS *pcp = TcicGetChipProperties(pInst);
  2545. PAGED_CODE();
  2546. //
  2547. // Get Table size
  2548. //
  2549. if (pcp == NULL) {
  2550. return 0;
  2551. }
  2552. j = pcp->privpwrtbl[0];
  2553. pwr = pcp->privpwrtbl[j + 1];
  2554. //
  2555. // If not from the 084 family, adjust power value for socket number.
  2556. //
  2557. if (!TcicIsPnP(pInst)) {
  2558. pwr <<= pInst->skt.RegisterOffset;
  2559. }
  2560. return pwr;
  2561. }
  2562. VOID
  2563. TcicGetIRQMap(
  2564. IN PDBSOCKET pInst
  2565. )
  2566. /*++
  2567. Routine Description:
  2568. Constructs an IRQ cross-mapping table for the controller in question.
  2569. This code just does a copy from a static table. It should be replaced
  2570. with the Win95 heuristic code.
  2571. Arguments:
  2572. pInst - pointer to an Instance data to work from.
  2573. Return Value:
  2574. None
  2575. --*/
  2576. {
  2577. int i, j;
  2578. UCHAR loc_tbl[16] = {0};
  2579. PAGED_CODE();
  2580. TcicGetPossibleIRQs(pInst, loc_tbl);
  2581. for (j = 0; j < 16; j++) {
  2582. pInst->IRQMapTbl[j] = loc_tbl[j];
  2583. }
  2584. //
  2585. // Don't let IRQ 14 through.. This is also done for the PCIC
  2586. //
  2587. pInst->IRQMapTbl[14] = 0;
  2588. }
  2589. USHORT
  2590. TcicClockRate(
  2591. PSOCKET pInst
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. This routine determines if CCLK is running at 1:1 (14.318 Mhz) or divided
  2596. by 2.
  2597. Arguments:
  2598. pInst - pointer to an Instance data to work from.
  2599. Return Value:
  2600. CCLK divisor as a shift count (0 or 1)
  2601. --*/
  2602. {
  2603. int i;
  2604. LARGE_INTEGER accum = RtlConvertLongToLargeInteger(0L);
  2605. LARGE_INTEGER start, stop, pc, tmp, tmp2;
  2606. USHORT mode;
  2607. USHORT wctl;
  2608. PAGED_CODE();
  2609. //
  2610. // The Ratio break point is the midpoint between 16K ticks at 14.31813 Mhz
  2611. // (14,318130 / 16K = 873 | 1:1 CCLK) and 16K ticks at 7.159065 Mhz
  2612. // (7,159,065 / 16K = 436 | 1:2 CCLK). We calculate the midpoint between
  2613. // these two values: ((873 - 436) / 2) + 436 = 654 to give a comparison
  2614. // value. If x < 654 we assume 1/2 CCLK, otherwise we assume 1/1 CCLK.
  2615. //
  2616. #define CLKRATIO_BRKPOINT 654L
  2617. mode = TcicReadBaseReg(pInst, R_MODE);
  2618. //
  2619. // set AR_PCTL to 0x4000
  2620. //
  2621. TcicWriteAuxReg(pInst, MODE_AR_PCTL, 0x4000);
  2622. TcicWriteBaseReg(pInst, R_MODE, MODE_AR_WCTL);
  2623. wctl = TcicReadBaseReg(pInst, R_AUX);
  2624. //
  2625. // Get the performance counter time base
  2626. //
  2627. KeQueryPerformanceCounter(&pc);
  2628. for (i = 0; i < 10; i++) {
  2629. //
  2630. // start the TCIC timer */
  2631. //
  2632. TcicWriteBaseReg(pInst, R_AUX, (USHORT)(wctl & 0xff));
  2633. start = KeQueryPerformanceCounter(NULL);
  2634. //
  2635. // wait for SSTAT_PROGTIME to go high */
  2636. //
  2637. while (!(TcicReadBaseReg(pInst, R_SSTAT) & SSTAT_PROGTIME))
  2638. ;
  2639. //
  2640. // nab the timer count
  2641. //
  2642. stop = KeQueryPerformanceCounter(NULL);
  2643. tmp = RtlLargeIntegerSubtract(stop, start);
  2644. accum = RtlLargeIntegerAdd(accum, tmp);
  2645. }
  2646. //
  2647. // Zero out the timer for power conservation
  2648. //
  2649. TcicWriteAuxReg(pInst, MODE_AR_PCTL, 0);
  2650. //
  2651. // replace Mode
  2652. //
  2653. TcicWriteBaseReg(pInst, R_MODE, mode);
  2654. //
  2655. // Get average elapsed time for 1 iter.
  2656. //
  2657. accum = RtlLargeIntegerDivide(accum, RtlConvertLongToLargeInteger(10L), &tmp2);
  2658. //
  2659. // Divide PC Freq by accum to base accum on some portion of 1 second
  2660. //
  2661. tmp = RtlLargeIntegerDivide(pc, accum, &tmp2);
  2662. return (RtlLargeIntegerLessThan(tmp, RtlConvertLongToLargeInteger(CLKRATIO_BRKPOINT))
  2663. ?(USHORT)2 : (USHORT)1);
  2664. }
  2665. VOID
  2666. TcicSetIoWin(
  2667. IN PSOCKET socketPtr,
  2668. IN USHORT winIdx,
  2669. IN ULONG BasePort,
  2670. IN ULONG NumPorts,
  2671. IN UCHAR Attributes
  2672. )
  2673. /*++
  2674. Routine Description:
  2675. Setup a TCIC I/O window.
  2676. Arguments:
  2677. socketPtr - ptr to socket instance data
  2678. winIdx - index of window to setup
  2679. BasePort - start base port address
  2680. NumPorts - size of range - 1
  2681. Attributes- window attributes
  2682. Return Value:
  2683. None
  2684. --*/
  2685. {
  2686. PDBSOCKET pdb = (PDBSOCKET)socketPtr;
  2687. USHORT tmp;
  2688. USHORT words[2];
  2689. //
  2690. // Simulate 365 by arbitrary attachment of IOW1:2 to SKT1 and IOW3:4 to SKT2
  2691. //
  2692. winIdx += (socketPtr->RegisterOffset * 2);
  2693. //
  2694. // NumPorts from CIS metaformat is really (NumPorts -1), normalize it now.
  2695. //
  2696. ++NumPorts;
  2697. words[0] = (USHORT)(BasePort + (NumPorts >> 1));
  2698. TcicReadIndirectRegs(socketPtr, IR_SCFG_S(socketPtr->RegisterOffset), 1, &tmp);
  2699. tmp |= (USHORT)(IRSCFG_SPKR | IRSCFG_FINPACK);
  2700. TcicWriteIndirectRegs(socketPtr, IR_SCFG_S(socketPtr->RegisterOffset), 1, &tmp);
  2701. TcicReadIndirectRegs(socketPtr, IR_SCF2_S(socketPtr->RegisterOffset), 1, &tmp);
  2702. tmp &= ~(IRSCF2_IDBR | IRSCF2_MDBR);
  2703. if (Attributes & IO_DATA_PATH_WIDTH) {
  2704. words[1] = ICTL_ENA;
  2705. tmp |= IRSCF2_IDBR;
  2706. } else {
  2707. words[1] = ICTL_B8 | ICTL_QUIET | ICTL_ENA;
  2708. }
  2709. TcicWriteIndirectRegs(socketPtr, IR_SCF2_S(socketPtr->RegisterOffset), 1, &tmp);
  2710. if (NumPorts < 1024) {
  2711. words[1] |= ICTL_1K;
  2712. if (NumPorts == 1) {
  2713. words[1] |= ICTL_TINY;
  2714. }
  2715. }
  2716. words[1] |= socketPtr->RegisterOffset << ICTL_SS_SHFT;
  2717. words[1] |= 3 + pdb->clkdiv;
  2718. TcicWriteIndirectRegs(socketPtr, IR_IOBASE_W(winIdx), 2, words);
  2719. }
  2720. USHORT
  2721. TcicMapSpeedCode(
  2722. IN PDBSOCKET pdb,
  2723. IN UCHAR AccessSpeed
  2724. )
  2725. /*++
  2726. Routine Description:
  2727. Determine the correct wait state bits for this controller
  2728. Arguments:
  2729. pdb - socket instance data
  2730. AccessSpeed - callers desired speed (unused)
  2731. Return Value:
  2732. TCIC wait state bits.
  2733. --*/
  2734. {
  2735. UNREFERENCED_PARAMETER(AccessSpeed);
  2736. if (pdb->clkdiv) {
  2737. return (3);
  2738. } else {
  2739. return (7);
  2740. }
  2741. }
  2742. VOID
  2743. TcicSetMemWin(
  2744. IN PSOCKET socketPtr,
  2745. IN USHORT winIdx,
  2746. IN ULONG cardbase,
  2747. IN ULONG hostbase,
  2748. IN ULONG size,
  2749. IN UCHAR AttrMem,
  2750. IN UCHAR AccessSpeed,
  2751. IN USHORT Attributes
  2752. )
  2753. /*++
  2754. Routine Description:
  2755. Setup the specified TCIC memory window
  2756. Arguments:
  2757. socketPtr - socket instance data
  2758. winIdx - index of window to setup
  2759. cardbase - PCCard base address
  2760. hostbase - host base address
  2761. size - window size
  2762. AttrMem - attribute or common space
  2763. AccessSpeed - wait states
  2764. Attributes - window attributes
  2765. Return Value:
  2766. None
  2767. --*/
  2768. {
  2769. PDBSOCKET pdb = (PDBSOCKET)socketPtr;
  2770. USHORT tmp;
  2771. USHORT words[4];
  2772. //
  2773. // Simulate 365 by arbitrary attachment of MEM1:(x/2-1) to SKT1
  2774. // and MEMx/2:x to SKT2
  2775. //
  2776. winIdx += (socketPtr->RegisterOffset * (pdb->nmemwins / 2));
  2777. //
  2778. // convert base, size, & map to 4K pages
  2779. //
  2780. cardbase >>= 12;
  2781. size >>= 12;
  2782. hostbase >>= 12;
  2783. //
  2784. // combine hostbase & size
  2785. //
  2786. words[0] = (USHORT)hostbase | (USHORT)(size / 2);
  2787. //
  2788. // Check if 4K bit is needed
  2789. //
  2790. if (size == 1) {
  2791. words[0] |= MBASE_4K;
  2792. }
  2793. //
  2794. // setup mapping of cardbase to host addr space
  2795. //
  2796. words[1] = (USHORT)(cardbase - (hostbase & 0xfff)) & 0x3fff;
  2797. if (AttrMem) {
  2798. words[1] |= MMAP_REG;
  2799. }
  2800. //
  2801. // now cook the control bits
  2802. //
  2803. words[2] = MCTL_ENA | MCTL_QUIET;
  2804. if (!(Attributes & MEM_DATA_PATH_WIDTH_16)) {
  2805. words[2] |= MCTL_B8;
  2806. }
  2807. //
  2808. // Now add in the socket selector
  2809. //
  2810. words[2] |= (socketPtr->RegisterOffset << MCTL_SS_SHFT);
  2811. //
  2812. // Last, add in the speed bits
  2813. //
  2814. words[2] |= TcicMapSpeedCode(pdb, AccessSpeed);
  2815. //
  2816. // HW BugFix1: First Rev of 082 needs to have SYSCFG_MCSFULL turned on
  2817. // if we have any open windows. We're opening one so we better assert.
  2818. //
  2819. tmp = TcicReadAuxReg(socketPtr, MODE_AR_SYSCFG);
  2820. tmp |= SYSCFG_MCSFULL;
  2821. TcicWriteAuxReg(socketPtr, MODE_AR_SYSCFG, tmp);
  2822. //
  2823. // HW BugFix2: '2' Step of 082 needs the wait state count written into
  2824. // window[~index] instead of index.
  2825. //
  2826. if (pdb->chipType != SILID_DB86082_1) {
  2827. //
  2828. // No bug case
  2829. //
  2830. TcicWriteIndirectRegs(socketPtr, IR_MBASE_W(winIdx), 3, words);
  2831. } else {
  2832. //
  2833. // Bug case
  2834. //
  2835. words[3] = words[2] & MCTL_WSCNT_MASK;
  2836. words[2] &= ~MCTL_WSCNT_MASK;
  2837. TcicWriteIndirectRegs(socketPtr, IR_MBASE_W(winIdx), 3, words);
  2838. TcicWriteIndirectRegs(socketPtr, IR_MBASE_W((~winIdx) & 7), 1, &words[3]);
  2839. }
  2840. }
  2841. VOID
  2842. TcicAutoBusyOff(
  2843. IN PDBSOCKET pdbs
  2844. )
  2845. /*++
  2846. Routine Description:
  2847. Turn off the busy LED, re-arm so that it comes on automatically with
  2848. any card access.
  2849. Arguments:
  2850. pdbs - socket instance data
  2851. Return Value:
  2852. None
  2853. --*/
  2854. {
  2855. USHORT syscfg;
  2856. USHORT oldmode;
  2857. //
  2858. // Save R_MODE for later restore
  2859. //
  2860. oldmode = TcicReadBaseReg(&pdbs->skt, R_MODE);
  2861. //
  2862. // R/M/W SYSCFG to add in the autobusy bit.
  2863. // This will turn LED off for now but allow it to come on automatically
  2864. // with the next access to this socket.
  2865. //
  2866. syscfg = TcicReadAuxReg(&pdbs->skt, MODE_AR_SYSCFG);
  2867. syscfg |= SYSCFG_AUTOBUSY;
  2868. TcicWriteAuxReg(&pdbs->skt, MODE_AR_SYSCFG, syscfg);
  2869. //
  2870. // Restore Mode
  2871. //
  2872. TcicWriteBaseReg(&pdbs->skt, R_MODE, oldmode);
  2873. }
  2874. UCHAR
  2875. TcicAutoBusyCheck(
  2876. IN PDBSOCKET pdbs
  2877. )
  2878. /*++
  2879. Routine Description:
  2880. Check SYSCFG access bit to see if PCCard has been accessed since last
  2881. call. If so, force LED to stay on and clear access bit.
  2882. Arguments:
  2883. pdbs - socket instance data
  2884. Return Value:
  2885. access bit as a right-justified UCHAR
  2886. --*/
  2887. {
  2888. USHORT syscfg;
  2889. USHORT oldmode;
  2890. UCHAR activity = 0;
  2891. //
  2892. // Save R_MODE for later restore
  2893. //
  2894. oldmode = TcicReadBaseReg(&pdbs->skt, R_MODE);
  2895. //
  2896. // Read AR_SYSCFG to check for recent activity
  2897. //
  2898. syscfg = TcicReadAuxReg(&pdbs->skt, MODE_AR_SYSCFG);
  2899. if (syscfg & SYSCFG_ACC) {
  2900. //
  2901. // the socket has been accessed since last check
  2902. // clear the access bit and disable AUTOBUSY to force LED to
  2903. // follow socket SCTRL_ENA.
  2904. //
  2905. syscfg &= ~(SYSCFG_ACC | SYSCFG_AUTOBUSY);
  2906. TcicWriteAuxReg(&pdbs->skt, MODE_AR_SYSCFG, syscfg);
  2907. ++activity;
  2908. }
  2909. //
  2910. // Restore Mode
  2911. //
  2912. TcicWriteBaseReg(&pdbs->skt, R_MODE, oldmode);
  2913. return activity;
  2914. }
  2915. VOID
  2916. TcicCheckSktLED(
  2917. IN PDBSOCKET pdbs
  2918. )
  2919. /*++
  2920. Routine Description:
  2921. Drive the low-level functions to check for PCcard access and control
  2922. the busy LED on this socket/controller.
  2923. Arguments:
  2924. pdbs - socket instance data
  2925. Return Value:
  2926. None
  2927. --*/
  2928. {
  2929. UCHAR lastbusy = pdbs->busyLed;
  2930. pdbs->busyLed = TcicAutoBusyCheck(pdbs);
  2931. if (lastbusy & !(pdbs->busyLed)) {
  2932. TcicAutoBusyOff(pdbs);
  2933. }
  2934. }
  2935. VOID
  2936. TcicBusyLedRoutine(
  2937. IN PDEVICE_OBJECT DeviceObject,
  2938. IN PVOID Context
  2939. )
  2940. /*++
  2941. Routine Description:
  2942. Main timer routine to drive Busy LED monitor
  2943. Arguments:
  2944. DeviceObject - instance data for driver
  2945. Context - unused parameter
  2946. Return Value:
  2947. None
  2948. --*/
  2949. {
  2950. PFDO_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2951. PDBSOCKET pdbs;
  2952. UNREFERENCED_PARAMETER(Context);
  2953. pdbs = (PDBSOCKET)(deviceExtension->SocketList);
  2954. while (pdbs) {
  2955. //
  2956. // If this device is from the 084 family, LED control is per/socket
  2957. //
  2958. if (TcicIsPnP(pdbs)) {
  2959. ULONG oldaddr = TcicReadAddrReg(&pdbs->skt);
  2960. // Do the first socket
  2961. //
  2962. TcicSocketSelect(&pdbs->skt, pdbs->skt.RegisterOffset);
  2963. TcicCheckSktLED(pdbs);
  2964. TcicWriteAddrReg(&pdbs->skt, oldaddr);
  2965. pdbs = (PDBSOCKET)(pdbs->skt.NextSocket);
  2966. // If a second socket is present, do it too.
  2967. //
  2968. if (pdbs && pdbs->skt.RegisterOffset == 1) {
  2969. oldaddr = TcicReadAddrReg(&pdbs->skt);
  2970. TcicSocketSelect(&pdbs->skt, pdbs->skt.RegisterOffset);
  2971. TcicCheckSktLED(pdbs);
  2972. TcicWriteAddrReg(&pdbs->skt, oldaddr);
  2973. pdbs = (PDBSOCKET)(pdbs->skt.NextSocket);
  2974. }
  2975. } else {
  2976. //
  2977. // Otherwise, LED control is per adapter so do the check and skip
  2978. // over the second socket if present.
  2979. //
  2980. TcicCheckSktLED(pdbs);
  2981. pdbs = (PDBSOCKET)(pdbs->skt.NextSocket);
  2982. if (pdbs && pdbs->skt.RegisterOffset == 1) {
  2983. pdbs = (PDBSOCKET)(pdbs->skt.NextSocket);
  2984. }
  2985. }
  2986. }
  2987. }
  2988. VOID
  2989. TcicDecodeMemWin(
  2990. USHORT mbase,
  2991. USHORT mmap,
  2992. USHORT mctl,
  2993. ULONG *Host,
  2994. ULONG *Card,
  2995. ULONG *Size,
  2996. UCHAR *Attr
  2997. )
  2998. /*++
  2999. Routine Description:
  3000. Convert TCIC mem window register values to something understandable
  3001. Arguments:
  3002. mbase - TCIC MBASE register value
  3003. mmap - TCIC MMAP register value
  3004. mctl - TCIC MCTL register value
  3005. Host - where to put Host address
  3006. Card - where to put PCCard address
  3007. Size - where to put window size
  3008. Attr - where to put attribute space flag
  3009. Return Value:
  3010. None
  3011. --*/
  3012. {
  3013. USHORT shft;
  3014. USHORT tmp;
  3015. //
  3016. // take care of mapping to common or attr space first.
  3017. // Strip ATTR bit if set
  3018. //
  3019. *Attr = 0;
  3020. if (mmap & MMAP_REG) {
  3021. *Attr = 1;
  3022. mmap &= ~MMAP_REG;
  3023. }
  3024. //
  3025. // Now concentrate on getting the host addr and window size
  3026. //
  3027. if (mbase & MBASE_4K) {
  3028. *Size = 1;
  3029. *Host = (ULONG)(mbase & ~MBASE_4K);
  3030. } else {
  3031. for (*Size = 2, shft = 0, tmp = mbase; !(tmp & 1) ; shft++ ) {
  3032. tmp >>= 1;
  3033. *Size <<= 1;
  3034. }
  3035. *Host = (ULONG)(mbase - (1 << shft));
  3036. }
  3037. //
  3038. // Now for the fun part. We're left with mmap being a 14-bit signed
  3039. // number. We need to normalize it so we can work with it.
  3040. //
  3041. // Check for negative (bit 13 set)
  3042. //
  3043. if (mmap & (1 << 13)) {
  3044. mmap |= 0xc000;
  3045. *Card = (ULONG)((short)mmap + (short)*Host);
  3046. } else {
  3047. *Card = (ULONG)(mmap) + *Host;
  3048. }
  3049. (*Size)--;
  3050. *Host <<= MBASE_HA_SHFT;
  3051. *Size <<= MBASE_HA_SHFT;
  3052. *Card <<= MMAP_CA_SHFT;
  3053. }
  3054. VOID
  3055. TcicDecodeIoWin(
  3056. USHORT iobase,
  3057. USHORT ioctl,
  3058. USHORT *NumPorts,
  3059. USHORT *BasePort
  3060. )
  3061. /*++
  3062. Routine Description:
  3063. Convert TCIC I/O window register values to something understandable
  3064. Arguments:
  3065. iobase - TCIC IOBASE register contents
  3066. ioctl - TCIC IOCTL register contents
  3067. NumPorts - where to put window size (size - 1)
  3068. BasePort - where to put base address
  3069. Return Value:
  3070. None
  3071. --*/
  3072. {
  3073. if (ioctl & ICTL_TINY) {
  3074. *BasePort = iobase;
  3075. *NumPorts = 1;
  3076. } else {
  3077. USHORT shft;
  3078. USHORT tmp;
  3079. for (*NumPorts = 2, shft = 0, tmp = iobase; !(tmp & 1) ; shft++ ) {
  3080. tmp >>= 1;
  3081. *NumPorts <<= 1;
  3082. }
  3083. *BasePort = (iobase - (1 << shft));
  3084. }
  3085. *NumPorts -= 1;
  3086. }
  3087. VOID
  3088. TcicRegistryLookupScanLimits(
  3089. PULONG Start,
  3090. PULONG End
  3091. )
  3092. /*++
  3093. Routine Description:
  3094. Open the registry key in the services entry for pcmcia and see if there
  3095. are some values set for TCIC searching. If not, use the defaults.
  3096. Arguments:
  3097. Start - the I/O location for start of search.
  3098. End - the I/O location to end the search (i.e. nothing greater than).
  3099. Return Values:
  3100. None - parameters are modified.
  3101. --*/
  3102. {
  3103. #define ITEMS_TO_QUERY 4
  3104. ULONG defaultStart = TCIC_LOW_ADDR_LIMIT;
  3105. ULONG defaultEnd = TCIC_HIGH_ADDR_LIMIT;
  3106. PRTL_QUERY_REGISTRY_TABLE params;
  3107. NTSTATUS status;
  3108. PWSTR keyName;
  3109. PAGED_CODE();
  3110. //
  3111. // Set up return codes in case there are errors in setting up processing.
  3112. //
  3113. *Start = defaultStart;
  3114. *End = defaultEnd;
  3115. //
  3116. // Allocate memory for operation.
  3117. //
  3118. params = ExAllocatePool(NonPagedPool,
  3119. sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
  3120. if (!params) {
  3121. return;
  3122. }
  3123. //
  3124. // Set up registry path. This should not be hard coded, but is for now.
  3125. //
  3126. keyName = L"\\registry\\machine\\system\\currentcontrolset\\services\\pcmcia";
  3127. //
  3128. // Set up query structure.
  3129. //
  3130. RtlZeroMemory(params, sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
  3131. params[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  3132. params[0].Name = L"TCICStartSearch";
  3133. params[0].EntryContext = Start;
  3134. params[0].DefaultType = REG_DWORD;
  3135. params[0].DefaultData = &defaultStart;
  3136. params[0].DefaultLength = sizeof(ULONG);
  3137. params[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  3138. params[1].Name = L"TCICStopSearch";
  3139. params[1].EntryContext = End;
  3140. params[1].DefaultType = REG_DWORD;
  3141. params[1].DefaultData = &defaultEnd;
  3142. params[1].DefaultLength = sizeof(ULONG);
  3143. //
  3144. // Perform the registry search
  3145. //
  3146. status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  3147. keyName,
  3148. params,
  3149. NULL,
  3150. NULL);
  3151. //
  3152. // Insure that start is less than end - if not, go back to default
  3153. // values
  3154. //
  3155. if (*Start > *End) {
  3156. *Start = defaultStart;
  3157. *End = defaultEnd;
  3158. }
  3159. //
  3160. // Free resources.
  3161. //
  3162. ExFreePool(params);
  3163. }