Leaked source code of windows server 2003
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.

899 lines
29 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: readwrit.c
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // This file contains functions associated with handling Read and Write requests
  12. //
  13. #include "pch.h"
  14. NTSTATUS
  15. ParForwardToReverse(
  16. IN PPDO_EXTENSION Pdx
  17. )
  18. /*++
  19. Routine Description:
  20. This routine flips the bus from Forward to Reverse direction.
  21. Arguments:
  22. Pdx - Supplies the device extension.
  23. Return Value:
  24. None.
  25. --*/
  26. {
  27. NTSTATUS Status = STATUS_SUCCESS;
  28. // Do a quick check to see if we are where we want to be.
  29. // Happy punt if everything is ok.
  30. if( Pdx->Connected &&
  31. ( Pdx->CurrentPhase == PHASE_REVERSE_IDLE || Pdx->CurrentPhase == PHASE_REVERSE_XFER) ) {
  32. DD((PCE)Pdx,DDT,"ParForwardToReverse - already in reverse mode\n");
  33. return Status;
  34. }
  35. if (Pdx->Connected) {
  36. if (Pdx->CurrentPhase != PHASE_REVERSE_IDLE &&
  37. Pdx->CurrentPhase != PHASE_REVERSE_XFER) {
  38. if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily ==
  39. arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
  40. // Protocol Families match and we are in Fwd. Exit Fwd to cleanup the state
  41. // machine, fifo, etc. We will call EnterReverse later to
  42. // actually bus flip. Also only do this if in safe mode
  43. if ( (afpForward[Pdx->IdxForwardProtocol].fnExitForward) ) {
  44. Status = afpForward[Pdx->IdxForwardProtocol].fnExitForward(Pdx);
  45. }
  46. } else {
  47. //
  48. // Protocol Families don't match...need to terminate from the forward mode
  49. //
  50. if (afpForward[Pdx->IdxForwardProtocol].fnDisconnect) {
  51. afpForward[Pdx->IdxForwardProtocol].fnDisconnect (Pdx);
  52. }
  53. if ((Pdx->ForwardInterfaceAddress != DEFAULT_ECP_CHANNEL) &&
  54. (afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress))
  55. Pdx->SetForwardAddress = TRUE;
  56. }
  57. }
  58. }
  59. if( (!Pdx->Connected) && (arpReverse[Pdx->IdxReverseProtocol].fnConnect) ) {
  60. //
  61. // If we are still connected the protocol families match...
  62. //
  63. Status = arpReverse[Pdx->IdxReverseProtocol].fnConnect(Pdx, FALSE);
  64. //
  65. // Makes the assumption that the connected address is always 0
  66. //
  67. if ((NT_SUCCESS(Status)) &&
  68. (arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress) &&
  69. (Pdx->ReverseInterfaceAddress != DEFAULT_ECP_CHANNEL)) {
  70. Pdx->SetReverseAddress = TRUE;
  71. }
  72. }
  73. //
  74. // Set the channel address if we need to.
  75. //
  76. if (NT_SUCCESS(Status) && Pdx->SetReverseAddress &&
  77. (arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress)) {
  78. Status = arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress (
  79. Pdx,
  80. Pdx->ReverseInterfaceAddress);
  81. if (NT_SUCCESS(Status))
  82. Pdx->SetReverseAddress = FALSE;
  83. else
  84. Pdx->SetReverseAddress = TRUE;
  85. }
  86. //
  87. // Do we need to reverse?
  88. //
  89. if ( (NT_SUCCESS(Status)) &&
  90. ((Pdx->CurrentPhase != PHASE_REVERSE_IDLE) &&
  91. (Pdx->CurrentPhase != PHASE_REVERSE_XFER)) ) {
  92. if ((arpReverse[Pdx->IdxReverseProtocol].fnEnterReverse))
  93. Status = arpReverse[Pdx->IdxReverseProtocol].fnEnterReverse(Pdx);
  94. }
  95. DD((PCE)Pdx,DDT,"ParForwardToReverse - exit w/status=%x\n",Status);
  96. return Status;
  97. }
  98. BOOLEAN
  99. ParHaveReadData(
  100. IN PPDO_EXTENSION Pdx
  101. )
  102. /*++
  103. Routine Description:
  104. This method determines if the dot4 peripheral has any data ready
  105. to send to the host.
  106. Arguments:
  107. Pdx - Supplies the device EXTENSION.
  108. Return Value:
  109. TRUE - Either the peripheral has data
  110. FALSE - No data
  111. --*/
  112. {
  113. NTSTATUS status;
  114. BOOLEAN justAcquiredPort = FALSE;
  115. if( Pdx->CurrentPhase != PHASE_TERMINATE &&
  116. Pdx->CurrentPhase != PHASE_REVERSE_IDLE &&
  117. Pdx->CurrentPhase != PHASE_REVERSE_XFER &&
  118. Pdx->CurrentPhase != PHASE_FORWARD_IDLE &&
  119. Pdx->CurrentPhase != PHASE_FORWARD_XFER ) {
  120. // unexpected phase - no idea what to do here - pretend that
  121. // there is no data avail and return
  122. DD((PCE)Pdx,DDE,"ParHaveReadData - unexpected CurrentPhase %x\n",Pdx->CurrentPhase);
  123. PptAssertMsg("ParHaveReadData - unexpected CurrentPhase",FALSE);
  124. return FALSE;
  125. }
  126. if( PHASE_TERMINATE == Pdx->CurrentPhase ) {
  127. //
  128. // we're not currently talking with the peripheral and we
  129. // likely don't have access to the port - try to acquire the
  130. // port and establish communication with the peripheral so
  131. // that we can check if the peripheral has data for us
  132. //
  133. // CurrentPhase indicates !Connected - do a check for consistency
  134. PptAssert( !Pdx->Connected );
  135. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE\n");
  136. if( !Pdx->bAllocated ) {
  137. // we don't have the port - try to acquire port
  138. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - don't have port\n");
  139. status = PptAcquirePortViaIoctl( Pdx->Fdo, NULL );
  140. if( STATUS_SUCCESS == status ) {
  141. // we now have the port
  142. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - port acquired\n");
  143. // note that we have just now acquired the port so
  144. // that we can release the port below if we are unable
  145. // to establish communication with the peripheral
  146. justAcquiredPort = TRUE;
  147. Pdx->bAllocated = TRUE;
  148. } else {
  149. // we couldn't get the port - bail out
  150. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - don't have port - acquire failed\n");
  151. return FALSE;
  152. }
  153. } // endif !Pdx->bAllocated
  154. //
  155. // we now have the port - try to negotiate into a forward
  156. // mode since we believe that the check for periph data
  157. // avail is more robust in forward modes
  158. //
  159. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - we have the port - try to Connect\n");
  160. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - try to Connect - calling ParReverseToForward\n");
  161. //
  162. // ParReverseToForward:
  163. //
  164. // 1) tries to negotiate the peripheral into the forward mode
  165. // specified by a combination of the device specific
  166. // Pdx->IdxForwardProtocol and the driver global afpForward
  167. // array.
  168. //
  169. // 2) sets up our internal state machine, Pdx->CurrentPhase
  170. //
  171. // 3) as a side effect - sets Pdx->SetForwardAddress if we
  172. // need to use a non-Zero ECP (or EPP) address.
  173. //
  174. status = ParReverseToForward( Pdx );
  175. if( STATUS_SUCCESS == status ) {
  176. //
  177. // We are in communication with the peripheral
  178. //
  179. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - ParReverseToForward SUCCESS\n");
  180. // Set the channel address if we need to - use the side effect from ParReverseToForward here
  181. if( Pdx->SetForwardAddress ) {
  182. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - try to set Forward Address\n");
  183. if( afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress ) {
  184. status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress ( Pdx, Pdx->ForwardInterfaceAddress );
  185. if( STATUS_SUCCESS == status ) {
  186. // success - set flag to indicate that we don't need to set the address again
  187. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - set Forward Address - SUCCESS\n");
  188. Pdx->SetForwardAddress = FALSE;
  189. } else {
  190. // couldn't set address - clean up and bail out - report no peripheral data avail
  191. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - set Forward Address - FAIL\n");
  192. Pdx->SetForwardAddress = TRUE;
  193. // Return peripheral to quiescent state
  194. // (Compatibility Mode Forward Idle) and set
  195. // our state machine accordingly
  196. ParTerminate( Pdx );
  197. // if we just acquired the port in this function then give
  198. // up the port, otherwise keep it for now
  199. if( justAcquiredPort ) {
  200. DD((PCE)Pdx,DDE,"ParHaveReadData - set address failed - giving up port\n");
  201. ParFreePort( Pdx );
  202. }
  203. return FALSE;
  204. }
  205. }
  206. } else {
  207. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - no need to set Forward Address\n");
  208. }
  209. } else {
  210. // unable to establish communication with peripheral
  211. DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - try to Connect - ParReverseToForward FAILED\n");
  212. // if we just acquired the port in this function then give
  213. // up the port, otherwise keep it for now
  214. if( justAcquiredPort ) {
  215. DD((PCE)Pdx,DDE,"ParHaveReadData - connect failed - giving up port\n");
  216. ParFreePort( Pdx );
  217. }
  218. return FALSE;
  219. }
  220. // we're communicating with the peripheral - fall through to below to check for data avail
  221. } // endif PHASE_TERMINATE == CurrentPhase
  222. if( Pdx->CurrentPhase == PHASE_REVERSE_IDLE ||
  223. Pdx->CurrentPhase == PHASE_REVERSE_XFER ) {
  224. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_*\n");
  225. if( arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData ) {
  226. if( arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData( Pdx ) ) {
  227. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_* - we have data\n");
  228. return TRUE;
  229. }
  230. }
  231. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_* - no data - flip bus to forward\n");
  232. // Don't have data. This could be a fluke. Let's flip the bus
  233. // and try again in Fwd mode since some peripherals reportedly
  234. // have broken firmware that does not properly signal that
  235. // they have data avail when in some reverse modes.
  236. ParReverseToForward( Pdx );
  237. }
  238. if( Pdx->CurrentPhase == PHASE_FORWARD_IDLE ||
  239. Pdx->CurrentPhase == PHASE_FORWARD_XFER ) {
  240. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_*\n");
  241. if( afpForward[Pdx->IdxForwardProtocol].ProtocolFamily == FAMILY_BECP ||
  242. afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_HW_NOIRQ ||
  243. afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_HW_IRQ) {
  244. if( PptEcpHwHaveReadData( Pdx ) ) {
  245. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP HW - have data\n");
  246. return TRUE;
  247. }
  248. // Hmmm. No data. Is the chip stuck?
  249. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP HW - no data\n");
  250. return FALSE;
  251. } else {
  252. if( afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_SW ) {
  253. DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP SW - checking for data\n");
  254. return ParEcpHaveReadData( Pdx );
  255. }
  256. }
  257. }
  258. // DVRH RMT
  259. // We got here because the protocol doesn't support peeking.
  260. // - pretend there is data avail
  261. DD((PCE)Pdx,DDE,"ParHaveReadData - exit - returning TRUE\n");
  262. return TRUE;
  263. }
  264. NTSTATUS
  265. ParPing(
  266. IN PPDO_EXTENSION Pdx
  267. )
  268. /*++
  269. Routine Description:
  270. This method was intended to ping the device, but it is currently a NOOP.
  271. Arguments:
  272. Pdx - Supplies the device EXTENSION.
  273. Return Value:
  274. none
  275. --*/
  276. {
  277. NTSTATUS NtStatus = STATUS_SUCCESS;
  278. UNREFERENCED_PARAMETER( Pdx );
  279. return NtStatus;
  280. }
  281. NTSTATUS
  282. PptPdoReadWrite(
  283. IN PDEVICE_OBJECT DeviceObject,
  284. IN PIRP Irp
  285. )
  286. /*++
  287. Routine Description:
  288. This is the dispatch routine for READ and WRITE requests.
  289. Arguments:
  290. DeviceObject - Supplies the device object.
  291. Irp - Supplies the I/O request packet.
  292. Return Value:
  293. STATUS_PENDING - Request pending - a worker thread will carry
  294. out the request at PASSIVE_LEVEL IRQL
  295. STATUS_SUCCESS - Success - asked for a read or write of
  296. length zero.
  297. STATUS_INVALID_PARAMETER - Invalid parameter.
  298. STATUS_DELETE_PENDING - This device object is being deleted.
  299. --*/
  300. {
  301. PIO_STACK_LOCATION IrpSp;
  302. PPDO_EXTENSION Pdx;
  303. Irp->IoStatus.Information = 0;
  304. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  305. Pdx = DeviceObject->DeviceExtension;
  306. //
  307. // bail out if a delete is pending for this device object
  308. //
  309. if(Pdx->DeviceStateFlags & PPT_DEVICE_DELETE_PENDING) {
  310. return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
  311. }
  312. //
  313. // bail out if a remove is pending for our ParPort device object
  314. //
  315. if(Pdx->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
  316. return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
  317. }
  318. //
  319. // bail out if device has been removed
  320. //
  321. if(Pdx->DeviceStateFlags & (PPT_DEVICE_REMOVED|PPT_DEVICE_SURPRISE_REMOVED) ) {
  322. return P4CompleteRequest( Irp, STATUS_DEVICE_REMOVED, Irp->IoStatus.Information );
  323. }
  324. //
  325. // Note that checks of the Write IRP parameters also handles Read IRPs
  326. // because the Write and Read structures are identical in the
  327. // IO_STACK_LOCATION.Parameters union
  328. //
  329. //
  330. // bail out on nonzero offset
  331. //
  332. if( (IrpSp->Parameters.Write.ByteOffset.HighPart != 0) || (IrpSp->Parameters.Write.ByteOffset.LowPart != 0) ) {
  333. return P4CompleteRequest( Irp, STATUS_INVALID_PARAMETER, Irp->IoStatus.Information );
  334. }
  335. //
  336. // immediately succeed read or write request of length zero
  337. //
  338. if (IrpSp->Parameters.Write.Length == 0) {
  339. return P4CompleteRequest( Irp, STATUS_SUCCESS, Irp->IoStatus.Information );
  340. }
  341. //
  342. // Request appears to be valid, queue it for our worker thread to handle at
  343. // PASSIVE_LEVEL IRQL and wake up the thread to do the work
  344. //
  345. {
  346. KIRQL OldIrql;
  347. // make sure IRP isn't cancelled out from under us
  348. IoAcquireCancelSpinLock(&OldIrql);
  349. if (Irp->Cancel) {
  350. // IRP has been cancelled, bail out
  351. IoReleaseCancelSpinLock(OldIrql);
  352. return STATUS_CANCELLED;
  353. } else {
  354. BOOLEAN needToSignalSemaphore = (IsListEmpty( &Pdx->WorkQueue ) &&
  355. !KeReadStateSemaphore( &Pdx->RequestSemaphore )) ? TRUE : FALSE;
  356. #pragma warning( push )
  357. #pragma warning( disable : 4054 4055 )
  358. IoSetCancelRoutine(Irp, ParCancelRequest);
  359. #pragma warning( pop )
  360. IoMarkIrpPending(Irp);
  361. InsertTailList(&Pdx->WorkQueue, &Irp->Tail.Overlay.ListEntry);
  362. IoReleaseCancelSpinLock(OldIrql);
  363. if( needToSignalSemaphore ) {
  364. KeReleaseSemaphore(&Pdx->RequestSemaphore, 0, 1, FALSE);
  365. }
  366. return STATUS_PENDING;
  367. }
  368. }
  369. }
  370. NTSTATUS
  371. ParRead(
  372. IN PPDO_EXTENSION Pdx,
  373. OUT PVOID Buffer,
  374. IN ULONG NumBytesToRead,
  375. OUT PULONG NumBytesRead
  376. )
  377. {
  378. NTSTATUS Status = STATUS_SUCCESS;
  379. PUCHAR lpsBufPtr = (PUCHAR)Buffer; // Pointer to buffer cast to desired data type
  380. ULONG Bytes = 0;
  381. *NumBytesRead = Bytes;
  382. // only do this if we are in safe mode
  383. if ( Pdx->ModeSafety == SAFE_MODE ) {
  384. if (arpReverse[Pdx->IdxReverseProtocol].fnReadShadow) {
  385. Queue *pQueue;
  386. pQueue = &(Pdx->ShadowBuffer);
  387. arpReverse[Pdx->IdxReverseProtocol].fnReadShadow( pQueue, lpsBufPtr, NumBytesToRead, &Bytes );
  388. NumBytesToRead -= Bytes;
  389. *NumBytesRead += Bytes;
  390. lpsBufPtr += Bytes;
  391. if ( 0 == NumBytesToRead ) {
  392. Status = STATUS_SUCCESS;
  393. if ((!Queue_IsEmpty(pQueue)) &&
  394. (TRUE == Pdx->P12843DL.bEventActive) ) {
  395. KeSetEvent(Pdx->P12843DL.Event, 0, FALSE);
  396. }
  397. goto ParRead_ExitLabel;
  398. }
  399. }
  400. if (arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData) {
  401. if (!arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData(Pdx)) {
  402. DD((PCE)Pdx,DDT,"ParRead - periph doesn't have data - give cycles to someone else\n");
  403. Status = STATUS_SUCCESS;
  404. goto ParRead_ExitLabel;
  405. }
  406. }
  407. }
  408. // Go ahead and flip the bus if need be. The proc will just make sure we're properly
  409. // connected and pointing in the right direction.
  410. Status = ParForwardToReverse( Pdx );
  411. //
  412. // The read mode will vary depending upon the currently negotiated mode.
  413. // Default: Nibble
  414. //
  415. if (NT_SUCCESS(Status)) {
  416. if (Pdx->fnRead || arpReverse[Pdx->IdxReverseProtocol].fnRead) {
  417. //
  418. // Do the read...
  419. //
  420. if(Pdx->fnRead) {
  421. Status = ((PPROTOCOL_READ_ROUTINE)Pdx->fnRead)( Pdx, (PVOID)lpsBufPtr, NumBytesToRead, &Bytes );
  422. } else {
  423. Status = arpReverse[Pdx->IdxReverseProtocol].fnRead( Pdx, (PVOID)lpsBufPtr, NumBytesToRead, &Bytes );
  424. }
  425. *NumBytesRead += Bytes;
  426. NumBytesToRead -= Bytes;
  427. #if DVRH_SHOW_BYTE_LOG
  428. {
  429. ULONG i=0;
  430. DD((PCE)Pdx,DDT,"Parallel:Read: ");
  431. for (i=0; i<*NumBytesRead; ++i) {
  432. DD((PCE)Pdx,DDT," %02x",((PUCHAR)lpsBufPtr)[i]);
  433. }
  434. DD((PCE)Pdx,DDT,"\n");
  435. }
  436. #endif
  437. } else {
  438. // If you are here, you've got a bug somewhere else
  439. DD((PCE)Pdx,DDE,"ParRead - you're hosed man - no fnRead\n");
  440. PptAssertMsg("ParRead - don't have a fnRead! Can't Read!\n",FALSE);
  441. }
  442. } else {
  443. DD((PCE)Pdx,DDE,"ParRead - Bus Flip Forward->Reverse FAILED - can't read\n");
  444. }
  445. ParRead_ExitLabel:
  446. return Status;
  447. }
  448. VOID
  449. ParReadIrp(
  450. IN PPDO_EXTENSION Pdx
  451. )
  452. /*++
  453. Routine Description:
  454. This routine implements a READ request with the extension's current irp.
  455. Arguments:
  456. Pdx - Supplies the device extension.
  457. Return Value:
  458. None.
  459. --*/
  460. {
  461. PIRP Irp = Pdx->CurrentOpIrp;
  462. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  463. ULONG bytesRead;
  464. NTSTATUS status;
  465. status = ParRead( Pdx, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Read.Length, &bytesRead );
  466. Irp->IoStatus.Status = status;
  467. Irp->IoStatus.Information = bytesRead;
  468. DD((PCE)Pdx,DDT,"ParReadIrp - status = %x, bytesRead=%d\n", status, bytesRead);
  469. return;
  470. }
  471. NTSTATUS
  472. ParReverseToForward(
  473. IN PPDO_EXTENSION Pdx
  474. )
  475. /*++
  476. Routine Description:
  477. This routine flips the bus from Reverse to Forward direction.
  478. Arguments:
  479. Pdx - Supplies the device extension.
  480. Return Value:
  481. None.
  482. --*/
  483. {
  484. NTSTATUS Status = STATUS_SUCCESS;
  485. // dvdr
  486. if (Pdx->Connected) {
  487. // Do a quick check to see if we are where we want to be.
  488. // Happy punt if everything is ok.
  489. if( Pdx->CurrentPhase == PHASE_FORWARD_IDLE || Pdx->CurrentPhase == PHASE_FORWARD_XFER ) {
  490. DD((PCE)Pdx,DDT,"ParReverseToForward: Already in Fwd. Exit STATUS_SUCCESS\n");
  491. return Status;
  492. } else {
  493. if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily !=
  494. arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
  495. //
  496. // Protocol Families don't match...need to terminate from the forward mode
  497. //
  498. if (arpReverse[Pdx->IdxReverseProtocol].fnDisconnect) {
  499. arpReverse[Pdx->IdxReverseProtocol].fnDisconnect (Pdx);
  500. }
  501. if ((Pdx->ReverseInterfaceAddress != DEFAULT_ECP_CHANNEL) &&
  502. (arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress)) {
  503. Pdx->SetReverseAddress = TRUE;
  504. }
  505. } else if((Pdx->CurrentPhase == PHASE_REVERSE_IDLE) || (Pdx->CurrentPhase == PHASE_REVERSE_XFER)) {
  506. if ( (arpReverse[Pdx->IdxReverseProtocol].fnExitReverse) ) {
  507. Status = arpReverse[Pdx->IdxReverseProtocol].fnExitReverse(Pdx);
  508. }
  509. } else {
  510. // We are in a screwy state.
  511. DD((PCE)Pdx,DDE,"ParReverseToForward: We're lost! Unknown state - Gonna start spewing!\n");
  512. Status = STATUS_IO_TIMEOUT; // I picked a RetVal from thin air!
  513. }
  514. }
  515. }
  516. // Yes, we still want to check for connection since we might have
  517. // terminated in the previous code block!
  518. if (!Pdx->Connected && afpForward[Pdx->IdxForwardProtocol].fnConnect) {
  519. Status = afpForward[Pdx->IdxForwardProtocol].fnConnect( Pdx, FALSE );
  520. //
  521. // Makes the assumption that the connected address is always 0
  522. //
  523. if ((NT_SUCCESS(Status)) && (Pdx->ForwardInterfaceAddress != DEFAULT_ECP_CHANNEL)) {
  524. Pdx->SetForwardAddress = TRUE;
  525. }
  526. }
  527. //
  528. // Do we need to enter a forward mode?
  529. //
  530. if ( (NT_SUCCESS(Status)) &&
  531. (Pdx->CurrentPhase != PHASE_FORWARD_IDLE) &&
  532. (Pdx->CurrentPhase != PHASE_FORWARD_XFER) &&
  533. (afpForward[Pdx->IdxForwardProtocol].fnEnterForward) ) {
  534. Status = afpForward[Pdx->IdxForwardProtocol].fnEnterForward(Pdx);
  535. }
  536. DD((PCE)Pdx,DDT,"ParReverseToForward - exit w/status= %x\n", Status);
  537. return Status;
  538. }
  539. NTSTATUS
  540. ParSetFwdAddress(
  541. IN PPDO_EXTENSION Pdx
  542. )
  543. {
  544. NTSTATUS Status = STATUS_SUCCESS;
  545. DD((PCE)Pdx,DDT,"ParSetFwdAddress: Start: Channel [%x]\n", Pdx->ForwardInterfaceAddress);
  546. if (afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress) {
  547. Status = ParReverseToForward(Pdx);
  548. if (!NT_SUCCESS(Status)) {
  549. DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Couldn't flip the bus for Set ECP/EPP Channel failed.\n");
  550. goto ParSetFwdAddress_ExitLabel;
  551. }
  552. Status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress (
  553. Pdx,
  554. Pdx->ForwardInterfaceAddress);
  555. if (NT_SUCCESS(Status)) {
  556. Pdx->SetForwardAddress = FALSE;
  557. } else {
  558. DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Set ECP/EPP Channel failed.\n");
  559. goto ParSetFwdAddress_ExitLabel;
  560. }
  561. } else {
  562. DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Protocol doesn't support SetECP/EPP Channel\n");
  563. Status = STATUS_UNSUCCESSFUL;
  564. goto ParSetFwdAddress_ExitLabel;
  565. }
  566. ParSetFwdAddress_ExitLabel:
  567. return Status;
  568. }
  569. VOID
  570. ParTerminate(
  571. IN PPDO_EXTENSION Pdx
  572. )
  573. {
  574. if (!Pdx->Connected) {
  575. return;
  576. }
  577. if (Pdx->CurrentPhase == PHASE_REVERSE_IDLE || Pdx->CurrentPhase == PHASE_REVERSE_XFER) {
  578. if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily !=
  579. arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
  580. if (arpReverse[Pdx->IdxReverseProtocol].fnDisconnect) {
  581. DD((PCE)Pdx,DDT,"ParTerminate: Calling arpReverse.fnDisconnect\r\n");
  582. arpReverse[Pdx->IdxReverseProtocol].fnDisconnect (Pdx);
  583. }
  584. return;
  585. }
  586. ParReverseToForward(Pdx);
  587. }
  588. if (afpForward[Pdx->IdxForwardProtocol].fnDisconnect) {
  589. DD((PCE)Pdx,DDT,"ParTerminate: Calling afpForward.fnDisconnect\r\n");
  590. afpForward[Pdx->IdxForwardProtocol].fnDisconnect (Pdx);
  591. }
  592. }
  593. NTSTATUS
  594. ParWrite(
  595. IN PPDO_EXTENSION Pdx,
  596. OUT PVOID Buffer,
  597. IN ULONG NumBytesToWrite,
  598. OUT PULONG NumBytesWritten
  599. )
  600. {
  601. NTSTATUS Status = STATUS_SUCCESS;
  602. //
  603. // The routine which performs the write varies depending upon the currently
  604. // negotiated mode. Start I/O moves the IRP into the Pdx (CurrentOpIrp)
  605. //
  606. // Default mode: Centronics
  607. //
  608. // Go ahead and flip the bus if need be. The proc will just make sure we're properly
  609. // connected and pointing in the right direction.
  610. Status = ParReverseToForward( Pdx );
  611. // only do this if we are in safe mode
  612. if ( Pdx->ModeSafety == SAFE_MODE ) {
  613. //
  614. // Set the channel address if we need to.
  615. //
  616. if (NT_SUCCESS(Status) && Pdx->SetForwardAddress &&
  617. (afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress))
  618. {
  619. Status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress (
  620. Pdx,
  621. Pdx->ForwardInterfaceAddress);
  622. if (NT_SUCCESS(Status))
  623. Pdx->SetForwardAddress = FALSE;
  624. else
  625. Pdx->SetForwardAddress = TRUE;
  626. }
  627. }
  628. if (NT_SUCCESS(Status)) {
  629. if (Pdx->fnWrite || afpForward[Pdx->IdxForwardProtocol].fnWrite) {
  630. *NumBytesWritten = 0;
  631. #if DVRH_SHOW_BYTE_LOG
  632. {
  633. ULONG i=0;
  634. DD((PCE)Pdx,DDT,"Parallel:Write: ");
  635. for (i=0; i<NumBytesToWrite; ++i) {
  636. DD((PCE)Pdx,DDT," %02x",*((PUCHAR)Buffer+i));
  637. }
  638. DD((PCE)Pdx,DDT,"\n");
  639. }
  640. #endif
  641. if( Pdx->fnWrite) {
  642. Status = ((PPROTOCOL_WRITE_ROUTINE)Pdx->fnWrite)(Pdx,
  643. Buffer,
  644. NumBytesToWrite,
  645. NumBytesWritten);
  646. } else {
  647. Status = afpForward[Pdx->IdxForwardProtocol].fnWrite(Pdx,
  648. Buffer,
  649. NumBytesToWrite,
  650. NumBytesWritten);
  651. }
  652. }
  653. }
  654. return Status;
  655. }
  656. VOID
  657. ParWriteIrp(
  658. IN PPDO_EXTENSION Pdx
  659. )
  660. /*++
  661. Routine Description:
  662. This routine implements a WRITE request with the extension's current irp.
  663. Arguments:
  664. Pdx - Supplies the device extension.
  665. Return Value:
  666. None.
  667. --*/
  668. {
  669. PIRP Irp;
  670. PIO_STACK_LOCATION IrpSp;
  671. ULONG NumBytesWritten = 0;
  672. Irp = Pdx->CurrentOpIrp;
  673. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  674. Irp->IoStatus.Status = ParWrite(Pdx,
  675. Irp->AssociatedIrp.SystemBuffer,
  676. IrpSp->Parameters.Write.Length,
  677. &NumBytesWritten);
  678. Irp->IoStatus.Information = NumBytesWritten;
  679. }