⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readwrite.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 2 页
字号:


    //
    // 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 + -