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

📄 hwecp.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    KeStallExecutionProcessor(100);                 // Hold long enough to capture
    P5WritePortUchar(wPortData, 0);                 // Now clear the data lines.


    //----------------------------------------------------------------------
    // Set the ECR to mode 000 (Compatibility Mode).
    //----------------------------------------------------------------------
    // Nothing needs to be done here.
    Pdx->PortHWMode = HW_MODE_COMPATIBILITY;


    //----------------------------------------------------------------------
    // Check for any link errors if nothing bad found yet.
    //----------------------------------------------------------------------
    bDSR = P5ReadPortUchar(wPortDSR);               // Get content of DSR.
    bDSRmasked = (UCHAR)(bDSR | 0x07);              // Set first 3 bits (don't cares).

    if( NT_SUCCESS(status) ) {

        if (bDSRmasked != 0xDF) {

            DD((PCE)Pdx,DDE,"ParEcpHwRecoverPort - DSR Exp value: 0xDF, Act value: 0x%X\n",bDSRmasked);

            // Get DSR again just to make sure...
            bDSR = P5ReadPortUchar(wPortDSR);           // Get content of DSR.
            bDSRmasked = (UCHAR)(bDSR | 0x07);          // Set first 3 bits (don't cares).

            if( (CHKPRNOFF1 == bDSRmasked ) || (CHKPRNOFF2 == bDSRmasked ) ) { // Check for printer off.
                DD((PCE)Pdx,DDW,"ParEcpHwRecoverPort - DSR value: 0x%X, Printer Off\n", bDSRmasked);
                status = STATUS_DEVICE_POWERED_OFF;
            } else {
                if( CHKNOCABLE == bDSRmasked ) {  // Check for cable unplugged.
                    DD((PCE)Pdx,DDW,"ParEcpHwRecoverPort - DSR value: 0x%X, Cable Unplugged\n",bDSRmasked);
                    status = STATUS_DEVICE_NOT_CONNECTED;
                } else {
                    DD((PCE)Pdx,DDW,"ParEcpHwRecoverPort - DSR value: 0x%X, Unknown error\n",bDSRmasked);
                    status = STATUS_LINK_FAILED;
                }
            }
        }
    }

    //----------------------------------------------------------------------
    // Set status byte to indicate Compatibility Mode.
    //----------------------------------------------------------------------
    P5SetPhase( Pdx, PHASE_FORWARD_IDLE );

    return status;

}   // ParEcpHwRecoverPort

NTSTATUS
ParEcpHwSetAddress(
    IN  PPDO_EXTENSION   Pdx,
    IN  UCHAR               Address
    )

/*++

Routine Description:

    Sets the ECP Address.
    
Arguments:

    Pdx           - Supplies the device extension.

    Address             - The bus address to be set.
    
Return Value:

    None.

--*/
{
    NTSTATUS   status = STATUS_SUCCESS;
    PUCHAR    wPortDSR;       // IO address of Device Status Register
    PUCHAR    wPortECR;       // IO address of Extended Control Register
    PUCHAR    wPortAFIFO;     // IO address of ECP Address FIFO
    UCHAR    bDSR;           // Contents of DSR
    UCHAR    bECR;           // Contents of ECR
    BOOLEAN    bDone;

    DD((PCE)Pdx,DDT,"ParEcpHwSetAddress, Start\n");

    // Calculate I/O port addresses for common registers
    wPortDSR = Pdx->Controller + DSR_OFFSET;
    wPortECR = Pdx->EcrController + ECR_OFFSET;
    wPortAFIFO = Pdx->Controller + AFIFO_OFFSET;

    //----------------------------------------------------------------------
    // Check for any link errors.
    //----------------------------------------------------------------------
    //ZIP_CHECK_PORT( DONT_CARE, DONT_CARE, ACTIVE, ACTIVE, DONT_CARE, DONT_CARE,
    //                "ZIP_SCA: init DCR", RECOVER_40, errorExit );

    //ZIP_CHECK_LINK( DONT_CARE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE,
    //                "ZIP_SCA: init DSR", RECOVER_41, errorExit );


    // Set state to indicate ECP forward transfer phase
    P5SetPhase( Pdx, PHASE_FORWARD_XFER );


    //----------------------------------------------------------------------
    // Send ECP channel address to AFIFO.
    //----------------------------------------------------------------------
    if ( ! ( TEST_ECR_FIFO( P5ReadPortUchar( wPortECR), ECR_FIFO_EMPTY ) ? TRUE : 
             CheckPort( wPortECR, ECR_FIFO_MASK, ECR_FIFO_EMPTY, IEEE_MAXTIME_TL ) ) ) {

        status = ParEcpHwHostRecoveryPhase(Pdx);
        DD((PCE)Pdx,DDT,"ParEcpHwSetAddress: FIFO full, timeout sending ECP channel address\n");
        status = STATUS_IO_DEVICE_ERROR;

    } else {

        // Send the address byte.  The most significant bit must be set to distinquish
        // it as an address (as opposed to a run-length compression count).
        P5WritePortUchar(wPortAFIFO, (UCHAR)(Address | 0x80));
    }

    if ( NT_SUCCESS(status) ) {

        // If there have been no previous errors, and synchronous writes
        // have been requested, wait for the FIFO to empty and the device to
        // complete the last PeriphAck handshake before returning success.

        if ( Pdx->bSynchWrites ) {

            LARGE_INTEGER   Wait;
            LARGE_INTEGER   Start;
            LARGE_INTEGER   End;

            // we wait up to 35 milliseconds.
            Wait.QuadPart = (IEEE_MAXTIME_TL * 10 * 1000) + KeQueryTimeIncrement();  // 35ms

            KeQueryTickCount(&Start);

            bDone = FALSE;
            while ( ! bDone )
            {
                bECR = P5ReadPortUchar( wPortECR );
                bDSR = P5ReadPortUchar( wPortDSR );
                // LLL/CGM 10/9/95: Tighten up link test - PeriphClk high
                if ( TEST_ECR_FIFO( bECR, ECR_FIFO_EMPTY ) &&
                     TEST_DSR( bDSR, INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE ) ) {
                    bDone = TRUE;

                } else {

                    KeQueryTickCount(&End);

                    if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart) {
                        DD((PCE)Pdx,DDT,"ParEcpHwSetAddress, timeout during synch\n");
                        bDone = TRUE;
                        status = ParEcpHwHostRecoveryPhase(Pdx);
                        status = STATUS_IO_DEVICE_ERROR;
                    }

                }

            } // of while...

        } // if bSynchWrites...

    }

    if ( NT_SUCCESS(status) ) {
        // Update the state to reflect that we are back in an idle phase
        P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
    } else if ( status == STATUS_IO_DEVICE_ERROR ) {
        // Update the state to reflect that we are back in an idle phase
        P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
    }       

    return status;
}

NTSTATUS
ParEcpHwSetupPhase(
    IN  PPDO_EXTENSION   Pdx
    )
