www.pudn.com > 9054Src.rar > PlxChip.c


/******************************************************************************* 
 * Copyright (c) 2006 PLX Technology, Inc. 
 * 
 * PLX Technology Inc. licenses this software under specific terms and 
 * conditions.  Use of any of the software or derviatives thereof in any 
 * product without a PLX Technology chip is strictly prohibited. 
 * 
 * PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY, 
 * EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF 
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  PLX makes no guarantee 
 * or representations regarding the use of, or the results of the use of, 
 * the software and documentation in terms of correctness, accuracy, 
 * reliability, currentness, or otherwise; and you rely on the software, 
 * documentation and results solely at your own risk. 
 * 
 * IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, 
 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES 
 * OF ANY KIND.  IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM 
 * PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER. 
 * 
 ******************************************************************************/ 
 
/****************************************************************************** 
 * 
 * File Name: 
 * 
 *      PlxChip.c 
 * 
 * Description: 
 * 
 *      This file contains functions specific to a PLX Chip. 
 * 
 * Revision History: 
 * 
 *      02-01-06 : PCI SDK v4.40 
 * 
 ******************************************************************************/ 
 
 
#include "DriverDefs.h" 
#include "PciSupport.h" 
#include "PlxInterrupt.h" 
#include "SupportFunc.h" 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxChipPciInterruptEnable 
 * 
 * Description:  Enables the PLX Chip PCI Interrupt 
 * 
 *****************************************************************************/ 
BOOLEAN 
PlxChipPciInterruptEnable( 
    DEVICE_EXTENSION *pdx 
    ) 
{ 
    U32 RegInterrupt; 
 
 
    RegInterrupt = 
        PLX_REG_READ( 
            pdx, 
            PCI9054_INT_CTRL_STAT 
            ); 
 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_INT_CTRL_STAT, 
        RegInterrupt | (1 << 8) 
        ); 
 
    return TRUE; 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxChipPciInterruptDisable 
 * 
 * Description:  Disables the PLX Chip PCI Interrupt 
 * 
 *****************************************************************************/ 
BOOLEAN 
PlxChipPciInterruptDisable( 
    DEVICE_EXTENSION *pdx 
    ) 
{ 
    U32 RegInterrupt; 
 
 
    RegInterrupt = 
        PLX_REG_READ( 
            pdx, 
            PCI9054_INT_CTRL_STAT 
            ); 
 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_INT_CTRL_STAT, 
        RegInterrupt & ~(1 << 8) 
        ); 
 
    return TRUE; 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxPciBoardReset 
 * 
 * Description:  Resets a device using software reset feature of PLX chip 
 * 
 ******************************************************************************/ 
VOID 
PlxPciBoardReset( 
    DEVICE_EXTENSION *pdx 
    ) 
{ 
    U8  MU_Enabled; 
    U8  EepromPresent; 
    U32 RegValue; 
    U32 RegInterrupt; 
    U32 RegHotSwap; 
    U32 RegPowerMgmnt; 
 
 
    // Clear any PCI errors 
    PLX_PCI_REG_READ( 
        pdx, 
        CFG_COMMAND, 
        &RegValue 
        ); 
 
    if (RegValue & (0xf8 << 24)) 
    { 
        // Write value back to clear aborts 
        PLX_PCI_REG_WRITE( 
            pdx, 
            CFG_COMMAND, 
            RegValue 
            ); 
    } 
 
    // Save state of I2O Decode Enable 
    RegValue = 
        PLX_REG_READ( 
            pdx, 
            PCI9054_FIFO_CTRL_STAT 
            ); 
 
    MU_Enabled = (U8)(RegValue & (1 << 0)); 
 
    // Determine if an EEPROM is present 
    RegValue = 
        PLX_REG_READ( 
            pdx, 
            PCI9054_EEPROM_CTRL_STAT 
            ); 
 
    // Make sure S/W Reset & EEPROM reload bits are clear 
    RegValue &= ~((1 << 30) | (1 << 29)); 
 
    // Remember if EEPROM is present 
    EepromPresent = (U8)((RegValue >> 28) & (1 << 0)); 
 
    // Save interrupt line 
    PLX_PCI_REG_READ( 
        pdx, 
        CFG_INT_LINE, 
        &RegInterrupt 
        ); 
 
    // Save some registers if EEPROM present 
    if (EepromPresent) 
    { 
        PLX_PCI_REG_READ( 
            pdx, 
            PCI9054_HS_CAP_ID, 
            &RegHotSwap 
            ); 
 
        PLX_PCI_REG_READ( 
            pdx, 
            PCI9054_PM_CSR, 
            &RegPowerMgmnt 
            ); 
    } 
 
    // Issue Software Reset to hold PLX chip in reset 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_EEPROM_CTRL_STAT, 
        RegValue | (1 << 30) 
        ); 
 
    // Delay for a bit 
    Plx_sleep(100); 
 
    // Bring chip out of reset 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_EEPROM_CTRL_STAT, 
        RegValue 
        ); 
 
    // Issue EEPROM reload in case now programmed 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_EEPROM_CTRL_STAT, 
        RegValue | (1 << 29) 
        ); 
 
    // Delay for a bit 
    Plx_sleep(10); 
 
    // Clear EEPROM reload 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_EEPROM_CTRL_STAT, 
        RegValue 
        ); 
 
    // Restore I2O Decode Enable state 
    if (MU_Enabled) 
    { 
        // Save state of I2O Decode Enable 
        RegValue = 
            PLX_REG_READ( 
                pdx, 
                PCI9054_FIFO_CTRL_STAT 
                ); 
 
        PLX_REG_WRITE( 
            pdx, 
            PCI9054_FIFO_CTRL_STAT, 
            RegValue | (1 << 0) 
            ); 
    } 
 
    // Restore interrupt line 
    PLX_PCI_REG_WRITE( 
        pdx, 
        CFG_INT_LINE, 
        RegInterrupt 
        ); 
 
    // If EEPROM was present, restore registers 
    if (EepromPresent) 
    { 
        // Mask out HS bits that can be cleared 
        RegHotSwap &= ~((1 << 23) | (1 << 22) | (1 << 17)); 
 
        PLX_PCI_REG_WRITE( 
            pdx, 
            PCI9054_HS_CAP_ID, 
            RegHotSwap 
            ); 
 
        // Mask out PM bits that can be cleared 
        RegPowerMgmnt &= ~(1 << 15); 
 
        PLX_PCI_REG_READ( 
            pdx, 
            PCI9054_PM_CSR, 
            &RegPowerMgmnt 
            ); 
    } 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxChipSetInterruptNotifyFlags 
 * 
 * Description:  Sets the interrupt notification flags of a wait object 
 * 
 ******************************************************************************/ 
