PCI驱动
一、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);
總結
- 上一篇: ce变速注入dll失败_调用CE变速DL
- 下一篇: Klog开发笔记——分页插件 Kamin