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.

296 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. ecp.c
  5. Abstract:
  6. Enhanced Capabilities Port (ECP)
  7. This module contains the common routines that aue used/ reused
  8. by swecp and hwecp.
  9. Author:
  10. Robbie Harris (Hewlett-Packard) - May 27, 1998
  11. Environment:
  12. Kernel mode
  13. Revision History :
  14. --*/
  15. #include "pch.h"
  16. //=========================================================
  17. // ECP::EnterForwardPhase
  18. //
  19. // Description : Do what is necessary to enter forward phase for ECP
  20. //
  21. // Input Parameters : Controller, pPortInfoStruct
  22. //
  23. // Modifies : ECR, DCR
  24. //
  25. //=========================================================
  26. NTSTATUS
  27. ParEcpEnterForwardPhase(IN PPDO_EXTENSION Pdx)
  28. {
  29. P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
  30. return STATUS_SUCCESS;
  31. }
  32. // =========================================================
  33. // ECP::EnterReversePhase
  34. //
  35. // Description : Move from the common phase (FwdIdle, wPortHWMode=PS2)
  36. // to ReversePhase.
  37. //
  38. // Input Parameters : Controller, pPortInfoStruct
  39. //
  40. // Modifies : pPortInfoStruct->CurrentPhase, DCR
  41. //
  42. // Pre-conditions : CurrentPhase == PHASE_FORWARD_IDLE
  43. // wPortHWMode == HW_MODE_PS2
  44. //
  45. // Post-conditions : Bus is in ECP State 40
  46. // CurrentPhase = PHASE_REVERSE_IDLE
  47. //
  48. // Returns : status of operation
  49. //
  50. //=========================================================
  51. NTSTATUS ParEcpEnterReversePhase(IN PPDO_EXTENSION Pdx)
  52. {
  53. // Assume that we are in the common entry phase (FWDIDLE, and ECR mode=PS/2)
  54. // EnterReversePhase assumes that we are in PHASE_FORWARD_IDLE,
  55. // and that the ECPMode is set to PS/2 mode at entry.
  56. // Setup the status to indicate successful
  57. NTSTATUS status = STATUS_SUCCESS;
  58. PUCHAR wPortDCR; // I/O address of Device Control Register
  59. PUCHAR wPortECR; // I/O address of ECR
  60. UCHAR dcr;
  61. // Calculate I/O port addresses for common registers
  62. wPortDCR = Pdx->Controller + OFFSET_DCR;
  63. wPortECR = Pdx->EcrController + ECR_OFFSET;
  64. // Now, Check the current state to make sure that we are ready for
  65. // a change to reverse phase.
  66. if ( PHASE_FORWARD_IDLE == Pdx->CurrentPhase ) {
  67. // Okay, we are ready to proceed. Set the CurrentPhase and go on to
  68. // state 47
  69. //----------------------------------------------------------------------
  70. // Set CurrentPhase to indicate Forward To Reverse Mode.
  71. //----------------------------------------------------------------------
  72. P5SetPhase( Pdx, PHASE_FWD_TO_REV );
  73. //----------------------------------------------------------------------
  74. // Set Dir=1 in DCR for reading.
  75. //----------------------------------------------------------------------
  76. dcr = P5ReadPortUchar(wPortDCR); // Get content of DCR.
  77. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
  78. P5WritePortUchar(wPortDCR, dcr);
  79. // Set the data port bits to 1 so that other circuits can control them
  80. //P5WritePortUchar(Controller + OFFSET_DATA, 0xFF);
  81. //----------------------------------------------------------------------
  82. // Assert HostAck low. (ECP State 38)
  83. //----------------------------------------------------------------------
  84. Pdx->CurrentEvent = 38;
  85. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE );
  86. P5WritePortUchar(wPortDCR, dcr);
  87. // REVISIT: Should use TICKCount to get a finer granularity.
  88. // According to the spec we need to delay at least .5 us
  89. KeStallExecutionProcessor((ULONG) 1); // Stall for 1 us
  90. //----------------------------------------------------------------------
  91. // Assert nReverseRequest low. (ECP State 39)
  92. //----------------------------------------------------------------------
  93. Pdx->CurrentEvent = 39;
  94. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE );
  95. P5WritePortUchar(wPortDCR, dcr);
  96. // NOTE: Let the caller check for State 40, since the error handling for
  97. // State 40 is different between hwecp and swecp.
  98. } else {
  99. DD((PCE)Pdx,DDE,"ParEcpEnterReversePhase - Invalid Phase on entry - broken state machine\n");
  100. PptAssertMsg("ParEcpEnterReversePhase - Invalid Phase on entry - broken state machine",FALSE);
  101. status = STATUS_LINK_FAILED;
  102. }
  103. return status;
  104. }
  105. //=========================================================
  106. // ECP::ExitReversePhase
  107. //
  108. // Description : Transition from the ECP reverse Phase to the
  109. // common phase for all entry functions
  110. //
  111. // Input Parameters : Controller - offset to the I/O ports
  112. // pPortInfoStruct - pointer to port information
  113. //
  114. // Modifies : CurrentPhase, DCR
  115. //
  116. // Pre-conditions :
  117. //
  118. // Post-conditions : NOTE: This function does not completely move to
  119. // the common phase for entry functions. Both the
  120. // HW and SW ECP classes must do extra work
  121. //
  122. // Returns : Status of the operation
  123. //
  124. //=========================================================
  125. NTSTATUS ParEcpExitReversePhase(IN PPDO_EXTENSION Pdx)
  126. {
  127. NTSTATUS status = STATUS_SUCCESS;
  128. PUCHAR Controller = Pdx->Controller;
  129. PUCHAR wPortDCR; // I/O address of Device Control Register
  130. PUCHAR wPortECR; // I/O address of ECR
  131. UCHAR dcr;
  132. wPortDCR = Controller + OFFSET_DCR;
  133. wPortECR = Pdx->EcrController + ECR_OFFSET;
  134. //----------------------------------------------------------------------
  135. // Set status byte to indicate Reverse To Forward Mode.
  136. //----------------------------------------------------------------------
  137. P5SetPhase( Pdx, PHASE_REV_TO_FWD );
  138. //----------------------------------------------------------------------
  139. // Set HostAck high
  140. //----------------------------------------------------------------------
  141. dcr = P5ReadPortUchar(wPortDCR);
  142. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE );
  143. P5WritePortUchar(wPortDCR, dcr);
  144. //----------------------------------------------------------------------
  145. // Set nReverseRequest high. (State 47)
  146. //----------------------------------------------------------------------
  147. Pdx->CurrentEvent = 47;
  148. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, DONT_CARE );
  149. P5WritePortUchar(wPortDCR, dcr);
  150. //----------------------------------------------------------------------
  151. // Check first for PeriphAck low and PeriphClk high. (State 48)
  152. //----------------------------------------------------------------------
  153. Pdx->CurrentEvent = 48;
  154. if( ! CHECK_DSR(Controller, INACTIVE, ACTIVE, DONT_CARE, ACTIVE, DONT_CARE, IEEE_MAXTIME_TL) ) {
  155. // Bad things happened - timed out on this state,
  156. // Mark Status as bad and let our mgr kill ECP mode.
  157. // status = SLP_RecoverPort( pSDCB, RECOVER_18 ); // Reset port.
  158. status = STATUS_LINK_FAILED;
  159. DD((PCE)Pdx,DDE,"ParEcpExitReversePhase - state 48 Timeout\n");
  160. goto ParEcpExitReversePhase;
  161. }
  162. //----------------------------------------------------------------------
  163. // Check next for nAckReverse high. (State 49)
  164. //----------------------------------------------------------------------
  165. Pdx->CurrentEvent = 49;
  166. if ( ! CHECK_DSR(Controller ,INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE, IEEE_MAXTIME_TL ) ) {
  167. // Bad things happened - timed out on this state,
  168. // Mark Status as bad and let our mgr kill ECP mode.
  169. //nError = RecoverPort( pSDCB, RECOVER_19 ); // Reset port.
  170. status = STATUS_LINK_FAILED;
  171. DD((PCE)Pdx,DDE,"ParEcpExitReversePhase:state 49 Timeout\n");
  172. goto ParEcpExitReversePhase;
  173. }
  174. // Warning: Don't assume that the ECR is in PS/2 mode here.
  175. // You cannot change the direction in this routine. It must be
  176. // done elsewhere (SWECP or HWECP).
  177. ParEcpExitReversePhase:
  178. DD((PCE)Pdx,DDT,"ParEcpExitReversePhase - exit w/status=%x\n",status);
  179. return status;
  180. }
  181. BOOLEAN
  182. ParEcpHaveReadData (
  183. IN PPDO_EXTENSION Pdx
  184. )
  185. {
  186. return ( (UCHAR)0 == (P5ReadPortUchar(Pdx->Controller + OFFSET_DSR) & DSR_NOT_PERIPH_REQUEST) );
  187. }
  188. NTSTATUS
  189. ParEcpSetupPhase(
  190. IN PPDO_EXTENSION Pdx
  191. )
  192. /*++
  193. Routine Description:
  194. This routine performs 1284 Setup Phase.
  195. Arguments:
  196. Controller - Supplies the port address.
  197. Return Value:
  198. STATUS_SUCCESS - Successful negotiation.
  199. otherwise - Unsuccessful negotiation.
  200. --*/
  201. {
  202. PUCHAR Controller;
  203. UCHAR dcr;
  204. // The negotiation succeeded. Current mode and phase.
  205. //
  206. P5SetPhase( Pdx, PHASE_SETUP );
  207. Controller = Pdx->Controller;
  208. // Negoiate leaves us in state 6, we need to be in state 30 to
  209. // begin transfer. Note that I am assuming that the controller
  210. // is already set as it should be for state 6.
  211. //
  212. // *************** State 30 Setup Phase ***************8
  213. // DIR = Don't Care
  214. // IRQEN = Don't Care
  215. // 1284/SelectIn = High
  216. // nReverseReq/**(ECP only)= High
  217. // HostAck/HostBusy = Low (Signals state 30)
  218. // HostClk/nStrobe = High
  219. //
  220. Pdx->CurrentEvent = 30;
  221. dcr = P5ReadPortUchar(Controller + OFFSET_DCR);
  222. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE, INACTIVE, ACTIVE);
  223. P5WritePortUchar(Controller + OFFSET_DCR, dcr);
  224. // *************** State 31 Setup Phase ***************8
  225. // PeriphAck/PtrBusy = low
  226. // PeriphClk/PtrClk = high
  227. // nAckReverse/AckDataReq = high (Signals state 31)
  228. // XFlag = high
  229. // nPeriphReq/nDataAvail = Don't Care
  230. Pdx->CurrentEvent = 31;
  231. if (!CHECK_DSR(Controller, INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE, IEEE_MAXTIME_TL)) {
  232. // Bad things happened - timed out on this state.
  233. // Set status to an error and let PortTuple kill ECP mode (Terminate).
  234. DD((PCE)Pdx,DDE,"ParEcpSetupPhase - State 31 Failed - dcr=%x\n",dcr);
  235. P5SetPhase( Pdx, PHASE_UNKNOWN );
  236. return STATUS_IO_DEVICE_ERROR;
  237. }
  238. P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
  239. DD((PCE)Pdx,DDT,"ParEcpSetupPhase - exit - STATUS_SUCCESS\n");
  240. return STATUS_SUCCESS;
  241. }