VOID 
PlxChipSetInterruptNotifyFlags( 
    PLX_INTR        *pPlxIntr, 
    PLX_WAIT_OBJECT *pWaitObject 
    ) 
{ 
    // Clear notify events 
    pWaitObject->NotifyOnInterrupt = INTR_TYPE_NONE; 
 
    if (pPlxIntr->IopToPciInt) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_LOCAL_1; 
 
    if (pPlxIntr->PciAbort) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_PCI_ABORT; 
 
    if (pPlxIntr->PciDoorbell) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_DOORBELL; 
 
    if (pPlxIntr->OutboundPost) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_OUTBOUND_POST; 
 
    if (pPlxIntr->PciDmaChannel0) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_DMA_0; 
 
    if (pPlxIntr->PciDmaChannel1) 
        pWaitObject->NotifyOnInterrupt |= INTR_TYPE_DMA_1; 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxChipGetSpace 
 * 
 * Description:  Returns the BAR index and remap register offset for a space 
 * 
 ******************************************************************************/ 
VOID 
PlxChipGetSpace( 
    DEVICE_EXTENSION *pdx, 
    IOP_SPACE         IopSpace, 
    U8               *pBarIndex, 
    U16              *pOffset_RegRemap 
    ) 
{ 
    U32 RegValue; 
 
 
    switch (IopSpace) 
    { 
        case IopSpace0: 
            *pOffset_RegRemap = PCI9054_SPACE0_REMAP; 
 
            // Check if BAR2/BAR3 are shifted to BAR0/BAR1 
            RegValue = 
                PLX_REG_READ( 
                    pdx, 
                    PCI9054_ENDIAN_DESC 
                    ); 
 
            if ((RegValue & 0x300) == 0x200) 
            { 
                *pBarIndex = 1; 
            } 
            else 
            { 
                *pBarIndex = 2; 
            } 
            break; 
 
        case IopSpace1: 
            *pOffset_RegRemap = PCI9054_SPACE1_REMAP; 
 
            /********************************************************************* 
             *  Note: Space 1 is a special case.  If the I2O Decode Enable bit 
             *        is set, BAR3 is moved to BAR0. 
             ********************************************************************/ 
 
            RegValue = 
                PLX_REG_READ( 
                    pdx, 
                    PCI9054_FIFO_CTRL_STAT 
                    ); 
 
            if (RegValue & (1 << 0)) 
            { 
                // I2O Decode is enbled, use BAR0 for Space 1 
                *pBarIndex = 0; 
            } 
            else 
            { 
                // Check if BAR2/BAR3 are shifted to BAR0/BAR1 
                RegValue = 
                    PLX_REG_READ( 
                        pdx, 
                        PCI9054_ENDIAN_DESC 
                        ); 
 
                if ((RegValue & 0x300) == 0x200) 
                { 
                    *pBarIndex = 2; 
                } 
                else 
                { 
                    *pBarIndex = 3; 
                } 
            } 
            break; 
 
        default: 
            *pBarIndex = (U8)-1; 
            DebugPrintf(("ERROR - Invalid Space\n")); 
            break; 
    } 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxChipPostCommonBufferProperties 
 * 
 * Description:  Post the common buffer properties to the device 
 * 
 ******************************************************************************/ 
VOID 
PlxChipPostCommonBufferProperties( 
    DEVICE_EXTENSION *pdx, 
    U32               PhysicalAddress, 
    U32               Size 
    ) 
{ 
    // Write the Physical Address 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_MAILBOX3, 
        PhysicalAddress 
        ); 
 
    // Write the Size 
    PLX_REG_WRITE( 
        pdx, 
        PCI9054_MAILBOX4, 
        Size 
        ); 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxIsPowerLevelSupported 
 * 
 * Description:  Verify that the power level is supported 
 * 
 ******************************************************************************/ 
BOOLEAN 
PlxIsPowerLevelSupported( 
    DEVICE_EXTENSION *pdx, 
    PLX_POWER_LEVEL   PowerLevel 
    ) 
{ 
    U32 RegisterValue; 
 
 
    // Check if New capabilities are enabled 
    if (PlxIsNewCapabilityEnabled( 
            pdx, 
            CAPABILITY_POWER_MANAGEMENT 
            ) == FALSE) 
    { 
        return FALSE; 
    } 
 
    // Verify that the Power State is supported 
    switch (PowerLevel) 
    { 
        case D0: 
        case D3Hot: 
            break; 
 
        case D1: 
        case D2: 
            // Get the Power Control/Status 
            PLX_PCI_REG_READ( 
                pdx, 
                PCI9054_PM_CAP_ID, 
                &RegisterValue 
                ); 
 
            if ((PowerLevel == D1) && !(RegisterValue & (1 << 25))) 
                return FALSE; 
 
            if ((PowerLevel == D2) && !(RegisterValue & (1 << 26))) 
                return FALSE; 
            break; 
 
        case D0Uninitialized:    // D0Uninitialized cannot be set by software 
        case D3Cold:             // D3Cold cannot be set by software 
        default: 
            return FALSE; 
    } 
 
    return TRUE; 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  PlxIsNewCapabilityEnabled 
 * 
 * Description:  Verifies access to the new Capabilities registers 
 * 
 ******************************************************************************/ 
BOOLEAN 
PlxIsNewCapabilityEnabled( 
    DEVICE_EXTENSION *pdx, 
    U8                CapabilityToVerify 
    ) 
{ 
    U32 RegisterValue; 
    U32 RegisterPmCapability; 
    U32 RegisterHsCapability; 
    U32 RegisterVpdCapability; 
 
 
    // Check if New capabilities are enabled 
    PLX_PCI_REG_READ( 
        pdx, 
        PCI9054_COMMAND, 
        &RegisterValue 
        ); 
 
    if ((RegisterValue & (1 << 20)) == 0) 
        return FALSE; 
 
    // Get capabilities pointer 
    PLX_PCI_REG_READ( 
        pdx, 
        PCI9054_CAP_PTR, 
        &RegisterValue 
        ); 
 
    // Mask non-relevant bits 
    RegisterValue = RegisterValue & 0xFF; 
 
    if (RegisterValue == 0) 
        return FALSE; 
 
    // Get PM capabilities pointer 
    PLX_PCI_REG_READ( 
        pdx, 
        PCI9054_PM_CAP_ID, 
        &RegisterPmCapability 
        ); 
 
    // Mask non-relevant bits 
    RegisterPmCapability = (RegisterPmCapability >> 8) & 0xFF; 
 
    // Get HS capabilities pointer 
    PLX_PCI_REG_READ( 
        pdx, 
        PCI9054_HS_CAP_ID, 
        &RegisterHsCapability 
        ); 
 
    // Mask non-relevant bits 
    RegisterHsCapability = (RegisterHsCapability >> 8) & 0xFF; 
 
    // Get VPD capabilities pointer 
    PLX_PCI_REG_READ( 
        pdx, 
        PCI9054_VPD_CAP_ID, 
        &RegisterVpdCapability 
        ); 
 
    // Mask non-relevant bits 
    RegisterVpdCapability = (RegisterVpdCapability >> 8) & 0xFF; 
 
    if (CapabilityToVerify & CAPABILITY_POWER_MANAGEMENT) 
    { 
        if ( (RegisterValue         != PCI9054_PM_CAP_ID) && 
             (RegisterPmCapability  != PCI9054_PM_CAP_ID) && 
             (RegisterHsCapability  != PCI9054_PM_CAP_ID) && 
             (RegisterVpdCapability != PCI9054_PM_CAP_ID) ) 
        { 
            return FALSE; 
        } 
    } 
 
    if (CapabilityToVerify & CAPABILITY_HOT_SWAP) 
    { 
        if ( (RegisterValue         != PCI9054_HS_CAP_ID) && 
             (RegisterPmCapability  != PCI9054_HS_CAP_ID) && 
             (RegisterHsCapability  != PCI9054_HS_CAP_ID) && 
             (RegisterVpdCapability != PCI9054_HS_CAP_ID) ) 
        { 
            return FALSE; 
        } 
    } 
 
    if (CapabilityToVerify & CAPABILITY_VPD) 
    { 
        if ( (RegisterValue         != PCI9054_VPD_CAP_ID) && 
             (RegisterPmCapability  != PCI9054_VPD_CAP_ID) && 
             (RegisterHsCapability  != PCI9054_VPD_CAP_ID) && 
             (RegisterVpdCapability != PCI9054_VPD_CAP_ID) ) 
        { 
            return FALSE; 
        } 
    } 
 
    return TRUE; 
}