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

📄 plx9054.c

📁 plx9054总线在vxworks系统下的bsp开发包
💻 C
📖 第 1 页 / 共 4 页
字号:
        return ERROR;
    }

    if( (spaceIndex < P9054_ADDR_REG) || (spaceIndex >= P9054_ADDR_EPROM))
    {
        printf("SpaceIndex out of range file:%s, line:%d.\n", __FILE__, __LINE__);
        return ERROR;
    }

    if(dwOffset >= pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].dwRange)
    {
        printf("Offset out of range file:%s, line:%d.\n", __FILE__, __LINE__);
        return ERROR;
    }
    
    if (pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].fIsMemory)
    {
        dwAddr = pDrvCtrl->pDevice[index]->spaceDesc[spaceIndex].dwPciBar + dwOffset;
        *(UINT32 *)dwAddr = data;
        return OK;
    }
    else
    {/* 暂不支持I/O空间*/
        return ERROR;
    }
}

/*
PLX9054_EEPROM_Valid
判断PLX9054 的EEPROM 是否存在
*/
BOOL PLX9054_EEPROM_Valid(int index)
{
    UINT32 data;
    PLX9054_DRVCTRL * pDrvCtrl;

    pDrvCtrl = pPlxDrvCtrl;
   
    /* 输入参数判断*/
    if( (index < 0)  || (index > (pDrvCtrl->plxCardNum - 1)))
    {
        printf("Index out of range file:%s, line:%d.\n", __FILE__, __LINE__);
        return ERROR;
    }
   
    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &data);
    return((data & BIT28)==BIT28);
}



/******************************************************************************
 *
 * Function   :  PLX9054_EepromReadDword
 *
 * Description:  Read a Dword from the EEPROM at a specified offset
 *
 */
