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.

1010 lines
26 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. swecp.c
  5. Abstract:
  6. Enhanced Capabilities Port (ECP)
  7. This module contains the code to perform all ECP related tasks (including
  8. ECP Software and ECP Hardware modes.)
  9. Author:
  10. Tim Wells (WESTTEK) - April 16, 1997
  11. Environment:
  12. Kernel mode
  13. Revision History :
  14. --*/
  15. #include "pch.h"
  16. #include "ecp.h"
  17. BOOLEAN
  18. ParIsEcpSwWriteSupported(
  19. IN PDEVICE_EXTENSION Extension
  20. );
  21. BOOLEAN
  22. ParIsEcpSwReadSupported(
  23. IN PDEVICE_EXTENSION Extension
  24. );
  25. NTSTATUS
  26. ParEnterEcpSwMode(
  27. IN PDEVICE_EXTENSION Extension,
  28. IN BOOLEAN DeviceIdRequest
  29. );
  30. VOID
  31. ParCleanupSwEcpPort(
  32. IN PDEVICE_EXTENSION Extension
  33. );
  34. VOID
  35. ParTerminateEcpMode(
  36. IN PDEVICE_EXTENSION Extension
  37. );
  38. NTSTATUS
  39. ParEcpSetAddress(
  40. IN PDEVICE_EXTENSION Extension,
  41. IN UCHAR Address
  42. );
  43. NTSTATUS
  44. ParEcpSwWrite(
  45. IN PDEVICE_EXTENSION Extension,
  46. IN PVOID Buffer,
  47. IN ULONG BufferSize,
  48. OUT PULONG BytesTransferred
  49. );
  50. NTSTATUS
  51. ParEcpSwRead(
  52. IN PDEVICE_EXTENSION Extension,
  53. IN PVOID Buffer,
  54. IN ULONG BufferSize,
  55. OUT PULONG BytesTransferred
  56. );
  57. NTSTATUS
  58. ParEcpForwardToReverse(
  59. IN PDEVICE_EXTENSION Extension
  60. );
  61. NTSTATUS
  62. ParEcpReverseToForward(
  63. IN PDEVICE_EXTENSION Extension
  64. );
  65. BOOLEAN
  66. ParIsEcpSwWriteSupported(
  67. IN PDEVICE_EXTENSION Extension
  68. )
  69. /*++
  70. Routine Description:
  71. This routine determines whether or not ECP mode is suported
  72. in the write direction by trying to negotiate when asked.
  73. Arguments:
  74. Extension - The device extension.
  75. Return Value:
  76. BOOLEAN.
  77. --*/
  78. {
  79. NTSTATUS Status;
  80. if (Extension->BadProtocolModes & ECP_SW)
  81. return FALSE;
  82. if (Extension->ProtocolModesSupported & ECP_SW)
  83. return TRUE;
  84. Status = ParEnterEcpSwMode (Extension, FALSE);
  85. ParTerminateEcpMode (Extension);
  86. if (NT_SUCCESS(Status)) {
  87. Extension->ProtocolModesSupported |= ECP_SW;
  88. return TRUE;
  89. }
  90. return FALSE;
  91. }
  92. BOOLEAN
  93. ParIsEcpSwReadSupported(
  94. IN PDEVICE_EXTENSION Extension
  95. )
  96. /*++
  97. Routine Description:
  98. This routine determines whether or not ECP mode is suported
  99. in the read direction (need to be able to float the data register
  100. drivers in order to do byte wide reads) by trying negotiate when asked.
  101. Arguments:
  102. Extension - The device extension.
  103. Return Value:
  104. BOOLEAN.
  105. --*/
  106. {
  107. NTSTATUS Status;
  108. if (!(Extension->HardwareCapabilities & PPT_ECP_PRESENT) &&
  109. !(Extension->HardwareCapabilities & PPT_BYTE_PRESENT)) {
  110. // Only use ECP Software in the reverse direction if an
  111. // ECR is present or we know that we can put the data register into Byte mode.
  112. return FALSE;
  113. }
  114. if (Extension->BadProtocolModes & ECP_SW)
  115. return FALSE;
  116. if (Extension->ProtocolModesSupported & ECP_SW)
  117. return TRUE;
  118. // Must use SWECP Enter and Terminate for this test.
  119. // Internel state machines will fail otherwise. --dvrh
  120. Status = ParEnterEcpSwMode (Extension, FALSE);
  121. ParTerminateEcpMode (Extension);
  122. if (NT_SUCCESS(Status)) {
  123. Extension->ProtocolModesSupported |= ECP_SW;
  124. return TRUE;
  125. }
  126. return FALSE;
  127. }
  128. NTSTATUS
  129. ParEnterEcpSwMode(
  130. IN PDEVICE_EXTENSION Extension,
  131. IN BOOLEAN DeviceIdRequest
  132. )
  133. /*++
  134. Routine Description:
  135. This routine performs 1284 negotiation with the peripheral to the
  136. ECP mode protocol.
  137. Arguments:
  138. Controller - Supplies the port address.
  139. DeviceIdRequest - Supplies whether or not this is a request for a device
  140. id.
  141. Return Value:
  142. STATUS_SUCCESS - Successful negotiation.
  143. otherwise - Unsuccessful negotiation.
  144. --*/
  145. {
  146. NTSTATUS Status = STATUS_SUCCESS;
  147. if ( Extension->ModeSafety == SAFE_MODE ) {
  148. if (DeviceIdRequest) {
  149. Status = IeeeEnter1284Mode (Extension, ECP_EXTENSIBILITY | DEVICE_ID_REQ);
  150. } else {
  151. Status = IeeeEnter1284Mode (Extension, ECP_EXTENSIBILITY);
  152. }
  153. } else {
  154. ParDump2(PARINFO, ("ParEnterEcpSwMode: In UNSAFE_MODE.\n"));
  155. Extension->Connected = TRUE;
  156. }
  157. if (NT_SUCCESS(Status)) {
  158. Status = ParEcpSetupPhase(Extension);
  159. }
  160. return Status;
  161. }
  162. VOID
  163. ParCleanupSwEcpPort(
  164. IN PDEVICE_EXTENSION Extension
  165. )
  166. /*++
  167. Routine Description:
  168. Cleans up prior to a normal termination from ECP mode. Puts the
  169. port HW back into Compatibility mode.
  170. Arguments:
  171. Controller - Supplies the parallel port's controller address.
  172. Return Value:
  173. None.
  174. --*/
  175. {
  176. PUCHAR Controller;
  177. UCHAR dcr; // Contents of DCR
  178. Controller = Extension->Controller;
  179. //----------------------------------------------------------------------
  180. // Set data bus for output
  181. //----------------------------------------------------------------------
  182. dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR); // Get content of DCR
  183. dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
  184. WRITE_PORT_UCHAR( Controller + OFFSET_DCR, dcr );
  185. return;
  186. }
  187. VOID
  188. ParTerminateEcpMode(
  189. IN PDEVICE_EXTENSION Extension
  190. )
  191. /*++
  192. Routine Description:
  193. This routine terminates the interface back to compatibility mode.
  194. Arguments:
  195. Controller - Supplies the parallel port's controller address.
  196. Return Value:
  197. None.
  198. --*/
  199. {
  200. ParCleanupSwEcpPort(Extension);
  201. if ( Extension->ModeSafety == SAFE_MODE ) {
  202. IeeeTerminate1284Mode (Extension);
  203. } else {
  204. ParDump2(PARINFO, ("ParTerminateEcpMode: In UNSAFE_MODE.\n"));
  205. Extension->Connected = FALSE;
  206. }
  207. return;
  208. }
  209. NTSTATUS
  210. ParEcpSetAddress(
  211. IN PDEVICE_EXTENSION Extension,
  212. IN UCHAR Address
  213. )
  214. /*++
  215. Routine Description:
  216. Sets the ECP Address.
  217. Arguments:
  218. Extension - Supplies the device extension.
  219. Address - The bus address to be set.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. PUCHAR Controller;
  225. PUCHAR DCRController;
  226. UCHAR dsr;
  227. UCHAR dcr;
  228. ParDump2( PARENTRY, ("ParEcpSetAddress: Start: Channel [%x]\n", Address));
  229. Controller = Extension->Controller;
  230. DCRController = Controller + OFFSET_DCR;
  231. //
  232. // Event 34
  233. //
  234. // HostAck low indicates a command byte
  235. Extension->CurrentEvent = 34;
  236. dcr = READ_PORT_UCHAR(DCRController);
  237. dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE );
  238. WRITE_PORT_UCHAR(DCRController, dcr);
  239. // Place the channel address on the bus
  240. // Bit 7 of the byte sent must be 1 to indicate that this is an address
  241. // instead of run length count.
  242. //
  243. WRITE_PORT_UCHAR(Controller + DATA_OFFSET, (UCHAR)(Address | 0x80));
  244. //
  245. // Event 35
  246. //
  247. // Start handshake by dropping HostClk
  248. Extension->CurrentEvent = 35;
  249. dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE );
  250. WRITE_PORT_UCHAR(DCRController, dcr);
  251. // =============== Periph State 36 ===============8
  252. // PeriphAck/PtrBusy = High (signals state 36)
  253. // PeriphClk/PtrClk = Don't Care
  254. // nAckReverse/AckDataReq = Don't Care
  255. // XFlag = Don't Care
  256. // nPeriphReq/nDataAvail = Don't Care
  257. Extension->CurrentEvent = 35;
  258. if (!CHECK_DSR(Controller,
  259. ACTIVE, DONT_CARE, DONT_CARE,
  260. DONT_CARE, DONT_CARE,
  261. DEFAULT_RECEIVE_TIMEOUT))
  262. {
  263. ParDump2(PARERRORS, ("ECP::SendChannelAddress:State 36 Failed: Controller %x\n",
  264. Controller));
  265. // Make sure both HostAck and HostClk are high before leaving
  266. // HostClk should be high in forward transfer except when handshaking
  267. // HostAck should be high to indicate that what follows is data (not commands)
  268. //
  269. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
  270. WRITE_PORT_UCHAR(DCRController, dcr);
  271. return STATUS_IO_DEVICE_ERROR;
  272. }
  273. //
  274. // Event 37
  275. //
  276. // Finish handshake by raising HostClk
  277. // HostClk is high when it's 0
  278. //
  279. Extension->CurrentEvent = 37;
  280. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE );
  281. WRITE_PORT_UCHAR(DCRController, dcr);
  282. // =============== Periph State 32 ===============8
  283. // PeriphAck/PtrBusy = Low (signals state 32)
  284. // PeriphClk/PtrClk = Don't Care
  285. // nAckReverse/AckDataReq = Don't Care
  286. // XFlag = Don't Care
  287. // nPeriphReq/nDataAvail = Don't Care
  288. Extension->CurrentEvent = 32;
  289. if (!CHECK_DSR(Controller,
  290. INACTIVE, DONT_CARE, DONT_CARE,
  291. DONT_CARE, DONT_CARE,
  292. DEFAULT_RECEIVE_TIMEOUT))
  293. {
  294. ParDump2(PARERRORS, ("ECP::SendChannelAddress:State 32 Failed: Controller %x\n",
  295. Controller));
  296. // Make sure both HostAck and HostClk are high before leaving
  297. // HostClk should be high in forward transfer except when handshaking
  298. // HostAck should be high to indicate that what follows is data (not commands)
  299. //
  300. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
  301. WRITE_PORT_UCHAR(DCRController, dcr);
  302. return STATUS_IO_DEVICE_ERROR;
  303. }
  304. // Make sure both HostAck and HostClk are high before leaving
  305. // HostClk should be high in forward transfer except when handshaking
  306. // HostAck should be high to indicate that what follows is data (not commands)
  307. //
  308. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
  309. WRITE_PORT_UCHAR(DCRController, dcr);
  310. ParDump2( PAREXIT, ("ParEcpSetAddress, Exit [%d]\n", NT_SUCCESS(STATUS_SUCCESS)));
  311. return STATUS_SUCCESS;
  312. }
  313. NTSTATUS
  314. ParEcpSwWrite(
  315. IN PDEVICE_EXTENSION Extension,
  316. IN PVOID Buffer,
  317. IN ULONG BufferSize,
  318. OUT PULONG BytesTransferred
  319. )
  320. /*++
  321. Routine Description:
  322. Writes data to the peripheral using the ECP protocol under software
  323. control.
  324. Arguments:
  325. Extension - Supplies the device extension.
  326. Buffer - Supplies the buffer to write from.
  327. BufferSize - Supplies the number of bytes in the buffer.
  328. BytesTransferred - Returns the number of bytes transferred.
  329. Return Value:
  330. None.
  331. --*/
  332. {
  333. PUCHAR Controller;
  334. NTSTATUS Status = STATUS_SUCCESS;
  335. PUCHAR pBuffer;
  336. LARGE_INTEGER Timeout;
  337. LARGE_INTEGER StartWrite;
  338. LARGE_INTEGER Wait;
  339. LARGE_INTEGER Start;
  340. LARGE_INTEGER End;
  341. UCHAR dsr;
  342. UCHAR dcr;
  343. ULONG i;
  344. Controller = Extension->Controller;
  345. pBuffer = Buffer;
  346. Status = ParTestEcpWrite(Extension);
  347. if (!NT_SUCCESS(Status))
  348. {
  349. Extension->CurrentPhase = PHASE_UNKNOWN;
  350. Extension->Connected = FALSE;
  351. ParDump2(PARERRORS,("ParEcpSwWrite: Invalid Entry State\r\n"));
  352. goto ParEcpSwWrite_ExitLabel;
  353. }
  354. Wait.QuadPart = DEFAULT_RECEIVE_TIMEOUT * 10 * 1000 + KeQueryTimeIncrement();
  355. Timeout.QuadPart = Extension->AbsoluteOneSecond.QuadPart *
  356. Extension->TimerStart;
  357. KeQueryTickCount(&StartWrite);
  358. dcr = GetControl (Controller);
  359. // clear direction bit - enable output
  360. dcr &= ~(DCR_DIRECTION);
  361. StoreControl(Controller, dcr);
  362. KeStallExecutionProcessor(1);
  363. for (i = 0; i < BufferSize; i++) {
  364. //
  365. // Event 34
  366. //
  367. Extension->CurrentEvent = 34;
  368. WRITE_PORT_UCHAR(Controller + DATA_OFFSET, *pBuffer++);
  369. //
  370. // Event 35
  371. //
  372. Extension->CurrentEvent = 35;
  373. dcr &= ~DCR_AUTOFEED;
  374. dcr |= DCR_STROBE;
  375. StoreControl (Controller, dcr);
  376. //
  377. // Waiting for Event 36
  378. //
  379. Extension->CurrentEvent = 36;
  380. while (TRUE) {
  381. KeQueryTickCount(&End);
  382. dsr = GetStatus(Controller);
  383. if (!(dsr & DSR_NOT_BUSY)) {
  384. break;
  385. }
  386. if ((End.QuadPart - StartWrite.QuadPart) *
  387. KeQueryTimeIncrement() > Timeout.QuadPart) {
  388. dsr = GetStatus(Controller);
  389. if (!(dsr & DSR_NOT_BUSY)) {
  390. break;
  391. }
  392. //
  393. // Return the device to Idle.
  394. //
  395. dcr &= ~(DCR_STROBE);
  396. StoreControl (Controller, dcr);
  397. *BytesTransferred = i;
  398. Extension->log.SwEcpWriteCount += *BytesTransferred;
  399. return STATUS_DEVICE_BUSY;
  400. }
  401. }
  402. //
  403. // Event 37
  404. //
  405. Extension->CurrentEvent = 37;
  406. dcr &= ~DCR_STROBE;
  407. StoreControl (Controller, dcr);
  408. //
  409. // Waiting for Event 32
  410. //
  411. Extension->CurrentEvent = 32;
  412. KeQueryTickCount(&Start);
  413. while (TRUE) {
  414. KeQueryTickCount(&End);
  415. dsr = GetStatus(Controller);
  416. if (dsr & DSR_NOT_BUSY) {
  417. break;
  418. }
  419. if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
  420. Wait.QuadPart) {
  421. dsr = GetStatus(Controller);
  422. if (dsr & DSR_NOT_BUSY) {
  423. break;
  424. }
  425. #if DVRH_BUS_RESET_ON_ERROR
  426. BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
  427. #endif
  428. *BytesTransferred = i;
  429. Extension->log.SwEcpWriteCount += *BytesTransferred;
  430. return STATUS_IO_DEVICE_ERROR;
  431. }
  432. }
  433. }
  434. ParEcpSwWrite_ExitLabel:
  435. *BytesTransferred = i;
  436. Extension->log.SwEcpWriteCount += *BytesTransferred;
  437. ParDumpReg(PAREXIT | PARECPTRACE, ("ParEcpSwWrite: Exit[%d] BytesTransferred[%lx]",
  438. NT_SUCCESS(Status),
  439. (long)*BytesTransferred),
  440. Controller + ECR_OFFSET,
  441. Controller + OFFSET_DCR,
  442. Controller + OFFSET_DSR);
  443. return Status;
  444. }
  445. NTSTATUS
  446. ParEcpSwRead(
  447. IN PDEVICE_EXTENSION Extension,
  448. IN PVOID Buffer,
  449. IN ULONG BufferSize,
  450. OUT PULONG BytesTransferred
  451. )
  452. /*++
  453. Routine Description:
  454. This routine performs a 1284 ECP mode read under software control
  455. into the given buffer for no more than 'BufferSize' bytes.
  456. Arguments:
  457. Extension - Supplies the device extension.
  458. Buffer - Supplies the buffer to read into.
  459. BufferSize - Supplies the number of bytes in the buffer.
  460. BytesTransferred - Returns the number of bytes transferred.
  461. --*/
  462. {
  463. PUCHAR Controller;
  464. PUCHAR pBuffer;
  465. USHORT usTime;
  466. LARGE_INTEGER End;
  467. UCHAR dsr;
  468. UCHAR dcr;
  469. ULONG i;
  470. UCHAR ecr;
  471. Controller = Extension->Controller;
  472. pBuffer = Buffer;
  473. dcr = GetControl (Controller);
  474. Extension->CurrentPhase = PHASE_REVERSE_XFER;
  475. //
  476. // Put ECR into PS/2 mode and float the drivers.
  477. //
  478. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  479. // Save off the ECR register
  480. ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
  481. #if (1 == PARCHIP_ECR_ARBITRATOR)
  482. #else
  483. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
  484. #endif
  485. }
  486. dcr |= DCR_DIRECTION;
  487. StoreControl (Controller, dcr);
  488. KeStallExecutionProcessor(1);
  489. for (i = 0; i < BufferSize; i++) {
  490. // dvtw - READ TIMEOUTS
  491. //
  492. // If it is the first byte then give it more time
  493. //
  494. if (!(GetStatus (Controller) & DSR_NOT_FAULT) || i == 0) {
  495. usTime = DEFAULT_RECEIVE_TIMEOUT;
  496. } else {
  497. usTime = IEEE_MAXTIME_TL;
  498. }
  499. // *************** State 43 Reverse Phase ***************8
  500. // PeriphAck/PtrBusy = DONT CARE
  501. // PeriphClk/PtrClk = LOW ( State 43 )
  502. // nAckReverse/AckDataReq = LOW
  503. // XFlag = HIGH
  504. // nPeriphReq/nDataAvail = DONT CARE
  505. Extension->CurrentEvent = 43;
  506. if (!CHECK_DSR(Controller, DONT_CARE, INACTIVE, INACTIVE, ACTIVE, DONT_CARE,
  507. usTime)) {
  508. Extension->CurrentPhase = PHASE_UNKNOWN;
  509. dcr &= ~DCR_DIRECTION;
  510. StoreControl (Controller, dcr);
  511. // restore ecr register
  512. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  513. #if (1 == PARCHIP_ECR_ARBITRATOR)
  514. #else
  515. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  516. #endif
  517. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  518. }
  519. *BytesTransferred = i;
  520. Extension->log.SwEcpReadCount += *BytesTransferred;
  521. return STATUS_IO_DEVICE_ERROR;
  522. }
  523. // *************** State 44 Setup Phase ***************8
  524. // DIR = DONT CARE
  525. // IRQEN = DONT CARE
  526. // 1284/SelectIn = DONT CARE
  527. // nReverseReq/**(ECP only)= DONT CARE
  528. // HostAck/HostBusy = HIGH ( State 44 )
  529. // HostClk/nStrobe = DONT CARE
  530. //
  531. Extension->CurrentEvent = 44;
  532. dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR);
  533. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE);
  534. WRITE_PORT_UCHAR(Controller + OFFSET_DCR, dcr);
  535. // *************** State 45 Reverse Phase ***************8
  536. // PeriphAck/PtrBusy = DONT CARE
  537. // PeriphClk/PtrClk = HIGH ( State 45 )
  538. // nAckReverse/AckDataReq = LOW
  539. // XFlag = HIGH
  540. // nPeriphReq/nDataAvail = DONT CARE
  541. Extension->CurrentEvent = 45;
  542. if (!CHECK_DSR(Controller, DONT_CARE, ACTIVE, INACTIVE, ACTIVE, DONT_CARE,
  543. IEEE_MAXTIME_TL)) {
  544. Extension->CurrentPhase = PHASE_UNKNOWN;
  545. dcr &= ~DCR_DIRECTION;
  546. StoreControl (Controller, dcr);
  547. // restore ecr register
  548. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  549. #if (1 == PARCHIP_ECR_ARBITRATOR)
  550. #else
  551. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  552. #endif
  553. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  554. }
  555. *BytesTransferred = i;
  556. Extension->log.SwEcpReadCount += *BytesTransferred;
  557. return STATUS_IO_DEVICE_ERROR;
  558. }
  559. //
  560. // Read the data
  561. //
  562. *pBuffer = READ_PORT_UCHAR (Controller + DATA_OFFSET);
  563. pBuffer++;
  564. // *************** State 46 Setup Phase ***************8
  565. // DIR = DONT CARE
  566. // IRQEN = DONT CARE
  567. // 1284/SelectIn = DONT CARE
  568. // nReverseReq/**(ECP only)= DONT CARE
  569. // HostAck/HostBusy = LOW ( State 46 )
  570. // HostClk/nStrobe = DONT CARE
  571. //
  572. Extension->CurrentEvent = 46;
  573. dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR);
  574. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE);
  575. WRITE_PORT_UCHAR(Controller + OFFSET_DCR, dcr);
  576. }
  577. Extension->CurrentPhase = PHASE_REVERSE_IDLE;
  578. dcr &= ~DCR_DIRECTION;
  579. StoreControl (Controller, dcr);
  580. // restore ecr register
  581. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  582. #if (1 == PARCHIP_ECR_ARBITRATOR)
  583. #else
  584. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  585. #endif
  586. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  587. }
  588. *BytesTransferred = i;
  589. Extension->log.SwEcpReadCount += *BytesTransferred;
  590. return STATUS_SUCCESS;
  591. }
  592. NTSTATUS
  593. ParEcpForwardToReverse(
  594. IN PDEVICE_EXTENSION Extension
  595. )
  596. /*++
  597. Routine Description:
  598. This routine reverses the channel (ECP).
  599. Arguments:
  600. Extension - Supplies the device extension.
  601. --*/
  602. {
  603. PUCHAR Controller;
  604. LARGE_INTEGER Wait35ms;
  605. LARGE_INTEGER Start;
  606. LARGE_INTEGER End;
  607. UCHAR dsr;
  608. UCHAR dcr;
  609. UCHAR ecr;
  610. Controller = Extension->Controller;
  611. Wait35ms.QuadPart = 10*35*1000 + KeQueryTimeIncrement();
  612. dcr = GetControl (Controller);
  613. //
  614. // Put ECR into PS/2 mode to flush the FIFO.
  615. //
  616. // Save off the ECR register
  617. // Note: Don't worry about checking to see if it's
  618. // safe to touch the ecr since we've already checked
  619. // that before we allowed this mode to be activated.
  620. ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
  621. #if (1 == PARCHIP_ECR_ARBITRATOR)
  622. #else
  623. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
  624. #endif
  625. //
  626. // Event 38
  627. //
  628. Extension->CurrentEvent = 38;
  629. dcr |= DCR_AUTOFEED;
  630. StoreControl (Controller, dcr);
  631. KeStallExecutionProcessor(1);
  632. //
  633. // Event 39
  634. //
  635. Extension->CurrentEvent = 39;
  636. dcr &= ~DCR_NOT_INIT;
  637. StoreControl (Controller, dcr);
  638. //
  639. // Wait for Event 40
  640. //
  641. Extension->CurrentEvent = 40;
  642. KeQueryTickCount(&Start);
  643. while (TRUE) {
  644. KeQueryTickCount(&End);
  645. dsr = GetStatus(Controller);
  646. if (!(dsr & DSR_PERROR)) {
  647. break;
  648. }
  649. if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
  650. Wait35ms.QuadPart) {
  651. dsr = GetStatus(Controller);
  652. if (!(dsr & DSR_PERROR)) {
  653. break;
  654. }
  655. #if DVRH_BUS_RESET_ON_ERROR
  656. BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
  657. #endif
  658. // restore the ecr register
  659. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  660. #if (1 == PARCHIP_ECR_ARBITRATOR)
  661. #else
  662. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  663. #endif
  664. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  665. }
  666. ParDump2(PARERRORS,("ParEcpForwardToReverse: Failed to get State 40\r\n"));
  667. return STATUS_IO_DEVICE_ERROR;
  668. }
  669. }
  670. // restore the ecr register
  671. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  672. #if (1 == PARCHIP_ECR_ARBITRATOR)
  673. #else
  674. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  675. #endif
  676. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  677. }
  678. Extension->CurrentPhase = PHASE_REVERSE_IDLE;
  679. return STATUS_SUCCESS;
  680. }
  681. NTSTATUS
  682. ParEcpReverseToForward(
  683. IN PDEVICE_EXTENSION Extension
  684. )
  685. /*++
  686. Routine Description:
  687. This routine puts the channel back into forward mode (ECP).
  688. Arguments:
  689. Extension - Supplies the device extension.
  690. --*/
  691. {
  692. PUCHAR Controller;
  693. LARGE_INTEGER Wait35ms;
  694. LARGE_INTEGER Start;
  695. LARGE_INTEGER End;
  696. UCHAR dsr;
  697. UCHAR dcr;
  698. UCHAR ecr;
  699. Controller = Extension->Controller;
  700. Wait35ms.QuadPart = 10*35*1000 + KeQueryTimeIncrement();
  701. dcr = GetControl (Controller);
  702. //
  703. // Put ECR into PS/2 mode to flush the FIFO.
  704. //
  705. // Save off the ECR register
  706. // Note: Don't worry about checking to see if it's
  707. // safe to touch the ecr since we've already checked
  708. // that before we allowed this mode to be activated.
  709. ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
  710. #if (1 == PARCHIP_ECR_ARBITRATOR)
  711. #else
  712. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
  713. #endif
  714. //
  715. // Event 47
  716. //
  717. Extension->CurrentEvent = 47;
  718. dcr |= DCR_NOT_INIT;
  719. StoreControl (Controller, dcr);
  720. //
  721. // Wait for Event 49
  722. //
  723. Extension->CurrentEvent = 49;
  724. KeQueryTickCount(&Start);
  725. while (TRUE) {
  726. KeQueryTickCount(&End);
  727. dsr = GetStatus(Controller);
  728. if (dsr & DSR_PERROR) {
  729. break;
  730. }
  731. if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
  732. Wait35ms.QuadPart) {
  733. dsr = GetStatus(Controller);
  734. if (dsr & DSR_PERROR) {
  735. break;
  736. }
  737. #if DVRH_BUS_RESET_ON_ERROR
  738. BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
  739. #endif
  740. // Restore the ecr register
  741. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  742. #if (1 == PARCHIP_ECR_ARBITRATOR)
  743. #else
  744. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  745. #endif
  746. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  747. }
  748. ParDump2(PARERRORS,("ParEcpReverseToForward: Failed to get State 49\r\n"));
  749. return STATUS_IO_DEVICE_ERROR;
  750. }
  751. }
  752. // restore the ecr register
  753. if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
  754. #if (1 == PARCHIP_ECR_ARBITRATOR)
  755. #else
  756. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
  757. #endif
  758. WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
  759. }
  760. Extension->CurrentPhase = PHASE_FORWARD_IDLE;
  761. return STATUS_SUCCESS;
  762. }