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

📄 plx_lib.c

📁 PCI口的驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    UINT32 u32Data)
{
    DWORD i;
    UINT32 u32ReadBack, u32EnableAccess;
    WORD wAddr, wData;
    BYTE bEnableOffset;

    if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_VPD_Write32"))
        return WD_INVALID_PARAMETER;

    if (dwOffset % 4)
    {
        ErrLog("PLX_EEPROM_VPD_Write32: Error - offset (0x%lX) is not a multiple of 4 "
            "(device handle: 0x%p)\n", dwOffset, hDev);
        return WD_INVALID_PARAMETER;
    }
    
    /* Clear EEDO Input Enable */
    EEPROM_VPD_EnableAccess(hDev, &u32EnableAccess);

    wAddr = (WORD)dwOffset;
    EEPROM_VPD_RemoveWriteProtection(hDev, wAddr, &bEnableOffset);

    EEPROM_VPD_Delay();

    /* Write desired data to PVPDATA register */
    WDC_PciWriteCfg32(hDev, PLX_VPD_DATA, u32Data);

    /* Write a destination serial EEPROM address and flag of operation, value of 1 */
    wAddr = (WORD)(wAddr | BIT15);
    WDC_PciWriteCfg16(hDev, PLX_VPD_ADDR, wAddr);

    /* Probe a flag of operation until it changes to a 0 to ensure the write completes */
    for (i = 0; i < 10; i++)
    {
        EEPROM_VPD_Delay();
        WDC_PciReadCfg16(hDev, PLX_VPD_ADDR, &wData);
        if (wData & BIT15)
            break;
    }

    EEPROM_VPD_RestoreWriteProtection((PWDC_DEVICE)hDev, bEnableOffset);

    /* Restore EEDO Input Enable */
    EEPROM_VPD_RestoreAccess(hDev, u32EnableAccess);

    PLX_EEPROM_VPD_Read32(hDev, dwOffset, &u32ReadBack);
  
    if (u32ReadBack != u32Data)
    {
        ErrLog("PLX_EEPROM_VPD_Write32: Error - Wrote 0x%08X, read back 0x%08X "
            "(device handle 0x%p)\n", u32Data, u32ReadBack);
        return WD_OPERATION_FAILED;
    }

    return WD_STATUS_SUCCESS;
}

/* Enable EEPROM access via VPD mechanism - disable EEDO Input (CNTRL[31]=0, default).
   This bit is specific to PLX 9656 and PLX 9056 chips (it is reserved on other boards) */
static DWORD EEPROM_VPD_EnableAccess(WDC_DEVICE_HANDLE hDev, UINT32 *pu32DataOld)
{
    DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
    
    PLX_ReadReg32(hDev, dwCNTRL, pu32DataOld);
    return PLX_WriteReg32(hDev, dwCNTRL, *pu32DataOld & ~BIT31);
}

/* Restore EEDO Input Enable */
static DWORD EEPROM_VPD_RestoreAccess(WDC_DEVICE_HANDLE hDev, UINT32 u32Data)
{
    return PLX_WriteReg32(hDev, ((PPLX_DEV_CTX)((((PWDC_DEVICE)hDev)->pCtx)))->dwCNTRL,
        u32Data);
}

static DWORD EEPROM_VPD_RemoveWriteProtection(WDC_DEVICE_HANDLE hDev, WORD wAddr,
    PBYTE pbDataOld)
{
    PPLX_DEV_CTX pDevCtx = (PPLX_DEV_CTX)WDC_GetDevContext(hDev);

    PLX_ReadReg8(hDev, pDevCtx->dwPROT_AREA, pbDataOld);
    
    wAddr /= 4;
    wAddr &= 0x7F;

    PLX_WriteReg8(hDev, pDevCtx->dwPROT_AREA, (BYTE)wAddr);

    *pbDataOld *= 4; /* Expand from DWORD to BYTE count */

    return WD_STATUS_SUCCESS;
}

static DWORD EEPROM_VPD_RestoreWriteProtection(WDC_DEVICE_HANDLE hDev, WORD wAddr)
{    
    PPLX_DEV_CTX pDevCtx = (PPLX_DEV_CTX)WDC_GetDevContext(hDev);
    return PLX_WriteReg8(hDev, pDevCtx->dwPROT_AREA, (BYTE)wAddr);
}

