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

📄 hwecp.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    Pdx->PortHWMode = HW_MODE_ECP;


    P5SetPhase( Pdx, PHASE_FORWARD_IDLE );

    return nError;
}

BOOLEAN
PptEcpHwHaveReadData (
    IN  PPDO_EXTENSION  Pdx
    )
{
    Queue     *pQueue;

    // check shadow buffer
    pQueue = &(Pdx->ShadowBuffer);
    if (!Queue_IsEmpty(pQueue)) {
        return TRUE;
    }

    // check periph
    if (ParEcpHaveReadData(Pdx))
        return TRUE;

    // Check if FIFO is not empty.
    return (BOOLEAN)( (UCHAR)0 == (P5ReadPortUchar(Pdx->EcrController + ECR_OFFSET) & ECR_FIFO_EMPTY) );
}

NTSTATUS
ParEcpHwHostRecoveryPhase(
    IN  PPDO_EXTENSION   Pdx
    )
{
    NTSTATUS  status = STATUS_SUCCESS;
    PUCHAR    pPortDCR;       // I/O address of Device Control Register
    PUCHAR    pPortDSR;       // I/O address of Device Status Register
    PUCHAR    pPortECR;       // I/O address of Extended Control Register
    UCHAR     bDCR;           // Contents of DCR
    UCHAR     bDSR;           // Contents of DSR

    if( !Pdx->bIsHostRecoverSupported ) {
        return STATUS_SUCCESS;
    }

    DD((PCE)Pdx,DDT,"ParEcpHwHostRecoveryPhase - enter\n");

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

    // Set the ECR to mode 001 (PS2 Mode)
    // Don't need to flip to Byte mode.  The ECR arbitrator will handle this.
    Pdx->PortHWMode = HW_MODE_PS2;
    
    // Set Dir=1 in DCR to disable host bus drive, because the peripheral may 
    // try to drive the bus during host recovery phase.  We are not really going
    // to let any data handshake across, because we don't set HostAck low, and
    // we don't enable the ECP chip during this phase.
    bDCR = P5ReadPortUchar(pPortDCR);               // Get content of DCR.
    bDCR = UPDATE_DCR( bDCR, DIR_READ, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
    P5WritePortUchar(pPortDCR, bDCR );
    
    // Check the DCR to see if it has been stomped on
    bDCR = P5ReadPortUchar( pPortDCR );
    if( TEST_DCR( bDCR, DIR_WRITE, DONT_CARE, ACTIVE, ACTIVE, DONT_CARE, DONT_CARE ) ) {
        // DCR ok, now test DSR for valid state, ignoring PeriphAck since it could change
        bDSR = P5ReadPortUchar( pPortDSR );
        // 11/21/95 LLL, CGM: change test to look for XFlag high
        if( TEST_DSR( bDSR, DONT_CARE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE ) ) {
            // Drop ReverseRequest to initiate host recovery
            bDCR = UPDATE_DCR( bDCR, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE );
            P5WritePortUchar( pPortDCR, bDCR );
            
            // Wait for nAckReverse response
            // 11/21/95 LLL, CGM: tightened test to include PeriphClk and XFlag.
            //                "ZIP_HRP: state 73, DSR" 
            if( CHECK_DSR( Pdx->Controller, DONT_CARE, ACTIVE, INACTIVE, ACTIVE, DONT_CARE, IEEE_MAXTIME_TL) ) {
                // Yes, raise nReverseRequest, HostClk and HostAck (HostAck high so HW can drive)
                bDCR = UPDATE_DCR( bDCR, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE, ACTIVE );
                P5WritePortUchar( pPortDCR, bDCR );

                // Wait for nAckReverse response
                // 11/21/95 LLL, CGM: tightened test to include XFlag and PeriphClk.
                //         "ZIP_HRP: state 75, DSR"
                if( CHECK_DSR( Pdx->Controller, DONT_CARE, ACTIVE, ACTIVE, ACTIVE, DONT_CARE, IEEE_MAXTIME_TL) ) {
                    // Let the host drive the bus again.
                    bDCR = P5ReadPortUchar(pPortDCR);               // Get content of DCR.
                    bDCR = UPDATE_DCR( bDCR, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
                    P5WritePortUchar(pPortDCR, bDCR );
                    
                    // Recovery is complete, let the caller decide what to do now
                    status = STATUS_SUCCESS;
                    P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
                } else {
                    status = STATUS_IO_TIMEOUT;
                    DD((PCE)Pdx,DDW,"ParEcpHwHostRecoveryPhase - error prior to state 75\n");
                }
            } else {
                status = STATUS_IO_TIMEOUT;
                DD((PCE)Pdx,DDW,"ParEcpHwHostRecoveryPhase - error prior to state 73\n");
            }
        } else {
#if DVRH_BUS_RESET_ON_ERROR
            BusReset(pPortDCR);  // Pass in the dcr address
#endif
            DD((PCE)Pdx,DDT, "ParEcpHwHostRecoveryPhase: VE_LINK_FAILURE \n");
            status = STATUS_LINK_FAILED;
        }
    } else {
        DD((PCE)Pdx,DDW,"ParEcpHwHostRecoveryPhase: VE_PORT_STOMPED\n");
        status = STATUS_DEVICE_PROTOCOL_ERROR;
    }
    
    if (!NT_SUCCESS(status)) {
        // Make sure both HostAck and HostClk are high before leaving
        // Also let the host drive the bus again.
        bDCR = P5ReadPortUchar( pPortDCR );
        bDCR = UPDATE_DCR( bDCR, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
        P5WritePortUchar( pPortDCR, bDCR );
        
        // [[REVISIT]] pSDCB->wCurrentPhase = PHASE_UNKNOWN;
    }

    // Set the ECR to ECP mode, disable DMA
    status = Pdx->TrySetChipMode ( Pdx->PortContext, ECR_ECP_PIO_MODE );

    Pdx->PortHWMode = HW_MODE_ECP;
    
    DD((PCE)Pdx,DDT,"ParEcpHwHostRecoveryPhase - Exit w/status = %x\n", status);

    return status;
}

NTSTATUS
ParEcpHwRead(
    IN  PPDO_EXTENSION   Pdx,
    IN  PVOID               Buffer,
    IN  ULONG               BufferSize,
    OUT PULONG              BytesTransferred
    )

/*++

Routine Description:

    This routine performs a 1284 ECP mode read under Hardware control
    into the given buffer for no more than 'BufferSize' bytes.

Arguments:

    Pdx           - Supplies the device extension.

    Buffer              - Supplies the buffer to read into.

    BufferSize          - Supplies the number of bytes in the buffer.

    BytesTransferred     - Returns the number of bytes transferred.

--*/

{
    NTSTATUS  status = STATUS_SUCCESS;
    PUCHAR    lpsBufPtr = (PUCHAR)Buffer;    // Pointer to buffer cast to desired data type
    ULONG     dCount = BufferSize;             // Working copy of caller's original request count
    UCHAR     bDSR;               // Contents of DSR
    UCHAR     bPeriphRequest;     // Calculated state of nPeriphReq signal, used in loop
    PUCHAR    wPortDSR = Pdx->Controller + DSR_OFFSET;
    PUCHAR    wPortECR = Pdx->EcrController + ECR_OFFSET;
    PUCHAR    wPortDFIFO = Pdx->EcrController;
    LARGE_INTEGER   WaitPerByteTimer;
    LARGE_INTEGER   StartPerByteTimer;
    LARGE_INTEGER   EndPerByteTimer;
    BOOLEAN         bResetTimer = TRUE;
    ULONG           wBurstCount;        // Calculated amount of data in FIFO
    UCHAR           ecrFIFO;
    
    WaitPerByteTimer.QuadPart = (35 * 10 * 1000) + KeQueryTimeIncrement();
    
    //----------------------------------------------------------------------
    // Set status byte to indicate Reverse Transfer Phase.
    //----------------------------------------------------------------------
    P5SetPhase( Pdx, PHASE_REVERSE_XFER );
    
    //----------------------------------------------------------------------
    // We've already checked the shadow in ParRead. So go right to the
    // Hardware FIFO and pull more data across.
    //----------------------------------------------------------------------
    KeQueryTickCount(&StartPerByteTimer);   // Start the timer
    
ParEcpHwRead_ReadLoopStart:
    //------------------------------------------------------------------
    // Determine whether the FIFO has any data and respond accordingly
    //------------------------------------------------------------------
    ecrFIFO = (UCHAR)(P5ReadPortUchar(wPortECR) & (UCHAR)ECR_FIFO_MASK);
    
    if (ECR_FIFO_FULL == ecrFIFO) {

        wBurstCount = ( dCount > Pdx->FifoDepth ? Pdx->FifoDepth : dCount );
        dCount -= wBurstCount;
        
        P5ReadPortBufferUchar(wPortDFIFO, lpsBufPtr, wBurstCount);
        lpsBufPtr += wBurstCount;

        bResetTimer = TRUE;

    } else if (ECR_FIFO_SOME_DATA == ecrFIFO) {
        // Read just one byte at a time, since we don't know exactly how much is
        // in the FIFO.
        *lpsBufPtr = P5ReadPortUchar(wPortDFIFO);
        lpsBufPtr++;
        dCount--;

        bResetTimer = TRUE;

    } else {   // ECR_FIFO_EMPTY

        DD((PCE)Pdx,DDW,"ParEcpHwRead - ECR_FIFO_EMPTY - slow or bad periph?\n");
        // Nothing to do. We either have a slow peripheral or a bad peripheral.
        // We don't have a good way to figure out if its bad.  Let's chew up our
        // time and hope for the best.

        bResetTimer = FALSE;

    }   //  ECR_FIFO_EMPTY a.k.a. else clause of (ECR_FIFO_FULL == ecrFIFO)
    
    if (dCount == 0)
        goto ParEcpHwRead_ReadLoopEnd;
    else {

        // Limit the overall time we spend in this loop.
        if (bResetTimer) {
            bResetTimer = FALSE;
            KeQueryTickCount(&StartPerByteTimer);   // Restart the timer
        } else {
            KeQueryTickCount(&EndPerByteTimer);
            if (((EndPerByteTimer.QuadPart - StartPerByteTimer.QuadPart) * KeQueryTimeIncrement()) > WaitPerByteTimer.QuadPart)
                goto ParEcpHwRead_ReadLoopEnd;
        }

    }

 goto ParEcpHwRead_ReadLoopStart;

ParEcpHwRead_ReadLoopEnd:

    P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
    
    *BytesTransferred  = BufferSize - dCount;      // Set current count.
    
    Pdx->log.HwEcpReadCount += *BytesTransferred;
    
    if (0 == *BytesTransferred) {
        bDSR = P5ReadPortUchar(wPortDSR);
        bPeriphRequest = (UCHAR)TEST_DSR( bDSR, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE );
        // Only flag a timeout error if the device still said it had data to send.
        if ( bPeriphRequest ) {
            //
            // Periph still says that it has data, but we timed out trying to read the data.
            //
            DD((PCE)Pdx,DDE,"ParEcpHwRead - read timout with nPeriphRequest asserted and no data read - error - STATUS_IO_TIMEOUT\n");
            status = STATUS_IO_TIMEOUT;
            if ((TRUE == Pdx->P12843DL.bEventActive) ) {
                //
                // Signal transport that it should try another read
                //
                KeSetEvent(Pdx->P12843DL.Event, 0, FALSE);
            }
        }
    }

    DD((PCE)Pdx,DDT,"ParEcpHwRead: Exit - status=%x, BytesTransferred[%d] dsr[%02x] dcr[%02x] ecr[%02x]\n",
       status, *BytesTransferred, P5ReadPortUchar(wPortDSR), 
       P5ReadPortUchar(Pdx->Controller + OFFSET_DCR), P5ReadPortUchar(wPortECR));
    
#if 1 == DBG_SHOW_BYTES
    if( DbgShowBytes ) {
        if( NT_SUCCESS( status ) && (*BytesTransferred > 0) ) {
            const ULONG maxBytes = 32;
            ULONG i;
            PUCHAR bytePtr = (PUCHAR)Buffer;
            DbgPrint("R: ");
            for( i=0 ; (i < *BytesTransferred) && (i < maxBytes ) ; ++i ) {
                DbgPrint("%02x ",*bytePtr++);
            }
            if( *BytesTransferred > maxBytes ) {
                DbgPrint("... ");
            }
            DbgPrint("zz\n");
        }
    }
#endif

    return status;
}   // ParEcpHwRead

NTSTATUS
ParEcpHwRecoverPort(
    PPDO_EXTENSION Pdx,
    UCHAR  bRecoverCode
    )
{
    NTSTATUS   status = STATUS_SUCCESS;
    PUCHAR    wPortDCR;       // IO address of Device Control Register (DCR)
    PUCHAR    wPortDSR;       // IO address of Device Status Register (DSR)
    PUCHAR    wPortECR;       // IO address of Extended Control Register (ECR)
    PUCHAR    wPortData;      // IO address of Data Register
    UCHAR    bDCR;           // Contents of DCR
    UCHAR    bDSR;           // Contents of DSR
    UCHAR    bDSRmasked;     // DSR after masking low order bits

    DD((PCE)Pdx,DDT,"ParEcpHwRecoverPort:  enter %d\n", bRecoverCode );

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


    //----------------------------------------------------------------------
    // Check if port is stomped.
    //----------------------------------------------------------------------
    bDCR = P5ReadPortUchar(wPortDCR);               // Get content of DCR.

    if ( ! TEST_DCR( bDCR, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, DONT_CARE, DONT_CARE ) )
    {
        #if DVRH_BUS_RESET_ON_ERROR
            BusReset(wPortDCR);  // Pass in the dcr address
        #endif
        DD((PCE)Pdx,DDE,"ParEcpHwRecoverPort - port stomped\n");
        status = STATUS_DEVICE_PROTOCOL_ERROR;
    }


    //----------------------------------------------------------------------
    // Attempt a termination phase to get the peripheral recovered.
    // Ignore the error return, we've already got that figured out.
    //----------------------------------------------------------------------
    IeeeTerminate1284Mode(Pdx );

    //----------------------------------------------------------------------
    // Set the ECR to PS2 Mode so we can change bus direction.
    //----------------------------------------------------------------------
    Pdx->ClearChipMode( Pdx->PortContext, ECR_ECP_PIO_MODE );
    Pdx->PortHWMode = HW_MODE_PS2;

    //----------------------------------------------------------------------
    // Assert nSelectIn low, nInit high, nStrobe high, and nAutoFd high.
    //----------------------------------------------------------------------
    bDCR = P5ReadPortUchar(wPortDCR);             // Get content of DCR.
    bDCR = UPDATE_DCR( bDCR, DIR_WRITE, DONT_CARE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
    P5WritePortUchar(wPortDCR, bDCR);
    P5WritePortUchar(wPortData, bRecoverCode);      // Output the error ID

⌨️ 快捷键说明

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