📄 readwrite.c
字号:
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: readwrit.c
//
//--------------------------------------------------------------------------
//
// This file contains functions associated with handling Read and Write requests
//
#include "pch.h"
NTSTATUS
ParForwardToReverse(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This routine flips the bus from Forward to Reverse direction.
Arguments:
Pdx - Supplies the device extension.
Return Value:
None.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
// Do a quick check to see if we are where we want to be.
// Happy punt if everything is ok.
if( Pdx->Connected &&
( Pdx->CurrentPhase == PHASE_REVERSE_IDLE || Pdx->CurrentPhase == PHASE_REVERSE_XFER) ) {
DD((PCE)Pdx,DDT,"ParForwardToReverse - already in reverse mode\n");
return Status;
}
if (Pdx->Connected) {
if (Pdx->CurrentPhase != PHASE_REVERSE_IDLE &&
Pdx->CurrentPhase != PHASE_REVERSE_XFER) {
if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily ==
arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
// Protocol Families match and we are in Fwd. Exit Fwd to cleanup the state
// machine, fifo, etc. We will call EnterReverse later to
// actually bus flip. Also only do this if in safe mode
if ( (afpForward[Pdx->IdxForwardProtocol].fnExitForward) ) {
Status = afpForward[Pdx->IdxForwardProtocol].fnExitForward(Pdx);
}
} else {
//
// Protocol Families don't match...need to terminate from the forward mode
//
if (afpForward[Pdx->IdxForwardProtocol].fnDisconnect) {
afpForward[Pdx->IdxForwardProtocol].fnDisconnect (Pdx);
}
if ((Pdx->ForwardInterfaceAddress != DEFAULT_ECP_CHANNEL) &&
(afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress))
Pdx->SetForwardAddress = TRUE;
}
}
}
if( (!Pdx->Connected) && (arpReverse[Pdx->IdxReverseProtocol].fnConnect) ) {
//
// If we are still connected the protocol families match...
//
Status = arpReverse[Pdx->IdxReverseProtocol].fnConnect(Pdx, FALSE);
//
// Makes the assumption that the connected address is always 0
//
if ((NT_SUCCESS(Status)) &&
(arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress) &&
(Pdx->ReverseInterfaceAddress != DEFAULT_ECP_CHANNEL)) {
Pdx->SetReverseAddress = TRUE;
}
}
//
// Set the channel address if we need to.
//
if (NT_SUCCESS(Status) && Pdx->SetReverseAddress &&
(arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress)) {
Status = arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress (
Pdx,
Pdx->ReverseInterfaceAddress);
if (NT_SUCCESS(Status))
Pdx->SetReverseAddress = FALSE;
else
Pdx->SetReverseAddress = TRUE;
}
//
// Do we need to reverse?
//
if ( (NT_SUCCESS(Status)) &&
((Pdx->CurrentPhase != PHASE_REVERSE_IDLE) &&
(Pdx->CurrentPhase != PHASE_REVERSE_XFER)) ) {
if ((arpReverse[Pdx->IdxReverseProtocol].fnEnterReverse))
Status = arpReverse[Pdx->IdxReverseProtocol].fnEnterReverse(Pdx);
}
DD((PCE)Pdx,DDT,"ParForwardToReverse - exit w/status=%x\n",Status);
return Status;
}
BOOLEAN
ParHaveReadData(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This method determines if the dot4 peripheral has any data ready
to send to the host.
Arguments:
Pdx - Supplies the device EXTENSION.
Return Value:
TRUE - Either the peripheral has data
FALSE - No data
--*/
{
NTSTATUS status;
BOOLEAN justAcquiredPort = FALSE;
if( Pdx->CurrentPhase != PHASE_TERMINATE &&
Pdx->CurrentPhase != PHASE_REVERSE_IDLE &&
Pdx->CurrentPhase != PHASE_REVERSE_XFER &&
Pdx->CurrentPhase != PHASE_FORWARD_IDLE &&
Pdx->CurrentPhase != PHASE_FORWARD_XFER ) {
// unexpected phase - no idea what to do here - pretend that
// there is no data avail and return
DD((PCE)Pdx,DDE,"ParHaveReadData - unexpected CurrentPhase %x\n",Pdx->CurrentPhase);
PptAssertMsg("ParHaveReadData - unexpected CurrentPhase",FALSE);
return FALSE;
}
if( PHASE_TERMINATE == Pdx->CurrentPhase ) {
//
// we're not currently talking with the peripheral and we
// likely don't have access to the port - try to acquire the
// port and establish communication with the peripheral so
// that we can check if the peripheral has data for us
//
// CurrentPhase indicates !Connected - do a check for consistency
PptAssert( !Pdx->Connected );
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE\n");
if( !Pdx->bAllocated ) {
// we don't have the port - try to acquire port
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - don't have port\n");
status = PptAcquirePortViaIoctl( Pdx->Fdo, NULL );
if( STATUS_SUCCESS == status ) {
// we now have the port
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - port acquired\n");
// note that we have just now acquired the port so
// that we can release the port below if we are unable
// to establish communication with the peripheral
justAcquiredPort = TRUE;
Pdx->bAllocated = TRUE;
} else {
// we couldn't get the port - bail out
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - don't have port - acquire failed\n");
return FALSE;
}
} // endif !Pdx->bAllocated
//
// we now have the port - try to negotiate into a forward
// mode since we believe that the check for periph data
// avail is more robust in forward modes
//
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_TERMINATE - we have the port - try to Connect\n");
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - try to Connect - calling ParReverseToForward\n");
//
// ParReverseToForward:
//
// 1) tries to negotiate the peripheral into the forward mode
// specified by a combination of the device specific
// Pdx->IdxForwardProtocol and the driver global afpForward
// array.
//
// 2) sets up our internal state machine, Pdx->CurrentPhase
//
// 3) as a side effect - sets Pdx->SetForwardAddress if we
// need to use a non-Zero ECP (or EPP) address.
//
status = ParReverseToForward( Pdx );
if( STATUS_SUCCESS == status ) {
//
// We are in communication with the peripheral
//
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - ParReverseToForward SUCCESS\n");
// Set the channel address if we need to - use the side effect from ParReverseToForward here
if( Pdx->SetForwardAddress ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - try to set Forward Address\n");
if( afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress ) {
status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress ( Pdx, Pdx->ForwardInterfaceAddress );
if( STATUS_SUCCESS == status ) {
// success - set flag to indicate that we don't need to set the address again
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - set Forward Address - SUCCESS\n");
Pdx->SetForwardAddress = FALSE;
} else {
// couldn't set address - clean up and bail out - report no peripheral data avail
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - set Forward Address - FAIL\n");
Pdx->SetForwardAddress = TRUE;
// Return peripheral to quiescent state
// (Compatibility Mode Forward Idle) and set
// our state machine accordingly
ParTerminate( Pdx );
// if we just acquired the port in this function then give
// up the port, otherwise keep it for now
if( justAcquiredPort ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - set address failed - giving up port\n");
ParFreePort( Pdx );
}
return FALSE;
}
}
} else {
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - connected - no need to set Forward Address\n");
}
} else {
// unable to establish communication with peripheral
DD((PCE)Pdx,DDE,"ParHaveReadData - we have the port - try to Connect - ParReverseToForward FAILED\n");
// if we just acquired the port in this function then give
// up the port, otherwise keep it for now
if( justAcquiredPort ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - connect failed - giving up port\n");
ParFreePort( Pdx );
}
return FALSE;
}
// we're communicating with the peripheral - fall through to below to check for data avail
} // endif PHASE_TERMINATE == CurrentPhase
if( Pdx->CurrentPhase == PHASE_REVERSE_IDLE ||
Pdx->CurrentPhase == PHASE_REVERSE_XFER ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_*\n");
if( arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData ) {
if( arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData( Pdx ) ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_* - we have data\n");
return TRUE;
}
}
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_REVERSE_* - no data - flip bus to forward\n");
// Don't have data. This could be a fluke. Let's flip the bus
// and try again in Fwd mode since some peripherals reportedly
// have broken firmware that does not properly signal that
// they have data avail when in some reverse modes.
ParReverseToForward( Pdx );
}
if( Pdx->CurrentPhase == PHASE_FORWARD_IDLE ||
Pdx->CurrentPhase == PHASE_FORWARD_XFER ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_*\n");
if( afpForward[Pdx->IdxForwardProtocol].ProtocolFamily == FAMILY_BECP ||
afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_HW_NOIRQ ||
afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_HW_IRQ) {
if( PptEcpHwHaveReadData( Pdx ) ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP HW - have data\n");
return TRUE;
}
// Hmmm. No data. Is the chip stuck?
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP HW - no data\n");
return FALSE;
} else {
if( afpForward[Pdx->IdxForwardProtocol].Protocol & ECP_SW ) {
DD((PCE)Pdx,DDE,"ParHaveReadData - PHASE_FORWARD_* - ECP SW - checking for data\n");
return ParEcpHaveReadData( Pdx );
}
}
}
// DVRH RMT
// We got here because the protocol doesn't support peeking.
// - pretend there is data avail
DD((PCE)Pdx,DDE,"ParHaveReadData - exit - returning TRUE\n");
return TRUE;
}
NTSTATUS
ParPing(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This method was intended to ping the device, but it is currently a NOOP.
Arguments:
Pdx - Supplies the device EXTENSION.
Return Value:
none
--*/
{
NTSTATUS NtStatus = STATUS_SUCCESS;
UNREFERENCED_PARAMETER( Pdx );
return NtStatus;
}
NTSTATUS
PptPdoReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch routine for READ and WRITE requests.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_PENDING - Request pending - a worker thread will carry
out the request at PASSIVE_LEVEL IRQL
STATUS_SUCCESS - Success - asked for a read or write of
length zero.
STATUS_INVALID_PARAMETER - Invalid parameter.
STATUS_DELETE_PENDING - This device object is being deleted.
--*/
{
PIO_STACK_LOCATION IrpSp;
PPDO_EXTENSION Pdx;
Irp->IoStatus.Information = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Pdx = DeviceObject->DeviceExtension;
//
// bail out if a delete is pending for this device object
//
if(Pdx->DeviceStateFlags & PPT_DEVICE_DELETE_PENDING) {
return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
}
//
// bail out if a remove is pending for our ParPort device object
//
if(Pdx->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
}
//
// bail out if device has been removed
//
if(Pdx->DeviceStateFlags & (PPT_DEVICE_REMOVED|PPT_DEVICE_SURPRISE_REMOVED) ) {
return P4CompleteRequest( Irp, STATUS_DEVICE_REMOVED, Irp->IoStatus.Information );
}
//
// Note that checks of the Write IRP parameters also handles Read IRPs
// because the Write and Read structures are identical in the
// IO_STACK_LOCATION.Parameters union
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -