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.

346 lines
12 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. #include "ecp.h"
  17. //=========================================================
  18. // ECP::EnterForwardPhase
  19. //
  20. // Description : Do what is necessary to enter forward phase for
  21. // ECP
  22. //
  23. // Input Parameters : Controller, pPortInfoStruct
  24. //
  25. // Modifies : ECR, DCR
  26. //
  27. // Pre-conditions :
  28. //
  29. // Post-conditions :
  30. //
  31. // Returns :
  32. //
  33. //=========================================================
  34. NTSTATUS ParEcpEnterForwardPhase(IN PDEVICE_EXTENSION Extension)
  35. {
  36. Extension->CurrentPhase = PHASE_FORWARD_IDLE;
  37. return STATUS_SUCCESS;
  38. }
  39. // =========================================================
  40. // ECP::EnterReversePhase
  41. //
  42. // Description : Move from the common phase (FwdIdle, wPortHWMode=PS2)
  43. // to ReversePhase.
  44. //
  45. // Input Parameters : Controller, pPortInfoStruct
  46. //
  47. // Modifies : pPortInfoStruct->CurrentPhase, DCR
  48. //
  49. // Pre-conditions : CurrentPhase == PHASE_FORWARD_IDLE
  50. // wPortHWMode == HW_MODE_PS2
  51. //
  52. // Post-conditions : Bus is in ECP State 40
  53. // CurrentPhase = PHASE_REVERSE_IDLE
  54. //
  55. // Returns : status of operation
  56. //
  57. //=========================================================
  58. NTSTATUS ParEcpEnterReversePhase(IN PDEVICE_EXTENSION Extension)
  59. {
  60. // Assume that we are in the common entry phase (FWDIDLE, and ECR mode=PS/2)
  61. // EnterReversePhase assumes that we are in PHASE_FORWARD_IDLE,
  62. // and that the ECPMode is set to PS/2 mode at entry.
  63. // Don't use this assert. If you are not in ECP mode in your BIOS
  64. // setup it will fail 100% of the time since the ECR is not present.
  65. //volatile UCHAR ecr = READ_PORT_UCHAR( Controller + ECR_OFFSET ) & 0xe0;
  66. //HPKAssert( ((PHASE_FORWARD_IDLE == pPortInfoStruct->CurrentPhase) && (0x20 == ecr)),
  67. // ("SoftwareECP::EnterReversePhase: Bad initial state (%d/%x)\n",(int)pPortInfoStruct->CurrentPhase,(int)ecr) );
  68. // Setup the status to indicate successful
  69. NTSTATUS status = STATUS_SUCCESS;
  70. PUCHAR wPortDCR; // I/O address of Device Control Register
  71. PUCHAR wPortECR; // I/O address of ECR
  72. UCHAR dcr;
  73. ParDump2(PARENTRY,("ParEcpEnterReversePhase: Start\n"));
  74. // Calculate I/O port addresses for common registers
  75. wPortDCR = Extension->Controller + OFFSET_DCR;
  76. #if (0 == DVRH_USE_PARPORT_ECP_ADDR)
  77. wPortECR = Extension->Controller + ECR_OFFSET;
  78. #else
  79. wPortECR = Extension->EcrController + ECR_OFFSET;
  80. #endif
  81. // Now, Check the current state to make sure that we are ready for
  82. // a change to reverse phase.
  83. if ( PHASE_FORWARD_IDLE == Extension->CurrentPhase )
  84. {
  85. // Okay, we are ready to proceed. Set the CurrentPhase and go on to
  86. // state 47
  87. //----------------------------------------------------------------------
  88. // Set CurrentPhase to indicate Forward To Reverse Mode.
  89. //----------------------------------------------------------------------
  90. ParDump2(PARECPTRACE,("ParEcpEnterReversePhase: PHASE_FwdToRev\n"));
  91. Extension->CurrentPhase = PHASE_FWD_TO_REV;
  92. //----------------------------------------------------------------------
  93. // Set Dir=1 in DCR for reading.
  94. //----------------------------------------------------------------------
  95. dcr = READ_PORT_UCHAR(wPortDCR); // Get content of DCR.
  96. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
  97. WRITE_PORT_UCHAR(wPortDCR, dcr);
  98. ParDump2(PARECPTRACE,("ParEcpEnterReversePhase: After DCR update DCR - %x.\n", READ_PORT_UCHAR(wPortDCR) ));
  99. // Set the data port bits to 1 so that other circuits can control them
  100. //WRITE_PORT_UCHAR(Controller + OFFSET_DATA, 0xFF);
  101. //----------------------------------------------------------------------
  102. // Assert HostAck low. (ECP State 38)
  103. //----------------------------------------------------------------------
  104. Extension->CurrentEvent = 38;
  105. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE );
  106. WRITE_PORT_UCHAR(wPortDCR, dcr);
  107. ParDump2(PARECPTRACE,("ParEcpEnterReversePhase: HostAck Low DCR - %x.\n", READ_PORT_UCHAR(wPortDCR) ));
  108. // REVISIT: Should use TICKCount to get a finer granularity.
  109. // According to the spec we need to delay at least .5 us
  110. KeStallExecutionProcessor((ULONG) 1); // Stall for 1 us
  111. //----------------------------------------------------------------------
  112. // Assert nReverseRequest low. (ECP State 39)
  113. //----------------------------------------------------------------------
  114. Extension->CurrentEvent = 39;
  115. dcr = UPDATE_DCR( dcr, DIR_READ, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE );
  116. WRITE_PORT_UCHAR(wPortDCR, dcr);
  117. ParDump2(PARECPTRACE,("ParEcpEnterReversePhase: nReverseRequest Low DCR - %x.\n", READ_PORT_UCHAR(wPortDCR) ));
  118. // NOTE: Let the caller check for State 40, since the error handling for
  119. // State 40 is different between hwecp and swecp.
  120. }
  121. else
  122. {
  123. //HPKAssert(0, ("ECP::EnterReversePhase: - Wrong phase on enter\n"));
  124. //status = ??
  125. ParDump2(PARERRORS,("ParEcpEnterReversePhase: Wrong Phase\n"));
  126. status = STATUS_LINK_FAILED;
  127. }
  128. ParDumpReg(PAREXIT, ("ParEcpEnterReversePhase: Exit[%d]", NT_SUCCESS(status)),
  129. wPortECR,
  130. wPortDCR,
  131. Extension->Controller + OFFSET_DSR);
  132. return( status );
  133. }
  134. //=========================================================
  135. // ECP::ExitReversePhase
  136. //
  137. // Description : Transition from the ECP reverse Phase to the
  138. // common phase for all entry functions
  139. //
  140. // Input Parameters : Controller - offset to the I/O ports
  141. // pPortInfoStruct - pointer to port information
  142. //
  143. // Modifies : CurrentPhase, DCR
  144. //
  145. // Pre-conditions :
  146. //
  147. // Post-conditions : NOTE: This function does not completely move to
  148. // the common phase for entry functions. Both the
  149. // HW and SW ECP classes must do extra work
  150. //
  151. // Returns : Status of the operation
  152. //
  153. //=========================================================
  154. NTSTATUS ParEcpExitReversePhase(IN PDEVICE_EXTENSION Extension)
  155. {
  156. NTSTATUS status = STATUS_SUCCESS;
  157. PUCHAR Controller = Extension->Controller;
  158. PUCHAR wPortDCR; // I/O address of Device Control Register
  159. PUCHAR wPortECR; // I/O address of ECR
  160. UCHAR dcr;
  161. ParDump2( PARENTRY, ("ParEcpExitReversePhase: Entry \n"));
  162. wPortDCR = Controller + OFFSET_DCR;
  163. #if (0 == DVRH_USE_PARPORT_ECP_ADDR)
  164. wPortECR = Controller + ECR_OFFSET;
  165. #else
  166. wPortECR = Extension->EcrController + ECR_OFFSET;
  167. #endif
  168. //----------------------------------------------------------------------
  169. // Set status byte to indicate Reverse To Forward Mode.
  170. //----------------------------------------------------------------------
  171. ParDump2(PARECPTRACE,("ParEcpExitReversePhase: Phase_RevToFwd\n"));
  172. Extension->CurrentPhase = PHASE_REV_TO_FWD;
  173. //----------------------------------------------------------------------
  174. // Set HostAck high
  175. //----------------------------------------------------------------------
  176. dcr = READ_PORT_UCHAR(wPortDCR);
  177. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE );
  178. WRITE_PORT_UCHAR(wPortDCR, dcr);
  179. //----------------------------------------------------------------------
  180. // Set nReverseRequest high. (State 47)
  181. //----------------------------------------------------------------------
  182. Extension->CurrentEvent = 47;
  183. dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, DONT_CARE );
  184. WRITE_PORT_UCHAR(wPortDCR, dcr);
  185. //----------------------------------------------------------------------
  186. // Check first for PeriphAck low and PeriphClk high. (State 48)
  187. //----------------------------------------------------------------------
  188. Extension->CurrentEvent = 48;
  189. if ( ! CHECK_DSR(Controller, INACTIVE, ACTIVE, DONT_CARE, ACTIVE, DONT_CARE,
  190. IEEE_MAXTIME_TL) )
  191. {
  192. // Bad things happened - timed out on this state,
  193. // Mark Status as bad and let our mgr kill ECP mode.
  194. // status = SLP_RecoverPort( pSDCB, RECOVER_18 ); // Reset port.
  195. status = STATUS_LINK_FAILED;
  196. ParDump2(PARERRORS,("ParEcpExitReversePhase: state 48 Timeout\n"));
  197. goto ParEcpExitReversePhase;
  198. }
  199. //----------------------------------------------------------------------
  200. // Check next for nAckReverse high. (State 49)
  201. //----------------------------------------------------------------------
  202. Extension->CurrentEvent = 49;
  203. if ( ! CHECK_DSR(Controller ,INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE,
  204. IEEE_MAXTIME_TL ) )
  205. {
  206. // Bad things happened - timed out on this state,
  207. // Mark Status as bad and let our mgr kill ECP mode.
  208. //nError = RecoverPort( pSDCB, RECOVER_19 ); // Reset port.
  209. status = STATUS_LINK_FAILED;
  210. ParDump2(PARERRORS,("ParEcpExitReversePhase:state 49 Timeout\n"));
  211. goto ParEcpExitReversePhase;
  212. }
  213. // Warning: Don't assume that the ECR is in PS/2 mode here.
  214. // You cannot change the direction in this routine. It must be
  215. // done elsewhere (SWECP or HWECP).
  216. ParEcpExitReversePhase:
  217. ParDumpReg(PAREXIT,
  218. ("ParEcpExitReversePhase: Exit [%d]\n", NT_SUCCESS(status)),
  219. wPortECR,
  220. wPortDCR,
  221. Extension->Controller + OFFSET_DSR);
  222. ParDump2(PAREXIT,("ParEcpExitReversePhase: Exit [%d]\n", NT_SUCCESS(status)));
  223. return status;
  224. }
  225. BOOLEAN
  226. ParEcpHaveReadData (
  227. IN PDEVICE_EXTENSION Extension
  228. )
  229. {
  230. return (BOOLEAN)( (UCHAR)0 == (READ_PORT_UCHAR(Extension->Controller + OFFSET_DSR) & DSR_NOT_PERIPH_REQUEST));
  231. }
  232. NTSTATUS
  233. ParEcpSetupPhase(
  234. IN PDEVICE_EXTENSION Extension
  235. )
  236. /*++
  237. Routine Description:
  238. This routine performs 1284 Setup Phase.
  239. Arguments:
  240. Controller - Supplies the port address.
  241. Return Value:
  242. STATUS_SUCCESS - Successful negotiation.
  243. otherwise - Unsuccessful negotiation.
  244. --*/
  245. {
  246. PUCHAR Controller;
  247. UCHAR dcr;
  248. ParDump2(PARENTRY,("ParEcpSetupPhase: Start\n"));
  249. // The negotiation succeeded. Current mode and phase.
  250. //
  251. Extension->CurrentPhase = PHASE_SETUP;
  252. Controller = Extension->Controller;
  253. // Negoiate leaves us in state 6, we need to be in state 30 to
  254. // begin transfer. Note that I am assuming that the controller
  255. // is already set as it should be for state 6.
  256. //
  257. ParDump2(PARECPTRACE,("ParEcpSetupPhase: Phase_Setup\n"));
  258. // *************** State 30 Setup Phase ***************8
  259. // DIR = Don't Care
  260. // IRQEN = Don't Care
  261. // 1284/SelectIn = High
  262. // nReverseReq/**(ECP only)= High
  263. // HostAck/HostBusy = Low (Signals state 30)
  264. // HostClk/nStrobe = High
  265. //
  266. Extension->CurrentEvent = 30;
  267. dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR);
  268. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE, INACTIVE, ACTIVE);
  269. WRITE_PORT_UCHAR(Controller + OFFSET_DCR, dcr);
  270. // *************** State 31 Setup Phase ***************8
  271. // PeriphAck/PtrBusy = low
  272. // PeriphClk/PtrClk = high
  273. // nAckReverse/AckDataReq = high (Signals state 31)
  274. // XFlag = high
  275. // nPeriphReq/nDataAvail = Don't Care
  276. Extension->CurrentEvent = 31;
  277. if (!CHECK_DSR(Controller,
  278. INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE,
  279. IEEE_MAXTIME_TL))
  280. {
  281. // Bad things happened - timed out on this state.
  282. // Set status to an error and let PortTuple kill ECP mode (Terminate).
  283. ParDump2(PARERRORS, ("ParEcpSetupPhase:State 31 Failed: Controller %x dcr %x\n",
  284. Controller, dcr));
  285. Extension->CurrentPhase = PHASE_UNKNOWN;
  286. return STATUS_IO_DEVICE_ERROR;
  287. }
  288. ParDump2(PARECPTRACE,("ParEcpSetupPhase: Phase_FwdIdle\n"));
  289. Extension->CurrentPhase = PHASE_FORWARD_IDLE;
  290. ParDump2(PAREXIT,("ParEcpSetupPhase: Exit status = STATUS_SUCCESS\n"));
  291. return STATUS_SUCCESS;
  292. }