📄 rtd-dm6430.c
字号:
printk( KERN_INFO "MOUTW io + 0x%04x = 0x%04x(0x%04x/0x%04x)\n", io_rq.reg, *value_p, io_rq.value, io_rq.mask );#endif return 0;}static intDM6430HR_IOCTL_CLEAR_Handler(struct Dm6430hrDevice *device_p, ulong arg) { spin_lock(&device_p->lock); DM6430HRClear(device_p, arg); spin_unlock(&device_p->lock); return 0;} static intDM6430HR_IOCTL_IRQ_INSTALL_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int status; struct DM6430HR_CallBack cb;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_INSTALL_ISR()\n");#endif if (copy_from_user(&cb, (struct DM6430HR_CallBack *) arg, sizeof(cb))) return -EFAULT; status = validate_interrupt_circuit(cb.intr); if (status != 0) { return status; } if (!device_p->irq[cb.intr] || (cb.signo >= _NSIG)) return -EINVAL; spin_lock(&device_p->lock); if (cb.action) { device_p->callback[cb.intr].signo = cb.signo; device_p->callback[cb.intr].process = current; device_p->callback[cb.intr].context = cb.context; } else { cb.context = device_p->callback[cb.intr].context; device_p->callback[cb.intr].signo = 0; device_p->callback[cb.intr].process = 0; device_p->callback[cb.intr].context = 0; } spin_unlock(&device_p->lock); if (!cb.action) if (copy_to_user((struct DM6430HR_CallBack *) arg, &cb, sizeof(cb))) return -EFAULT;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_INSTALL_ISR() end\n");#endif return 0;}static intDM6430HR_IOCTL_IRQ_ENABLE_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int status; struct DM6430HR_IE io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_IRQ_ENABLE()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_IE *) arg, sizeof(io_rq))) return -EFAULT; status = validate_interrupt_circuit(io_rq.intr); if (status != 0) { return status; } if (!device_p->irq[io_rq.intr]) return -EINVAL; spin_lock(&device_p->lock); DM6430HRIRQEnable(device_p, io_rq.intr, io_rq.action ? 1 : 0 ); spin_unlock(&device_p->lock);#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_IRQ_ENABLE() end\n");#endif return 0;}static intDM6430HR_IOCTL_DMA_INSTALL_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int status; struct dm_dma_buf *buf_p; struct DM6430HR_DI io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_DMA_INSTALL()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_DI *) arg, sizeof(io_rq))) return -EFAULT; status = validate_dma_circuit(io_rq.dma); if (status != 0) { return status; } if (!device_p->dma[io_rq.dma]) return -EINVAL; buf_p = &device_p->dmabuf[io_rq.dma]; if (io_rq.action) { if (buf_p->addr) return 0; spin_lock(&device_p->lock); buf_p->addr = (char *) dm_dma_mem_alloc(buflength); buf_p->length = buflength; spin_unlock(&device_p->lock); if (!buf_p->addr) return -ENOMEM; memset(buf_p->addr, 0, buflength); } else {// m_Dma[Channel].TerminateXfer(); dm_stop_dma(device_p, io_rq.dma); spin_lock(&device_p->lock); if (buf_p->addr) dm_dma_mem_free((unsigned long) buf_p->addr, buf_p->length); buf_p->length = 0; buf_p->addr = 0; spin_unlock(&device_p->lock); } return 0;}static intDM6430HR_IOCTL_DMA_GETDATA_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int status; struct DM6430HR_GDD io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_DMA_GETDATA()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_GDD *) arg, sizeof(io_rq))) return -EFAULT; status = validate_dma_circuit(io_rq.dma); if (status != 0) { return status; } if ( !device_p->dma[io_rq.dma] || !device_p->dmabuf[io_rq.dma].addr || ((io_rq.offset + io_rq.length) > device_p->dmabuf[io_rq.dma].length) ) return -EINVAL; if ( copy_to_user( io_rq.buf, (device_p->dmabuf[io_rq.dma].addr + io_rq.offset), io_rq.length ) ) return -EFAULT; return 0;}static intDM6430HR_IOCTL_DMA_GETINC_Handler(struct Dm6430hrDevice *device_p, ulong arg) { struct DM6430HR_GID io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_DMA_GETINC()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_GID *) arg, sizeof(io_rq))) return -EFAULT; switch (io_rq.port) { case rSTR_AD_6430: case rSTR_DIN_FIFO_6430: break; default: return -EINVAL; break; } switch (io_rq.type) { case DM6430HR_STR_TYPE_BYTE: case DM6430HR_STR_TYPE_WORD: break; default: return -EINVAL; break; } /* * Do not allow byte transfers from A/D FIFO */ if ( (io_rq.port == rSTR_AD_6430) && (io_rq.type != DM6430HR_STR_TYPE_WORD) ) { return -EOPNOTSUPP; } /* * Do not allow word transfers from digital input FIFO */ if ( (io_rq.port == rSTR_DIN_FIFO_6430) && (io_rq.type != DM6430HR_STR_TYPE_BYTE) ) { return -EOPNOTSUPP; } /* * Each FIFO has 1024 elements, don't allow more in one read */ if (io_rq.times > 1024) { return -EINVAL; } if (io_rq.times) { io_rq.port += device_p->io; spin_lock(&device_p->lock); /* * Do I/O into kernel stream read buffer, not into user space buffer. * In order to do I/O into a user space buffer, it must be remapped * into kernel space using the kiobuf interface. It's a stupid idea * to do I/O directly into a user buffer without remapping because * 1) the kernel is not set up do so, 2) it is a user address, 3) the * 3) address can refer to anything or anywhere, 4) the address may * not even be valid or in memory, 5) access_ok()/verify_area() can * "approve" a user address which can later cause a fault, and 6) the * I/O occurs into a kernel area that probably should not be mucked * with. Just say no to I/O directly into user space. */ switch (io_rq.type) { case DM6430HR_STR_TYPE_BYTE: dm_insb(io_rq.port, device_p->stream_buff_p, io_rq.times); break; case DM6430HR_STR_TYPE_WORD: dm_insw(io_rq.port, device_p->stream_buff_p, io_rq.times); break; } spin_unlock(&device_p->lock); if ( copy_to_user( io_rq.buf, device_p->stream_buff_p, (io_rq.times * io_rq.type) ) ) { return -EFAULT; } } return 0;}unsigned long flags;static intDM6430HR_IOCTL_DMA_START_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int channel; int status; struct dm_dma_buf *buf_p; struct DM6430HR_DST io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_DMA_START()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_DST *) arg, sizeof(io_rq))) return -EFAULT; status = validate_dma_circuit(io_rq.dma); if (status != 0) { return status; } if ( !device_p->dma[io_rq.dma] || !device_p->dmabuf[io_rq.dma].addr || (io_rq.length & 1) || (io_rq.length > device_p->dmabuf[io_rq.dma].length) ) return -EINVAL; channel = device_p->dma[io_rq.dma]; buf_p = &device_p->dmabuf[io_rq.dma]; //m_Dma[Channel].Initiate(&I, this, Offset, xFerLength, bDemand); flags = claim_dma_lock(); //fixme FIRST DMA FLAG bug test only //memset(bufp->addr, 0, bufp->length); disable_dma(channel); clear_dma_ff(channel); set_dma_mode(channel, DMA_MODE_READ); set_dma_addr(channel, virt_to_bus(buf_p->addr)); set_dma_count(channel, io_rq.length); enable_dma(channel); //release_dma_lock(flags); return 0;}static intDM6430HR_IOCTL_DMA_STOP_Handler(struct Dm6430hrDevice *device_p, ulong arg) { int status;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_DMA_STOP(%ld)\n", arg);#endif status = validate_dma_circuit(arg); if (status != 0) { return status; } if (!device_p->dma[arg]) return -EINVAL; //return m_Dma[Channel].TerminateXfer(); //flags = claim_dma_lock(); disable_dma(device_p->dma[arg]); clear_dma_ff(device_p->dma[arg]); release_dma_lock(flags); return 0;}static intDM6430HR_IOCTL_GET_IRQ_COUNTER_Handler( struct Dm6430hrDevice *device_p, ulong arg) { int status; struct DM6430HR_GIC io_rq;#ifdef DEBUG if (debug & DBG_IOCTLS) printk(KERN_INFO "DM6430HR_GET_IRQ_COUNTER()\n");#endif if (copy_from_user(&io_rq, (struct DM6430HR_GIC *) arg, sizeof(io_rq))) return -EFAULT; status = validate_interrupt_circuit(io_rq.intr); if (status != 0) { return status; } if (!device_p->irq[io_rq.intr]) return -EINVAL; spin_lock(&device_p->lock); io_rq.counter = device_p->irq_count[io_rq.intr]; spin_unlock(&device_p->lock); if (copy_to_user((struct DM6430HR_GIC *) arg, &io_rq, sizeof(io_rq))) return -EFAULT; return 0;}static intdm6430hr_ioctl( struct inode *inode_p, struct file *file_p, uint cmd, ulong arg) { int rc = 0; struct Dm6430hrDevice *device_p;#ifdef DEBUG if (debug & DBG_FILEOPS) printk(KERN_INFO "dm6430hr_ioctl()\n");#endif device_p = (struct Dm6430hrDevice *) file_p->private_data; if (!device_p) return -EINVAL; switch (cmd) { case DM6430HR_IOCTL_OUTW: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_OUTW_Handler(device_p, arg); break; case DM6430HR_IOCTL_MOUTW: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_MOUTW_Handler(device_p, arg); break; case DM6430HR_IOCTL_OUTB: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_OUTB_Handler(device_p, arg); break; case DM6430HR_IOCTL_MOUTB: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_MOUTB_Handler(device_p, arg); break; case DM6430HR_IOCTL_INW: if (!(file_p->f_mode & FMODE_READ)) return -EACCES; rc = DM6430HR_IOCTL_INW_Handler(device_p, arg); break; case DM6430HR_IOCTL_INB: if (!(file_p->f_mode & FMODE_READ)) return -EACCES; rc = DM6430HR_IOCTL_INB_Handler(device_p, arg); break; case DM6430HR_IOCTL_CLEAR: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_CLEAR_Handler(device_p, arg); break; case DM6430HR_IOCTL_IRQ_INSTALL: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_IRQ_INSTALL_Handler(device_p, arg); break; case DM6430HR_IOCTL_IRQ_ENABLE: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_IRQ_ENABLE_Handler(device_p, arg); break; case DM6430HR_IOCTL_DMA_INSTALL: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_DMA_INSTALL_Handler(device_p, arg); break; case DM6430HR_IOCTL_DMA_START: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_DMA_START_Handler(device_p, arg); break; case DM6430HR_IOCTL_DMA_STOP: if (!(file_p->f_mode & FMODE_WRITE)) return -EACCES; rc = DM6430HR_IOCTL_DMA_STOP_Handler(device_p, arg); break; case DM6430HR_IOCTL_DMA_GETDATA: if (!(file_p->f_mode & FMODE_READ)) return -EACCES; rc = DM6430HR_IOCTL_DMA_GETDATA_Handler(device_p, arg); break; case DM6430HR_IOCTL_DMA_GETINC: if (!(file_p->f_mode & FMODE_READ)) return -EACCES; rc = DM6430HR_IOCTL_DMA_GETINC_Handler(device_p, arg); break; case DM6430HR_IOCTL_GET_IRQ_COUNTER: if (!(file_p->f_mode & FMODE_READ)) return -EACCES; rc = DM6430HR_IOCTL_GET_IRQ_COUNTER_Handler(device_p, arg); break; default: rc = -EINVAL; } return rc;}static struct file_operations driver_fops = { owner: THIS_MODULE, open: dm6430hr_open, ioctl: dm6430hr_ioctl, release: dm6430hr_release,};static voiddm6430hr_interrupt(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -