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驱动实例
# 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;
}
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;
}
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;
}
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_unregister_driver ( & pci_driver) ;
}
MODULE_LICENSE ( "GPL" ) ;
module_init ( pci_module_init) ;
module_exit ( pci_module_exit) ;