DWORD PLX_EEPROM_RT_Read16(WDC_DEVICE_HANDLE hDev, DWORD dwOffset, PWORD pwData,
    DWORD EEPROMmsb)
{
    WORD i;
    DWORD dwAddr = dwOffset >> 1;
    BOOL bit = 0;
    
    if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Read16"))
        return WD_INVALID_PARAMETER;

    *pwData = 0;

    EEPROM_RT_ChipSelect(hDev, TRUE);
    EEPROM_RT_WriteBit(hDev, 1);
    EEPROM_RT_WriteBit(hDev, 1);
    EEPROM_RT_WriteBit(hDev, 0);

    /* CS06, CS46 EEPROM - send 6bit address
     * CS56, CS66 EEPROM - send 8bit address */
    for (i = (WORD)EEPROMmsb; i; i >>= 1)
        EEPROM_RT_WriteBit(hDev, (dwAddr & i) == i);
    
    for (i = BIT15; i; i >>= 1)
    {
        EEPROM_RT_ReadBit(hDev, &bit);
        *pwData |= (bit ? i : 0);
    }

    EEPROM_RT_ChipSelect(hDev, FALSE);

    return WD_STATUS_SUCCESS;
}

DWORD PLX_EEPROM_RT_Write16(WDC_DEVICE_HANDLE hDev, DWORD dwOffset, WORD wData,
    DWORD EEPROMmsb)
{
    WORD i;
    DWORD dwAddr = dwOffset >> 1;
    WORD wReadBack;
    
    if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Write16"))
        return WD_INVALID_PARAMETER;

    EEPROM_RT_WriteEnableDisable(hDev, TRUE);

    EEPROM_RT_ChipSelect(hDev, TRUE);

    /* Send a PRWRITE instruction */
    EEPROM_RT_WriteBit(hDev, 1);
    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, 1);
    
    /* CS06, CS46 EEPROM - send 6bit address
     * CS56, CS66 EEPROM - send 8bit address */
    for (i = (WORD)EEPROMmsb; i; i >>= 1)
        EEPROM_RT_WriteBit(hDev, (dwAddr & i) == i);
    
    for (i = BIT15; i; i >>= 1)
        EEPROM_RT_WriteBit(hDev, (wData & i) == i);

    EEPROM_RT_ChipSelect(hDev, FALSE);
    
    EEPROM_RT_WriteEnableDisable(hDev, TRUE);

    PLX_EEPROM_RT_Read16(hDev, dwOffset, &wReadBack, EEPROMmsb);
    
    if (wData != wReadBack)
    {
        ErrLog("PLX_EEPROM_RT_Write16: Error - Wrote 0x%04X, read back 0x%04X "
            "(device handle 0x%p)\n", wData, wReadBack);
        return WD_OPERATION_FAILED;
    }
    
    return WD_STATUS_SUCCESS;
}

DWORD PLX_EEPROM_RT_Read32(WDC_DEVICE_HANDLE hDev, DWORD dwOffset,
    UINT32 *pu32Data, DWORD EEPROMmsb)
{
    WORD wData1, wData2;
    
    if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Read32"))
        return WD_INVALID_PARAMETER;

    if (dwOffset % 4)
    {
        ErrLog("PLX_EEPROM_RT_Read32: Error - offset (0x%lX) is not a multiple of 4 "
            "(device handle: 0x%p)\n", dwOffset, hDev);
        return WD_INVALID_PARAMETER;
    }
    
    PLX_EEPROM_RT_Read16(hDev, dwOffset, &wData1, EEPROMmsb);

    PLX_EEPROM_RT_Read16(hDev, dwOffset + 2, &wData2, EEPROMmsb);

    *pu32Data = (UINT32)((wData1 << 16) + wData2);
    
    return WD_STATUS_SUCCESS;
}

