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

📄 chipmode.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
    // Read the ECR again
    ecr = P5ReadPortUchar( wPortECR );

    // Now test the ECR snapshot to see if the FIFO status is correct.  The FIFO
    // should test empty.
    if (!TEST_ECR_FIFO( ecr, ECR_FIFO_EMPTY ) )
    {
        // Restore the DCR so that all lines are inactive.
        dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
        P5WritePortUchar( wPortDCR, dcr );
        return;
    }

    // OK, it looks very promising.  Perform a couple of additional tests that
    // will give us a lot of confidence, as well as providing some information
    // we need about the ECP chip.
    
    // return ecr to original
    P5WritePortUchar(wPortECR, ecrLast);

    //
    // Test here for ECP capable
    //

    // get value from ECR reg & save it
    ecrLast = P5ReadPortUchar( wPortECR );
    ecr     = (UCHAR)(ecrLast & ECR_MODE_MASK);

    // Put the chip into test mode; the FIFO should start out empty
    P5WritePortUchar(wPortECR, (UCHAR)(ecr | ECR_TEST_MODE) );

    PptDetermineFifoWidth(Fdx);    
    if( 0 != Fdx->PnpInfo.FifoWidth) {
        Fdx->PnpInfo.HardwareCapabilities |= PPT_ECP_PRESENT;
 
        PptDetermineFifoDepth( Fdx );

        if( 0 == Fdx->PnpInfo.FifoDepth ) {
            // Probe for FIFO depth failed - mark ECP as bad chip mode
            Fdx->PnpInfo.HardwareCapabilities &= ~(PPT_ECP_PRESENT);
        }
    }
    
    // return ecr to original
    P5WritePortUchar( wPortECR, ecrLast );

    return;
}

VOID
PptDetectEppPortIfDot3DevicePresent(
    IN  PFDO_EXTENSION   Fdx
    )
    
