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.

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