📄 readwrite.c
字号:
//
// bail out on nonzero offset
//
if( (IrpSp->Parameters.Write.ByteOffset.HighPart != 0) || (IrpSp->Parameters.Write.ByteOffset.LowPart != 0) ) {
return P4CompleteRequest( Irp, STATUS_INVALID_PARAMETER, Irp->IoStatus.Information );
}
//
// immediately succeed read or write request of length zero
//
if (IrpSp->Parameters.Write.Length == 0) {
return P4CompleteRequest( Irp, STATUS_SUCCESS, Irp->IoStatus.Information );
}
//
// Request appears to be valid, queue it for our worker thread to handle at
// PASSIVE_LEVEL IRQL and wake up the thread to do the work
//
{
KIRQL OldIrql;
// make sure IRP isn't cancelled out from under us
IoAcquireCancelSpinLock(&OldIrql);
if (Irp->Cancel) {
// IRP has been cancelled, bail out
IoReleaseCancelSpinLock(OldIrql);
return STATUS_CANCELLED;
} else {
BOOLEAN needToSignalSemaphore = IsListEmpty( &Pdx->WorkQueue ) ? TRUE : FALSE;
#pragma warning( push )
#pragma warning( disable : 4054 4055 )
IoSetCancelRoutine(Irp, ParCancelRequest);
#pragma warning( pop )
IoMarkIrpPending(Irp);
InsertTailList(&Pdx->WorkQueue, &Irp->Tail.Overlay.ListEntry);
IoReleaseCancelSpinLock(OldIrql);
if( needToSignalSemaphore ) {
KeReleaseSemaphore(&Pdx->RequestSemaphore, 0, 1, FALSE);
}
return STATUS_PENDING;
}
}
}
NTSTATUS
ParRead(
IN PPDO_EXTENSION Pdx,
OUT PVOID Buffer,
IN ULONG NumBytesToRead,
OUT PULONG NumBytesRead
)
{
NTSTATUS Status = STATUS_SUCCESS;
PUCHAR lpsBufPtr = (PUCHAR)Buffer; // Pointer to buffer cast to desired data type
ULONG Bytes = 0;
*NumBytesRead = Bytes;
// only do this if we are in safe mode
if ( Pdx->ModeSafety == SAFE_MODE ) {
if (arpReverse[Pdx->IdxReverseProtocol].fnReadShadow) {
Queue *pQueue;
pQueue = &(Pdx->ShadowBuffer);
arpReverse[Pdx->IdxReverseProtocol].fnReadShadow( pQueue, lpsBufPtr, NumBytesToRead, &Bytes );
NumBytesToRead -= Bytes;
*NumBytesRead += Bytes;
lpsBufPtr += Bytes;
if ( 0 == NumBytesToRead ) {
Status = STATUS_SUCCESS;
if ((!Queue_IsEmpty(pQueue)) &&
(TRUE == Pdx->P12843DL.bEventActive) ) {
KeSetEvent(Pdx->P12843DL.Event, 0, FALSE);
}
goto ParRead_ExitLabel;
}
}
if (arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData) {
if (!arpReverse[Pdx->IdxReverseProtocol].fnHaveReadData(Pdx)) {
DD((PCE)Pdx,DDT,"ParRead - periph doesn't have data - give cycles to someone else\n");
Status = STATUS_SUCCESS;
goto ParRead_ExitLabel;
}
}
}
// Go ahead and flip the bus if need be. The proc will just make sure we're properly
// connected and pointing in the right direction.
Status = ParForwardToReverse( Pdx );
//
// The read mode will vary depending upon the currently negotiated mode.
// Default: Nibble
//
if (NT_SUCCESS(Status)) {
if (Pdx->fnRead || arpReverse[Pdx->IdxReverseProtocol].fnRead) {
//
// Do the read...
//
if(Pdx->fnRead) {
Status = ((PPROTOCOL_READ_ROUTINE)Pdx->fnRead)( Pdx, (PVOID)lpsBufPtr, NumBytesToRead, &Bytes );
} else {
Status = arpReverse[Pdx->IdxReverseProtocol].fnRead( Pdx, (PVOID)lpsBufPtr, NumBytesToRead, &Bytes );
}
*NumBytesRead += Bytes;
NumBytesToRead -= Bytes;
#if DVRH_SHOW_BYTE_LOG
{
ULONG i=0;
DD((PCE)Pdx,DDT,"Parallel:Read: ");
for (i=0; i<*NumBytesRead; ++i) {
DD((PCE)Pdx,DDT," %02x",((PUCHAR)lpsBufPtr)[i]);
}
DD((PCE)Pdx,DDT,"\n");
}
#endif
} else {
// If you are here, you've got a bug somewhere else
DD((PCE)Pdx,DDE,"ParRead - you're hosed man - no fnRead\n");
PptAssertMsg("ParRead - don't have a fnRead! Can't Read!\n",FALSE);
}
} else {
DD((PCE)Pdx,DDE,"ParRead - Bus Flip Forward->Reverse FAILED - can't read\n");
}
ParRead_ExitLabel:
return Status;
}
VOID
ParReadIrp(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This routine implements a READ request with the extension's current irp.
Arguments:
Pdx - Supplies the device extension.
Return Value:
None.
--*/
{
PIRP Irp = Pdx->CurrentOpIrp;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
ULONG bytesRead;
NTSTATUS status;
status = ParRead( Pdx, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Read.Length, &bytesRead );
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = bytesRead;
DD((PCE)Pdx,DDT,"ParReadIrp - status = %x, bytesRead=%d\n", status, bytesRead);
return;
}
NTSTATUS
ParReverseToForward(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This routine flips the bus from Reverse to Forward direction.
Arguments:
Pdx - Supplies the device extension.
Return Value:
None.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
// dvdr
if (Pdx->Connected) {
// Do a quick check to see if we are where we want to be.
// Happy punt if everything is ok.
if( Pdx->CurrentPhase == PHASE_FORWARD_IDLE || Pdx->CurrentPhase == PHASE_FORWARD_XFER ) {
DD((PCE)Pdx,DDT,"ParReverseToForward: Already in Fwd. Exit STATUS_SUCCESS\n");
return Status;
} else {
if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily !=
arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
//
// Protocol Families don't match...need to terminate from the forward mode
//
if (arpReverse[Pdx->IdxReverseProtocol].fnDisconnect) {
arpReverse[Pdx->IdxReverseProtocol].fnDisconnect (Pdx);
}
if ((Pdx->ReverseInterfaceAddress != DEFAULT_ECP_CHANNEL) &&
(arpReverse[Pdx->IdxReverseProtocol].fnSetInterfaceAddress)) {
Pdx->SetReverseAddress = TRUE;
}
} else if((Pdx->CurrentPhase == PHASE_REVERSE_IDLE) || (Pdx->CurrentPhase == PHASE_REVERSE_XFER)) {
if ( (arpReverse[Pdx->IdxReverseProtocol].fnExitReverse) ) {
Status = arpReverse[Pdx->IdxReverseProtocol].fnExitReverse(Pdx);
}
} else {
// We are in a screwy state.
DD((PCE)Pdx,DDE,"ParReverseToForward: We're lost! Unknown state - Gonna start spewing!\n");
Status = STATUS_IO_TIMEOUT; // I picked a RetVal from thin air!
}
}
}
// Yes, we still want to check for connection since we might have
// terminated in the previous code block!
if (!Pdx->Connected && afpForward[Pdx->IdxForwardProtocol].fnConnect) {
Status = afpForward[Pdx->IdxForwardProtocol].fnConnect( Pdx, FALSE );
//
// Makes the assumption that the connected address is always 0
//
if ((NT_SUCCESS(Status)) && (Pdx->ForwardInterfaceAddress != DEFAULT_ECP_CHANNEL)) {
Pdx->SetForwardAddress = TRUE;
}
}
//
// Do we need to enter a forward mode?
//
if ( (NT_SUCCESS(Status)) &&
(Pdx->CurrentPhase != PHASE_FORWARD_IDLE) &&
(Pdx->CurrentPhase != PHASE_FORWARD_XFER) &&
(afpForward[Pdx->IdxForwardProtocol].fnEnterForward) ) {
Status = afpForward[Pdx->IdxForwardProtocol].fnEnterForward(Pdx);
}
DD((PCE)Pdx,DDT,"ParReverseToForward - exit w/status= %x\n", Status);
return Status;
}
NTSTATUS
ParSetFwdAddress(
IN PPDO_EXTENSION Pdx
)
{
NTSTATUS Status = STATUS_SUCCESS;
DD((PCE)Pdx,DDT,"ParSetFwdAddress: Start: Channel [%x]\n", Pdx->ForwardInterfaceAddress);
if (afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress) {
Status = ParReverseToForward(Pdx);
if (!NT_SUCCESS(Status)) {
DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Couldn't flip the bus for Set ECP/EPP Channel failed.\n");
goto ParSetFwdAddress_ExitLabel;
}
Status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress (
Pdx,
Pdx->ForwardInterfaceAddress);
if (NT_SUCCESS(Status)) {
Pdx->SetForwardAddress = FALSE;
} else {
DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Set ECP/EPP Channel failed.\n");
goto ParSetFwdAddress_ExitLabel;
}
} else {
DD((PCE)Pdx,DDE,"ParSetFwdAddress: FAIL. Protocol doesn't support SetECP/EPP Channel\n");
Status = STATUS_UNSUCCESSFUL;
goto ParSetFwdAddress_ExitLabel;
}
ParSetFwdAddress_ExitLabel:
return Status;
}
VOID
ParTerminate(
IN PPDO_EXTENSION Pdx
)
{
if (!Pdx->Connected) {
return;
}
if (Pdx->CurrentPhase == PHASE_REVERSE_IDLE || Pdx->CurrentPhase == PHASE_REVERSE_XFER) {
if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily !=
arpReverse[Pdx->IdxReverseProtocol].ProtocolFamily) {
if (arpReverse[Pdx->IdxReverseProtocol].fnDisconnect) {
DD((PCE)Pdx,DDT,"ParTerminate: Calling arpReverse.fnDisconnect\r\n");
arpReverse[Pdx->IdxReverseProtocol].fnDisconnect (Pdx);
}
return;
}
ParReverseToForward(Pdx);
}
if (afpForward[Pdx->IdxForwardProtocol].fnDisconnect) {
DD((PCE)Pdx,DDT,"ParTerminate: Calling afpForward.fnDisconnect\r\n");
afpForward[Pdx->IdxForwardProtocol].fnDisconnect (Pdx);
}
}
NTSTATUS
ParWrite(
IN PPDO_EXTENSION Pdx,
OUT PVOID Buffer,
IN ULONG NumBytesToWrite,
OUT PULONG NumBytesWritten
)
{
NTSTATUS Status = STATUS_SUCCESS;
//
// The routine which performs the write varies depending upon the currently
// negotiated mode. Start I/O moves the IRP into the Pdx (CurrentOpIrp)
//
// Default mode: Centronics
//
// Go ahead and flip the bus if need be. The proc will just make sure we're properly
// connected and pointing in the right direction.
Status = ParReverseToForward( Pdx );
// only do this if we are in safe mode
if ( Pdx->ModeSafety == SAFE_MODE ) {
//
// Set the channel address if we need to.
//
if (NT_SUCCESS(Status) && Pdx->SetForwardAddress &&
(afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress))
{
Status = afpForward[Pdx->IdxForwardProtocol].fnSetInterfaceAddress (
Pdx,
Pdx->ForwardInterfaceAddress);
if (NT_SUCCESS(Status))
Pdx->SetForwardAddress = FALSE;
else
Pdx->SetForwardAddress = TRUE;
}
}
if (NT_SUCCESS(Status)) {
if (Pdx->fnWrite || afpForward[Pdx->IdxForwardProtocol].fnWrite) {
*NumBytesWritten = 0;
#if DVRH_SHOW_BYTE_LOG
{
ULONG i=0;
DD((PCE)Pdx,DDT,"Parallel:Write: ");
for (i=0; i<NumBytesToWrite; ++i) {
DD((PCE)Pdx,DDT," %02x",*((PUCHAR)Buffer+i));
}
DD((PCE)Pdx,DDT,"\n");
}
#endif
if( Pdx->fnWrite) {
Status = ((PPROTOCOL_WRITE_ROUTINE)Pdx->fnWrite)(Pdx,
Buffer,
NumBytesToWrite,
NumBytesWritten);
} else {
Status = afpForward[Pdx->IdxForwardProtocol].fnWrite(Pdx,
Buffer,
NumBytesToWrite,
NumBytesWritten);
}
}
}
return Status;
}
VOID
ParWriteIrp(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This routine implements a WRITE request with the extension's current irp.
Arguments:
Pdx - Supplies the device extension.
Return Value:
None.
--*/
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
ULONG NumBytesWritten = 0;
Irp = Pdx->CurrentOpIrp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Status = ParWrite(Pdx,
Irp->AssociatedIrp.SystemBuffer,
IrpSp->Parameters.Write.Length,
&NumBytesWritten);
Irp->IoStatus.Information = NumBytesWritten;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -