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.

1244 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. cb.c
  5. Abstract:
  6. This module contains the code that contains
  7. generic (Yenta compliant) cardbus controller
  8. specific initialization and other dispatches
  9. Author:
  10. Ravisankar Pudipeddi (ravisp) 1-Nov-97
  11. Neil Sandlin (neilsa) June 1 1999
  12. Environment:
  13. Kernel mode
  14. Revision History :
  15. Neil Sandlin (neilsa) 3-Mar-99
  16. new setpower routine interface
  17. --*/
  18. #include "pch.h"
  19. //
  20. // Function Prototypes
  21. //
  22. BOOLEAN
  23. CBInitializePcmciaSocket(
  24. PSOCKET Socket
  25. );
  26. NTSTATUS
  27. CBResetCard(
  28. PSOCKET Socket,
  29. PULONG pDelayTime
  30. );
  31. BOOLEAN
  32. CBDetectCardInSocket(
  33. IN PSOCKET Socket
  34. );
  35. BOOLEAN
  36. CBDetectCardChanged(
  37. IN PSOCKET Socket
  38. );
  39. BOOLEAN
  40. CBDetectCardStatus(
  41. IN PSOCKET Socket
  42. );
  43. BOOLEAN
  44. CBDetectReadyChanged(
  45. IN PSOCKET Socket
  46. );
  47. NTSTATUS
  48. CBGetPowerRequirements(
  49. IN PSOCKET Socket
  50. );
  51. BOOLEAN
  52. CBProcessConfigureRequest(
  53. IN PSOCKET Socket,
  54. IN PVOID ConfigRequest,
  55. IN PUCHAR Base
  56. );
  57. BOOLEAN
  58. CBEnableDisableCardDetectEvent(
  59. IN PSOCKET Socket,
  60. IN BOOLEAN Enable
  61. );
  62. ULONG
  63. CBGetIrqMask(
  64. IN PFDO_EXTENSION DeviceExtension
  65. );
  66. ULONG
  67. CBReadCardMemory(
  68. IN PPDO_EXTENSION PdoExtension,
  69. IN MEMORY_SPACE MemorySpace,
  70. IN ULONG Offset,
  71. IN PUCHAR Buffer,
  72. IN ULONG Length
  73. );
  74. ULONG
  75. CBWriteCardMemory(
  76. IN PPDO_EXTENSION PdoExtension,
  77. IN MEMORY_SPACE MemorySpace,
  78. IN ULONG Offset,
  79. IN PUCHAR Buffer,
  80. IN ULONG Length
  81. );
  82. VOID
  83. CBEnableDisableWakeupEvent(
  84. IN PSOCKET Socket,
  85. IN PPDO_EXTENSION PdoExtension,
  86. IN BOOLEAN Enable
  87. );
  88. BOOLEAN
  89. CBModifyMemoryWindow(
  90. IN PDEVICE_OBJECT Pdo,
  91. IN ULONGLONG HostBase,
  92. IN ULONGLONG CardBase OPTIONAL,
  93. IN BOOLEAN Enable,
  94. IN ULONG WindowSize OPTIONAL,
  95. IN UCHAR AccessSpeed OPTIONAL,
  96. IN UCHAR BusWidth OPTIONAL,
  97. IN BOOLEAN IsAttributeMemory OPTIONAL
  98. );
  99. BOOLEAN
  100. CBSetVpp(
  101. IN PDEVICE_OBJECT Pdo,
  102. IN UCHAR Vpp
  103. );
  104. BOOLEAN
  105. CBIsWriteProtected(
  106. IN PDEVICE_OBJECT Pdo
  107. );
  108. //
  109. // Function dispatch data block
  110. //
  111. PCMCIA_CTRL_BLOCK CBSupportFns = {
  112. CBInitializePcmciaSocket,
  113. CBResetCard,
  114. CBDetectCardInSocket,
  115. CBDetectCardChanged,
  116. CBDetectCardStatus,
  117. CBDetectReadyChanged,
  118. CBGetPowerRequirements,
  119. CBProcessConfigureRequest,
  120. CBEnableDisableCardDetectEvent,
  121. CBEnableDisableWakeupEvent,
  122. CBGetIrqMask,
  123. CBReadCardMemory,
  124. CBWriteCardMemory,
  125. CBModifyMemoryWindow,
  126. CBSetVpp,
  127. CBIsWriteProtected
  128. };
  129. extern PCMCIA_CTRL_BLOCK PcicSupportFns;
  130. //
  131. // Support functions
  132. //
  133. NTSTATUS
  134. CBBuildSocketList(
  135. IN PFDO_EXTENSION FdoExtension
  136. )
  137. /*++
  138. Routine Description:
  139. This routine builds the socket list for the given FDO. This is very
  140. simple for cardbus since there is always only 1 socket per controller.
  141. Arguments:
  142. FdoExtension - device extension for the controller
  143. Return Value:
  144. ntstatus
  145. --*/
  146. {
  147. PSOCKET socket = NULL;
  148. socket = ExAllocatePool(NonPagedPool, sizeof(SOCKET));
  149. if (!socket) {
  150. return STATUS_INSUFFICIENT_RESOURCES;
  151. }
  152. RtlZeroMemory(socket, sizeof(SOCKET));
  153. FdoExtension->SocketList = socket;
  154. socket->DeviceExtension = FdoExtension;
  155. socket->SocketFnPtr = &CBSupportFns;
  156. return STATUS_SUCCESS;
  157. }
  158. BOOLEAN
  159. CBInitializePcmciaSocket(
  160. PSOCKET Socket
  161. )
  162. /*++
  163. Routine Description:
  164. This routine will setup the controller into a state where the pcmcia support
  165. module will be able to issue commands to read device tuples from the
  166. cards in the sockets.
  167. Arguments:
  168. Socket - socket specific information
  169. Return Value:
  170. TRUE if successful
  171. FALSE if not successful
  172. --*/
  173. {
  174. UCHAR index;
  175. UCHAR reg;
  176. //
  177. // Initialize exca registers
  178. //
  179. if (!PcicSupportFns.PCBInitializePcmciaSocket(Socket)) {
  180. return FALSE;
  181. }
  182. //
  183. // Clear pending events
  184. //
  185. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0x0000000F);
  186. //
  187. // Since we may have just powered up, do a cvstest to make sure the socket registers
  188. // are valid
  189. //
  190. if (CBDetectCardInSocket(Socket) &&
  191. !IsDeviceFlagSet(Socket->DeviceExtension, PCMCIA_FDO_ON_DEBUG_PATH)) {
  192. CBIssueCvsTest(Socket);
  193. }
  194. return TRUE;
  195. }
  196. VOID
  197. CBIssueCvsTest(
  198. IN PSOCKET Socket
  199. )
  200. /*++
  201. Routine Description:
  202. This routine forces the controller to reinterrogate the card type and voltage
  203. requirements. This is to insure correct values read from the socket registers.
  204. Arguments:
  205. Socket - socket specific information
  206. Return Value:
  207. none
  208. --*/
  209. {
  210. ULONG dwSktMask;
  211. //
  212. // Issue CVSTEST to interrogate card
  213. // Disable interrupt temporarily because TI 12xx could cause spurious
  214. // interrupt when playing with SktForce register.
  215. //
  216. dwSktMask = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG);
  217. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, 0);
  218. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, SKTFORCE_CVSTEST);
  219. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwSktMask);
  220. // it would be nice to figure out a cleaner way to determine when interrogation is complete
  221. PcmciaWait(300000);
  222. }
  223. BOOLEAN
  224. CBEnableDeviceInterruptRouting(
  225. IN PSOCKET Socket
  226. )
  227. /*++
  228. Routine Description:
  229. Arguments:
  230. Socket - socket specific information
  231. Return Value:
  232. FALSE - irq to PCI
  233. TRUE - route to ISA
  234. --*/
  235. {
  236. USHORT word, orig_word;
  237. //
  238. // set up IRQ routing
  239. //
  240. GetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  241. orig_word = word;
  242. if (IsCardBusCardInSocket(Socket) ||
  243. (Is16BitCardInSocket(Socket) && IsSocketFlagSet(Socket, SOCKET_CB_ROUTE_R2_TO_PCI))) {
  244. //
  245. // route to PCI
  246. //
  247. word &= ~BCTRL_IRQROUTING_ENABLE;
  248. } else {
  249. //
  250. // route to ISA
  251. //
  252. word |= BCTRL_IRQROUTING_ENABLE;
  253. }
  254. if (orig_word != word) {
  255. SetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  256. }
  257. // return TRUE for routing to ISA
  258. return ((word & BCTRL_IRQROUTING_ENABLE) == BCTRL_IRQROUTING_ENABLE);
  259. }
  260. NTSTATUS
  261. CBResetCard(
  262. PSOCKET Socket,
  263. OUT PULONG pDelayTime
  264. )
  265. /*++
  266. Routine Description:
  267. Resets the pc-card in the given socket.
  268. Arguments:
  269. Socket - Pointer to the socket in which the pc-card resides
  270. pDelayTime - specifies delay (msec) to occur after the current phase
  271. Return value:
  272. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  273. other status values terminate sequence
  274. --*/
  275. {
  276. NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  277. UCHAR byte;
  278. USHORT word;
  279. PFDO_EXTENSION deviceExtension=Socket->DeviceExtension;
  280. if (Is16BitCardInSocket(Socket)) {
  281. if (Socket->CardResetPhase == 2) {
  282. GetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  283. //
  284. // R2 card. Turn off write posting
  285. //
  286. word &= ~BCTRL_WRITE_POSTING_ENABLE;
  287. SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  288. }
  289. status = PcicSupportFns.PCBResetCard(Socket, pDelayTime);
  290. return status;
  291. }
  292. switch(Socket->CardResetPhase) {
  293. case 1:
  294. //
  295. // Reset via bridge control
  296. //
  297. GetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  298. word |= BCTRL_CRST;
  299. SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  300. Socket->PowerData = (ULONG) word;
  301. *pDelayTime = CBResetWidthDelay;
  302. break;
  303. case 2:
  304. word = (USHORT)Socket->PowerData;
  305. word &= ~BCTRL_CRST;
  306. //
  307. // CardBus card. Turn on write posting
  308. //
  309. word |= BCTRL_WRITE_POSTING_ENABLE;
  310. word &= ~BCTRL_IRQROUTING_ENABLE;
  311. //
  312. // Hack: turn of write posting for topic95 to avoid hardware
  313. // bug with intel NICs
  314. //
  315. if (deviceExtension->ControllerType == PcmciaTopic95) {
  316. word &= ~BCTRL_WRITE_POSTING_ENABLE;
  317. }
  318. //
  319. // Stop bridge control reset
  320. //
  321. SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  322. *pDelayTime = CBResetSetupDelay;
  323. break;
  324. case 3:
  325. status = STATUS_SUCCESS;
  326. break;
  327. default:
  328. ASSERT(FALSE);
  329. status = STATUS_UNSUCCESSFUL;
  330. }
  331. return status;
  332. }
  333. BOOLEAN
  334. CBDetectCardInSocket(
  335. IN PSOCKET Socket
  336. )
  337. /*++
  338. Routine Description:
  339. This routine will determine if a card is in the socket
  340. Arguments:
  341. Socket -- Socket information
  342. Return Value:
  343. TRUE if card is present.
  344. --*/
  345. {
  346. ULONG state;
  347. BOOLEAN cardPresent=FALSE;
  348. //
  349. // Read the CARDBUS status register to see if the card is in there.
  350. //
  351. state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG);
  352. if ((state & SKTSTATE_CCD_MASK) == 0) {
  353. cardPresent = TRUE;
  354. }
  355. return(cardPresent);
  356. }
  357. BOOLEAN
  358. CBDetectCardChanged(
  359. IN PSOCKET Socket
  360. )
  361. /*++
  362. Routine Description:
  363. This routine will determine if socket's card insertion status has changed.
  364. Arguments:
  365. Socket -- Socket info.
  366. Return Value:
  367. TRUE if card insertion status has changed.
  368. --*/
  369. {
  370. BOOLEAN retVal = FALSE;
  371. ULONG tmp;
  372. //
  373. // Read SOCKET Event register to see if CD's changed
  374. //
  375. tmp = CBReadSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG);
  376. if ((tmp & SKTEVENT_CCD_MASK) != 0) {
  377. //
  378. // Yes they did..
  379. // first clear the interrupt
  380. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CCD_MASK);
  381. retVal = TRUE;
  382. }
  383. return retVal;
  384. }
  385. BOOLEAN
  386. CBDetectCardStatus(
  387. IN PSOCKET Socket
  388. )
  389. /*++
  390. Routine Description:
  391. This routine will determine if socket's card insertion status has changed.
  392. Arguments:
  393. Socket -- Socket info.
  394. Return Value:
  395. TRUE if card insertion status has changed.
  396. --*/
  397. {
  398. BOOLEAN retVal = FALSE;
  399. ULONG tmp;
  400. if (Is16BitCardInSocket(Socket)) {
  401. // NOTE: UNIMPLEMENTED: may need to do something for 16-bit cards
  402. return FALSE;
  403. }
  404. //
  405. // Read SOCKET Event register to see if CD's changed
  406. //
  407. tmp = CBReadSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG);
  408. if ((tmp & SKTEVENT_CSTSCHG) != 0) {
  409. //
  410. // Yes they did..
  411. // first clear the interrupt
  412. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CSTSCHG);
  413. retVal = TRUE;
  414. }
  415. return retVal;
  416. }
  417. BOOLEAN
  418. CBDetectReadyChanged(
  419. IN PSOCKET Socket
  420. )
  421. {
  422. return(PcicSupportFns.PCBDetectReadyChanged(Socket));
  423. }
  424. BOOLEAN
  425. CBProcessConfigureRequest(
  426. IN PSOCKET Socket,
  427. IN PCARD_REQUEST Request,
  428. IN PUCHAR Base
  429. )
  430. {
  431. BOOLEAN bStatus = TRUE;
  432. USHORT word;
  433. //
  434. // Shouldn't this check for 16-bit cards?
  435. //
  436. switch (Request->RequestType) {
  437. case IRQ_REQUEST:
  438. if (CBEnableDeviceInterruptRouting(Socket)) {
  439. bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base);
  440. }
  441. break;
  442. case DECONFIGURE_REQUEST:
  443. bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base);
  444. GetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  445. word |= BCTRL_IRQROUTING_ENABLE;
  446. SetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
  447. break;
  448. default:
  449. bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base);
  450. }
  451. return bStatus;
  452. }
  453. BOOLEAN
  454. CBEnableDisableCardDetectEvent(
  455. IN PSOCKET Socket,
  456. IN BOOLEAN Enable
  457. )
  458. /*++
  459. Routine Description:
  460. Enable card detect/card ready interrupt.
  461. Arguments:
  462. Socket - socket information
  463. Enable - if TRUE, CSC interrupt is enabled,
  464. if FALSE, it is disabled
  465. Return Value:
  466. TRUE if successful
  467. FALSE if not successful
  468. --*/
  469. {
  470. switch (Enable) {
  471. case TRUE: {
  472. UCHAR byte;
  473. //
  474. // Only if TI 1130/1250?
  475. // Route through PCI interrupts
  476. byte = PcicReadSocket(Socket, PCIC_INTERRUPT);
  477. byte |= IGC_INTR_ENABLE;
  478. PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
  479. //
  480. // Clear the bits in Socket Event Register
  481. //
  482. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0xF);
  483. //
  484. // Enable card-detect interrupt in Socket Mask Register
  485. //
  486. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, SKTMSK_CCD);
  487. break;
  488. }
  489. case FALSE: {
  490. ULONG oldValue;
  491. //
  492. // Clear the bits in Socket Event Register
  493. //
  494. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0xF);
  495. //
  496. // Disable card-detect interrupt in Socket Mask Register
  497. //
  498. oldValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG);
  499. oldValue &= ~SKTMSK_CCD;
  500. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, oldValue);
  501. break;
  502. }
  503. }
  504. return TRUE;
  505. }
  506. VOID
  507. CBEnableDisableWakeupEvent(
  508. IN PSOCKET Socket,
  509. IN PPDO_EXTENSION PdoExtension,
  510. IN BOOLEAN Enable
  511. )
  512. /*++
  513. Routine Description:
  514. Arguments:
  515. Socket - socket information
  516. Enable - if TRUE, interrupt is enabled,
  517. if FALSE, it is disabled
  518. Return Value:
  519. none
  520. --*/
  521. {
  522. ULONG dwValue;
  523. switch (Enable) {
  524. case TRUE: {
  525. //
  526. // Enable card-status interrupt in Socket Mask Register
  527. //
  528. dwValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG);
  529. dwValue |= SKTMSK_CSTSCHG;
  530. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwValue);
  531. if (PdoExtension && IsCardBusCard(PdoExtension)) {
  532. UCHAR capptr;
  533. ULONG powercaps;
  534. //
  535. // HACK ALERT - should be handled by PCI.SYS
  536. // Have a look to see if PME_ENABLE has been turned on by PCI. If not then we do it.
  537. //
  538. GetPciConfigSpace(PdoExtension, CBCFG_CAPPTR, &capptr, sizeof(capptr));
  539. if (capptr) {
  540. GetPciConfigSpace(PdoExtension, capptr, &powercaps, sizeof(powercaps));
  541. if ((powercaps & 0xff) == 1) {
  542. GetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  543. if (!(powercaps & PME_EN)) {
  544. powercaps |= PME_EN;
  545. DebugPrint((PCMCIA_DEBUG_POWER, "pdo %08x setting PME_EN!\n", PdoExtension->DeviceObject));
  546. SetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  547. }
  548. }
  549. }
  550. }
  551. break;
  552. }
  553. case FALSE: {
  554. PFDO_EXTENSION fdoExtension = Socket->DeviceExtension;
  555. UCHAR capptr;
  556. ULONG powercaps, newPowercaps;
  557. //
  558. // Check to see if PMESTAT is on... It shouldn't be. If it is, it probably means
  559. // that the BIOS did not notify us that the device did the wake, and PCI didn't
  560. // get a chance to clear the condition. This is really a BIOS bug.
  561. //
  562. if (PdoExtension && IsCardBusCard(PdoExtension)) {
  563. GetPciConfigSpace(PdoExtension, CBCFG_CAPPTR, &capptr, sizeof(capptr));
  564. if (capptr) {
  565. GetPciConfigSpace(PdoExtension, capptr, &powercaps, sizeof(powercaps));
  566. if ((powercaps & 0xff) == 1) {
  567. GetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  568. if (powercaps & (PME_STAT | PME_EN)) {
  569. DebugPrint((PCMCIA_DEBUG_POWER, "pdo %08x PME bits still set! stat=%x en=%x\n",
  570. PdoExtension->DeviceObject, ((powercaps&PME_STAT)!=0), ((powercaps&PME_EN)!=0)));
  571. powercaps |= PME_STAT;
  572. powercaps &= ~PME_EN;
  573. SetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  574. }
  575. }
  576. }
  577. }
  578. GetPciConfigSpace(fdoExtension, CFGSPACE_CAPPTR, &capptr, sizeof(capptr));
  579. if (capptr) {
  580. GetPciConfigSpace(fdoExtension, capptr, &powercaps, sizeof(powercaps));
  581. if ((powercaps & 0xff) == 1) {
  582. //
  583. // Clear PMESTAT, if on
  584. //
  585. GetPciConfigSpace(fdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  586. if (powercaps & PME_STAT) {
  587. DebugPrint((PCMCIA_DEBUG_POWER, "fdo %08x PME_STAT still set!\n", fdoExtension->DeviceObject));
  588. SetPciConfigSpace(fdoExtension, capptr+4, &powercaps, sizeof(powercaps));
  589. }
  590. }
  591. }
  592. //
  593. // Disable card-status interrupt in Socket Mask Register
  594. //
  595. dwValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG);
  596. dwValue &= ~SKTMSK_CSTSCHG;
  597. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwValue);
  598. //
  599. // Clear the event in Socket Event Register
  600. //
  601. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CSTSCHG);
  602. break;
  603. }
  604. }
  605. }
  606. ULONG
  607. CBGetIrqMask(
  608. IN PFDO_EXTENSION DeviceExtension
  609. )
  610. {
  611. return(PcicSupportFns.PCBGetIrqMask(DeviceExtension));
  612. }
  613. ULONG
  614. CBReadCardMemory(
  615. IN PPDO_EXTENSION PdoExtension,
  616. IN MEMORY_SPACE MemorySpace,
  617. IN ULONG Offset,
  618. IN PUCHAR Buffer,
  619. IN ULONG Length
  620. )
  621. {
  622. ULONG bytesCopied = 0;
  623. if (!IsCardBusCard(PdoExtension)) {
  624. return(PcicSupportFns.PCBReadCardMemory(PdoExtension,
  625. MemorySpace,
  626. Offset,
  627. Buffer,
  628. Length));
  629. }
  630. switch(MemorySpace){
  631. case PCCARD_PCI_CONFIGURATION_SPACE:
  632. bytesCopied = GetPciConfigSpace(PdoExtension, Offset, Buffer, Length);
  633. break;
  634. case PCCARD_CARDBUS_BAR0:
  635. case PCCARD_CARDBUS_BAR1:
  636. case PCCARD_CARDBUS_BAR2:
  637. case PCCARD_CARDBUS_BAR3:
  638. case PCCARD_CARDBUS_BAR4:
  639. case PCCARD_CARDBUS_BAR5:
  640. break;
  641. case PCCARD_CARDBUS_ROM:
  642. bytesCopied = PdoExtension->PciBusInterface.GetBusData(
  643. PdoExtension->PciBusInterface.Context,
  644. PCI_WHICHSPACE_ROM, Buffer, Offset, Length);
  645. break;
  646. }
  647. return bytesCopied;
  648. }
  649. ULONG
  650. CBWriteCardMemory(
  651. IN PPDO_EXTENSION PdoExtension,
  652. IN MEMORY_SPACE MemorySpace,
  653. IN ULONG Offset,
  654. IN PUCHAR Buffer,
  655. IN ULONG Length
  656. )
  657. {
  658. if (IsCardBusCard(PdoExtension)) {
  659. return 0;
  660. }
  661. return(PcicSupportFns.PCBWriteCardMemory(PdoExtension,
  662. MemorySpace,
  663. Offset,
  664. Buffer,
  665. Length));
  666. }
  667. BOOLEAN
  668. CBModifyMemoryWindow(
  669. IN PDEVICE_OBJECT Pdo,
  670. IN ULONGLONG HostBase,
  671. IN ULONGLONG CardBase OPTIONAL,
  672. IN BOOLEAN Enable,
  673. IN ULONG WindowSize OPTIONAL,
  674. IN UCHAR AccessSpeed OPTIONAL,
  675. IN UCHAR BusWidth OPTIONAL,
  676. IN BOOLEAN IsAttributeMemory OPTIONAL
  677. )
  678. {
  679. return(PcicSupportFns.PCBModifyMemoryWindow(Pdo,
  680. HostBase,
  681. CardBase,
  682. Enable,
  683. WindowSize,
  684. AccessSpeed,
  685. BusWidth,
  686. IsAttributeMemory));
  687. }
  688. BOOLEAN
  689. CBSetVpp(
  690. IN PDEVICE_OBJECT Pdo,
  691. IN UCHAR Vpp
  692. )
  693. {
  694. return(PcicSupportFns.PCBSetVpp(Pdo, Vpp));
  695. }
  696. BOOLEAN
  697. CBIsWriteProtected(
  698. IN PDEVICE_OBJECT Pdo
  699. )
  700. {
  701. return(PcicSupportFns.PCBIsWriteProtected(Pdo));
  702. }
  703. NTSTATUS
  704. CBGetPowerRequirements(
  705. IN PSOCKET Socket
  706. )
  707. /*++
  708. Routine Description:
  709. Look at the hardware to see what it says the card needs, and update the
  710. socket structure accordingly.
  711. Arguments:
  712. Socket - the socket to examine
  713. Return Value:
  714. n/a
  715. --*/
  716. {
  717. ULONG state;
  718. UCHAR voltage;
  719. //
  720. // Check what voltages are supported by this card
  721. //
  722. state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG);
  723. if (!(state & (SKTSTATE_5VCARD | SKTSTATE_3VCARD))) {
  724. ULONG dwSktMask;
  725. //
  726. // neither 5v or 3v is set... try cvstest
  727. // Disable interrupt temporarily because TI 12xx could cause spurious
  728. // interrupt when playing with SktForce register.
  729. //
  730. dwSktMask = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG);
  731. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, 0);
  732. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, SKTFORCE_CVSTEST);
  733. state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG);
  734. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwSktMask);
  735. }
  736. state &= (SKTSTATE_5VCARD | SKTSTATE_3VCARD);
  737. if (state == 0) {
  738. return STATUS_UNSUCCESSFUL;
  739. }
  740. if (state == (SKTSTATE_5VCARD | SKTSTATE_3VCARD)) {
  741. //
  742. // both are specified. Check for preference
  743. //
  744. voltage = IsDeviceFlagSet(Socket->DeviceExtension, PCMCIA_FDO_PREFER_3V) ? 33 : 50;
  745. } else {
  746. voltage = (state & SKTSTATE_5VCARD) ? 50 : 33;
  747. }
  748. Socket->Vcc = Socket->Vpp1 = Socket->Vpp2 = voltage;
  749. return STATUS_SUCCESS;
  750. }
  751. NTSTATUS
  752. CBSetPower(
  753. IN PSOCKET Socket,
  754. IN BOOLEAN Enable,
  755. OUT PULONG pDelayTime
  756. )
  757. /*++
  758. Routine Description:
  759. Set power to the specified socket.
  760. Arguments:
  761. Socket - the socket to set
  762. Enable - TRUE means to set power - FALSE is to turn it off.
  763. pDelayTime - specifies delay (msec) to occur after the current phase
  764. Return Value:
  765. STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
  766. other status values terminate sequence
  767. --*/
  768. {
  769. NTSTATUS status;
  770. ULONG oldPower, state, newPower;
  771. ULONG vcc, vpp;
  772. UCHAR tmp;
  773. USHORT word;
  774. switch(Socket->PowerPhase) {
  775. case 1:
  776. if (Enable) {
  777. //
  778. // Turn on the power
  779. //
  780. switch(Socket->Vcc) {
  781. case 50: vcc = SKTPOWER_VCC_050V; break;
  782. case 33: vcc = SKTPOWER_VCC_033V; break;
  783. default: vcc = SKTPOWER_VCC_OFF;
  784. }
  785. switch(Socket->Vpp1) {
  786. case 120: vpp = SKTPOWER_VPP_120V; break;
  787. case 50: vpp = SKTPOWER_VPP_050V; break;
  788. case 33: vpp = SKTPOWER_VPP_033V; break;
  789. default: vpp = SKTPOWER_VPP_OFF;
  790. }
  791. } else {
  792. //
  793. // Power off
  794. //
  795. vcc = SKTPOWER_VCC_OFF;
  796. vpp = SKTPOWER_VPP_OFF;
  797. //
  798. // Disable output before powering down to avoid spurious signals
  799. // from reaching the card
  800. //
  801. if (Is16BitCardInSocket(Socket)) {
  802. tmp = PcicReadSocket(Socket, PCIC_PWR_RST);
  803. if (tmp & PC_OUTPUT_ENABLE) {
  804. tmp &= ~PC_OUTPUT_ENABLE;
  805. PcicWriteSocket(Socket, PCIC_PWR_RST, tmp);
  806. }
  807. }
  808. }
  809. oldPower = CBReadSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG);
  810. newPower = vcc | vpp;
  811. newPower|= oldPower & ~(SKTPOWER_VPP_CONTROL |SKTPOWER_VCC_CONTROL);
  812. if (newPower != oldPower) {
  813. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG, newPower);
  814. //
  815. // When power is enabled always stall to give the PCCARD
  816. // a chance to react.
  817. //
  818. *pDelayTime = PcicStallPower;
  819. Socket->PowerData = newPower;
  820. status = STATUS_MORE_PROCESSING_REQUIRED;
  821. } else {
  822. //
  823. // Indicate that nothing was done
  824. //
  825. status = STATUS_INVALID_DEVICE_STATE;
  826. }
  827. break;
  828. case 2:
  829. case 3:
  830. case 4:
  831. newPower = Socket->PowerData;
  832. //
  833. // Try to apply the required power setting a few times.
  834. // We bail if it doesn't succeed after the given number of tries
  835. //
  836. state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG);
  837. if (state & SKTSTATE_BADVCCREQ) {
  838. DebugPrint((PCMCIA_DEBUG_INFO, "skt %08 CBSetPower: Bad vcc request\n", Socket));
  839. //
  840. // Clear the status bits & try again
  841. //
  842. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, 0);
  843. CBWriteSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG, newPower);
  844. *pDelayTime = PcicStallPower;
  845. status = STATUS_MORE_PROCESSING_REQUIRED;
  846. } else {
  847. status = STATUS_SUCCESS;
  848. if (Is16BitCardInSocket(Socket)) {
  849. tmp = PcicReadSocket(Socket, PCIC_PWR_RST);
  850. if (newPower & SKTPOWER_VCC_CONTROL) {
  851. //
  852. // Vcc is on..
  853. //
  854. tmp |= PC_OUTPUT_ENABLE | PC_AUTOPWR_ENABLE;
  855. PcicWriteSocket(Socket, PCIC_PWR_RST, tmp);
  856. *pDelayTime = PcicStallPower;
  857. } else {
  858. //
  859. // power off..
  860. //
  861. tmp &= ~(PC_OUTPUT_ENABLE | PC_AUTOPWR_ENABLE);
  862. PcicWriteSocket(Socket, PCIC_PWR_RST, tmp);
  863. }
  864. }
  865. }
  866. break;
  867. default:
  868. DebugPrint((PCMCIA_DEBUG_FAIL, "skt %08 CBSetPower: Final retry failed - bad vcc\n", Socket));
  869. ASSERT(FALSE);
  870. status = STATUS_UNSUCCESSFUL;
  871. }
  872. return status;
  873. }
  874. BOOLEAN
  875. CBSetWindowPage(
  876. IN PSOCKET Socket,
  877. USHORT Index,
  878. UCHAR Page
  879. )
  880. {
  881. ASSERT(Index <= 4);
  882. PcicWriteSocket(Socket, (UCHAR) (PCIC_PAGE_REG + Index), Page);
  883. return TRUE;
  884. }
  885. ULONG
  886. CBReadSocketRegister(
  887. IN PSOCKET Socket,
  888. IN UCHAR Register
  889. )
  890. /*++
  891. Routine Description
  892. Returns the contents of the specified Cardbus socket register for the
  893. given socket
  894. Arguments
  895. Socket - Pointer to the socket
  896. Register - Cardbus socket register
  897. Return Value
  898. Contents of the register
  899. --*/
  900. {
  901. ULONG data;
  902. ASSERT (CardBus(Socket));
  903. ASSERT (Socket->DeviceExtension->CardBusSocketRegisterBase != NULL);
  904. ASSERT ((Register&3) == 0);
  905. //
  906. // Sanity check in case controller wasn't started
  907. // or if the register is not dword aligned
  908. //
  909. if ((Socket->DeviceExtension->CardBusSocketRegisterBase) && ((Register&3) == 0)) {
  910. data = READ_REGISTER_ULONG((PULONG) (Socket->DeviceExtension->CardBusSocketRegisterBase+Register));
  911. } else {
  912. data = 0xFFFFFFFF;
  913. }
  914. return data;
  915. }
  916. VOID
  917. CBWriteSocketRegister(
  918. IN PSOCKET Socket,
  919. IN UCHAR Register,
  920. IN ULONG Data
  921. )
  922. /*++
  923. Routine Description
  924. Writes the supplied value to the Cardbus socket register for the
  925. given socket
  926. Arguments
  927. Socket - Pointer to the socket
  928. Register - Cardbus socket register
  929. Data - Value to be written to the register
  930. Return Value
  931. --*/
  932. {
  933. ASSERT (CardBus(Socket));
  934. ASSERT (Socket->DeviceExtension->CardBusSocketRegisterBase != NULL);
  935. ASSERT ((Register&3) == 0);
  936. //
  937. // Sanity check in case controller wasn't started
  938. // or if the register is not dword aligned
  939. //
  940. if ((Socket->DeviceExtension->CardBusSocketRegisterBase) && ((Register&3) == 0)) {
  941. WRITE_REGISTER_ULONG((PULONG) (Socket->DeviceExtension->CardBusSocketRegisterBase+Register), Data);
  942. }
  943. }