PCI驱动

来源:互联网 发布:caffe教程数据层视觉层 编辑:程序博客网 时间:2024/05/11 14:08
一、PCI总线
1、PCI桥
Host/PCI桥:用于连接CPU与PCI根总线,即“北桥芯片组”
PCI/ISA桥:用于连接PCI与旧的ISA总线,即“南桥芯片组”
PCI-to-PCI桥:用于连接PCI主总线与次总线


2、pci_bus结构体(PCI总线结构体)
定义在include/linux/pci.h中
struct pci_bus {
struct list_head node;/* 链表元素node*/
struct pci_bus*parent; /* PCI总线的父总线*/
struct list_head children;/* 子总线链表头 */
struct list_head devices;/* PCI总线上的设备链表*/
struct pci_dev*self; /* 指向应用该PCI总线*/
struct list_head slots;/* PCI总线上的插槽链表*/
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources;/* 路由到该总线上的地址空间资源链表*/


struct pci_ops*ops; /* PCI总线的访问配置空间的函数集 */
void *sysdata;/* 系统特定的数据hook for sys-specific extension */
struct proc_dir_entry *procdir;/* /proc/bus/pci对应的目录项*/


unsigned char number; /* 总线数*/
unsigned char primary; /* 总线号 */
unsigned char secondary; /* 次总线号 */
unsigned char subordinate; /* 最大总线号 */
unsigned char max_bus_speed; /* enum pci_bus_speed */
unsigned char cur_bus_speed; /* enum pci_bus_speed */


char name[48];


unsigned short  bridge_ctl;/* manage NO_ISA/FBB/et al behaviors */
pci_bus_flags_t bus_flags;/* Inherited by child busses */
struct device *bridge;
struct device dev;
struct bin_attribute*legacy_io; /* legacy I/O for this bus */
struct bin_attribute*legacy_mem; /* legacy mem */
unsigned int is_added:1;
};


3、pci_dev结构体(PCI设备结构体)
定义在include/linux/pci.h中
struct pci_dev {
struct list_head bus_list;/* node in per-bus list */
struct pci_bus*bus; /* 这个设备所在的PCI总线的pci_bus结构体 */
struct pci_bus*subordinate; /*这个设备所桥接的下级总线*/


void *sysdata;/* 系统的扩展数据*/
struct proc_dir_entry *procent;/*/proc/bus/pci对应的目录项 */
struct pci_slot*slot; /* 这个设备位于的物理插槽*/


unsigned int devfn; /* 设备的功能号 */
unsigned shortvendor;//PCI厂商ID
unsigned shortdevice;//PCI设备ID
unsigned shortsubsystem_vendor;//子系统厂商ID
unsigned shortsubsystem_device;//子系统设备ID
unsigned int class; /* PCI设备的类别*/
u8 revision;/* PCI版本 */
u8 hdr_type;/* PCI配置空间头类型 */
u8 pcie_cap;/* PCI-E capability offset */
u8 pcie_type;/* PCI-E 设备/端口 类型 */
u8 rom_base_reg;/* 配置寄存器在ROM中的位置 */
u8 pin;  /* 中断引脚 */


struct pci_driver *driver;/*对应的驱动pci_driver结构体 */
u64 dma_mask;/* 总线地址为掩码*/
struct device_dma_parameters dma_parms;


pci_power_t     current_state;  /* 当前操作状态*/
int pm_cap;
unsigned int pme_support:5; /* Bitmask of states from which PME#
  can be generated */
unsigned int pme_interrupt:1;
unsigned int d1_support:1; /* Low power state D1 is supported */
unsigned int d2_support:1; /* Low power state D2 is supported */
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
unsigned int mmio_always_on:1; /* disallow turning off io/mem
  decoding during bar sizing */
unsigned int wakeup_prepared:1;
unsigned int d3_delay; /* D3->D0 transition time in ms */


#ifdef CONFIG_PCIEASPM
struct pcie_link_state*link_state; /* ASPM link state. */
#endif
pci_channel_state_t error_state;/* current connectivity state */
struct device dev; /* 通用设备接口 */


int cfg_size;/* 配置空间大小 */


unsigned int irq;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* 该设备可能用到的资源 */
resource_size_tfw_addr[DEVICE_COUNT_RESOURCE]; /* FW-assigned addr */


/* 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_added:1;
unsigned int is_busmaster:1; /* device is busmaster */
unsigned int no_msi:1; /* device may not use msi */
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */
unsigned int msi_enabled:1;
unsigned int msix_enabled:1;
unsigned int ari_enabled:1; /* ARI forwarding */
unsigned int is_managed:1;
unsigned int is_pcie:1; /* Obsolete. Will be removed.
  Use pci_is_pcie() instead */
unsigned int    needs_freset:1; /* Dev requires fundamental reset */
unsigned int state_saved:1;
unsigned int is_physfn:1;
unsigned int is_virtfn:1;
unsigned int reset_fn:1;
unsigned int    is_hotplug_bridge:1;
unsigned int    __aer_firmware_first_valid:1;
unsigned int __aer_firmware_first:1;
pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */


u32 saved_config_space[16]; /* config space saved at suspend time */
struct hlist_head saved_cap_space;
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 */
struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
#ifdef CONFIG_PCI_MSI
struct list_head msi_list;
#endif
struct pci_vpd *vpd;
#ifdef CONFIG_PCI_IOV
union {
struct pci_sriov *sriov;/* SR-IOV capability related */
struct pci_dev *physfn;/* the PF this VF is associated with */
};
struct pci_ats*ats; /* Address Translation Service */
#endif
}


4、PCI头部寄存器定义在include/linux/pci_regs.h中


5、pci_ops结构体
是PCI总线使用的配置空间访问操作的具体实现
定义在include/linux/pci.h中
struct pci_ops {
int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
};


二、PCI设备驱动的组成
一个通过PCI总线与系统连接的设备驱动应包括PCI驱动、设备本身的驱动;
1、pci_driver结构体
定义在include/linux/pci.h中
struct pci_driver {
struct list_head node;
const char *name;
const struct pci_device_id *id_table;/* must be non-NULL for probe to be called */
int  (*probe)  (struct pci_dev *dev, const struct pci_device_id *id);/* New device inserted */
void (*remove) (struct pci_dev *dev);/* Device removed (NULL if not a hot-plug capable driver) */
int  (*suspend) (struct pci_dev *dev, pm_message_t state);/* Device suspended */
int  (*suspend_late) (struct pci_dev *dev, pm_message_t state);
int  (*resume_early) (struct pci_dev *dev);
int  (*resume) (struct pci_dev *dev);               /* Device woken up */
void (*shutdown) (struct pci_dev *dev);
struct pci_error_handlers *err_handler;
struct device_driverdriver;
struct pci_dynids dynids;
};


2、PCI驱动程序模板
static struct pci_device_id xxx_pci_tbl[] __initdate={
{
PCI_VENDOR_IO_DEMO,
PCI_DEVICE_ID_DEMO,
...
}
}
static void xxx_interrupt(int irq,coid *dev_id,strutc pt_reg *reg)
{
...
}
static int xxx_open(struct inode *indoe,struct file *file)
{
request_irq(xxx_irq,&xxx_interrupt,...);//申请呢中断
...
}
static int xxx_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
...
}
//设备文件操作接口
static struct file_operations xxx_fops={
.owner=THIS_MODULE,
.open=xxx_open,
.ioctl=xxx_ioctl
};
//probe方法
static int  xxx_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
pci_enable_device(dev);//启动pci设备
//读取PCI设备信息
iobase=pci_resource_start(dev,i);
...
pci_set_master(dev);//设置成总线DMA模式
pci_request_regions(dev);//申请io资源
//注册字符设备
cdev_init(xxx_dev,&xxx_fops);
register_chardev_region(xxx_dev_no,1..);
cdev_add(xxx_cdev);
return 0;
}
//remove函数
static void (*remove) (struct pci_dev *dev)
{
pci_release_region(dev);//释放io资源
pci_disable_device(dev);//停止PCI设备
unregister_chrdev_region(xxx_dev_no,1...);//释放设备号
cdev_del(&xxx_dev.cdev);//释放字符设备
...
}
//设备模块信息
static struct pci_driver xxx_pci_driver={
.name=xxx_module_name,
.id_table=xxx_pci_tbl,
.probe=xxx_probe,
.remove=xxx_remove
};
static int __init xxx_init_module(void)
{
//注册pci驱动
pci_register_driver(&xxx_pci_driver);
}
static int __exit xxx_exit_module(void)
{
//卸载pci驱动
pci_unregister_driver(&xxx_pci_driver);
}
//驱动加载函数
module_init(xxx_init_module);
//驱动卸载函数
module_exit(xxx_exit_module);
0 0