/*++
      
Routine Description:
      
    If a 1284.3 daisy chain device is present, use the dot3 device to screen
    any printer from signal leakage while doing EPP detection. Otherwise
    abort detection.
      
Arguments:
      
    Fdx           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
    
{
    NTSTATUS status;
    PUCHAR   Controller = Fdx->PortInfo.Controller;
    PARALLEL_1284_COMMAND Command;

    if( 0 == Fdx->PnpInfo.Ieee1284_3DeviceCount ) {
        // No dot3 DC device present - aborting - unsafe for some printers if we check for EPP here
        return;
    }
        
    //
    // 1284.3 daisy chain device is present. Use device to screen printer from
    //   possible signal leakage.
    //

    //
    // Select 1284.3 daisy chain  device
    //
    Command.ID           = 0;
    Command.Port         = 0;
    Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
    status = PptTrySelectDevice( Fdx, &Command );
    if( !NT_SUCCESS( status ) ) {
        // unable to select device - something is wrong - just bail out
        return;
    }

    //
    // do the detection for chipset EPP capability
    //
    // DOT3 Device Present and selected
    PptDetectEppPort( Fdx );

    //
    // Deselect 1284.3 daisy chain device
    //
    Command.ID           = 0;
    Command.Port         = 0;
    Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
    status = PptDeselectDevice( Fdx, &Command );
    if( !NT_SUCCESS( status ) ) {
        // deselect failed??? - this shouldn't happen - our daisy chain interface is likely hung
        DD((PCE)Fdx,DDE,"PptDetectEppPort - deselect of 1284.3 device FAILED - Controller=%x\n", Controller);
    }
    
    return;
}

VOID
PptDetectEppPortIfUserRequested(
    IN  PFDO_EXTENSION   Fdx
    )
/*++
      
Routine Description:
      
    If user explicitly requested Generic EPP detection then do the check.
      
Arguments:
      
    Fdx           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
{
    ULONG RequestEppTest = 0;
    PptRegGetDeviceParameterDword( Fdx->PhysicalDeviceObject, (PWSTR)L"RequestEppTest", &RequestEppTest );
    if( RequestEppTest ) {
        DD((PCE)Fdx,DDT,"-- User Requested EPP detection - %x\n", RequestEppTest);
        PptDetectEppPort( Fdx );
    } else {
        DD((PCE)Fdx,DDT,"-- User did not request EPP detection\n");
    }
    return;
}

VOID
PptDetectEppPort(
    IN  PFDO_EXTENSION   Fdx
    )
    
/*++
      
Routine Description:
      
    This routine checks for EPP capable port after ECP was found.
      
Arguments:
      
    Fdx           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
    
{
    PUCHAR   Controller;
    UCHAR    dcr, i;
    UCHAR    Reverse = (UCHAR)(DCR_DIRECTION | DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
    UCHAR    Forward = (UCHAR)(DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);

    ASSERTMSG(FALSE, "PptDetectEppPort shouldn't be called in current driver version");

    DD((PCE)Fdx,DDT,"-- PptDetectEppPort - Enter\n");
    DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: Enter\n");

    Controller = Fdx->PortInfo.Controller;
    
    // Get current DCR
    dcr = P5ReadPortUchar( Controller + DCR_OFFSET );

    //
    // Temporarily set capability to true to bypass PptEcrSetMode validity
    //   check. We'll clear the flag before we return if EPP test fails.
    //
    Fdx->PnpInfo.HardwareCapabilities |= PPT_EPP_PRESENT;

    // Setting EPP mode
    DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: Setting EPP Mode\n");
    PptEcrSetMode( Fdx, ECR_EPP_PIO_MODE );

    //
    // Testing the hardware for EPP capable
    //
    for ( i = 0x01; i <= 0x02; i++ ) {
        // Put it into reverse phase so it doesn't talk to a device
        P5WritePortUchar( Controller + DCR_OFFSET, Reverse );
        KeStallExecutionProcessor( 5 );
        P5WritePortUchar( Controller + EPP_OFFSET, (UCHAR)i );

        // put it back into forward phase to read the byte we put out there
        P5WritePortUchar( Controller + DCR_OFFSET, Forward );
        KeStallExecutionProcessor( 5 );
        if ( P5ReadPortUchar( Controller ) != i ) {
            // failure so clear EPP flag
            Fdx->PnpInfo.HardwareCapabilities &= ~PPT_EPP_PRESENT;
            break;
        }
    }

    // Clearing EPP Mode
    PptEcrClearMode( Fdx );
    // Restore DCR
    P5WritePortUchar( Controller + DCR_OFFSET, dcr );

    Fdx->CheckedForGenericEpp = TRUE; // check is complete

    if( Fdx->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT ) {
        DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: EPP present - Controller=%x\n", Controller);
        DD((PCE)Fdx,DDT,"-- PptDetectEppPort - HAVE Generic EPP\n");
    } else {
        DD((PCE)Fdx,DDT,"ParMode::PptDetectEppPort: EPP NOT present - Controller=%x\n", Controller);
        DD((PCE)Fdx,DDT,"-- PptDetectEppPort - DON'T HAVE Generic EPP\n");
    }

    DD((PCE)Fdx,DDT,"-- PptDetectEppPort - Exit\n");
    return;
}

VOID
PptDetectBytePort(
    IN  PFDO_EXTENSION   Fdx
    )
    
/*++
      
Routine Description:
      
    This routine check to see if the port is Byte capable.
      
Arguments:
      
    Fdx           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
    
{
    NTSTATUS    Status = STATUS_SUCCESS;
    
    DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort Enter.\n" );

    Status = PptSetByteMode( Fdx, ECR_BYTE_PIO_MODE );

    if ( NT_SUCCESS(Status) ) {
        // Byte Mode found
        DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort: Byte Found\n");
        Fdx->PnpInfo.HardwareCapabilities |= PPT_BYTE_PRESENT;
    } else {
        // Byte Mode Not Found
        DD((PCE)Fdx,DDT,"ParMode::PptDetectBytePort: Byte Not Found\n");
    }    
    
    (VOID)PptClearByteMode( Fdx );

}

VOID PptDetermineFifoDepth(
    IN PFDO_EXTENSION   Fdx
    )
{
    PUCHAR  Controller;
    PUCHAR  wPortECR;       // IO address of Extended Control Register (ECR)
    PUCHAR  wPortDFIFO;
    UCHAR   ecr, ecrLast;
    ULONG   wFifoDepth;
    UCHAR   writeFifoDepth;     // Depth calculated while writing FIFO
    UCHAR   readFifoDepth;      // Depth calculated while reading FIFO
    ULONG   limitCount;         // Prevents infinite looping on FIFO status
    UCHAR   testData;
    
    Controller = Fdx->PortInfo.Controller;
    wPortECR =  Fdx->PnpInfo.EcpController+ ECR_OFFSET;
    wPortDFIFO = Fdx->PnpInfo.EcpController;
    wFifoDepth = 0;

    ecrLast = P5ReadPortUchar(wPortECR );

    P5WritePortUchar(wPortECR, DEFAULT_ECR_TEST );

    ecr = P5ReadPortUchar(wPortECR );
    
    if ( TEST_ECR_FIFO( ecr, ECR_FIFO_EMPTY ) ) {
    
        // Write bytes into the FIFO until it indicates full.
        writeFifoDepth = 0;
        limitCount     = 0;
        
        while (((P5ReadPortUchar (wPortECR) & ECR_FIFO_MASK) != ECR_FIFO_FULL ) &&
                    (limitCount <= ECP_MAX_FIFO_DEPTH)) {
                    
            P5WritePortUchar( wPortDFIFO, (UCHAR)(writeFifoDepth & 0xFF) );
            writeFifoDepth++;
            limitCount++;
        }
        
        DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth::  write fifo depth = %d\r\n", writeFifoDepth);

        // Now read the bytes back, comparing what comes back.
        readFifoDepth = 0;
        limitCount    = 0;
        
        while (((P5ReadPortUchar( wPortECR ) & ECR_FIFO_MASK ) != ECR_FIFO_EMPTY ) &&
                    (limitCount <= ECP_MAX_FIFO_DEPTH)) {
                    
            testData = P5ReadPortUchar( wPortDFIFO );
            if ( testData != (readFifoDepth & (UCHAR)0xFF )) {
            
                // Data mismatch indicates problems...
                // FIFO status didn't pan out, may not be an ECP chip after all
                P5WritePortUchar( wPortECR, ecrLast);
                DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth:::  data mismatch\n");
                return;
            }
            
            readFifoDepth++;
            limitCount++;
        }

        DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth:::  read fifo depth = %d\r\n", readFifoDepth);

        // The write depth should match the read depth...
        if ( writeFifoDepth == readFifoDepth ) {
        
            wFifoDepth = readFifoDepth;
            
        } else {
        
            // Assume no FIFO
            P5WritePortUchar( wPortECR, ecrLast);
            DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth:::  No Fifo\n");
            return;
        }
                
    } else {
    
        // FIFO status didn't pan out, may not be an ECP chip after all
        DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoDepth::  Bad Fifo\n");
        P5WritePortUchar(wPortECR, ecrLast);
        return;
    }

    // put chip into spp mode
    P5WritePortUchar( wPortECR, ecrLast );
    Fdx->PnpInfo.FifoDepth = wFifoDepth;
}

VOID
PptDetermineFifoWidth(
    IN PFDO_EXTENSION   Fdx
    )
{
    PUCHAR Controller;
    UCHAR   bConfigA;
    PUCHAR wPortECR;

    DD((PCE)Fdx,DDT,"ParMode::PptDetermineFifoWidth: Start\n");
    Controller = Fdx->PortInfo.Controller;

    wPortECR = Fdx->PnpInfo.EcpController + ECR_OFFSET;

    // Put chip into configuration mode so we can access the ConfigA register
    P5WritePortUchar( wPortECR, DEFAULT_ECR_CONFIGURATION );

    // The FIFO width is bits <6:4> of the ConfigA register.
    bConfigA = P5ReadPortUchar( Fdx->PnpInfo.EcpController );
    Fdx->PnpInfo.FifoWidth = (ULONG)(( bConfigA & CNFGA_IMPID_MASK ) >> CNFGA_IMPID_SHIFT);

    // Put the chip back in compatibility mode.
    P5WritePortUchar(wPortECR, DEFAULT_ECR_COMPATIBILITY );
    return;
}

NTSTATUS
PptSetChipMode (
    IN  PFDO_EXTENSION  Fdx,
    IN  UCHAR              ChipMode
    )

/*++

Routine Description:

    This function will put the current parallel chip into the
    given mode if supported.  The determination of supported mode 
    was in the PptDetectPortType function.

Arguments:

    Fdx   - Supplies the device extension.

Return Value:

    STATUS_SUCCESS  - if the port type was detected.
   !STATUS_SUCCESS  - otherwise.

--*/

{
    NTSTATUS    Status = STATUS_SUCCESS;
    UCHAR EcrMode = (UCHAR)( ChipMode & ~ECR_MODE_MASK );

    // Also allow PptSetChipMode from PS/2 mode - we need this for HWECP
    //   bus flip from Forward to Reverse in order to meet the required
    //   sequence specified in the Microsoft ECP Port Spec version 1.06,
    //   July 14, 1993, to switch directly from PS/2 mode with output 
    //   drivers disabled (direction bit set to "read") to HWECP via 
    //   the ECR. Changed 2000-02-11.
    if ( Fdx->PnpInfo.CurrentMode != INITIAL_MODE && Fdx->PnpInfo.CurrentMode != ECR_BYTE_MODE ) {

        DD((PCE)Fdx,DDW,"PptSetChipMode - CurrentMode invalid\n");

        // Current mode is not valid to put in EPP or ECP mode
        Status = STATUS_INVALID_DEVICE_STATE;

⌨️ 快捷键说明

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