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

📄 pci550x.c

📁 linux下面
💻 C
📖 第 1 页 / 共 5 页
字号:
		timeout = interruptible_sleep_on_timeout(&dib->adc_wq,				dib->adc_timeout);		if (signal_pending(current))			return(-ERESTARTSYS);		if (dib->int_status & INT_STATUS_DA0ERR)			return(-EIO);		if (dib->adc_status & AD_STATUS_ERROR) 			return (-EIO);	}	/* process next ADC DMA Buffer */	if (!(dib->adc_status & AD_STATUS_MPRF0)) {		pci_dma_sync_single(dib->pdev, dib->adc_dma_handle0,			PAGE_SIZE * PCI550X_DMA_PAGES,			PCI_DMA_FROMDEVICE);		bytes = copy_to_user((void *)buff,			(void *)(dib->adc_dma_buf0 + *offp), count);		if (bytes)			return(-EFAULT);		else {			*offp += count;			if (*offp >= (dib->adc_dma_bytes)) {				dib->adc_status |= AD_STATUS_MPRF0;				AD_STATUS_W(dib->adc_status);				*offp = 0;			}			return(count);		}	} else if (!(dib->adc_status & AD_STATUS_MPRF1)) {		pci_dma_sync_single(dib->pdev, dib->adc_dma_handle1,			PAGE_SIZE * PCI550X_DMA_PAGES,			PCI_DMA_FROMDEVICE);		bytes = copy_to_user((void *)buff,			(void *)(dib->adc_dma_buf1 + *offp), count);		if (bytes)			return(-EFAULT);		else {			*offp += count;			if (*offp >= (dib->adc_dma_bytes)) {				dib->adc_status |= AD_STATUS_MPRF1;				AD_STATUS_W(dib->adc_status);			*offp = 0;			}			return(count);		}	} else		return(-ETIME);}/* * pci550x_readv - readv method (ADC Scatter-Gather DMA) */static ssize_t pci550x_readv(struct file* filp, const struct iovec* iovp,	unsigned long count, loff_t *offp){	return(0);}/* * pci550x_write - write method (DAC Ping-Pong DMA) */static ssize_t pci550x_write(struct file* filp, const char *buff,	size_t count, loff_t *offp){	pci550x_dib *dib = (pci550x_dib *)filp->private_data;	pci550x_hwregs *REGS = (pci550x_hwregs *)dib->membase;	unsigned long bytes;	long timeout;	if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B)		return(-ENODEV);	/* Process selected DAC */	if (dib->dac_select == PCI550X_DAC0) { /* DAC0 */		/* can't write more than one buffer at a time */		if (count > ((dib->dac0_dma_bytes) - *offp))			count = ((dib->dac0_dma_bytes) - *offp);		/* process next DMA write Buffer */		if (dib->dac0_status & DA0_STATUS_ERROR)			return(-EIO);		else if ( (dib->dac0_status & DA0_STATUS_MPRF0) &&			(dib->dac0_status & DA0_STATUS_MPRF1) ) {			timeout = interruptible_sleep_on_timeout(&dib->dac0_wq,					dib->dac0_timeout);			if (signal_pending(current))				return(-ERESTARTSYS);			if (dib->int_status & INT_STATUS_DA0ERR)				return(-EIO);			if (dib->dac0_status & DA0_STATUS_ERROR) 				return (-EIO);		}		if (!(dib->dac0_status & DA0_STATUS_MPRF0)) {			pci_dma_sync_single(dib->pdev, dib->dac0_dma_handle0,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			bytes = copy_from_user((void *)(dib->dac0_dma_buf0 +					*offp), (void *)buff, count);			if (bytes)				return(-EFAULT);			else {				*offp += count;				if (*offp >= (dib->dac0_dma_bytes)) {					dib->dac0_status |= DA0_STATUS_MPRF0;					DA0_STATUS_W(dib->dac0_status);					*offp = 0;				}				return(count);			}		} else if (!(dib->dac0_status & DA0_STATUS_MPRF1)) {			pci_dma_sync_single(dib->pdev, dib->dac0_dma_handle1,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			bytes = copy_from_user((void *)(dib->dac0_dma_buf1 +					*offp), (void *)buff, count);			if (bytes)				return(-EFAULT);			else {				*offp += count;				if (*offp >= (dib->dac0_dma_bytes) ) {					dib->dac0_status |= DA0_STATUS_MPRF1;					DA0_STATUS_W(dib->dac0_status);					*offp = 0;				}				return(count);			}		} else			return(-ETIME);	} else { /* DAC1 */		/* can't write more than one buffer at a time */		if (count > ((dib->dac1_dma_bytes) - *offp))			count = ((dib->dac1_dma_bytes) - *offp);		/* process next DMA write Buffer */		if (dib->dac1_status & DA1_STATUS_ERROR)			return(-EIO);		else if ( (dib->dac1_status & DA1_STATUS_MPRF0) &&			(dib->dac1_status & DA1_STATUS_MPRF1) ) {			timeout = interruptible_sleep_on_timeout(&dib->dac1_wq,					dib->dac1_timeout);			if (signal_pending(current))				return(-ERESTARTSYS);			if (dib->int_status & INT_STATUS_DA1ERR)				return(-EIO);			if (dib->dac1_status & DA1_STATUS_ERROR) 				return (-EIO);		}		if (!(dib->dac1_status & DA1_STATUS_MPRF0)) {			pci_dma_sync_single(dib->pdev, dib->dac1_dma_handle0,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			bytes = copy_from_user((void *)(dib->dac1_dma_buf0 +					*offp), (void *)buff, count);			if (bytes)				return(-EFAULT);			else {				*offp += count;				if (*offp >= (dib->dac1_dma_bytes)) {					dib->dac1_status |= DA1_STATUS_MPRF0;					DA1_STATUS_W(dib->dac1_status);					*offp = 0;				}				return(count);			}		} else if (!(dib->dac1_status & DA1_STATUS_MPRF1)) {			pci_dma_sync_single(dib->pdev, dib->dac1_dma_handle1,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			bytes = copy_from_user((void *)(dib->dac1_dma_buf1 +				 *offp), (void *)buff, count);			if (bytes)				return(-EFAULT);			else {				*offp += count;				if (*offp >= (dib->dac1_dma_bytes)) {					dib->dac1_status |= DA1_STATUS_MPRF1;					DA1_STATUS_W(dib->dac1_status);					*offp = 0;				}				return(count);			}		} else			return(-ETIME);	}}/* * pci550x_writev - writev method (DAC Scatter-Gather DMA) */static ssize_t pci550x_writev(struct file* filp, const struct iovec* iovp,	unsigned long count, loff_t *offp){	return(0);}/* * pci550x_ioctl - ioctl method */static int pci550x_ioctl(struct inode *inode, struct file *filp,                        unsigned int cmd, unsigned long arg){	int err = 0;	int ret = 0;	int i,j;	u_int32_t reg, treg;	union {	 s32 pacer_clockf;	 u_int16_t pacer_clockh[2];	} u1;	pci550x_dib *dib = (pci550x_dib *)filp->private_data;	pci550x_hwregs *REGS = (pci550x_hwregs *)dib->membase;	/*	 * extract the type and number bitfields, and don't decode	 * wrong commands: return ENOTTY (inappropriate IOCTL) before         * access ok()	 */	if (_IOC_TYPE(cmd) != PCI550X_IOC_MAGIC) return -ENOTTY;	if (_IOC_NR(cmd) > PCI550X_IOC_MAXNR) return -ENOTTY;	/*	 * the direction is a bitmask, and VERIFY_WRITE catches R/W	 * transfers.  'Type' is user oriented, while access_ok() is	 * kernel oriented, so the concept of read and write is reversed.	 */	if(_IOC_DIR(cmd) & _IOC_READ)		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd) );	else if (_IOC_DIR(cmd) & _IOC_WRITE)		err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));	if (err) return -EFAULT;	/* synchronize access to the board registers */	spin_lock(&dib->reg_lock);	switch(cmd) {		case PCI550X_IOCRESET: /* board reset */		 if ( (ret = pci550x_adc_reset(dib)) ) break;		 if (dib->pdev->subsystem_device == PCI_SUBSYSTEM_ID_B) {			if ( (ret = pci550x_dac0_reset(dib)) ) break;			ret = pci550x_dac1_reset(dib);		 }		 break;		case PCI550X_IOC_DAC0_RESET: /* DAC0 reset */		 ret = pci550x_dac0_reset(dib);		 break;		case PCI550X_IOC_DAC1_RESET: /* DAC1 reset */		 ret = pci550x_dac1_reset(dib);		 break;		case PCI550X_IOCG_BRD_TYPE: /* query board type */		 ret = __put_user(dib->brd_type, (int *)arg);		 break;		case PCI550X_IOC_ADC_RESET: /* reset ADC subsystem */		 ret = pci550x_adc_reset(dib);		 break;		case PCI550X_IOCS_AD_CCRAM_D: /* download channel list */		 AD_STATUS_R(reg);		 if (reg & AD_STATUS_GATE) {			ret = -EBUSY;			break;		 }		 if ( (err = copy_from_user((void *)&dib->ccram, (void *)arg,			sizeof(adc_ccram) )) ) {				ret = -EFAULT;				break;			}		 if (dib->ccram.elements == 1) {			AD_CCRAM_D_W(dib->ccram.ccram[0], ADC_CCRAM_MAX-1);			AD_SADDR_W(0xffff);			AD_SADDR_WORK_W(0xffff);		 } else if ( (dib->ccram.elements > 1) &&                           (dib->ccram.elements <= ADC_CCRAM_MAX) ) {			for (i = dib->ccram.elements - 1, j = ADC_CCRAM_MAX-1;				i >= 0;  i--, j--)				AD_CCRAM_D_W(dib->ccram.ccram[i], j);			AD_SADDR_W(-dib->ccram.elements);			AD_SADDR_WORK_W(-dib->ccram.elements);		 } else {			ret = -EINVAL;			break;		 }		 AD_CCRAM_I_W;		 break;		case PCI550X_IOCG_AD_CCRAM_D: /* upload channel list */		 if ( (err = copy_to_user((void *)arg, (void *)&dib->ccram,			sizeof(adc_ccram) )) ) {				ret = -EFAULT;				break;			}		 break;		case PCI550X_IOCS_AD_CCRAM_I: /* load the AD_CCRAM_D */		 AD_CCRAM_I_W;		 break;		case PCI550X_IOCG_AD_FIFO: /* read the ADC FIFO */		 AD_STATUS_R(reg);		 if ( (reg & AD_STATUS_FFEN) && (reg & AD_STATUS_FNE) )		 	ret = put_user(AD_FIFO_R, (u_int32_t *)arg);		 else if (reg & AD_STATUS_FFEN)			ret = -EAGAIN;		 else			ret = -EPERM;		 break;		case PCI550X_IOCT_DAC_SELECT:	/* select DAC channel */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B) {			ret = -ENODEV;			break;		 }		 switch(arg) {			case PCI550X_DAC0:				dib->dac_select = PCI550X_DAC0;				break;			case PCI550X_DAC1:				dib->dac_select = PCI550X_DAC1;				break;			default:				ret = -EINVAL;				break;		}		break;		case PCI550X_IOCQ_DAC_SELECT:	/* Query selected DAC */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B)			ret = -ENODEV;		 else			ret = dib->dac_select;		 break;		case PCI550X_IOCQ_INT_STATUS: /* latest interrupt status */		 ret = dib->int_status;		 break;		case PCI550X_IOCQ_ADC_STATUS: /* latest ADC status */		 ret = dib->adc_status;		 break;		case PCI550X_IOCQ_DAC0_STATUS: /* latest DAC0 status */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B)			ret = -ENODEV;		 else			ret = dib->dac0_status;		 break;		case PCI550X_IOCQ_DAC1_STATUS: /* latest DAC1 status */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B)			ret = -ENODEV;		 else			ret = dib->dac1_status;		 break;		case PCI550X_IOCS_TMR0_LOAD: /* Load TIMER 0 */		 TMR0_CTRL_R(reg);		 if (reg & TMR0_CTRL_ENA) {			ret = -EBUSY;			break;		 }		 ret = get_user(reg, (u_int32_t *)arg);		 if (!ret) {		 	if ( (reg > 131070) || (reg < 2) || (reg % 2) ) {				ret = -EINVAL;				break;			}		 TMR0_WORK_W((65536 - (reg >> 1)));		 TMR0_W((65536 - (reg >> 1)));		 }		 break;		case PCI550X_IOCG_TMR0_POLL:	/* Poll Timer 0 */		 TMR0_CTRL_R(reg);		 if (reg & TMR0_CTRL_ENA) {		 	TMR0_WORK_POLL(reg);			ret = put_user(reg, (int *)arg);		 } else			ret = -EAGAIN;		 break;		case PCI550X_IOCS_TMR1_LOAD: /* Load TIMER 1 */		 TMR1_CTRL_R(reg);		 if (reg & TMR1_CTRL_ENA) {			ret = -EBUSY;			break;		 }		 ret = get_user(reg, (u_int32_t *)arg);		 if (!ret) {		 	if ( (reg > 131070) || (reg < 2) || (reg % 2) ) {				ret = -EINVAL;				break;			}		 TMR1_WORK_W((65536 - (reg >> 1)));		 TMR1_W((65536 - (reg >> 1)));		 }		 break;		case PCI550X_IOCG_TMR1_POLL:	/* Poll Timer 1 */		 TMR1_CTRL_R(reg);		 if (reg & TMR1_CTRL_ENA) {		 	TMR1_WORK_POLL(reg);			ret = put_user(reg, (int *)arg);		 } else			ret = -EAGAIN;		 break;		case PCI550X_IOCS_CNTR0_LOAD: /* Load Counter 0 */		 CNTR0_CTRL_R(reg);		 if (reg & CNTR0_CTRL_ENA) {			ret = -EBUSY;			break;		 }		 ret = get_user(reg, (u_int32_t *)arg);		 if (!ret) {		 	if (reg > 65535) {				ret = -EINVAL;				break;			}		 CNTR0_WORK_W(reg);		 CNTR0_W(reg);		 }		 break;		case PCI550X_IOCG_CNTR0_POLL:	/* Poll Counter 0 */		 CNTR0_CTRL_R(reg);		 if (reg & CNTR0_CTRL_ENA) {		 	CNTR0_WORK_POLL(reg);			ret = put_user(reg, (int *)arg);		 	CNTR0_CTRL_W(reg & CNT0);		 } else			ret = -EAGAIN;		 break;		case PCI550X_IOCS_CNTR1_LOAD: /* Load Counter 1 */		 CNTR1_CTRL_R(reg);		 if (reg & CNTR1_CTRL_ENA) {			ret = -EBUSY;			break;		 }		 ret = get_user(reg, (u_int32_t *)arg);		 if (!ret) {		 	if (reg > 65535)  {				ret = -EINVAL;				break;			}		 CNTR1_WORK_W(reg);		 CNTR1_W(reg);		 }		 break;		case PCI550X_IOCG_CNTR1_POLL:	/* Poll Counter 1 */		 CNTR1_CTRL_R(reg);		 if (reg & CNTR1_CTRL_ENA) {		 	CNTR1_WORK_POLL(reg);			ret = put_user(reg, (int *)arg);		 	CNTR1_CTRL_W(reg & CNT1);		 } else			ret = -EAGAIN;		 break;		case PCI550X_IOCS_DA0_FIFO: /* write the DAC0 FIFO */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B) {			ret = -ENODEV;			break;		 }		 DA0_STATUS_R(reg);		 if ((reg & DA0_STATUS_FFEN) && (!(reg & DA0_STATUS_FF)) ) {		 	ret = get_user(reg, (u_int32_t *)arg);		 	if (!ret) DA0_FIFO_W(reg);		 } else if (reg & DA0_STATUS_FFEN)			ret = -EAGAIN;		 else			ret = -EPERM;		 break;		case PCI550X_IOCS_DA1_FIFO: /* write the DAC1 FIFO */		 if (dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B) {			ret = -ENODEV;			break;		 }		 DA1_STATUS_R(reg);		 if ((reg & DA1_STATUS_FFEN) && (!(reg & DA1_STATUS_FF)) ) {		 	ret = get_user(reg, (u_int32_t *)arg);		 	if (!ret) DA1_FIFO_W(reg);		 } else if (reg & DA1_STATUS_FFEN)			ret = -EAGAIN;		 else			ret = -EPERM;		 break;		case PCI550X_IOCS_DIO_0: /* DIO Port 0 Output */		 DIO_CTRL_R(reg);		 if (reg & DIO_CTRL_DDC0) {			ret = get_user(reg, (u_int32_t *)arg);			if (!ret) DIO_0_W(reg);		 } else

⌨️ 快捷键说明

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