STATUS PLX9054_EepromReadDword(int index, EEPROM_TYPE EepromType, UINT32 offset, UINT32 *pValue)
{
    UCHAR   BitPos;
    UCHAR   CommandShift;
    UCHAR   CommandLength;
    UINT16  count;
    UINT32  RegisterValue;


    switch (EepromType)
    {
        case Eeprom93CS46:
            CommandShift  = 0;
            CommandLength = EE46_CMD_LEN;
            break;

        case Eeprom93CS56:
            CommandShift  = 2;
            CommandLength = EE56_CMD_LEN;
            break;

        case Eeprom93CS66:
            CommandShift  = 2;
            CommandLength = EE66_CMD_LEN;
            break;

        default:
            *pValue = (UINT32)-1;
            return ERROR;
    }

    /*Send EEPROM read command and offset to EEPROM*/
    PLX9054_EepromSendCommand(index, (EE_READ << CommandShift) | (offset / 2), CommandLength);

    /*****************************************************
     * Note: The EEPROM write ouput bit (26) is set here
     *       because it is required before EEPROM read
     *       operations on the 9054.  It does not affect
     *       behavior of non-9054 chips.
     *
     *       The EEDO Input enable bit (31) is required for
     *       some chips.  Since it is a reserved bit in older
     *       chips, there is no harm in setting it for all.
     ****************************************************/

    /* Set EEPROM write output bit*/
    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);

    /* Set EEDO Input enable for some PLX chips*/
    RegisterValue |= (1 << 31);

    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 26));

    /* Get 32-bit value from EEPROM - one bit at a time*/
    for (BitPos = 0; BitPos < 32; BitPos++)
    {
        /* Trigger the EEPROM clock*/
        PLX9054_EepromClock(index);

        /*****************************************************
         * Note: After the EEPROM clock, a delay is sometimes
         *       needed to let the data bit propagate from the
         *       EEPROM to the PLX chip.  If a sleep mechanism
         *       is used, the result is an extremely slow EEPROM
         *       access since the delay resolution is large and
         *       is required for every data bit read.
         *
         *       Rather than using the standard sleep mechanism,
         *       the code, instead, reads the PLX register
         *       multiple times.  This is harmless and provides
         *       enough delay for the EEPROM data to propagate.
         ****************************************************/

        for (count=0; count < 1; count++)
        {
            /* Get the result bit*/
            PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
        }

        /* Get bit value and shift into result*/
        if (RegisterValue & (1 << 27))
        {
            *pValue = (*pValue << 1) | 1;
        }
        else
        {
            *pValue = (*pValue << 1);
        }
    }

    /* Clear EEDO Input enable for some PLX chips*/
    RegisterValue &= ~(1 << 31);

    /* Clear Chip Select and all other EEPROM bits*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(0xF << 24));

    return OK;
}


/******************************************************************************
 Function   :  PLX9054_EepromWriteDword
 Description:  Write a value to the EEPROM at a specified offset

 author: wang.qi
 data: 2006-10-18
*/
STATUS PLX9054_EepromWriteDword(int index, EEPROM_TYPE EepromType, UINT32 offset, UINT32 value)
{
    char   i;
    char   BitPos;
    char   CommandShift;
    char   CommandLength;
    UINT16  EepromValue;
    int  Timeout;
    UINT32  RegisterValue;


    switch (EepromType)
    {
        case Eeprom93CS46:
            CommandShift  = 0;
            CommandLength = EE46_CMD_LEN;
            break;

        case Eeprom93CS56:
            CommandShift  = 2;
            CommandLength = EE56_CMD_LEN;
            break;

        case Eeprom93CS66:
            CommandShift  = 2;
            CommandLength = EE66_CMD_LEN;
            break;

        default:
            return ERROR;
    }

    /* Write EEPROM 16-bits at a time*/
    for (i=0; i<2; i++)
    {
        /* Set 16-bit value to write*/
        if (i == 0)
        {
            EepromValue = (UINT16)(value >> 16);
        }
        else
        {
            EepromValue = (UINT16)value;

            /*Update offset*/
            offset = offset + sizeof(UINT16);
        }
        printf("0ffset=0x%02x, value=0x%04x\n", offset, (UINT16)EepromValue);
        /* Send Write_Enable command to EEPROM */
        PLX9054_EepromSendCommand(index, (EE_WREN << CommandShift), CommandLength);

        /* Send EEPROM Write command and offset to EEPROM */
        PLX9054_EepromSendCommand(index,  (EE_WRITE << CommandShift) | (offset / 2), CommandLength);

        PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);

        /* Clear all EEPROM bits */
        RegisterValue &= ~(0xF << 24);

        /* Make sure EEDO Input is disabled for some PLX chips */
        RegisterValue &= ~(1 << 31);

        /* Enable EEPROM Chip Select */
        RegisterValue |= (1 << 25);

        /* Write 16-bit value to EEPROM - one bit at a time */
        for (BitPos = 15; BitPos >= 0; BitPos--)
        {
            /* Get bit value and shift into result */
            if (EepromValue & (1 << BitPos))
            {
                PLX9054_Local_Reg_Write(index, P9054_CNTRL,  RegisterValue | (1 << 26));
            }
            else
            {
                PLX9054_Local_Reg_Write(index, P9054_CNTRL,  RegisterValue);
            }

            /* Trigger the EEPROM clock */
            PLX9054_EepromClock(index);
        }

        /* Deselect Chip */
        PLX9054_Local_Reg_Write(index, P9054_CNTRL,  RegisterValue & ~(1 << 25));

        /* Re-select Chip */
        PLX9054_Local_Reg_Write(index, P9054_CNTRL,  RegisterValue | (1 << 25));

        /*****************************************************
         * Note: After the clocking in the last data bit, a
         *       delay is needed to let the EEPROM internally
         *       complete the write operation.  If a sleep
         *       mechanism is used, the result is an extremely
         *       slow EEPROM access since the delay resolution
         *       is too large.
         *
         *       Rather than using the standard sleep mechanism,
         *       the code, instead, reads the PLX register
         *       multiple times.  This is harmless and provides
         *       enough delay for the EEPROM write to complete.
         ****************************************************/

        /* A small delay is needed to let EEPROM complete*/
        Timeout = 0;
        do
        {
            PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);

            Timeout++;
        }
        while (((RegisterValue & (1 << 27)) == 0) && (Timeout < 20000));

        /* Send Write_Disable command to EEPROM */
        PLX9054_EepromSendCommand(index, EE_WDS << CommandShift, CommandLength);

        /* Clear Chip Select and all other EEPROM bits */
        PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(0xF << 24));
    }

    return OK;
}



/******************************************************************************
 *
 * Function   :  PLX9054_EepromSendCommand
 *
 * Description:  Sends a Command to the EEPROM
 *
*/
void PLX9054_EepromSendCommand(int index, UINT32 EepromCommand, UCHAR DataLengthInBits)
{
    char  BitPos;
    UINT32 RegisterValue;


    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);

    /* 清所有与EEPROM 相关的位 */
    RegisterValue &= ~(0xF << 24);

    /* Toggle EEPROM's Chip select to get it out of Shift Register Mode*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);

    /* Enable EEPROM Chip Select */
    RegisterValue |= (1 << 25);

    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);

    /* Send EEPROM command - one bit at a time*/
    for (BitPos = (char)(DataLengthInBits-1); BitPos >= 0; BitPos--)
    {
        /* Check if current bit is 0 or 1*/
        if (EepromCommand & (1 << BitPos))
        {
             PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 26));
        }
        else
        {
            PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue);
        }

        PLX9054_EepromClock(index);
    }
}




