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

📄 pci550x.c

📁 linux下面
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ADAC/5500 Series Device Driver */#include <linux/module.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <linux/proc_fs.h>#include "pci550x.h"MODULE_AUTHOR("Boca Microsystems Incorporated");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("ADAC/5500 Series Device Driver");#ifndef CONFIG_PCI#error "This driver requires that PCI support be configured in the Kernel"#endif/* GLOBAL DATA */static struct file_operations pci550x_fops = {        owner:          THIS_MODULE,        read:           pci550x_read,        readv:          pci550x_readv,        write:          pci550x_write,        writev:         pci550x_writev,        ioctl:          pci550x_ioctl,        open:           pci550x_open,        release:        pci550x_release,};static const char *driver_name = "pci550x";static unsigned int pci550x_major = PCI550X_MAJOR;static unsigned int minor = 0;#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *pci550x_proc_dir_entry = NULL;static const char* proc_dir_entry = "driver/pci550x";#endifunion { u_int32_t bus_addressf; u_int16_t bus_addressh[2];} dma;/* * pci550x_interrupt - interrupt handler  */void pci550x_interrupt(int irq, void *dev_id, struct pt_regs *regs) {	pci550x_dib *dib;	pci550x_hwregs *REGS;	u_int32_t int_status;	/* if it's not our interrupt,...ignore it */	dib = (pci550x_dib *)dev_id;	REGS = (pci550x_hwregs *)dib->membase;	INT_STATUS_R(int_status);	if (!(int_status & INTMASK)) return;	/* process ADC interrupt */	if ( (dib->int_status = int_status) & INT_STATUS_ADINT) {		AD_STATUS_R(dib->adc_status);		if (dib->adc_status & AD_STATUS_ERROR) {			if (dib->adc_status & AD_STATUS_MERR0)				dib->adc_stats.merr0++;			else if (dib->adc_status & AD_STATUS_MERR1)				dib->adc_stats.merr1++;			else if (dib->adc_status & AD_STATUS_FOVR)				dib->adc_stats.fovr++;			else if (dib->adc_status & AD_STATUS_FUNDR)				dib->adc_stats.fundr++;			else if (dib->adc_status & AD_STATUS_CERR)				dib->adc_stats.cerr++;			else if (dib->adc_status & AD_STATUS_BERR)				dib->adc_stats.berr++;			AD_STATUS_W(dib->adc_status);		}		if (!(list_empty(&dib->adc_wq.task_list))) {			wake_up_interruptible_sync(&dib->adc_wq);		}	}	/* process DAC0 interrupt */	if ((dib->int_status = int_status) & INT_STATUS_DA0INT) {		DA0_STATUS_R(dib->dac0_status);		if (dib->dac0_status & DA0_STATUS_ERROR) {			if (dib->dac0_status & DA0_STATUS_MERR0)				dib->dac0_stats.merr0++;			else if (dib->dac0_status & DA0_STATUS_MERR1)				dib->dac0_stats.merr1++;			else if (dib->dac0_status & DA0_STATUS_FOVR)				dib->dac0_stats.fovr++;			else if (dib->adc_status & DA0_STATUS_DERR)				dib->dac0_stats.derr++;			else if (dib->dac0_status & DA0_STATUS_CERR)				dib->adc_stats.cerr++;			DA0_STATUS_W(dib->dac0_status);		}		if (!(list_empty(&dib->dac0_wq.task_list))) {			wake_up_interruptible_sync(&dib->dac0_wq);		}	}	/* process DAC1 interrupt */	if ((dib->int_status = int_status) & INT_STATUS_DA1INT) {		DA1_STATUS_R(dib->dac1_status);		if (dib->dac1_status & DA1_STATUS_ERROR) {			if (dib->dac1_status & DA1_STATUS_MERR0)				dib->dac1_stats.merr0++;			else if (dib->dac1_status & DA1_STATUS_MERR1)				dib->dac1_stats.merr1++;			else if (dib->dac1_status & DA1_STATUS_FOVR)				dib->dac1_stats.fovr++;			else if (dib->adc_status & DA1_STATUS_DERR)				dib->dac1_stats.derr++;			else if (dib->dac1_status & DA1_STATUS_CERR)				dib->adc_stats.cerr++;			DA1_STATUS_W(dib->dac1_status);		}		if (!(list_empty(&dib->dac1_wq.task_list))) {			wake_up_interruptible_sync(&dib->dac1_wq);		}	}	/* reset the interrupt */	INT_STATUS_W(int_status);}/* * pci550x_open - open method */static int pci550x_open(struct inode* inode, struct file* filp){    struct pci_dev *pdev = NULL;	pci550x_dib *dib;	pci550x_hwregs *REGS;	int ret = 0;	int i;	/* by device minor number */        while( (pdev=pci_find_device(PCI_VENDOR_ID_ADAC, PCI_ANY_ID, pdev))) {		if  ( (dib = (pci550x_dib *)pci_get_drvdata(pdev) ) &&			(MINOR(inode->i_rdev) == dib->minor) ) break;	}	if(!pdev) return(-ENODEV);	REGS = (pci550x_hwregs *)dib->membase;	/* if WRONLY we must have a board with DAC channels */	if (  ((filp->f_flags & O_ACCMODE) == O_WRONLY) &&		(dib->pdev->subsystem_device != PCI_SUBSYSTEM_ID_B) ) {			return(-ENODEV);	}	/* open access control - SMP safe */	if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {		spin_lock(&dib->adc_lock);		if (dib->adc_opened) {			spin_unlock(&dib->adc_lock);			return(-EBUSY);	/* already opened */		}		dib->adc_opened++;		spin_unlock(&dib->adc_lock);	} else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {		spin_lock(&dib->dac_lock);		if (dib->dac_opened) {			spin_unlock(&dib->dac_lock);			return(-EBUSY);	/* already opened */		}		dib->dac_opened++;		spin_unlock(&dib->dac_lock);	}	/* calculate page order for ADC DMA buffer allocation */	if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {		if (PCI550X_DMA_PAGES == 1)			dib->adc_dma_page_order = 0;		else {			dib->adc_dma_page_order = 1;			for (i = 2; i < PCI550X_DMA_PAGES;				i*=2, dib->adc_dma_page_order++);		}		/* allocate ADC DMA buffers */		dib->adc_dma_buf0 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->adc_dma_page_order);		if (!dib->adc_dma_buf0) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			dib->adc_opened--;			return(-ENOMEM);		}		dib->adc_dma_buf1 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->adc_dma_page_order);		if (!dib->adc_dma_buf1) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			free_pages((unsigned long)dib->adc_dma_buf0,				dib->adc_dma_page_order);			dib->adc_dma_buf0 = (unsigned long)NULL;			dib->adc_opened--;			return(-ENOMEM);		}		/* setup the streaming DMA mappings */		dib->adc_dma_handle0 = pci_map_single(dib->pdev,			(void *)dib->adc_dma_buf0,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_FROMDEVICE);		if(!(dib->adc_dma_handle0)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			free_pages((unsigned long)dib->adc_dma_buf0,				dib->adc_dma_page_order);			dib->adc_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->adc_dma_buf1,				dib->adc_dma_page_order);			dib->adc_dma_buf1 = (unsigned long)NULL;			dib->adc_opened--;			return(-ENOMEM);		}		dib->adc_dma_handle1 = pci_map_single(dib->pdev,			(void *)dib->adc_dma_buf1,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_FROMDEVICE);		if(!(dib->adc_dma_handle1)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			pci_unmap_single(dib->pdev, dib->adc_dma_handle0,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_FROMDEVICE);			dib->adc_dma_handle0 = (dma_addr_t)NULL;			free_pages((unsigned long)dib->adc_dma_buf0,				dib->adc_dma_page_order);			dib->adc_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->adc_dma_buf1,				dib->adc_dma_page_order);			dib->adc_dma_buf1 = (unsigned long)NULL;			dib->adc_opened--;			return(-ENOMEM);		}		} else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {		if (PCI550X_DMA_PAGES == 1)			dib->dac0_dma_page_order = 0;		else {			dib->dac0_dma_page_order = 1;			for (i = 2; i < PCI550X_DMA_PAGES;				i*=2, dib->dac0_dma_page_order++);		}		/* allocate DAC0 DMA buffers */		dib->dac0_dma_buf0 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->dac0_dma_page_order);		if (!dib->dac0_dma_buf0) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			dib->dac_opened--;			return(-ENOMEM);		}		dib->dac0_dma_buf1 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->dac0_dma_page_order);		if (!dib->dac0_dma_buf1) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			free_pages((unsigned long)dib->dac0_dma_buf0,				dib->dac0_dma_page_order);			dib->dac0_dma_buf0 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}		/* setup the streaming DMA mappings */		dib->dac0_dma_handle0 = pci_map_single(dib->pdev,			(void *)dib->dac0_dma_buf0,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_TODEVICE);		if(!(dib->dac0_dma_handle0)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			free_pages((unsigned long)dib->dac0_dma_buf0,				dib->dac0_dma_page_order);			dib->dac0_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->dac0_dma_buf1,				dib->dac0_dma_page_order);			dib->dac0_dma_buf1 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}		dib->dac0_dma_handle1 = pci_map_single(dib->pdev,			(void *)dib->dac0_dma_buf1,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_TODEVICE);		if(!(dib->dac0_dma_handle1)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			pci_unmap_single(dib->pdev, dib->dac0_dma_handle0,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			dib->dac0_dma_handle0 = (dma_addr_t)NULL;			free_pages((unsigned long)dib->dac0_dma_buf0,				dib->dac0_dma_page_order);			dib->dac0_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->dac0_dma_buf1,				dib->dac0_dma_page_order);			dib->dac0_dma_buf1 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}	/* calculate page order for DAC1 DMA buffer allocation */		if (PCI550X_DMA_PAGES == 1)			dib->dac1_dma_page_order = 0;		else {			dib->dac1_dma_page_order = 1;			for (i = 2; i < PCI550X_DMA_PAGES;				i*=2, dib->dac1_dma_page_order++);		}		/* allocate DAC1 DMA buffers */		dib->dac1_dma_buf0 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->dac1_dma_page_order);		if (!dib->dac1_dma_buf0) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			pci550x_free_dac0_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}		dib->dac1_dma_buf1 =			 (u_int32_t *)__get_free_pages(GFP_KERNEL | __GFP_DMA,				 dib->dac1_dma_page_order);		if (!dib->dac1_dma_buf1) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"__get_free_pages() failure -"				" kernel memory unavailable.\n");			free_pages((unsigned long)dib->dac1_dma_buf0,				dib->dac1_dma_page_order);			dib->dac1_dma_buf0 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			pci550x_free_dac1_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}		/* setup the streaming DMA mappings */		dib->dac1_dma_handle0 = pci_map_single(dib->pdev,			(void *)dib->dac1_dma_buf0,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_TODEVICE);		if(!(dib->dac1_dma_handle0)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			free_pages((unsigned long)dib->dac1_dma_buf0,				dib->dac1_dma_page_order);			dib->dac1_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->dac1_dma_buf1,				dib->dac1_dma_page_order);			dib->dac1_dma_buf1 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			pci550x_free_dac1_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}		dib->dac1_dma_handle1 = pci_map_single(dib->pdev,			(void *)dib->dac1_dma_buf1,			PAGE_SIZE * PCI550X_DMA_PAGES, PCI_DMA_TODEVICE);		if(!(dib->dac1_dma_handle1)) {			printk(KERN_ERR PCI550X_PFX				"In function pci550x_open:\n"				"pci_map_single() failure -"				" DMA mapping failed.\n");			pci_unmap_single(dib->pdev, dib->dac1_dma_handle0,				PAGE_SIZE * PCI550X_DMA_PAGES,				PCI_DMA_TODEVICE);			dib->dac1_dma_handle0 = (dma_addr_t)NULL;			free_pages((unsigned long)dib->dac1_dma_buf0,				dib->dac1_dma_page_order);			dib->dac1_dma_buf0 = (unsigned long)NULL;			free_pages((unsigned long)dib->dac1_dma_buf1,				dib->dac1_dma_page_order);			dib->dac1_dma_buf1 = (unsigned long)NULL;			pci550x_free_dac0_buffs(dib);			pci550x_free_dac1_buffs(dib);			dib->dac_opened--;			return(-ENOMEM);		}	} /* end O_RDONLY/O_WRONLY check */	/* reset the board and request the interrupt on first open */	spin_lock(&dib->open_lock);	if (dib->opened == 0) {		pci550x_adc_reset(dib);		if (dib->pdev->subsystem_device == PCI_SUBSYSTEM_ID_B) {			pci550x_dac0_reset(dib);			pci550x_dac1_reset(dib);		}		ret = request_irq(dib->irq, &pci550x_interrupt,			 SA_SHIRQ | SA_INTERRUPT, driver_name, (void *)dib);		if (ret) {			if (dib->adc_opened) {				pci550x_free_adc_buffs(dib);				dib->adc_opened--;			} else if (dib->dac_opened) {				pci550x_free_dac0_buffs(dib);				pci550x_free_dac1_buffs(dib);				dib->dac_opened--;			}			printk(KERN_ERR PCI550X_PFX "IRQ %d is not free.\n",				dib->irq);			spin_unlock(&dib->open_lock);			return(ret);		}	}	/* init the wait QUEUEs used for blocking I/O */	init_waitqueue_head(&dib->adc_wq);	init_waitqueue_head(&dib->dac0_wq);	init_waitqueue_head(&dib->dac1_wq);	filp->private_data = (void *)dib;	dib->opened++;	spin_unlock(&dib->open_lock);	return(ret);}/* * pci550x_release - release method */static int pci550x_release(struct inode* inode, struct file* filp){	pci550x_dib *dib = (pci550x_dib *)filp->private_data;	/*	 * free the interrupt on final release 	 */	spin_lock(&dib->open_lock);	if (dib->opened == 1)		free_irq(dib->irq, (void *)dib);	/* free DMA buffers */	if (dib->adc_opened) {		pci550x_free_adc_buffs(dib);		dib->adc_opened--;	} else if (dib->dac_opened) {		pci550x_free_dac0_buffs(dib);		pci550x_free_dac1_buffs(dib);		dib->dac_opened--;	}	filp->private_data = NULL;	dib->opened--;	spin_unlock(&dib->open_lock);	return(0);	/* success */}/* * pci550x_read - read method (ADC Ping-Pong DMA) */static ssize_t pci550x_read(struct file* filp, 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;	/* can't read more than one buffer at a time */	if (count > ((dib->adc_dma_bytes) - *offp))		return(-EINVAL);	/* wait for the next ADC buffer */	AD_CTRL_R(dib->adc_ctrl);	if (!(dib->adc_ctrl & AD_CTRL_CVEN))		return(0); /* EOF */	else if ( (dib->adc_status & AD_STATUS_MPRF0) &&		  (dib->adc_status & AD_STATUS_MPRF1) ) {

⌨️ 快捷键说明

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