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

📄 icp_multi.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*==============================================================================	Name:	icp_multi_insn_read_ctr	Description:		This function reads the specified counter.	Parameters:		comedi_device *dev	Pointer to current device structure		comedi_subdevice *s	Pointer to current subdevice structure		comedi_insn *insn	Pointer to current comedi instruction		lsampl_t *data		Pointer to counter data	Returns:int			Nmuber of instructions executed==============================================================================*/static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s, comedi_insn *insn, lsampl_t *data){        return 0;}/*==============================================================================	Name:	icp_multi_insn_write_ctr	Description:		This function write to the specified counter.	Parameters:		comedi_device *dev	Pointer to current device structure		comedi_subdevice *s	Pointer to current subdevice structure		comedi_insn *insn	Pointer to current comedi instruction		lsampl_t *data		Pointer to counter data	Returns:int			Nmuber of instructions executed==============================================================================*/static int icp_multi_insn_write_ctr(comedi_device * dev, comedi_subdevice * s, comedi_insn *insn, lsampl_t *data){        return 0;}/*==============================================================================	Name:	interrupt_service_icp_multi	Description:		This function is the interrupt service routine for all		interrupts generated by the icp multi board.	Parameters:		int irq		void *d			Pointer to current device		struct pt_regs *regs	Pointer to	Returns:int			Nmuber of instructions executed==============================================================================*/static void interrupt_service_icp_multi(int irq, void *d, struct pt_regs *regs){        comedi_device *dev = d;	int	int_no;	#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n",irq);#endif	// Is this interrupt from our board?	int_no = readw(dev->iobase + ICP_MULTI_INT_STAT) & Status_IRQ;	if (!int_no) 			// No, exit		return;#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n",readw(dev->iobase + ICP_MULTI_INT_STAT));#endif	// Determine which interrupt is active & handle it	switch(int_no)	{		case ADC_READY:				break;		case DAC_READY:				break;		case DOUT_ERROR:				break;		case DIN_STATUS:				break;		case CIE0:				break;		case CIE1:				break;		case CIE2:				break;		case CIE3:				break;		default:				break;	}#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG: END: interrupt_service_icp_multi(...)\n");#endif}#if 0/*==============================================================================	Name:	check_channel_list		Description:		This function checks if the channel list, provided by user		is built correctly	Parameters:		comedi_device *dev	Pointer to current sevice structure		comedi_subdevice *s	Pointer to current subdevice structure		unsigned int *chanlist	Pointer to packed channel list		unsigned int n_chan	Number of channels to scan	Returns:int 0 = failure		    1 = success==============================================================================*/static int check_channel_list(comedi_device * dev, comedi_subdevice * s, unsigned int *chanlist, unsigned int n_chan){        unsigned int i;    #ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG:  check_channel_list(...,%d)\n",n_chan);#endif    	// Check that we at least have one channel to check	if (n_chan<1) {		comedi_error(dev,"range/channel list is empty!");		return 0;        }	// Check all channels	for (i=0; i<n_chan; i++) {		// Check that channel number is < maximum		if (CR_AREF(chanlist[i])==AREF_DIFF) {			if (CR_CHAN(chanlist[i]) > this_board->n_aichand) {				comedi_error(dev,"Incorrect differential ai channel number");				return 0;			}                }		else {			if (CR_CHAN(chanlist[i]) > this_board->n_aichan) {				comedi_error(dev,"Incorrect ai channel number");				return 0;			}                }	}	return 1;}#endif/*==============================================================================	Name:	setup_channel_list	Description:		This function sets the appropriate channel selection,		differential input mode and range bits in the ADC Command/		Status register.	Parameters:		comedi_device *dev	Pointer to current sevice structure		comedi_subdevice *s	Pointer to current subdevice structure		unsigned int *chanlist	Pointer to packed channel list		unsigned int n_chan	Number of channels to scan	Returns:Void==============================================================================*/static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, unsigned int *chanlist,			unsigned int n_chan){	unsigned int i, range, chanprog;	unsigned int diff;#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG:  setup_channel_list(...,%d)\n",n_chan);#endif	devpriv->act_chanlist_len=n_chan;	devpriv->act_chanlist_pos=0; 	for (i=0; i<n_chan; i++) {		// Get channel		chanprog=CR_CHAN(chanlist[i]);		// Determine if it is a differential channel (Bit 15  = 1)		if (CR_AREF(chanlist[i])==AREF_DIFF) {			diff = 1;			chanprog &= 0x0007;		}		else {			diff = 0;			chanprog &= 0x000f;		}		// Clear channel, range and input mode bits in A/D command/status register		devpriv->AdcCmdStatus &= 0xf00f;		// Set channel number and differential mode status bit		if (diff) {			// Set channel number, bits 9-11 & mode, bit 6			devpriv->AdcCmdStatus |= (chanprog << 9);			devpriv->AdcCmdStatus |= ADC_DI;                }		else			// Set channel number, bits 8-11			devpriv->AdcCmdStatus |= (chanprog << 8);		// Get range for current channel		range=this_board->rangecode[CR_RANGE(chanlist[i])];		// Set range. bits 4-5		devpriv->AdcCmdStatus |= range;		/* Output channel, range, mode to ICP Multi*/		writew(devpriv->AdcCmdStatus, dev->iobase+ICP_MULTI_ADC_CSR);#ifdef ICP_MULTI_EXTDEBUG		printk("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, devpriv->act_chanlist[i]);#endif	}}/*==============================================================================	Name:	icp_multi_reset	Description:		This function resets the icp multi device to a 'safe' state		Parameters:		comedi_device *dev	Pointer to current sevice structure	Returns:int	0 = success==============================================================================*/static int icp_multi_reset(comedi_device *dev){        unsigned int    i;#ifdef ICP_MULTI_EXTDEBUG	printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n");#endif	// Clear INT enables and requests	writew(0, dev->iobase + ICP_MULTI_INT_EN);	writew(0x00ff, dev->iobase + ICP_MULTI_INT_STAT);	if (this_board->n_aochan)		// Set DACs to 0..5V range and 0V output		for (i =0; i < this_board->n_aochan; i++) {			devpriv->DacCmdStatus &= 0xfcce;			// Set channel number			devpriv->DacCmdStatus |= (i << 8);			// Output 0V			writew(0, dev->iobase+ICP_MULTI_AO);			// Set start conversion bit			devpriv->DacCmdStatus |= DAC_ST;			// Output to command / status register			writew(devpriv->DacCmdStatus, dev->iobase+ICP_MULTI_DAC_CSR);						// Delay to allow DAC time to recover			comedi_udelay(1);		}		// Digital outputs to 0	writew(0, dev->iobase + ICP_MULTI_DO);#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG: END: icp_multi_reset(...)\n");#endif	return 0;}/*==============================================================================	Name:	icp_multi_attach		Description:		This function sets up all the appropriate data for the current		device.	Parameters:		comedi_device *dev	Pointer to current device structure		comedi_devconfig *it	Pointer to current device configuration	Returns:int	0 = success==============================================================================*/static int icp_multi_attach(comedi_device *dev,comedi_devconfig *it){	comedi_subdevice 	*s;	int ret, subdev, n_subdevices;	unsigned short 		master,irq;	struct pcilst_struct 	*card=NULL;        unsigned long 		io_addr[5], iobase;	unsigned char 		pci_bus, pci_slot, pci_func;	printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");	// Alocate private data storage space	if ((ret=alloc_private(dev, sizeof(icp_multi_private)))<0)		return ret;	// Initialise list of PCI cards in system, if not already done so	if (!pci_list_builded) {		pci_card_list_init(PCI_VENDOR_ID_ICP,#ifdef ICP_MULTI_EXTDEBUG						    1#else						    0#endif			);			pci_list_builded=1;	}	printk("Anne's comedi%d: icp_multi: board=%s", dev->minor, this_board->name);	if ((card=select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, this_board->device_id, it->options[0], it->options[1]))==NULL)		return -EIO;	if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], &irq, &master))<0) {		pci_card_free(card);		printk(" - Can't get configuration data!\n");		return -EIO;	}	iobase=io_addr[2];//	if(check_mem_region(iobase, ICP_MULTI_SIZE))//	{		/* Couldn't allocate io space *///		printk(KERN_WARNING "couldn't allocate IO space\n");//		return -EIO;//	}//	request_mem_region(iobase, ICP_MULTI_SIZE, "icp_multi");	devpriv->phys_iobase = iobase;	printk(", b:s:f=%d:%d:%d, io=0x%8lx \n", pci_bus, pci_slot, pci_func, iobase);	devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE);	if (devpriv->io_addr == NULL) {		printk("ioremap failed.\n");		return -ENOMEM;	}#ifdef ICP_MULTI_EXTDEBUG	printk("0x%08lx mapped to %p, ", iobase, devpriv->io_addr);#endif	dev->iobase = (int)devpriv->io_addr;	dev->board_name = this_board->name;        n_subdevices = 0;	if (this_board->n_aichan) n_subdevices++;	if (this_board->n_aochan) n_subdevices++;	if (this_board->n_dichan) n_subdevices++;	if (this_board->n_dochan) n_subdevices++;	if (this_board->n_ctrs)	  n_subdevices++;        if((ret=alloc_subdevices(dev, n_subdevices))<0) {		pci_card_free(card);    		return ret;	}	if (this_board->have_irq) {		if (irq)  {			if (comedi_request_irq(irq, interrupt_service_icp_multi, SA_SHIRQ, "Inova Icp Multi", dev)) {				printk(", unable to allocate IRQ %d, DISABLING IT", irq);				irq=0; /* Can't use IRQ */			}			else				printk(", irq=%d", irq);		}		else			printk(", IRQ disabled");	}	else		irq=0;	        dev->irq = irq;	printk(".\n");	subdev=0;		if (this_board->n_aichan) {		s = dev->subdevices + subdev;		dev->read_subdev = s;		s->type = COMEDI_SUBD_AI;		s->subdev_flags = SDF_READABLE|SDF_COMMON|SDF_GROUND;		if (this_board->n_aichand)			s->subdev_flags |= SDF_DIFF;		s->n_chan = this_board->n_aichan;		s->maxdata = this_board->ai_maxdata;		s->len_chanlist = this_board->n_aichan;		s->range_table = this_board->rangelist_ai;		s->insn_read=icp_multi_insn_read_ai;		subdev++;	}		if (this_board->n_aochan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_AO;		s->subdev_flags = SDF_WRITABLE|SDF_GROUND|SDF_COMMON;		s->n_chan = this_board->n_aochan;		s->maxdata = this_board->ao_maxdata;		s->len_chanlist = this_board->n_aochan;		s->range_table = this_board->rangelist_ao;		s->insn_write=icp_multi_insn_write_ao;		s->insn_read=icp_multi_insn_read_ao;		subdev++;	}	if (this_board->n_dichan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_DI;		s->subdev_flags = SDF_READABLE;		s->n_chan = this_board->n_dichan;		s->maxdata = 1;		s->len_chanlist = this_board->n_dichan;		s->range_table = &range_digital;		s->io_bits=0;		s->insn_bits=icp_multi_insn_bits_di;		subdev++;	}	if (this_board->n_dochan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_DO;		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;		s->n_chan = this_board->n_dochan;		s->maxdata = 1;		s->len_chanlist = this_board->n_dochan;		s->range_table = &range_digital;		s->io_bits=(1 << this_board->n_dochan)-1;		s->state=0;		s->insn_bits=icp_multi_insn_bits_do;		subdev++;	}	if (this_board->n_ctrs) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_COUNTER;		s->subdev_flags = SDF_WRITABLE|SDF_GROUND|SDF_COMMON;		s->n_chan = this_board->n_ctrs;		s->maxdata = 0xffff;		s->len_chanlist = this_board->n_ctrs;		s->state=0;		s->insn_read=icp_multi_insn_read_ctr;		s->insn_write=icp_multi_insn_write_ctr;		subdev++;	}		devpriv->valid = 1;	icp_multi_reset(dev);#ifdef ICP_MULTI_EXTDEBUG	printk("icp multi EDBG: END: icp_multi_attach(...)\n");#endif	return 0;}/*==============================================================================	Name:	icp_multi_detach		Description:		This function releases all the resources used by the current		device.		Parameters:		comedi_device *dev	Pointer to current device structure	Returns:int	0 = success==============================================================================*/static int icp_multi_detach(comedi_device *dev){	if (dev->private) 		if (devpriv->valid)			icp_multi_reset(dev);		if (dev->irq)		comedi_free_irq(dev->irq,dev);	if (dev->iobase) {		iounmap(devpriv->io_addr);//		release_mem_region(iobase, ICP_MULTI_SIZE);	}	if (pci_list_builded) {	    	pci_card_list_cleanup(PCI_VENDOR_ID_ICP);		pci_list_builded=0;	}	return 0;}

⌨️ 快捷键说明

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