18d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 28d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi/drivers/dt282x.c 38d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef Hardware driver for Data Translation DT2821 series 48d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 58d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef COMEDI - Linux Control and Measurement Device Interface 68d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> 78d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 88d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef This program is free software; you can redistribute it and/or modify 98d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef it under the terms of the GNU General Public License as published by 108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef the Free Software Foundation; either version 2 of the License, or 118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef (at your option) any later version. 128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef This program is distributed in the hope that it will be useful, 148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef GNU General Public License for more details. 178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef You should have received a copy of the GNU General Public License 198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef along with this program; if not, write to the Free Software 208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 248d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefDriver: dt282x 258d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefDescription: Data Translation DT2821 series (including DT-EZ) 268d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefAuthor: ds 278d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefDevices: [Data Translation] DT2821 (dt2821), 288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2821-F-16SE (dt2821-f), DT2821-F-8DI (dt2821-f), 298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2821-G-16SE (dt2821-f), DT2821-G-8DI (dt2821-g), 308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2823 (dt2823), 318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2824-PGH (dt2824-pgh), DT2824-PGL (dt2824-pgl), DT2825 (dt2825), 328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2827 (dt2827), DT2828 (dt2828), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez), 338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl) 348d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefStatus: complete 358d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefUpdated: Wed, 22 Aug 2001 17:11:34 -0700 368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 378d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefConfiguration options: 388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [0] - I/O port base address 398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [1] - IRQ 408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [2] - DMA 1 418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [3] - DMA 2 428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [4] - AI jumpered for 0=single ended, 1=differential 438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [5] - AI jumpered for 0=straight binary, 1=2's complement 448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [6] - AO 0 jumpered for 0=straight binary, 1=2's complement 458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [7] - AO 1 jumpered for 0=straight binary, 1=2's complement 468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5] 478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [9] - AO 0 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], 4818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4=[-2.5,2.5] 498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef [10]- A0 1 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], 5018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4=[-2.5,2.5] 518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 528d3d823c74a4c967b4a02e6466c6727ad21422a0David SchleefNotes: 538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef - AO commands might be broken. 548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef - If you try to run a command on both the AI and AO subdevices 558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef simultaneously, bad things will happen. The driver needs to 568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef be fixed to check for this situation and return an error. 578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef*/ 588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#include "../comedidev.h" 608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 615a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#include <linux/ioport.h> 638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#include <linux/interrupt.h> 64845d131e2b363717d8ac8db2c6b4417de8cf10b5Greg Kroah-Hartman#include <linux/io.h> 658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#include <asm/dma.h> 668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#include "comedi_fc.h" 678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DEBUG 698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_TIMEOUT 100 /* 500 us */ 718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SIZE 0x10 728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * Registers in the DT282x 758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADCSR 0x00 /* A/D Control/Status */ 788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_CHANCSR 0x02 /* Channel Control/Status */ 798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADDAT 0x04 /* A/D data */ 808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACSR 0x06 /* D/A Control/Status */ 818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DADAT 0x08 /* D/A data */ 828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DIODAT 0x0a /* digital data */ 838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SUPCSR 0x0c /* Supervisor Control/Status */ 848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_TMRCTR 0x0e /* Timer/Counter */ 858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * At power up, some registers are in a well-known state. The 888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * masks and values are as follows: 898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADCSR_MASK 0xfff0 928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADCSR_VAL 0x7c00 938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_CHANCSR_MASK 0xf0f0 958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_CHANCSR_VAL 0x70f0 968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACSR_MASK 0x7c93 988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACSR_VAL 0x7c90 998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SUPCSR_MASK 0xf8ff 1018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SUPCSR_VAL 0x0000 1028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_TMRCTR_MASK 0xff00 1048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_TMRCTR_VAL 0xf000 1058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 1078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * Bit fields of each register 1088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 1098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* ADCSR */ 1118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADERR 0x8000 /* (R) 1 for A/D error */ 1138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADCLK 0x0200 /* (R/W) A/D clock enable */ 1148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x7c00 read as 1's */ 1158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_MUXBUSY 0x0100 /* (R) multiplexer busy */ 1168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADDONE 0x0080 /* (R) A/D done */ 1178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_IADDONE 0x0040 /* (R/W) interrupt on A/D done */ 1188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x0030 gain select */ 1198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x000f channel select */ 1208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* CHANCSR */ 1228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_LLE 0x8000 /* (R/W) Load List Enable */ 1248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x7000 read as 1's */ 1258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x0f00 (R) present address */ 1268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x00f0 read as 1's */ 1278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* 0x000f (R) number of entries - 1 */ 1288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* DACSR */ 1308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DAERR 0x8000 /* (R) D/A error */ 1328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_YSEL 0x0200 /* (R/W) DAC 1 select */ 1338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SSEL 0x0100 /* (R/W) single channel select */ 1348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACRDY 0x0080 /* (R) DAC ready */ 1358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_IDARDY 0x0040 /* (R/W) interrupt on DAC ready */ 1368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACLK 0x0020 /* (R/W) D/A clock enable */ 1378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_HBOE 0x0002 /* (R/W) DIO high byte output enable */ 1388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_LBOE 0x0001 /* (R/W) DIO low byte output enable */ 1398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* SUPCSR */ 1418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DMAD 0x8000 /* (R) DMA done */ 1438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ERRINTEN 0x4000 /* (R/W) interrupt on error */ 1448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_CLRDMADNE 0x2000 /* (W) clear DMA done */ 1458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DDMA 0x1000 /* (R/W) dual DMA */ 1468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DS1 0x0800 /* (R/W) DMA select 1 */ 1478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DS0 0x0400 /* (R/W) DMA select 0 */ 1488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_BUFFB 0x0200 /* (R/W) buffer B selected */ 1498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_SCDN 0x0100 /* (R) scan done */ 1508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACON 0x0080 /* (W) DAC single conversion */ 1518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_ADCINIT 0x0040 /* (W) A/D initialize */ 1528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_DACINIT 0x0020 /* (W) D/A initialize */ 1538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_PRLD 0x0010 /* (W) preload multiplexer */ 1548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_STRIG 0x0008 /* (W) software trigger */ 1558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_XTRIG 0x0004 /* (R/W) external trigger enable */ 1568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_XCLK 0x0002 /* (R/W) external clock enable */ 1578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define DT2821_BDINIT 0x0001 /* (W) initialize board */ 1588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 15918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_lo_bipolar = { 16018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 16118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-10, 10), 16218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-5, 5), 16318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-2.5, 2.5), 16418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-1.25, 1.25) 16518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 1668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 1670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 16818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_lo_unipolar = { 16918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 17018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 10), 17118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 5), 17218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 2.5), 17318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 1.25) 17418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 1758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 1760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 17718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_5_bipolar = { 17818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 17918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-5, 5), 18018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-2.5, 2.5), 18118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-1.25, 1.25), 18218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-0.625, 0.625) 18318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 1848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 1850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 18618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_5_unipolar = { 18718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 18818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 5), 18918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 2.5), 19018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 1.25), 19118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 0.625), 19218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 1938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 19518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_hi_bipolar = { 19618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 19718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-10, 10), 19818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-1, 1), 19918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-0.1, 0.1), 20018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(-0.02, 0.02) 20118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 2028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 2030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 20418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherstatic const struct comedi_lrange range_dt282x_ai_hi_unipolar = { 20518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 4, { 20618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 10), 20718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 1), 20818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 0.1), 20918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher RANGE(0, 0.02) 21018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } 2118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 2128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 21398484c1ae621eb784c4b2a7dd6c76a069bad6214Bill Pembertonstruct dt282x_board { 2148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef const char *name; 2158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int adbits; 2168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int adchan_se; 2178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int adchan_di; 2188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ai_speed; 2198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ispgl; 2208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dachan; 2218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dabits; 22298484c1ae621eb784c4b2a7dd6c76a069bad6214Bill Pemberton}; 2238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 22498484c1ae621eb784c4b2a7dd6c76a069bad6214Bill Pembertonstatic const struct dt282x_board boardtypes[] = { 22568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2821", 22668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 22768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 22868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 22968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 20000, 23068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 23168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 23268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 23468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2821-f", 23568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 23668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 23768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 23868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 6500, 23968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 24068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 24168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 24368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2821-g", 24468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 24568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 24668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 24768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 4000, 24868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 24968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 25068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 25268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2823", 25368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 16, 25468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 0, 25568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 4, 25668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 25768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 25868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 25968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 16, 2600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 26168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2824-pgh", 2620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .adbits = 12, 2630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .adchan_se = 16, 2640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .adchan_di = 8, 2650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_speed = 20000, 2660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ispgl = 0, 2670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dachan = 0, 2680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dabits = 0, 2690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 27068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2824-pgl", 27168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 27268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 27368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 27468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 20000, 27568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 1, 27668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 0, 27768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 0, 2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 27968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2825", 28068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 28168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 28268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 28368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 20000, 28468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 1, 28568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 28668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 28868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2827", 28968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 16, 29068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 0, 29168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 4, 29268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 29368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 29468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 29568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 29768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2828", 29868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 29968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 4, 30068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 0, 30168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 30268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 30368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 30468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 30668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt2829", 30768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 16, 30868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 8, 30968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 0, 31068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 33250, 31168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 31268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 31368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 16, 3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 31568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt21-ez", 31668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 31768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 31868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 31968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 32068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 32168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 2, 32268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 12, 3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 32468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt23-ez", 32568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 16, 32668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 32768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 32868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 32968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 33068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 0, 33168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 0, 3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 33368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt24-ez", 33468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 33568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 33668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 33768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 33868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 0, 33968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 0, 34068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 0, 3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 34268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton {.name = "dt24-ez-pgl", 34368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adbits = 12, 34468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_se = 16, 34568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .adchan_di = 8, 34668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ai_speed = 10000, 34768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .ispgl = 1, 34868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dachan = 0, 34968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .dabits = 0, 3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 3518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 3528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 35318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dt282x_board)) 35498484c1ae621eb784c4b2a7dd6c76a069bad6214Bill Pemberton#define this_board ((const struct dt282x_board *)dev->board_ptr) 3558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 35668b08cdad78c79fc87df52f8c8d4adf60ec5d7fcBill Pembertonstruct dt282x_private { 3578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ad_2scomp; /* we have 2's comp jumper set */ 3588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int da0_2scomp; /* same, for DAC0 */ 3598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int da1_2scomp; /* same, for DAC1 */ 3608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3619ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton const struct comedi_lrange *darangelist[2]; 3628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 363790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short ao[2]; 3648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int dacsr; /* software copies of registers */ 3668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int adcsr; 3678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int supcsr; 3688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int ntrig; 3708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int nread; 3718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef struct { 3738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int chan; 3748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef short *buf; /* DMA buffer */ 3758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int size; /* size of current transfer */ 3768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } dma[2]; 3778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dma_maxsize; /* max size of DMA transfer (in bytes) */ 3788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int usedma; /* driver uses DMA */ 3798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef volatile int current_dma_index; 3808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dma_dir; 38168b08cdad78c79fc87df52f8c8d4adf60ec5d7fcBill Pemberton}; 3828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 38368b08cdad78c79fc87df52f8c8d4adf60ec5d7fcBill Pemberton#define devpriv ((struct dt282x_private *)dev->private) 38498484c1ae621eb784c4b2a7dd6c76a069bad6214Bill Pemberton#define boardtype (*(const struct dt282x_board *)dev->board_ptr) 3858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 3878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * Some useless abstractions 3888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 3898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define chan_to_DAC(a) ((a)&1) 390f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton#define update_dacsr(a) outw(devpriv->dacsr|(a), dev->iobase+DT2821_DACSR) 391f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton#define update_adcsr(a) outw(devpriv->adcsr|(a), dev->iobase+DT2821_ADCSR) 3928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY) 3938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE) 39418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher#define update_supcsr(a) outw(devpriv->supcsr|(a), dev->iobase+DT2821_SUPCSR) 3958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 3978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * danger! macro abuse... a is the expression to wait on, and b is 3988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * the statement(s) to execute if it doesn't happen. 3998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 40018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher#define wait_for(a, b) \ 40118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher do { \ 40218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher int _i; \ 40318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher for (_i = 0; _i < DT2821_TIMEOUT; _i++) { \ 40418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (a) { \ 40518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher _i = 0; \ 40618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher break; \ 40718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } \ 40818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher udelay(5); \ 40918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } \ 41018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (_i) \ 41118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher b \ 41218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher } while (0) 4138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_attach(struct comedi_device *dev, 4150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 416da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_detach(struct comedi_device *dev); 417139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_dt282x = { 41868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "dt282x", 41968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 42068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = dt282x_attach, 42168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = dt282x_detach, 42268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &boardtypes[0].name, 42368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .num_names = n_boardtypes, 42468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct dt282x_board), 4258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 4268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4277114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_dt282x_init_module(void) 4287114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 4297114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_dt282x); 4307114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 4317114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 4327114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_dt282x_cleanup_module(void) 4337114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 4347114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_dt282x); 4357114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 4367114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 4377114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_dt282x_init_module); 4387114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_dt282x_cleanup_module); 4398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 440da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void free_resources(struct comedi_device *dev); 441da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int prep_ai_dma(struct comedi_device *dev, int chan, int size); 442da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int prep_ao_dma(struct comedi_device *dev, int chan, int size); 4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ai_cancel(struct comedi_device *dev, 4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s); 4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_cancel(struct comedi_device *dev, 4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s); 4478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleefstatic int dt282x_ns_to_timer(int *nanosec, int round_mode); 448da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_disable_dma(struct comedi_device *dev); 4498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 450da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2); 4518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 452da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_munge(struct comedi_device *dev, short *buf, 4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int nbytes) 4548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 4558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned int i; 4568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned short mask = (1 << boardtype.adbits) - 1; 4578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned short sign = 1 << (boardtype.adbits - 1); 4588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int n; 4598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 46018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (devpriv->ad_2scomp) 4618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef sign = 1 << (boardtype.adbits - 1); 46218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher else 4638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef sign = 0; 4648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (nbytes % 2) 4668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, "bug! odd number of bytes from dma xfer"); 4678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef n = nbytes / 2; 46818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher for (i = 0; i < n; i++) 4698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef buf[i] = (buf[i] & mask) ^ sign; 4708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 4718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 472da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_ao_dma_interrupt(struct comedi_device *dev) 4738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 4748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef void *ptr; 4758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int size; 4768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int i; 47734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->subdevices + 1; 4788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_CLRDMADNE); 4808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!s->async->prealloc_buf) { 48218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR "async->data disappeared. dang!\n"); 4838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 4848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 4858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef i = devpriv->current_dma_index; 4878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ptr = devpriv->dma[i].buf; 4888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef disable_dma(devpriv->dma[i].chan); 4908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->current_dma_index = 1 - i; 4928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize); 4948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (size == 0) { 49518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR "dt282x: AO underrun\n"); 4968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ao_cancel(dev, s); 4978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_OVERFLOW; 4988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 4998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ao_dma(dev, i, size); 5018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 5028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 5038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 504da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_ai_dma_interrupt(struct comedi_device *dev) 5058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 5068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef void *ptr; 5078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int size; 5088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int i; 5098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ret; 51034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->subdevices; 5118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_CLRDMADNE); 5138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!s->async->prealloc_buf) { 51518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR "async->data disappeared. dang!\n"); 5168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 5178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef i = devpriv->current_dma_index; 5208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ptr = devpriv->dma[i].buf; 5218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef size = devpriv->dma[i].size; 5228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef disable_dma(devpriv->dma[i].chan); 5248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->current_dma_index = 1 - i; 5268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_munge(dev, ptr, size); 5288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ret = cfc_write_array_to_buffer(s, ptr, size); 5298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ret != size) { 5308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ai_cancel(dev, s); 5318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 5328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->nread -= size / 2; 5348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->nread < 0) { 53618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO "dt282x: off by one\n"); 5378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->nread = 0; 5388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!devpriv->nread) { 5408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ai_cancel(dev, s); 5418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_EOA; 5428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return; 5438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#if 0 5458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* clear the dual dma flag, making this the last dma segment */ 5468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* XXX probably wrong */ 5478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!devpriv->ntrig) { 5488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr &= ~(DT2821_DDMA); 5498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(0); 5508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 5518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 5528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* restart the channel */ 5538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ai_dma(dev, i, 0); 5548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 5558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 556da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int prep_ai_dma(struct comedi_device *dev, int dma_index, int n) 5578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 5588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dma_chan; 5598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long dma_ptr; 5608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long flags; 5618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!devpriv->ntrig) 5638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 5648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (n == 0) 5668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef n = devpriv->dma_maxsize; 5678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (n > devpriv->ntrig * 2) 5688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef n = devpriv->ntrig * 2; 5698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->ntrig -= n / 2; 5708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[dma_index].size = n; 5728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma_chan = devpriv->dma[dma_index].chan; 5738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); 5748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_mode(dma_chan, DMA_MODE_READ); 5768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef flags = claim_dma_lock(); 5778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef clear_dma_ff(dma_chan); 5788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_addr(dma_chan, dma_ptr); 5798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_count(dma_chan, n); 5808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef release_dma_lock(flags); 5818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef enable_dma(dma_chan); 5838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return n; 5858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 5868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 587da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int prep_ao_dma(struct comedi_device *dev, int dma_index, int n) 5888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 5898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int dma_chan; 5908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long dma_ptr; 5918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long flags; 5928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[dma_index].size = n; 5948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma_chan = devpriv->dma[dma_index].chan; 5958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); 5968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_mode(dma_chan, DMA_MODE_WRITE); 5988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef flags = claim_dma_lock(); 5998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef clear_dma_ff(dma_chan); 6008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_addr(dma_chan, dma_ptr); 6018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef set_dma_count(dma_chan, n); 6028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef release_dma_lock(flags); 6038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef enable_dma(dma_chan); 6058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return n; 6078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 6088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 60970265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t dt282x_interrupt(int irq, void *d) 6108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 61171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = d; 61234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 61334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s_ao; 6148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned int supcsr, adcsr, dacsr; 6158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int handled = 0; 6168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!dev->attached) { 6188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, "spurious interrupt"); 6198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return IRQ_HANDLED; 6208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s = dev->subdevices + 0; 6238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s_ao = dev->subdevices + 1; 6248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef adcsr = inw(dev->iobase + DT2821_ADCSR); 6258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dacsr = inw(dev->iobase + DT2821_DACSR); 6268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef supcsr = inw(dev->iobase + DT2821_SUPCSR); 6278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (supcsr & DT2821_DMAD) { 6288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->dma_dir == DMA_MODE_READ) 6298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ai_dma_interrupt(dev); 6308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef else 6318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ao_dma_interrupt(dev); 6328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef handled = 1; 6338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (adcsr & DT2821_ADERR) { 6358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->nread != 0) { 6368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, "A/D error"); 6378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ai_cancel(dev, s); 6388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_ERROR; 6398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef handled = 1; 6418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (dacsr & DT2821_DAERR) { 6438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#if 0 6448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef static int warn = 5; 6458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (--warn <= 0) { 6468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef disable_irq(dev->irq); 64718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO "disabling irq\n"); 6488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 6508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, "D/A error"); 6518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ao_cancel(dev, s_ao); 6528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_ERROR; 6538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef handled = 1; 6548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#if 0 6568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (adcsr & DT2821_ADDONE) { 6578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ret; 658790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short data; 6598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data = (short)inw(dev->iobase + DT2821_ADDAT); 6618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data &= (1 << boardtype.adbits) - 1; 66218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 66318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (devpriv->ad_2scomp) 6648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data ^= 1 << (boardtype.adbits - 1); 6658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ret = comedi_buf_put(s->async, data); 66618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher 66718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (ret == 0) 6688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_OVERFLOW; 6698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->nread--; 6718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!devpriv->nread) { 6728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->events |= COMEDI_CB_EOA; 6738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 6748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (supcsr & DT2821_SCDN) 6758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_STRIG); 6768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef handled = 1; 6788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 6808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_event(dev, s); 68118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher /* printk("adcsr=0x%02x dacsr-0x%02x supcsr=0x%02x\n", 68218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher adcsr, dacsr, supcsr); */ 6838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return IRQ_RETVAL(handled); 6848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 6858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 686da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_load_changain(struct comedi_device *dev, int n, 6870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *chanlist) 6888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 6898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned int i; 6908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned int chan, range; 6918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(DT2821_LLE | (n - 1), dev->iobase + DT2821_CHANCSR); 6938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef for (i = 0; i < n; i++) { 6948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef chan = CR_CHAN(chanlist[i]); 6958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef range = CR_RANGE(chanlist[i]); 6968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_adcsr((range << 4) | (chan)); 6978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 6988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(n - 1, dev->iobase + DT2821_CHANCSR); 6998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 7008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 7028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * Performs a single A/D conversion. 7038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * - Put channel/gain into channel-gain list 7048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * - preload multiplexer 7058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * - trigger conversion and wait for it to finish 7068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 7070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ai_insn_read(struct comedi_device *dev, 7080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 7108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 7118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int i; 7128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* XXX should we really be enabling the ad clock here? */ 7148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->adcsr = DT2821_ADCLK; 7158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_adcsr(0); 7168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_load_changain(dev, 1, &insn->chanspec); 7188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_PRLD); 7200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); 7218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef for (i = 0; i < insn->n; i++) { 7238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_STRIG); 7248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef wait_for(ad_done(), comedi_error(dev, "timeout\n"); 7250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral return -ETIME;); 7268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data[i] = 7280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + 7298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef DT2821_ADDAT) & ((1 << boardtype.adbits) - 1); 7308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->ad_2scomp) 7318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data[i] ^= (1 << (boardtype.adbits - 1)); 7328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 7338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return i; 7358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 7368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ai_cmdtest(struct comedi_device *dev, 7380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 7398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 7408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int err = 0; 7418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int tmp; 7428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 1: make sure trigger sources are trivially valid */ 7448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->start_src; 7468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->start_src &= TRIG_NOW; 7478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->start_src || tmp != cmd->start_src) 7488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->scan_begin_src; 7518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT; 7528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 7538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->convert_src; 7568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_src &= TRIG_TIMER; 7578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 7588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->scan_end_src; 7618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_end_src &= TRIG_COUNT; 7628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 7638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->stop_src; 7668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 7678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 7688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 7718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 7728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 77318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher /* 77418e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher * step 2: make sure trigger sources are unique 77518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher * and mutually compatible 77618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher */ 7778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 778828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel /* note that mutual compatibility is not an issue here */ 7798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_src != TRIG_FOLLOW && 7800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_EXT) 7818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 7838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 7868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 2; 7878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 3: make sure arguments are trivially compatible */ 7898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->start_arg != 0) { 7918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->start_arg = 0; 7928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 7948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_src == TRIG_FOLLOW) { 7958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* internal trigger */ 7968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_arg != 0) { 7978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_begin_arg = 0; 7988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 7998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 8018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* external trigger */ 8028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* should be level/edge, hi/lo specification here */ 8038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_arg != 0) { 8048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_begin_arg = 0; 8058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->convert_arg < 4000) { 8098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* XXX board dependent */ 8108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_arg = 4000; 8118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#define SLOWEST_TIMER (250*(1<<15)*255) 8148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->convert_arg > SLOWEST_TIMER) { 8158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_arg = SLOWEST_TIMER; 8168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->convert_arg < this_board->ai_speed) { 8198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_arg = this_board->ai_speed; 8208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_end_arg != cmd->chanlist_len) { 8238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_end_arg = cmd->chanlist_len; 8248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_src == TRIG_COUNT) { 8278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* any count is allowed */ 8288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 8298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* TRIG_NONE */ 8308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_arg != 0) { 8318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->stop_arg = 0; 8328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 8378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 3; 8388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 4: fix up any arguments */ 8408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->convert_arg; 8428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ns_to_timer(&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); 8438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (tmp != cmd->convert_arg) 8448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 8458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 8478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 4; 8488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 8508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 8518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 852da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 8538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 854ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 8558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int timer; 8568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->usedma == 0) { 8588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, 85918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher "driver requires 2 dma channels" 86018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher " to execute command"); 8618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EIO; 8628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_disable_dma(dev); 8658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->convert_arg < this_board->ai_speed) 8678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_arg = this_board->ai_speed; 8688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST); 8698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(timer, dev->iobase + DT2821_TMRCTR); 8708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_src == TRIG_FOLLOW) { 8728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* internal trigger */ 8738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0; 8748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 8758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* external trigger */ 8768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1; 8778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT); 8798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; 8818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->nread = devpriv->ntrig; 8828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma_dir = DMA_MODE_READ; 8848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->current_dma_index = 0; 8858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ai_dma(dev, 0, 0); 8868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->ntrig) { 8878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ai_dma(dev, 1, 0); 8888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr |= DT2821_DDMA; 8898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(0); 8908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 8918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->adcsr = 0; 8938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist); 8958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE; 8978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_adcsr(0); 8988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_PRLD); 9000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); 9018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_begin_src == TRIG_FOLLOW) { 9038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_STRIG); 9048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 9058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr |= DT2821_XTRIG; 9068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(0); 9078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 9088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 9108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 9118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 912da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void dt282x_disable_dma(struct comedi_device *dev) 9138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 9148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->usedma) { 9158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef disable_dma(devpriv->dma[0].chan); 9168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef disable_dma(devpriv->dma[1].chan); 9178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 9188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 9198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ai_cancel(struct comedi_device *dev, 9210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 9228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 9238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_disable_dma(dev); 9248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->adcsr = 0; 9268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_adcsr(0); 9278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr = 0; 9298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_ADCINIT); 9308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 9328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 9338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleefstatic int dt282x_ns_to_timer(int *nanosec, int round_mode) 9358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 9368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int prescale, base, divider; 9378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef for (prescale = 0; prescale < 16; prescale++) { 9398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (prescale == 1) 9408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef continue; 9418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef base = 250 * (1 << prescale); 9428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef switch (round_mode) { 9438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef case TRIG_ROUND_NEAREST: 9448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef default: 9458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef divider = (*nanosec + base / 2) / base; 9468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef break; 9478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef case TRIG_ROUND_DOWN: 9488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef divider = (*nanosec) / base; 9498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef break; 9508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef case TRIG_ROUND_UP: 9518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef divider = (*nanosec + base - 1) / base; 9528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef break; 9538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 9548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (divider < 256) { 9558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef *nanosec = divider * base; 9568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return (prescale << 8) | (255 - divider); 9578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 9588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 9598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef base = 250 * (1 << 15); 9608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef divider = 255; 9618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef *nanosec = divider * base; 9628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return (15 << 8) | (255 - divider); 9638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 9648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 9668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * Analog output routine. Selects single channel conversion, 9678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * selects correct channel, converts from 2's compliment to 9688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * offset binary if necessary, loads the data into the DAC 9698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef * data register, and performs the conversion. 9708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 9710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_insn_read(struct comedi_device *dev, 9720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 9730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 9748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 9758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; 9768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 9788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 9798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_insn_write(struct comedi_device *dev, 9810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 9820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 9838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 984790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short d; 9858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned int chan; 9868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef chan = CR_CHAN(insn->chanspec); 9888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef d = data[0]; 9898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef d &= (1 << boardtype.dabits) - 1; 9908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->ao[chan] = d; 9918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr |= DT2821_SSEL; 9938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (chan) { 9958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* select channel */ 9968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr |= DT2821_YSEL; 9978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->da0_2scomp) 9988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef d ^= (1 << (boardtype.dabits - 1)); 9998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 10008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr &= ~DT2821_YSEL; 10018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->da1_2scomp) 10028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef d ^= (1 << (boardtype.dabits - 1)); 10038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_dacsr(0); 10068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(d, dev->iobase + DT2821_DADAT); 10088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_DACON); 10108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 10128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 10138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_cmdtest(struct comedi_device *dev, 10150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 10168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 10178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int err = 0; 10188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int tmp; 10198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 1: make sure trigger sources are trivially valid */ 10218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->start_src; 10238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->start_src &= TRIG_INT; 10248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->start_src || tmp != cmd->start_src) 10258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->scan_begin_src; 10288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_begin_src &= TRIG_TIMER; 10298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 10308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->convert_src; 10338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_src &= TRIG_NOW; 10348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 10358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->scan_end_src; 10388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_end_src &= TRIG_COUNT; 10398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 10408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->stop_src; 10438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->stop_src &= TRIG_NONE; 10448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 10458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 10488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 10498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 105018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher /* 105118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher * step 2: make sure trigger sources are unique 105218e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher * and mutually compatible 105318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher */ 10548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1055828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel /* note that mutual compatibility is not an issue here */ 10568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 10578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 10608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 2; 10618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 3: make sure arguments are trivially compatible */ 10638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->start_arg != 0) { 10658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->start_arg = 0; 10668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 106818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (cmd->scan_begin_arg < 5000 /* XXX unknown */) { 10698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_begin_arg = 5000; 10708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->convert_arg != 0) { 10738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->convert_arg = 0; 10748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->scan_end_arg > 2) { 10778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* XXX chanlist stuff? */ 10788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->scan_end_arg = 2; 10798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_src == TRIG_COUNT) { 10828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* any count is allowed */ 10838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 10848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* TRIG_NONE */ 10858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (cmd->stop_arg != 0) { 10868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef cmd->stop_arg = 0; 10878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 10888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 10908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 10928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 3; 10938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* step 4: fix up any arguments */ 10958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef tmp = cmd->scan_begin_arg; 10978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); 10988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (tmp != cmd->scan_begin_arg) 10998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef err++; 11008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (err) 11028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 4; 11038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 11058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 11078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_inttrig(struct comedi_device *dev, 11090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, unsigned int x) 11108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 11118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int size; 11128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (x != 0) 11148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EINVAL; 11158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf, 11170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->dma_maxsize); 11188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (size == 0) { 111918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR "dt282x: AO underrun\n"); 11208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EPIPE; 11218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 11228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ao_dma(dev, 0, size); 11238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf, 11250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->dma_maxsize); 11268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (size == 0) { 112718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR "dt282x: AO underrun\n"); 11288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EPIPE; 11298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 11308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef prep_ao_dma(dev, 1, size); 11318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_STRIG); 11338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->inttrig = NULL; 11348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 11368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 11378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1138da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 11398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 11408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int timer; 1141ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 11428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->usedma == 0) { 11448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef comedi_error(dev, 114518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher "driver requires 2 dma channels" 114618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher " to execute command"); 11478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EIO; 11488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 11498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_disable_dma(dev); 11518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA; 11538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT); 11548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; 11568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->nread = devpriv->ntrig; 11578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma_dir = DMA_MODE_WRITE; 11598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->current_dma_index = 0; 11608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST); 11628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(timer, dev->iobase + DT2821_TMRCTR); 11638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY; 11658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_dacsr(0); 11668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->async->inttrig = dt282x_ao_inttrig; 11688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 11708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 11718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_ao_cancel(struct comedi_device *dev, 11730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 11748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 11758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dt282x_disable_dma(dev); 11768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr = 0; 11788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_dacsr(0); 11798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->supcsr = 0; 11818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef update_supcsr(DT2821_DACINIT); 11828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 11848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 11858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_dio_insn_bits(struct comedi_device *dev, 11870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 11880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 11898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 11908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (data[0]) { 11918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->state &= ~data[0]; 11928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->state |= (data[0] & data[1]); 11938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(s->state, dev->iobase + DT2821_DIODAT); 11958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 11968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef data[1] = inw(dev->iobase + DT2821_DIODAT); 11978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 11988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 2; 11998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 12008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt282x_dio_insn_config(struct comedi_device *dev, 12020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 12030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 12048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 12058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int mask; 12068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef mask = (CR_CHAN(insn->chanspec) < 8) ? 0x00ff : 0xff00; 12088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (data[0]) 12098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->io_bits |= mask; 12108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef else 12118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->io_bits &= ~mask; 12128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (s->io_bits & 0x00ff) 12148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr |= DT2821_LBOE; 12158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef else 12168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr &= ~DT2821_LBOE; 12178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (s->io_bits & 0xff00) 12188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr |= DT2821_HBOE; 12198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef else 12208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dacsr &= ~DT2821_HBOE; 12218d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); 12238d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 1; 12258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 12268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12279ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange *const ai_range_table[] = { 12288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_lo_bipolar, 12298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_lo_unipolar, 12308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_5_bipolar, 12318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_5_unipolar 12328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 12330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 12349ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange *const ai_range_pgl_table[] = { 12358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_hi_bipolar, 12368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_dt282x_ai_hi_unipolar 12378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 12380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 12399ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) 12408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 12418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ispgl) { 12428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (x < 0 || x >= 2) 12438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef x = 0; 12448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ai_range_pgl_table[x]; 12458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 12468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (x < 0 || x >= 4) 12478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef x = 0; 12488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ai_range_table[x]; 12498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 12508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 12510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 12529ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange *const ao_range_table[] = { 12538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_bipolar10, 12548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_unipolar10, 12558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_bipolar5, 12568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_unipolar5, 12578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef &range_bipolar2_5 12588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 12590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 12609ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange *opt_ao_range_lkup(int x) 12618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 12628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (x < 0 || x >= 5) 12638d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef x = 0; 12648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ao_range_table[x]; 12658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 12668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 126718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcherenum { /* i/o base, irq, dma channels */ 126818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher opt_iobase = 0, opt_irq, opt_dma1, opt_dma2, 12698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef opt_diff, /* differential */ 12708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef opt_ai_twos, opt_ao0_twos, opt_ao1_twos, /* twos comp */ 12718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef opt_ai_range, opt_ao0_range, opt_ao1_range, /* range */ 12728d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef}; 12738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef/* 12758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef options: 12768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 0 i/o base 12778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1 irq 12788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 2 dma1 12798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 3 dma2 12808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 4 0=single ended, 1=differential 12818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 5 ai 0=straight binary, 1=2's comp 12828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 6 ao0 0=straight binary, 1=2's comp 12838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 7 ao1 0=straight binary, 1=2's comp 12848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 8 ai 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V 12858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 9 ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V 12868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 10 ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V 12878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef */ 1288da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) 12898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 12908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int i, irq; 12918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ret; 129234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 12938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long iobase; 12948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dev->board_name = this_board->name; 12968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 12978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef iobase = it->options[opt_iobase]; 12988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!iobase) 12998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef iobase = 0x240; 13008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 130118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO "comedi%d: dt282x: 0x%04lx", dev->minor, iobase); 13028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!request_region(iobase, DT2821_SIZE, "dt282x")) { 130318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " I/O port conflict\n"); 13048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EBUSY; 13058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 13068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dev->iobase = iobase; 13078d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR); 13098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef i = inw(dev->iobase + DT2821_ADCSR); 13108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#ifdef DEBUG 131118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_DEBUG " fingerprint=%x,%x,%x,%x,%x", 13120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + DT2821_ADCSR), 13130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + DT2821_CHANCSR), 13140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + DT2821_DACSR), 13150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + DT2821_SUPCSR), 13160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral inw(dev->iobase + DT2821_TMRCTR)); 13178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 13188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (((inw(dev->iobase + DT2821_ADCSR) & DT2821_ADCSR_MASK) 13200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != DT2821_ADCSR_VAL) || 13210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((inw(dev->iobase + DT2821_CHANCSR) & DT2821_CHANCSR_MASK) 13220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != DT2821_CHANCSR_VAL) || 13230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((inw(dev->iobase + DT2821_DACSR) & DT2821_DACSR_MASK) 13240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != DT2821_DACSR_VAL) || 13250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((inw(dev->iobase + DT2821_SUPCSR) & DT2821_SUPCSR_MASK) 13260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != DT2821_SUPCSR_VAL) || 13270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((inw(dev->iobase + DT2821_TMRCTR) & DT2821_TMRCTR_MASK) 13280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != DT2821_TMRCTR_VAL)) { 132918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR " board not found"); 13308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EIO; 13318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 13328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* should do board test */ 13338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef irq = it->options[opt_irq]; 13358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#if 0 13368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (irq < 0) { 13378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef unsigned long flags; 13388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int irqs; 13398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13408d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef save_flags(flags); 13418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef sti(); 13428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef irqs = probe_irq_on(); 13438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* trigger interrupt */ 13458d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13465f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(100); 13478d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13488d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef irq = probe_irq_off(irqs); 13498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef restore_flags(flags); 135018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (0 /* error */) 135118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR " error probing irq (bad)"); 13528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 13538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 13548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (irq > 0) { 135518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " ( irq = %d )", irq); 13565f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman ret = request_irq(irq, dt282x_interrupt, 0, "dt282x", dev); 13578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ret < 0) { 135818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR " failed to get irq\n"); 13598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EIO; 13608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 13618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dev->irq = irq; 13628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else if (irq == 0) { 136318e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " (no irq)"); 13648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 13658d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#if 0 136618e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " (probe returned multiple irqs--bad)"); 13678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#else 136818e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " (irq probe not implemented)"); 13698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef#endif 13708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 13718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1372c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_private(dev, sizeof(struct dt282x_private)); 1373c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 13748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ret; 13758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ret = dt282x_grab_dma(dev, it->options[opt_dma1], 13770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral it->options[opt_dma2]); 13788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ret < 0) 13798d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ret; 13808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1381c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_subdevices(dev, 3); 1382c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 13838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return ret; 13848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s = dev->subdevices + 0; 13868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 13878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dev->read_subdev = s; 13888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* ai subdevice */ 13898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->type = COMEDI_SUBD_AI; 13908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->subdev_flags = SDF_READABLE | SDF_CMD_READ | 13910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON); 13928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->n_chan = 13930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (it->options[opt_diff]) ? boardtype.adchan_di : boardtype.adchan_se; 13948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->insn_read = dt282x_ai_insn_read; 13958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->do_cmdtest = dt282x_ai_cmdtest; 13968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->do_cmd = dt282x_ai_cmd; 13978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->cancel = dt282x_ai_cancel; 13988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->maxdata = (1 << boardtype.adbits) - 1; 13998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->len_chanlist = 16; 14008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->range_table = 14010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral opt_ai_range_lkup(boardtype.ispgl, it->options[opt_ai_range]); 14028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->ad_2scomp = it->options[opt_ai_twos]; 14038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s++; 1405c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 1406c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton s->n_chan = boardtype.dachan; 1407c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (s->n_chan) { 14088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* ao subsystem */ 14098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->type = COMEDI_SUBD_AO; 14108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dev->write_subdev = s; 14118d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->subdev_flags = SDF_WRITABLE | SDF_CMD_WRITE; 14128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->insn_read = dt282x_ao_insn_read; 14138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->insn_write = dt282x_ao_insn_write; 14148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->do_cmdtest = dt282x_ao_cmdtest; 14158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->do_cmd = dt282x_ao_cmd; 14168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->cancel = dt282x_ao_cancel; 14178d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->maxdata = (1 << boardtype.dabits) - 1; 14188d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->len_chanlist = 2; 14198d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->range_table_list = devpriv->darangelist; 14208d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->darangelist[0] = 14210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral opt_ao_range_lkup(it->options[opt_ao0_range]); 14228d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->darangelist[1] = 14230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral opt_ao_range_lkup(it->options[opt_ao1_range]); 14248d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->da0_2scomp = it->options[opt_ao0_twos]; 14258d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->da1_2scomp = it->options[opt_ao1_twos]; 14268d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } else { 14278d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->type = COMEDI_SUBD_UNUSED; 14288d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 14298d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14308d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s++; 14318d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef /* dio subsystem */ 14328d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->type = COMEDI_SUBD_DIO; 14338d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 14348d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->n_chan = 16; 14358d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->insn_bits = dt282x_dio_insn_bits; 14368d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->insn_config = dt282x_dio_insn_config; 14378d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->maxdata = 1; 14388d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef s->range_table = &range_digital; 14398d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 144018e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO "\n"); 14418d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14428d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 14438d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 14448d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1445da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void free_resources(struct comedi_device *dev) 14468d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 144718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher if (dev->irq) 14485f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(dev->irq, dev); 14498d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (dev->iobase) 14508d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef release_region(dev->iobase, DT2821_SIZE); 14518d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (dev->private) { 14528d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->dma[0].chan) 14538d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef free_dma(devpriv->dma[0].chan); 14548d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->dma[1].chan) 14558d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef free_dma(devpriv->dma[1].chan); 14568d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->dma[0].buf) 14578d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef free_page((unsigned long)devpriv->dma[0].buf); 14588d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (devpriv->dma[1].buf) 14598d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef free_page((unsigned long)devpriv->dma[1].buf); 14608d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 14618d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 14628d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1463da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_detach(struct comedi_device *dev) 14648d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 146518e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO "comedi%d: dt282x: remove\n", dev->minor); 14668d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14678d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef free_resources(dev); 14688d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14698d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 14708d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 14718d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 1472da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) 14738d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef{ 14748d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int ret; 14758d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14768d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->usedma = 0; 14778d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14788d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!dma1 && !dma2) { 147918e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR " (no dma)"); 14808d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 14818d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 14828d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14838d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7) 14848d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EINVAL; 14858d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14868d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (dma2 < dma1) { 14878d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef int i; 14888d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef i = dma1; 14898d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma1 = dma2; 14908d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef dma2 = i; 14918d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 14928d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14938d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ret = request_dma(dma1, "dt282x A"); 14948d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ret) 14958d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EBUSY; 14968d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[0].chan = dma1; 14978d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 14988d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef ret = request_dma(dma2, "dt282x B"); 14998d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (ret) 15008d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -EBUSY; 15018d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[1].chan = dma2; 15028d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 15038d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma_maxsize = PAGE_SIZE; 15048d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); 15058d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); 15068d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) { 150718e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_ERR " can't get DMA memory"); 15088d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return -ENOMEM; 15098d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef } 15108d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 151118e7e78e945527d9cb570a17f0835815f1794c2fIain Churcher printk(KERN_INFO " (dma=%d,%d)", dma1, dma2); 15128d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 15138d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef devpriv->usedma = 1; 15148d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef 15158d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef return 0; 15168d3d823c74a4c967b4a02e6466c6727ad21422a0David Schleef} 151790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 151890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 151990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 152090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 1521