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.

552 lines
14 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. epp.c
  5. Abstract:
  6. This module contains the code to perform all EPP related tasks (including
  7. EPP Software and EPP Hardware modes.)
  8. Author:
  9. Timothy T. Wells (WestTek, L.L.C.) - April 16, 1997
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "pch.h"
  15. BOOLEAN
  16. ParIsEppSwWriteSupported(
  17. IN PPDO_EXTENSION Pdx
  18. );
  19. BOOLEAN
  20. ParIsEppSwReadSupported(
  21. IN PPDO_EXTENSION Pdx
  22. );
  23. NTSTATUS
  24. ParEnterEppSwMode(
  25. IN PPDO_EXTENSION Pdx,
  26. IN BOOLEAN DeviceIdRequest
  27. );
  28. VOID
  29. ParTerminateEppSwMode(
  30. IN PPDO_EXTENSION Pdx
  31. );
  32. NTSTATUS
  33. ParEppSwWrite(
  34. IN PPDO_EXTENSION Pdx,
  35. IN PVOID Buffer,
  36. IN ULONG BufferSize,
  37. OUT PULONG BytesTransferred
  38. );
  39. NTSTATUS
  40. ParEppSwRead(
  41. IN PPDO_EXTENSION Pdx,
  42. IN PVOID Buffer,
  43. IN ULONG BufferSize,
  44. OUT PULONG BytesTransferred
  45. );
  46. BOOLEAN
  47. ParIsEppSwWriteSupported(
  48. IN PPDO_EXTENSION Pdx
  49. )
  50. /*++
  51. Routine Description:
  52. This routine determines whether or not EPP mode is suported
  53. in the write direction by trying negotiate when asked.
  54. Arguments:
  55. Pdx - The device extension.
  56. Return Value:
  57. BOOLEAN.
  58. --*/
  59. {
  60. NTSTATUS Status;
  61. // dvdr
  62. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Entering\n");
  63. if (!(Pdx->HardwareCapabilities & PPT_ECP_PRESENT) &&
  64. !(Pdx->HardwareCapabilities & PPT_BYTE_PRESENT)) {
  65. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Hardware Not Supported Leaving\n");
  66. // Only use EPP Software in the reverse direction if an ECR is
  67. // present or we know that we can put the data register into Byte mode.
  68. return FALSE;
  69. }
  70. if (Pdx->BadProtocolModes & EPP_SW) {
  71. // dvdr
  72. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Not Supported Leaving\n");
  73. return FALSE;
  74. }
  75. if (Pdx->ProtocolModesSupported & EPP_SW) {
  76. // dvdr
  77. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Supported Leaving\n");
  78. return TRUE;
  79. }
  80. // Must use SWEPP Enter and Terminate for this test.
  81. // Internel state machines will fail otherwise. --dvrh
  82. Status = ParEnterEppSwMode (Pdx, FALSE);
  83. ParTerminateEppSwMode (Pdx);
  84. if (NT_SUCCESS(Status)) {
  85. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Negotiated Supported Leaving\n");
  86. Pdx->ProtocolModesSupported |= EPP_SW;
  87. return TRUE;
  88. }
  89. DD((PCE)Pdx,DDT,"ParIsEppSwWriteSupported: Not Negotiated Not Supported Leaving\n");
  90. return FALSE;
  91. }
  92. BOOLEAN
  93. ParIsEppSwReadSupported(
  94. IN PPDO_EXTENSION Pdx
  95. )
  96. /*++
  97. Routine Description:
  98. This routine determines whether or not EPP mode is suported
  99. in the read direction (need to be able to float the data register
  100. drivers in order to do byte wide reads) by trying negotiate when asked.
  101. Arguments:
  102. Pdx - The device extension.
  103. Return Value:
  104. BOOLEAN.
  105. --*/
  106. {
  107. NTSTATUS Status;
  108. if (!(Pdx->HardwareCapabilities & PPT_ECP_PRESENT) &&
  109. !(Pdx->HardwareCapabilities & PPT_BYTE_PRESENT)) {
  110. DD((PCE)Pdx,DDT,"ParIsEppSwReadSupported: Hardware Not Supported Leaving\n");
  111. // Only use EPP Software in the reverse direction if an ECR is
  112. // present or we know that we can put the data register into Byte mode.
  113. return FALSE;
  114. }
  115. if (Pdx->BadProtocolModes & EPP_SW)
  116. return FALSE;
  117. if (Pdx->ProtocolModesSupported & EPP_SW)
  118. return TRUE;
  119. // Must use SWEPP Enter and Terminate for this test.
  120. // Internel state machines will fail otherwise. --dvrh
  121. Status = ParEnterEppSwMode (Pdx, FALSE);
  122. ParTerminateEppSwMode (Pdx);
  123. if (NT_SUCCESS(Status)) {
  124. DD((PCE)Pdx,DDT,"ParIsEppSwReadSupported: Negotiated Supported Leaving\n");
  125. Pdx->ProtocolModesSupported |= EPP_SW;
  126. return TRUE;
  127. }
  128. DD((PCE)Pdx,DDT,"ParIsEppSwReadSupported: Not Negotiated Not Supported Leaving\n");
  129. return FALSE;
  130. }
  131. NTSTATUS
  132. ParEnterEppSwMode(
  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. EPP mode protocol.
  140. Arguments:
  141. Controller - Supplies the port address.
  142. DeviceIdRequest - Supplies whether or not this is a request for a device
  143. id.
  144. Return Value:
  145. STATUS_SUCCESS - Successful negotiation.
  146. otherwise - Unsuccessful negotiation.
  147. --*/
  148. {
  149. NTSTATUS Status = STATUS_SUCCESS;
  150. // dvdr
  151. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: Entering\n");
  152. // Parport Set Chip mode will put the Chip into Byte Mode if Capable
  153. // We need it for Epp Sw Mode
  154. Status = Pdx->TrySetChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
  155. if ( NT_SUCCESS(Status) ) {
  156. if ( Pdx->ModeSafety == SAFE_MODE ) {
  157. if (DeviceIdRequest) {
  158. // dvdr
  159. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: Calling IeeeEnter1284Mode with DEVICE_ID_REQUEST\n");
  160. Status = IeeeEnter1284Mode (Pdx, EPP_EXTENSIBILITY | DEVICE_ID_REQ);
  161. } else {
  162. // dvdr
  163. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: Calling IeeeEnter1284Mode\n");
  164. Status = IeeeEnter1284Mode (Pdx, EPP_EXTENSIBILITY);
  165. }
  166. } else {
  167. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: In UNSAFE_MODE.\n");
  168. Pdx->Connected = TRUE;
  169. }
  170. }
  171. if ( NT_SUCCESS(Status) ) {
  172. // dvdr
  173. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: IeeeEnter1284Mode returned success\n");
  174. P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
  175. Pdx->IsIeeeTerminateOk = TRUE;
  176. } else {
  177. // dvdr
  178. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: IeeeEnter1284Mode returned unsuccessful\n");
  179. P5SetPhase( Pdx, PHASE_UNKNOWN );
  180. Pdx->IsIeeeTerminateOk = FALSE;
  181. }
  182. DD((PCE)Pdx,DDT,"ParEnterEppSwMode: Leaving with Status : %x \n", Status);
  183. return Status;
  184. }
  185. VOID
  186. ParTerminateEppSwMode(
  187. IN PPDO_EXTENSION Pdx
  188. )
  189. /*++
  190. Routine Description:
  191. This routine terminates the interface back to compatibility mode.
  192. Arguments:
  193. Pdx - The Device Extension which has the parallel port's controller address.
  194. Return Value:
  195. None.
  196. --*/
  197. {
  198. // dvdr
  199. DD((PCE)Pdx,DDT,"ParTerminateEppMode: Entering\n");
  200. if ( Pdx->ModeSafety == SAFE_MODE ) {
  201. IeeeTerminate1284Mode (Pdx);
  202. } else {
  203. DD((PCE)Pdx,DDT,"ParTerminateEppMode: In UNSAFE_MODE.\n");
  204. Pdx->Connected = FALSE;
  205. }
  206. Pdx->ClearChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
  207. DD((PCE)Pdx,DDT,"ParTerminateEppMode: Leaving\n");
  208. return;
  209. }
  210. NTSTATUS
  211. ParEppSwWrite(
  212. IN PPDO_EXTENSION Pdx,
  213. IN PVOID Buffer,
  214. IN ULONG BufferSize,
  215. OUT PULONG BytesTransferred
  216. )
  217. /*++
  218. Routine Description:
  219. Writes data to the peripheral using the EPP protocol under software
  220. control.
  221. Arguments:
  222. Pdx - Supplies the device extension.
  223. Buffer - Supplies the buffer to write from.
  224. BufferSize - Supplies the number of bytes in the buffer.
  225. BytesTransferred - Returns the number of bytes transferred.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. PUCHAR Controller;
  231. PUCHAR pBuffer = (PUCHAR)Buffer;
  232. NTSTATUS Status = STATUS_SUCCESS;
  233. ULONG i, j;
  234. UCHAR HDReady, HDAck, HDFinished;
  235. // dvdr
  236. DD((PCE)Pdx,DDT,"ParEppSwWrite: Entering\n");
  237. Controller = Pdx->Controller;
  238. P5SetPhase( Pdx, PHASE_FORWARD_XFER );
  239. // BIT5 of DCR needs to be low to be in BYTE forward mode
  240. HDReady = SET_DCR( INACTIVE, INACTIVE, ACTIVE, ACTIVE, INACTIVE, INACTIVE );
  241. HDAck = SET_DCR( INACTIVE, INACTIVE, ACTIVE, ACTIVE, ACTIVE, INACTIVE );
  242. HDFinished = SET_DCR( INACTIVE, INACTIVE, ACTIVE, ACTIVE, ACTIVE, ACTIVE );
  243. for (i = 0; i < BufferSize; i++) {
  244. // dvdr
  245. DD((PCE)Pdx,DDT,"ParEppSwWrite: Writing Byte to port\n");
  246. P5WritePortBufferUchar( Controller, pBuffer++, (ULONG)0x01 );
  247. //
  248. // Event 62
  249. //
  250. StoreControl (Controller, HDReady);
  251. // =============== Periph State 58 ===============
  252. // Should wait up to 10 micro Seconds but waiting up
  253. // to 15 micro just in case
  254. for ( j = 16; j > 0; j-- ) {
  255. if( !(GetStatus(Controller) & DSR_NOT_BUSY) )
  256. break;
  257. KeStallExecutionProcessor(1);
  258. }
  259. // see if we timed out on state 58
  260. if ( !j ) {
  261. // Time out.
  262. // Bad things happened - timed out on this state,
  263. // Mark Status as bad and let our mgr kill current mode.
  264. Status = STATUS_IO_DEVICE_ERROR;
  265. DD((PCE)Pdx,DDE,"ParEppSwModeWrite:Failed State 58: Controller %x\n", Controller);
  266. P5SetPhase( Pdx, PHASE_UNKNOWN );
  267. break;
  268. }
  269. //
  270. // Event 63
  271. //
  272. StoreControl (Controller, HDAck);
  273. // =============== Periph State 60 ===============
  274. // Should wait up to 125 nano Seconds but waiting up
  275. // to 5 micro seconds just in case
  276. for ( j = 6; j > 0; j-- ) {
  277. if( GetStatus(Controller) & DSR_NOT_BUSY )
  278. break;
  279. KeStallExecutionProcessor(1);
  280. }
  281. if( !j ) {
  282. // Time out.
  283. // Bad things happened - timed out on this state,
  284. // Mark Status as bad and let our mgr kill current mode.
  285. Status = STATUS_IO_DEVICE_ERROR;
  286. DD((PCE)Pdx,DDE,"ParEppSwModeWrite:Failed State 60: Controller %x\n", Controller);
  287. P5SetPhase( Pdx, PHASE_UNKNOWN );
  288. break;
  289. }
  290. //
  291. // Event 61
  292. //
  293. StoreControl (Controller, HDFinished);
  294. // Stall a little bit between data bytes
  295. KeStallExecutionProcessor(1);
  296. }
  297. *BytesTransferred = i;
  298. // dvdr
  299. DD((PCE)Pdx,DDT,"ParEppSwWrite: Leaving with %i Bytes Transferred\n", i);
  300. if ( Status == STATUS_SUCCESS )
  301. P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
  302. return Status;
  303. }
  304. NTSTATUS
  305. ParEppSwRead(
  306. IN PPDO_EXTENSION Pdx,
  307. IN PVOID Buffer,
  308. IN ULONG BufferSize,
  309. OUT PULONG BytesTransferred
  310. )
  311. /*++
  312. Routine Description:
  313. This routine performs a 1284 EPP mode read under software control
  314. into the given buffer for no more than 'BufferSize' bytes.
  315. Arguments:
  316. Pdx - Supplies the device extension.
  317. Buffer - Supplies the buffer to read into.
  318. BufferSize - Supplies the number of bytes in the buffer.
  319. BytesTransferred - Returns the number of bytes transferred.
  320. --*/
  321. {
  322. PUCHAR Controller;
  323. PUCHAR pBuffer = (PUCHAR)Buffer;
  324. NTSTATUS Status = STATUS_SUCCESS;
  325. ULONG i, j;
  326. UCHAR dcr;
  327. UCHAR HDReady, HDAck;
  328. // dvdr
  329. DD((PCE)Pdx,DDT,"ParEppSwRead: Entering\n");
  330. Controller = Pdx->Controller;
  331. P5SetPhase( Pdx, PHASE_REVERSE_XFER );
  332. // Save off Control
  333. dcr = GetControl (Controller);
  334. // BIT5 of DCR needs to be high to be in BYTE reverse mode
  335. HDReady = SET_DCR( ACTIVE, INACTIVE, ACTIVE, ACTIVE, INACTIVE, ACTIVE );
  336. HDAck = SET_DCR( ACTIVE, INACTIVE, ACTIVE, ACTIVE, ACTIVE, ACTIVE );
  337. // First time to get into reverse mode quickly
  338. StoreControl (Controller, HDReady);
  339. for (i = 0; i < BufferSize; i++) {
  340. //
  341. // Event 67
  342. //
  343. StoreControl (Controller, HDReady);
  344. // =============== Periph State 58 ===============
  345. // Should wait up to 10 micro Seconds but waiting up
  346. // to 15 micro just in case
  347. for ( j = 16; j > 0; j-- ) {
  348. if( !(GetStatus(Controller) & DSR_NOT_BUSY) )
  349. break;
  350. KeStallExecutionProcessor(1);
  351. }
  352. // see if we timed out on state 58
  353. if ( !j ) {
  354. // Time out.
  355. // Bad things happened - timed out on this state,
  356. // Mark Status as bad and let our mgr kill current mode.
  357. Status = STATUS_IO_DEVICE_ERROR;
  358. DD((PCE)Pdx,DDE,"ParEppSwRead:Failed State 58: Controller %x\n", Controller);
  359. P5SetPhase( Pdx, PHASE_UNKNOWN );
  360. break;
  361. }
  362. // Read the Byte
  363. P5ReadPortBufferUchar( Controller,
  364. pBuffer++,
  365. (ULONG)0x01 );
  366. //
  367. // Event 63
  368. //
  369. StoreControl (Controller, HDAck);
  370. // =============== Periph State 60 ===============
  371. // Should wait up to 125 nano Seconds but waiting up
  372. // to 5 micro seconds just in case
  373. for ( j = 6; j > 0; j-- ) {
  374. if( GetStatus(Controller) & DSR_NOT_BUSY )
  375. break;
  376. KeStallExecutionProcessor(1);
  377. }
  378. if( !j ) {
  379. // Time out.
  380. // Bad things happened - timed out on this state,
  381. // Mark Status as bad and let our mgr kill current mode.
  382. Status = STATUS_IO_DEVICE_ERROR;
  383. DD((PCE)Pdx,DDE,"ParEppSwRead:Failed State 60: Controller %x\n", Controller);
  384. P5SetPhase( Pdx, PHASE_UNKNOWN );
  385. break;
  386. }
  387. // Stall a little bit between data bytes
  388. KeStallExecutionProcessor(1);
  389. }
  390. dcr &= ~DCR_DIRECTION;
  391. StoreControl (Controller, dcr);
  392. *BytesTransferred = i;
  393. // dvdr
  394. DD((PCE)Pdx,DDT,"ParEppSwRead: Leaving with %x Bytes Transferred\n", i);
  395. if ( Status == STATUS_SUCCESS )
  396. P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
  397. return Status;
  398. }