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

📄 das16.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(devpriv->timer_running)		mod_timer(&devpriv->timer, jiffies + timer_period);}static void das16_interrupt( comedi_device *dev ){	unsigned long dma_flags, spin_flags;	comedi_subdevice *s = dev->read_subdev;	comedi_async *async;	comedi_cmd *cmd;	int num_bytes, residue;	int buffer_index;	if(dev->attached == 0)	{		comedi_error(dev, "premature interrupt");		return;	}	// initialize async here to make sure it is not NULL	async = s->async;	cmd = &async->cmd;	if( devpriv->dma_chan == 0 )	{		comedi_error(dev, "interrupt with no dma channel?");		return;	}	comedi_spin_lock_irqsave( &dev->spinlock, spin_flags );	if( ( devpriv->control_state & DMA_ENABLE ) == 0 )	{		comedi_spin_unlock_irqrestore( &dev->spinlock, spin_flags );		DEBUG_PRINT( "interrupt while dma disabled?\n" );		return;	}	dma_flags = claim_dma_lock();	disable_dma(devpriv->dma_chan);	/* clear flip-flop to make sure 2-byte registers for	 * count and address get set correctly */	clear_dma_ff(devpriv->dma_chan);	// figure out how many points to read	/* residue is the number of bytes left to be done on the dma	 * transfer.	 */	residue = get_dma_residue(devpriv->dma_chan);	if(residue > devpriv->dma_transfer_size)	{		comedi_error(dev, "residue > transfer size!\n");		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;		num_bytes = 0;	}else		num_bytes = devpriv->dma_transfer_size - residue;	if(cmd->stop_src == TRIG_COUNT &&		num_bytes > devpriv->adc_byte_count)	{		num_bytes = devpriv->adc_byte_count;		async->events |= COMEDI_CB_EOA;	}	buffer_index = devpriv->current_buffer;	devpriv->current_buffer = ( devpriv->current_buffer + 1 ) % 2;	devpriv->adc_byte_count -= num_bytes;	// figure out how many bytes for next transfer	if(cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&		devpriv->dma_transfer_size > devpriv->adc_byte_count )		devpriv->dma_transfer_size = devpriv->adc_byte_count;	// re-enable  dma	if(( async->events & COMEDI_CB_EOA ) == 0)	{		set_dma_addr( devpriv->dma_chan,			devpriv->dma_buffer_addr[ devpriv->current_buffer ] );		set_dma_count( devpriv->dma_chan, devpriv->dma_transfer_size );		enable_dma(devpriv->dma_chan);	}	release_dma_lock(dma_flags);	comedi_spin_unlock_irqrestore( &dev->spinlock, spin_flags );	das16_write_array_to_buffer( dev,		devpriv->dma_buffer[ buffer_index ], num_bytes );	cfc_handle_events( dev, s );}static unsigned int das16_set_pacer(comedi_device *dev, unsigned int ns, int rounding_flags){	i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),		&(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK);	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */	i8254_load(dev->iobase + DAS16_CNTR0_DATA, 1, devpriv->divisor1, 2);	i8254_load(dev->iobase + DAS16_CNTR0_DATA, 2, devpriv->divisor2, 2);	return ns;}static void reg_dump(comedi_device *dev){	DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");	DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase+DAS16_MUX) );	DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase+DAS16_DIO) );	DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase+DAS16_STATUS) );	DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase+DAS16_CONTROL) );	DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase+DAS16_PACER) );	DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase+DAS16_GAIN) );	DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n", inb(dev->iobase+DAS16_CNTR_CONTROL) );	DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase+DAS1600_CONV) );	DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase+DAS1600_BURST) );	DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase+DAS1600_ENABLE) );	DEBUG_PRINT("DAS1600_STATUS_B: %x\n", inb(dev->iobase+DAS1600_STATUS_B) );}static int das16_probe(comedi_device *dev, comedi_devconfig *it){	int status;	int diobits;	/* status is available on all boards */	status = inb(dev->iobase + DAS16_STATUS);	if((status & UNIPOLAR)){		devpriv->ai_unipolar = 1;	}else{		devpriv->ai_unipolar = 0;	}	if((status & DAS16_MUXBIT)){		devpriv->ai_singleended = 1;	}else{		devpriv->ai_singleended = 0;	}	/* diobits indicates boards */	diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;	printk(" id bits are 0x%02x\n",diobits);	if(thisboard->id != diobits)	{		printk(" requested board's id bits are 0x%x\n", thisboard->id);		return -1;	}	return 0;}static int das1600_mode_detect(comedi_device *dev){	int status=0;	status = inb(dev->iobase + DAS1600_STATUS_B);	if(status & DAS1600_CLK_10MHZ) {		devpriv->clockbase = 100;		printk(" 10MHz pacer clock\n");	} else {		devpriv->clockbase = 1000;		printk(" 1MHz pacer clock\n");	}	reg_dump(dev);	return 0;}/* * * Options list: *   0  I/O base *   1  IRQ *   2  DMA *   3  Clock speed (in MHz) */static int das16_attach(comedi_device *dev, comedi_devconfig *it){	comedi_subdevice *s;	int ret, irq;	int iobase;	int dma_chan;	int timer_mode;	unsigned long flags;	comedi_krange *user_ai_range, *user_ao_range;	iobase = it->options[0];	irq = it->options[1];	timer_mode = it->options[8];	if( timer_mode ) irq = 0;		printk("comedi%d: das16:",dev->minor);	// check that clock setting is valid	if(it->options[3])	{		if(it->options[3] != 0 &&			it->options[3] != 1 &&			it->options[3] != 10)		{			printk("\n Invalid option.  Master clock must be set to 1 or 10 (MHz)\n");			return -EINVAL;		}	}	if((ret=alloc_private(dev,sizeof(struct das16_private_struct)))<0)		return ret;	if(thisboard->size<0x400){		printk(" 0x%04x-0x%04x\n", iobase, iobase+thisboard->size);		if(check_region(iobase,thisboard->size)<0){			printk(" I/O port conflict\n");			return -EIO;		}	}else{		printk(" 0x%04x-0x%04x 0x%04x-0x%04x\n",			   iobase,iobase+0x0f,			   iobase+0x400,iobase+0x400+(thisboard->size&0x3ff));		if(check_region(iobase,0x10) < 0) {			printk(" I/O port conflict:  0x%04x-0x%04x\n",				   iobase,iobase+0x0f);			return -EIO;		}		if(check_region(iobase+0x400,thisboard->size&0x3ff)<0){			printk(" I/O port conflict:  0x%04x-0x%04x\n",				   iobase+0x400,				   iobase+0x400+(thisboard->size&0x3ff));			return -EIO;		}	}	if(thisboard->size < 0x400){		request_region(iobase,thisboard->size,"das16");	}else{		request_region(iobase,0x10,"das16");		request_region(iobase+0x400,thisboard->size&0x3ff,"das16");	}	dev->iobase = iobase;	// probe id bits to make sure they are consistent	if(das16_probe(dev, it))	{		printk(" id bits do not match selected board, aborting\n");		return -EINVAL;	}	dev->board_name = thisboard->name;	// get master clock speed	if(thisboard->size < 0x400)	{		if(it->options[3])			devpriv->clockbase = 1000 / it->options[3];		else			devpriv->clockbase = 1000;	// 1 MHz default	}else	{		das1600_mode_detect(dev);	}	/* now for the irq */	if( irq > 1 && irq < 8 )	{		if((ret=comedi_request_irq(irq, das16_dma_interrupt, 0, "das16",dev)) < 0)			return ret;		dev->irq = irq;		printk(" ( irq = %d )",irq);	}else if(irq == 0){		printk(" ( no irq )");	}else	{		printk(" invalid irq\n");		return -EINVAL;	}	// initialize dma	dma_chan = it->options[2];	if(dma_chan == 1 || dma_chan == 3)	{		// allocate dma buffers		int i;		for( i = 0; i < 2; i++)		{			devpriv->dma_buffer[i] = pci_alloc_consistent( NULL,				DAS16_DMA_SIZE, &devpriv->dma_buffer_addr[i] );			if( devpriv->dma_buffer[i] == NULL )				return -ENOMEM;		}		if(request_dma(dma_chan, "das16"))		{			printk(" failed to allocate dma channel %i\n", dma_chan);			return -EINVAL;		}		devpriv->dma_chan = dma_chan;		flags = claim_dma_lock();		disable_dma(devpriv->dma_chan);		set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);		release_dma_lock(flags);		printk(" ( dma = %d)\n", dma_chan);	}else if(dma_chan == 0){		printk(" ( no dma )\n");	}else	{		printk(" invalid dma channel\n");		return -EINVAL;	}	// get any user-defined input range	if(thisboard->ai_pg == das16_pg_none &&		(it->options[4] || it->options[5]))	{		// allocate single-range range table		devpriv->user_ai_range_table =			kmalloc(sizeof(comedi_lrange) + sizeof(comedi_krange), GFP_KERNEL);		// initialize ai range		devpriv->user_ai_range_table->length = 1;		user_ai_range = devpriv->user_ai_range_table->range;		user_ai_range->min = it->options[4];		user_ai_range->max = it->options[5];		user_ai_range->flags = UNIT_volt;	}	// get any user-defined output range	if(it->options[6] || it->options[7])	{		// allocate single-range range table		devpriv->user_ao_range_table =			kmalloc(sizeof(comedi_lrange) + sizeof(comedi_krange), GFP_KERNEL);		// initialize ao range		devpriv->user_ao_range_table->length = 1;		user_ao_range = devpriv->user_ao_range_table->range;		user_ao_range->min = it->options[6];		user_ao_range->max = it->options[7];		user_ao_range->flags = UNIT_volt;	}	if(timer_mode)	{		init_timer(&(devpriv->timer));		devpriv->timer.function = das16_timer_interrupt;		devpriv->timer.data = (unsigned long) dev;		devpriv->timer_mode = timer_mode ? 1 : 0;	}	if((ret=alloc_subdevices(dev, 5))<0)		return ret;	s=dev->subdevices+0;	dev->read_subdev=s;	/* ai */	if(thisboard->ai){		s->type = COMEDI_SUBD_AI;		s->subdev_flags = SDF_READABLE;		if(devpriv->ai_singleended){			s->n_chan = 16;			s->len_chanlist = 16;			s->subdev_flags |= SDF_GROUND;		}else{			s->n_chan = 8;			s->len_chanlist = 8;			s->subdev_flags |= SDF_DIFF;		}		s->maxdata = (1 << thisboard->ai_nbits) - 1;		if(devpriv->user_ai_range_table)		{	// user defined ai range			s->range_table = devpriv->user_ai_range_table;		}else if(devpriv->ai_unipolar){			s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];		}else{			s->range_table = das16_ai_bip_lranges[thisboard->ai_pg];		}		s->insn_read = thisboard->ai;		s->do_cmdtest = das16_cmd_test;		s->do_cmd = das16_cmd_exec;		s->cancel = das16_cancel;	}else{		s->type=COMEDI_SUBD_UNUSED;	}	s = dev->subdevices + 1;	/* ao */	if(thisboard->ao){		s->type = COMEDI_SUBD_AO;		s->subdev_flags = SDF_WRITABLE;		s->n_chan = 2;		s->maxdata = (1 << thisboard->ao_nbits) - 1;		if(devpriv->user_ao_range_table)		{	// user defined ao range			s->range_table = devpriv->user_ao_range_table;		}else		{			s->range_table = &range_unknown;		}		s->insn_write = thisboard->ao;	}else{		s->type = COMEDI_SUBD_UNUSED;	}	s = dev->subdevices + 2;	/* di */	if(thisboard->di){		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 = thisboard->di;	}else{		s->type = COMEDI_SUBD_UNUSED;	}	s = dev->subdevices + 3;	/* do */	if(thisboard->do_){		s->type = COMEDI_SUBD_DO;		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;		s->n_chan = 4;		s->maxdata = 1;		s->range_table = &range_digital;		s->insn_bits = thisboard->do_;		// initialize digital output lines		outb(s->state, dev->iobase + DAS16_DIO);	}else{		s->type = COMEDI_SUBD_UNUSED;	}	s = dev->subdevices + 4;	/* 8255 */	if(thisboard->i8255_offset!=0){		subdev_8255_init(dev,s,NULL,(unsigned long)(dev->iobase+			thisboard->i8255_offset));	}else{		s->type = COMEDI_SUBD_UNUSED;	}	das16_reset(dev);	/* set the interrupt level */	devpriv->control_state = DAS16_IRQ(dev->irq);	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);	// turn on das1600 mode if available	if(thisboard->size > 0x400)	{		outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);		outb(0, dev->iobase + DAS1600_CONV);		outb(0, dev->iobase + DAS1600_BURST);	}	return 0;}static int das16_detach(comedi_device *dev){	printk("comedi%d: das16: remove\n", dev->minor);	das16_reset(dev);	if(dev->subdevices)		subdev_8255_cleanup(dev,dev->subdevices+4);	if(devpriv)	{		int i;		for( i = 0; i < 2; i++ )		{			if( devpriv->dma_buffer[i] )				pci_free_consistent( NULL, DAS16_DMA_SIZE, devpriv->dma_buffer[i],					devpriv->dma_buffer_addr[i] );		}		if(devpriv->dma_chan)			free_dma(devpriv->dma_chan);		if(devpriv->user_ai_range_table)			kfree(devpriv->user_ai_range_table);		if(devpriv->user_ao_range_table)			kfree(devpriv->user_ao_range_table);	}	if(dev->irq)		comedi_free_irq(dev->irq, dev);	if( dev->iobase )	{		if(thisboard->size < 0x400){			release_region(dev->iobase, thisboard->size);		}else{			release_region(dev->iobase, 0x10);			release_region(dev->iobase + 0x400, thisboard->size&0x3ff);		}	}	return 0;}COMEDI_INITCLEANUP(driver_das16);// utility function that suggests a dma transfer size in bytesstatic unsigned int das16_suggest_transfer_size(comedi_device *dev, comedi_cmd cmd){	unsigned int size;	unsigned int freq;	/* if we are using timer interrupt, we don't care how long it	 * will take to complete transfer since it will be interrupted	 * by timer interrupt */	if(devpriv->timer_mode) return DAS16_DMA_SIZE;	/* otherwise, we are relying on dma terminal count interrupt,	 * so pick a reasonable size */	if(cmd.convert_src == TRIG_TIMER)		freq = 1000000000 / cmd.convert_arg;	else if(cmd.scan_begin_src == TRIG_TIMER)		freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;	// return some default value	else		freq = 0xffffffff;	if(cmd.flags & TRIG_WAKE_EOS)	{		size = sample_size * cmd.chanlist_len;	}else	{		// make buffer fill in no more than 1/3 second		size = (freq / 3) * sample_size;	}	// set a minimum and maximum size allowed	if(size > DAS16_DMA_SIZE)		size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;	else if(size < sample_size)		size = sample_size;	if( cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count )		size = devpriv->adc_byte_count;		return size;}static void init_munge_info( struct munge_info *info ){	info->have_byte = 0;}/* we want to be able to write one byte at a time to buffer to deal with * possibility that 8-bit dma transfer will be interrupted inbetween * least significant and most significant byte of a sample */static void write_byte_to_buffer( comedi_device *dev, comedi_subdevice *subd, uint8_t raw_byte ){	sampl_t data;	struct munge_info *info = &devpriv->ai_munge_info;	if( info->have_byte == 0 )	{		info->byte = raw_byte;		info->have_byte = 1;	}else	{		info->have_byte = 0;		if( thisboard->ai_nbits == 12 )		{			data = ( raw_byte << 4 ) & 0xff0;			data |= ( info->byte >> 4 ) & 0xf;		}else		{			data = ( raw_byte << 8 ) & 0xff00;			data |= info->byte & 0xff;		}		cfc_write_to_buffer( subd, data );	}}static void das16_write_array_to_buffer( comedi_device *dev, void *data, unsigned int num_bytes ){	unsigned int i;	uint8_t *array = data;	for( i = 0; i < num_bytes; i++ )		write_byte_to_buffer( dev, dev->read_subdev, array[i] );};

⌨️ 快捷键说明

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