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.

348 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. becp.c
  5. Abstract:
  6. This module contains code for the host to utilize BoundedECP if it has been
  7. detected and successfully enabled.
  8. Author:
  9. Robbie Harris (Hewlett-Packard) 27-May-1998
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "pch.h"
  15. NTSTATUS
  16. PptBecpExitReversePhase(
  17. IN PPDO_EXTENSION Pdx
  18. )
  19. {
  20. //
  21. // When using BECP, test nPeriphRequest prior to negotiation
  22. // from reverse phase to forward phase. Do not negotiate unless the
  23. // peripheral indicates it is finished sending. If using any other
  24. // mode, negotiate immediately.
  25. //
  26. if( SAFE_MODE == Pdx->ModeSafety ) {
  27. if( PHASE_REVERSE_IDLE == Pdx->CurrentPhase ) {
  28. if( !CHECK_DSR( Pdx->Controller, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, IEEE_MAXTIME_TL) ) {
  29. DD((PCE)Pdx,DDT,"PptBecpExitReversePhase: Periph Stuck. Can't Flip Bus\n");
  30. return STATUS_IO_TIMEOUT;
  31. }
  32. }
  33. }
  34. return ParEcpHwExitReversePhase( Pdx );
  35. }
  36. //============================================================================
  37. // NAME: ECPFrame::Read()
  38. //
  39. //
  40. // LAC FRAME 12Dec97
  41. // This function is used for two different kinds of reads:
  42. // 1) continuing read - where we don't expect to exit reverse mode afterwards
  43. // 2) non-continuing read - where we expect to exit reverse mode afterwards
  44. // The problem is that we have no way of knowing which is which. I can
  45. // either wait after each read for nPeriphRequest to drop, or I can
  46. // check to see if it has dropped when I enter and handle it then.
  47. //
  48. // The other problem is that we have no way of communicating the fact that
  49. // we have done this to the PortTuple. It uses the last_direction member
  50. // to decide whether it should even look at entering or exiting some phase.
  51. //
  52. // Lets face it, we are on our own with this. It is safer to leave it
  53. // connected and then try to straighten things out when we come back. I
  54. // know that this wastes some time, but so does waiting at the end of
  55. // every read when only half of them are going to drop the nPeriphRequest.
  56. //
  57. // This routine performs a 1284 ECP mode read into the given
  58. // buffer for no more than 'BufferSize' bytes.
  59. //
  60. // This routine runs at DISPATCH_LEVEL.
  61. //
  62. // PARAMETERS:
  63. // Controller - Supplies the base address of the parallel port.
  64. // pPortInfoStruct - Supplies port information as defined in p1284.h
  65. // Buffer - Supplies the buffer to read into.
  66. // BufferSize - Supplies the number of bytes in the buffer.
  67. // BytesTransferred - Returns the number of bytes transferred.
  68. //
  69. // RETURNS:
  70. // NTSTATUS STATUS_SUCCESS or...
  71. // The number of bytes successfully read from the port is
  72. // returned via one of the arguments passed into this method.
  73. //
  74. // NOTES:
  75. // - Called ECP_PatchReverseTransfer in the original 16 bit code.
  76. //
  77. //============================================================================
  78. NTSTATUS
  79. PptBecpRead(
  80. IN PPDO_EXTENSION Pdx,
  81. IN PVOID Buffer,
  82. IN ULONG BufferSize,
  83. OUT PULONG BytesTransferred
  84. )
  85. {
  86. NTSTATUS status = STATUS_SUCCESS;
  87. DD((PCE)Pdx,DDT,"PptBecpRead: Enter BufferSize[%d]\n", BufferSize);
  88. status = ParEcpHwRead( Pdx, Buffer, BufferSize, BytesTransferred );
  89. if (NT_SUCCESS(status)) {
  90. PUCHAR Controller;
  91. Controller = Pdx->Controller;
  92. if ( CHECK_DSR_WITH_FIFO( Controller, DONT_CARE, DONT_CARE, INACTIVE, ACTIVE, ACTIVE,
  93. ECR_FIFO_EMPTY, ECR_FIFO_SOME_DATA,
  94. DEFAULT_RECEIVE_TIMEOUT) ) {
  95. DD((PCE)Pdx,DDT,"PptBecpRead: No more data. Flipping to Fwd\n");
  96. //
  97. // Bounded ECP rule - no more data from periph - flip bus to forward
  98. //
  99. status = ParReverseToForward( Pdx );
  100. } else {
  101. UCHAR bDSR = P5ReadPortUchar( Controller + OFFSET_DSR );
  102. //
  103. // Periph still has data, check for valid state
  104. //
  105. DD((PCE)Pdx,DDT,"PptBecpRead: Periph says there is more data. Checking for stall.\n");
  106. // It's OK for the device to continue asserting nPeriphReq,
  107. // it may have more data to send. However, nAckReverse and
  108. // XFlag should be in a known state, so double check them.
  109. if ( ! TEST_DSR( bDSR, DONT_CARE, DONT_CARE, INACTIVE, ACTIVE, DONT_CARE ) ) {
  110. #if DVRH_BUS_RESET_ON_ERROR
  111. BusReset(Controller + OFFSET_DCR); // Pass in the dcr address
  112. #endif
  113. status = STATUS_LINK_FAILED;
  114. DD((PCE)Pdx,DDT,"PptBecpRead: nAckReverse and XFlag are bad.\n");
  115. } else {
  116. //
  117. // Periph has correctly acknowledged that it has data (state valid)
  118. //
  119. if ( (TRUE == Pdx->P12843DL.bEventActive) ) {
  120. //
  121. // Signal transport (e.g., dot4) that data is avail
  122. //
  123. KeSetEvent(Pdx->P12843DL.Event, 0, FALSE);
  124. }
  125. }
  126. }
  127. }
  128. DD((PCE)Pdx,DDT,"PptBecpRead: exit - status %x - BytesTransferred[%d]\n", status, *BytesTransferred);
  129. return status;
  130. }
  131. NTSTATUS
  132. PptEnterBecpMode(
  133. IN PPDO_EXTENSION Pdx,
  134. IN BOOLEAN DeviceIdRequest
  135. )
  136. /*++
  137. Routine Description:
  138. This routine performs 1284 negotiation with the peripheral to the
  139. BECP mode protocol.
  140. Arguments:
  141. Controller - Supplies the port address.
  142. DeviceIdRequest - FALSE - driver only supports Device ID Query in NIBBLE mode
  143. Return Value:
  144. STATUS_SUCCESS - Successful negotiation.
  145. otherwise - Unsuccessful negotiation.
  146. --*/
  147. {
  148. NTSTATUS status = STATUS_SUCCESS;
  149. if( DeviceIdRequest ) {
  150. // driver error if we hit this assert
  151. PptAssert(FALSE == DeviceIdRequest);
  152. status = STATUS_INVALID_PARAMETER;
  153. goto targetExit;
  154. }
  155. if( SAFE_MODE == Pdx->ModeSafety ) {
  156. status = IeeeEnter1284Mode( Pdx, BECP_EXTENSIBILITY );
  157. } else {
  158. Pdx->Connected = TRUE;
  159. }
  160. if( STATUS_SUCCESS == status ) {
  161. status = ParEcpHwSetupPhase( Pdx );
  162. Pdx->bSynchWrites = TRUE; // NOTE this is a temp hack!!! dvrh
  163. if (!Pdx->bShadowBuffer) {
  164. Queue_Create(&(Pdx->ShadowBuffer), Pdx->FifoDepth * 2);
  165. Pdx->bShadowBuffer = TRUE;
  166. }
  167. Pdx->IsIeeeTerminateOk = TRUE;
  168. }
  169. targetExit:
  170. DD((PCE)Pdx,DDT,"PptEnterBecpMode - exit w/status %x\n", status);
  171. return status;
  172. }
  173. BOOLEAN
  174. PptIsBecpSupported(
  175. IN PPDO_EXTENSION Pdx
  176. )
  177. /*++
  178. Routine Description:
  179. This routine determines whether or not ECP mode is suported
  180. in the write direction by trying to negotiate when asked.
  181. Arguments:
  182. Pdx - The device extension.
  183. Return Value:
  184. BOOLEAN.
  185. --*/
  186. {
  187. NTSTATUS status;
  188. if( Pdx->BadProtocolModes & BOUNDED_ECP ) {
  189. DD((PCE)Pdx,DDT,"PptIsBecpSupported - FAILED - BOUNDED_ECP in BadProtocolModes\n");
  190. return FALSE;
  191. }
  192. if( Pdx->ProtocolModesSupported & BOUNDED_ECP ) {
  193. DD((PCE)Pdx,DDT,"PptIsBecpSupported - PASSED - BOUNDED_ECP already cheacked\n");
  194. return TRUE;
  195. }
  196. if( !(Pdx->HardwareCapabilities & PPT_ECP_PRESENT) ) {
  197. DD((PCE)Pdx,DDT,"PptIsBecpSupported - FAILED - HWECP not avail\n");
  198. return FALSE;
  199. }
  200. if( 0 == Pdx->FifoWidth ) {
  201. DD((PCE)Pdx,DDT,"PptIsBecpSupported - FAILED - 0 == FifoWidth\n");
  202. return FALSE;
  203. }
  204. // Must use BECP Enter and Terminate for this test.
  205. // Internel state machines will fail otherwise. --dvrh
  206. status = PptEnterBecpMode( Pdx, FALSE );
  207. PptTerminateBecpMode( Pdx );
  208. if( STATUS_SUCCESS == status ) {
  209. Pdx->ProtocolModesSupported |= BOUNDED_ECP;
  210. DD((PCE)Pdx,DDT,"PptIsBecpSupported - PASSED\n");
  211. return TRUE;
  212. } else {
  213. DD((PCE)Pdx,DDT,"PptIsBecpSupported - FAILED - BOUNDED_ECP negotiate failed\n");
  214. return FALSE;
  215. }
  216. }
  217. VOID
  218. PptTerminateBecpMode(
  219. IN PPDO_EXTENSION Pdx
  220. )
  221. /*++
  222. Routine Description:
  223. This routine terminates the interface back to compatibility mode.
  224. Arguments:
  225. Controller - Supplies the parallel port's controller address.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. DD((PCE)Pdx,DDT,"PptTerminateBecpMode - Enter - CurrentPhase %x\n", Pdx->CurrentPhase);
  231. // Need to check current phase -- if its reverse, need to flip bus
  232. // If its not forward -- its an incorrect phase and termination will fail.
  233. switch (Pdx->CurrentPhase) {
  234. case PHASE_FORWARD_IDLE: // Legal state to terminate
  235. break;
  236. case PHASE_REVERSE_IDLE: // Flip the bus so we can terminate
  237. {
  238. NTSTATUS status = ParEcpHwExitReversePhase( Pdx );
  239. if( STATUS_SUCCESS == status ) {
  240. status = ParEcpEnterForwardPhase(Pdx );
  241. } else {
  242. DD((PCE)Pdx,DDT,"PptTerminateBecpMode: Couldn't flip the bus\n");
  243. }
  244. }
  245. break;
  246. case PHASE_FORWARD_XFER:
  247. case PHASE_REVERSE_XFER:
  248. // Dunno what to do here. We probably will confuse the peripheral.
  249. DD((PCE)Pdx,DDE,"PptTerminateBecpMode: invalid wCurrentPhase (XFer in progress)\n");
  250. break;
  251. case PHASE_TERMINATE:
  252. // Included PHASE_TERMINATE in the switch so we won't return
  253. // an error if we are already terminated. We are already
  254. // terminated, nothing more to do.
  255. break;
  256. default:
  257. DD((PCE)Pdx,DDE,"PptTerminateBecpMode: invalid CurrentPhase %x\n", Pdx->CurrentPhase);
  258. // Dunno what to do here. We're lost and don't have a map to figure out where we are!
  259. break;
  260. }
  261. ParEcpHwWaitForEmptyFIFO( Pdx );
  262. ParCleanupHwEcpPort( Pdx );
  263. if ( Pdx->ModeSafety == SAFE_MODE ) {
  264. IeeeTerminate1284Mode( Pdx );
  265. } else {
  266. Pdx->Connected = FALSE;
  267. }
  268. return;
  269. }