DWORD PLX_EEPROM_RT_Write32(WDC_DEVICE_HANDLE hDev, DWORD dwOffset,
    UINT32 u32Data, DWORD EEPROMmsb)
{
    WORD wData1, wData2;

    if (!IsValidDevice((PWDC_DEVICE)hDev, "PLX_EEPROM_RT_Write32"))
        return WD_INVALID_PARAMETER;

    if (dwOffset % 4)
    {
        ErrLog("PLX_EEPROM_RT_Write32: Error - offset (0x%lX) is not a multiple of 4 "
            "(device handle: 0x%p)\n", dwOffset, hDev);
        return WD_INVALID_PARAMETER;
    }

    wData1 = (WORD)(u32Data >> 16);
    wData2 = (WORD)(u32Data & 0xFFFF);

    PLX_EEPROM_RT_Write16(hDev, dwOffset, wData1, EEPROMmsb);

    PLX_EEPROM_RT_Write16(hDev, dwOffset + 2, wData2, EEPROMmsb);

    return WD_STATUS_SUCCESS;
}

static void EEPROM_RT_ChipSelect(WDC_DEVICE_HANDLE hDev, BOOL fSelect)
{
    DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
    UINT32 u32CNTRL;

    PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
    
    PLX_WriteReg32(hDev, dwCNTRL,
        fSelect ? (u32CNTRL | BIT25) : (u32CNTRL & ~BIT25) );
    
    EEPROM_RT_Delay();
}

static void EEPROM_RT_ReadBit(WDC_DEVICE_HANDLE hDev, BOOL *pBit)
{
    DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
    UINT32 u32CNTRL;

    PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);

    /* clock */
    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);

    EEPROM_RT_Delay();

    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL | BIT24);

    EEPROM_RT_Delay();

    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);

    EEPROM_RT_Delay();

    /* data */
    PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
    *pBit = (u32CNTRL & BIT27) == BIT27;
}

static void EEPROM_RT_WriteBit(WDC_DEVICE_HANDLE hDev, BOOL bit)
{
    DWORD dwCNTRL = ((PPLX_DEV_CTX)(((PWDC_DEVICE)hDev)->pCtx))->dwCNTRL;
    UINT32 u32CNTRL;
    
    PLX_ReadReg32(hDev, dwCNTRL, &u32CNTRL);
    
    if (bit) /* data */
        u32CNTRL |= BIT26;
    else
        u32CNTRL &= ~BIT26;

    /* clock */
    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);

    EEPROM_RT_Delay();

    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL | BIT24);

    EEPROM_RT_Delay();

    PLX_WriteReg32(hDev, dwCNTRL, u32CNTRL & ~BIT24);

    EEPROM_RT_Delay();
}

static void EEPROM_RT_WriteEnableDisable(WDC_DEVICE_HANDLE hDev, BOOL fEnable)
{
    EEPROM_RT_ChipSelect(hDev, TRUE);

    /* Send a WEN instruction */
    EEPROM_RT_WriteBit(hDev, 1);
    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, fEnable ? 1 : 0);
    EEPROM_RT_WriteBit(hDev, fEnable ? 1 : 0);

    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, 0);
    EEPROM_RT_WriteBit(hDev, 0);

    EEPROM_RT_ChipSelect(hDev, FALSE);
}

/* -----------------------------------------------
    Reset of PLX board
   ----------------------------------------------- */
/* Definition of abort bits in commad (CMD) configuration register */
#define PLX_M_CR_ABORT_BITS (\
    BIT24   /* Detected Master Data Parity Error */ \
    | BIT27 /* Signaled Target Abort */ \
    | BIT28 /* Received Target Abort */ \
    | BIT29 /* Received Master Abort */ \
    | BIT30 /* Signaled System Error */ \
    | BIT31 /* Detected Parity Error on PCI bus */ \
    )

