简体   繁体   English

Linux驱动程序开发:PCI和PCIe驱动程序之间的区别?

[英]Linux driver development: Difference between PCI and PCIe driver?

I'm programming a PCI driver for Linux 2.6.36. 我正在为Linux 2.6.36编写PCI驱动程序。

Here is my code. 这是我的代码。 My question is, do I have to do some modifications if I want to use this driver for a PCIe device? 我的问题是,如果我想将此驱动程序用于PCIe设备,是否需要进行一些修改?

#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm-generic/signal.h>
#undef debug


// ATTENTION copied from /uboot_for_mpc/arch/powerpc/include/asm/signal.h
// Maybe it don't work with that
//____________________________________________________________
#define SA_INTERRUPT    0x20000000 /* dummy -- ignored */
#define SA_SHIRQ        0x04000000
//____________________________________________________________

#define pci_module_init pci_register_driver // function is obsoleted

// Hardware specific part
#define MY_VENDOR_ID 0x5333
#define MY_DEVICE_ID 0x8e40
#define MAJOR_NR     240
#define DRIVER_NAME  "PCI-Driver"

static unsigned long ioport=0L, iolen=0L, memstart=0L, memlen=0L,flag0,flag1,flag2,temp=0L;

// private_data
struct _instance_data {

    int counter; // just as a example (5-27)

    // other instance specific data
};

// Interrupt Service Routine
static irqreturn_t pci_isr( int irq, void *dev_id, struct pt_regs *regs )
{
    return IRQ_HANDLED;
}


// Check if this driver is for the new device
static int device_init(struct pci_dev *dev,
        const struct pci_device_id *id)
{
    int err=0;  // temp variable

    #ifdef debug

    flag0=pci_resource_flags(dev, 0 );
    flag1=pci_resource_flags(dev, 1 );
    flag2=pci_resource_flags(dev, 2 );
    printk("DEBUG: FLAGS0 = %u\n",flag0);
    printk("DEBUG: FLAGS1 = %u\n",flag1);
    printk("DEBUG: FLAGS2 = %u\n",flag2);

    /*
     * The following sequence checks if the resource is in the
     * IO / Storage / Interrupt / DMA address space
     * and prints the result in the dmesg log
     */
    if(pci_resource_flags(dev,0) & IORESOURCE_IO)
    {
        // Ressource is in the IO address space
        printk("DEBUG: IORESOURCE_IO\n");
    }
    else if (pci_resource_flags(dev,0) & IORESOURCE_MEM)
    {
        // Resource is in the Storage address space
        printk("DEBUG: IORESOURCE_MEM\n");
    }
    else if (pci_resource_flags(dev,0) & IORESOURCE_IRQ)
    {
        // Resource is in the IRQ address space
        printk("DEBUG: IORESOURCE_IRQ\n");
    }
    else if (pci_resource_flags(dev,0) & IORESOURCE_DMA)
    {
        // Resource is in the DMA address space
        printk("DEBUG: IORESOURCE_DMA\n");
    }
    else
    {
        printk("DEBUG: NOTHING\n");
    }

    #endif /* debug */

    // allocate memory_region
    memstart = pci_resource_start( dev, 0 );
    memlen = pci_resource_len( dev, 0 );
    if( request_mem_region( memstart, memlen, dev->dev.kobj.name )==NULL ) {
        printk(KERN_ERR "Memory address conflict for device \"%s\"\n",
                dev->dev.kobj.name);
        return -EIO;
    }
    // allocate a interrupt
    if(request_irq(dev->irq,pci_isr,SA_INTERRUPT|SA_SHIRQ,
            "pci_drv",dev)) {
        printk( KERN_ERR "pci_drv: IRQ %d not free.\n", dev->irq );
    }
    else
    {
        err=pci_enable_device( dev );
        if(err==0)      // enable device successful
        {
            return 0;
        }
        else        // enable device not successful
        {
            return err;
        }

    }
    // cleanup_mem
    release_mem_region( memstart, memlen );
    return -EIO;
}
// Function for deinitialization of the device
static void device_deinit( struct pci_dev *pdev )
{
    free_irq( pdev->irq, pdev );
    if( memstart )
        release_mem_region( memstart, memlen );
}

