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

📄 pcl812.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * comedi/drivers/pcl812.c * * Author: Michal Dobes <dobes@tesnet.cz> * * hardware driver for Advantech cards *  card:   PCL-812, PCL-812PG, PCL-813, PCL-813B *  driver: pcl812,  pcl812pg,  pcl813,  pcl813b * and for ADlink cards *  card:   ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216 *  driver: acl8112dg,  acl8112hg,  acl8112pg,  acl8113,  acl8216 * and for ICP DAS cards *  card:   ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL,  *  driver: iso813,  a821pgh,  a-821pgl, a-821pglnda,  a822pgh,  a822pgl, *  card:   A-823PGH, A-823PGL, A-826PG  * driver:  a823pgh,  a823pgl,  a826pg *//*Driver: pcl812.oDescription: Advantech PCL-812/PG, PCL-813/B,             ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216,             ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG,             ICP DAS ISO-813Author: Michal Dobes <dobes@tesnet.cz>Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg),  PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg),  ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216),  [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl),  A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl),  A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg)Status: works (I hope. My board fire up under my hands               and I cann't test all features.)This driver supports insn and cmd interfaces. Some boards support only insnbecouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813).Data transfer over DMA is supported only when you measure only onechannel, this is too hardware limitation of these boards.See the head of the source file pcl812.c for configuration options.*//* * * Options for PCL-812: *  [0] - IO Base *  [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) *  [2] - DMA  (0=disable, 1, 3) *  [3] - 0=trigger source is internal 8253 with 2MHz clock *        1=trigger source is external  *  [4] - 0=A/D input range is +/-10V *        1=A/D input range is +/-5V *        2=A/D input range is +/-2.5V *        3=A/D input range is +/-1.25V *        4=A/D input range is +/-0.625V *        5=A/D input range is +/-0.3125V *  [5] - 0=D/A outputs 0-5V  (internal reference -5V) *        1=D/A outputs 0-10V (internal reference -10V) *        2=D/A outputs unknow (external reference) * * Options for PCL-812PG, ACL-8112PG: *  [0] - IO Base *  [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) *  [2] - DMA  (0=disable, 1, 3) *  [3] - 0=trigger source is internal 8253 with 2MHz clock *        1=trigger source is external  *  [4] - 0=A/D have max +/-5V input *        1=A/D have max +/-10V input *  [5] - 0=D/A outputs 0-5V  (internal reference -5V) *        1=D/A outputs 0-10V (internal reference -10V) *        2=D/A outputs unknow (external reference) * * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: *  [0] - IO Base *  [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) *  [2] - DMA  (0=disable, 1, 3) *  [3] - 0=trigger source is internal 8253 with 2MHz clock *        1=trigger source is external  *  [4] - 0=A/D channels are S.E. *        1=A/D channels are DIFF *  [5] - 0=D/A outputs 0-5V  (internal reference -5V) *        1=D/A outputs 0-10V (internal reference -10V) *        2=D/A outputs unknow (external reference) * * Options for A-821PGL/PGH: *  [0] - IO Base *  [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7) *  [2] - 0=A/D channels are S.E. *        1=A/D channels are DIFF *  [3] - 0=D/A output 0-5V  (internal reference -5V)  *        1=D/A output 0-10V (internal reference -10V) * * Options for A-821PGL-NDA: *  [0] - IO Base *  [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7) *  [2] - 0=A/D channels are S.E. *        1=A/D channels are DIFF * * Options for PCL-813: *  [0] - IO Base * * Options for PCL-813B: *  [0] - IO Base *  [1] - 0= bipolar inputs *        1= unipolar inputs *      * Options for ACL-8113, ISO-813: *  [0] - IO Base *  [1] - 0= 10V bipolar inputs *        1= 10V unipolar inputs *        2= 20V bipolar inputs *        3= 20V unipolar inputs *      */#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/ioport.h>#include <asm/dma.h>#include "8253.h"#undef PCL812_EXTDEBUG		/* if this is defined then a lot of messages is printed */// hardware types of the cards#define boardPCL812PG 		 0 	/* and ACL-8112PG */#define boardPCL813B 		 1#define boardPCL812		 2#define boardPCL813 		 3#define boardISO813 		 5#define boardACL8113 		 6#define boardACL8112 		 7 	/* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */#define boardACL8216		 8 	/* and ICP DAS A-826PG */#define boardA821		 9	/* PGH, PGL, PGL/NDA versions */#define PCLx1x_IORANGE 		16#define PCL812_CTR0		 0#define PCL812_CTR1		 1#define PCL812_CTR2		 2#define PCL812_CTRCTL		 3#define PCL812_AD_LO		 4#define PCL812_DA1_LO		 4#define PCL812_AD_HI		 5#define PCL812_DA1_HI		 5#define PCL812_DA2_LO		 6#define PCL812_DI_LO		 6#define PCL812_DA2_HI		 7#define PCL812_DI_HI		 7#define PCL812_CLRINT		 8#define PCL812_GAIN		 9#define PCL812_MUX		10#define PCL812_MODE		11#define PCL812_CNTENABLE 	10#define PCL812_SOFTTRIG 	12#define PCL812_DO_LO		13#define PCL812_DO_HI 		14#define PCL812_DRDY 		0x10	/* =0 data ready */#define ACL8216_STATUS 		 8	/* 5. bit signalize data ready */#define ACL8216_DRDY 		0x20	/* =0 data ready */#define MAX_CHANLIST_LEN	256	/* length of scan list */static comedi_lrange range_pcl812pg_ai = { 5, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),	BIP_RANGE(0.3125),}};static comedi_lrange range_pcl812pg2_ai = { 5, {	BIP_RANGE(10),	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),}};static comedi_lrange range812_bipolar1_25 = { 1, {	BIP_RANGE(1.25),}};static comedi_lrange range812_bipolar0_625 = { 1, {	BIP_RANGE(0.625),}};static comedi_lrange range812_bipolar0_3125 = { 1, {	BIP_RANGE(0.3125),}};static comedi_lrange range_pcl813b_ai = { 4, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),}};static comedi_lrange range_pcl813b2_ai = { 4, {	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),	UNI_RANGE(1.25),}};static comedi_lrange range_iso813_1_ai = { 5, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),	BIP_RANGE(0.3125),}};static comedi_lrange range_iso813_1_2_ai = { 5, {	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),	UNI_RANGE(1.25),	UNI_RANGE(0.625),}};static comedi_lrange range_iso813_2_ai = { 4, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),}};static comedi_lrange range_iso813_2_2_ai = { 4, {	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),	UNI_RANGE(1.25),}};static comedi_lrange range_acl8113_1_ai = { 4, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),}};static comedi_lrange range_acl8113_1_2_ai = { 4, {	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),	UNI_RANGE(1.25),}};static comedi_lrange range_acl8113_2_ai = { 3, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),}};static comedi_lrange range_acl8113_2_2_ai = { 3, {	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),}};static comedi_lrange range_acl8112dg_ai = { 9, {	BIP_RANGE(5),	BIP_RANGE(2.5),	BIP_RANGE(1.25),	BIP_RANGE(0.625),	UNI_RANGE(10),	UNI_RANGE(5),	UNI_RANGE(2.5),	UNI_RANGE(1.25),	BIP_RANGE(10),}};static comedi_lrange range_acl8112hg_ai = { 12, {	BIP_RANGE(5),	BIP_RANGE(0.5),	BIP_RANGE(0.05),	BIP_RANGE(0.005),	UNI_RANGE(10),	UNI_RANGE(1),	UNI_RANGE(0.1),	UNI_RANGE(0.01),	BIP_RANGE(10),	BIP_RANGE(1),	BIP_RANGE(0.1),	BIP_RANGE(0.01),}};static comedi_lrange range_a821pgh_ai = { 4, {	BIP_RANGE(5),	BIP_RANGE(0.5),	BIP_RANGE(0.05),	BIP_RANGE(0.005),}};static int pcl812_attach(comedi_device *dev,comedi_devconfig *it);static int pcl812_detach(comedi_device *dev);typedef struct {	char 		*name;		// driver name	int 		board_type;	// type of this board	int 		n_aichan;	// num of AI chans in S.E.	int 		n_aichan_diff;	// DIFF num of chans	int 		n_aochan;	// num of DA chans	int		n_dichan;	// DI and DO chans	int 		n_dochan;	int 		ai_maxdata;	// AI resolution	unsigned int	ai_ns_min;	// max sample speed of card v ns	unsigned int	i8254_osc_base;	// clock base	comedi_lrange	*rangelist_ai;	// rangelist for A/D	comedi_lrange	*rangelist_ao;	// rangelist for D/A	unsigned int	IRQbits;	// allowed IRQ	unsigned char 	DMAbits;	// allowed DMA chans	unsigned char	io_range;	// iorange for this board	unsigned char	haveMPC508;	// 1=board use MPC508A multiplexor} boardtype;static boardtype boardtypes[] ={	{"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,	 33000, 500, &range_bipolar10, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,	 33000, 500, &range_pcl812pg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,	 10000, 500, &range_pcl812pg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	 10000, 500, &range_acl8112dg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},	{"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	 10000, 500, &range_acl8112hg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},	{"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,	 10000, 500, &range_pcl813b_ai, &range_unipolar5,	 0x000c, 0x00, PCLx1x_IORANGE, 0},	{"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,	 10000, 500, &range_pcl813b_ai, NULL,	 0x000c, 0x00, PCLx1x_IORANGE, 0},	{"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,	 10000, 500, &range_a821pgh_ai, &range_unipolar5,	 0x000c, 0x00, PCLx1x_IORANGE, 0},	{"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	 10000, 500, &range_acl8112dg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	 10000, 500, &range_acl8112hg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	  8000, 500, &range_acl8112dg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,	  8000, 500, &range_acl8112hg_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},	{"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,	     0, 0, &range_pcl813b_ai, NULL,	 0x0000, 0x00, PCLx1x_IORANGE, 0},	{"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,	     0, 0, &range_pcl813b_ai, NULL,	 0x0000, 0x00, PCLx1x_IORANGE, 0},	{"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,	     0, 0, &range_acl8113_1_ai, NULL,	 0x0000, 0x00, PCLx1x_IORANGE, 0},	{"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,	     0, 0, &range_iso813_1_ai, NULL,	 0x0000, 0x00, PCLx1x_IORANGE, 0},	{"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,	 10000, 500, &range_pcl813b2_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},	{"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,	 10000, 500, &range_pcl813b2_ai, &range_unipolar5,	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},};#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))#define this_board ((boardtype *)dev->board_ptr)static comedi_driver driver_pcl812={	driver_name:	"pcl812",	module:		THIS_MODULE,	attach:		pcl812_attach,	detach:		pcl812_detach,	board_name:	boardtypes,	num_names:	n_boardtypes,	offset:		sizeof(boardtype),};COMEDI_INITCLEANUP(driver_pcl812);typedef struct {	unsigned char	valid;			// =1 device is OK	unsigned char	dma;			// >0 use dma ( usedDMA channel)	unsigned char	use_diff;		// =1 diff inputs	unsigned char	use_MPC;		// 1=board uses MPC508A multiplexor	unsigned char	use_ext_trg;		// 1=board uses external trigger	unsigned char	range_correction;	// =1 we must add 1 to range number	unsigned char	old_chan_reg;		// lastly used chan/gain pair	unsigned char	old_gain_reg;	unsigned char	mode_reg_int;		// there is stored INT number for some card	unsigned char	ai_neverending;		// =1 we do unlimited AI	unsigned char	ai_eos;			// 1=EOS wake up	unsigned char	ai_dma;			// =1 we use DMA	unsigned int	ai_poll_ptr;		// how many sampes transfer poll	unsigned int	ai_scans;		// len of scanlist	unsigned int	ai_act_scan;		// how many scans we finished	unsigned int 	ai_chanlist[MAX_CHANLIST_LEN];// our copy of channel/range list	unsigned int	ai_n_chan;		// how many channels is measured		unsigned int	ai_flags;		// flaglist	unsigned int	ai_data_len;		// len of data buffer	sampl_t		*ai_data;		// data buffer	unsigned int	ai_is16b;		// =1 we have 16 bit card	unsigned long 	dmabuf[2];		// PTR to DMA buf	unsigned int 	dmapages[2];		// how many pages we have allocated	unsigned int 	hwdmaptr[2];		// HW PTR to DMA buf	unsigned int 	hwdmasize[2];		// DMA buf size in bytes	unsigned int 	dmabytestomove[2];	// how many bytes DMA transfer	int 		next_dma_buf;		// which buffer is next to use	unsigned int	dma_runs_to_end;	// how many times we must switch DMA buffers	unsigned int	last_dma_run;		// how many bytes to transfer on last DMA buffer	unsigned int	max_812_ai_mode0_rangewait;// setling time for gain	lsampl_t 	ao_readback[2];		// data for AO readback} pcl812_private;#define devpriv ((pcl812_private *)dev->private)/* ==============================================================================*/static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1, unsigned int divisor2);static void setup_range_channel(comedi_device * dev, comedi_subdevice * s, 	unsigned int rangechan, char wait);static int pcl812_ai_cancel(comedi_device * dev, comedi_subdevice * s);/* ==============================================================================*/static int pcl812_ai_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int n;	int timeout, hi;	outb(devpriv->mode_reg_int|1, dev->iobase + PCL812_MODE);	/* select software trigger */	setup_range_channel(dev, s, insn->chanspec, 1); // select channel and renge	for(n=0;n<insn->n;n++){		outb(255, dev->iobase + PCL812_SOFTTRIG);	/* start conversion */		comedi_udelay(5);		timeout = 50;	/* wait max 50us, it must finish under 33us */		while (timeout--) {			hi = inb(dev->iobase + PCL812_AD_HI);			if (!(hi & PCL812_DRDY))				goto conv_finish;			comedi_udelay(1);		}		rt_printk("comedi%d: pcl812: (%s at 0x%x) A/D insn read timeout\n", dev->minor, dev->board_name, dev->iobase);		outb(devpriv->mode_reg_int|0, dev->iobase + PCL812_MODE);		return -ETIME;	      conv_finish:		data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO);	}	outb(devpriv->mode_reg_int|0, dev->iobase + PCL812_MODE);	return n;}/* ==============================================================================*/static int acl8216_ai_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int n;	int timeout;	outb(1, dev->iobase + PCL812_MODE);	/* select software trigger */	setup_range_channel(dev, s, insn->chanspec, 1); // select channel and renge	for(n=0;n<insn->n;n++){		outb(255, dev->iobase + PCL812_SOFTTRIG);	/* start conversion */		comedi_udelay(5);		timeout = 50;	/* wait max 50us, it must finish under 33us */		while (timeout--) {			if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY))				goto conv_finish;			comedi_udelay(1);		}		rt_printk("comedi%d: pcl812: (%s at 0x%x) A/D insn read timeout\n", dev->minor, dev->board_name, dev->iobase);		outb(0, dev->iobase + PCL812_MODE);		return -ETIME;	      conv_finish:		data[n] = (inb(dev->iobase + PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO);	}	outb(0, dev->iobase + PCL812_MODE);	return n;}/* ==============================================================================*/static int pcl812_ao_insn_write(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int chan = CR_CHAN(insn->chanspec);	int i;

⌨️ 快捷键说明

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