📄 rtd-dm6430.c
字号:
int irq, struct Dm6430hrDevice *device_p, struct pt_regs *regs_p) { static short mask[] = {DM6430_CL_IRQ1, DM6430_CL_IRQ2}; if (device_p) { int channel; unsigned long flags;#ifdef DEBUG if (debug & DBG_INT) printk(KERN_INFO "dm6430: hardware int\n");#endif if ( (device_p->irq[channel = 0] == irq) || (device_p->irq[channel = 1] == irq) ) { if (dm_inw_p(device_p->io + r_STATUS_6430) & (0x2000 << channel)) { spin_lock_irqsave(&device_p->lock, flags); // fixme tmp // printk(KERN_INFO "STATUS = 0x%04x, residue0=%d, residue1=%d\n", dm_inw_p(dev->io + r_STATUS_6430), get_dma_residue(dev->dma[0]), get_dma_residue(dev->dma[1]) );#ifdef DEBUG if (debug & DBG_INT) printk(KERN_INFO "dm6430: int ch=%d\n", channel);#endif device_p->irq_count[channel]++; /* clear interrupts */ DM6430HRClear(device_p, mask[channel]); if ( (device_p->callback[channel].signo != 0) && (device_p->callback[channel].process != 0) ) { struct siginfo info;#ifdef DEBUG if (debug & DBG_INT) printk( KERN_INFO "sending %d to %d\n", device_p->callback[channel].signo, device_p->callback[channel].process->pid );#endif info.si_signo = device_p->callback[channel].signo; info.si_errno = channel; // must be < 0 for info.si_ptr info.si_code = DM6430HR_SI_CODE; /* sending from kernel */ info.si_pid = 0; info.si_uid = 0; info.si_ptr = device_p->callback[channel].context; send_sig_info( info.si_signo, &info, device_p->callback[channel].process ); } spin_unlock_irqrestore(&device_p->lock, flags); } } }}static inline intdm6430hr_detect(struct Dm6430hrDevice *device_p) { return 1; /* return dm_inb_p(device_p->io + 2) != 0xFF; */}static voiddm6430hr_unregister_device(struct Dm6430hrDevice *device_p) { int i;#ifdef DEBUG if (debug & DBG_REG_DEVS) printk(KERN_INFO "dm6430hr_unregister_device()\n");#endif if (device_p && (device_p->flags & INITIALIZED)) { spin_lock(&device_p->lock); for (i = 0; i < DM6430HR_DMAS; i++) { if (device_p->dma[i]) free_dma(device_p->dma[i]); if (device_p->dmabuf[i].addr) { dm_dma_mem_free( (unsigned long) device_p->dmabuf[i].addr, device_p->dmabuf[i].length ); device_p->dmabuf[i].length = 0; device_p->dmabuf[i].addr = 0; } } for (i = 0; i < DM6430HR_IRQS; i++) { if (device_p->irq[i]) { free_irq(device_p->irq[i], device_p); } } if (device_p->io) release_region(device_p->io, DM6430HR_IO_EXTENT); for (i = 0; i < DM6430HR_IRQS; ++i) { device_p->callback[i].signo = 0; device_p->callback[i].process = 0; device_p->callback[i].context = 0; } atomic_set(&device_p->counter, 0); device_p->flags &= ~INITIALIZED; /* * Free streaming read buffer memory. */ if (device_p->stream_buff_p != NULL) { kfree(device_p->stream_buff_p); } spin_unlock(&device_p->lock); }}static intdm6430hr_register_device(struct Dm6430hrDevice *device_p) { int rc = 0, i; void *stream_p; EXPORT_NO_SYMBOLS;#ifdef DEBUG if (debug & DBG_REG_DEVS) printk( KERN_INFO "dm6430hr_register_device(io=%#x irq=%d,%d dma=%d,%d)\n", device_p->io, device_p->irq[0], device_p->irq[1], device_p->dma[0], device_p->dma[1] );#endif if ((device_p->flags & INITIALIZED) || !device_p->io) return 0; /* * Allocate memory for streaming read buffer. Maximum size is 2048 bytes * because it can hold 1024 8-bit samples or 1024 16-bit samples. Get the * memory while no spinlock is held. */ stream_p = kmalloc(2048, GFP_KERNEL); if (stream_p == NULL) { return -ENOMEM; } spin_lock(&device_p->lock); if (request_region(device_p->io, DM6430HR_IO_EXTENT, name) == NULL) { printk( KERN_ERR "Unable get IO port range %#x-%#x: resource busy\n", device_p->io, (device_p->io + DM6430HR_IO_EXTENT - 1) ); spin_unlock(&device_p->lock); kfree(stream_p); return -EBUSY; } if (dm6430hr_detect(device_p) == 0) { printk(KERN_ERR "No dm6430 device found at %#x\n", device_p->io); release_region(device_p->io, DM6430HR_IO_EXTENT); spin_unlock(&device_p->lock); kfree(stream_p); return -ENXIO; } for (i = 0; i < DM6430HR_IRQS; i++) { if ( device_p->irq[i] && ( rc = request_irq( device_p->irq[i], (isr_handler) dm6430hr_interrupt, 0, name, device_p ) ) ) { printk( KERN_ERR "dm6430hr: unable to get IRQ %#x (error = %d)\n", device_p->irq[i], -rc ); while (--i >= 0) { if (device_p->irq[i]) { free_irq(device_p->irq[i], device_p); } } release_region(device_p->io, DM6430HR_IO_EXTENT); spin_unlock(&device_p->lock); kfree(stream_p); return rc; } } for (i = 0; i < DM6430HR_DMAS; i++) { if (device_p->dma[i] && (rc = request_dma(device_p->dma[i], name))) { printk( KERN_ERR "dm6430hr: unable to get DMA channel %#x (error = %d)\n", device_p->dma[i], -rc ); while (--i >= 0) { if (device_p->dma[i]) { free_dma(device_p->dma[i]); } } i = 2; while (--i >= 0) { if (device_p->irq[i]) { free_irq(device_p->irq[i], device_p); } } release_region(device_p->io, DM6430HR_IO_EXTENT); spin_unlock(&device_p->lock); kfree(stream_p); return -EBUSY; } } printk( KERN_INFO "dm6430hr device successfully registered at io=%#x, " "irq=%d,%d dma=%d,%d\n", device_p->io, device_p->irq[0], device_p->irq[1], device_p->dma[0], device_p->dma[1] ); DM6430HR_Initdev(device_p); device_p->flags |= INITIALIZED; device_p->stream_buff_p = stream_p; spin_unlock(&device_p->lock); return rc;}#ifdef MODULEstatic unsigned short io[DM6430HR_MAX_DEVS];static int irq1[DM6430HR_MAX_DEVS];static int irq2[DM6430HR_MAX_DEVS];static int dma1[DM6430HR_MAX_DEVS];static int dma2[DM6430HR_MAX_DEVS];MODULE_AUTHOR(DRIVER_COPYRIGHT);MODULE_DESCRIPTION(DRIVER_DESCRIPTION);MODULE_SUPPORTED_DEVICE(DRIVER_NAME);MODULE_PARM(force, "i" );MODULE_PARM_DESC(force, "allocate resources on driver load");MODULE_PARM(buflength, "i");MODULE_PARM_DESC(buflength, "DMA buffer length");MODULE_PARM(io, "1-" __MODULE_STRING(DM6430HR_MAX_DEVS) "h");MODULE_PARM_DESC(io, "I/O port base address");MODULE_PARM(irq1, "1-" __MODULE_STRING(DM6430HR_MAX_DEVS) "i");MODULE_PARM_DESC(irq1, "IRQ line #1");MODULE_PARM(irq2, "1-" __MODULE_STRING(DM6430HR_MAX_DEVS) "i");MODULE_PARM_DESC(irq2, "IRQ line #2");MODULE_PARM(dma1, "1-" __MODULE_STRING(DM6430HR_MAX_DEVS) "i");MODULE_PARM_DESC(dma1, "DMA channel #1");MODULE_PARM(dma2, "1-" __MODULE_STRING(DM6430HR_MAX_DEVS) "i");MODULE_PARM_DESC(dma2, "DMA channel #2");#ifdef DEBUGMODULE_PARM(debug , "i");MODULE_PARM_DESC(debug , "Debug level, bits field");#endif/******************************************************************************validate_irq() Purpose: Determine if an IRQ number given on the insmod command line is valid for our purposes. Called from init_module() only. Parameters: irq_num => IRQ number to validate. Return Value: 0 Success or irq_num is 0. EINVAL irq_num is not valid.*******************************************************************************/static intvalidate_irq(int irq_num) { /* Acceptable irq, first is IRQ3 */ static int irqs[] = {3, 0, 5, 0, 0, 0, 9, 10, 11, 12, 0, 0, 15}; if (irq_num == 0) { return 0; } if ((irq_num < 3) || (irq_num > 15) || !irqs[irq_num - 3]) { printk(KERN_ERR "Invalid dm6430 device IRQ %u\n", irq_num); return -EINVAL; } return 0;}/******************************************************************************validate_dma() Purpose: Determine if a DMA channel number given on the insmod command line is valid for our purposes. Called from init_module() only. Parameters: dma_channel => DMA channel number to validate. Return Value: 0 Success or dma_channel is 0. EINVAL dma_channel is not valid.*******************************************************************************/static intvalidate_dma_channel(int dma_channel) { if (dma_channel == 0) { return 0; } if ((dma_channel < 5) || (dma_channel > 7)) { printk(KERN_ERR "Invalid dm6430 device DMA channel %u\n", dma_channel); return -EINVAL; } return 0;}intinit_module(void) { int device_num; int rc; int device_present = 0;#ifdef DEBUG if (debug & DBG_LOAD) printk(KERN_INFO "dm6430hr init_module()\n");#endif /* * Validate base I/O addresses, IRQs, and DMA channels before making any * changes. This makes it easier to keep the driver in a consistent state * in case something goes wrong. */ for (device_num = 0; device_num < DM6430HR_MAX_DEVS; device_num++) { unsigned short io_addr; /* * No base I/O address means no device present */ io_addr = io[device_num]; if (!io_addr) continue; device_present = 1; /* * Validate base I/O address */ if ((io_addr < 0x200) || (io_addr > 0x3E0) || (io_addr & 0xF)) { printk( KERN_ERR "Invalid dm6430 device base I/O address 0x%04x\n", io_addr ); return -EINVAL; } /* * Validate IRQ numbers */ rc = validate_irq(irq1[device_num]); if (rc != 0) { return rc; } rc = validate_irq(irq2[device_num]); if (rc != 0) { return rc; } /* * Validate DMA channels */ rc = validate_dma_channel(dma1[device_num]); if (rc != 0) { return rc; } rc = validate_dma_channel(dma2[device_num]); if (rc != 0) { return rc; } } if (device_present == 0) { printk(KERN_ERR "No DM6430 devices configured.\n"); return -ENODEV; } /* * We've done as much validation as possible, now reserve a character major * number */ rc = register_chrdev(major, name, &driver_fops); if (rc < 0) { printk( KERN_ERR "Major %u character device registration failed, errno = %d\n", major, -rc ); return rc; } /* * rc contains character device major number from register_chrdev(), so * save it for use when device is unregistered */ major = rc;#ifdef DEBUG if (debug & DBG_LOAD) printk(KERN_INFO "Registered dm6430 device with major %d\n", major);#endif /* * Set up the device structure for each possible board and register each * device */ for (device_num = 0; device_num < DM6430HR_MAX_DEVS; device_num++) { struct Dm6430hrDevice *device_p = &devices[device_num]; atomic_set(&device_p->counter, 0); device_p->lock = SPIN_LOCK_UNLOCKED; device_p->io = io[device_num]; device_p->irq[0] = irq1[device_num]; device_p->irq[1] = irq2[device_num]; device_p->dma[0] = dma1[device_num]; device_p->dma[1] = dma2[device_num]; device_p->stream_buff_p = NULL; if (force) { rc = dm6430hr_register_device(device_p); if (rc != 0) { /* * Registration of current device failed, so completely * clean up by unregistering any device successfully registered * so far and unreserving the character major number */ printk( KERN_ERR "dm6430 device #%d registration failed.\n", device_num ); while (--device_num > 0) { (void) dm6430hr_unregister_device(&devices[device_num]); } unregister_chrdev(major, name); return rc; } } }#ifdef DEBUG if (debug & DBG_LOAD) printk(KERN_INFO "dm6430hr init_module() done\n");#endif return 0;}voidcleanup_module(void) { int devno;#ifdef DEBUG if (debug & DBG_LOAD) printk(KERN_INFO "dm6430hr cleanup_module()\n");#endif unregister_chrdev(major, name); for (devno = 0; devno < DM6430HR_MAX_DEVS; devno++) dm6430hr_unregister_device(&devices[devno]);#ifdef DEBUG if (debug & DBG_LOAD) printk(KERN_INFO "dm6430hr cleanup_module() done\n");#endif}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -