2012-08-28 37 views
9

Tôi đang lập trình trình điều khiển PCI cho Linux 2.6.36.Phát triển trình điều khiển Linux: Sự khác biệt giữa trình điều khiển PCI và PCIe?

Đây là mã của tôi. Câu hỏi của tôi là, tôi có phải làm một số sửa đổi nếu tôi muốn sử dụng trình điều khiển này cho một thiết bị 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"); 
+0

Nó sẽ không thích hợp để gọi 'release_mem_region' sau khi gọi' pci_enable_device'? Khi nó đứng, vùng nhớ sẽ vẫn được cấp phát ngay cả khi cuộc gọi này thất bại. Có lẽ đó chỉ là hành vi lành mạnh để sử dụng 'check_mem_region'? – HonkyTonk

Trả lời

2

Từ quan điểm phần mềm, các thiết bị PCI và PCI Express cơ bản giống nhau. Các thiết bị PCIe có cùng một không gian cấu hình, các BAR và (thường) hỗ trợ các ngắt PCI INTx giống nhau.

Ví dụ # 1: Windows XP không có kiến ​​thức đặc biệt về PCIe, nhưng hoạt động tốt trên các hệ thống PCIe.

Ví dụ # 2: Công ty của tôi cung cấp cả phiên bản PCI và PCIe của bảng ngoại vi và họ sử dụng cùng gói trình điều khiển Windows/Linux. Người lái xe không "biết" sự khác biệt giữa hai bảng.

Tuy nhiên: Thiết bị PCIe thường tận dụng các tính năng "nâng cao", như MSI, Hotplugging, không gian cấu hình mở rộng, vv. Nhiều tính năng này tồn tại trên PCI cũ nhưng không được sử dụng. Nếu đây là thiết bị bạn đang thiết kế, bạn có nên thực hiện các tính năng nâng cao này hay không.

+0

Đừng quên rằng các thiết bị di sản PCIe (thiết bị PCIe hoạt động như chúng là thiết bị PCI vì lý do tương thích) thực hiện một số tính năng không còn được đề xuất nữa. Các tính năng chính đến với tâm trí là I/O đọc và viết, mà đã được tìm thấy là terribly không hiệu quả trong thực tế. – Joshua

3

Theo tôi nhớ, đối với trình điều khiển thiết bị tôi đã viết, không có sự khác biệt giữa thiết bị PCI và thiết bị PCIe. Trình điều khiển thiết bị của tôi sử dụng cùng một loại cuộc gọi như của bạn: chrdev, pci_resource, irqmem_region.

+0

Cảm ơn bạn đã trả lời! – Peter

+1

Hi @Peter, như tôi nhớ, các thiết bị PCIE cũng hỗ trợ ngắt MSI. Vì vậy, bạn có thể yêu cầu MSI ngắt để lưu chu kỳ CPU. Cảm ơn –

0

PCIe là phiên bản nâng cao với tốc độ và khả năng cao hơn. Các khả năng cơ bản vẫn giữ nguyên cho tất cả các tiêu chuẩn. Việc đăng ký trình điều khiển và cung cấp các trình xử lý là một và giống nhau vì tất cả các trình điều khiển PCI đăng ký vào cùng một hệ thống con PCI PCI.

Các vấn đề liên quan