findecp.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 380 行

C
380
字号
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:

   FINDECP.C

Abstract:

   ECP hardware detection functions

Notes:


--*/


#include  <windows.h>
#include  <wdm.h>
#include  "pardbg.h"
#include  "1284comm.h"
#include  "tmtick.h"
#include  "comdef.h"
#include  "ecpreg.h"


// ECP ImpID
#define ECP_IMPID_MASK       0x70    // 0111 0000
#define ECP_IS_16BIT         0x00
#define ECP_IS_8BIT          0x10
#define ECP_IS_32BIT         0x20

// ECR test mode with interrupt enabled
#define ECP_TEST_MODE_INT    0xD0    // Test Mode,dmaEn=0,serviceIntr=0

// interrupt type in CnfgA
#define ECP_ISA_LEVEL        0x80

/*
//-------------------------------------------------------------------------
// Internal routine
//-------------------------------------------------------------------------
BOOL GetFifoInfo
(
    PPortInformation PortObj
)
// PURPOSE
//
//  This function supports to detect the depth of FIFO and read/write service
//  interrupt threshold from test mode.
// 
// ASSUMPTIONS & ASSERTIONS
//  A)readIntrThreshold is determined by
//   1)setting direction bit to 1.
//   2)filling empty tFifo a PWORD at a time until serviceIntr is set.
//
//  B)writeIntrThreshold is determined by
//   1)starting from a full FIFO
//   2)setting direction bit to 0
//   3)emptying FIFO a PWORD at a time until serviceIntr is set.
// 
//  C)depth of FIFO is determined by
//   1)filling empty tFifo a PWORD at a time until full bit is set.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
//---------------------------------------------------------------------------
{
    WORD        wCount = 0;
    WORD        wData = 0xFFFF;
    DWORD       dwData = 0xFFFFFFFF;
    BYTE        bData;
    BYTE        bStatus;
    unsigned    uD_reg;
    unsigned    uC_reg;
    unsigned    uE_reg;
    WORD        wTemp;
    
    uC_reg = PortObj->ulBase + ECP_DCR_Reg;
    uE_reg = PortObj->ulBase + ECP_ECR_Reg;
    uD_reg = PortObj->ulBase + ECP_TFifo;
    
    DEBUGMSG(ZONE_IO,(TEXT("[GetFifoInfo]: Test mode, Interrupt enabled.")));


    // Initialize FIFO records
    PortObj->lpFIFO.wFifoDepth = 1;
    PortObj->lpFIFO.writeIntrThreshold = 0;
    PortObj->lpFIFO.readIntrThreshold = 1;

    // Set direction = 1 
    bData = (BYTE)(READ_PORT_UCHAR((PUCHAR)uC_reg) | ECP_DCR_DIRECTION_BIT_1);
    WRITE_PORT_UCHAR((PUCHAR)uC_reg, bData);
    
    // Set to test mode and enable interrupt service
    // Find out the depth of FIFO and read/write thresholds
    WRITE_PORT_UCHAR((PUCHAR)uE_reg, ECP_TEST_MODE_INT);

    bData = 0xFF;
    
    do
    {
        // Write a PWORD to tFifo register, reverse direction now
        //(PortObj->lpFIFO.wFifoSize == ECP_8BIT) ? WRITE_PORT_UCHAR((PUCHAR)uD_reg, bData) :
        // (PortObj->lpFIFO.wFifoSize == ECP_16BIT) ? outps(uD_reg, wData) : 
        //            outpl(uD_reg, dwData);

        WRITE_PORT_UCHAR((PUCHAR)uD_reg, bData);

        wCount ++;

        bStatus = READ_PORT_UCHAR((PUCHAR)uE_reg);
        if ((bStatus & ECP_FIFOBITS_MASK) == ECP_FIFO_EMPTY)
            return(FALSE);
            
        bStatus &= ECP_ECR_SERVICE_INT_BIT;  //0x04    
        
    } while (bStatus != ECP_ECR_SERVICE_INT_ON);

    PortObj->lpFIFO.readIntrThreshold = (WORD)(wCount * PortObj->lpFIFO.wFifoSize);
    
#ifdef MAXDEBUG
    wTemp = PortObj->lpFIFO.readIntrThreshold;
    
    _asm { push  eax }
    _asm { mov   ax, wTemp }
    
    Trace_Out("Get ReadIntrTh = #AX bytes ");
    _asm { pop   eax }
#endif

    do
    {
        // Write a PWORD to tFifo register, forward direction now
        (PortObj->lpFIFO.wFifoSize == ECP_8BIT) ? WRITE_PORT_UCHAR((PUCHAR)uD_reg, bData) :
        (PortObj->lpFIFO.wFifoSize == ECP_16BIT) ? outps(uD_reg, wData) :
            outpl(uD_reg, dwData);

        wCount ++;

        bStatus = (BYTE)(READ_PORT_UCHAR((PUCHAR)uE_reg) & ECP_FIFOBITS_MASK);
        
    } while (bStatus != ECP_FIFO_FULL);

    PortObj->lpFIFO.wFifoDepth = wCount;

#ifdef MAXDEBUG
    _asm { push  eax }
    _asm { mov   ax, wCount }
    
    Trace_Out("Get fifo depth = #AX PWORD ");
    _asm { pop   eax }
#endif

    // Now we have a full FIFO could be used for detecting write threshold
    // Set direction 0 and reset serviceIntr
    bData = READ_PORT_UCHAR((PUCHAR)uC_reg);
    WRITE_PORT_UCHAR((PUCHAR)uC_reg, (BYTE)(bData & ECP_DCR_DIRECTION_BIT_MASK));

    bData = READ_PORT_UCHAR((PUCHAR)uE_reg);
    WRITE_PORT_UCHAR((PUCHAR)uE_reg, (BYTE)(bData & ECP_ECR_SERVICE_INT_MASK));

    do
    {
        // read a PWORD from FIFO
        (PortObj->lpFIFO.wFifoSize == ECP_8BIT) ? (bData = READ_PORT_UCHAR((PUCHAR)uD_reg)) :
        (PortObj->lpFIFO.wFifoSize == ECP_16BIT) ? (wData = inpw(uD_reg)) :
            (dwData = inpd(uD_reg));

        wCount --;
        
        // Check the interrupt sesrvice bit
        bData = READ_PORT_UCHAR((PUCHAR)uE_reg);
        if (bData & ECP_ECR_SERVICE_INT_BIT)
            break;
            
    } while (wCount > 0);

    PortObj->lpFIFO.writeIntrThreshold = (WORD)(wCount * PortObj->lpFIFO.wFifoSize);

#ifdef MAXDEBUG
    wTemp = PortObj->lpFIFO.writeIntrThreshold;
    
    _asm { push  eax }
    _asm { mov   ax, wTemp}
    
    Trace_Out("Get WriteIntrTh = #AX bytes ");
    _asm { pop   eax }
#endif

    return (TRUE);
}
*/

