一、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 short vendor;//PCI厂商ID
unsigned short device;//PCI设备ID
unsigned short subsystem_vendor;//子系统厂商ID
unsigned short subsystem_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_t fw_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_driver driver;
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);
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 short vendor;//PCI厂商ID
unsigned short device;//PCI设备ID
unsigned short subsystem_vendor;//子系统厂商ID
unsigned short subsystem_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_t fw_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_driver driver;
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);