/* Software board reset for master devices (9054, 9056, 9080, 9656) */
void PLX_SoftResetMaster(WDC_DEVICE_HANDLE hDev)
{
    BOOL fMUEnabled, fEEPROMPresent;
    WORD wCMD = 0;
    UINT32 u32QSR = 0;
    UINT32 u32CNTRL = 0;
    UINT32 u32INTLN = 0;
    UINT32 u32MBOX0 = 0, u32MBOX1 = 0;
    UINT32 u32HS_CNTL = 0;
    UINT32 u32PMCSR = 0;
    
    /* Clear any PCI errors */
    WDC_PciReadCfg16(hDev, PCI_CR, &wCMD);
    if (wCMD & PLX_M_CR_ABORT_BITS)
    {
        /* Write value back to clear aborts */
        WDC_PciWriteCfg16(hDev, PCI_CR, wCMD);
    }

    /* Save state of I2O Decode Enable */
    PLX_ReadReg32(hDev, PLX_M_QSR, &u32QSR);
    fMUEnabled = u32QSR & BIT0 ? TRUE : FALSE;

    /* Make sure S/W Reset & EEPROM reload bits are clear */
    PLX_ReadReg32(hDev, PLX_M_CNTRL, &u32CNTRL);
    u32CNTRL &= ~(BIT30 | BIT29);

    /* Determine if an EEPROM is present */
    fEEPROMPresent = PLX_EEPROMIsPresent(hDev);

    /* Save some registers if EEPROM present */
    if (fEEPROMPresent)
    {
        /* Run-time registers */
        PLX_ReadReg32(hDev, PLX_M_MBOX0, &u32MBOX0);
        PLX_ReadReg32(hDev, PLX_M_MBOX1, &u32MBOX1);

        /* PCI configuration registers */       
        WDC_PciReadCfg32(hDev, PCI_ILR, &u32INTLN);
        WDC_PciReadCfg32(hDev, PLX_HS_CAPID, &u32HS_CNTL);
        WDC_PciReadCfg32(hDev, PLX_PMCSR, &u32PMCSR);
    }

    /* Issue Software Reset to hold PLX chip in reset */
    PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL | BIT30);

    /* Bring chip out of reset */
    PLX_SOFT_RESET_DELAY();
    PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL);

    /* Issue EEPROM reload in case now programmed */
    PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL | BIT29);

    /* Clear EEPROM reload */
    PLX_SOFT_RESET_DELAY();
    PLX_WriteReg32(hDev, PLX_M_CNTRL, u32CNTRL);

    /* Restore I2O Decode Enable state */
    if (fMUEnabled)
    {
        PLX_ReadReg32(hDev, PLX_M_QSR, &u32QSR);
        PLX_WriteReg32(hDev, PLX_M_QSR, u32QSR | BIT0);
    }

    /* If EEPROM was present, restore registers */
    if (fEEPROMPresent)
    {
        /* Run-time registers */
        PLX_WriteReg32(hDev, PLX_M_MBOX0, u32MBOX0);
        PLX_WriteReg32(hDev, PLX_M_MBOX1, u32MBOX1);

        /* PCI configuration registers */
        WDC_PciReadCfg32(hDev, PCI_ILR, &u32INTLN);

        /* Mask out HS bits that can be cleared */
        u32HS_CNTL &= ~(BIT23 | BIT22 | BIT17);
        WDC_PciWriteCfg32(hDev, PLX_HS_CAPID, u32HS_CNTL);

        /* Mask out PM bits that can be cleared */
        u32PMCSR &= ~BIT15;
        WDC_PciWriteCfg32(hDev, PLX_PMCSR, u32PMCSR);
    }
}

/* -----------------------------------------------
    Debugging and error handling
   ----------------------------------------------- */
static void ErrLog(const CHAR *sFormat, ...)
{
    va_list argp;
    va_start(argp, sFormat);
    vsnprintf(gsPLX_LastErr, sizeof(gsPLX_LastErr) - 1, sFormat, argp);
#if defined(DEBUG)
    WDC_Err("PLX lib: %s", gsPLX_LastErr);
#endif
    va_end(argp);
}

static void TraceLog(const CHAR *sFormat, ...)
{
#if defined(DEBUG)
    CHAR sMsg[256];
    va_list argp;
    va_start(argp, sFormat);
    vsnprintf(sMsg, sizeof(sMsg) - 1, sFormat, argp);
    WDC_Trace("PLX lib: %s", sMsg);
    va_end(argp);
#endif
}

const char *PLX_GetLastErr(void)
{
    return gsPLX_LastErr;
}

⌨️ 快捷键说明

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