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

📄 das1800.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		common:	1,		do_n_chan:	4,		ao_ability:	2,		ao_n_chan:	2,		range_ai:	&range_ai_das1802,	},};/* * Useful for shorthand access to the particular board structure */#define thisboard ((das1800_board *)dev->board_ptr)typedef struct{	volatile unsigned int count;  /* number of data points left to be taken */	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */	unsigned int divisor2; 	/* value to load into board's counter 2 for timed conversions */	int do_bits;	/* digital output bits */	int irq_dma_bits;	/* bits for control register b */	/* dma bits for control register b, stored so that dma can be	 * turned on and off */	int dma_bits;	unsigned int dma0;	/* dma channels used */	unsigned int dma1;	volatile unsigned int dma_current;	/* dma channel currently in use */	uint16_t *ai_buf0;	/* pointers to dma buffers */	uint16_t *ai_buf1;	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */	int iobase2;	/* secondary io address used for analog out on 'ao' boards */	short ao_update_bits; /* remembers the last write to the 'update' dac */}das1800_private;#define devpriv ((das1800_private *)dev->private)// analog out range for boards with basic analog outstatic comedi_lrange range_ao_1 = {	1,	{		RANGE(-10, 10),	}};// analog out range for 'ao' boards/*static comedi_lrange range_ao_2 = {	2,	{		RANGE(-10, 10),		RANGE(-5, 5),	}};*/static comedi_driver driver_das1800={	driver_name:	"das1800",	module:		THIS_MODULE,	attach:		das1800_attach,	detach:		das1800_detach,	num_names:	sizeof(das1800_boards) / sizeof(das1800_board),	board_name:	das1800_boards,	offset:		sizeof(das1800_board),};/* * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */COMEDI_INITCLEANUP(driver_das1800);static int das1800_init_dma( comedi_device *dev, unsigned int dma0, unsigned int dma1 ){	unsigned long flags;		// need an irq to do dma	if( dev->irq && dma0 )	{		//encode dma0 and dma1 into 2 digit hexadecimal for switch		switch((dma0 & 0x7) | (dma1 << 4))		{			case 0x5:	// dma0 == 5				devpriv->dma_bits |= DMA_CH5;				break;			case 0x6:	// dma0 == 6				devpriv->dma_bits |= DMA_CH6;				break;			case 0x7:	// dma0 == 7				devpriv->dma_bits |= DMA_CH7;				break;			case 0x65:	// dma0 == 5, dma1 == 6				devpriv->dma_bits |= DMA_CH5_CH6;				break;			case 0x76:	// dma0 == 6, dma1 == 7				devpriv->dma_bits |= DMA_CH6_CH7;				break;			case 0x57:	// dma0 == 7, dma1 == 5				devpriv->dma_bits |= DMA_CH7_CH5;				break;			default:				printk(" only supports dma channels 5 through 7\n"					" Dual dma only allows the following combinations:\n"					" dma 5,6 / 6,7 / or 7,5\n");				return -EINVAL;				break;		}		if( request_dma( dma0, driver_das1800.driver_name ) )		{			printk( " failed to allocate dma channel %i\n", dma0 );			return -EINVAL;		}		devpriv->dma0 = dma0;		devpriv->dma_current = dma0;		if( dma1 )		{			if( request_dma( dma1, driver_das1800.driver_name ) )			{				printk( " failed to allocate dma channel %i\n", dma1 );				return -EINVAL;			}			devpriv->dma1 = dma1;		}		devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);		if(devpriv->ai_buf0 == NULL)			return -ENOMEM;		devpriv->dma_current_buf = devpriv->ai_buf0;		if( dma1 )		{			devpriv->ai_buf1 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);			if(devpriv->ai_buf1 == NULL)				return -ENOMEM;		}		flags = claim_dma_lock();		disable_dma(devpriv->dma0);		set_dma_mode(devpriv->dma0, DMA_MODE_READ);		if( dma1 )		{			disable_dma(devpriv->dma1);			set_dma_mode(devpriv->dma1, DMA_MODE_READ);		}		release_dma_lock(flags);	}	return 0;}static int das1800_attach(comedi_device *dev, comedi_devconfig *it){	comedi_subdevice *s;	int iobase = it->options[0];	int irq = it->options[1];	int dma0 = it->options[2];	int dma1 = it->options[3];	int iobase2;	int board;	int retval;	/* allocate and initialize dev->private */	if(alloc_private(dev, sizeof(das1800_private)) < 0)		return -ENOMEM;	printk("comedi%d: %s: io 0x%x", dev->minor, driver_das1800.driver_name, iobase);	if(irq)	{		printk(", irq %i", irq);		if(dma0)		{			printk(", dma %i", dma0);			if(dma1) printk(" and %i", dma1);		}	}	printk("\n");	if(iobase == 0)	{		printk(" io base address required\n");		return -EINVAL;	}	/* check if io addresses are available */	if(check_region(iobase, DAS1800_SIZE) < 0)	{		printk(" I/O port conflict: failed to allocate ports 0x%x to 0x%x\n",			iobase, iobase + DAS1800_SIZE - 1);		return -EIO;	}	request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name);	dev->iobase = iobase;	board = das1800_probe(dev);	if(board < 0)	{		printk(" unable to determine board type\n");		return -ENODEV;	}	dev->board_ptr = das1800_boards + board;	dev->board_name = thisboard->name;	// if it is an 'ao' board with fancy analog out then we need extra io ports	if(thisboard->ao_ability == 2)	{		iobase2 = iobase + IOBASE2;		if(check_region(iobase2, DAS1800_SIZE) < 0)		{			printk(" I/O port conflict: failed to allocate ports 0x%x to 0x%x\n",				iobase2, iobase2 + DAS1800_SIZE - 1);			return -EIO;		}		request_region(iobase2, DAS1800_SIZE, driver_das1800.driver_name);		devpriv->iobase2 = iobase2;	}	/* grab our IRQ */	if(irq)	{		if(comedi_request_irq( irq, das1800_interrupt, 0, driver_das1800.driver_name, dev ))		{			printk(" unable to allocate irq %d\n", irq);			return -EINVAL;		}	}	dev->irq = irq;	// set bits that tell card which irq to use	switch(irq)	{		case 0:			break;		case 3:			devpriv->irq_dma_bits |= 0x8;			break;		case 5:			devpriv->irq_dma_bits |= 0x10;			break;		case 7:			devpriv->irq_dma_bits |= 0x18;			break;		case 10:			devpriv->irq_dma_bits |= 0x28;			break;		case 11:			devpriv->irq_dma_bits |= 0x30;			break;		case 15:			devpriv->irq_dma_bits |= 0x38;			break;		default:			printk(" irq out of range\n");			return -EINVAL;			break;	}	retval = das1800_init_dma( dev, dma0, dma1 );	if( retval < 0 ) return retval;	if( devpriv->ai_buf0 == NULL )	{		devpriv->ai_buf0 = kmalloc( FIFO_SIZE * sizeof( uint16_t ), GFP_KERNEL );		if(devpriv->ai_buf0 == NULL)			return -ENOMEM;	}	if(alloc_subdevices(dev, 4) < 0)		return -ENOMEM;	/* analog input subdevice */	s = dev->subdevices + 0;	dev->read_subdev = s;	s->type = COMEDI_SUBD_AI;	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;	if(thisboard->common)		s->subdev_flags |= SDF_COMMON;	s->n_chan = thisboard->qram_len;	s->len_chanlist = thisboard->qram_len;	s->maxdata = (1 << thisboard->resolution) - 1;	s->range_table = thisboard->range_ai;	s->do_cmd = das1800_ai_do_cmd;	s->do_cmdtest = das1800_ai_do_cmdtest;	s->insn_read = das1800_ai_rinsn;	s->poll = das1800_ai_poll;	s->cancel = das1800_cancel;	/* analog out */	s = dev->subdevices + 1;	if(thisboard->ao_ability == 1)	{		s->type = COMEDI_SUBD_AO;		s->subdev_flags = SDF_WRITABLE;		s->n_chan = thisboard->ao_n_chan;		s->maxdata = (1 << thisboard->resolution) - 1;		s->range_table = &range_ao_1;		s->insn_write = das1800_ao_winsn;	}	else	{		s->type = COMEDI_SUBD_UNUSED;	}	/* di */	s = dev->subdevices + 2;	s->type = COMEDI_SUBD_DI;	s->subdev_flags = SDF_READABLE;	s->n_chan = 4;	s->maxdata = 1;	s->range_table = &range_digital;	s->insn_bits = das1800_di_rbits;	/* do */	s = dev->subdevices + 3;	s->type = COMEDI_SUBD_DO;	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;	s->n_chan = thisboard->do_n_chan;	s->maxdata = 1;	s->range_table = &range_digital;	s->insn_bits = das1800_do_wbits;	das1800_cancel(dev, dev->read_subdev);	// initialize digital out channels	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);	// initialize analog out channels	if(thisboard->ao_ability == 1)	{		// select 'update' dac channel for baseAddress + 0x0		outb(DAC(thisboard->ao_n_chan - 1), dev->iobase + DAS1800_SELECT);		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);	}	return 0;};static int das1800_detach(comedi_device *dev){	/* only free stuff if it has been allocated by _attach */	if(dev->iobase)		release_region(dev->iobase, DAS1800_SIZE);	if(dev->irq)		comedi_free_irq(dev->irq, dev);	if(dev->private)	{		if(devpriv->iobase2)			release_region(devpriv->iobase2, DAS1800_SIZE);		if(devpriv->dma0)			free_dma(devpriv->dma0);		if(devpriv->dma1)			free_dma(devpriv->dma1);		if(devpriv->ai_buf0)			kfree(devpriv->ai_buf0);		if(devpriv->ai_buf1)			kfree(devpriv->ai_buf1);	}	printk("comedi%d: %s: remove\n", dev->minor, driver_das1800.driver_name);	return 0;};/* probes and checks das-1800 series board type */static int das1800_probe(comedi_device *dev){	int id;	int board;	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */	board = ((das1800_board *)dev->board_ptr) - das1800_boards;	switch(id)	{		case 0x3:			if(board == das1801st_da || board == das1802st_da ||				board == das1701st_da || board == das1702st_da)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1800st-da series\n");			return das1801st;			break;		case 0x4:			if(board == das1802hr_da || board == das1702hr_da)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1802hr-da\n");			return das1802hr;			break;		case 0x5:			if(board == das1801ao || board == das1802ao ||				board == das1701ao || board == das1702ao)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1800ao series\n");			return das1801ao;			break;		case 0x6:			if(board == das1802hr || board == das1702hr)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1802hr\n");			return das1802hr;			break;		case 0x7:			if(board == das1801st || board == das1802st ||				board == das1701st || board == das1702st)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1800st series\n");			return das1801st;			break;		case 0x8:			if(board == das1801hc || board == das1802hc)			{				printk(" Board model: %s\n", das1800_boards[board].name);				return board;			}			printk(" Board model (probed, not recommended): das-1800hc series\n");			return das1801hc;			break;		default :			printk(" Board model: probe returned 0x%x (unknown, please report)\n", id);			return board;			break;	}	return -1;}static int das1800_ai_poll(comedi_device *dev,comedi_subdevice *s){	unsigned long flags;	// prevent race with interrupt handler	comedi_spin_lock_irqsave(&dev->spinlock, flags);	das1800_ai_handler(dev);	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);

⌨️ 快捷键说明

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