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.

389 lines
11 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. Byte.c
  5. Abstract:
  6. This module contains the code to do byte mode reads.
  7. Author:
  8. Don Redford 30-Aug-1998
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "pch.h"
  14. BOOLEAN
  15. ParIsByteSupported(
  16. IN PPDO_EXTENSION Pdx
  17. )
  18. /*++
  19. Routine Description:
  20. This routine determines whether or not byte mode is suported
  21. by trying to negotiate when asked.
  22. Arguments:
  23. Pdx - The device extension.
  24. Return Value:
  25. BOOLEAN.
  26. --*/
  27. {
  28. NTSTATUS Status;
  29. if (Pdx->BadProtocolModes & BYTE_BIDIR) {
  30. DD((PCE)Pdx,DDT,"ParIsByteSupported - BAD PROTOCOL\n");
  31. return FALSE;
  32. }
  33. if (!(Pdx->HardwareCapabilities & PPT_BYTE_PRESENT)) {
  34. DD((PCE)Pdx,DDT,"ParIsByteSupported - NO\n");
  35. return FALSE;
  36. }
  37. if (Pdx->ProtocolModesSupported & BYTE_BIDIR) {
  38. DD((PCE)Pdx,DDT,"ParIsByteSupported - Already Checked - YES\n");
  39. return TRUE;
  40. }
  41. // Must use Byte Enter and Terminate for this test.
  42. // Internel state machines will fail otherwise. --dvrh
  43. Status = ParEnterByteMode (Pdx, FALSE);
  44. ParTerminateByteMode (Pdx);
  45. if (NT_SUCCESS(Status)) {
  46. DD((PCE)Pdx,DDT,"ParIsByteSupported - SUCCESS\n");
  47. Pdx->ProtocolModesSupported |= BYTE_BIDIR;
  48. return TRUE;
  49. }
  50. DD((PCE)Pdx,DDT,"ParIsByteSupported - UNSUCCESSFUL\n");
  51. return FALSE;
  52. }
  53. NTSTATUS
  54. ParEnterByteMode(
  55. IN PPDO_EXTENSION Pdx,
  56. IN BOOLEAN DeviceIdRequest
  57. )
  58. /*++
  59. Routine Description:
  60. This routine performs 1284 negotiation with the peripheral to the
  61. byte mode protocol.
  62. Arguments:
  63. Controller - Supplies the port address.
  64. DeviceIdRequest - Supplies whether or not this is a request for a device
  65. id.
  66. Return Value:
  67. STATUS_SUCCESS - Successful negotiation.
  68. otherwise - Unsuccessful negotiation.
  69. --*/
  70. {
  71. NTSTATUS Status = STATUS_SUCCESS;
  72. // Make sure Byte mode Harware is still there
  73. Status = Pdx->TrySetChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
  74. if( NT_SUCCESS(Status) ) {
  75. if ( SAFE_MODE == Pdx->ModeSafety ) {
  76. if( DeviceIdRequest ) {
  77. // RMT - not sure if we want to support non-nibble 1284 ID query
  78. Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY | DEVICE_ID_REQ );
  79. } else {
  80. Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY );
  81. }
  82. } else {
  83. // UNSAFE_MODE
  84. Pdx->Connected = TRUE;
  85. }
  86. }
  87. if (NT_SUCCESS(Status)) {
  88. P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
  89. Pdx->IsIeeeTerminateOk = TRUE;
  90. } else {
  91. ParTerminateByteMode ( Pdx );
  92. P5SetPhase( Pdx, PHASE_UNKNOWN );
  93. Pdx->IsIeeeTerminateOk = FALSE;
  94. }
  95. DD((PCE)Pdx,DDT,"ParEnterByteMode - exit w/Status=%x\n",Status);
  96. return Status;
  97. }
  98. VOID
  99. ParTerminateByteMode(
  100. IN PPDO_EXTENSION Pdx
  101. )
  102. /*++
  103. Routine Description:
  104. This routine terminates the interface back to compatibility mode.
  105. Arguments:
  106. Controller - Supplies the parallel port's controller address.
  107. Return Value:
  108. None.
  109. --*/
  110. {
  111. if ( Pdx->ModeSafety == SAFE_MODE ) {
  112. IeeeTerminate1284Mode( Pdx );
  113. } else {
  114. Pdx->Connected = FALSE;
  115. }
  116. Pdx->ClearChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
  117. DD((PCE)Pdx,DDT,"ParTerminateByteMode - exit\n");
  118. }
  119. NTSTATUS
  120. ParByteModeRead(
  121. IN PPDO_EXTENSION Pdx,
  122. IN PVOID Buffer,
  123. IN ULONG BufferSize,
  124. OUT PULONG BytesTransferred
  125. )
  126. /*++
  127. Routine Description:
  128. This routine performs a 1284 byte mode read into the given
  129. buffer for no more than 'BufferSize' bytes.
  130. Arguments:
  131. Pdx - Supplies the device extension.
  132. Buffer - Supplies the buffer to read into.
  133. BufferSize - Supplies the number of bytes in the buffer.
  134. BytesTransferred - Returns the number of bytes transferred.
  135. --*/
  136. {
  137. PUCHAR Controller;
  138. NTSTATUS Status = STATUS_SUCCESS;
  139. PUCHAR lpsBufPtr = (PUCHAR)Buffer;
  140. ULONG i;
  141. UCHAR dsr, dcr;
  142. UCHAR HDReady, HDAck, HDFinished;
  143. Controller = Pdx->Controller;
  144. // Read Byte according to 1284 spec.
  145. DD((PCE)Pdx,DDT,"ParByteModeRead: Start\n");
  146. dcr = GetControl (Controller);
  147. // Set Direction to be in reverse
  148. dcr |= DCR_DIRECTION;
  149. StoreControl (Controller, dcr);
  150. HDReady = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, INACTIVE, ACTIVE );
  151. HDAck = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, ACTIVE, INACTIVE );
  152. HDFinished = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, ACTIVE, ACTIVE );
  153. switch( Pdx->CurrentPhase ) {
  154. case PHASE_REVERSE_IDLE:
  155. // Check to see if the peripheral has indicated Interrupt Phase and if so,
  156. // get us ready to reverse transfer.
  157. for (;;) {
  158. // See if data is available (looking for state 7)
  159. dsr = GetStatus(Controller);
  160. if (dsr & DSR_NOT_DATA_AVAIL) {
  161. // Data is NOT available - do nothing
  162. // The device doesn't report any data, it still looks like it is
  163. // in ReverseIdle. Just to make sure it hasn't powered off or somehow
  164. // jumped out of Byte mode, test also for AckDataReq high and XFlag low
  165. // and nDataAvaul high.
  166. if( (dsr & DSR_BYTE_VALIDATION) != DSR_BYTE_TEST_RESULT ) {
  167. Status = STATUS_IO_DEVICE_ERROR;
  168. P5SetPhase( Pdx, PHASE_UNKNOWN );
  169. DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 7 - dcr=%x\n",dcr);
  170. }
  171. goto ByteReadExit;
  172. } else {
  173. // Data is available, go to Reverse Transfer Phase
  174. P5SetPhase( Pdx, PHASE_REVERSE_XFER);
  175. // Go to Reverse XFER phase
  176. goto PhaseReverseXfer;
  177. }
  178. }
  179. PhaseReverseXfer:
  180. case PHASE_REVERSE_XFER:
  181. for (i = 0; i < BufferSize; i++) {
  182. // Host enters state 7
  183. StoreControl (Controller, HDReady);
  184. // =============== Periph State 9 ===============8
  185. // PeriphAck/PtrBusy = Don't Care
  186. // PeriphClk/PtrClk = low (signals state 9)
  187. // nAckReverse/AckDataReq = Don't Care
  188. // XFlag = Don't Care
  189. // nPeriphReq/nDataAvail = Don't Care
  190. if (!CHECK_DSR(Controller, DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE, DONT_CARE, IEEE_MAXTIME_TL)) {
  191. // Time out.
  192. // Bad things happened - timed out on this state,
  193. // Mark Status as bad and let our mgr kill current mode.
  194. Status = STATUS_IO_DEVICE_ERROR;
  195. DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 9 - dcr=%x\n",dcr);
  196. P5SetPhase( Pdx, PHASE_UNKNOWN );
  197. goto ByteReadExit;
  198. }
  199. // Read the Byte
  200. P5ReadPortBufferUchar( Controller, lpsBufPtr++, (ULONG)0x01 );
  201. // Set host lines to indicate state 10.
  202. StoreControl (Controller, HDAck);
  203. // =============== Periph State 11 ===============8
  204. // PeriphAck/PtrBusy = Don't Care
  205. // PeriphClk/PtrClk = High (signals state 11)
  206. // nAckReverse/AckDataReq = Don't Care
  207. // XFlag = Don't Care
  208. // nPeriphReq/nDataAvail = Don't Care
  209. if( !CHECK_DSR(Controller, DONT_CARE, ACTIVE, DONT_CARE, DONT_CARE, DONT_CARE, IEEE_MAXTIME_TL)) {
  210. // Time out.
  211. // Bad things happened - timed out on this state,
  212. // Mark Status as bad and let our mgr kill current mode.
  213. Status = STATUS_IO_DEVICE_ERROR;
  214. DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 11 - dcr=%x\n",dcr);
  215. P5SetPhase( Pdx, PHASE_UNKNOWN );
  216. goto ByteReadExit;
  217. }
  218. // Set host lines to indicate state 16.
  219. StoreControl (Controller, HDFinished);
  220. // At this point, we've either received the number of bytes we
  221. // were looking for, or the peripheral has no more data to
  222. // send, or there was an error of some sort (of course, in the
  223. // error case we shouldn't get to this comment). Set the
  224. // phase to indicate reverse idle if no data available or
  225. // reverse data transfer if there's some waiting for us
  226. // to get next time.
  227. dsr = GetStatus(Controller);
  228. if (dsr & DSR_NOT_DATA_AVAIL) {
  229. // Data is NOT available - go to Reverse Idle
  230. // Really we are going to HBDNA, but if we set
  231. // current phase to reverse idle, the next time
  232. // we get into this function all we have to do
  233. // is set hostbusy low to indicate idle and
  234. // we have infinite time to do that.
  235. // Break out of the loop so we don't try to read
  236. // data that isn't there.
  237. // NOTE - this is a successful case even if we
  238. // didn't read all that the caller requested
  239. P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
  240. i++; // account for this last byte transferred
  241. break;
  242. } else {
  243. // Data is available, go to (remain in ) Reverse Transfer Phase
  244. P5SetPhase( Pdx, PHASE_REVERSE_XFER);
  245. }
  246. } // end for i loop
  247. *BytesTransferred = i;
  248. dsr = GetStatus(Controller);
  249. // DON'T FALL THRU THIS ONE
  250. break;
  251. default:
  252. Status = STATUS_IO_DEVICE_ERROR;
  253. P5SetPhase( Pdx, PHASE_UNKNOWN );
  254. DD((PCE)Pdx,DDE,"ParByteModeRead:Failed State 9: Unknown Phase - dcr=%x\n",dcr);
  255. goto ByteReadExit;
  256. } // end switch
  257. ByteReadExit:
  258. if( Pdx->CurrentPhase == PHASE_REVERSE_IDLE ) {
  259. // Host enters state 7 - officially in Reverse Idle now
  260. dcr |= DCR_NOT_HOST_BUSY;
  261. StoreControl (Controller, dcr);
  262. }
  263. // Set Direction to be in forward
  264. dcr &= ~DCR_DIRECTION;
  265. StoreControl (Controller, dcr);
  266. DD((PCE)Pdx,DDT,"ParByteModeRead - exit, status=%x, bytes read=%d\n", Status, *BytesTransferred);
  267. Pdx->log.ByteReadCount += *BytesTransferred;
  268. return Status;
  269. }