//---------------------------------------------------------------------------
BOOL
IsHwECP
(
    PPortInformation     PortObj     // -> PPortInformation block
)
// PURPOSE
//
//  Check if host is ECP capable. (host only)
//  If host is ECP capable
// 
// ASSUMPTIONS & ASSERTIONS
//   1)Read DCR, bits 0 and 1 are NOT equal to 01. If we do read 01, set
//     the low two bits to 10.
//   2)Write bits <7:5> of ECR to 000. (change to standard Centronic mode)
//     This will clear the FIFO if ECP exists.
//   3)Read ECR, bits <1:0> are equal to 01 for checking empty FIFO.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// REUTRNS
//  1)TRUE, if success.
//  2)IE_HARDWARE, there is no ECP existing.
//
//---------------------------------------------------------------------------
{  
    unsigned     uDCR_reg;
    unsigned     uECR_reg;
    BYTE         bData;

    // Initialize the LPT Port variables
    uDCR_reg   = PortObj->ulBase + ECP_DCR_Reg;
    uECR_reg   = PortObj->ulBase + ECP_ECR_Reg;

    PortObj->wHost = HOST_NO_ECP;

    //
    // fEcpEnable can be turned FALSE in the registry 
    //
    if( FALSE == PortObj->fEcpEnable )
        return FALSE;

    // Check if DCR contains FIFO empty pattern, actually at the sense of
    // nAutoFd and nStrobe lines
    bData = READ_PORT_UCHAR((PUCHAR)uDCR_reg);
    if ((bData & ECP_FIFOBITS_MASK) == ECP_FIFO_EMPTY)
    {
        bData &= ECP_HW_DETECT;
        WRITE_PORT_UCHAR((PUCHAR)uDCR_reg, bData);
    }

    // Set ECP into standard Centronic parallel mode
    // The FIFO should be cleared if ECP exists.
    bData = (BYTE)(READ_PORT_UCHAR((PUCHAR)uECR_reg) & 0x1F | 0x20);
    WRITE_PORT_UCHAR((PUCHAR)uECR_reg, bData);

    // Check if FIFO is empty, if not empty, it's not ECP capable.
    // ECR should contain ECP_PS2_MODE+1 (0x35)
    if ((READ_PORT_UCHAR((PUCHAR)uECR_reg) & ECP_FIFOBITS_MASK) != ECP_FIFO_EMPTY)
        return (FALSE);

    PortObj->wHost = HOST_HAS_ECP;
    return TRUE;
    
}
//---------------------------------------------------------------------------
BOOL
GetECPInfo
(
    PPortInformation     PortObj     // -> PPortInformation block
)
// PURPOSE
//
//  If host is ECP capable, its FIFO, IRQ level and DMA channel info will
//  be recorded in its PortObj 
// 
// ASSUMPTIONS & ASSERTIONS
//   1)Write bits <7:5> of ECR to 111. (change to CNFG mode)
//   2)Read CNFG A, test bits <7:4> if equal to 0 or 1, if yes
//   3)Write bits <7:5> of ECR to 000. (change to STD mode to clear FIFO)
//   4)Write bits <7:5> of ECR to 110. (change to TEST mode)
//   5)Read ECR, bit 0 is equal to 1. (FIFO is empty)
//   6)Write one PWORD data to FIFO.
//   7)Read ECR, bit 0 is equal to 0. (FIFO is not empty)
//   
//  If we go here witout error, then starting to find out the depth of FIFO,
//  and IRQ level and DMA channel.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// REUTRNS
//  1)TRUE, if success.
//  2)IE_HARDWARE, there is no ECP existing.
//
//---------------------------------------------------------------------------
{  
    unsigned     uDCR_reg;
    unsigned     uECR_reg;
    unsigned     uCnfgA_reg;
    BYTE         bData;
    BYTE         bTemp;

#ifdef NSC 
    if (FindNSC())
        InitLP();
#endif    
    
    // Initialize the LPT Port variables
    uDCR_reg   = PortObj->ulBase + ECP_DCR_Reg;
    uECR_reg   = PortObj->ulBase + ECP_ECR_Reg;
    uCnfgA_reg = PortObj->ulBase + ECP_CONFG_A;

    // Here, we may have a ECP hardware. Apply method B to verify again.
    // Set to configuration mode to find out the size of FIFO (PWORD)
    WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_CONFG_MODE);

    bTemp = READ_PORT_UCHAR((PUCHAR)uCnfgA_reg);
    bData = (BYTE)(bTemp & ECP_IMPID_MASK);     //0x70
    

    //PortObj->lpFIFO.wFifoSize = 0;
    
    //
    // [a-jsouth]: need to add lpFifo info to PortInformation
    //
    if (bData == ECP_IS_8BIT)
    {
        //PortObj->lpFIFO.wFifoSize = ECP_8BIT;
    }    
    else if (bData == ECP_IS_16BIT)
    {
        //PortObj->lpFIFO.wFifoSize = ECP_16BIT;
    }    
    else if (bData == ECP_IS_32BIT)
    {
        //PortObj->lpFIFO.wFifoSize = ECP_32BIT;
    }    
    else
    {
        // presumably we have switched modes to something other than compat mode
        // so switch back.
        WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_STD_MODE);
        return (FALSE);
    }
    
    /*
    (bTemp & ECP_ISA_LEVEL) ?                   // 0x80
        (PortObj->pPortData.dwLastError = ISA_LEVEL) :           // ISA Level interrupts
        (PortObj->pPortData.dwLastError= ISA_PULSE);            // ISA Pulsed interrupts

    (bTemp & 0x04) ?
        (PortObj->lpFIFO.bInXver = FALSE) :     // 0 byte in transceiver
        (PortObj->lpFIFO.bInXver = TRUE);       // 1 byte in transceiver
    */
/*
        
    if (FindNSC())
        PortObj->lpFIFO.bInXver = FALSE;
        
    if (!GetFifoInfo(PortObj))
    {
        // presumably we have switched modes something other than compat mode
        // so switch back
        WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_STD_MODE);
        return (FALSE);
    }
  */  
    (PortObj->pPortData.dwLastError == ISA_LEVEL) ?
       WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_STD_MODE) :
       WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_PS2_MODE);

   return (TRUE);
}


⌨️ 快捷键说明

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