/*++

Routine Description:

    This routine performs 1284 Setup Phase.

Arguments:

    Controller      - Supplies the port address.

Return Value:

    STATUS_SUCCESS  - Successful negotiation.

    otherwise       - Unsuccessful negotiation.

--*/
{
    NTSTATUS   Status = STATUS_SUCCESS;
    PUCHAR    pPortDCR;       // IO address of Device Control Register (DCR)
    PUCHAR    pPortDSR;       // IO address of Device Status Register (DSR)
    PUCHAR    pPortECR;       // IO address of Extended Control Register (ECR)
    UCHAR    bDCR;           // Contents of DCR

    // Calculate I/O port addresses for common registers
    pPortDCR = Pdx->Controller + OFFSET_DCR;
    pPortDSR = Pdx->Controller + OFFSET_DSR;
    pPortECR = Pdx->EcrController + ECR_OFFSET;

    // Get the DCR and make sure port hasn't been stomped
    //ZIP_CHECK_PORT( DIR_WRITE, DONT_CARE, ACTIVE, ACTIVE, DONT_CARE, DONT_CARE,
    //                "ZIP_SP: init DCR", RECOVER_44, exit1 );


    // Set HostAck low
    bDCR = P5ReadPortUchar(pPortDCR);               // Get content of DCR.
    bDCR = UPDATE_DCR( bDCR, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE );
    P5WritePortUchar( pPortDCR, bDCR );

    // for some reason dvdr doesn't want an extra check in UNSAFE_MODE
    if ( Pdx->ModeSafety == SAFE_MODE ) {
        // Wait for nAckReverse to go high
        // LLL/CGM 10/9/95:  look for PeriphAck low, PeriphClk high as per 1284 spec.
        if ( !CHECK_DSR(Pdx->Controller, INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE,
                        IEEE_MAXTIME_TL ) )
        {
            // Any failure leaves us in an unknown state to recover from.
            P5SetPhase( Pdx, PHASE_UNKNOWN );
            Status = STATUS_IO_DEVICE_ERROR;
            goto HWECP_SetupPhaseExitLabel;
        }
    }

    //----------------------------------------------------------------------
    // Set the ECR to mode 001 (PS2 Mode).
    //----------------------------------------------------------------------
    Status = Pdx->TrySetChipMode ( Pdx->PortContext, ECR_ECP_PIO_MODE );            
    // Set DCR:  DIR=0 for output, HostAck and HostClk high so HW can drive
    bDCR = UPDATE_DCR( bDCR, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
    P5WritePortUchar( pPortDCR, bDCR );

    // Set the ECR to ECP mode, disable DMA

    Pdx->PortHWMode = HW_MODE_ECP;

    // If setup was successful, mark the new ECP phase.
    P5SetPhase( Pdx, PHASE_FORWARD_IDLE );

    Status = STATUS_SUCCESS;

HWECP_SetupPhaseExitLabel:

    DD((PCE)Pdx,DDT,"ParEcpHwSetupPhase - exit w/status=%x\n",Status);

    return Status;
}

NTSTATUS ParEcpHwWaitForEmptyFIFO(IN PPDO_EXTENSION   Pdx)
/*++

Routine Description:

    This routine will babysit the Fifo.

Arguments:

    Pdx  - The device extension.

Return Value:

    NTSTATUS.

--*/
{
    UCHAR           bDSR;         // Contents of DSR
    UCHAR           bECR;         // Contents of ECR
    UCHAR           bDCR;         // Contents of ECR
    BOOLEAN         bDone = FALSE;
    PUCHAR          wPortDSR;
    PUCHAR          wPortECR;
    PUCHAR          wPortDCR;
    LARGE_INTEGER   Wait;
    LARGE_INTEGER   Start;
    LARGE_INTEGER   End;
    NTSTATUS        status = STATUS_SUCCESS;

    // Calculate I/O port addresses for common registers 
    wPortDSR = Pdx->Controller + OFFSET_DSR;
    wPortECR = Pdx->EcrController + ECR_OFFSET;
    wPortDCR = Pdx->Controller + OFFSET_DCR;

    Wait.QuadPart = (330 * 10 * 1000) + KeQueryTimeIncrement();  // 330ms
    
    KeQueryTickCount(&Start);

    //--------------------------------------------------------------------
    // wait for the FIFO to empty and the last
    // handshake of PeriphAck to complete before returning success.
    //--------------------------------------------------------------------

    while ( ! bDone )
    {
        bECR = P5ReadPortUchar(wPortECR);
        bDSR = P5ReadPortUchar(wPortDSR);
        bDCR = P5ReadPortUchar(wPortDCR);
        
#if 0 // one bit differs - keep alternate around until we know which to really use
        if ( TEST_ECR_FIFO( bECR, ECR_FIFO_EMPTY ) &&
            TEST_DCR( bDCR, INACTIVE, ***INACTIVE***, ACTIVE, ACTIVE, DONT_CARE, ACTIVE ) &&
            TEST_DSR( bDSR, INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE ) )  {
#else
        if ( TEST_ECR_FIFO( bECR, ECR_FIFO_EMPTY ) &&
            TEST_DCR( bDCR, INACTIVE, DONT_CARE, ACTIVE, ACTIVE, DONT_CARE, ACTIVE ) &&
            TEST_DSR( bDSR, INACTIVE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE ) )  {
#endif
            
            // FIFO is empty, exit without error.
            bDone = TRUE;

        } else {
        
            KeQueryTickCount(&End);
            
            if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart) {
                
                // FIFO not empty, timeout occurred, exit with error.
                // NOTE: There is not a good way to determine how many bytes
                // are stuck in the fifo
                DD((PCE)Pdx,DDT,"ParEcpHwWaitForEmptyFIFO: timeout during synch\n");
                status = STATUS_IO_TIMEOUT;
                bDone = TRUE;
            }
        }
     } // of while...
     
     return status;
}

NTSTATUS
ParEcpHwWrite(
    IN  PPDO_EXTENSION  Pdx,
    IN  PVOID           Buffer,
    IN  ULONG           BufferSize,
    OUT PULONG          BytesTransferred
    )
/*++

Routine Description:

    Writes data to the peripheral using the ECP protocol under hardware
    control.
    
Arguments:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -