2012-08-28 4 views
9

Linux 2.6.36 용 PCI 드라이버를 프로그래밍하고 있습니다.Linux 드라이버 개발 : PCI와 PCIe 드라이버의 차이점은 무엇입니까?

여기 내 코드입니다. 내 질문은, 내가 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

''pci_enable_device'를 호출 한 후'release_mem_region'을 호출하는 것이 적절하지 않습니까? 이 호출이 실패하더라도 메모리 영역은 여전히 ​​할당됩니다. 아마도'check_mem_region'을 사용하는 것이 제정신이 아닌가? – HonkyTonk

답변

2

소프트웨어 측면에서 보면 PCI 및 PCI Express 장치는 기본적으로 동일합니다. PCIe 장치는 동일한 구성 공간, BAR을 가지며 (일반적으로) 동일한 PCI INTx 인터럽트를 지원합니다.

예제 # 1 : Windows XP는 PCIe에 대한 특별한 지식이 없지만 PCIe 시스템에서는 정상적으로 작동합니다.

예 # 2 : 회사는 PCI 및 PCIe 버전의 주변 장치 보드를 제공하며 동일한 Windows/Linux 드라이버 패키지를 사용합니다. 운전자는 두 보드의 차이를 "알지 못합니다".

그러나 : PCIe 장치 자주 등 MSI, 핫 플러그, 확장 구성 공간, 이러한 기능의 대부분은 기존의 PCI에 존재하지만 사용되지 않는 것처럼, "고급"기능을 활용. 이 장치가 설계중인 장치 인 경우 이러한 고급 기능을 구현할지 여부는 사용자에게 달려 있습니다.

+0

PCIe 레거시 장치 (호환성 이유로 PCI 장치처럼 작동하는 PCIe 장치)는 더 이상 권장되지 않는 많은 기능을 구현합니다. 마음에 떠오르는 주요 기능은 I/O 읽기 및 쓰기로, 이는 실제로 비효율적 인 것으로 판명되었습니다. – Joshua

3

는 지금까지 내가 기억하는, 내가 작성한 디바이스 드라이버는 PCI 장치와 PCIe 장치 사이에 차이가 없습니다. 내 장치 드라이버는 chrdev, pci_resource, irqmem_region과 같은 종류의 호출을 사용합니다.

+0

답변 해 주셔서 감사합니다! – Peter

+1

안녕하세요 @ 피터, 기억, PCIE 장치도 MSI 인터럽트를 지원합니다. 따라서 CPU주기를 절약하기 위해 MSI 인터럽트를 요청할 수 있습니다. 감사합니다 –

0

PCIe는보다 빠른 속도와 기능을 갖춘 고급 버전입니다. 기본 기능은 모든 표준에서 동일하게 유지됩니다. 모든 PCI 드라이버가 동일한 Linux PCI 하위 시스템에 등록되므로 드라이버 등록 및 핸들러 제공은 동일합니다.

관련 문제