static struct file_operations pci_fops;

static struct pci_device_id pci_drv_tbl[] __devinitdata = {
    {       MY_VENDOR_ID,           // manufacturer identifier
        MY_DEVICE_ID,           // device identifier
        PCI_ANY_ID,             // subsystem manufacturer identifier
        PCI_ANY_ID,             // subsystem device identifier
        0,                      // device class
        0,                      // mask for device class
        0 },                    // driver specific data
        { 0, }
};

static int driver_open( struct inode *geraetedatei, struct file *instance )
{
    struct _instance_data *iptr;

    iptr = (struct _instance_data *)kmalloc(sizeof(struct _instance_data),
            GFP_KERNEL);
    if( iptr==0 ) {
        printk("not enough kernel mem\n");
        return -ENOMEM;
    }
    /* replace the following line with your instructions  */
    iptr->counter= strlen("Hello World\n")+1;    // just as a example (5-27)

    instance->private_data = (void *)iptr;
    return 0;
}

static void driver_close( struct file *instance )
{
    if( instance->private_data )
        kfree( instance->private_data );
}


static struct pci_driver pci_drv = {
    .name= "pci_drv",
            .id_table= pci_drv_tbl,
            .probe= device_init,
            .remove= device_deinit,
};

static int __init pci_drv_init(void)
{    // register the driver by the OS
    if(register_chrdev(MAJOR_NR, DRIVER_NAME, &pci_fops)==0) {
        if(pci_module_init(&pci_drv) == 0 ) // register by the subsystem
            return 0;
        unregister_chrdev(MAJOR_NR,DRIVER_NAME); // unregister if no subsystem support
    }
    return -EIO;
}

static void __exit pci_drv_exit(void)
{
    pci_unregister_driver( &pci_drv );
    unregister_chrdev(MAJOR_NR,DRIVER_NAME);
}

module_init(pci_drv_init);
module_exit(pci_drv_exit);

MODULE_LICENSE("GPL");

As far as I remember, for the device driver I've written, there's no difference between the PCI devices and the PCIe devices. 据我所知,对于我编写的设备驱动程序,PCI设备和PCIe设备之间没有区别。 My device driver uses the same kind of calls as yours: chrdev , pci_resource , irq , and mem_region . 我的设备驱动程序使用与您相同类型的调用: chrdevpci_resourceirqmem_region

From a software standpoint, PCI and PCI Express devices are essentially the same. 从软件的角度来看,PCI和PCI Express设备基本相同。 PCIe devices had the same configuration space, BARs, and (usually) support the same PCI INTx interrupts. PCIe设备具有相同的配置空间BAR,并且(通常)支持相同的PCI INTx中断。

Example #1: Windows XP has no special knowledge of PCIe, but runs fine on PCIe systems. 示例#1:Windows XP没有PCIe的特殊知识,但在PCIe系统上运行良好。

Example #2: My company offers both PCI and PCIe versions of a peripheral board, and they use the same Windows/Linux driver package. 示例#2:我的公司提供外围板的PCI和PCIe版本,并且它们使用相同的Windows / Linux驱动程序包。 The driver does not "know" the difference between the two boards. 司机不“知道”两块板之间的区别。

However: PCIe devices frequently take advantage of "advanced" features, like MSI , Hotplugging, extended configuration space, etc. Many of these feature existed on legacy PCI, but were unused. 但是:PCIe设备经常利用“高级”功能,如MSI ,热插拔,扩展配置空间等。传统PCI中存在许多这些功能,但尚未使用。 If this is a device you are designing, it is up to you whether or not you implement these advanced features. 如果这是您正在设计的设备,则无论您是否实施这些高级功能,都由您决定。

PCIe is an advanced version with more speed and capabilities. PCIe是一种具有更高速度和功能的高级版本。 The basic capabilities remains same for all standards. 所有标准的基本功能都保持不变。 The driver registration and providing the handlers is one and the same because all PCI drivers register to the same Linux PCI subsystem. 驱动程序注册和提供处理程序是一样的,因为所有PCI驱动程序都注册到同一个Linux PCI子系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM