1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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; /* ... */ } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; } /* ... */ } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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缓冲区指针等 */ } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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; /* ... */ } |
1 2 3 4 | static void __exit demo_cleanup_module (void) { pci_unregister_driver(&demo_pci_driver); } |
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |