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

📄 plx9054.c

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

/* Plx9054.c: Plx9054 PCI桥片驱动源文件*/
/* author: Wang.qi Jilin Univ. 2004512025*/

/*
PLX9054驱动程序从功能上可划分为以下模块:
初始化模块、PCI配置寄存器读写模块、本地寄存器读写模块、
本地空间读写模块、读写模块、控制与配置模块、DMA模块、
中断处理模块及测试维护模块。

各模块调用关系图

                                                  配置和
                                                  控制模块

PLX9054 PCI 配                    PLX9054 本
置寄存器                       地寄存器
读写模块                       读写模块


PLX9054本地空间读写模块                       DMA模块

*/
/*
modification history
------------------
2006-09-17
*/

#ifdef __cplusplus
extern "C" {
#endif

/* includes (header file) 头包含文件 */
#include "vxWorks.h"
#include "vme.h"
#include "memLib.h"
#include "sysLib.h"
#include "string.h"
#include "intLib.h"
#include "config.h"
#include "logLib.h"
#include "taskLib.h"
#include "vxLib.h"
#include "errnoLib.h"
#include "dosFsLib.h"
#include "stdio.h"
#include "cacheLib.h"
#include "private/vmLibP.h"
#include "arch/i86/pentiumLib.h"

#include "drv/pci/pciConfigLib.h"
#include "drv/pci/pciIntLib.h"

#include "plx9054.h"

/* define 宏定义 */

/* global */
PLX9054_DRVCTRL * pPlxDrvCtrl = NULL;  /* 指向设备驱动结构体,驱动里通过这个指针操作设备*/

static PLX9054_DRVCTRL plxDrvCtrl;
static PLX9054_DEVICE plxDevCtrl[PLX9054_MAX_DEV];
/* local */
LOCAL PLX9054_BOARD_RESOURCES plx9054Brds [] =
    {
	{0, PLX_9054_VENDORID, PLX_9054_DEVICEID, 0},
    };

LOCAL PLX9054_PCI_RESOURCES plx9054PciResrcs [] = /*默认分配给PLX 的PCI资源*/
    {
    {PLX9054_MEM_ADR0, PLX9054_IO_ADR0, PLX9054_INT_LVL0, PLX9054_INT_VEC0,
     PCI_CFG_TYPE, 0, 0, 0},
    {PLX9054_MEM_ADR1, PLX9054_IO_ADR1, PLX9054_INT_LVL1, PLX9054_INT_VEC1,
     PCI_CFG_TYPE, 0, 0, 0},
    {PLX9054_MEM_ADR2, PLX9054_IO_ADR2, PLX9054_INT_LVL2, PLX9054_INT_VEC2,
     PCI_CFG_TYPE, 0, 0, 0},
    {PLX9054_MEM_ADR3, PLX9054_IO_ADR3, PLX9054_INT_LVL3, PLX9054_INT_VEC3,
     PCI_CFG_TYPE, 0, 0, 0}
    };
    
static char line[256];

/* import */
IMPORT STATUS sysMmuMapAdd (void *, UINT, UINT, UINT);
IMPORT void	sysWait(void);
#ifdef BOOT_COM_PRINT
IMPORT void com1BootPrint(char * buf);
#endif
IMPORT STATUS pciIntConnect();
IMPORT STATUS 	rebootHookAdd (FUNCPTR rebootHook);

/* function declarations*/
#if 0
STATUS PLX9054_GetSpaceInfo(int index, PLX9054_SPACE_INDEX spaceIndex, PLX9054_SPACE_DESC * pPlxSpace);
STATUS PLX9054_GetAllSpaceInfo(int index);
STATUS PLX9054_Local_Reg_Read( int index, int offset, UINT32 * pData);
STATUS PLX9054_Local_Reg_Write( int index, int offset, UINT32  data);
STATUS PLX9054_Pci_Reg_Read( int index, int offset, UINT32 * pData, DATA_WIDTH_MODE dataWidth);
STATUS PLX9054_Pci_Reg_Write( int index, int offset, UINT32 data, DATA_WIDTH_MODE dataWidth);
void PLX9054_IntEnable (int index);
void PLX9054_IntDisable (int index);
STATUS PLX9054_ReadByte (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, char * pData);
STATUS PLX9054_WriteByte (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, char data);
STATUS PLX9054_ReadWord (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, short * pData);
STATUS PLX9054_WriteWord (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, short data);
STATUS PLX9054_ReadDword (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, UINT32 * pData);
STATUS PLX9054_WriteDword (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, UINT32 data);
#endif
void PLX9054_EepromSendCommand(int index, UINT32 EepromCommand, UCHAR DataLengthInBits);
void PLX9054_EepromClock(int index);
void PLX9054_Int(int index);
STATUS sysPlx9054IntEnable(int level);
STATUS sysPlx9054IntDisable(int level);

/* function */
/* 
 sysPlx9054PciInit
 在sysHwInit中调用,此时系统内核、MMU 等还未初始化
查找PLX9054扩展卡,读取PLX9054的PCI配置空间,以获取
BIOS分配给PLX9054扩展卡的资源
*/
STATUS sysPlx9054PciInit (void)
{
    UINT32 		membaseCsr;
    UINT32 		iobaseCsr;
    UINT32             sp0MemBase; /* PCI9054 本地空间0 的PCI Memory 基地址*/
    UINT32             sp1MemBase; /* PCI9054 本地空间1 的PCI Memory 基地址*/
    UINT32             sp0Range;      /* PCI9054 本地空间0 的大小*/
    UINT32             sp1Range;      /* PCI9054 本地空间1 的大小*/
    char 		irq;
    int 		pciBus;
    int 		pciDevice;
    int 		pciFunc;
    int 		ix;
    int 		unit;
    int 		found = FALSE;
    int 		plx9054Units = 0;
    char           buf[255];

    PLX9054_DRVCTRL *  pDrvCtrl = NULL;
    PLX9054_DEVICE * pDevCtrl = NULL;

    /* 为驱动结构体申请内存空间*/
    #if 0
    pDrvCtrl = (PLX9054_DRVCTRL *)malloc(sizeof(PLX9054_DRVCTRL));
    if(NULL == pDrvCtrl)
    {
        printf("Malloc return NULL File:%s, Line:%d.\n", __FILE__, __LINE__);
        return ERROR;
    }
    #endif

    pDrvCtrl = &plxDrvCtrl;

    PLX9054_SetDrvCtrl(pDrvCtrl);   /* 设置全局设备驱动结构体指针*/

    memset((void *)pDrvCtrl, 0, sizeof(PLX9054_DRVCTRL));
    /* find all plx9054 cards */
    for (unit = 0; unit < PLX9054_MAX_DEV; unit++)
    {
        for (ix=0; ix < NELEMENTS (plx9054Brds); ix++)
        {
            if (pciFindDevice (plx9054Brds [ix].vendorId, plx9054Brds [ix].deviceId,
                           		unit, &pciBus, &pciDevice, &pciFunc) == OK)
            {

                /* board detected */
                found = TRUE;
                #if 0
                /* 为设备结构体申请内存空间*/
                pDevCtrl = (PLX9054_DEVICE *)malloc(sizeof(PLX9054_DEVICE));
                if(NULL == pDevCtrl)
                {
                    printf("Malloc return NULL File:%s, Line:%d.\n", __FILE__, __LINE__);
                    /* 释放已分配的内存空间*/
                    return ERROR;
                }
                memset((void *)pDevCtrl, 0, sizeof(PLX9054_DEVICE));
                #endif
                pDevCtrl = &(plxDevCtrl[unit]);
                
                /* load up the PCI device table */
                pDevCtrl->PlxPciRsrc = plx9054PciResrcs[unit];
                pDevCtrl->PlxPciRsrc.pciBus = pciBus;
                pDevCtrl->PlxPciRsrc.pciDevice = pciDevice;
                pDevCtrl->PlxPciRsrc.pciFunc = pciFunc;
                
                pDrvCtrl->pDevice[unit] = pDevCtrl;

                plx9054Units++;   	/* number of units found */
                break;
            }
        }
    }
    
    pDrvCtrl->plxCardNum = plx9054Units;
    
    if ((found != TRUE) || (pciDevice > PCI_MAX_DEV))
    {
        #ifdef PLX_DEBUG_PRINT
        #ifdef BOOT_COM_PRINT
        com1BootPrint("No PLX Device Find\n\r");
        #endif
        #endif
        return ((int)NULL);
    }
    sprintf(buf, "Driver Find %d PLX9054 Devices.\n\r", plx9054Units);
    #ifdef BOOT_COM_PRINT
    com1BootPrint(buf);
    #endif
    
    /* Now initialize all the units we found 
    由于BIOS已经分配好资源,这里只需要读取BIOS
    分配给PLX9054的资源信息即可,无需配置*/

    for (unit = 0; unit < plx9054Units; unit++)
    {
        /* Fill in the resource entry */
        pDevCtrl = pDrvCtrl->pDevice[unit];
        if (PCI_CFG_FORCE == pDevCtrl->PlxPciRsrc.configType)
        {
            /* write the iobase, membase, and irq */

            pciConfigOutLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_1, 
                    pDevCtrl->PlxPciRsrc.iobaseCsr |
                    PCI_BASE_IO);
		 
            pciConfigOutLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_0, 
                    pDevCtrl->PlxPciRsrc.membaseCsr);

            pciConfigOutByte (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_DEV_INT_LINE, 
                    pDevCtrl->PlxPciRsrc.irq);
        }
	    
        /*
         * get memory base address and IO base address
         * Note: we read it in again, even if we just wrote it out because  
         * the device can change what we wrote
         */

        pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_1, &iobaseCsr);

        pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_0, &membaseCsr);
     
        pciConfigInByte (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_DEV_INT_LINE, &irq);

        /*
         * mask off registers. IO base needs to be masked off because bit0
         * will always be set to 1
         */

        membaseCsr   &= PCI_MEMBASE_MASK;
        iobaseCsr    &= PCI_IOBASE_MASK;

