hwybird
论坛版主
论坛版主
  • 注册日期2006-11-11
  • 最后登录2010-08-31
  • 粉丝0
  • 关注0
  • 积分988分
  • 威望359点
  • 贡献值0点
  • 好评度96点
  • 原创分0分
  • 专家分0分
阅读:5107回复:3

原创,PCI板卡内存映射一揽子解决方案(源程序)

楼主#
更多 发布于:2007-09-04 22:51
很早以前就想做一个这样的程序,一直懒得动手,直到自己不得不做。不过,既然做了还是给大家贴出来,免得他人再遇到问题。目前贴的是未调试版本,仅仅编译通过,不过一来留出了调试接口,二来是在原来的一个类似文件改过来的,应该不会有太大问题。之后的几天会调试一下,调试的结果和详细的使用方法可能会在几天后贴在我的空间中http://embedchinadesign.spaces.live.com/,希望大家喜欢。另外,我的调试应该只局限于x86。

文件中的一些名字我使用了最喜欢的“xxx”看到的时候可以略过。
#include "vxworks.h"
#include "tasklib.h"
#include "syslib.h"
#include "config.h"
#include "vmlib.h"
#include "drv/pci/pciConfigLib.h"
/*使用须知:
任何人可以将该文件用于任何目的。但是如果改动了
该程序的任何部分(宏定义除外),请通过电子邮件通
知作者。地址是hwybird@gmail.com,欢迎交流。
2003.5  形成想法,可惜没有机会做
2007.8.31 有了机会
2007.9.3正式完成未调试版
*/


/*该文件通用于PCI板卡配置
板卡配置的目的就是内存映射。其实这个工作可以由
WindRiver来做。
解决的问题是:
1、每一个板卡都有不同的VID和DID,这样需要一个数组
    完成,    也就是说在循环的过程中通过数组访问实
    现多个板卡支持。
2、同类型板卡支持。同类型的板卡可能会存在多个实
    例。每一个实例都会占用资源,不同的板卡占用的
    资源是不同的,需要不同的配置。
3、每一块板卡都有不同的配置空间数量。对于每一个
    板卡来说,需要配置的内存空间是不相同的,从一
    个到多个不等,中间还有可能跳过一些配置,这就
    需要程序可以自动完成配置。
4、内存空间大小不一。不同类型的板卡所需要映射的
    内存空间都是不相同的。这时需要计算出内存地址
    的容量,这样可以进行设置。

没有解决的问题:
1、该文件并不想为其他程序提供什么方便。提供方便
    实际上无可厚非,但是可能会降低通用性。基于这
    种考虑,该程序并不为其他程序提供任何方便的接
    口。
2、用户需要对文件进行自定义,由于文件的目的是解
    决通用性的问题,所以用户需要自己定义板卡的数
    量和种类。另外用户需要对BSP进行改动。
3、每一个映射的类型都是VM_STATE_MASK_FOR_ALL和VM_STATE_FOR_PCI。
    这个问题目前不知道应如何解决。
*/

#undef xxx_DEBUG /*用于调试,平常不要定义*/
/*这里定义每一个VID和DID*/
#define xxx_VENDOR_ID 0xFFFF
#define xxx_DEV_ID 0xFFFF



#define xxxUNKNOWN 0
#define xxx_MAX_UNITS 2   /*这里以2个卡为例子*/

/*每一个板卡的资源*/
typedef struct xxxResource        /* xxx_RESOURCE */
{
    int BoardVID;
    int BoardDID;
    int unitInx;
} xxx_RESOURCE;

/*板卡资源的定义,这里以相同的板卡为例子
板卡如果相同的话unitInx逐次递增,如果不同
的话则从零开始*/

LOCAL xxx_RESOURCE xxxRes [xxx_MAX_UNITS] =
    {
    {xxx_VENDOR_ID, xxx_DEV_ID, 0},
    {xxx_VENDOR_ID, xxx_DEV_ID, 1},
     };


/*这里就是PCI初始化部分了*/
void xxxPciInit (void)
    {
    xxx_RESOURCE *pReso;
    int pciBus;
    int pciDevice;
    int pciFunc;
    int unit;
    int iCommand;
    BOOL duplicate;
    UINT32 membaseCsr;
    UINT32 r_membase;/*用于计算地址映射的空间*/

    char irq;
    int ix;
    


    for (unit = 0; unit < xxx_MAX_UNITS; unit++)
    {
        /*寻找板卡*/
        if (pciFindDevice (xxxRes[unit].BoardVID, xxxRes[unit].BoardDID,
                xxxRes[unit].unitInx, &pciBus, &pciDevice, &pciFunc) != OK)
        break;

        /* 检查是否重复配置 ,这里应该不会有问题,所以暂时去掉*/

/*        pReso     = &xxxResources [0];
        duplicate = FALSE;

        for (ix = 0; ix < xxx_MAX_UNITS; ix++, pReso++)
        {
            if ((ix != unit) && (pReso->pciBus == pciBus) &&
                (pReso->pciDevice == pciDevice) && (pReso->pciFunc == pciFunc))
            duplicate = TRUE;
        }
        if (duplicate)  continue;*/

        /* 应该是找到了*/

        pReso = &xxxRes [unit];

        /*  PCI_CFG_TYPE can be defined to PCI_CFG_NONE,PC_CFG_AUTO,or PCI_CFG_FORCE.*/
        /*  在X86下,BIOS会分配好资源的,所以不需要再配置了,嘿嘿*/
        for(ix=0; ix<6; ix++)/*总共是6个地址*/
        {
            pciConfigInLong (pciBus, pciDevice, pciFunc,
                             PCI_CFG_BASE_ADDRESS_0 + 0x04 * ix, &membaseCsr);  /*读回地址内容*/

            /*首先需要判断是内存还是端口,如果不是端口就映射*/
            if(!(membaseCsr&PCI_BAR_SPACE_IO))
            {
                /*首先,需要判断所需内存的大小
                根据PCI的规范,将内容写回就可以得到大小*/
                pciConfigOutLong (pciBus, pciDevice, pciFunc,
                                 PCI_CFG_BASE_ADDRESS_0 + 0x04 * ix, 0xffffffff);

                pciConfigInLong (pciBus, pciDevice, pciFunc,
                                 PCI_CFG_BASE_ADDRESS_0 + 0x04 * ix, &r_membase);

                r_membase &= PCI_MEMBASE_MASK; /*现在r_membase就是长度了*/

                /*再把地址写回去*/
                pciConfigOutLong (pciBus, pciDevice, pciFunc,
                                 PCI_CFG_BASE_ADDRESS_0 + 0x04 * ix, membaseCsr);


                membaseCsr   &= PCI_MEMBASE_MASK;
#ifdef xxx_DEBUG
        /*如果现在是调试阶段,则不用映射,继续下一个*/
        printf("\nmemory space is : 0x%x", membaseCsr);
        printf("\nlength is : 0x%x", r_membase);
        continue;
#endif
                /*此时就可以将内存映射过去了*/
                if (sysMmuMapAdd((void *)membaseCsr, r_membase,
                              VM_STATE_MASK_FOR_ALL,
                              VM_STATE_FOR_PCI) == ERROR)
                break;

            }
        }
    }
}


Angle1981
驱动牛犊
驱动牛犊
  • 注册日期2006-11-08
  • 最后登录2007-12-02
  • 粉丝0
  • 关注0
  • 积分90分
  • 威望10点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-09-08 08:47
楼主:您程序中的 if(!(membaseCsr&PCI_BAR_SPACE_IO))是判断该空间
不是内存,是IO吧?这个if语句我看不大明白,请指点!
另,您在程序中的0x04*ix,是偏移地址吧?
exqtr
驱动牛犊
驱动牛犊
  • 注册日期2007-06-05
  • 最后登录2008-12-13
  • 粉丝0
  • 关注0
  • 积分105分
  • 威望51点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-10-25 23:39
不错,顶.
hwybird
论坛版主
论坛版主
  • 注册日期2006-11-11
  • 最后登录2010-08-31
  • 粉丝0
  • 关注0
  • 积分988分
  • 威望359点
  • 贡献值0点
  • 好评度96点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-10-27 15:13
if(!(membaseCsr&PCI_BAR_SPACE_IO))这一句是判断非IO空间,请注意前面的叹号,嘿嘿
游客

返回顶部