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.

2857 lines
73 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. pcicsup.c
  5. Abstract:
  6. This module supplies functions that control the 82365SL chip. In turn,
  7. these functions are abstracted out to the main PCMCIA support module.
  8. Author(s):
  9. Bob Rinne (BobRi) 3-Aug-1994
  10. Jeff McLeman (mcleman@zso.dec.com)
  11. Neil Sandlin (neilsa) June 1 1999
  12. Revisions:
  13. 6-Apr-95
  14. Modified for databook support changes - John Keys Databook
  15. 1-Nov-96
  16. Complete overhaul for plug'n'play support,
  17. flash interfaces, power support etc.
  18. - Ravisankar Pudipeddi (ravisp)
  19. --*/
  20. #include "pch.h"
  21. #ifdef POOL_TAGGING
  22. #undef ExAllocatePool
  23. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'cicP')
  24. #endif
  25. //
  26. // Internal References
  27. //
  28. NTSTATUS
  29. PcicResetCard(
  30. IN PSOCKET Socket,
  31. OUT PULONG pDelayTime
  32. );
  33. BOOLEAN
  34. PcicInitializePcmciaSocket(
  35. IN PSOCKET Socket
  36. );
  37. UCHAR
  38. PcicReadController(
  39. IN PUCHAR Base,
  40. IN USHORT Socket,
  41. IN UCHAR PcicRegister
  42. );
  43. VOID
  44. PcicWriteController(
  45. IN PUCHAR Base,
  46. IN USHORT Socket,
  47. IN UCHAR PcicRegister,
  48. IN UCHAR DataByte
  49. );
  50. NTSTATUS
  51. PcicDetect(
  52. IN PFDO_EXTENSION DeviceExtension,
  53. IN INTERFACE_TYPE InterfaceType,
  54. IN ULONG IoPortBase
  55. );
  56. BOOLEAN
  57. PcicDetectCardInSocket(
  58. IN PSOCKET Socket
  59. );
  60. BOOLEAN
  61. PcicDetectCardChanged(
  62. IN PSOCKET Socket
  63. );
  64. BOOLEAN
  65. PcicPCCardReady(
  66. IN PSOCKET Socket
  67. );
  68. BOOLEAN
  69. PcicDetectReadyChanged(
  70. IN PSOCKET Socket
  71. );
  72. BOOLEAN
  73. PcicProcessConfigureRequest(
  74. IN PSOCKET Socket,
  75. IN PCARD_REQUEST ConfigRequest,
  76. IN PUCHAR Base
  77. );
  78. VOID
  79. PcicEnableDisableWakeupEvent(
  80. IN PSOCKET Socket,
  81. IN PPDO_EXTENSION PdoExtension,
  82. IN BOOLEAN Enable
  83. );
  84. VOID
  85. PcicEnableDisableMemory(
  86. IN PSOCKET Socket,
  87. IN MEMORY_SPACE MemorySpace,
  88. IN ULONG CardBase,
  89. IN UCHAR Mem16BitWindow,
  90. IN BOOLEAN Enable
  91. );
  92. BOOLEAN
  93. PcicEnableDisableCardDetectEvent(
  94. IN PSOCKET Socket,
  95. IN BOOLEAN Enable
  96. );
  97. UCHAR
  98. PcicReadExtendedCirrusController(
  99. IN PUCHAR Base,
  100. IN USHORT Socket,
  101. IN UCHAR Register
  102. );
  103. VOID
  104. PcicWriteExtendedCirrusController(
  105. IN PUCHAR Base,
  106. IN USHORT Socket,
  107. IN UCHAR PcicRegister,
  108. IN UCHAR DataByte
  109. );
  110. ULONG
  111. PcicWriteCardMemory(
  112. IN PPDO_EXTENSION PdoExtension,
  113. IN MEMORY_SPACE MemorySpace,
  114. IN ULONG Offset,
  115. IN PUCHAR Buffer,
  116. IN ULONG Length
  117. );
  118. ULONG
  119. PcicReadCardMemory(
  120. IN PPDO_EXTENSION PdoExtension,
  121. IN MEMORY_SPACE MemorySpace,
  122. IN ULONG Offset,
  123. IN PUCHAR Buffer,
  124. IN ULONG Length
  125. );
  126. BOOLEAN
  127. PcicModifyMemoryWindow(
  128. IN PDEVICE_OBJECT Pdo,
  129. IN ULONGLONG HostBase,
  130. IN ULONGLONG CardBase,
  131. IN BOOLEAN Enable,
  132. IN ULONG WindowSize OPTIONAL,
  133. IN UCHAR AccessSpeed OPTIONAL,
  134. IN UCHAR BusWidth OPTIONAL,
  135. IN BOOLEAN IsAttributeMemory OPTIONAL
  136. );
  137. BOOLEAN
  138. PcicSetVpp(
  139. IN PDEVICE_OBJECT Pdo,
  140. IN UCHAR VppLevel
  141. );
  142. BOOLEAN
  143. PcicIsWriteProtected(
  144. IN PDEVICE_OBJECT Pdo
  145. );
  146. ULONG
  147. PcicGetIrqMask(
  148. IN PFDO_EXTENSION deviceExtension
  149. );
  150. NTSTATUS
  151. PcicConvertSpeedToWait(
  152. IN UCHAR Speed,
  153. OUT PUCHAR WaitIndex
  154. );
  155. //
  156. // Internal Data
  157. //
  158. ULONG PcicStallCounter = 4000; //4ms
  159. UCHAR WaitToSpeedTable[4] = {
  160. 0x42, //350ns
  161. 0x52, //450ns
  162. 0x62, //600ns
  163. 0x72 //700ns
  164. };
  165. UCHAR DevSpeedTable[8] = {
  166. 0xff, // speed 0: invalid
  167. 0x32, // speed 1: 250ns
  168. 0x2a, // speed 2: 200ns
  169. 0x22, // speed 3: 150ns
  170. 0x0a, // speed 4: 100ns
  171. 0xff, // speed 5: reserved
  172. 0xff, // speed 6: reserved
  173. 0xff // speed 7: invalid
  174. };
  175. PCMCIA_CTRL_BLOCK PcicSupportFns = {
  176. PcicInitializePcmciaSocket,
  177. PcicResetCard,
  178. PcicDetectCardInSocket,
  179. PcicDetectCardChanged,
  180. NULL, // PcicDetectCardStatus
  181. PcicDetectReadyChanged,
  182. NULL, // GetPowerRequirements
  183. PcicProcessConfigureRequest,
  184. PcicEnableDisableCardDetectEvent,
  185. PcicEnableDisableWakeupEvent,
  186. PcicGetIrqMask,
  187. PcicReadCardMemory,
  188. PcicWriteCardMemory,
  189. PcicModifyMemoryWindow,
  190. PcicSetVpp,
  191. PcicIsWriteProtected
  192. };
  193. #define MEM_16BIT 1
  194. #define MEM_8BIT 0
  195. #ifdef ALLOC_PRAGMA
  196. #pragma alloc_text(INIT,PcicIsaDetect)
  197. #pragma alloc_text(INIT,PcicDetect)
  198. #pragma alloc_text(PAGE,PcicBuildSocketList)
  199. #endif
  200. ULONG
  201. PcicGetIrqMask(
  202. IN PFDO_EXTENSION DeviceExtension
  203. )
  204. /*++
  205. Routine Description:
  206. Arguments:
  207. Return value:
  208. --*/
  209. {
  210. //
  211. // Return the set of supported IRQs for the controller
  212. // and PcCards
  213. //
  214. if (CLPD6729(DeviceExtension->SocketList)) {
  215. return CL_SUPPORTED_INTERRUPTS;
  216. } else {
  217. return PCIC_SUPPORTED_INTERRUPTS;
  218. }
  219. }
  220. BOOLEAN
  221. PcicEnableDisableCardDetectEvent(
  222. IN PSOCKET Socket,
  223. IN BOOLEAN Enable
  224. )
  225. /*++
  226. Routine Description:
  227. Enable card detect interrupt.
  228. Arguments:
  229. Socket - socket information
  230. Irq - the interrupt value to set.
  231. Enable - if TRUE, CSC interrupt is enabled,
  232. if FALSE, it is disabled
  233. Return Value:
  234. None
  235. --*/
  236. {
  237. PFDO_EXTENSION deviceExtension = Socket->DeviceExtension;
  238. INTERFACE_TYPE interface;
  239. UCHAR byte;
  240. ULONG Irq = Socket->FdoIrq;
  241. switch (Enable) {
  242. case TRUE: {
  243. if (CLPD6729(Socket)) {
  244. //
  245. // For Cirrus Logic PCI controller we need to know the interrupt pin
  246. // (INTA, INTB etc.) corresponding to the level passed in. Hence the
  247. // passed in Irq is discarded. Actually the Irq parameter is redundant
  248. // since it can be fetched from the device extension itself.
  249. // If we remove the Irq param from this routine, the following is
  250. // not so inelegant..
  251. //
  252. interface = PCIBus;
  253. switch (deviceExtension->Configuration.InterruptPin) {
  254. case 0: {
  255. //
  256. // This is what tells us that ISA interrupts are being used...
  257. //
  258. interface = Isa;
  259. break;
  260. }
  261. case 1: {
  262. Irq = PCIC_CIRRUS_INTA;
  263. break;
  264. }
  265. case 2: {
  266. Irq = PCIC_CIRRUS_INTB;
  267. break;
  268. }
  269. case 3: {
  270. Irq = PCIC_CIRRUS_INTC;
  271. break;
  272. }
  273. case 4: {
  274. Irq = PCIC_CIRRUS_INTD;
  275. break;
  276. }
  277. }
  278. //
  279. // Set the Cirrus Logic controller for PCI style interrupts
  280. //
  281. byte = PcicReadExtendedCirrusController(Socket->AddressPort,
  282. Socket->RegisterOffset,
  283. PCIC_CIRRUS_EXTENSION_CTRL_1);
  284. if (interface == PCIBus) {
  285. byte |= 0x10; // PCI style interrupt
  286. } else {
  287. byte &= ~0x10; // Isa style interrupt
  288. }
  289. PcicWriteExtendedCirrusController(Socket->AddressPort,
  290. Socket->RegisterOffset,
  291. PCIC_CIRRUS_EXTENSION_CTRL_1,
  292. byte);
  293. PcmciaWait(100);
  294. }
  295. byte=PcicReadSocket(Socket, PCIC_CARD_INT_CONFIG);
  296. byte = byte & CSCFG_BATT_MASK; // Don't nuke any other enables
  297. byte = byte | (UCHAR) ((Irq << 4) & 0x00ff); // Put IRQ in upper nibble
  298. byte |= CSCFG_CD_ENABLE;
  299. PcicWriteSocket(Socket, PCIC_CARD_INT_CONFIG, byte);
  300. break;
  301. }
  302. case FALSE: {
  303. //
  304. // Clear pending interrupt (for now)
  305. //
  306. byte = PcicReadSocket(Socket, PCIC_CARD_CHANGE);
  307. DebugPrint((PCMCIA_DEBUG_INFO, "PcicDisableInterrupt:Status Change %x\n", byte));
  308. PcicWriteSocket(Socket,
  309. PCIC_CARD_INT_CONFIG,
  310. 0x0);
  311. break;
  312. }
  313. }
  314. return TRUE;
  315. }
  316. NTSTATUS
  317. PcicSetPower(
  318. IN PSOCKET Socket,
  319. IN BOOLEAN Enable,
  320. OUT PULONG pDelayTime
  321. )
  322. /*++
  323. Routine Description:
  324. Set power to the specified socket.
  325. Arguments:
  326. Socket - the socket to set
  327. Enable - TRUE means to set power - FALSE is to turn it off.
  328. pDelayTime - specifies delay (msec) to occur after the current phase
  329. Return Value:
  330. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  331. other status values terminate sequence
  332. --*/
  333. {
  334. NTSTATUS status;
  335. UCHAR tmp, vcc;
  336. //
  337. // Turn on the power - then turn on output - this is two operations
  338. // per the Intel 82365SL documentation.
  339. //
  340. if (Enable) {
  341. switch(Socket->PowerPhase) {
  342. case 1:
  343. tmp = PcicReadSocket(Socket, PCIC_PWR_RST);
  344. //
  345. // 5V for R2 cards..
  346. //
  347. vcc = PC_CARDPWR_ENABLE;
  348. if (Elc(Socket)) {
  349. tmp = PC_VPP_SETTO_VCC | vcc; // vpp1 = vcc
  350. } else {
  351. //
  352. // Apparently we need to set bit 2 also for some obscure reason
  353. //
  354. tmp = 0x4 | PC_VPP_SETTO_VCC | vcc; // vpp1 = vpp2 = vcc
  355. }
  356. PcicWriteSocket(Socket, PCIC_PWR_RST, tmp);
  357. //
  358. // OUTPUT_ENABLE & AUTOPWR_ENABLE..
  359. // Disable RESETDRV also..
  360. //
  361. tmp |= PC_OUTPUT_ENABLE | PC_AUTOPWR_ENABLE | PC_RESETDRV_DISABLE;
  362. PcicWriteSocket(Socket, PCIC_PWR_RST, tmp);
  363. //
  364. // When power is enabled always stall to give the PCCARD
  365. // a chance to react.
  366. //
  367. *pDelayTime = PcicStallPower;
  368. status = STATUS_MORE_PROCESSING_REQUIRED;
  369. break;
  370. case 2:
  371. //
  372. // Check for an as yet unexplained condition on Dell Latitude XPi's
  373. //
  374. tmp = PcicReadSocket(Socket, PCIC_STATUS);
  375. if (!(tmp & 0x40)) {
  376. //
  377. // power hasn't come on, flip the mystery bit
  378. //
  379. tmp = PcicReadSocket(Socket, 0x2f);
  380. if (tmp == 0x42) {
  381. PcicWriteSocket(Socket, 0x2f, 0x40);
  382. *pDelayTime = PcicStallPower;
  383. }
  384. }
  385. status = STATUS_SUCCESS;
  386. break;
  387. default:
  388. ASSERT(FALSE);
  389. status = STATUS_UNSUCCESSFUL;
  390. }
  391. } else {
  392. PcicWriteSocket(Socket, PCIC_PWR_RST, 0x00);
  393. status = STATUS_SUCCESS;
  394. }
  395. return status;
  396. }
  397. NTSTATUS
  398. PcicConvertSpeedToWait(
  399. IN UCHAR Speed,
  400. OUT PUCHAR WaitIndex
  401. )
  402. {
  403. NTSTATUS status = STATUS_INVALID_PARAMETER;
  404. UCHAR exponent, exponent2, mantissa, index;
  405. if (Speed & SPEED_EXT_MASK) {
  406. return status;
  407. }
  408. exponent = Speed & SPEED_EXPONENT_MASK;
  409. mantissa = Speed & SPEED_MANTISSA_MASK;
  410. if (mantissa == 0) {
  411. mantissa = DevSpeedTable[exponent] & SPEED_MANTISSA_MASK;
  412. exponent = DevSpeedTable[exponent] & SPEED_EXPONENT_MASK;
  413. }
  414. for (index = 0; index < sizeof(WaitToSpeedTable); index++) {
  415. exponent2= WaitToSpeedTable[index] & SPEED_EXPONENT_MASK;
  416. if ((exponent < exponent2) ||
  417. ((exponent == exponent2) &&
  418. (mantissa < (WaitToSpeedTable[index] & SPEED_MANTISSA_MASK)))) {
  419. *WaitIndex = index;
  420. status = STATUS_SUCCESS;
  421. break;
  422. }
  423. }
  424. return status;
  425. }
  426. BOOLEAN
  427. PcicSetVpp(
  428. IN PDEVICE_OBJECT Pdo,
  429. IN UCHAR Vpp
  430. )
  431. /*++
  432. Routine Description
  433. Part of the interfaces originally developed to
  434. support flash memory cards.
  435. Sets VPP1 to the required setting
  436. Arguments
  437. Pdo - Pointer to device object for the PC-Card
  438. Vpp - Desired Vpp setting. This is currently one of
  439. PCMCIA_VPP_12V (12 volts)
  440. PCMCIA_VPP_0V (disable VPP)
  441. PCMCIA_VPP_IS_VCC (route VCC to VPP)
  442. Return
  443. TRUE - if successful
  444. FALSE - if not. This will be returned if the
  445. PC-Card is not already powered up
  446. --*/
  447. {
  448. PSOCKET socketPtr = ((PPDO_EXTENSION) Pdo->DeviceExtension)->Socket;
  449. UCHAR tmp;
  450. ASSERT ( socketPtr != NULL );
  451. tmp = PcicReadSocket(socketPtr, PCIC_PWR_RST);
  452. if ((tmp & 0x10) == 0) {
  453. //
  454. // Vcc not set.
  455. //
  456. return FALSE;
  457. }
  458. //
  459. // Turn off Vpp bits
  460. //
  461. tmp &= ~0x3;
  462. switch (Vpp) {
  463. case PCMCIA_VPP_IS_VCC: {
  464. tmp |= 0x1;
  465. break;
  466. }
  467. case PCMCIA_VPP_12V: {
  468. tmp |= 0x2;
  469. break;
  470. }
  471. case PCMCIA_VPP_0V: {
  472. tmp |= 0x0;
  473. break;
  474. }
  475. }
  476. PcicWriteSocket(socketPtr, PCIC_PWR_RST, tmp);
  477. if (Vpp != PCMCIA_VPP_0V) {
  478. //
  479. // When power is enabled always stall to give the PCCARD
  480. // a chance to react.
  481. //
  482. PcmciaWait(PcicStallPower);
  483. }
  484. return TRUE;
  485. }
  486. BOOLEAN
  487. PcicModifyMemoryWindow(
  488. IN PDEVICE_OBJECT Pdo,
  489. IN ULONGLONG HostBase,
  490. IN ULONGLONG CardBase OPTIONAL,
  491. IN BOOLEAN Enable,
  492. IN ULONG WindowSize OPTIONAL,
  493. IN UCHAR AccessSpeed OPTIONAL,
  494. IN UCHAR BusWidth OPTIONAL,
  495. IN BOOLEAN IsAttributeMemory OPTIONAL
  496. )
  497. /*++
  498. Routine Description:
  499. Part of the interfaces originally developed to
  500. support flash memory cards.
  501. This routine enables the caller to 'slide' the supplied
  502. host memory window across the given (16-bit)pc-card's card memory.
  503. i.e. the host memory window will be modified to map
  504. the pc-card at a new card memory offset
  505. Arguments:
  506. Pdo - Pointer to the device object for the PC-Card
  507. HostBase - Host memory window base to be mapped
  508. CardBase - Mandatory if Enable is TRUE
  509. New card memory offset to map the host memory window
  510. to
  511. Enable - If this is FALSE - all the remaining arguments
  512. are ignored and the host window will simply be
  513. disabled
  514. WindowSize - Specifies the size of the host memory window to
  515. be mapped. Note this must be at the proper alignment
  516. and must be less than or equal to the originally
  517. allocated window size for the host base.
  518. If this is zero, the originally allocated window
  519. size will be used.
  520. AccessSpeed - Mandatory if Enable is TRUE
  521. Specifies the new access speed for the pc-card.
  522. (AccessSpeed should be encoded as per the pc-card
  523. standard, card/socket services spec)
  524. BusWidth - Mandatory if Enable is TRUE
  525. One of PCMCIA_MEMORY_8BIT_ACCESS
  526. or PCMCIA_MEMORY_16BIT_ACCESS
  527. IsAttributeMemory - Mandatory if Enable is TRUE
  528. Specifies if the window should be mapped
  529. to the pc-card's attribute or common memory
  530. Return Value:
  531. TRUE - Memory window was enabled/disabled as requested
  532. FALSE - If not
  533. --*/
  534. {
  535. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  536. PFDO_EXTENSION fdoExtension;
  537. PSOCKET socketPtr;
  538. PSOCKET_CONFIGURATION socketConfig;
  539. USHORT index;
  540. UCHAR registerOffset;
  541. UCHAR regl;
  542. UCHAR regh;
  543. UCHAR tmp, waitIndex;
  544. socketConfig = pdoExtension->SocketConfiguration;
  545. if (!socketConfig) {
  546. // doesn't look like we are started.
  547. return FALSE;
  548. }
  549. socketPtr = pdoExtension->Socket;
  550. ASSERT ( socketPtr != NULL );
  551. fdoExtension = socketPtr->DeviceExtension;
  552. for (index = 0 ; index < socketConfig->NumberOfMemoryRanges; index++) {
  553. if (socketConfig->Memory[index].HostBase == HostBase) {
  554. break;
  555. }
  556. }
  557. if (index >= socketConfig->NumberOfMemoryRanges) {
  558. //
  559. // Unknown hostbase
  560. //
  561. return FALSE;
  562. }
  563. //
  564. // Make sure caller isn't asking a bigger window
  565. // than he is permitted to
  566. //
  567. if (WindowSize > socketConfig->Memory[index].Length) {
  568. return FALSE;
  569. }
  570. if (WindowSize == 0) {
  571. //
  572. // WindowSize not provided. Default to
  573. // the largest size permitted for this pc-card
  574. //
  575. WindowSize = socketConfig->Memory[index].Length;
  576. }
  577. //
  578. // Determine offset in registers.
  579. //
  580. registerOffset = (index * 8);
  581. //
  582. // Disable the window first (this has to be done regardless
  583. // of whether we want to enable/disable the window ultimately)
  584. //
  585. PCMCIA_ACQUIRE_DEVICE_LOCK(socketPtr->DeviceExtension);
  586. tmp = PcicReadSocket(socketPtr, PCIC_ADD_WIN_ENA);
  587. tmp &= ~(1 << index);
  588. PcicWriteSocket(socketPtr, PCIC_ADD_WIN_ENA, tmp);
  589. if (!Enable) {
  590. //
  591. // We're done.. Just write zeroes to the window registers anyway
  592. // before returning
  593. //
  594. PcicWriteSocket(socketPtr,
  595. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_L+registerOffset),
  596. 0);
  597. PcicWriteSocket(socketPtr,
  598. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_H+registerOffset),
  599. 0);
  600. PcicWriteSocket(socketPtr,
  601. (UCHAR)(PCIC_MEM_ADD0_STRT_L+registerOffset),
  602. 0);
  603. PcicWriteSocket(socketPtr,
  604. (UCHAR)(PCIC_MEM_ADD0_STRT_H+registerOffset),
  605. 0);
  606. PcicWriteSocket(socketPtr,
  607. (UCHAR)(PCIC_MEM_ADD0_STOP_L+registerOffset),
  608. 0);
  609. PcicWriteSocket(socketPtr,
  610. (UCHAR)(PCIC_MEM_ADD0_STOP_H+registerOffset),
  611. 0);
  612. PcmciaSetWindowPage(fdoExtension, socketPtr, index, 0);
  613. PCMCIA_RELEASE_DEVICE_LOCK(socketPtr->DeviceExtension);
  614. return TRUE;
  615. }
  616. if (AccessSpeed) {
  617. if (!NT_SUCCESS(PcicConvertSpeedToWait(AccessSpeed, &waitIndex))) {
  618. PCMCIA_RELEASE_DEVICE_LOCK(socketPtr->DeviceExtension);
  619. return FALSE;
  620. }
  621. }
  622. //
  623. // Calculate and set card base addresses.
  624. // This is the 2's complement of the host address and
  625. // the card offset.
  626. //
  627. CardBase = (CardBase - (HostBase & OFFSETCALC_BASE_MASK)) & OFFSETCALC_OFFSET_MASK;
  628. regl = (UCHAR) (CardBase >> 12);
  629. regh = (UCHAR) ((CardBase >> 20) & 0x003f);
  630. if (IsAttributeMemory) {
  631. regh |= 0x40;
  632. }
  633. PcicWriteSocket(socketPtr,
  634. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_L + registerOffset),
  635. regl);
  636. PcicWriteSocket(socketPtr,
  637. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_H + registerOffset),
  638. regh);
  639. //
  640. // Calculate and set host window.
  641. //
  642. if (!PcmciaSetWindowPage(fdoExtension, socketPtr, index, (UCHAR) ((ULONG) HostBase >> 24))) {
  643. if ((HostBase + WindowSize) > 0xFFFFFF) {
  644. DebugPrint((PCMCIA_DEBUG_FAIL, "PcicModifyMemorywindow: HostBase %x specified: doesn't fit in 24 bits!\n", (ULONG) HostBase));
  645. PCMCIA_RELEASE_DEVICE_LOCK(socketPtr->DeviceExtension);
  646. return FALSE;
  647. }
  648. }
  649. regl = (UCHAR) (HostBase >> 12);
  650. regh = (UCHAR) (HostBase >> 20) & 0xF;
  651. if (BusWidth == PCMCIA_MEMORY_16BIT_ACCESS) {
  652. regh |= 0x80; // 16-bit access
  653. #if 0
  654. //
  655. // If this is not a revision 1 part (0x82), then set
  656. // the work around register for 16-bit windows.
  657. //
  658. // This bit is not used on any chip that I have
  659. // documentation for. I have no idea why it is here, it is
  660. // not in win9x.
  661. // In any case it looks like a NOOP for the vast majority of
  662. // chips, but since it uses a NOT, then it is invoked on all
  663. // new controllers. REMOVE after next major release
  664. //
  665. if (socketPtr->Revision != PCIC_REVISION) {
  666. tmp = PcicReadSocket(socketPtr,
  667. PCIC_CARD_DETECT);
  668. tmp |= 0x01;
  669. PcicWriteSocket(socketPtr,
  670. PCIC_CARD_DETECT,
  671. tmp);
  672. }
  673. #endif
  674. }
  675. PcicWriteSocket(socketPtr,
  676. (UCHAR)(PCIC_MEM_ADD0_STRT_L + registerOffset),
  677. regl);
  678. PcicWriteSocket(socketPtr,
  679. (UCHAR)(PCIC_MEM_ADD0_STRT_H + registerOffset),
  680. regh);
  681. //
  682. // Set stop address.
  683. //
  684. HostBase += WindowSize - 1;
  685. regl = (UCHAR) (HostBase >> 12);
  686. regh = (UCHAR) (HostBase >> 20) & 0xF;
  687. //
  688. // Set the wait states
  689. //
  690. if (AccessSpeed) {
  691. //
  692. // New access speed specified, use it
  693. //
  694. regh |= (waitIndex << 6);
  695. } else {
  696. //
  697. // Use existing access speed
  698. //
  699. regh |= (PcicReadSocket(socketPtr, (UCHAR)(PCIC_MEM_ADD0_STOP_H + registerOffset)) & 0xC0);
  700. }
  701. PcicWriteSocket(socketPtr,
  702. (UCHAR)(PCIC_MEM_ADD0_STOP_L + registerOffset),
  703. regl);
  704. PcicWriteSocket(socketPtr,
  705. (UCHAR)(PCIC_MEM_ADD0_STOP_H + registerOffset),
  706. regh);
  707. //
  708. // Memory window set up now enable it
  709. //
  710. tmp = (1 << index);
  711. tmp |= PcicReadSocket(socketPtr, PCIC_ADD_WIN_ENA);
  712. PcicWriteSocket(socketPtr, PCIC_ADD_WIN_ENA, tmp);
  713. //
  714. // Allow the window to settle
  715. //
  716. (VOID) PcicPCCardReady(socketPtr);
  717. PCMCIA_RELEASE_DEVICE_LOCK(socketPtr->DeviceExtension);
  718. return TRUE;
  719. }
  720. BOOLEAN
  721. PcicIsWriteProtected(
  722. IN PDEVICE_OBJECT Pdo
  723. )
  724. /*++
  725. Routine Description:
  726. Part of the interfaces originally developed to
  727. support flash memory cards.
  728. Returns the status of the write protected pin
  729. for the given PC-Card
  730. Arguments:
  731. Pdo - Pointer to the device object for the PC-Card
  732. Return Value:
  733. TRUE - if the PC-Card is write-protected
  734. FALSE - if not
  735. --*/
  736. {
  737. PSOCKET socketPtr = ((PPDO_EXTENSION) Pdo->DeviceExtension)->Socket;
  738. ASSERT ( socketPtr != NULL );
  739. return ((PcicReadSocket(socketPtr, PCIC_STATUS) & 0x10) != 0);
  740. }
  741. VOID
  742. PcicEnableDisableWakeupEvent(
  743. IN PSOCKET Socket,
  744. IN PPDO_EXTENSION PdoExtension,
  745. IN BOOLEAN Enable
  746. )
  747. /*++
  748. Routine Description
  749. This routine sets/resets the Ring Indicate enable bit for the given socket,
  750. enabling a PC-Card in the socket to assert/not assert wake through the RingIndicate
  751. pin.
  752. Arguments
  753. Socket - Pointer to the socket
  754. Enable - TRUE : set ring indicate enable
  755. FALSE: turn off ring indicate, i.e. system cannot be woken up through
  756. a pc-card in this socket
  757. Return Value
  758. None
  759. --*/
  760. {
  761. UCHAR byte;
  762. byte = PcicReadSocket(Socket, PCIC_INTERRUPT);
  763. if (Enable) {
  764. byte |= IGC_RINGIND_ENABLE;
  765. } else {
  766. byte &= ~IGC_RINGIND_ENABLE;
  767. }
  768. PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
  769. }
  770. BOOLEAN
  771. PcicInitializePcmciaSocket(
  772. PSOCKET Socket
  773. )
  774. /*++
  775. Routine Description:
  776. This routine will setup the 82365 into a state where the pcmcia support
  777. module will be able to issue commands to read device tuples from the
  778. cards in the sockets.
  779. Arguments:
  780. Socket - socket specific information
  781. Return Value:
  782. TRUE if successful
  783. FALSE if not successful
  784. --*/
  785. {
  786. UCHAR index;
  787. UCHAR byte;
  788. UCHAR reg;
  789. //
  790. // Initialize the EXCA registers
  791. //
  792. //
  793. for (index = 0; index < 0xFF; index++) {
  794. reg = (UCHAR) PcicRegisterInitTable[index].Register;
  795. if (reg == 0xFF) {
  796. //
  797. // End of table
  798. //
  799. break;
  800. }
  801. byte = (UCHAR) PcicRegisterInitTable[index].Value;
  802. if (reg == PCIC_INTERRUPT) {
  803. //
  804. // Don't clobber the Ring Enable bit
  805. // NOTE: this entire if statement should be removed
  806. // when WAIT_WAKE support is done for modems
  807. // also don't clobber the interrupt enable bit
  808. //
  809. byte |= (PcicReadSocket(Socket, reg) & (IGC_RINGIND_ENABLE | IGC_INTR_ENABLE));
  810. }
  811. PcicWriteSocket(Socket, reg, byte);
  812. }
  813. if (CLPD6729(Socket)) {
  814. //
  815. // Need to program the chip per code in
  816. // Windows 95. This will turn on the
  817. // audio support bit.
  818. // NOTE: This used to be done in PcicDetect
  819. //
  820. byte = PcicReadSocket(Socket, PCIC_CL_MISC_CTRL1);
  821. byte |= CL_MC1_SPKR_ENABLE;
  822. PcicWriteSocket(Socket, PCIC_CL_MISC_CTRL1, byte);
  823. //
  824. // Set the Cirrus Logic controller for ISA style interrupts
  825. //
  826. byte = PcicReadExtendedCirrusController(Socket->AddressPort,
  827. Socket->RegisterOffset,
  828. PCIC_CIRRUS_EXTENSION_CTRL_1);
  829. byte &= ~0x08; // Isa style interrupt
  830. PcicWriteExtendedCirrusController(Socket->AddressPort,
  831. Socket->RegisterOffset,
  832. PCIC_CIRRUS_EXTENSION_CTRL_1,
  833. byte);
  834. }
  835. return TRUE;
  836. }
  837. NTSTATUS
  838. PcicResetCard (
  839. IN PSOCKET Socket,
  840. OUT PULONG pDelayTime
  841. )
  842. /*++
  843. Routine Description:
  844. Resets the pc-card in the given socket.
  845. Arguments:
  846. Socket - Pointer to the socket in which the pc-card resides
  847. pDelayTime - specifies delay (msec) to occur after the current phase
  848. Return value:
  849. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  850. other status values terminate sequence
  851. --*/
  852. {
  853. NTSTATUS status;
  854. UCHAR byte;
  855. switch(Socket->CardResetPhase) {
  856. case 1:
  857. //
  858. // Set interface mode to memory to begin with
  859. //
  860. byte = PcicReadSocket(Socket, PCIC_INTERRUPT);
  861. byte &= ~IGC_PCCARD_IO;
  862. PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
  863. //
  864. // Start reset
  865. //
  866. byte = PcicReadSocket(Socket, PCIC_INTERRUPT);
  867. byte = byte & ~IGC_PCCARD_RESETLO;
  868. PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
  869. *pDelayTime = PcicResetWidthDelay;
  870. status = STATUS_MORE_PROCESSING_REQUIRED;
  871. break;
  872. case 2:
  873. //
  874. // Stop reset
  875. //
  876. byte = PcicReadSocket(Socket, PCIC_INTERRUPT);
  877. byte |= IGC_PCCARD_RESETLO;
  878. PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
  879. *pDelayTime = PcicResetSetupDelay;
  880. status = STATUS_MORE_PROCESSING_REQUIRED;
  881. break;
  882. case 3:
  883. //
  884. // Wait for the card to settle
  885. //
  886. PcicPCCardReady(Socket);
  887. status = STATUS_SUCCESS;
  888. break;
  889. default:
  890. ASSERT(FALSE);
  891. status = STATUS_UNSUCCESSFUL;
  892. }
  893. return status;
  894. }
  895. UCHAR
  896. PcicReadSocket(
  897. IN PSOCKET Socket,
  898. IN ULONG Register
  899. )
  900. /*++
  901. Routine Description:
  902. This routine will read a byte from the specified socket EXCA register
  903. Arguments:
  904. Socket -- Pointer to the socket from which we should read
  905. Register -- The register to be read
  906. Return Value:
  907. The data returned from the port.
  908. --*/
  909. {
  910. UCHAR byte;
  911. if (CardBus(Socket)) {
  912. //
  913. // Sanity check in case controller wasn't started
  914. //
  915. if (Socket->DeviceExtension->CardBusSocketRegisterBase) {
  916. byte = READ_REGISTER_UCHAR((PUCHAR) (Socket->DeviceExtension->CardBusSocketRegisterBase + Register
  917. + CARDBUS_EXCA_REGISTER_BASE));
  918. } else {
  919. byte = 0xff;
  920. }
  921. } else {
  922. byte = PcicReadController(Socket->AddressPort, Socket->RegisterOffset,
  923. (UCHAR) Register);
  924. }
  925. return byte;
  926. }
  927. VOID
  928. PcicWriteSocket(
  929. IN PSOCKET Socket,
  930. IN ULONG Register,
  931. IN UCHAR DataByte
  932. )
  933. /*++
  934. Routine Description:
  935. This routine will write a byte to the specified socket EXCA register
  936. Arguments:
  937. Socket -- Pointer to the socket to which we write
  938. Register -- The register to be read
  939. DataByte -- Data to be written
  940. Return Value:
  941. None
  942. --*/
  943. {
  944. if (CardBus(Socket)) {
  945. //
  946. // Sanity check in case controller wasn't started
  947. //
  948. if (Socket->DeviceExtension->CardBusSocketRegisterBase) {
  949. WRITE_REGISTER_UCHAR((PUCHAR) (Socket->DeviceExtension->CardBusSocketRegisterBase+Register+CARDBUS_EXCA_REGISTER_BASE), DataByte);
  950. }
  951. } else {
  952. PcicWriteController(Socket->AddressPort, Socket->RegisterOffset, (UCHAR)Register, DataByte);
  953. }
  954. }
  955. UCHAR
  956. PcicReadController(
  957. IN PUCHAR Base,
  958. IN USHORT Socket,
  959. IN UCHAR Register
  960. )
  961. /*++
  962. Routine Description:
  963. This routine will read a byte from the controller data port
  964. Arguments:
  965. Base -- The I/O port for the controller
  966. Socket -- The socket in for the card being read
  967. Register -- The register to be read
  968. Return Value:
  969. The data returned from the port.
  970. --*/
  971. {
  972. UCHAR dataByte = 0;
  973. WRITE_PORT_UCHAR(Base, (UCHAR)(Socket+Register));
  974. dataByte = READ_PORT_UCHAR((PUCHAR)Base + 1);
  975. return dataByte;
  976. }
  977. VOID
  978. PcicWriteController(
  979. IN PUCHAR Base,
  980. IN USHORT Socket,
  981. IN UCHAR Register,
  982. IN UCHAR DataByte
  983. )
  984. /*++
  985. Routine Description:
  986. This routine will write a byte to the controller data port
  987. Arguments:
  988. Base -- The I/O port for the controller
  989. Socket -- The socket in for the card being read
  990. Register -- The register to be read
  991. DataByte -- Data to be written
  992. Return Value:
  993. None
  994. --*/
  995. {
  996. WRITE_PORT_UCHAR(Base, (UCHAR)(Socket+Register));
  997. WRITE_PORT_UCHAR((PUCHAR)Base + 1, DataByte);
  998. }
  999. UCHAR
  1000. PcicReadExtendedCirrusController(
  1001. IN PUCHAR Base,
  1002. IN USHORT Socket,
  1003. IN UCHAR Register
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. This routine will read a byte from the Cirrus
  1008. logic extended registers
  1009. Arguments:
  1010. Base -- The I/O port for the controller
  1011. Socket -- The socket in for the card being read
  1012. Register -- The register to be read
  1013. Return Value:
  1014. The data returned from the port.
  1015. --*/
  1016. {
  1017. UCHAR dataByte = 0;
  1018. PcicWriteController(Base, Socket, PCIC_CIRRUS_EXTENDED_INDEX, Register);
  1019. dataByte = PcicReadController(Base, Socket, PCIC_CIRRUS_INDEX_REG);
  1020. return dataByte;
  1021. }
  1022. VOID
  1023. PcicWriteExtendedCirrusController(
  1024. IN PUCHAR Base,
  1025. IN USHORT Socket,
  1026. IN UCHAR Register,
  1027. IN UCHAR DataByte
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. This routine will write a byte to one of the
  1032. Cirrus Logic extended registers
  1033. Arguments:
  1034. Base -- The I/O port for the controller
  1035. Socket -- The socket in for the card being read
  1036. Register -- The register to be read
  1037. DataByte -- Data to be written
  1038. Return Value:
  1039. None
  1040. --*/
  1041. {
  1042. //
  1043. // Register needs to be written out to the extended index register
  1044. //
  1045. PcicWriteController(Base, Socket, PCIC_CIRRUS_EXTENDED_INDEX, Register);
  1046. PcicWriteController(Base, Socket, PCIC_CIRRUS_INDEX_REG, DataByte);
  1047. }
  1048. ULONG
  1049. PcicReadWriteCardMemory(
  1050. IN PSOCKET Socket,
  1051. IN MEMORY_SPACE MemorySpace,
  1052. IN ULONG Offset,
  1053. IN PUCHAR Buffer,
  1054. IN ULONG Length,
  1055. IN CONST BOOLEAN Read
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. This routine will read or write into the configuration memory on the card
  1060. with the supplied buffer. This is provided as a service to certain
  1061. client drivers (netcard) which need to write to the attribute memory
  1062. (say) to set parameters etc.
  1063. Arguments:
  1064. Socket -- The socket info in for the card being written to
  1065. MemorySpace -- indicates which space - attribute or common memory
  1066. Offset -- Offset in the memory to write to
  1067. Buffer -- Buffer contents being dumped to the card
  1068. Length -- Length of the buffer being written out
  1069. Read -- boolean indicating read or write
  1070. --*/
  1071. {
  1072. PFDO_EXTENSION fdoExtension = Socket->DeviceExtension;
  1073. PUCHAR memoryPtr, memoryPtrMax;
  1074. PUCHAR bufferPtr;
  1075. ULONG index, adjustedOffset, adjustedBase;
  1076. UCHAR memGran;
  1077. UCHAR memWidth;
  1078. //
  1079. // NOTE: memGran HAS to be a integral divisor of AttributeMemorySize for
  1080. // the rest of the code to work!
  1081. //
  1082. memGran = (MemorySpace == PCCARD_ATTRIBUTE_MEMORY) ? 2 : 1;
  1083. memWidth = (MemorySpace == PCCARD_ATTRIBUTE_MEMORY) ? MEM_8BIT : MEM_16BIT;
  1084. //
  1085. // Adjust for offsets > size of attribute memory window.
  1086. //
  1087. adjustedOffset = (Offset*memGran) % fdoExtension->AttributeMemorySize;
  1088. //
  1089. // Adjusted base is: |_ Offset _| mod AttrributeMemorySize
  1090. //
  1091. adjustedBase = ((Offset*memGran) / fdoExtension->AttributeMemorySize) *
  1092. fdoExtension->AttributeMemorySize;
  1093. bufferPtr = Buffer;
  1094. PcicEnableDisableMemory(Socket, MemorySpace, adjustedBase, memWidth, TRUE);
  1095. //
  1096. // Now read the memory contents into the user buffer
  1097. //
  1098. memoryPtr = fdoExtension->AttributeMemoryBase + adjustedOffset;
  1099. memoryPtrMax = fdoExtension->AttributeMemoryBase + fdoExtension->AttributeMemorySize;
  1100. for (index = 0; index < Length; index++) {
  1101. if (memoryPtr >= memoryPtrMax) {
  1102. //
  1103. // Skip to next page of attribute memory
  1104. // (size of page = fdoExtension->AttributeMemorySize)
  1105. //
  1106. adjustedBase += fdoExtension->AttributeMemorySize;
  1107. //
  1108. // Remap window at new base
  1109. //
  1110. PcicEnableDisableMemory(Socket, MemorySpace, adjustedBase, memWidth, TRUE);
  1111. memoryPtr = fdoExtension->AttributeMemoryBase;
  1112. }
  1113. if (Read) {
  1114. *bufferPtr++ = READ_REGISTER_UCHAR(memoryPtr);
  1115. } else {
  1116. WRITE_REGISTER_UCHAR(memoryPtr, *bufferPtr++);
  1117. }
  1118. memoryPtr += memGran;
  1119. }
  1120. PcicEnableDisableMemory(Socket, 0,0,0, FALSE);
  1121. return Length;
  1122. }
  1123. ULONG
  1124. PcicReadWriteCardMemoryIndirect(
  1125. IN PSOCKET Socket,
  1126. IN MEMORY_SPACE MemorySpace,
  1127. IN ULONG Offset,
  1128. IN PUCHAR Buffer,
  1129. IN ULONG Length,
  1130. IN CONST BOOLEAN Read
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. This routine will read or write the memory space of a pcmcia card
  1135. using the indirect access method.
  1136. Arguments:
  1137. Socket -- The socket info in for the card being written to
  1138. MemorySpace -- indicates which space - attribute or common memory
  1139. Offset -- Offset in the memory to write to
  1140. Buffer -- Buffer contents being dumped to the card
  1141. Length -- Length of the buffer being written out
  1142. Read -- boolean indicating read or write
  1143. --*/
  1144. {
  1145. PFDO_EXTENSION fdoExtension = Socket->DeviceExtension;
  1146. ULONG index, adjustedOffset;
  1147. PUCHAR pMem;
  1148. UCHAR Control = 0;
  1149. UCHAR memGran;
  1150. PcicEnableDisableMemory(Socket, PCCARD_COMMON_MEMORY, 0, MEM_8BIT, TRUE);
  1151. pMem = (PUCHAR) ((ULONG_PTR)(fdoExtension->AttributeMemoryBase) + IAR_CONTROL_LOW);
  1152. Control = (MemorySpace == PCCARD_ATTRIBUTE_MEMORY_INDIRECT) ? IARF_AUTO_INC :
  1153. IARF_AUTO_INC | IARF_COMMON | IARF_BYTE_GRAN;
  1154. WRITE_REGISTER_UCHAR(pMem, Control);
  1155. memGran = (MemorySpace == PCCARD_ATTRIBUTE_MEMORY_INDIRECT) ? 2 : 1;
  1156. adjustedOffset = Offset*memGran;
  1157. pMem = (PUCHAR) ((ULONG_PTR)(fdoExtension->AttributeMemoryBase) + IAR_ADDRESS);
  1158. for (index = 0; index < sizeof(ULONG); index++) {
  1159. WRITE_REGISTER_UCHAR(pMem++, (UCHAR)(adjustedOffset>>(index*8)));
  1160. }
  1161. PcicEnableDisableMemory(Socket, PCCARD_COMMON_MEMORY, 0, MEM_16BIT, TRUE);
  1162. for (index = 0; index < Length; index++) {
  1163. // Note that pMem should be pointing to IAR_DATA, and is NOT
  1164. // supposed to be incremented
  1165. if (Read) {
  1166. Buffer[index] = READ_REGISTER_UCHAR(pMem);
  1167. } else {
  1168. WRITE_REGISTER_UCHAR(pMem, Buffer[index]);
  1169. }
  1170. }
  1171. PcicEnableDisableMemory(Socket, 0,0,0, FALSE);
  1172. return Length;
  1173. }
  1174. ULONG
  1175. PcicWriteCardMemory(
  1176. IN PPDO_EXTENSION PdoExtension,
  1177. IN MEMORY_SPACE MemorySpace,
  1178. IN ULONG Offset,
  1179. IN PUCHAR Buffer,
  1180. IN ULONG Length
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. This routine will write into the configuration memory on the card
  1185. with the supplied buffer. This is provided as a service to certain
  1186. client drivers (netcard) which need to write to the attribute memory
  1187. (say) to set parameters etc.
  1188. Arguments:
  1189. PdoExtension-- The extension of the device being written to
  1190. MemorySpace -- indicates which space - attribute or common memory
  1191. Offset -- Offset in the memory to write to
  1192. Buffer -- Buffer contents being dumped to the card
  1193. Length -- Length of the buffer being written out
  1194. --*/
  1195. {
  1196. PSOCKET Socket = PdoExtension->Socket;
  1197. ULONG retLength;
  1198. ASSERT (IsSocketFlagSet(Socket, SOCKET_CARD_POWERED_UP));
  1199. switch(MemorySpace) {
  1200. case PCCARD_ATTRIBUTE_MEMORY_INDIRECT:
  1201. case PCCARD_COMMON_MEMORY_INDIRECT:
  1202. retLength = PcicReadWriteCardMemoryIndirect(Socket, MemorySpace, Offset, Buffer, Length, FALSE);
  1203. break;
  1204. case PCCARD_ATTRIBUTE_MEMORY:
  1205. case PCCARD_COMMON_MEMORY:
  1206. retLength = PcicReadWriteCardMemory(Socket, MemorySpace, Offset, Buffer, Length, FALSE);
  1207. break;
  1208. default:
  1209. retLength = 0;
  1210. ASSERT(FALSE);
  1211. }
  1212. return retLength;
  1213. }
  1214. ULONG
  1215. PcicReadCardMemory(
  1216. IN PPDO_EXTENSION PdoExtension,
  1217. IN MEMORY_SPACE MemorySpace,
  1218. IN ULONG Offset,
  1219. IN PUCHAR Buffer,
  1220. IN ULONG Length
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. This routine will read the configuration memory on the card
  1225. Arguments:
  1226. PdoExtension-- The extension of the device being read
  1227. MemorySpace -- indicates which space - attribute or common memory
  1228. Offset -- Offset in the memory to read
  1229. Buffer -- pointer to pointer for tuple information.
  1230. Length -- maximum size of the buffer area for tuple information.
  1231. Return Value:
  1232. --*/
  1233. {
  1234. PSOCKET Socket = PdoExtension->Socket;
  1235. ULONG retLength;
  1236. ASSERT (IsSocketFlagSet(Socket, SOCKET_CARD_POWERED_UP));
  1237. switch(MemorySpace) {
  1238. case PCCARD_ATTRIBUTE_MEMORY_INDIRECT:
  1239. case PCCARD_COMMON_MEMORY_INDIRECT:
  1240. retLength = PcicReadWriteCardMemoryIndirect(Socket, MemorySpace, Offset, Buffer, Length, TRUE);
  1241. break;
  1242. case PCCARD_ATTRIBUTE_MEMORY:
  1243. case PCCARD_COMMON_MEMORY:
  1244. retLength = PcicReadWriteCardMemory(Socket, MemorySpace, Offset, Buffer, Length, TRUE);
  1245. DebugPrint((PCMCIA_DEBUG_INFO,"PcicReadCardMemory: "
  1246. "%.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X-%.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X\n",
  1247. Buffer[0], Buffer[1], Buffer[2], Buffer[3], Buffer[4], Buffer[5], Buffer[6], Buffer[7],
  1248. Buffer[8], Buffer[9], Buffer[10], Buffer[11], Buffer[12], Buffer[13], Buffer[14], Buffer[15]));
  1249. break;
  1250. default:
  1251. retLength = 0;
  1252. ASSERT(FALSE);
  1253. }
  1254. return retLength;
  1255. }
  1256. BOOLEAN
  1257. PcicProcessConfigureRequest(
  1258. IN PSOCKET Socket,
  1259. IN PCARD_REQUEST request,
  1260. IN PUCHAR Base
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. Processes a configure or IRQ setup request.
  1265. Arguments:
  1266. ConfigRequest -- Socket config structure
  1267. Base - the I/O port base
  1268. Return Value:
  1269. None
  1270. --*/
  1271. {
  1272. USHORT index;
  1273. UCHAR tmp;
  1274. //
  1275. // Since all first entries in the config structure is a RequestType,
  1276. // cast the pointer comming in as a PREQUEST_CONFIG to get the proper
  1277. // RequestType
  1278. //
  1279. switch (request->RequestType) {
  1280. case IO_REQUEST: {
  1281. UCHAR ioControl = 0;
  1282. if (!request->u.Io.IoEntry[0].BasePort) {
  1283. break;
  1284. }
  1285. for (index = 0; index < request->u.Io.NumberOfRanges; index++) {
  1286. UCHAR registerOffset;
  1287. registerOffset = (index * 4);
  1288. if (request->u.Io.IoEntry[index].BasePort) {
  1289. PcicWriteSocket( Socket,
  1290. PCIC_IO_ADD0_STRT_L + registerOffset,
  1291. (UCHAR) (request->u.Io.IoEntry[index].BasePort & 0xff));
  1292. PcicWriteSocket( Socket,
  1293. PCIC_IO_ADD0_STRT_H + registerOffset,
  1294. (UCHAR) (request->u.Io.IoEntry[index].BasePort >> 8));
  1295. PcicWriteSocket(Socket,
  1296. PCIC_IO_ADD0_STOP_L + registerOffset,
  1297. (UCHAR) ((request->u.Io.IoEntry[index].BasePort +
  1298. request->u.Io.IoEntry[index].NumPorts) & 0xff));
  1299. PcicWriteSocket(Socket,
  1300. PCIC_IO_ADD0_STOP_H + registerOffset,
  1301. (UCHAR) ((request->u.Io.IoEntry[index].BasePort +
  1302. request->u.Io.IoEntry[index].NumPorts) >> 8));
  1303. }
  1304. //
  1305. // set up the io control register
  1306. //
  1307. tmp = 0;
  1308. if (request->u.Io.IoEntry[index].Attributes & IO_DATA_PATH_WIDTH) {
  1309. tmp |= IOC_IO0_DATASIZE;
  1310. }
  1311. if ((request->u.Io.IoEntry[index].Attributes & IO_WAIT_STATE_16) &&
  1312. !((Elc(Socket) || CLPD6729(Socket)))) {
  1313. tmp |= IOC_IO0_WAITSTATE;
  1314. }
  1315. if (request->u.Io.IoEntry[index].Attributes & IO_SOURCE_16) {
  1316. tmp |= IOC_IO0_IOCS16;
  1317. }
  1318. if (request->u.Io.IoEntry[index].Attributes & IO_ZERO_WAIT_8) {
  1319. tmp |= IOC_IO0_ZEROWS;
  1320. }
  1321. ioControl |= tmp << registerOffset;
  1322. }
  1323. PcicWriteSocket(Socket, PCIC_IO_CONTROL, ioControl);
  1324. tmp = PcicReadSocket( Socket, PCIC_ADD_WIN_ENA);
  1325. tmp &= ~(WE_IO0_ENABLE | WE_IO1_ENABLE);
  1326. switch(request->u.Io.NumberOfRanges) {
  1327. case 1:
  1328. tmp |= WE_IO0_ENABLE;
  1329. break;
  1330. case 2:
  1331. tmp |= (WE_IO0_ENABLE | WE_IO1_ENABLE);
  1332. break;
  1333. }
  1334. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1335. break;
  1336. }
  1337. case IRQ_REQUEST: {
  1338. //
  1339. // Do not nuke the reset and cardtype bits.
  1340. //
  1341. tmp = PcicReadSocket(Socket, PCIC_INTERRUPT);
  1342. tmp &= ~IGC_IRQ_MASK;
  1343. tmp |= request->u.Irq.AssignedIRQ;
  1344. DebugPrint((PCMCIA_DEBUG_INFO, "PcicProcessConfigureRequest: Assigned IRQ %x programming IRQ %x\n", request->u.Irq.AssignedIRQ,tmp));
  1345. PcicWriteSocket(Socket, PCIC_INTERRUPT, tmp);
  1346. if (tmp = request->u.Irq.ReadyIRQ) {
  1347. tmp = (tmp << 4) | 0x04;
  1348. PcicWriteSocket(Socket, PCIC_CARD_INT_CONFIG, tmp);
  1349. }
  1350. break;
  1351. }
  1352. case DECONFIGURE_REQUEST: {
  1353. //
  1354. // Deregister the interrupt, re-init to memory interface
  1355. //
  1356. tmp = PcicReadSocket(Socket, PCIC_INTERRUPT);
  1357. tmp &= ~(IGC_PCCARD_IO | IGC_IRQ_MASK);
  1358. PcicWriteSocket(Socket, PCIC_INTERRUPT, tmp);
  1359. //
  1360. // Disable memory/io windows
  1361. // Don't touch the memory window which is
  1362. // is used by the controller for reading attribute memory
  1363. //
  1364. if (IsSocketFlagSet(Socket, SOCKET_MEMORY_WINDOW_ENABLED)) {
  1365. UCHAR enableMask;
  1366. enableMask = WE_MEM0_ENABLE << Socket->CurrentMemWindow;
  1367. tmp = PcicReadSocket(Socket, PCIC_ADD_WIN_ENA);
  1368. tmp &= enableMask;
  1369. } else {
  1370. //
  1371. // no attribute window enabled, just turn off everything
  1372. //
  1373. tmp = 0;
  1374. }
  1375. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1376. //
  1377. // Zero out the I/O windows
  1378. //
  1379. for (index = PCIC_IO_ADD0_STRT_L; index <= PCIC_IO_ADD1_STOP_H; index++) {
  1380. PcicWriteSocket( Socket,
  1381. (ULONG) index,
  1382. 0);
  1383. }
  1384. break;
  1385. }
  1386. case CONFIGURE_REQUEST:{
  1387. //
  1388. // Tell the socket controller we are an I/O card if InterfaceType says so
  1389. //
  1390. if (request->u.Config.InterfaceType == CONFIG_INTERFACE_IO_MEM) {
  1391. tmp = PcicReadSocket(Socket, PCIC_INTERRUPT);
  1392. tmp |= IGC_PCCARD_IO;
  1393. PcicWriteSocket(Socket, PCIC_INTERRUPT, tmp);
  1394. } else {
  1395. tmp = PcicReadSocket(Socket, PCIC_INTERRUPT);
  1396. tmp &= ~IGC_PCCARD_IO;
  1397. PcicWriteSocket(Socket, PCIC_INTERRUPT, tmp);
  1398. }
  1399. if (request->u.Config.RegisterWriteMask & (REGISTER_WRITE_CONFIGURATION_INDEX |
  1400. REGISTER_WRITE_CARD_CONFIGURATION |
  1401. REGISTER_WRITE_IO_BASE)) {
  1402. //
  1403. // This is where we setup the card and get it ready for operation
  1404. //
  1405. ULONG configRegisterBase = request->u.Config.ConfigBase / 2;
  1406. PDEVICE_OBJECT Pdo = Socket->PdoList;
  1407. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  1408. MEMORY_SPACE memorySpace = IsPdoFlagSet(pdoExtension, PCMCIA_PDO_INDIRECT_CIS) ? PCCARD_ATTRIBUTE_MEMORY_INDIRECT :
  1409. PCCARD_ATTRIBUTE_MEMORY;
  1410. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_IO_BASE) {
  1411. UCHAR ioHigh = (UCHAR)(request->u.Config.IoBaseRegister>>8);
  1412. UCHAR ioLow = (UCHAR) request->u.Config.IoBaseRegister;
  1413. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase + 5, &ioLow, 1);
  1414. PcmciaWait(PcicStallCounter);
  1415. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase + 6, &ioHigh, 1);
  1416. PcmciaWait(PcicStallCounter);
  1417. }
  1418. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_IO_LIMIT) {
  1419. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase + 9, (PUCHAR)&request->u.Config.IoLimitRegister, 1);
  1420. PcmciaWait(PcicStallCounter);
  1421. }
  1422. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_CONFIGURATION_INDEX) {
  1423. UCHAR configIndex = request->u.Config.ConfigIndex;
  1424. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase, &configIndex, 1);
  1425. PcmciaWait(PcicStallCounter);
  1426. configIndex |= 0x40;
  1427. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase, &configIndex, 1);
  1428. PcmciaWait(PcicStallCounter);
  1429. }
  1430. if (request->u.Config.RegisterWriteMask & REGISTER_WRITE_CARD_CONFIGURATION) {
  1431. PcicReadCardMemory(pdoExtension, memorySpace, configRegisterBase + 1, &tmp, 1);
  1432. PcmciaWait(PcicStallCounter);
  1433. tmp |= request->u.Config.CardConfiguration;
  1434. //
  1435. // turn off power control bit
  1436. //
  1437. tmp &= ~0x04;
  1438. PcicWriteCardMemory(pdoExtension, memorySpace, configRegisterBase + 1, &tmp, 1);
  1439. PcmciaWait(PcicStallCounter);
  1440. }
  1441. }
  1442. break;
  1443. }
  1444. case MEM_REQUEST: {
  1445. //
  1446. // Set up memory ranges on the controller.
  1447. //
  1448. PFDO_EXTENSION deviceExtension = Socket->DeviceExtension;
  1449. for (index = 0; index < request->u.Memory.NumberOfRanges; index++) {
  1450. UCHAR registerOffset;
  1451. UCHAR regl;
  1452. UCHAR regh;
  1453. ULONG cardBase = request->u.Memory.MemoryEntry[index].BaseAddress;
  1454. ULONG base = request->u.Memory.MemoryEntry[index].HostAddress;
  1455. ULONG size = request->u.Memory.MemoryEntry[index].WindowSize;
  1456. //
  1457. // Determine offset in registers.
  1458. //
  1459. registerOffset = (index * 8);
  1460. //
  1461. // Calculate and set card base addresses.
  1462. // This is the 2's complement of the host address and
  1463. // the card offset.
  1464. //
  1465. cardBase = (cardBase - (base & OFFSETCALC_BASE_MASK)) & OFFSETCALC_OFFSET_MASK;
  1466. regl = (UCHAR) (cardBase >> 12);
  1467. regh = (UCHAR) (cardBase >> 20);
  1468. if (request->u.Memory.MemoryEntry[index].AttributeMemory) {
  1469. regh |= 0x40;
  1470. }
  1471. PcicWriteSocket(Socket,
  1472. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_L + registerOffset),
  1473. regl);
  1474. PcicWriteSocket(Socket,
  1475. (UCHAR)(PCIC_CRDMEM_OFF_ADD0_H + registerOffset),
  1476. regh);
  1477. //
  1478. // Calculate and set host window.
  1479. //
  1480. if (!PcmciaSetWindowPage(deviceExtension, Socket, index, (UCHAR) (base >> 24))) {
  1481. ASSERT (base <= 0xFFFFFF);
  1482. }
  1483. base &= 0xFFFFFF; // only 24bit host base allowed
  1484. regl = (UCHAR) (base >> 12);
  1485. regh = (UCHAR) (base >> 20);
  1486. if (request->u.Memory.MemoryEntry[index].WindowDataSize16) {
  1487. //
  1488. // This memory window is for a 16-bit data path
  1489. // to the card. Enable appropriately.
  1490. //
  1491. regh |= (MEMBASE_16BIT >> 8);
  1492. #if 0
  1493. //
  1494. // If this is not a revision 1 part (0x82), then set
  1495. // the work around register for 16-bit windows.
  1496. //
  1497. // This bit is not used on any chip that I have
  1498. // documentation for. I have no idea why it is here, it is
  1499. // not in win9x.
  1500. // In any case it looks like a NOOP for the vast majority of
  1501. // chips, but since it uses a NOT, then it is invoked on all
  1502. // new controllers. REMOVE after next major release
  1503. //
  1504. if (Socket->Revision != PCIC_REVISION) {
  1505. tmp = PcicReadSocket(Socket,
  1506. PCIC_CARD_DETECT);
  1507. tmp |= 0x01;
  1508. PcicWriteSocket(Socket,
  1509. PCIC_CARD_DETECT,
  1510. tmp);
  1511. }
  1512. #endif
  1513. }
  1514. PcicWriteSocket(Socket,
  1515. (UCHAR)(PCIC_MEM_ADD0_STRT_L + registerOffset),
  1516. regl);
  1517. PcicWriteSocket(Socket,
  1518. (UCHAR)(PCIC_MEM_ADD0_STRT_H + registerOffset),
  1519. regh);
  1520. //
  1521. // Set stop address.
  1522. //
  1523. base += size - 1;
  1524. regl = (UCHAR) (base >> 12);
  1525. regh = (UCHAR) (base >> 20);
  1526. //
  1527. // Add specified wait states
  1528. //
  1529. regh |= (request->u.Memory.MemoryEntry[index].WaitStates << 6);
  1530. PcicWriteSocket(Socket,
  1531. (UCHAR)(PCIC_MEM_ADD0_STOP_L + registerOffset),
  1532. regl);
  1533. PcicWriteSocket(Socket,
  1534. (UCHAR)(PCIC_MEM_ADD0_STOP_H + registerOffset),
  1535. regh);
  1536. }
  1537. //
  1538. // Memory windows are set up now enable them.
  1539. //
  1540. tmp = 0;
  1541. for (index = 0; index < request->u.Memory.NumberOfRanges; index++) {
  1542. tmp |= (1 << index);
  1543. }
  1544. tmp |= PcicReadSocket(Socket, PCIC_ADD_WIN_ENA);
  1545. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1546. break;
  1547. }
  1548. default: {
  1549. DebugPrint((PCMCIA_DEBUG_FAIL, "ConfigRequest is INVALID!\n"));
  1550. }
  1551. }
  1552. return TRUE;
  1553. }
  1554. BOOLEAN
  1555. PcicDetectCardInSocket(
  1556. IN PSOCKET Socket
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. This routine will determine if a card is in the socket
  1561. Arguments:
  1562. Socket -- Socket information
  1563. Return Value:
  1564. TRUE if card is present.
  1565. --*/
  1566. {
  1567. UCHAR tmp;
  1568. BOOLEAN cardPresent=FALSE;
  1569. //
  1570. // Read the PCIC status register to see if the card is in there.
  1571. //
  1572. tmp = PcicReadSocket(Socket, PCIC_STATUS);
  1573. tmp &= (CARD_DETECT_1 | CARD_DETECT_2);
  1574. if (tmp == (CARD_DETECT_1 | CARD_DETECT_2)) {
  1575. cardPresent = TRUE;
  1576. }
  1577. return cardPresent;
  1578. }
  1579. BOOLEAN
  1580. PcicDetectCardChanged(
  1581. IN PSOCKET Socket
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. This routine will determine if socket's card insertion status has changed.
  1586. Arguments:
  1587. Socket -- Socket info.
  1588. Return Value:
  1589. TRUE if card insertion status has changed.
  1590. --*/
  1591. {
  1592. //
  1593. // Read the PCIC CardStatusChange register to see if CD's have changed.
  1594. //
  1595. return (BOOLEAN) (PcicReadSocket(Socket, PCIC_CARD_CHANGE) & CSC_CD_CHANGE);
  1596. }
  1597. BOOLEAN
  1598. PcicDetectReadyChanged(
  1599. IN PSOCKET Socket
  1600. )
  1601. /*++
  1602. Routine Description:
  1603. This routine will determine if socket's card ready status has changed
  1604. Arguments:
  1605. Socket -- Socket info.
  1606. Return Value:
  1607. TRUE if card ready enable has changed.
  1608. --*/
  1609. {
  1610. //
  1611. // Read the PCIC Card status change register to see if ready has changed
  1612. //
  1613. return (PcicReadSocket(Socket, PCIC_CARD_CHANGE) & CSC_READY_CHANGE
  1614. ?TRUE :FALSE);
  1615. }
  1616. VOID
  1617. PcicEnableDisableMemory(
  1618. IN PSOCKET Socket,
  1619. IN MEMORY_SPACE MemorySpace,
  1620. IN ULONG CardBase,
  1621. IN UCHAR memWidth,
  1622. IN BOOLEAN Enable
  1623. )
  1624. /*++
  1625. Routine Description:
  1626. This routine will enable or disable attribute/common memory.
  1627. It searches for a free window first to avoid using a window already
  1628. in use. Repeated 'enable' calls to this routine without a disable
  1629. (in order to remap the base) is allowed.
  1630. Arguments:
  1631. Socket -- Socket information
  1632. MemorySpace -- Indicates which space - ATTRIBUTE_MEMORY/COMMON_MEMORY
  1633. CardBase -- card offset (base) for the attribute memory window
  1634. Enable -- If TRUE, enable, if FALSE, disable
  1635. Return Value:
  1636. None
  1637. --*/
  1638. {
  1639. ULONG location;
  1640. PUCHAR cisBufferPointer;
  1641. PFDO_EXTENSION deviceExtension= Socket->DeviceExtension;
  1642. PUCHAR PcicCisBufferBase = (PUCHAR) deviceExtension->AttributeMemoryBase;
  1643. ULONG PcicPhysicalBase = deviceExtension->PhysicalBase.LowPart;
  1644. BOOLEAN memoryInterface;
  1645. UCHAR tmp;
  1646. UCHAR index;
  1647. UCHAR registerOffset;
  1648. UCHAR enableMask;
  1649. USHORT word;
  1650. ASSERT (IsSocketFlagSet(Socket, SOCKET_CARD_POWERED_UP));
  1651. if (Enable) {
  1652. tmp = PcicReadSocket(Socket, PCIC_INTERRUPT);
  1653. if (tmp & IGC_PCCARD_IO) {
  1654. //
  1655. // Card configured for i/o interface
  1656. //
  1657. memoryInterface = FALSE;
  1658. } else {
  1659. //
  1660. // Card configured for Memory interface
  1661. //
  1662. memoryInterface = TRUE;
  1663. }
  1664. //
  1665. // Find a window to use.
  1666. //
  1667. tmp = PcicReadSocket(Socket, PCIC_ADD_WIN_ENA);
  1668. if (IsSocketFlagSet(Socket, SOCKET_MEMORY_WINDOW_ENABLED)) {
  1669. index = Socket->CurrentMemWindow;
  1670. enableMask = WE_MEM0_ENABLE << index;
  1671. } else {
  1672. for (index = 0, enableMask = WE_MEM0_ENABLE; index < 5; index++, enableMask <<= 1) {
  1673. if (!(tmp & enableMask)) {
  1674. break;
  1675. }
  1676. if (index==4) {
  1677. //
  1678. // If we are here, we didn't find an available window. Just use the last
  1679. // one anyway, it is likely a pcmcia.sys bug.
  1680. //
  1681. // ASSERT(FALSE); // hits docked thinkpads
  1682. break;
  1683. }
  1684. }
  1685. Socket->CurrentMemWindow = index;
  1686. SetSocketFlag(Socket, SOCKET_MEMORY_WINDOW_ENABLED);
  1687. }
  1688. registerOffset = (index * 8);
  1689. //
  1690. // First turn the window off
  1691. //
  1692. tmp &= ~enableMask;
  1693. tmp &= ~WE_MEMCS16_DECODE;
  1694. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1695. //
  1696. // Calculate and set the memory windows start and stop locations.
  1697. //
  1698. //
  1699. // Only 24 bit addresses programmed
  1700. // For cardbus controllers, 32 bit addresses are supported,
  1701. // but the higher 8 bits are written to the page register (see below)
  1702. location = PcicPhysicalBase & 0xFFFFFF;
  1703. word = (USHORT) ((location >> 12) & MEMBASE_ADDR_MASK);
  1704. //
  1705. // typically run attribute memory with 8-bit window, common with 16-bit
  1706. // (except for writing the registers for attribute_indirect)
  1707. //
  1708. if (memWidth == MEM_16BIT) {
  1709. word |= MEMBASE_16BIT;
  1710. }
  1711. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STRT_L+registerOffset), (UCHAR)(word));
  1712. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STRT_H+registerOffset), (UCHAR)(word >> 8));
  1713. location += (deviceExtension->AttributeMemorySize - 1);
  1714. word = (USHORT) ((location >> 12) & MEMEND_ADDR_MASK);
  1715. //
  1716. // Impose 3 wait states..lessons learnt from win9x implementations
  1717. //
  1718. word |= MEMEND_WS_MASK;
  1719. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STOP_L+registerOffset), (UCHAR)(word));
  1720. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STOP_H+registerOffset), (UCHAR)(word >> 8));
  1721. //
  1722. // Set up the 2's complement card offset to zero
  1723. //
  1724. location = (CardBase - (PcicPhysicalBase & OFFSETCALC_BASE_MASK)) & OFFSETCALC_OFFSET_MASK;
  1725. word = (USHORT) ((location >> 12) & MEMOFF_ADDR_MASK);
  1726. if (MemorySpace == PCCARD_ATTRIBUTE_MEMORY) {
  1727. word |= MEMOFF_REG_ACTIVE;
  1728. }
  1729. PcicWriteSocket(Socket, (UCHAR)(PCIC_CRDMEM_OFF_ADD0_L+registerOffset), (UCHAR)(word));
  1730. PcicWriteSocket(Socket, (UCHAR)(PCIC_CRDMEM_OFF_ADD0_H+registerOffset), (UCHAR)(word >> 8));
  1731. //
  1732. // Set the page register
  1733. // (this routine is called only for R2 cards)
  1734. // Use mem4 window explicitly
  1735. //
  1736. if (!PcmciaSetWindowPage(deviceExtension, Socket, (USHORT)index, (UCHAR) (PcicPhysicalBase >> 24))) {
  1737. ASSERT (PcicPhysicalBase <= 0xFFFFFF);
  1738. }
  1739. //
  1740. // Enable the address window
  1741. //
  1742. tmp = PcicReadSocket(Socket, PCIC_ADD_WIN_ENA);
  1743. tmp |= enableMask | WE_MEMCS16_DECODE;
  1744. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1745. cisBufferPointer = PcicCisBufferBase;
  1746. if (memoryInterface) {
  1747. //
  1748. // Only wait for card ready if the memory window does not appear
  1749. //
  1750. (VOID) PcicPCCardReady(Socket);
  1751. } else {
  1752. //
  1753. // Wait a little bit for the window to appear
  1754. //
  1755. PcmciaWait(PcicMemoryWindowDelay);
  1756. }
  1757. DebugPrint((PCMCIA_DEBUG_INFO, "skt %08x memory window %d enabled %x\n", Socket, index, PcicPhysicalBase));
  1758. } else {
  1759. if (IsSocketFlagSet(Socket, SOCKET_MEMORY_WINDOW_ENABLED)) {
  1760. enableMask = WE_MEM0_ENABLE << Socket->CurrentMemWindow;
  1761. registerOffset = (Socket->CurrentMemWindow * 8);
  1762. //
  1763. // Disable the Address window
  1764. //
  1765. tmp = PcicReadSocket(Socket, PCIC_ADD_WIN_ENA);
  1766. tmp &= ~enableMask;
  1767. PcicWriteSocket(Socket, PCIC_ADD_WIN_ENA, tmp);
  1768. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STRT_L+registerOffset), 0xFF);
  1769. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STRT_H+registerOffset), 0x0F);
  1770. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STOP_L+registerOffset), 0xFF);
  1771. PcicWriteSocket(Socket, (UCHAR)(PCIC_MEM_ADD0_STOP_H+registerOffset), 0x0F);
  1772. PcicWriteSocket(Socket, (UCHAR)(PCIC_CRDMEM_OFF_ADD0_L+registerOffset), 0x00);
  1773. PcicWriteSocket(Socket, (UCHAR)(PCIC_CRDMEM_OFF_ADD0_H+registerOffset), 0x00);
  1774. PcmciaSetWindowPage(deviceExtension, Socket, Socket->CurrentMemWindow, 0);
  1775. DebugPrint((PCMCIA_DEBUG_INFO, "skt %08x memory window %d disabled\n", Socket, Socket->CurrentMemWindow));
  1776. ResetSocketFlag(Socket, SOCKET_MEMORY_WINDOW_ENABLED);
  1777. }
  1778. }
  1779. return;
  1780. }
  1781. BOOLEAN
  1782. PcicPCCardReady(
  1783. IN PSOCKET Socket
  1784. )
  1785. /*++
  1786. Routine Description:
  1787. Loop for a reasonable amount of time waiting for the card status to
  1788. return ready.
  1789. Arguments:
  1790. Socket - the socket to check.
  1791. Return Value:
  1792. TRUE - the card is ready.
  1793. FALSE - after a reasonable delay the card is still not ready.
  1794. --*/
  1795. {
  1796. ULONG index;
  1797. UCHAR byte;
  1798. PFDO_EXTENSION fdoExtension = Socket->DeviceExtension;
  1799. NTSTATUS status;
  1800. LARGE_INTEGER timeout;
  1801. #ifdef READY_ENABLE
  1802. if (fdoExtension->PcmciaInterruptObject) {
  1803. byte = PcicReadSocket(Socket, PCIC_STATUS);
  1804. if (byte & 0x20) {
  1805. return TRUE;
  1806. }
  1807. //
  1808. // Enable ready enable controller interrupt
  1809. //
  1810. PcicEnableDisableControllerInterrupt(
  1811. Socket,
  1812. fdoExtension->Configuration.Interrupt.u.Interrupt.Level,
  1813. TRUE,
  1814. TRUE);
  1815. RtlConvertLongToLargeInteger(-PCMCIA_READY_WAIT_INTERVAL);
  1816. status = KeWaitForSingleObject(&Socket->PCCardReadyEvent,
  1817. Executive,
  1818. KernelMode,
  1819. FALSE,
  1820. &timeout
  1821. );
  1822. if (status != STATUS_TIMEOUT) {
  1823. return TRUE;
  1824. }
  1825. return FALSE;
  1826. }
  1827. #endif
  1828. for (index = 0; index < fdoExtension->ReadyDelayIter; index++) {
  1829. byte = PcicReadSocket(Socket, PCIC_STATUS);
  1830. if (byte & 0x20) {
  1831. break;
  1832. }
  1833. PcmciaWait(fdoExtension->ReadyStall);
  1834. }
  1835. if (index < fdoExtension->ReadyDelayIter) {
  1836. DebugPrint((PCMCIA_COUNTERS, "PcicPCCardReady: %d\n", index));
  1837. return TRUE;
  1838. }
  1839. return FALSE;
  1840. }
  1841. NTSTATUS
  1842. PcicIsaDetect(
  1843. IN PFDO_EXTENSION DeviceExtension
  1844. )
  1845. /*++
  1846. Routine Description:
  1847. Locate any PCMCIA sockets supported by this driver. This routine
  1848. will find the 82365SL and compatible parts and construct SOCKET
  1849. structures to represent all sockets found
  1850. Arguments:
  1851. DeviceExtension - the root for the SocketList.
  1852. Return Value:
  1853. STATUS_SUCCESS if a controller is found: also indicates this might be called
  1854. again to locate another controller
  1855. STATUS_UNSUCCESSFUL if something failed/no controllers found.
  1856. STATUS_NO_MORE_ENTRIES if no more pcic controllers can be found.
  1857. Stop calling this routine.
  1858. --*/
  1859. {
  1860. #define PCMCIA_NUMBER_ISA_PORT_ADDRESSES 3
  1861. static ULONG isaIndex=0;
  1862. ULONG index;
  1863. ULONG ioPortBases[PCMCIA_NUMBER_ISA_PORT_ADDRESSES] = { 0x3e0, 0x3e2, 0x3e4};
  1864. NTSTATUS status=STATUS_NO_MORE_ENTRIES;
  1865. PAGED_CODE();
  1866. DeviceExtension->Configuration.InterfaceType = Isa;
  1867. DeviceExtension->Configuration.BusNumber = 0x0;
  1868. for (index = isaIndex; !NT_SUCCESS(status) && (index < PCMCIA_NUMBER_ISA_PORT_ADDRESSES); index++) {
  1869. status = PcicDetect(DeviceExtension,Isa, ioPortBases[index]);
  1870. }
  1871. //
  1872. // Set index for next search
  1873. //
  1874. isaIndex = index;
  1875. return status;
  1876. }
  1877. NTSTATUS
  1878. PcicDetect(
  1879. IN PFDO_EXTENSION DeviceExtension,
  1880. IN INTERFACE_TYPE InterfaceType,
  1881. IN ULONG IoPortBase
  1882. )
  1883. /*++
  1884. Routine Description:
  1885. This routine is used for legacy detecting PCIC-compatible
  1886. PCMCIA controllers.
  1887. This attempts to sniff the standard PCMCIA controller ports
  1888. to check if anything resembling the PCMCIA revisions exists,
  1889. and if so obtain and initialize socket information for the controller.
  1890. Arguments:
  1891. DeviceExtension - pointer to the already allocated device extension
  1892. for the yet-to-be-detected pcmcia controller.
  1893. InterfaceType - Bus interface type on which the pcmcia
  1894. controller is expected to reside. Currently
  1895. we legacy detect only ISA based controllers
  1896. IoPortBase - IoPort address we need to sniff at for finding
  1897. the controller
  1898. Return value:
  1899. STATUS_SUCCESS PCMCIA controller was found
  1900. STATUS_UNSUCCESSFUL otherwise
  1901. --*/
  1902. {
  1903. ULONG addressSpace;
  1904. NTSTATUS status;
  1905. PUCHAR port;
  1906. PUCHAR elcPort;
  1907. PHYSICAL_ADDRESS cardAddress;
  1908. PHYSICAL_ADDRESS portAddress;
  1909. PCM_RESOURCE_LIST cmResourceList = NULL;
  1910. PCM_PARTIAL_RESOURCE_LIST cmPartialResourceList;
  1911. UCHAR saveBytes[2];
  1912. UCHAR dataByte;
  1913. UCHAR revisionByte;
  1914. USHORT socket;
  1915. UCHAR socketNumber = 0;
  1916. BOOLEAN translated;
  1917. BOOLEAN mapped = FALSE;
  1918. BOOLEAN conflict = TRUE;
  1919. BOOLEAN resourcesAllocated = FALSE;
  1920. PAGED_CODE();
  1921. portAddress.LowPart = IoPortBase;
  1922. portAddress.u.HighPart = 0;
  1923. //
  1924. // Get the resources used for detection
  1925. //
  1926. cmResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
  1927. if (!cmResourceList) {
  1928. status = STATUS_INSUFFICIENT_RESOURCES;
  1929. goto Exit;
  1930. }
  1931. RtlZeroMemory(cmResourceList, sizeof(CM_RESOURCE_LIST));
  1932. cmResourceList->Count = 1;
  1933. cmResourceList->List[0].InterfaceType = Isa;
  1934. cmPartialResourceList = &(cmResourceList->List[0].PartialResourceList);
  1935. cmPartialResourceList->Version = 1;
  1936. cmPartialResourceList->Revision = 1;
  1937. cmPartialResourceList->Count = 1;
  1938. cmPartialResourceList->PartialDescriptors[0].Type = CmResourceTypePort;
  1939. cmPartialResourceList->PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
  1940. cmPartialResourceList->PartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_10_BIT_DECODE;
  1941. cmPartialResourceList->PartialDescriptors[0].u.Port.Start = portAddress;
  1942. cmPartialResourceList->PartialDescriptors[0].u.Port.Length = 2;
  1943. status=IoReportResourceForDetection(
  1944. DeviceExtension->DriverObject,
  1945. cmResourceList,
  1946. sizeof(CM_RESOURCE_LIST),
  1947. NULL,
  1948. NULL,
  1949. 0,
  1950. &conflict);
  1951. if (!NT_SUCCESS(status) || conflict) {
  1952. goto Exit;
  1953. }
  1954. resourcesAllocated = TRUE;
  1955. addressSpace = 1; // port space
  1956. translated = HalTranslateBusAddress(InterfaceType,
  1957. 0,
  1958. portAddress,
  1959. &addressSpace,
  1960. &cardAddress);
  1961. if (!translated) {
  1962. //
  1963. // HAL would not translate the address.
  1964. //
  1965. status = STATUS_UNSUCCESSFUL;
  1966. goto Exit;
  1967. }
  1968. if (addressSpace) {
  1969. //
  1970. // I/O port space
  1971. //
  1972. port = (PUCHAR)(cardAddress.QuadPart);
  1973. } else {
  1974. //
  1975. // Memory space.. we need to map this into memory
  1976. //
  1977. port = MmMapIoSpace(cardAddress,
  1978. 2,
  1979. FALSE);
  1980. mapped = TRUE;
  1981. }
  1982. status = STATUS_UNSUCCESSFUL;
  1983. socket = 0;
  1984. dataByte = PcicReadController(port, socket, PCIC_IDENT);
  1985. revisionByte = dataByte;
  1986. switch (dataByte) {
  1987. case PCIC_REVISION:
  1988. case PCIC_REVISION2:
  1989. case PCIC_REVISION3: {
  1990. //
  1991. // The cirrus logic controller will toggle top 2 lines from the chip info
  1992. // register on the chip. Read from thelocation 3 times and verify that the top two
  1993. // lines are changing. We do this for NEC 98 also..
  1994. //
  1995. ULONG i;
  1996. UCHAR data[4];
  1997. WRITE_PORT_UCHAR(port, (UCHAR)(socket + PCIC_CL_CHIP_INFO));
  1998. for (i = 0; i < 3; i++) {
  1999. data[i] = READ_PORT_UCHAR(port+1);
  2000. if (i) {
  2001. dataByte = data[i - 1] ^ data[i];
  2002. if (dataByte != 0xc0) {
  2003. break;
  2004. }
  2005. }
  2006. }
  2007. if (i == 3) {
  2008. //
  2009. // Ah. this is a cirrus logic controller
  2010. //
  2011. PcmciaSetControllerType(DeviceExtension, PcmciaCLPD6729);
  2012. }
  2013. dataByte = PcicReadController(port, socket, PCIC_CARD_CHANGE);
  2014. if (dataByte & 0xf0) {
  2015. //
  2016. // Not a socket.
  2017. //
  2018. break;
  2019. }
  2020. //
  2021. // Map and try to locate the Compaq Elite controller
  2022. // This code is a rough approximation of the code in
  2023. // the Windows 95 detection module for the PCIC part.
  2024. //
  2025. addressSpace = 1; // port space
  2026. portAddress.LowPart = IoPortBase + 0x8000;
  2027. portAddress.HighPart = 0;
  2028. translated = HalTranslateBusAddress(Isa,
  2029. 0,
  2030. portAddress,
  2031. &addressSpace,
  2032. &cardAddress);
  2033. if (translated) {
  2034. if (!addressSpace) {
  2035. elcPort = MmMapIoSpace(cardAddress,
  2036. 2,
  2037. FALSE);
  2038. } else {
  2039. elcPort = (PUCHAR)(cardAddress.QuadPart);
  2040. }
  2041. //
  2042. // Save current index value.
  2043. //
  2044. saveBytes[0] = READ_PORT_UCHAR(elcPort);
  2045. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + PCIC_IDENT));
  2046. //
  2047. // Save data byte for the location that will be used
  2048. // for the test.
  2049. //
  2050. saveBytes[1] = READ_PORT_UCHAR(elcPort + 1);
  2051. //
  2052. // Check for an ELC
  2053. //
  2054. WRITE_PORT_UCHAR(elcPort+1, 0x55);
  2055. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + PCIC_IDENT));
  2056. dataByte = READ_PORT_UCHAR(elcPort+1);
  2057. if (dataByte == 0x55) {
  2058. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + PCIC_IDENT));
  2059. WRITE_PORT_UCHAR(elcPort+1, 0xaa);
  2060. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + PCIC_IDENT));
  2061. dataByte = READ_PORT_UCHAR(elcPort+1);
  2062. if (dataByte == 0xaa) {
  2063. //
  2064. // ELC found - initialize eaddr registers
  2065. //
  2066. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + 0));
  2067. WRITE_PORT_UCHAR(elcPort+1, 0);
  2068. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + 1));
  2069. WRITE_PORT_UCHAR(elcPort+1, 0);
  2070. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + 2));
  2071. WRITE_PORT_UCHAR(elcPort+1, 0x10);
  2072. PcmciaSetControllerType(DeviceExtension, PcmciaElcController);
  2073. }
  2074. }
  2075. //
  2076. // Restore the original values.
  2077. //
  2078. WRITE_PORT_UCHAR(elcPort, (UCHAR)(socket + PCIC_IDENT));
  2079. WRITE_PORT_UCHAR(elcPort+1, saveBytes[1]);
  2080. WRITE_PORT_UCHAR(elcPort, saveBytes[0]);
  2081. if (!addressSpace) {
  2082. MmUnmapIoSpace(elcPort, 2);
  2083. }
  2084. }
  2085. DeviceExtension->Configuration.UntranslatedPortAddress = (USHORT)IoPortBase;
  2086. DeviceExtension->Configuration.PortSize = 2;
  2087. DebugPrint((PCMCIA_DEBUG_DETECT, "Port %x Offset %x\n", port, socket));
  2088. status = STATUS_SUCCESS;
  2089. break;
  2090. }
  2091. default: {
  2092. DebugPrint((PCMCIA_DEBUG_DETECT,
  2093. "controller at (0x%x:0x%x) not found, returns %x\n",
  2094. portAddress.LowPart, socket, dataByte));
  2095. break;
  2096. }
  2097. }
  2098. Exit:
  2099. if (!NT_SUCCESS(status) && mapped) {
  2100. MmUnmapIoSpace(port, 2);
  2101. }
  2102. //
  2103. // Free up the allocated resources if any
  2104. //
  2105. if (resourcesAllocated) {
  2106. IoReportResourceForDetection(DeviceExtension->DriverObject,
  2107. NULL,
  2108. 0,
  2109. NULL,
  2110. NULL,
  2111. 0,
  2112. &conflict);
  2113. }
  2114. //
  2115. // Free up allocated memory if any
  2116. //
  2117. if (cmResourceList) {
  2118. ExFreePool(cmResourceList);
  2119. }
  2120. return status;
  2121. }
  2122. NTSTATUS
  2123. PcicBuildSocketList(
  2124. IN PFDO_EXTENSION DeviceExtension
  2125. )
  2126. /*++
  2127. Routine Description:
  2128. This routine looks out at the registers of the controller to see how
  2129. many sockets there are. For each socket, a SOCKET structure is allocated
  2130. and chained onto the SocketList pointer of the device extension.
  2131. Arguments:
  2132. DeviceExtension - pointer to the device extension
  2133. enumerated PDO
  2134. Return value:
  2135. STATUS_SUCCESS PCMCIA controller was found and socket structures were
  2136. succesfully initialized
  2137. STATUS_UNSUCCESSFUL otherwise
  2138. --*/
  2139. {
  2140. ULONG addressSpace;
  2141. NTSTATUS status;
  2142. PUCHAR port;
  2143. PSOCKET socketPtr;
  2144. PSOCKET previousSocket;
  2145. UCHAR dataByte;
  2146. UCHAR revisionByte;
  2147. USHORT socket;
  2148. UCHAR socketNumber = 0;
  2149. PAGED_CODE();
  2150. previousSocket = DeviceExtension->SocketList;
  2151. port = (PUCHAR)DeviceExtension->Configuration.UntranslatedPortAddress;
  2152. status = STATUS_UNSUCCESSFUL;
  2153. for (socket = 0; socket < 0xFF; socket += 0x40) {
  2154. dataByte = PcicReadController(port, socket, PCIC_IDENT);
  2155. revisionByte = dataByte;
  2156. switch (dataByte) {
  2157. case PCIC_REVISION:
  2158. case PCIC_REVISION2:
  2159. case PCIC_REVISION3: {
  2160. dataByte = PcicReadController(port, socket, PCIC_CARD_CHANGE);
  2161. if (dataByte & 0xf0) {
  2162. //
  2163. // Not a socket.
  2164. //
  2165. continue;
  2166. }
  2167. //
  2168. // Check for IBM 750
  2169. //
  2170. if (socket & 0x80) {
  2171. ULONG i;
  2172. UCHAR tmp;
  2173. //
  2174. // See if this socket shadows the socket without
  2175. // the sign bit.
  2176. //
  2177. tmp = PcicReadController(port, socket, PCIC_MEM_ADD4_STRT_L);
  2178. for (i = 0; i < 8; i++) {
  2179. //
  2180. // See if memory window 4 is the same on both sockets
  2181. //
  2182. if (PcicReadController(port, socket, (UCHAR) (PCIC_MEM_ADD4_STRT_L + i)) !=
  2183. PcicReadController(port, (USHORT) (socket & 0x7f), (UCHAR) (PCIC_MEM_ADD4_STRT_L + i))) {
  2184. break;
  2185. }
  2186. }
  2187. if (i == 8) {
  2188. //
  2189. // Currently window is the same - change the
  2190. // window at one of the socket offsets.
  2191. //
  2192. PcicWriteController(port, (USHORT) (socket & 0x7f), PCIC_MEM_ADD4_STRT_L, (UCHAR) ~tmp);
  2193. if (PcicReadController(port, socket, PCIC_MEM_ADD4_STRT_L) == (UCHAR) ~tmp) {
  2194. //
  2195. // The sockets are the same.
  2196. //
  2197. continue;
  2198. } else {
  2199. PcicWriteController(port, (USHORT) (socket & 0x7f), PCIC_MEM_ADD4_STRT_L, tmp);
  2200. }
  2201. }
  2202. }
  2203. socketPtr = ExAllocatePool(NonPagedPool, sizeof(SOCKET));
  2204. if (!socketPtr) {
  2205. return STATUS_INSUFFICIENT_RESOURCES;
  2206. }
  2207. RtlZeroMemory(socketPtr, sizeof(SOCKET));
  2208. socketPtr->DeviceExtension = DeviceExtension;
  2209. socketPtr->SocketFnPtr = &PcicSupportFns;
  2210. socketPtr->RegisterOffset = socket;
  2211. socketPtr->AddressPort = port;
  2212. socketPtr->Revision = revisionByte;
  2213. socketPtr->SocketNumber = socketNumber++;
  2214. if (previousSocket) {
  2215. previousSocket->NextSocket = socketPtr;
  2216. } else {
  2217. DeviceExtension->SocketList = socketPtr;
  2218. }
  2219. previousSocket = socketPtr;
  2220. status = STATUS_SUCCESS;
  2221. break;
  2222. }
  2223. default: {
  2224. break;
  2225. }
  2226. }
  2227. }
  2228. return status;
  2229. }