#ifdef INCLUDE_MMU_BASIC
        if (sysMmuMapAdd ((void *)(membaseCsr & PCI_DEV_MMU_MSK),
                        PCI_DEV_ADRS_SIZE,
                        VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
                        VM_STATE_MASK_CACHEABLE,
                        VM_STATE_VALID      | VM_STATE_WRITABLE |
                        VM_STATE_CACHEABLE_NOT
                        ) == ERROR)
        {
            /* for now, exit, but later break and stop where we're at 
                when we're detecting multiple units */
            return (ERROR);

        }
#else
        #warning INCLUDE_MMU_BASIC not defined
#endif /* INCLUDE_MMU_BASIC */

        /* 获取PCI9054 本地空间的PCI 基地址*/
        pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_2, &sp0MemBase);
                    
        pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                    PCI_CFG_BASE_ADDRESS_3, &sp1MemBase); 
                    
        /* 利用PCI I/O 读取PCI9054本地配置寄存器,获取本地空间的大小*/
        sp0Range = sysInLong(iobaseCsr + P9054_LAS0RR);
        sp1Range = sysInLong(iobaseCsr + P9054_LAS1RR);
        
        sp0Range = (~(sp0Range & PCI_MEMBASE_MASK)) + 1;
        sp1Range = (~(sp1Range & PCI_MEMBASE_MASK)) + 1;

        /* 将PCI9054 本地空间0、1申请的PCI Memory空间加入MMU 表中sysPhysMemDesc*/
#ifdef INCLUDE_MMU_BASIC
        if((sp0MemBase & BIT0) != BIT0) /* 是PCI Memory 空间,将其加入到MMU表中*/
        {
            sp0MemBase &= PCI_MEMBASE_MASK;
            sp0Range = ROUND_UP(sp0Range, VM_PAGE_SIZE);
            
            if (sysMmuMapAdd ((void *)(sp0MemBase & PCI_DEV_MMU_MSK),
                        sp0Range,
                        VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
                        VM_STATE_MASK_CACHEABLE,
                        VM_STATE_VALID      | VM_STATE_WRITABLE |
                        VM_STATE_CACHEABLE
                        ) == ERROR)
            {
                /* for now, exit, but later break and stop where we're at 
                when we're detecting multiple units */
                return (ERROR);

            }
        }

        if((sp1MemBase & BIT0) != BIT0) /* 是PCI Memory 空间,将其加入到MMU表中*/
        {
            sp1MemBase &= PCI_MEMBASE_MASK;
            sp1Range = ROUND_UP(sp1Range, VM_PAGE_SIZE);
            
            if (sysMmuMapAdd ((void *)(sp1MemBase & PCI_DEV_MMU_MSK),
                        sp1Range,
                        VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
                        VM_STATE_MASK_CACHEABLE,
                        VM_STATE_VALID      | VM_STATE_WRITABLE |
                        VM_STATE_CACHEABLE
                        ) == ERROR)
            {
                /* for now, exit, but later break and stop where we're at 
                when we're detecting multiple units */
                return (ERROR);

            }
        }
#else
        #warning INCLUDE_MMU_BASIC not defined
#endif /* INCLUDE_MMU_BASIC */

        /* over write the resource table with values read */

        pDevCtrl->PlxPciRsrc.membaseCsr = membaseCsr;
        pDevCtrl->PlxPciRsrc.iobaseCsr = iobaseCsr;
        pDevCtrl->PlxPciRsrc.irq = irq;
        pDevCtrl->PlxPciRsrc.irqvec = irq + EXT_INTERRUPT_BASE;

        /* enable mapped memory and IO addresses */

        pciConfigOutWord (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                        PCI_CFG_COMMAND, PCI_CMD_IO_ENABLE |
                        PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE);

        /* disable sleep mode */

        pciConfigOutWord (pDevCtrl->PlxPciRsrc.pciBus,
                    pDevCtrl->PlxPciRsrc.pciDevice,
                    pDevCtrl->PlxPciRsrc.pciFunc,
                        PCI_CFG_MODE, 
                        SLEEP_MODE_DIS);

        /* 获取PLX9054所有本地空间信息*/
        PLX9054_GetAllSpaceInfo(unit);
    }

    return (int)NULL; 
}

/******************************************************************
sysPlx9054PciStart
在系统内核初始化完毕后,启动扩展卡

需要注意sysPlx9054PciInit 与sysPlx9054PciStart 函数的区别,
两者执行时所处的运行环境不同,
一个在系统内核初始化前被调用---- sysPlx9054PciInit
一个在系统内核初始化后被调用---- sysPlx9054PciStart
*/
void sysPlx9054PciStart(void)
{
    PLX9054_DRVCTRL * pDrvCtrl;

    int index;

    pDrvCtrl = PLX9054_GetDrvCtrl( );

    for(index = 0; index < pDrvCtrl->plxCardNum; index++)
    {
        #if 0
        /* 此处用于复位CPLD 逻辑,使其状态机处于S0(idle)状态.
            规避一开始状态错误问题,也可以在VHDL中修改*/
        PLX9054_SoftReset(index);
        #endif
        PLX9054_DMA_Init(index);

        /* 挂接中断*/
        #if 1
        pciIntConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->pDevice[index]->PlxPciRsrc.irqvec), \
                                   (VOIDFUNCPTR)PLX9054_Int, index);
        #else
        intConnect(pDrvCtrl->pDevice[index]->PlxPciRsrc.irq, (FUNCPTR)PLX9054_Int, index);
        #endif
        /* 使能中断*/
        PLX9054_IntEnable(index);

        /* 使能系统中断*/
        sysPlx9054IntEnable((int)(pDrvCtrl->pDevice[index]->PlxPciRsrc.irq));

        /* 挂接热启动函数*/
        rebootHookAdd((FUNCPTR)PLX9054_SoftReset);
    }
}

/*************************************************************************
系统中断使能
*/
STATUS sysPlx9054IntEnable(int level)
{
    return (sysIntEnablePIC(level));
}

/*************************************************************************
系统中断使能
*/
STATUS sysPlx9054IntDisable(int level)
{
    return (sysIntDisablePIC(level));
}
/*
PLX9054_GetSpaceInfo
获取PLX9054本地空间信息Space0、Space1、Programe ROM Space
input
      int index: 设备索引
      int spaceIndex: 本地空间索引
      pPlxSpace: 指向本地空间信息结构体
*/
STATUS PLX9054_GetSpaceInfo(int index, PLX9054_SPACE_INDEX spaceIndex, PLX9054_SPACE_DESC * pPlxSpace)
{
    PLX9054_DRVCTRL * pDrvCtrl;

    UINT32 range, localBase, pciBase;

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

    switch(spaceIndex)
    {
        case P9054_ADDR_REG:
            sprintf(pPlxSpace->spaceName, "Pci Mem For Local Reg");
            pPlxSpace->dwPciBar = pDrvCtrl->pDevice[index]->PlxPciRsrc.membaseCsr;
            pPlxSpace->dwRange = 256;
            pPlxSpace->fIsEnable = TRUE;
            pPlxSpace->fIsMemory = TRUE;
            return OK;
            break;
            
        case P9054_ADDR_REG_IO:

⌨️ 快捷键说明

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