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

📄 cb_pcimdas.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//	request_mem_region(BADR0, BADR0_SIZE, "cb_pcimdas");//	devpriv->BADR0 = BADR0;	request_region(BADR1, BADR1_SIZE, "cb_pcimdas");	devpriv->BADR1 = BADR1;	request_region(BADR2, BADR2_SIZE, "cb_pcimdas");	devpriv->BADR2 = BADR2;	request_region(BADR3, BADR3_SIZE, "cb_pcimdas");	devpriv->BADR3 = BADR3;	request_region(BADR4, BADR4_SIZE, "cb_pcimdas");	devpriv->BADR4 = BADR4;#ifdef CBPCIMDAS_DEBUG	printk("devpriv->BADR0 = %d\n",devpriv->BADR0);	printk("devpriv->BADR1 = %d\n",devpriv->BADR1);	printk("devpriv->BADR2 = %d\n",devpriv->BADR2);	printk("devpriv->BADR3 = %d\n",devpriv->BADR3);	printk("devpriv->BADR4 = %d\n",devpriv->BADR4);#endif// Dont support IRQ yet//	// get irq//	if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcimdas_interrupt, SA_SHIRQ, "cb_pcimdas", dev ))//	{//		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);//		return -EINVAL;//	}//	dev->irq = devpriv->pci_dev->irq;	//Initialize dev->board_name	dev->board_name = thisboard->name;/* * Allocate the subdevice structures.  alloc_subdevice() is a * convenient macro defined in comedidev.h. */	if(alloc_subdevices(dev, 3)<0)		return -ENOMEM;	s=dev->subdevices+0;	//dev->read_subdev=s;	// analog input subdevice 	s->type=COMEDI_SUBD_AI;	s->subdev_flags=SDF_READABLE|SDF_GROUND;	s->n_chan=thisboard->ai_se_chans;	s->maxdata=(1<<thisboard->ai_bits)-1;	s->range_table=&range_unknown;	s->len_chanlist=1;  // This is the maximum chanlist length that			     //	the board can handle 	s->insn_read = cb_pcimdas_ai_rinsn;	s=dev->subdevices+1;	// analog output subdevice	s->type=COMEDI_SUBD_AO;	s->subdev_flags=SDF_WRITABLE;	s->n_chan=thisboard->ao_nchan;	s->maxdata=1<<thisboard->ao_bits;	s->range_table=&range_unknown; //ranges are hardware settable, but not software readable.	s->insn_write = &cb_pcimdas_ao_winsn;	s->insn_read = &cb_pcimdas_ao_rinsn;	s=dev->subdevices+2;	/* digital i/o subdevice */	if(thisboard->has_dio){		s->type=COMEDI_SUBD_DIO;		s->subdev_flags=SDF_READABLE|SDF_WRITABLE;		s->n_chan=thisboard->dio_bits;		s->maxdata=1;		s->range_table=&range_digital;		s->insn_bits = cb_pcimdas_dio_insn_bits;		s->insn_config = cb_pcimdas_dio_insn_config;	}else{		s->type = COMEDI_SUBD_UNUSED;	}		printk("attached\n");	return 1;}/* * _detach is called to deconfigure a device.  It should deallocate * resources.   * This function is also called when _attach() fails, so it should be * careful not to release resources that were not necessarily * allocated by _attach().  dev->private and dev->subdevices are * deallocated automatically by the core. */static int cb_pcimdas_detach(comedi_device *dev){#ifdef CBPCIMDAS_DEBUG	printk("devpriv->BADR0 = %d\n",devpriv->BADR0);	printk("devpriv->BADR1 = %d\n",devpriv->BADR1);	printk("devpriv->BADR2 = %d\n",devpriv->BADR2);	printk("devpriv->BADR3 = %d\n",devpriv->BADR3);	printk("devpriv->BADR4 = %d\n",devpriv->BADR4);#endif	printk("comedi%d: cb_pcimdas: remove\n",dev->minor);		if(devpriv->BADR0)			release_mem_region(devpriv->BADR0, BADR0_SIZE);		if(devpriv->BADR1)			release_region(devpriv->BADR1, BADR1_SIZE);		if(devpriv->BADR2)			release_region(devpriv->BADR2, BADR2_SIZE);		if(devpriv->BADR3)			release_region(devpriv->BADR3, BADR3_SIZE);		if(devpriv->BADR4)			release_region(devpriv->BADR4, BADR4_SIZE);		if(dev->irq)		comedi_free_irq(dev->irq, dev);	return 0;}/* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. */static int cb_pcimdas_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int n,i;	unsigned int d;	unsigned int busy;	int chan = CR_CHAN(insn->chanspec);	unsigned short chanlims;	int maxchans;	// only support sw initiated reads from a single channel	//check channel number	if ((inb(devpriv->BADR3+2) & 0x20)==0) //differential mode		maxchans=thisboard->ai_diff_chans;	else		maxchans=thisboard->ai_se_chans;	if (chan>(maxchans-1)) 		return -ETIMEDOUT;  //*** Wrong error code. Fixme.	//configure for sw initiated read	d=inb(devpriv->BADR3+5);	if ((d & 0x03)>0) { 			//only reset if needed.		d=d & 0xfd;		outb(d,devpriv->BADR3+5);	}	outb(0x01,devpriv->BADR3+6); //set bursting off, conversions on	outb(0x00,devpriv->BADR3+7); //set range to 10V. UP/BP is controlled by a switch on the board	// write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan.	chanlims=chan | (chan<<4);	outb(chanlims,devpriv->BADR3+0);	/* convert n samples */	for(n=0;n<insn->n;n++){		/* trigger conversion */		outw(0,devpriv->BADR2+0);#define TIMEOUT 1000 	//typically takes 5 loops on a lightly loaded Pentium 100MHz,			//this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit.		/* wait for conversion to end */		for(i=0;i<TIMEOUT;i++){			busy = inb(devpriv->BADR3+2)&0x80;			if(!busy)break;		}		if(i==TIMEOUT){			printk("timeout\n");			return -ETIMEDOUT;		}		/* read data */		d = inw(devpriv->BADR2+0);		/* mangle the data as necessary */		//d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed.		data[n] = d;	}	/* return the number of samples read/written */	return n;}static int cb_pcimdas_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int chan = CR_CHAN(insn->chanspec);	/* Writing a list of values to an AO channel is probably not	 * very useful, but that's how the interface is defined. */	for(i=0;i<insn->n;i++){		switch ( chan ) {		case 0:	 			outw(data[i] & 0x0FFF,devpriv->BADR2+DAC0_OFFSET);			break;		case 1:			outw(data[i] & 0x0FFF,devpriv->BADR2+DAC1_OFFSET);			break;		default:			return -1;		}		devpriv->ao_readback[chan] = data[i];	}	/* return the number of samples read/written */	return i;}/* AO subdevices should have a read insn as well as a write insn. * Usually this means copying a value stored in devpriv. */static int cb_pcimdas_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int chan = CR_CHAN(insn->chanspec);	for(i=0;i<insn->n;i++)		data[i] = devpriv->ao_readback[chan];	return i;}/* DIO devices are slightly special.  Although it is possible to * implement the insn_read/insn_write interface, it is much more * useful to applications if you implement the insn_bits interface. * This allows packed reading/writing of the DIO channels.  The * comedi core can convert between insn_bits and insn_read/write */static int cb_pcimdas_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){// Much of this based on the 8255 driver.	if(data[0]){		s->state &= ~data[0];		s->state |= (data[0]&data[1]);				if(data[0]&PORT_A_MASK) {			devpriv->port_a=s->state&0xff;			outb(devpriv->port_a,devpriv->BADR4+PORT_A);		}		if(data[0]&PORT_B_MASK) {			devpriv->port_b=(s->state>>8)&0xff;			outb(devpriv->port_b,devpriv->BADR4+PORT_B);		}		if(data[0]&PORT_C_MASK) {			devpriv->port_c=(s->state>>16)&0xff;			outb(devpriv->port_c,devpriv->BADR4+PORT_C);		}	}	data[1]=inb(devpriv->BADR4+PORT_A);	data[1]|=(inb(devpriv->BADR4+PORT_B)<<8);	data[1]|=(inb(devpriv->BADR4+PORT_C)<<16);	return 2; //should this be 2?}static int cb_pcimdas_dio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){// DIO config on this card is per port (or half port for port C), not per line.	unsigned int mask;	unsigned int bits;	int config;	mask=1<<CR_CHAN(insn->chanspec);	if(mask&PORT_A_MASK){		bits=PORT_A_MASK;	}else if(mask&PORT_B_MASK){		bits=PORT_B_MASK;	}else if(mask&PORT_CL_MASK){		bits=PORT_CL_MASK;	}else{		bits=PORT_CH_MASK;	}	switch(data[0]){	case COMEDI_INPUT:		s->io_bits&=~bits;		break;	case COMEDI_OUTPUT:		s->io_bits|=bits;		break;	default:		return -EINVAL;	}	config=ALL_OUTPUT;	/* 0 in io_bits indicates output, 1 in config indicates input */	if(!(s->io_bits&PORT_A_MASK))		config|=PORT_A_IN;	if(!(s->io_bits&PORT_B_MASK))		config|=PORT_B_IN;	if(!(s->io_bits&PORT_CL_MASK))		config|=PORT_CL_IN;	if(!(s->io_bits&PORT_CH_MASK))		config|=PORT_CH_IN;	outb(config,devpriv->BADR4+DIO_CONFIG);	devpriv->dio_mode=config;	return 1;} /* * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */COMEDI_INITCLEANUP(driver_cb_pcimdas);

⌨️ 快捷键说明

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