SPCI编程需要装什么库?怎么调用?

使用Cbuilder编程连接频谱仪LAN,可以仅使用SPCI吗?怎么调用?谢谢!

http://download.csdn.net/detail/lulu_vicky/5243851

PCI 驱动编程步骤

  1. 复制~Tornado\target\h\drv\pci目录下pciAutoConfigLib.h, pciConfigLib.h等PCI头文件文件

和~Tornado\target\src\drv\pci目录下pciAutoConfigLib.c, pciConfigLib.c等PCI文件到BSP目录下。

  1. 根据实际的PCI硬件定义改写或重写这些PCI文件。

  2. 改写BSP配置文件

a. 在BSP 文件config.h中加入语句 #define&nbspINCLUDE_PCI (添加PCI模块)。
b. 在BSP 文件sysLib.c中加入语句 #include "pci/pciConfigLib.c"(主要PCI初始化函数在这个文件中)。
c. 在BSP 文件sysLib.c中加入语句 IMPORT void sysOutLong(); (导入PCI需要的一些基本函数)。
IMPORT char sysInByte();
IMPORT char sysOutByte();

PCI设备上有三种地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。CPU可以访问PCI设备上的所有地址空间,其中I/O空间和存储空间提供给设备驱动程序使用,而配置空间则由Linux内核中的PCI初始化代码使用。内核在启动时负责对所有PCI设备进行初始化,配置好所有的PCI设备,包括中断号以及I/O基址,并在文件/proc/pci中列出所有找到的PCI设备,以及这些设备的参数和属性。

Linux驱动程序通常使用结构(struct)来表示一种设备,而结构体中的变量则代表某一具体设备,该变量存放了与该设备相关的所有信息。好的驱动程序都应该能驱动多个同种设备,每个设备之间用次设备号进行区分,如果采用结构数据来代表所有能由该驱动程序驱动的设备,那么就可以简单地使用数组下标来表示次设备号。

在PCI驱动程序中,下面几个关键数据结构起着非常核心的作用:
1)pci_driver:
1) 这个数据结构在文件include/linux/pci.h里,这是Linux内核版本2.4之后为新型的PCI设备驱动程序所添加的,其中最主要的是用于识别设备的id_table结构,以及用于检测设备的函数probe()和卸载设备的函数remove() :
struct pci_driver {
struct list_head node;
char name;
const struct pci_device_id *id_table;
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
void (*remove) (struct pci_dev *dev);
int (*save_state) (struct pci_dev *dev, u32 state);
int (*suspend)(struct pci_dev *dev, u32 state);
int (*resume) (struct pci_dev *dev);
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable);
};
其中name 是驱动程序名称;id_table指向一个与驱动程序相关的设备ID表的指针。大多数驱动程序应当用MODULE_DEVICE_TABLE(pci,…)将该设备ID表导出。在调用prob( )时设成NULL 以让系统检测到所有的pci设备。
代码中是这样定义的:MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
probe 指向设备检测函数probe( ) 的指针。该函数将在pci设备ID与设备ID表匹配且还没有被其它驱动程序处理时(一般在对已存在的设备执行pci_register_driver或以后又有新设备插入时)被调用。调用时传入一个指向struct pci_driver结构的指针和与设备匹配的设备ID表做参数。若成功(驱动程序检测到pci设备)则返回0,否则返回一个负的错误代码。这个函数总是在上下文之间调用的,因此可以进入睡眠状态的
remove指向一个设备卸载函数remove( )的指针。该函数在pci设备被卸载时(如在注销设备驱动程序或者手动拔出该设备)被调用。同probe一样,该函数也是可以睡眠的。
2)pci_dev:
1) 这个数据结构也在文件include/linux/pci.h里,它详细描述了一个PCI设备几乎所有的
硬件信息,包括厂商ID、设备ID、各种资源等:
struct pci_dev {
struct list_head global_list; /
node in list of all PCI devices /
struct list_head bus_list; /
node in per-bus list /
struct pci_bus *bus; /
bus this device is on /
struct pci_bus *subordinate; /
bus this device bridges to */

   void              *sysdata;      /* hook for sys-specific extension */
   struct proc_dir_entry *procent;     /* device entry in /proc/bus/pci */

   unsigned int devfn;           /* encoded device & function index */
   unsigned short    vendor;
   unsigned short    device;
   unsigned short    subsystem_vendor;
   unsigned short    subsystem_device;
   unsigned int class;            /* 3 bytes: (base,sub,prog-if) */
   u8          hdr_type;      /* PCI header type (`multi' flag masked out) */
   u8          rom_base_reg;   /* which config register controls the ROM */

   struct pci_driver *driver;  /* which driver has allocated this device */
   u64        dma_mask;  /* Mask of the bits of bus address this
                                  device implements.  Normally this is
                                  0xffffffff.  You only need to change
                                  this if your device has broken DMA
                                  or supports 64-bit transfers.  */

   pci_power_t     current_state;  /* Current operating state. In ACPI-speak,
                                  this is D0-D3, D0 being fully functional,
                                  and D3 being off. */

   struct     device    dev;              /* Generic device interface */

   /* device is compatible with these IDs */
   unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
   unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];

   int          cfg_size;       /* Size of configuration space */

   /*
    * Instead of touching interrupt line and base address registers
    * directly, use the values stored here. They might be different!
    */
   unsigned int irq;

struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */

   /* These fields are used by common fixups */
   unsigned int transparent:1;     /* Transparent PCI bridge */
   unsigned int multifunction:1;/* Part of multi-function device */
   /* keep track of device state */
   unsigned int is_enabled:1;       /* pci_enable_device has been called */
   unsigned int is_busmaster:1; /* device is busmaster */
   unsigned int no_msi:1;     /* device may not use msi */

   u32        saved_config_space[16]; /* config space saved at suspend time */
   struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
   int rom_attr_enabled;             /* has display of the rom attribute been enabled? */
   struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */

};

         同加载和卸载模块相关的函数或数据结构都要在前面加上__init、__exit等

标志符,以使同普通函数区分开来。static int __init sil_init(void)
{
return pci_module_init(&sil_pci_driver);
}
驱动程式通过pci_module_init向内核注册自己(我们有时会看到pci_register_driver函数,其实他们是同一个,在内核代码中会看到,只是个简单的#define):
pci_module_init(&sil_pci_driver);
调用函数后,如果pci_device_id数组中标识的设备存在于系统中,并且该设备恰好还没有驱动程式,则该驱动程式会被安装。
注册驱动程式成功后,sil_init_one会被调用,在这个函数中,我们能通过插入一些打印输出语句看到PCI的设置地址空间和I/O地址区域的一些情况。

        pci_enable_device和pci_disable_device

在一个pci设备可以被使用之前,必须调用pci_enable_device进行激活,该函数会调用底层代码激活PCI设备上的I/O和内存,使之可用。而pci_disable_device所做的事情刚好相反,告诉系统该PCI设备不再使用,
同时,禁用相关的一些资源。