| struct pci_driver {    struct list_head node;     char *name;     const struct pci_device_id *id_table;     int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);     void (*remove) (struct pci_dev *dev);     int (*save_state) (struct pci_dev *dev, u32 state);     int (*suspend)(struct pci_dev *dev, u32 state);     int (*resume) (struct pci_dev *dev);     int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); }; | 
| struct pci_dev {     struct list_head global_list;     struct list_head bus_list;     struct pci_bus *bus;     struct pci_bus *subordinate;     void        *sysdata;     struct proc_dir_entry *procent;     unsigned int    devfn;     unsigned short vendor;     unsigned short device;     unsigned short subsystem_vendor;     unsigned short subsystem_device;     unsigned int    class;     u8      hdr_type;     u8      rom_base_reg;     struct pci_driver *driver;     void        *driver_data;     u64     dma_mask;     u32             current_state;     unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];     unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];     unsigned int    irq;     struct resource resource[DEVICE_COUNT_RESOURCE];     struct resource dma_resource[DEVICE_COUNT_DMA];     struct resource irq_resource[DEVICE_COUNT_IRQ];     char        name[80];     char        slot_name[8];     int     active;     int     ro;     unsigned short regs;     int (*prepare)(struct pci_dev *dev);     int (*activate)(struct pci_dev *dev);     int (*deactivate)(struct pci_dev *dev); }; | 
| /* 指明该驱动程序适用于哪一些PCI设备 */ static struct pci_device_id demo_pci_tbl [] __initdata = {     {PCI_VENDOR_ID_DEMO, PCI_DEVICE_ID_DEMO,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEMO},     {0,} }; /* 对特定PCI设备进行描述的数据结构 */ struct demo_card {     unsigned int magic;     /* 使用链表保存所有同类的PCI设备 */     struct demo_card *next;     /* ... */ } /* 中断处理模块 */ static void demo_interrupt(int irq, void *dev_id, struct pt_regs *regs) {     /* ... */ } /* 设备文件操作接口 */ static struct file_operations demo_fops = {     owner:      THIS_MODULE,   /* demo_fops所属的设备模块 */     read:       demo_read,    /* 读设备操作*/     write:      demo_write,    /* 写设备操作*/     ioctl:      demo_ioctl,    /* 控制设备操作*/     mmap:       demo_mmap,    /* 内存重映射操作*/     open:       demo_open,    /* 打开设备操作*/     release:    demo_release    /* 释放设备操作*/     /* ... */ }; /* 设备模块信息 */ static struct pci_driver demo_pci_driver = {     name:       demo_MODULE_NAME,    /* 设备模块名称 */     id_table:   demo_pci_tbl,    /* 能够驱动的设备列表 */     probe:      demo_probe,    /* 查找并初始化设备 */     remove:     demo_remove    /* 卸载设备模块 */     /* ... */ }; static int __init demo_init_module (void) {     /* ... */ } static void __exit demo_cleanup_module (void) {     pci_unregister_driver(&demo_pci_driver); } /* 加载驱动程序模块入口 */ module_init(demo_init_module); /* 卸载驱动程序模块入口 */ module_exit(demo_cleanup_module); | 
| static int __init demo_init_module (void) {     /* 检查系统是否支持PCI总线 */     if (!pci_present())         return -ENODEV;     /* 注册硬件驱动程序 */     if (!pci_register_driver(&demo_pci_driver)) {         pci_unregister_driver(&demo_pci_driver);                 return -ENODEV;     }     /* ... */     return 0; } | 
| static int __init demo_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) {     struct demo_card *card;     /* 启动PCI设备 */     if (pci_enable_device(pci_dev))         return -EIO;     /* 设备DMA标识 */     if (pci_set_dma_mask(pci_dev, DEMO_DMA_MASK)) {         return -ENODEV;     }     /* 在内核空间中动态申请内存 */     if ((card = kmalloc(sizeof(struct demo_card), GFP_KERNEL)) == NULL) {         printk(KERN_ERR "pci_demo: out of memory/n");         return -ENOMEM;     }     memset(card, 0, sizeof(*card));     /* 读取PCI配置信息 */     card->iobase = pci_resource_start (pci_dev, 1);     card->pci_dev = pci_dev;     card->pci_id = pci_id->device;     card->irq = pci_dev->irq;     card->next = devs;     card->magic = DEMO_CARD_MAGIC;     /* 设置成总线主DMA模式 */         pci_set_master(pci_dev);     /* 申请I/O资源 */     request_region(card->iobase, 64, card_names[pci_id->driver_data]);     return 0; } | 
| static int demo_open(struct inode *inode, struct file *file) {     /* 申请中断,注册中断处理程序 */     request_irq(card->irq, &demo_interrupt, SA_SHIRQ,         card_names[pci_id->driver_data], card)) {     /* 检查读写模式 */     if(file->f_mode & FMODE_READ) {         /* ... */     }     if(file->f_mode & FMODE_WRITE) {        /* ... */     }     /* 申请对设备的控制权 */     down(&card->open_sem);     while(card->open_mode & file->f_mode) {         if (file->f_flags & O_NONBLOCK) {             /* NONBLOCK模式,返回-EBUSY */             up(&card->open_sem);             return -EBUSY;         } else {             /* 等待调度,获得控制权 */             card->open_mode |= f_mode & (FMODE_READ | FMODE_WRITE);             up(&card->open_sem);             /* 设备打开计数增1 */             MOD_INC_USE_COUNT;             /* ... */         }     } } | 
| static int demo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {     /* ... */     switch(cmd) {         case DEMO_RDATA:             /* 从I/O端口读取4字节的数据 */             val = inl(card->iobae + 0x10); /* 将读取的数据传输到用户空间 */             return 0;     }     /* ... */ } | 
| static void demo_interrupt(int irq, void *dev_id, struct pt_regs *regs) {     struct demo_card *card = (struct demo_card *)dev_id;     u32 status;     spin_lock(&card->lock);     /* 识别中断 */     status = inl(card->iobase + GLOB_STA);     if(!(status & INT_MASK))      {         spin_unlock(&card->lock);         return; /* not for us */     }     /* 告诉设备已经收到中断 */     outl(status & INT_MASK, card->iobase + GLOB_STA);     spin_unlock(&card->lock);     /* 其它进一步的处理,如更新DMA缓冲区指针等 */ } | 
| static int demo_release(struct inode *inode, struct file *file) {     /* ... */     /* 释放对设备的控制权 */     card->open_mode &= (FMODE_READ | FMODE_WRITE);     /* 唤醒其它等待获取控制权的进程 */     wake_up(&card->open_wait);     up(&card->open_sem);     /* 释放中断 */     free_irq(card->irq, card);     /* 设备打开计数增1 */     MOD_DEC_USE_COUNT;     /* ... */  } | 
| static void __exit demo_cleanup_module (void) {     pci_unregister_driver(&demo_pci_driver); } | 
PCI总线不仅是目前应用广泛的计算机总线标准,而且是一种兼容性最强、功能最全的计算机总线。而Linux作为一种新的操作系统,其发展前景是无法估量的,同时也为PCI总线与各种新型设备互连成为可能。由于Linux源码开放,因此给连接到PCI总线上的任何设备编写驱动程序变得相对容易。本文介绍如何编译Linux下的PCI驱动程序,针对的内核版本是2.4。
Linux下PCI设备驱动程序开发 --- PCI驱动程序实现(三)
原文:http://www.cnblogs.com/wanghuaijun/p/7522655.html