PCI基础
- PCI总线为高性能局部总线,主要解决外部设备之间以及外部设备与主机之间高速数据传输。在数字图形、图像等处理,以及告诉实时数据采集与处理等队数据传输速率要求高的应用中,采用PCI总线进行数据传输。
- PCI规范能够实现32位并行数据传输,工作频率为33MHz或66MHz,最大吞吐率为266MB/s。PCI-E是目前PCI系列最具代表性的一种,与并行PCI总线区别在于它采用串行传输数据模式,最大支持32个串行连接。每个传输方向上吞吐率为250MB/s,方向上总传输速率达8GB/s。
- 串行通讯比并行通讯速度快,成本低。比如PCIe64位总线,133MHz,吞吐率1GB/s,内存于台式机和服务器,比PCI宽,但是能插入PCI卡。
- PCI总线特点
- 具有隐含的中央仲裁系统。
- 具有与处理器和存储器自诩痛完全并行操作的能力。
- 提供地址和数据的奇偶校验,完全的多总线主控能力。
PCI数据结构
- 连接CPU和PCI系统对应的数据结构类型
pci_host_bridge
:
- 描述PCI总线对应的数据结构类型
pci_bus
:
- 用于指向PCI读写操作函数集的结构体类型
pci_ops
:
- 专门用于描述总线的物理插槽的结构体类型
pci_slot
:
- PCI设备结构体类型
pci_dev
:
- PCI驱动程序结构体类型
pci_driver
:
- PCI卡标识结构类型
pci_driver_i
:
PCI驱动实例
/* PCI设备驱动编程,必须包括两个核心重要的头文件 */
#include <linux/module.h>
#include <linux/pci.h>
/* 用户自定义结构体类型,作用于中断服务函数里面 */
struct pci_Card
{
resource_size_t io;
long range, flags;
void __iomem *ioaddr;
int irq;
};
static struct pci_device_id ids[] =
{
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL,
0x100f)
},
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_80332_0)
},
{0,}
};
MODULE_DEVICE_TABLE(pci, ids);
void skel_get_configs(struct pci_dev *dev)
{
uint8_t revisionId;
uint16_t vendorId, deviceId;
uint32_t classId;
pci_read_config_word(dev, PCI_VENDOR_ID, &vendorId);
printk("vendorID = %x", vendorId);
pci_read_config_word(dev, PCI_DEVICE_ID, &deviceId);
printk("deviceID = %x", deviceId);
pci_read_config_byte(dev, PCI_REVISION_ID, &revisionId);
printk("revisionID = %x",revisionId);
pci_read_config_dword(dev, PCI_CLASS_REVISION, &classId);
printk("classID = %x",classId);
}
static irqreturn_t pci_Mcard_interrupt(int irq, void *dev_id)
{
struct pci_Card *pci_Mcard = (struct pci_Card *)dev_id;
printk("irq = %d, pci_Mcard_irq = %d\n", irq, pci_Mcard->irq);
return IRQ_HANDLED;
}
static int probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval = 0;
struct pci_Card *pci_Mcard;
printk("probe func\n");
/* 设备使能 */
if(pci_enable_device(dev)) {
printk (KERN_ERR "IO Error.\n");
return -EIO;
}
pci_Mcard = kmalloc(sizeof(struct pci_Card),GFP_KERNEL);
if(!pci_Mcard) {
printk("In %s,kmalloc err!",__func__);
return -ENOMEM;
}
/* 设备中断号 */
pci_Mcard->irq = dev->irq;
if(pci_Mcard->irq < 0) {
printk("IRQ is %d, it's invalid!\n",pci_Mcard->irq);
goto out_pci_Mcard;
}
/*获取io内存相关信息*/
pci_Mcard->io = pci_resource_start(dev, 0);
pci_Mcard->range = pci_resource_end(dev, 0) - pci_Mcard->io + 1;
pci_Mcard->flags = pci_resource_flags(dev,0);
printk("start %llx %lx %lx\n",pci_Mcard->io, pci_Mcard->range, pci_Mcard->flags);
printk("PCI base addr 0 is io%s.\n",(pci_Mcard->flags & IORESOURCE_MEM)? "mem":"port");
/*防止地址访问冲突,所以这里先申请*/
retval = pci_request_regions(dev,"pci_module");
if(retval) {
printk("PCI request regions err!\n");
goto out_pci_Mcard;
}
/*再进行映射*/
pci_Mcard->ioaddr = pci_ioremap_bar(dev, 0);
if(!pci_Mcard->ioaddr) {
printk("ioremap err!\n");
retval = -ENOMEM;
goto out_regions;
}
/*申请中断IRQ并设定中断服务子函数*/
retval = request_irq(pci_Mcard->irq, pci_Mcard_interrupt, IRQF_SHARED, "pci_module", pci_Mcard);
if(retval) {
printk (KERN_ERR "Can't get assigned IRQ %d.\n",pci_Mcard->irq);
goto out_iounmap;
}
pci_set_drvdata(dev, pci_Mcard);
skel_get_configs(dev);
return 0;
out_iounmap:
iounmap(pci_Mcard->ioaddr);
out_regions:
pci_release_regions(dev);
out_pci_Mcard:
kfree(pci_Mcard);
return retval;
}
/* 移除PCI设备 */
static void remove(struct pci_dev *dev)
{
struct pci_Card *pci_Mcard = pci_get_drvdata(dev);
free_irq (pci_Mcard->irq, pci_Mcard);
iounmap(pci_Mcard->ioaddr);
pci_release_regions(dev);
kfree(pci_Mcard);
pci_disable_device(dev);
printk("remove pci device ok\n");
}
/* 结构体成员变量填充 */
static struct pci_driver pci_driver =
{
.name = "pci_module",
.id_table = ids,
.probe = probe,
.remove = remove,
};
/* 模块入口函数 */
static int __init pci_module_init(void)
{
printk("PCI module entry function\n");
return pci_register_driver(&pci_driver);
}
/* 模块退出函数 */
static void __exit pci_module_exit(void)
{
printk("PCI module exit function.\n");
// PCI驱动被卸载时,需要调用pci_unregister_driver
pci_unregister_driver(&pci_driver);
}
MODULE_LICENSE("GPL");
module_init(pci_module_init);
module_exit(pci_module_exit);
标签:20,irq,dev,pci,printk,源码,Mcard,PCI
From: https://blog.csdn.net/H520xcodenodev/article/details/141038824