⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtd-dm6430.c

📁 rt 6430 采集卡 linux下驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	FILE NAME: rtd-dm64320.c	FILE DESCRIPTION: Driver code for DM6430	PROJECT NAME: Linux DM6430 Driver, Library, and Example Programs	PROJECT VERSION: (Defined in README.TXT)	Copyright 2004 RTD Embedded Technologies, Inc.  All Rights Reserved.*/#include <linux/spinlock.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>//#include <linux/config.h>#include <linux/init.h>#include <linux/stat.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/ioport.h>#include <linux/time.h>#include <linux/mm.h>#include <linux/signal.h>#include <linux/slab.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <dm6430ioctl.h>#include <dm6430driver.h>#define DRIVER_NAME		"rtd-dm6430"#define PROJECT_RELEASE		"2.0"#define DRIVER_DESCRIPTION	"DM6430 device driver"#define DRIVER_COPYRIGHT \    "Copyright 2004 RTD Embedded Technologies, Inc.  All Rights Reserved."static const char	name[]             	= DRIVER_NAME;static const char	description[] __initdata= DRIVER_DESCRIPTION;static const char	version[]     __initdata= PROJECT_RELEASE;static const char	copyright[]   __initdata= DRIVER_COPYRIGHT;static unsigned char	major	      __initdata= 0;static int 		force 	      __initdata= 0;static size_t		buflength     __initdata= 0x10000;	/* default value 64K */#ifdef DEBUGstatic int 		debug 	      __initdata= 0;#endifstatic struct Dm6430hrDevice devices[DM6430HR_MAX_DEVS];#ifndef DEBUG#define dm_outb_p(x, y)		(outb_p(y, x))#define dm_inb_p(x)		(inb_p(x))#define dm_outw_p(x, y)		(outw_p(y, x))#define dm_inw_p(x)		(inw_p(x))#elseunsigned chardm_inb_p(unsigned port) {		    unsigned char	byte_read;    byte_read = inb_p(port);    printk(KERN_INFO "%X = inb_p(%X);\n", byte_read, port);    return byte_read;}unsigned shortdm_inw_p(unsigned port) {		    unsigned short	word_read;    word_read = inw_p(port);    printk(KERN_INFO "%X = inw_p(%X);\n", word_read, port);    return word_read;}voiddm_outb_p(unsigned port, unsigned char byte_to_write) {    printk(KERN_INFO "outb_p(%X,%X);\n", port, byte_to_write);    outb_p(byte_to_write, port);}voiddm_outw_p(unsigned port, unsigned short word_to_write) {    printk(KERN_INFO "outw_p(%X,%X);\n", port, word_to_write);    outw_p(word_to_write, port);}#endif#define dm_insb(port, addr, count)	(insb((port), (addr), (count)))#define dm_insw(port, addr, count)	(insw((port), (addr), (count)))#define dm_dma_mem_alloc(size) 		__get_dma_pages(GFP_KERNEL, get_order(size))#define dm_dma_mem_free(addr, size) 	free_pages(addr, get_order(size))static int  dm6430hr_register_device(struct Dm6430hrDevice * dev);static void dm6430hr_unregister_device(struct Dm6430hrDevice *dev);#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0))/* Pure 2^n version of get_order */static inline intget_order(unsigned long size) {    int	order;    size = (size - 1) >> (PAGE_SHIFT - 1);    order = -1;    do {	size >>= 1;	order++;    } while(size);    return order;}#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,98) */static voiddm_stop_dma(struct Dm6430hrDevice *device_p, int dma) {    unsigned long	flags;    flags = claim_dma_lock();    disable_dma(device_p->dma[dma]);    clear_dma_ff(device_p->dma[dma]);    release_dma_lock(flags);}static inline voidDM6430HRClear(struct Dm6430hrDevice *device_p, unsigned short Mask) {#ifdef DEBUG    if (debug & DBG_DEV)	printk(KERN_INFO "DM6430HRClear(0x%04x)\n", Mask);#endif    /* setup the clear mask */    dm_outw_p(device_p->io + r_CLEAR_6430, Mask);    /* clear */    dm_inw_p(device_p->io + r_CLEAR_6430);}static voidDM6430HR_Initdev(struct Dm6430hrDevice *device_p) {    int	i;#ifdef DEBUG    if (debug & DBG_IOCTLS)	printk(KERN_INFO "DM6430HR_Initdev()\n");#endif    spin_lock(&device_p->lock);    device_p->Control_Register = 0;    for (i = 0; i < DM6430HR_IRQS ; i++) {	device_p->irq_count[i] = 0;    }    for (i = 0; i < DM6430HR_DMAS; i++) {	device_p->dmabuf[i].addr = 0;	device_p->dmabuf[i].length = 0;	device_p->Control_Register |=	    (device_p->dma[i] & 0x03) << (i ? 14 : 12);    }    /* Default board settings */    dm_outw_p(device_p->io + r_CONTROL_6430, device_p->Control_Register);    dm_outw_p(device_p->io + r_TRIGGER_6430, device_p->Trigger_Register = 0);    dm_outw_p(device_p->io + r_IRQ_6430, device_p->IRQ_Register = 0);    dm_outw_p(device_p->io + r_DIN_CONFIG_6430, device_p->DIN_Register = 0);    DM6430HRClear(device_p, 0x00FF);    spin_unlock(&device_p->lock);}static voidDM6430HRIRQEnable(struct Dm6430hrDevice *device_p, int IRQChannel, int Enable) {    static const unsigned short	IRQs[16] =	{0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 4, 5, 6, 0, 0, 7};#ifdef DEBUG    if (debug & DBG_DEV)	printk(KERN_INFO "DM6430HRIRQEnable(%d, %d)\n", IRQChannel, Enable);#endif    device_p->IRQ_Register &= (IRQChannel ? 0x1FFF : 0xFF1F);    if (Enable)	device_p->IRQ_Register |=	    ((IRQs[device_p->irq[IRQChannel]]) << (IRQChannel ? 13 : 5));    dm_outw_p(device_p->io + r_IRQ_6430, device_p->IRQ_Register);    /* clear irq */    DM6430HRClear(device_p, IRQChannel ? DM6430_CL_IRQ2 : DM6430_CL_IRQ1);}static inline struct Dm6430hrDevice *lookup_dev(int minor) {    if (minor >= DM6430HR_MAX_DEVS)	return 0;    return &devices[minor];}/******************************************************************************validate_dma_circuit()    Purpose:        Determine if a DMA circuit number given on certain ioctl() calls is        valid.    Parameters:        dma_circuit => DMA circuit number to validate.    Return Value:        0            dma_circuit is valid.        EINVAL            dma_circuit is not valid.*******************************************************************************/static intvalidate_dma_circuit(int dma_circuit) {    switch (dma_circuit) {	case DM6430HR_DMA1:	case DM6430HR_DMA2:	    return 0;	    break;	default:	    return -EINVAL;	    break;    }}/******************************************************************************validate_interrupt_circuit()    Purpose:        Determine if an interrupt circuit number given on certain ioctl()        calls is valid.    Parameters:        interrupt_circuit => Interrupt circuit number to validate.    Return Value:        0            interrupt_circuit is valid.        EINVAL            interrupt_circuit is not valid.*******************************************************************************/static intvalidate_interrupt_circuit(int interrupt_circuit) {    switch (interrupt_circuit) {	case DM6430HR_INT1:	case DM6430HR_INT2:	    return 0;	    break;	default:	    return -EINVAL;	    break;    }}static intdm6430hr_open(struct inode *inode_p, struct file *file_p) {    int				rc;    struct Dm6430hrDevice	*device_p;#ifdef DEBUG    if (debug & DBG_FILEOPS)	printk(KERN_INFO "dm6430hr_open()\n");#endif       device_p = lookup_dev(MINOR((inode_p)->i_rdev));    if (!device_p)	return -ENXIO;    if (!device_p->io)	return -ENXIO;    if (	!(device_p->flags & INITIALIZED)	&&	(rc = dm6430hr_register_device(device_p))    )	return rc;    if (file_p->private_data)	return -EBUSY;    file_p->private_data = device_p;    atomic_inc(&device_p->counter);    return 0;}static intdm6430hr_release(struct inode *inode_p, struct file *file_p) {    struct Dm6430hrDevice	*device_p;#ifdef DEBUG    if (debug & DBG_FILEOPS)	printk(KERN_INFO "dm6430hr_release()\n");#endif       device_p = (struct Dm6430hrDevice *) file_p->private_data;    if (device_p) {	int	i;	spin_lock(&device_p->lock);	for (i = 0; i < DM6430HR_IRQS; i++) {	    if (device_p->callback[i].process == current) {		device_p->callback[i].signo = 0;		device_p->callback[i].process = 0;		device_p->callback[i].context = 0;	    }	}	spin_unlock(&device_p->lock);	if (atomic_dec_and_test(&device_p->counter) && !force)	    dm6430hr_unregister_device(device_p);    }    file_p->private_data = 0;    return 0;}static intDM6430HR_IOCTL_INB_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    struct DM6430HR_IO8	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO8 *) arg, sizeof(io_rq)))	return -EFAULT;    if (io_rq.reg >= DM6430HR_IO_EXTENT)	return -EINVAL;    spin_lock(&device_p->lock);    io_rq.value = dm_inb_p(device_p->io + io_rq.reg);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)	printk(	    KERN_INFO "INB io + 0x%04x, value 0x%02x\n",	    io_rq.reg,	    io_rq.value	);#endif    if (copy_to_user((struct DM6430HR_IO8 *) arg, &io_rq, sizeof(io_rq)))	return -EFAULT;    return 0;}static intDM6430HR_IOCTL_OUTB_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    struct DM6430HR_IO8	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO8 *) arg, sizeof(io_rq)))	return -EFAULT;    if (io_rq.reg >= DM6430HR_IO_EXTENT)	return -EINVAL;    spin_lock(&device_p->lock);    dm_outb_p(device_p->io + io_rq.reg, io_rq.value);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)	printk(	    KERN_INFO "OUTB io + 0x%04x = 0x%02x\n",	    io_rq.reg,	    io_rq.value	);#endif    return 0;}static intDM6430HR_IOCTL_MOUTB_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    u_int8_t			value;    struct DM6430HR_MIO8	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO8 *) arg, sizeof(io_rq)))	return -EFAULT;    if (io_rq.reg >= DM6430HR_IO_EXTENT)	return -EINVAL;    spin_lock(&device_p->lock);    value = dm_inb_p(device_p->io + io_rq.reg);    value = (value & io_rq.mask) | (io_rq.value & ~io_rq.mask);    dm_outb_p(device_p->io + io_rq.reg, value);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)	printk(	    KERN_INFO "MOUTB io + 0x%04x = 0x%04x(0x%04x/0x%04x)\n",	    io_rq.reg,	    value,	    io_rq.value,	    io_rq.mask	);#endif    return 0;}static intDM6430HR_IOCTL_INW_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    struct DM6430HR_IO16	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO16 *) arg, sizeof(io_rq)))	return -EFAULT;    if ((io_rq.reg > (DM6430HR_IO_EXTENT - 2)) || (io_rq.reg & 1))	return -EINVAL;    spin_lock(&device_p->lock);    io_rq.value = dm_inw_p(device_p->io + io_rq.reg);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)	printk(	    KERN_INFO "INW io + 0x%04x, value 0x%04x\n",	    io_rq.reg,	    io_rq.value	);#endif    if (copy_to_user((struct DM6430HR_IO16 *) arg, &io_rq, sizeof(io_rq)))	return -EFAULT;    return 0;}static intDM6430HR_IOCTL_OUTW_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    struct DM6430HR_IO16	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO16 *) arg, sizeof(io_rq)))	return -EFAULT;    if ((io_rq.reg > (DM6430HR_IO_EXTENT - 2)) || (io_rq.reg & 1))	return -EINVAL;    spin_lock(&device_p->lock);    switch (io_rq.reg) {	case r_CONTROL_6430:	    device_p->Control_Register = io_rq.value;	    break;	case r_DIN_CONFIG_6430:	    device_p->DIN_Register = io_rq.value;	    break;	case r_IRQ_6430:	    device_p->IRQ_Register = io_rq.value;	    break;	case r_TRIGGER_6430:	    device_p->Trigger_Register = io_rq.value;	    break;	default:	    ;    }    dm_outw_p(device_p->io + io_rq.reg, io_rq.value);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)	printk(	    KERN_INFO "OUTW io + 0x%04x = 0x%04x\n",	    io_rq.reg,	    io_rq.value	);#endif    return 0;}static intDM6430HR_IOCTL_MOUTW_Handler(struct Dm6430hrDevice *device_p, ulong arg) {    u_int16_t			value, *value_p;    struct DM6430HR_MIO16	io_rq;    if (copy_from_user(&io_rq, (struct DM6430HR_IO16 *) arg, sizeof(io_rq)))	return -EFAULT;    if ((io_rq.reg > (DM6430HR_IO_EXTENT - 2)) || (io_rq.reg & 1))	return -EINVAL;    spin_lock(&device_p->lock);    switch (io_rq.reg) {	case r_CONTROL_6430:	    value_p = &device_p->Control_Register;	    break;	case r_DIN_CONFIG_6430:	    value_p = &device_p->DIN_Register;	    break;	case r_IRQ_6430:	    value_p = &device_p->IRQ_Register;	    break;	case r_TRIGGER_6430:	    value_p = &device_p->Trigger_Register;	    break;	default: 	    value = dm_inw_p(device_p->io + io_rq.reg);	    value_p = &value;    }    *value_p = (*value_p & io_rq.mask) | (io_rq.value & (~io_rq.mask));    dm_outw_p(device_p->io + io_rq.reg, *value_p);    spin_unlock(&device_p->lock);#ifdef DEBUG    if (debug & DBG_DEV)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -