Leaked source code of windows server 2003
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.

1433 lines
33 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. toshiba.c
  5. Abstract:
  6. This module supplies functions that control the Toshiba SD controller.
  7. Based on the Toshiba "Pelican3"
  8. Author(s):
  9. Neil Sandlin (neilsa) Jan 1 2002
  10. Revisions:
  11. --*/
  12. #include "pch.h"
  13. #include "toshiba.h"
  14. //
  15. // Internal References
  16. //
  17. VOID
  18. ToshibaInitializeController(
  19. IN PFDO_EXTENSION FdoExtension
  20. );
  21. VOID
  22. ToshibaInitializeFunction(
  23. IN PFDO_EXTENSION FdoExtension,
  24. IN PPDO_EXTENSION PdoExtension
  25. );
  26. ULONG
  27. ToshibaGetPendingEvents(
  28. IN PFDO_EXTENSION FdoExtension
  29. );
  30. VOID
  31. ToshibaEnableEvent(
  32. IN PFDO_EXTENSION FdoExtension,
  33. IN ULONG EventMask
  34. );
  35. VOID
  36. ToshibaDisableEvent(
  37. IN PFDO_EXTENSION FdoExtension,
  38. IN ULONG EventMask
  39. );
  40. VOID
  41. ToshibaAcknowledgeEvent(
  42. IN PFDO_EXTENSION FdoExtension,
  43. IN ULONG EventMask
  44. );
  45. NTSTATUS
  46. ToshibaSetPower(
  47. IN PFDO_EXTENSION FdoExtension,
  48. IN BOOLEAN Enable,
  49. OUT PULONG pDelayTime
  50. );
  51. NTSTATUS
  52. ToshibaResetHost(
  53. IN PFDO_EXTENSION FdoExtension,
  54. IN UCHAR Phase,
  55. OUT PULONG pDelayTime
  56. );
  57. VOID
  58. ToshibaSetLED(
  59. IN PFDO_EXTENSION FdoExtension,
  60. IN BOOLEAN Enable
  61. );
  62. VOID
  63. ToshibaSetFunctionType(
  64. IN PFDO_EXTENSION FdoExtension,
  65. IN UCHAR FunctionType
  66. );
  67. BOOLEAN
  68. ToshibaDetectCardInSocket(
  69. IN PFDO_EXTENSION FdoExtension
  70. );
  71. BOOLEAN
  72. ToshibaIsWriteProtected(
  73. IN PFDO_EXTENSION FdoExtension
  74. );
  75. NTSTATUS
  76. ToshibaCheckStatus(
  77. IN PFDO_EXTENSION FdoExtension
  78. );
  79. NTSTATUS
  80. ToshibaSDCommand(
  81. IN PFDO_EXTENSION FdoExtension,
  82. IN PSD_WORK_PACKET WorkPacket
  83. );
  84. NTSTATUS
  85. ToshibaSDGetResponse(
  86. IN PFDO_EXTENSION FdoExtension,
  87. IN PSD_WORK_PACKET WorkPacket
  88. );
  89. VOID
  90. ToshibaStartBlockOperation(
  91. IN PFDO_EXTENSION FdoExtension
  92. );
  93. VOID
  94. ToshibaSetBlockParameters(
  95. IN PFDO_EXTENSION FdoExtension,
  96. IN USHORT SectorCount
  97. );
  98. VOID
  99. ToshibaEndBlockOperation(
  100. IN PFDO_EXTENSION FdoExtension
  101. );
  102. VOID
  103. ToshibaReadDataPort(
  104. IN PFDO_EXTENSION FdoExtension,
  105. IN PUCHAR Buffer,
  106. IN ULONG Length
  107. );
  108. VOID
  109. ToshibaWriteDataPort(
  110. IN PFDO_EXTENSION FdoExtension,
  111. IN PUCHAR Buffer,
  112. IN ULONG Length
  113. );
  114. UCHAR
  115. ToshibaReadRegisterUchar(
  116. IN PFDO_EXTENSION FdoExtension,
  117. IN USHORT Register
  118. );
  119. USHORT
  120. ToshibaReadRegisterUshort(
  121. IN PFDO_EXTENSION FdoExtension,
  122. IN USHORT Register
  123. );
  124. VOID
  125. ToshibaWriteRegisterUshort(
  126. IN PFDO_EXTENSION FdoExtension,
  127. IN USHORT Register,
  128. IN USHORT Data
  129. );
  130. ULONG
  131. ToshibaReadRegisterUlong(
  132. IN PFDO_EXTENSION FdoExtension,
  133. IN USHORT Register
  134. );
  135. VOID
  136. ToshibaWriteRegisterUlong(
  137. IN PFDO_EXTENSION FdoExtension,
  138. IN USHORT Register,
  139. IN ULONG Data
  140. );
  141. //
  142. // Internal Data
  143. //
  144. SD_FUNCTION_BLOCK ToshibaSupportFns = {
  145. ToshibaInitializeController,
  146. ToshibaInitializeFunction,
  147. ToshibaSetPower,
  148. ToshibaResetHost,
  149. ToshibaSetLED,
  150. ToshibaSetFunctionType,
  151. ToshibaDetectCardInSocket,
  152. ToshibaIsWriteProtected,
  153. ToshibaCheckStatus,
  154. ToshibaSDCommand,
  155. ToshibaSDGetResponse,
  156. ToshibaStartBlockOperation,
  157. ToshibaSetBlockParameters,
  158. ToshibaEndBlockOperation,
  159. ToshibaReadDataPort,
  160. ToshibaWriteDataPort,
  161. ToshibaEnableEvent,
  162. ToshibaDisableEvent,
  163. ToshibaGetPendingEvents,
  164. ToshibaAcknowledgeEvent
  165. };
  166. VOID
  167. DebugDumpRegs(
  168. IN PFDO_EXTENSION FdoExtension
  169. )
  170. {
  171. #if DBG
  172. if (SdbusDebugMask & SDBUS_DEBUG_DUMP_REGS) {
  173. USHORT i,j;
  174. USHORT buffer[8];
  175. USHORT offset;
  176. USHORT count = 0;
  177. ULONG skip = 0x03000000;
  178. USHORT index;
  179. offset = 0;
  180. for (j = 0; j < 8; j++) {
  181. for (i = 0; i < 8; i++) {
  182. index = offset + (i*2);
  183. if (skip & (1 << (index/2))) {
  184. buffer[i] = 0xFEFE;
  185. } else {
  186. buffer[i] = ToshibaReadRegisterUshort(FdoExtension, index);
  187. }
  188. count++;
  189. }
  190. DebugPrint((SDBUS_DEBUG_DUMP_REGS, "%04x: %04x %04x %04x %04x-%04x %04x %04x %04x\n", offset,
  191. buffer[0], buffer[1], buffer[2], buffer[3],
  192. buffer[4], buffer[5], buffer[6], buffer[7]));
  193. offset += 16;
  194. if (offset == 0x40) {
  195. offset = 0x100;
  196. }
  197. }
  198. }
  199. #endif
  200. }
  201. // ---------------------------------------------------------------
  202. // External interface routines
  203. // ---------------------------------------------------------------
  204. VOID
  205. ToshibaInitializeController(
  206. IN PFDO_EXTENSION FdoExtension
  207. )
  208. /*++
  209. Routine Description:
  210. Arguments:
  211. Return value:
  212. --*/
  213. {
  214. USHORT data;
  215. UCHAR configData;
  216. DebugPrint((SDBUS_DEBUG_DEVICE, "ToshibaInitializeController\n"));
  217. //
  218. // The Toshiba device appears to need this in order to function at all
  219. //
  220. // SetPciConfigSpace(FdoExtension, 0x40, &configData, 1);
  221. configData = 0x1F; // Clock enable
  222. SetPciConfigSpace(FdoExtension, TOCFG_CLOCK_CONTROL, &configData, 1);
  223. configData = 0x08; // Power control
  224. SetPciConfigSpace(FdoExtension, TOCFG_POWER_CTL1, &configData, 1);
  225. data = ToshibaReadRegisterUshort(FdoExtension, TOMHC_HOST_CORE_VERSION);
  226. DebugPrint((SDBUS_DEBUG_DEVICE, "TOMHC_HOST_CORE_VERSION - %x\n",
  227. data));
  228. ToshibaWriteRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK, 0xFFFFFFFF);
  229. ToshibaWriteRegisterUlong(FdoExtension, TOIOHC_INTERRUPT_MASK, 0xFFFFFFFF);
  230. //
  231. // start the controller off in memory mode
  232. //
  233. ToshibaSetFunctionType(FdoExtension, SDBUS_FUNCTION_TYPE_MEMORY);
  234. }
  235. VOID
  236. ToshibaInitializeFunction(
  237. IN PFDO_EXTENSION FdoExtension,
  238. IN PPDO_EXTENSION PdoExtension
  239. )
  240. /*++
  241. Routine Description:
  242. Arguments:
  243. Return value:
  244. --*/
  245. {
  246. ULONG sdRca = FdoExtension->RelativeAddr;
  247. DebugPrint((SDBUS_DEBUG_DEVICE, "ToshibaInitializeFunction(%d)\n", PdoExtension->Function));
  248. if (PdoExtension->Function == 8) {
  249. //
  250. // Memory function
  251. //
  252. } else {
  253. }
  254. }
  255. NTSTATUS
  256. ToshibaSetPower(
  257. IN PFDO_EXTENSION FdoExtension,
  258. IN BOOLEAN Enable,
  259. OUT OPTIONAL PULONG pDelayTime
  260. )
  261. /*++
  262. Routine Description:
  263. Arguments:
  264. Return value:
  265. --*/
  266. {
  267. UCHAR reg;
  268. UCHAR mask;
  269. UCHAR data;
  270. GetPciConfigSpace(FdoExtension, TOCFG_POWER_CTL2, &reg, 1);
  271. mask = 0x03;
  272. reg &= ~mask;
  273. if (Enable) {
  274. reg |= TO_POWER_33;
  275. }
  276. SetPciConfigSpace(FdoExtension, TOCFG_POWER_CTL2, &reg, 1);
  277. if (pDelayTime) {
  278. *pDelayTime = 0x5dc;
  279. }
  280. return STATUS_SUCCESS;
  281. }
  282. NTSTATUS
  283. ToshibaResetHost(
  284. IN PFDO_EXTENSION FdoExtension,
  285. IN UCHAR Phase,
  286. OUT PULONG pDelayTime
  287. )
  288. {
  289. NTSTATUS status;
  290. UCHAR data;
  291. switch(Phase) {
  292. case 0:
  293. data = 0x0B;
  294. SetPciConfigSpace(FdoExtension, TOCFG_CLOCK_CONTROL, &data, 1);
  295. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_SOFTWARE_RESET, 0);
  296. *pDelayTime = 0x5dc;
  297. status = STATUS_MORE_PROCESSING_REQUIRED;
  298. break;
  299. case 1:
  300. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_SOFTWARE_RESET, 1);
  301. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_SOFTWARE_RESET, 0);
  302. *pDelayTime = 0x5dc;
  303. status = STATUS_MORE_PROCESSING_REQUIRED;
  304. break;
  305. case 2:
  306. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_SOFTWARE_RESET, 1);
  307. // ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CLOCK_AND_WAIT_CONTROL,
  308. // ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CLOCK_AND_WAIT_CONTROL) & 0xFCFC);
  309. //
  310. // turn off IOHC clock enable and card wait
  311. //
  312. ToshibaWriteRegisterUshort(FdoExtension,
  313. TOIOHC_CLOCK_AND_WAIT_CONTROL,
  314. ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CLOCK_AND_WAIT_CONTROL) &
  315. ~(TOIO_CWCF_CLOCK_ENABLE | TOIO_CWCF_CARD_WAIT));
  316. //
  317. // turn off MHC clock enable
  318. //
  319. ToshibaWriteRegisterUshort(FdoExtension,
  320. TOMHC_CARD_CLOCK_CTL,
  321. ToshibaReadRegisterUshort(FdoExtension, TOMHC_CARD_CLOCK_CTL) &
  322. ~TO_CCC_CLOCK_ENABLE);
  323. //
  324. // Turn on MHC clock enable
  325. //
  326. ToshibaWriteRegisterUshort(FdoExtension,
  327. TOMHC_CARD_CLOCK_CTL,
  328. // (TO_CCC_CLOCK_ENABLE | TO_CCC_CLOCK_DIVISOR_128));
  329. TO_CCC_CLOCK_ENABLE);
  330. //
  331. // Turn on IOHC clock enable and card wait
  332. //
  333. ToshibaWriteRegisterUshort(FdoExtension,
  334. TOIOHC_CLOCK_AND_WAIT_CONTROL,
  335. (TOIO_CWCF_CLOCK_ENABLE | TOIO_CWCF_CARD_WAIT));
  336. data = 0x1F;
  337. SetPciConfigSpace(FdoExtension, TOCFG_CLOCK_CONTROL, &data, 1);
  338. *pDelayTime = 0x3e8;
  339. status = STATUS_MORE_PROCESSING_REQUIRED;
  340. break;
  341. case 3:
  342. status = STATUS_SUCCESS;
  343. break;
  344. }
  345. return status;
  346. }
  347. VOID
  348. ToshibaSetLED(
  349. IN PFDO_EXTENSION FdoExtension,
  350. IN BOOLEAN Enable
  351. )
  352. {
  353. }
  354. //
  355. // Event handling functions
  356. //
  357. ULONG
  358. EventMaskToHardwareMask(
  359. ULONG EventMask
  360. )
  361. {
  362. ULONG hardwareMask = 0;
  363. if (EventMask & SDBUS_EVENT_INSERTION) {
  364. hardwareMask |= TO_EVT_CARD_INSERTION;
  365. }
  366. if (EventMask & SDBUS_EVENT_REMOVAL) {
  367. hardwareMask |= TO_EVT_CARD_REMOVAL;
  368. }
  369. if (EventMask & SDBUS_EVENT_CARD_RESPONSE) {
  370. hardwareMask |= TO_EVT_RESPONSE;
  371. }
  372. if (EventMask & SDBUS_EVENT_CARD_RW_END) {
  373. hardwareMask |= TO_EVT_RW_END;
  374. }
  375. if (EventMask & SDBUS_EVENT_BUFFER_EMPTY) {
  376. hardwareMask |= TO_EVT_BUFFER_EMPTY;
  377. }
  378. if (EventMask & SDBUS_EVENT_BUFFER_FULL) {
  379. hardwareMask |= TO_EVT_BUFFER_FULL;
  380. }
  381. return hardwareMask;
  382. }
  383. ULONG
  384. HardwareMaskToEventMask(
  385. ULONG HardwareMask
  386. )
  387. {
  388. ULONG eventMask = 0;
  389. if (HardwareMask & TO_EVT_CARD_INSERTION) {
  390. eventMask |= SDBUS_EVENT_INSERTION;
  391. }
  392. if (HardwareMask & TO_EVT_CARD_REMOVAL) {
  393. eventMask |= SDBUS_EVENT_REMOVAL;
  394. }
  395. if (HardwareMask & TO_EVT_RESPONSE) {
  396. eventMask |= SDBUS_EVENT_CARD_RESPONSE;
  397. }
  398. if (HardwareMask & TO_EVT_RW_END) {
  399. eventMask |= SDBUS_EVENT_CARD_RW_END;
  400. }
  401. if (HardwareMask & TO_EVT_BUFFER_EMPTY) {
  402. eventMask |= SDBUS_EVENT_BUFFER_EMPTY;
  403. }
  404. if (HardwareMask & TO_EVT_BUFFER_FULL) {
  405. eventMask |= SDBUS_EVENT_BUFFER_FULL;
  406. }
  407. return eventMask;
  408. }
  409. VOID
  410. ToshibaEnableEvent(
  411. IN PFDO_EXTENSION FdoExtension,
  412. IN ULONG EventMask
  413. )
  414. /*++
  415. Routine Description:
  416. Arguments:
  417. Return value:
  418. --*/
  419. {
  420. ULONG data;
  421. ULONG cardEvents, ctlrEvents, ioCardEvent;
  422. ULONG mask;
  423. DebugPrint((SDBUS_DEBUG_EVENT, "EnableEvent: %08x\n", EventMask));
  424. FdoExtension->CurrentlyEnabledEvents |= EventMask;
  425. ctlrEvents = EventMask & (SDBUS_EVENT_INSERTION | SDBUS_EVENT_REMOVAL);
  426. EventMask &= ~(SDBUS_EVENT_INSERTION | SDBUS_EVENT_REMOVAL);
  427. ioCardEvent = EventMask & SDBUS_EVENT_CARD_INTERRUPT;
  428. EventMask &= ~SDBUS_EVENT_CARD_INTERRUPT;
  429. cardEvents = EventMask;
  430. mask = EventMaskToHardwareMask(cardEvents);
  431. if (mask) {
  432. data = ToshibaReadRegisterUlong(FdoExtension, FdoExtension->InterruptMaskReg);
  433. data &= ~mask;
  434. ToshibaWriteRegisterUlong(FdoExtension, FdoExtension->InterruptMaskReg, data);
  435. }
  436. mask = EventMaskToHardwareMask(ctlrEvents);
  437. if (mask) {
  438. data = ToshibaReadRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK);
  439. data &= ~mask;
  440. ToshibaWriteRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK, data);
  441. }
  442. if (ioCardEvent) {
  443. USHORT usData;
  444. usData = ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL);
  445. usData &= ~TOIO_CICF_CARD_INTMASK;
  446. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL, usData);
  447. }
  448. }
  449. VOID
  450. ToshibaDisableEvent(
  451. IN PFDO_EXTENSION FdoExtension,
  452. IN ULONG EventMask
  453. )
  454. /*++
  455. Routine Description:
  456. Arguments:
  457. Return value:
  458. --*/
  459. {
  460. ULONG data;
  461. ULONG cardEvents, ctlrEvents, ioCardEvent;
  462. ULONG mask;
  463. FdoExtension->CurrentlyEnabledEvents &= ~EventMask;
  464. ctlrEvents = EventMask & (SDBUS_EVENT_INSERTION | SDBUS_EVENT_REMOVAL);
  465. EventMask &= ~(SDBUS_EVENT_INSERTION | SDBUS_EVENT_REMOVAL);
  466. ioCardEvent = EventMask & SDBUS_EVENT_CARD_INTERRUPT;
  467. EventMask &= ~SDBUS_EVENT_CARD_INTERRUPT;
  468. cardEvents = EventMask;
  469. mask = EventMaskToHardwareMask(cardEvents);
  470. if (mask) {
  471. data = ToshibaReadRegisterUlong(FdoExtension, FdoExtension->InterruptMaskReg);
  472. data |= mask;
  473. ToshibaWriteRegisterUlong(FdoExtension, FdoExtension->InterruptMaskReg, data);
  474. }
  475. mask = EventMaskToHardwareMask(ctlrEvents);
  476. if (mask) {
  477. data = ToshibaReadRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK);
  478. data |= mask;
  479. ToshibaWriteRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK, data);
  480. }
  481. if (ioCardEvent) {
  482. USHORT usData;
  483. usData = ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL);
  484. usData |= TOIO_CICF_CARD_INTMASK;
  485. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL, usData);
  486. }
  487. }
  488. ULONG
  489. ToshibaGetPendingEvents(
  490. IN PFDO_EXTENSION FdoExtension
  491. )
  492. /*++
  493. Routine Description:
  494. Arguments:
  495. Return value:
  496. --*/
  497. {
  498. ULONG statusMask, eventMask;
  499. ULONG mhcEvent = 0, iohcEvent = 0, iocardEvent = 0;
  500. USHORT usData;
  501. //
  502. // The Pelican3 has interrupt status spread out everywhere. First try
  503. // the memory host controller
  504. //
  505. statusMask = ToshibaReadRegisterUlong(FdoExtension, TOMHC_CARD_STATUS);
  506. eventMask = ToshibaReadRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK);
  507. // turn off undefined bits
  508. statusMask &= 0x837F031D;
  509. // turn off bits that are masked
  510. statusMask &= ~eventMask;
  511. mhcEvent = HardwareMaskToEventMask(statusMask);
  512. if (statusMask && (mhcEvent == 0)) {
  513. // got an interrupt, but we don't know what type
  514. ASSERT(FALSE);
  515. eventMask |= statusMask;
  516. ToshibaWriteRegisterUlong(FdoExtension, TOMHC_INTERRUPT_MASK, eventMask);
  517. }
  518. //
  519. // Now try the IO host controller
  520. //
  521. if (!mhcEvent) {
  522. statusMask = ToshibaReadRegisterUlong(FdoExtension, TOIOHC_CARD_STATUS);
  523. eventMask = ToshibaReadRegisterUlong(FdoExtension, TOIOHC_INTERRUPT_MASK);
  524. // turn off undefined bits
  525. statusMask &= 0xA37F0005;
  526. // turn off bits that are masked
  527. statusMask &= ~eventMask;
  528. iohcEvent = HardwareMaskToEventMask(statusMask);
  529. if (statusMask && (iohcEvent == 0)) {
  530. // got an interrupt, but we don't know what type
  531. ASSERT(FALSE);
  532. eventMask |= statusMask;
  533. ToshibaWriteRegisterUlong(FdoExtension, TOIOHC_INTERRUPT_MASK, eventMask);
  534. }
  535. //
  536. // get IO card interrupt
  537. //
  538. usData = ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL);
  539. if ((usData & TOIO_CICF_CARD_INTERRUPT) && ((usData & TOIO_CICF_CARD_INTMASK)==0)) {
  540. if (ToshibaDetectCardInSocket(FdoExtension)) {
  541. iocardEvent = SDBUS_EVENT_CARD_INTERRUPT;
  542. } else {
  543. //
  544. // the card is gone, this must be spurious
  545. //
  546. usData |= TOIO_CICF_CARD_INTMASK;
  547. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL, usData);
  548. }
  549. }
  550. }
  551. return mhcEvent | iohcEvent | iocardEvent;
  552. }
  553. VOID
  554. ToshibaAcknowledgeEvent(
  555. IN PFDO_EXTENSION FdoExtension,
  556. IN ULONG EventMask
  557. )
  558. /*++
  559. Routine Description:
  560. Arguments:
  561. Return value:
  562. --*/
  563. {
  564. ULONG hardwareMask = EventMaskToHardwareMask(EventMask);
  565. ULONG data;
  566. USHORT interruptMaskReg, cardStatusReg;
  567. if (EventMask & SDBUS_EVENT_CARD_INTERRUPT) {
  568. //
  569. // No need to clear io card IRQ, just reenable it
  570. //
  571. USHORT usData;
  572. usData = ToshibaReadRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL);
  573. usData &= ~TOIO_CICF_CARD_INTMASK;
  574. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CARD_INTERRUPT_CONTROL, usData);
  575. return;
  576. }
  577. if (EventMask & (SDBUS_EVENT_INSERTION | SDBUS_EVENT_REMOVAL)) {
  578. interruptMaskReg = TOMHC_INTERRUPT_MASK;
  579. cardStatusReg = TOMHC_CARD_STATUS;
  580. } else {
  581. interruptMaskReg = FdoExtension->InterruptMaskReg;
  582. cardStatusReg = FdoExtension->CardStatusReg;
  583. }
  584. //
  585. // Clear event in status register
  586. //
  587. data = ToshibaReadRegisterUlong(FdoExtension, cardStatusReg);
  588. DebugPrint((SDBUS_DEBUG_EVENT, "AcknowledgeEvent: %08x - cardstatus %08x\n", EventMask, data));
  589. data &= ~hardwareMask;
  590. ToshibaWriteRegisterUlong(FdoExtension, cardStatusReg, data);
  591. #if DBG
  592. data = ToshibaReadRegisterUlong(FdoExtension, cardStatusReg);
  593. DebugPrint((SDBUS_DEBUG_EVENT, "AcknowledgeEvent: new cardstatus %08x\n", data));
  594. #endif
  595. //
  596. // Reenable event
  597. //
  598. FdoExtension->CurrentlyEnabledEvents |= EventMask;
  599. data = ToshibaReadRegisterUlong(FdoExtension, interruptMaskReg);
  600. data &= ~hardwareMask;
  601. ToshibaWriteRegisterUlong(FdoExtension, interruptMaskReg, data);
  602. }
  603. VOID
  604. ToshibaSetFunctionType(
  605. IN PFDO_EXTENSION FdoExtension,
  606. IN UCHAR FunctionType
  607. )
  608. {
  609. ULONG currentlyEnabledEvents = FdoExtension->CurrentlyEnabledEvents;
  610. if (FunctionType == FdoExtension->FunctionType) {
  611. return;
  612. }
  613. //
  614. // The pelican3 implements these event masks in two places, so disable and reenable them
  615. //
  616. if (currentlyEnabledEvents) {
  617. ToshibaDisableEvent(FdoExtension, currentlyEnabledEvents);
  618. }
  619. switch(FunctionType) {
  620. case SDBUS_FUNCTION_TYPE_MEMORY:
  621. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_CLOCK_AND_WAIT_CONTROL, 0x100);
  622. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_TRANSACTION_CONTROL,
  623. ToshibaReadRegisterUshort(FdoExtension, TOIOHC_TRANSACTION_CONTROL) & 0xEFFF);
  624. FdoExtension->ArgumentReg = TOMHC_ARGUMENT;
  625. FdoExtension->CmdReg = TOMHC_COMMAND;
  626. FdoExtension->CardStatusReg = TOMHC_CARD_STATUS;
  627. FdoExtension->ResponseReg = TOMHC_RESPONSE;
  628. FdoExtension->InterruptMaskReg = TOMHC_INTERRUPT_MASK;
  629. break;
  630. case SDBUS_FUNCTION_TYPE_IO:
  631. FdoExtension->ArgumentReg = TOIOHC_ARGUMENT;
  632. FdoExtension->CmdReg = TOIOHC_COMMAND;
  633. FdoExtension->CardStatusReg = TOIOHC_CARD_STATUS;
  634. FdoExtension->ResponseReg = TOIOHC_RESPONSE_0;
  635. FdoExtension->InterruptMaskReg = TOIOHC_INTERRUPT_MASK;
  636. break;
  637. default:
  638. ASSERT(FALSE);
  639. }
  640. if (currentlyEnabledEvents) {
  641. ToshibaEnableEvent(FdoExtension, currentlyEnabledEvents);
  642. }
  643. FdoExtension->FunctionType = FunctionType;
  644. }
  645. BOOLEAN
  646. ToshibaDetectCardInSocket(
  647. IN PFDO_EXTENSION FdoExtension
  648. )
  649. /*++
  650. Routine Description:
  651. Arguments:
  652. Return value:
  653. --*/
  654. {
  655. USHORT data;
  656. data = ToshibaReadRegisterUshort(FdoExtension, TOMHC_CARD_STATUS);
  657. return !((data & TO_STS_CARD_PRESENT) == 0);
  658. }
  659. BOOLEAN
  660. ToshibaIsWriteProtected(
  661. IN PFDO_EXTENSION FdoExtension
  662. )
  663. {
  664. USHORT data;
  665. data = ToshibaReadRegisterUshort(FdoExtension, TOMHC_CARD_STATUS);
  666. return ((data & TO_STS_WRITE_PROTECT) == 0);
  667. }
  668. #if 0
  669. BOOLEAN
  670. ToshibaClearStatus(
  671. IN PFDO_EXTENSION FdoExtension
  672. )
  673. /*++
  674. Routine Description:
  675. Arguments:
  676. Return value:
  677. --*/
  678. {
  679. //
  680. // This was stuff that was done before the first SEND... it is unclear how
  681. // much should be moved to the send
  682. //
  683. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_TRANSACTION_CONTROL,
  684. ToshibaReadRegisterUshort(FdoExtension, TOIOHC_TRANSACTION_CONTROL) & 0xEFFF);
  685. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_BUFFER_CTL_AND_ERR,
  686. ToshibaReadRegisterUshort(FdoExtension, TOMHC_BUFFER_CTL_AND_ERR) & 0x7D00);
  687. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_CARD_STATUS,
  688. ToshibaReadRegisterUshort(FdoExtension, TOMHC_CARD_STATUS) & 0xFFFA);
  689. return TRUE;
  690. }
  691. #endif
  692. NTSTATUS
  693. ToshibaCheckStatus(
  694. IN PFDO_EXTENSION FdoExtension
  695. )
  696. /*++
  697. Routine Description:
  698. Arguments:
  699. Return value:
  700. --*/
  701. {
  702. ULONG cardStatus;
  703. ULONG errorStatus;
  704. NTSTATUS status = STATUS_SUCCESS;
  705. DebugDumpRegs(FdoExtension);
  706. cardStatus = ToshibaReadRegisterUlong(FdoExtension, FdoExtension->CardStatusReg);
  707. if (FdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
  708. errorStatus = cardStatus & (TOMHC_BCE_CMD_INDEX_ERROR |
  709. TOMHC_BCE_CRC_ERROR |
  710. TOMHC_BCE_END_BIT_ERROR |
  711. TOMHC_BCE_CMD_TIMEOUT |
  712. TOMHC_BCE_DATA_TIMEOUT |
  713. TOMHC_BCE_FIFO_OVERFLOW |
  714. TOMHC_BCE_FIFO_UNDERFLOW |
  715. TOMHC_BCE_ILLEGAL_ACCESS);
  716. } else {
  717. errorStatus = cardStatus & (TOMHC_BCE_CMD_INDEX_ERROR |
  718. // TOMHC_BCE_CRC_ERROR |
  719. TOMHC_BCE_END_BIT_ERROR |
  720. TOMHC_BCE_CMD_TIMEOUT |
  721. TOMHC_BCE_DATA_TIMEOUT |
  722. TOMHC_BCE_FIFO_OVERFLOW |
  723. TOMHC_BCE_FIFO_UNDERFLOW |
  724. TOMHC_BCE_ILLEGAL_ACCESS);
  725. }
  726. if (errorStatus) {
  727. DebugPrint((SDBUS_DEBUG_WARNING, "CheckStatus detected Error! status = %08x\n", errorStatus));
  728. //ISSUE: NEED TO IMPLEMENT: I/O error handling
  729. ToshibaWriteRegisterUlong(FdoExtension, FdoExtension->CardStatusReg, cardStatus & ~errorStatus);
  730. // possibilities:
  731. // STATUS_PARITY_ERROR
  732. // STATUS_DEVICE_DATA_ERROR
  733. // STATUS_DEVICE_POWER_FAILURE
  734. // STATUS_DEVICE_NOT_READY
  735. // STATUS_IO_TIMEOUT
  736. // STATUS_INVALID_DEVICE_STATE
  737. // STATUS_IO_DEVICE_ERROR
  738. // STATUS_DEVICE_PROTOCOL_ERROR
  739. // STATUS_DEVICE_REMOVED
  740. // STATUS_POWER_STATE_INVALID
  741. status = STATUS_IO_DEVICE_ERROR;
  742. }
  743. return status;
  744. }
  745. NTSTATUS
  746. ToshibaSDCommand(
  747. IN PFDO_EXTENSION FdoExtension,
  748. IN PSD_WORK_PACKET WorkPacket
  749. )
  750. /*++
  751. Routine Description:
  752. Arguments:
  753. Return value:
  754. --*/
  755. {
  756. USHORT cmdWord;
  757. ULONG Flags = WorkPacket->Flags;
  758. NTSTATUS status;
  759. ToshibaWriteRegisterUlong(FdoExtension, FdoExtension->ArgumentReg, WorkPacket->Argument);
  760. cmdWord = WorkPacket->Cmd;
  761. switch (WorkPacket->ResponseType) {
  762. case SDCMD_RESP_NONE:
  763. cmdWord |= TOMHC_CMD_RESP_NONE;
  764. break;
  765. case SDCMD_RESP_1:
  766. case SDCMD_RESP_5:
  767. case SDCMD_RESP_6:
  768. cmdWord |= 0x400;
  769. break;
  770. case SDCMD_RESP_2:
  771. cmdWord |= 0x600;
  772. break;
  773. case SDCMD_RESP_3:
  774. case SDCMD_RESP_4:
  775. cmdWord |= 0x700;
  776. break;
  777. case SDCMD_RESP_1B:
  778. case SDCMD_RESP_5B:
  779. cmdWord |= 0x500;
  780. break;
  781. default:
  782. ASSERT(FALSE);
  783. return STATUS_UNSUCCESSFUL;
  784. }
  785. //
  786. // Add flags
  787. //
  788. if (Flags & SDCMDF_ACMD) {
  789. cmdWord |= TOMHC_CMD_ACMD;
  790. }
  791. if (Flags & SDCMDF_DATA) {
  792. cmdWord |= TOMHC_CMD_NTDT;
  793. }
  794. if (Flags & SDCMDF_MULTIBLOCK) {
  795. cmdWord |= TOMHC_CMD_MSSL;
  796. }
  797. if (Flags & SDCMDF_READ) {
  798. cmdWord |= TOMHC_CMD_RWDI;
  799. }
  800. //
  801. // Write Cmd and flags to command register
  802. //
  803. DebugPrint((SDBUS_DEBUG_DEVICE, "SEND: Cmd%d (0x%04x) arg = 0x%08x\n", WorkPacket->Cmd, cmdWord, WorkPacket->Argument));
  804. ToshibaWriteRegisterUshort(FdoExtension, FdoExtension->CmdReg, cmdWord);
  805. return STATUS_SUCCESS;
  806. }
  807. NTSTATUS
  808. ToshibaSDGetResponse(
  809. IN PFDO_EXTENSION FdoExtension,
  810. IN PSD_WORK_PACKET WorkPacket
  811. )
  812. /*++
  813. Routine Description:
  814. Arguments:
  815. Return value:
  816. --*/
  817. {
  818. // ULONG cardStatus;
  819. UCHAR i;
  820. PUCHAR pRespPtr;
  821. NTSTATUS status = STATUS_SUCCESS;
  822. pRespPtr = (PUCHAR) WorkPacket->ResponseBuffer;
  823. for (i=0; i<SDBUS_RESPONSE_BUFFER_LENGTH; i++) {
  824. *pRespPtr++ = ToshibaReadRegisterUchar(FdoExtension, FdoExtension->ResponseReg+i);
  825. }
  826. return status;
  827. }
  828. VOID
  829. ToshibaStartBlockOperation(
  830. IN PFDO_EXTENSION FdoExtension
  831. )
  832. {
  833. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_CARD_CLOCK_CTL, 0x100);
  834. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_OPTIONS, 0x40e0);
  835. }
  836. VOID
  837. ToshibaSetBlockParameters(
  838. IN PFDO_EXTENSION FdoExtension,
  839. IN USHORT Length
  840. )
  841. {
  842. if (FdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
  843. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_CARD_TRANSFER_LENGTH, 512);
  844. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_STOP_INTERNAL, 0x100);
  845. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_TRANSFER_SECTOR_COUNT, Length);
  846. } else {
  847. ToshibaWriteRegisterUshort(FdoExtension, TOIOHC_TRANSFER_DATA_LEN_SELECT, Length);
  848. }
  849. }
  850. VOID
  851. ToshibaEndBlockOperation(
  852. IN PFDO_EXTENSION FdoExtension
  853. )
  854. {
  855. ToshibaWriteRegisterUshort(FdoExtension, TOMHC_BUFFER_CTL_AND_ERR, 0);
  856. }
  857. VOID
  858. ToshibaReadDataPort(
  859. IN PFDO_EXTENSION FdoExtension,
  860. IN PUCHAR Buffer,
  861. IN ULONG Length
  862. )
  863. /*++
  864. Routine Description:
  865. The data port must be accessed maintaining DWORD alignment. So for example:
  866. IN DWORD 130
  867. IN DWORD 130
  868. is the same as
  869. IN USHORT 130
  870. IN USHORT 132
  871. IN UCHAR 130
  872. IN UCHAR 131
  873. IN UCHAR 132
  874. IN UCHAR 133
  875. Arguments:
  876. Return value:
  877. --*/
  878. {
  879. USHORT i;
  880. ULONG dwordCount, wordCount, byteCount;
  881. PULONG ulBuffer = (PULONG) Buffer;
  882. PUSHORT usBuffer;
  883. USHORT port = (FdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) ? TOMHC_DATA_PORT :
  884. TOIOHC_DATA_TRANSFER;
  885. PUCHAR portAddress = ((PUCHAR)FdoExtension->HostRegisterBase + port);
  886. dwordCount = Length / 4;
  887. wordCount = (Length % 4) / 2;
  888. byteCount = (Length % 4) % 2;
  889. for (i = 0; i < dwordCount; i++) {
  890. READ_REGISTER_BUFFER_ULONG((PULONG) portAddress, ulBuffer, 1);
  891. ulBuffer++;
  892. }
  893. if (wordCount) {
  894. usBuffer = (PUSHORT) ulBuffer;
  895. ASSERT(wordCount == 1);
  896. READ_REGISTER_BUFFER_USHORT((PUSHORT) portAddress, usBuffer, 1);
  897. usBuffer++;
  898. }
  899. if (byteCount) {
  900. PUCHAR ucBuffer = (PUCHAR) usBuffer;
  901. ASSERT(byteCount == 1);
  902. // maintain byte order within ULONG dataport
  903. portAddress++;
  904. portAddress++;
  905. READ_REGISTER_BUFFER_UCHAR((PUCHAR) portAddress, ucBuffer, 1);
  906. }
  907. }
  908. VOID
  909. ToshibaWriteDataPort(
  910. IN PFDO_EXTENSION FdoExtension,
  911. IN PUCHAR Buffer,
  912. IN ULONG Length
  913. )
  914. {
  915. USHORT i;
  916. ULONG dwordCount, wordCount, byteCount;
  917. PULONG ulBuffer = (PULONG) Buffer;
  918. PUSHORT usBuffer;
  919. USHORT port = (FdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) ? TOMHC_DATA_PORT :
  920. TOIOHC_DATA_TRANSFER;
  921. PUCHAR portAddress = ((PUCHAR)FdoExtension->HostRegisterBase + port);
  922. dwordCount = Length / 4;
  923. wordCount = (Length % 4) / 2;
  924. byteCount = (Length % 4) % 2;
  925. for (i = 0; i < dwordCount; i++) {
  926. WRITE_REGISTER_BUFFER_ULONG((PULONG) portAddress, ulBuffer, 1);
  927. ulBuffer++;
  928. }
  929. if (wordCount) {
  930. usBuffer = (PUSHORT) ulBuffer;
  931. ASSERT(wordCount == 1);
  932. WRITE_REGISTER_BUFFER_USHORT((PUSHORT) portAddress, usBuffer, 1);
  933. usBuffer++;
  934. }
  935. if (byteCount) {
  936. PUCHAR ucBuffer = (PUCHAR) usBuffer;
  937. ASSERT(byteCount == 1);
  938. // maintain byte order within ULONG dataport
  939. portAddress++;
  940. portAddress++;
  941. WRITE_REGISTER_BUFFER_UCHAR((PUCHAR) portAddress, ucBuffer, 1);
  942. }
  943. }
  944. // ---------------------------------------------------------------
  945. // Internal routines
  946. // ---------------------------------------------------------------
  947. UCHAR
  948. ToshibaReadRegisterUchar(
  949. IN PFDO_EXTENSION FdoExtension,
  950. IN USHORT Register
  951. )
  952. /*++
  953. Routine Description:
  954. This routine will read a byte from the specified socket EXCA register
  955. Arguments:
  956. Socket -- Pointer to the socket from which we should read
  957. Register -- The register to be read
  958. Return Value:
  959. The data returned from the port.
  960. --*/
  961. {
  962. UCHAR byte;
  963. //
  964. // Sanity check in case controller wasn't started
  965. //
  966. if (FdoExtension->HostRegisterBase) {
  967. byte = READ_REGISTER_UCHAR((PUCHAR) ((PUCHAR)FdoExtension->HostRegisterBase + Register));
  968. } else {
  969. byte = 0xff;
  970. }
  971. return byte;
  972. }
  973. USHORT
  974. ToshibaReadRegisterUshort(
  975. IN PFDO_EXTENSION FdoExtension,
  976. IN USHORT Register
  977. )
  978. /*++
  979. Routine Description:
  980. This routine will read a byte from the specified socket EXCA register
  981. Arguments:
  982. Socket -- Pointer to the socket from which we should read
  983. Register -- The register to be read
  984. Return Value:
  985. The data returned from the port.
  986. --*/
  987. {
  988. USHORT word;
  989. //
  990. // Sanity check in case controller wasn't started
  991. //
  992. if (FdoExtension->HostRegisterBase) {
  993. word = READ_REGISTER_USHORT((PUSHORT) ((PUCHAR)FdoExtension->HostRegisterBase + Register));
  994. } else {
  995. word = 0xff;
  996. }
  997. return word;
  998. }
  999. VOID
  1000. ToshibaWriteRegisterUshort(
  1001. IN PFDO_EXTENSION FdoExtension,
  1002. IN USHORT Register,
  1003. IN USHORT Data
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. This routine will read a byte from the specified socket EXCA register
  1008. Arguments:
  1009. Socket -- Pointer to the socket from which we should read
  1010. Register -- The register to be read
  1011. Return Value:
  1012. The data returned from the port.
  1013. --*/
  1014. {
  1015. //
  1016. // Sanity check in case controller wasn't started
  1017. //
  1018. if (FdoExtension->HostRegisterBase) {
  1019. WRITE_REGISTER_USHORT((PUSHORT) ((PUCHAR)FdoExtension->HostRegisterBase + Register), Data);
  1020. }
  1021. }
  1022. ULONG
  1023. ToshibaReadRegisterUlong(
  1024. IN PFDO_EXTENSION FdoExtension,
  1025. IN USHORT Register
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. This routine will read a byte from the specified socket EXCA register
  1030. Arguments:
  1031. Socket -- Pointer to the socket from which we should read
  1032. Register -- The register to be read
  1033. Return Value:
  1034. The data returned from the port.
  1035. --*/
  1036. {
  1037. ULONG dword;
  1038. //
  1039. // Sanity check in case controller wasn't started
  1040. //
  1041. if (FdoExtension->HostRegisterBase) {
  1042. dword = READ_REGISTER_ULONG((PULONG) ((PUCHAR)FdoExtension->HostRegisterBase + Register));
  1043. } else {
  1044. dword = 0xff;
  1045. }
  1046. return dword;
  1047. }
  1048. VOID
  1049. ToshibaWriteRegisterUlong(
  1050. IN PFDO_EXTENSION FdoExtension,
  1051. IN USHORT Register,
  1052. IN ULONG Data
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. This routine will read a byte from the specified socket EXCA register
  1057. Arguments:
  1058. Socket -- Pointer to the socket from which we should read
  1059. Register -- The register to be read
  1060. Return Value:
  1061. The data returned from the port.
  1062. --*/
  1063. {
  1064. //
  1065. // Sanity check in case controller wasn't started
  1066. //
  1067. if (FdoExtension->HostRegisterBase) {
  1068. WRITE_REGISTER_ULONG((PULONG) ((PUCHAR)FdoExtension->HostRegisterBase + Register), Data);
  1069. }
  1070. }