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

📄 adl_pci9111.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*   comedi/drivers/adl_pci9111.c    Hardware driver for PCI9111 ADLink cards:      PCI-9111HR               Copyright (C) 2002 Emmanuel Pacaud <emmanuel.pacaud@free.fr>     This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*Driver: adl_pci9111.oDescription: Driver for the Adlink PCI-9111HR card.Author: Emmanuel Pacaud <emmanuel.pacaud@free.fr>Devices: [ADLink] PCI-9111HR (adl_pci9111)Status: experimentalSupports:  - ai_insn read  - ao_insn read/write  - di_insn read  - do_insn read/write  - ai_do_cmd mode with the following sources:      - start_src 		TRIG_NOW    - scan_begin_src 		TRIG_FOLLOW 	TRIG_TIMER	TRIG_EXT    - convert_src				TRIG_TIMER	TRIG_EXT    - scan_end_src		TRIG_COUNT    - stop_src			TRIG_COUNT	TRIG_NONE        The scanned channels must be consecutive and start from 0. They must    all have the same range and aref.    Configuration options:      [0] - PCI bus number (optional)    [1] - PCI slot number (optional)        If bus/slot is not specified, the first available PCI    device will be used.  *//*CHANGELOG:  2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.  2002/02/18 Added external trigger support for analog input.TODO:   - Really test implemented functionality.  - Add support for the PCI-9111DG with a probe routine to identify the card type     (perhaps with the help of the channel number readback of the A/D Data register).   - Add analog input mode 4 suppport.  - Add external multiplexer support.  - Add analog output cmd support (use irq_on_timer_tick to update analog output).  - Add kernel < 2.4 support.*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/pci.h>#include "8253.h"typedef enum{  false,  true} bool;#define PCI9111_DRIVER_NAME 	"adl_pci9111"#define PCI9111_HR_DEVICE_ID 	0x9111// TODO: Add other pci9111 board id#define PCI9111_IO_RANGE 	0x0100#define PCI9111_FIFO_HALF_SIZE	512#define PCI9111_AI_CHANNEL_NBR			16#define PCI9111_AI_RESOLUTION			12#define PCI9111_AI_RESOLUTION_MASK		0x0FFF#define PCI9111_AI_RESOLUTION_2_CMP_BIT		0x0800#define PCI9111_HR_AI_RESOLUTION		16#define PCI9111_HR_AI_RESOLUTION_MASK		0xFFFF#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT	0x8000#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000#define PCI9111_AO_CHANNEL_NBR			1#define	PCI9111_AO_RESOLUTION			12#define PCI9111_AO_RESOLUTION_MASK		0x0FFF#define PCI9111_DI_CHANNEL_NBR			16#define	PCI9111_DO_CHANNEL_NBR			16#define PCI9111_DO_MASK				0xFFFF#define PCI9111_RANGE_SETTING_DELAY		10#define PCI9111_AI_INSTANT_READ_UDELAY_US	2			#define PCI9111_AI_INSTANT_READ_TIMEOUT		100#define PCI9111_8254_CLOCK_PERIOD_NS		500#define PCI9111_8254_COUNTER_0			0x00#define PCI9111_8254_COUNTER_1			0x40#define PCI9111_8254_COUNTER_2			0x80#define PCI9111_8254_COUNTER_LATCH		0x00#define PCI9111_8254_READ_LOAD_LSB_ONLY		0x10#define PCI9111_8254_READ_LOAD_MSB_ONLY		0x20#define PCI9111_8254_READ_LOAD_LSB_MSB		0x30#define PCI9111_8254_MODE_0			0x00#define PCI9111_8254_MODE_1			0x02#define PCI9111_8254_MODE_2			0x04#define PCI9111_8254_MODE_3			0x06#define PCI9111_8254_MODE_4			0x08#define PCI9111_8254_MODE_5			0x0A#define PCI9111_8254_BINARY_COUNTER		0x00#define PCI9111_8254_BCD_COUNTER		0x01/* IO address map */#define PCI9111_REGISTER_AD_FIFO_VALUE 			0x00 // AD Data stored in FIFO #define PCI9111_REGISTER_DA_OUTPUT 			0x00#define PCI9111_REGISTER_DIGITAL_IO 			0x02#define PCI9111_REGISTER_EXTENDED_IO_PORTS 		0x04#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 		0x06 // Channel selection #define PCI9111_REGISTER_AD_CHANNEL_READBACK 		0x06#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 		0x08#define PCI9111_REGISTER_RANGE_STATUS_READBACK 		0x08#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 		0x0A#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 	0x0A#define PCI9111_REGISTER_SOFTWARE_TRIGGER 		0x0E#define PCI9111_REGISTER_INTERRUPT_CONTROL 		0x0C#define PCI9111_REGISTER_8254_COUNTER_0			0x40#define PCI9111_REGISTER_8254_COUNTER_1			0x42#define PCI9111_REGISTER_8254_COUNTER_2 		0X44#define PCI9111_REGISTER_8254_CONTROL			0x46#define PCI9111_REGISTER_INTERRUPT_CLEAR 		0x48#define PCI9111_TRIGGER_MASK 				0x0F#define PCI9111_PTRG_OFF 				(0 << 3)#define PCI9111_PTRG_ON 				(1 << 3)#define PCI9111_EITS_EXTERNAL				(1 << 2)#define PCI9111_EITS_INTERNAL				(0 << 2)#define PCI9111_TPST_SOFTWARE_TRIGGER			(0 << 1)#define PCI9111_TPST_TIMER_PACER			(1 << 1)#define PCI9111_ASCAN_ON				(1 << 0)#define PCI9111_ASCAN_OFF				(0 << 0)#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL		(1 << 0)#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK  		(0 << 1)#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG 		(1 << 1)#define PCI9111_FFEN_SET_FIFO_ENABLE 			(0 << 2)#define PCI9111_FFEN_SET_FIFO_DISABLE			(1 << 2)#define PCI9111_CHANNEL_MASK				0x0F#define PCI9111_RANGE_MASK				0x07#define PCI9111_FIFO_EMPTY_MASK				0x10#define PCI9111_FIFO_HALF_FULL_MASK			0x20#define PCI9111_FIFO_FULL_MASK				0x40#define PCI9111_AD_BUSY_MASK				0x80#define PCI9111_IO_BASE dev->iobase/*  * Define inlined function */#define pci9111_trigger_and_autoscan_get() \  (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)#define pci9111_trigger_and_autoscan_set(flags) \  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)#define pci9111_interrupt_and_fifo_get() \  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)#define pci9111_interrupt_and_fifo_set(flags) \  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)#define pci9111_interrupt_clear() \  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)  #define pci9111_software_trigger() \  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)#define pci9111_fifo_reset() \  outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \  outb(PCI9111_FFEN_SET_FIFO_DISABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \  outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)#define pci9111_is_fifo_full() \  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \    PCI9111_FIFO_FULL_MASK)==0)#define pci9111_is_fifo_half_full() \  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \    PCI9111_FIFO_HALF_FULL_MASK)==0)#define pci9111_is_fifo_empty() \  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \    PCI9111_FIFO_EMPTY_MASK)==0)#define pci9111_ai_channel_set(channel) \  outb((channel)&PCI9111_CHANNEL_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)#define pci9111_ai_channel_get() \  inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK#define pci9111_ai_range_set(range) \  outb((range)&PCI9111_RANGE_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)#define pci9111_ai_range_get() \  inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK#define pci9111_ai_get_data() \  ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \  ^ PCI9111_AI_RESOLUTION_2_CMP_BIT#define pci9111_hr_ai_get_data() \  (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \  ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT  #define pci9111_ao_set_data(data) \  outb(data&PCI9111_AO_RESOLUTION_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)#define pci9111_di_get_bits() \  inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)#define pci9111_do_set_bits(bits) \  outw(bits,PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)  #define pci9111_8254_control_set(flags) \  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)#define pci9111_8254_counter_0_set(data) \  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)  #define pci9111_8254_counter_1_set(data) \  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)  #define pci9111_8254_counter_2_set(data) \  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)  // // Function prototypes//  static int pci9111_attach (comedi_device *dev,comedi_devconfig *it);static int pci9111_detach (comedi_device *dev);static comedi_lrange pci9111_hr_ai_range={   5,  {    BIP_RANGE(10),    BIP_RANGE(5),    BIP_RANGE(2.5),    BIP_RANGE(1.25),    BIP_RANGE(0.625)  }};static struct pci_device_id pci9111_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	//{ PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0 }};MODULE_DEVICE_TABLE(pci, pci9111_pci_table);//// Board specification structure//typedef struct {  char 		*name;			// driver name  int		device_id;  int 		ai_channel_nbr;		// num of A/D chans  int 		ao_channel_nbr;		// num of D/A chans  int		ai_resolution;		// resolution of A/D  int		ai_resolution_mask;  int		ao_resolution;		// resolution of D/A  int		ao_resolution_mask;  comedi_lrange	*ai_range_list;		// rangelist for A/D  comedi_lrange	*ao_range_list;		// rangelist for D/A  unsigned int	ai_acquisition_period_min_ns;} pci9111_board_struct;static pci9111_board_struct pci9111_boards[] ={  {    name: 		"pci9111_hr",     device_id:		PCI9111_HR_DEVICE_ID,    ai_channel_nbr:	PCI9111_AI_CHANNEL_NBR,			    ao_channel_nbr:	PCI9111_AO_CHANNEL_NBR,			    ai_resolution:	PCI9111_HR_AI_RESOLUTION,    ai_resolution_mask:	PCI9111_HR_AI_RESOLUTION_MASK,		    ao_resolution:	PCI9111_AO_RESOLUTION,    ao_resolution_mask:	PCI9111_AO_RESOLUTION_MASK,			    ai_range_list:	&pci9111_hr_ai_range,      ao_range_list:	&range_bipolar10,    ai_acquisition_period_min_ns:	PCI9111_AI_ACQUISITION_PERIOD_MIN_NS  }};#define pci9111_board_nbr \  (sizeof(pci9111_boards)/sizeof(pci9111_board_struct))static comedi_driver pci9111_driver={  driver_name:	PCI9111_DRIVER_NAME,  module:	THIS_MODULE,  attach:	pci9111_attach,  detach:	pci9111_detach,  num_names:	pci9111_board_nbr,  board_name:	pci9111_boards,  offset:	sizeof(pci9111_board_struct),};COMEDI_INITCLEANUP(pci9111_driver);//// Private data structure//typedef struct {  struct pci_dev*	pci_device;  int			io_range;		// PCI6503 io range  int			lcr_io_base;		// Local configuration register base address  int			lcr_io_range;		  int		scan_begin_counter;  int		scan_begin_counter_limit;  int		stop_counter;			  int		stop_is_none;  int 		ao_readback;			// Last written analog output data  int 		timer_divisor_1;		// Divisor values for the 8254 timer pacer  int 		timer_divisor_2;  int 		is_valid;			// Is device valid} pci9111_private_data_struct;#define dev_private 	((pci9111_private_data_struct *)dev->private)// ------------------------------------------------------------------// // PLX9050 SECTION// // ------------------------------------------------------------------#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c#define PLX9050_LINTI1_ENABLE		(1 << 0)#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)#define PLX9050_LINTI1_STATUS		(1 << 2)#define PLX9050_LINTI2_ENABLE		(1 << 3)#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)#define PLX9050_LINTI2_STATUS		(1 << 5)#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)static void plx9050_interrupt_control (int io_base,				       bool LINTi1_enable,				       bool LINTi1_active_high,				       bool LINTi2_enable,				       bool LINTi2_active_high,				       bool interrupt_enable){  int flags = 0;    if (LINTi1_enable) flags |= PLX9050_LINTI1_ENABLE;  if (LINTi1_active_high) flags |= PLX9050_LINTI1_ACTIVE_HIGH;  if (LINTi2_enable) flags |= PLX9050_LINTI2_ENABLE;  if (LINTi2_active_high) flags |= PLX9050_LINTI2_ACTIVE_HIGH;  if (interrupt_enable) flags |= PLX9050_PCI_INTERRUPT_ENABLE;    outb (flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);}   // ------------------------------------------------------------------// // MISCELLANEOUS SECTION// // ------------------------------------------------------------------//// 8254 timer //static void pci9111_timer_set ( comedi_device * dev) {  pci9111_8254_control_set ( PCI9111_8254_COUNTER_0|			     PCI9111_8254_READ_LOAD_LSB_MSB|			     PCI9111_8254_MODE_0|			     PCI9111_8254_BINARY_COUNTER);  pci9111_8254_control_set ( PCI9111_8254_COUNTER_1|			     PCI9111_8254_READ_LOAD_LSB_MSB|			     PCI9111_8254_MODE_2|			     PCI9111_8254_BINARY_COUNTER);  pci9111_8254_control_set ( PCI9111_8254_COUNTER_2|			     PCI9111_8254_READ_LOAD_LSB_MSB|			     PCI9111_8254_MODE_2|			     PCI9111_8254_BINARY_COUNTER);  comedi_udelay(1);  pci9111_8254_counter_2_set (dev_private->timer_divisor_2);  pci9111_8254_counter_1_set (dev_private->timer_divisor_1);}typedef enum {  software,  timer_pacer,  external} pci9111_trigger_sources;  static void pci9111_trigger_source_set (comedi_device *dev,					pci9111_trigger_sources source){  int flags;    flags = pci9111_trigger_and_autoscan_get() & 0x09;  switch (source)  {    case software :      flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;      break;    case timer_pacer :      flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;      break;    case external :       flags |= PCI9111_EITS_EXTERNAL;      break;  }  pci9111_trigger_and_autoscan_set (flags);}

⌨️ 快捷键说明

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