/******************************************************************************
 *
 * Function   :  PLX9054_EepromClock
 *
 * Description:  输出EEPROM 时钟信号
 *
*/
void PLX9054_EepromClock(int index)
{
    UCHAR  i;
    UINT32 RegisterValue;


    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);

    /* Set EEPROM clock High, EESK(pin165)输出高电平*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue | (1 << 24));

    /* 保持高电平一段时间Need a small delay, perform dummy register reads */
    for (i=0; i<5; i++)
    {
        PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
    }

    /* Set EEPROM clock Low, EESK(pin165)输出低电平*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, RegisterValue & ~(1 << 24));
    /* 保持低电平一段时间*/
    for (i=0; i<5; i++)
    {
        PLX9054_Local_Reg_Read(index, P9054_CNTRL, &RegisterValue);
    }
}


/*****************************************************************************
PLX9054_SoftReset
软复位PLX9054 扩展卡,并通过LReseto#引脚复位CPLD
*/
void PLX9054_SoftReset(int index)
{
    PLX9054_DRVCTRL * pDrvCtrl;
    UINT32 dwData;
    UCHAR EepromPresent;
    UINT32 RegInterrupt;

    if(0 != index)
    {
        index =0;
    }
    
    pDrvCtrl = PLX9054_GetDrvCtrl();
    
    /* 输入参数判断*/
    if( (index < 0)  || (index > (pDrvCtrl->plxCardNum - 1)))
    {
        printf("Index out of range file:%s, line:%d.\n", __FILE__, __LINE__);
        return;
    }

    /* Clear any PCI errors */
    PLX9054_Pci_Reg_Read(index, PCI_CR, &dwData, DATA_DWORD);

    if (dwData & (0xf8 << 24))
    {
        /* Write value back to clear aborts */
        PLX9054_Pci_Reg_Write(index, PCI_CR, dwData, DATA_DWORD);
    }

    /* Determine if an EEPROM is present */
    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &dwData);
  
    /* Make sure S/W Reset & EEPROM reload bits are clear */
    dwData &= ~((1 << 30) | (1 << 29));

    /* Remember if EEPROM is present */
    EepromPresent = (UCHAR)((dwData >> 28) & (1 << 0));

    /* Save interrupt line */
    PLX9054_Pci_Reg_Read(index, PCI_ILR, &RegInterrupt, DATA_BYTE);

    /* Save some registers if EEPROM present */
    #if 0
    if (EepromPresent)
    {
        PLX9054_Pci_Reg_Read(index, 
        PLX_PCI_REG_READ(
            pdx,
            PCI9054_HS_CAP_ID,
            &RegHotSwap
            );

        PLX_PCI_REG_READ(
            pdx,
            PCI9054_PM_CSR,
            &RegPowerMgmnt
            );
    }
    #endif

    PLX9054_Local_Reg_Read(index, P9054_CNTRL, &dwData);

    /* 复位*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData |(1 << 30));
    taskDelay(1);
    /* 清复位*/
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData);

    /* 重新加载EEPROM */
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData |(1 << 29));
    taskDelay(1);
    PLX9054_Local_Reg_Write(index, P9054_CNTRL, dwData);

    /* restore interrupt line */
    PLX9054_Pci_Reg_Write(index, PCI_ILR, RegInterrupt, DATA_BYTE);
}

/*************************************************************************
向DSP 写一个字节的数据
*/
void PLX9054_WriteByteToDsp(int index, UINT8 data)
{
    PLX9054_DRVCTRL * pDrvCtrl;
    
    pDrvCtrl = PLX9054_GetDrvCtrl( );

    /* 按32 位输出数据,低8 位有效*/
    *(UINT32 *)(pDrvCtrl->pDevice[index]->spaceDesc[AD_PCI_BAR3].dwPciBar) = (UINT32)data;
}

/*
PLX9054_GetDrvCtrl
获取设备驱动控制结构体指针
*/
PLX9054_DRVCTRL * PLX9054_GetDrvCtrl(void)
{
    return(pPlxDrvCtrl);
}

/*
PLX9054_SetDrvCtrl
设置设备驱动控制结构体指针
*/
void PLX9054_SetDrvCtrl(PLX9054_DRVCTRL * pDrvCtrl)
{
    pPlxDrvCtrl = pDrvCtrl;
}


#ifdef __cplusplus
}
#endif

⌨️ 快捷键说明

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