paep.c
来自「这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自」· C语言 代码 · 共 1,171 行 · 第 1/3 页
C
1,171 行
dev_param_p->flags |= READ_DATA_AVAILABLE; /*Post the semaphore controlling reads to the device*/ up(&dev_param_p->read_sem); wake_up_interruptible(&dev_param_p->select_wq); } if (status & DMA_WRITE_COMPLETE) { acknowledge_irq(DMA_WRITE_COMPLETE, dev_p); #ifdef INSTRUMENT ++dev_param_p->DMA_WRITE_COMPLETE_int_cnt;#endif/*INSTRUMENT*/ dev_param_p->write_state = WS_DMA_COMPLETE; wake_up_interruptible(&dev_param_p->wq); } if (status & DMA_WRITE_NO_SPACE) { acknowledge_irq(DMA_WRITE_NO_SPACE, dev_p); #ifdef INSTRUMENT ++dev_param_p->DMA_WRITE_NO_SPACE_int_cnt;#endif/*INSTRUMENT*/ dev_param_p->write_fail_reason = DMA_WRITE_NO_SPACE; wake_up_interruptible(&dev_param_p->wq); } if (status & DMA_WRITE_ERROR) { acknowledge_irq(DMA_WRITE_ERROR, dev_p);#ifdef INSTRUMENT ++dev_param_p->DMA_WRITE_ERROR_int_cnt;#endif/*INSTRUMENT*/ dev_param_p->write_fail_reason = DMA_WRITE_ERROR; wake_up_interruptible(&dev_param_p->wq); } if (status & DMA_READ_COMPLETE) { acknowledge_irq(DMA_READ_COMPLETE, dev_p);#ifdef INSTRUMENT ++dev_param_p->DMA_READ_COMPLETE_int_cnt;#endif/*INSTRUMENT*/ /* save how many didn't get transferred */ dev_param_p->read_residual = read_mailbox_status(dev_p); dev_param_p->read_state = RS_DMA_COMPLETE; wake_up_interruptible(&dev_param_p->rq); } if (status & DMA_READ_ERROR) { acknowledge_irq(DMA_READ_ERROR, dev_p);#ifdef INSTRUMENT ++dev_param_p->DMA_READ_ERROR_int_cnt;#endif/* INSTRUMENT */ wake_up_interruptible(&dev_param_p->rq); } return;}/* * Module Initialization (find it on the PCI bus) */static int __init aep_init_module(void) { int count; BANNER(); printk("%s%s%s%s\n", aep_version_str, DRIVER_VERSION, " Build Date: ", __DATE__); DPRINTK("AEP_MAXCARDS_NB = %d\n", AEP_MAXCARDS_NB); dev_list_pp = NULL; dma_buff_order = get_order(AEP_DMA_BUFFER_SIZE); DPRINTK("dma_buff_order = %d\n", dma_buff_order); DPRINTK("allocating pointer list\n"); dev_list_pp = (struct pci_dev **) kmalloc(AEP_MAXCARDS_NB * sizeof(struct pci_dev*), GFP_KERNEL); DPRINTK("dev_list_pp = 0x%p\n", dev_list_pp); if (!dev_list_pp) { ERR_PRINTK("Pointer list allocation failed (returning -ENOMEM)\n"); return -ENOMEM; } for (count = 0; count < AEP_MAXCARDS_NB; count++){ DPRINTK("zeroing pointer for card %d\n", count); dev_list_pp[count] = NULL; } if (pci_present()){ if (pci_register_driver(&aep_driver) <= 0) { ERR_PRINTK("no devices (returning -ENODEV)\n"); pci_unregister_driver(&aep_driver); return -ENODEV; } } DPRINTK("returning\n"); return 0;}static void __exit aep_cleanup_module(void) { DPRINTK("unregistering driver\n"); pci_unregister_driver(&aep_driver); nb_cards = 0; DPRINTK("freeing list of pointers 0x%p\n", dev_list_pp); kfree(dev_list_pp); dev_list_pp = NULL;} /* setup data for one AEP card, NOTE: pci_device_id can be used in the future if different initialisation methods are required for different chipsets */static int __devinit aep_init_one_device (struct pci_dev *dev_p, const struct pci_device_id *unused_p){ paep_unit_info_t *dev_param_p; unsigned long bar1; unsigned long bar3; int major,result; assert(dev_p); BANNER(); exit_if_too_many_cards(nb_cards); DPRINTK("allocating unit info struct\n"); dev_param_p = (paep_unit_info_t *) kmalloc(sizeof(paep_unit_info_t), GFP_KERNEL); if (!dev_param_p) { ERR_PRINTK("Couldn't allocate memory for device information (returning -ENOMEM)\n"); return -ENOMEM; } DPRINTK("dev_param_p = 0x%p\n", dev_param_p); dev_p->driver_data = dev_param_p; dev_param_p->major = 0; dev_param_p->int_inuse = 0; dev_param_p->flags = 0; dev_param_p->config_space = 0; dev_param_p->mem_space = 0; dev_param_p->read_dma_buf_p = 0; dev_param_p->write_dma_buf_p = 0; init_waitqueue_head(&dev_param_p->rq); init_waitqueue_head(&dev_param_p->drq); init_waitqueue_head(&dev_param_p->wq); init_waitqueue_head(&dev_param_p->select_wq); dev_param_p->read_state = RS_IDLE; dev_param_p->write_state = WS_IDLE; dev_param_p->read_residual = 0; dev_param_p->last_read_dma = 0; dev_param_p->last_write_dma = 0;#ifdef INSTRUMENT dev_param_p->open_cnt = 0; dev_param_p->open_busy_cnt = 0; dev_param_p->close_cnt = 0; dev_param_p->read_cnt = 0; dev_param_p->read_dma_cnt = 0; dev_param_p->read_busy_cnt = 0; dev_param_p->read_byte_cnt = 0; dev_param_p->write_cnt = 0; dev_param_p->write_dma_cnt = 0; dev_param_p->write_busy_cnt = 0; dev_param_p->write_busy_cnt2 = 0; dev_param_p->write_byte_cnt = 0; dev_param_p->interrupt_cnt = 0; dev_param_p->SIGNAL_DRIVER_int_cnt = 0; dev_param_p->DMA_WRITE_COMPLETE_int_cnt = 0; dev_param_p->DMA_WRITE_NO_SPACE_int_cnt = 0; dev_param_p->DMA_WRITE_ERROR_int_cnt = 0; dev_param_p->DMA_READ_COMPLETE_int_cnt = 0; dev_param_p->DMA_READ_ERROR_int_cnt = 0;#endif /* INSTRUMENT */ /* set up mapping to PCI device addresses */ DPRINTK("mapping PCI\n"); bar1 = pci_resource_start(dev_p, 0); DPRINTK("bar1 = 0x%08lX\n", bar1); dev_param_p->config_space = ioremap(bar1, AEP_CONFIG_SIZE); DPRINTK("config_space = 0x%p\n", dev_param_p->config_space); if (!dev_param_p->config_space) { ERR_PRINTK("Unable to map PCI config space (returning -ENOMEM)\n"); kfree(dev_param_p); return -ENOMEM; } bar3 = pci_resource_start(dev_p, 2); DPRINTK("bar3 = 0x%08lX\n", bar3); dev_param_p->mem_space = ioremap(bar3, AEP_MEM_SIZE); DPRINTK("mem_space = 0x%p\n", dev_param_p->mem_space); if (!dev_param_p->mem_space) { ERR_PRINTK("Unable to map PCI memory space (returning -ENOMEM)\n"); iounmap(dev_param_p->config_space); kfree(dev_param_p); return -ENOMEM; } init_MUTEX(&(dev_param_p->aep_sem)); init_MUTEX(&(dev_param_p->read_sem)); /* create and register _PROPERLY_ /dev entry in device filesystem * NOTE: unlike the driver for the 2.2 kernel, each card has a different major number */ sprintf(dev_p->name, "%s%d", AEP_DEVICE_NAME, nb_cards); major = devfs_register_chrdev(dev_param_p->major, dev_p->name, &aep_fops); if (major < 0) { ERR_PRINTK("Unable to get major for aep device (returning %d)\n", major); return major; } dev_param_p->dev_fs_handle = devfs_register(NULL, dev_p->name, DEVFS_FL_DEFAULT, dev_param_p->major, nb_cards, S_IFCHR | S_IRUGO | S_IWUSR, &aep_fops, NULL); if (dev_param_p->major == 0) dev_param_p->major = major; DPRINTK("successfully registered devfs entry %s (major=%d)\n", dev_p->name, dev_param_p->major); /*See the comment for the open routine for an explanation for why we're requesting the irq here*/ DPRINTK("requesting irq %d\n", dev_p->irq); result = request_irq(dev_p->irq, aep_interrupt_handler, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, AEP_DEVICE_NAME, dev_p); if (result) { ERR_PRINTK("Can't get assigned irq %d (returning -EBUSY)\n", dev_p->irq);#ifdef INSTRUMEN ++dev_param_p->open_busy_cnt;#endif/*INSTRUMENT*/ return( -EBUSY); } dev_param_p->int_inuse = 1;#ifdef AEP_HAS_PROC_ENTRY if (proc_entry_owner_p == NULL) { if ((dev_p->procent = create_proc_entry(AEP_DEVICE_NAME, S_IRUGO | S_IWUSR, NULL)) != NULL) { /* NOTE: I think there is no need to protect this section by a mutex, * as the driver registers each device sequentially one after another. * The first device will become the owner of the /proc entry. VF */ dev_p->procent->read_proc = aep_read_procmem; proc_entry_owner_p = dev_p; DPRINTK("created proc entry %s successfully\n", AEP_DEVICE_NAME); } else WARN_PRINTK("Failed to create proc entry %s\n", AEP_DEVICE_NAME); } #endif /* AEP_HAS_PROC_ENTRY */ dev_list_pp[nb_cards] = dev_p; nb_cards++; DPRINTK("returning\n"); return 0;}/* unmap bar1 and bar3, free corresponding PCI resources */static void __devexit aep_remove_one_device (struct pci_dev *rem_dev_p){ int dev_num = 0; int removed = 0; struct pci_dev *dev_p = NULL; paep_unit_info_t *dev_param_p = NULL; assert(rem_dev_p); BANNER(); if (dev_list_pp) for (dev_num = 0; dev_num < AEP_MAXCARDS_NB; dev_num++) { dev_p = dev_list_pp[dev_num]; if (dev_p) if (dev_p == rem_dev_p) { removed = dev_num; dev_param_p = dev_p->driver_data; DPRINTK("cleaning up card %d\n", dev_num); /* clean up resources */ if (dev_param_p->int_inuse) { DPRINTK("freeing irq\n"); free_irq(dev_p->irq, dev_p); dev_param_p->int_inuse = 0; } else WARN_PRINTK("IRQ not in use, won't free\n");#ifdef AEP_HAS_PROC_ENTRY if (dev_p == proc_entry_owner_p) { DPRINTK("removing proc entry %s\n", dev_p->procent->name); remove_proc_entry(dev_p->procent->name, NULL); }#endif /* AEP_HAS_PROC_ENTRY */ devfs_unregister_chrdev(dev_param_p->major, dev_p->name); devfs_unregister(dev_param_p->dev_fs_handle); DPRINTK("successfully un-registered devfs entry %s (major=%d)\n", dev_p->name, dev_param_p->major); /* release all resources associated with each card */ if (dev_param_p->config_space) { DPRINTK(" unmapping config space 0x%p\n", dev_param_p->config_space); iounmap(dev_param_p->config_space); } if (dev_param_p->mem_space) { DPRINTK(" unmapping register space 0x%p\n", dev_param_p->mem_space); iounmap(dev_param_p->mem_space); } if (dev_param_p) { DPRINTK(" freeing card info struct 0x%p\n", dev_param_p); kfree(dev_param_p); dev_param_p = NULL; } dev_list_pp[removed] = NULL; nb_cards--; } } }module_init(aep_init_module); module_exit(aep_cleanup_module);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?