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

📄 parmode.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 4 页
字号:
    // reading a non-existant ECR could have one of two results:  the ECR address
    // could decode on top of the DCR, so we'll read the value we are about to set.
    // Alternately, we might just read a floating bus and get a random value.
    dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, INACTIVE, ACTIVE );
    WRITE_PORT_UCHAR( wPortDCR, dcr );

    ecrLast = ecr = READ_PORT_UCHAR(wPortECR);
    
    PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: Ecr Value After DCR write: %x\n", ecr));
    
    // Attempt to read the ECR.  If ECP hardware is present, the ECR register's
    // bit 1 and bit 0 should read a 00 (some data in the FIFO), 01 (FIFO empty),
    // or 10 (FIFO full).  If we read a 11 (illegal combination) then we know for
    // sure that no ECP hardware is present.  Also, a valid ECR should never return
    // 0xFF (but a nonexistant register probably would), so we'll test for that 
    // specific value also.
    if ( ( TEST_ECR_FIFO( ecr, ECR_FIFO_MASK ) ) || ( ecrLast == 0xFF ) )
    {
        // ECR[1:0] returned a value of 11, so this can't be hardware ECP.
        PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort:  illegal FIFO status\n"));

        // Restore the DCR so that all lines are inactive.
        dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
        WRITE_PORT_UCHAR( wPortDCR, dcr );
        return;
    }

    // OK, so we got either a 00, 01, or 10 for ECR[1:0].  If it was 10, the
    if ( TEST_ECR_FIFO( ecr, ECR_FIFO_FULL ) )  // Looking for ECR[1:0] of 10...
    {
        // The ECR[1:0] returned 10.  This is a legal value, but possibly the
        // hardware might have just decoded the DCR and we merely read back the
        // DCR value we set earlier.  Or, we might have just read back a value
        // that was hanging on the bus due to bus capacitance.  So, we'll change 
        // the DCR, read the ECR again, and see if the two registers continue to 
        // track each other.  If they do track, we'll conclude that there is no
        // ECP hardware.

        // Put the DCR's nAutoFeed and nStrobe register bits back to zero.
        dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
        WRITE_PORT_UCHAR( wPortDCR, dcr );

        // Read the ECR again
        ecr = READ_PORT_UCHAR( wPortECR );

        if ( TEST_ECR_FIFO( ecr, ECR_FIFO_SOME_DATA ) )
        {
            // ECR[1:0] is tracking DCR[1:0], so this can't be hardware ECP.
            PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: FIFO status follows DCR\r\n"));
            // Restore the DCR so that all lines are inactive.
            dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
            WRITE_PORT_UCHAR( wPortDCR, dcr );
            return;
        }
    }
    
    // If we get this far, then the ECR appears to be returning something valid that
    // doesn't track the DCR.  It is beginning to look promising.  We're going
    // to take a chance, and write the ECR to put the chip in compatiblity
    // mode.  Doing so will reset the FIFO, so when we read FIFO status it should
    // come back empty.  However, if we're wrong and this isn't ECP hardware, the
    // value we're about to write will turn on 1284Active (nSelectIn) and this might
    // cause headaches for the peripheral.
    WRITE_PORT_UCHAR( wPortECR, DEFAULT_ECR_COMPATIBILITY );

    // Read the ECR again
    ecr = READ_PORT_UCHAR( 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 ) )
    {
        PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: FIFO shows full\n"));
        // Restore the DCR so that all lines are inactive.
        dcr = SET_DCR( DIR_WRITE, IRQEN_DISABLE, INACTIVE, ACTIVE, ACTIVE, ACTIVE );
        WRITE_PORT_UCHAR( 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
    WRITE_PORT_UCHAR(wPortECR, ecrLast);

    //
    // Test here for ECP capable
    //

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

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

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

        PptDump2(PARINITDEV, ("ParMode::PptDetectEcpPort: ECP present\n") );
    }
    
    // return ecr to original
    WRITE_PORT_UCHAR( wPortECR, ecrLast);
    return;
}

VOID
PptDetectEppPortIfDot3DevicePresent(
    IN  PDEVICE_EXTENSION   Extension
    )
    
/*++
      
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:
      
    Extension           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
    
{
    NTSTATUS status;
    PUCHAR   Controller = Extension->PortInfo.Controller;
    UCHAR    Reverse = (UCHAR)(DCR_DIRECTION | DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
    UCHAR    Forward = (UCHAR)(DCR_NOT_INIT | DCR_AUTOFEED | DCR_DSTRB);
    BOOLEAN  daisyChainDevicePresent = FALSE;
    // ULONG    DisableEppTest = 0; // any value != 0 means disable the test
    PARALLEL_1284_COMMAND Command;

    if( 0 == Extension->PnpInfo.Ieee1284_3DeviceCount ) {
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPortIfDot3DevicePresent "
                              "- No dot3 device present - aborting - Controller=%x\n", Controller) );
        PARDD01(("-- No DOT3 Device Present\n"));
        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( Extension, &Command );
    if( !NT_SUCCESS( status ) ) {
        // unable to select device - something is wrong - just bail out
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPortIfDot3DevicePresent: "
                              "unable to select 1284.3 device - bailing out - Controller=%x\n",
                              Controller) );
        return;
    }

    //
    // do the detection for chipset EPP capability
    //
    PARDD01(("-- DOT3 Device Present and selected\n"));
    PptDetectEppPort( Extension );

    //
    // Deselect 1284.3 daisy chain device
    //
    Command.ID           = 0;
    Command.Port         = 0;
    Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
    status = PptDeselectDevice( Extension, &Command );
    if( !NT_SUCCESS( status ) ) {
        // deselect failed??? - this shouldn't happen - our daisy chain interface is likely hung
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: deselect 1284.3 device FAILED - Controller=%x\n", Controller) );
    } else {
        // 1284.3 daisy chain device deselected
        PARDD01(("-- DOT3 Device deselected\n"));
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: 1284.3 device deselected - Controller=%x\n", Controller) );
    }
    
#if DBG
    if( Extension->PnpInfo.HardwareCapabilities & PPT_EPP_PRESENT ) {
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP present - Controller=%x\n", Controller) );
    } else {
        PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: EPP NOT present - Controller=%x\n", Controller) );        
    }
#endif

    return;
}

VOID
PptDetectEppPortIfUserRequested(
    IN  PDEVICE_EXTENSION   Extension
    )
    
/*++
      
Routine Description:
      
    If user explicitly requested Generic EPP detection then do the check.
      
Arguments:
      
    Extension           - Supplies the device extension of the device we are
                            reporting resources for.
      
Return Value:
      
    None.
      
--*/
    
{
    ULONG RequestEppTest = 0;
    PptRegGetDeviceParameterDword( Extension->PhysicalDeviceObject, (PWSTR)L"RequestEppTest", &RequestEppTest );
    if( RequestEppTest ) {
        PARDD01(("-- User Requested EPP detection - %x\n", RequestEppTest));
        PptDetectEppPort( Extension );
    } else {
        PARDD01(("-- User did not request EPP detection\n"));
    }
    return;
}

VOID
PptDetectEppPort(
    IN  PDEVICE_EXTENSION   Extension
    )
    
/*++
      
Routine Description:
      
    This routine checks for EPP capable port after ECP was found.
      
Arguments:
      
    Extension           - 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);
    BOOLEAN  daisyChainDevicePresent = FALSE;
    ULONG    DisableEppTest = 0; // any value != 0 means disable the test

    PARDD01(("-- PptDetectEppPort - Enter\n"));
    PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: Enter\n") );

    Controller = Extension->PortInfo.Controller;
    
    // Get current DCR
    dcr = READ_PORT_UCHAR( 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.
    //
    Extension->PnpInfo.HardwareCapabilities |= PPT_EPP_PRESENT;

    // Setting EPP mode
    PptDump2(PARINITDEV, ("ParMode::PptDetectEppPort: Setting EPP Mode\n") );
    PptEcrSetMode( Extension, 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
        WRITE_PORT_UCHAR( Controller + DCR_OFFSET, Reverse );
        KeStallExecutionProcessor( 5 );
        WRITE_PORT_UCHAR( Controller + EPP_OFFSET, (UCHAR)i );

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

    // Clearing EPP Mode
    PptEcrClearMode( Extension );
    // Restore DCR
    WRITE_PORT_UCHAR( Controller + DCR_OFFSET, dcr );

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

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

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

    Status = PptSetByteMode( Extension, ECR_BYTE_PIO_MODE );

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

}

VOID PptDetermineFifoDepth(
    IN PDEVICE_EXTENSION   Extension
    )
{
    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 = Extension->PortInfo.Controller;
    #if (0 == DVRH_USE_PARPORT_ECP_ADDR)
        wPortECR = Controller + ECR_OFFSET;
        wPortDFIFO = Controller + ECP_DFIFO_OFFSET;
    #else
        wPortECR =  Extension->PnpInfo.EcpController+ ECR_OFFSET;
        wPortDFIFO = Extension->PnpInfo.EcpController;
    #endif
    wFifoDepth = 0;

    ecrLast = READ_PORT_UCHAR(wPortECR );

    WRITE_PORT_UCHAR(wPortECR, DEFAULT_ECR_TEST );

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

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

        PptDump2(PARINITDEV, ("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
            WRITE_PORT_UCHAR( wPortECR, ecrLast);
            PptDump2(PARINITDEV, ("ParMode::PptDetermineFifoDepth:::  No Fifo\n"));
            return;

⌨️ 快捷键说明

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