13726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/*
23726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    comedi/drivers/das800.c
33726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    Driver for Keitley das800 series boards and compatibles
43726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
53726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
63726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    COMEDI - Linux Control and Measurement Device Interface
73726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
83726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
93726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    This program is free software; you can redistribute it and/or modify
103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    it under the terms of the GNU General Public License as published by
113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    the Free Software Foundation; either version 2 of the License, or
123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    (at your option) any later version.
133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    This program is distributed in the hope that it will be useful,
153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    but WITHOUT ANY WARRANTY; without even the implied warranty of
163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    GNU General Public License for more details.
183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    You should have received a copy of the GNU General Public License
203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    along with this program; if not, write to the Free Software
213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess************************************************************************
243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess*/
253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/*
263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessDriver: das800
273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessDescription: Keithley Metrabyte DAS800 (& compatibles)
283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessAuthor: Frank Mori Hess <fmhess@users.sourceforge.net>
293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessDevices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  DAS-802 (das-802),
313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  [Measurement Computing] CIO-DAS800 (cio-das800),
323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  CIO-DAS802/16 (cio-das802/16)
343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessStatus: works, cio-das802/16 untested - email me if you have tested it
353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessConfiguration options:
373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  [0] - I/O port base address
383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess  [1] - IRQ (optional, required for timed or externally triggered conversions)
393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori HessNotes:
413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	IRQ can be omitted, although the cmd interface will not work without it.
423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	All entries in the channel/gain list must use the same gain and be
443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	consecutive channels counting upwards in channel number (these are
453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	hardware limitations.)
463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	I've never tested the gain setting stuff since I only have a
483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	DAS-800 board with fixed gain.
493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	The cio-das802/16 does not have a fifo-empty status bit!  Therefore
513726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	only fifo-half-full transfers are possible with this card.
523726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess*/
533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/*
543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
553726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hesscmd triggers supported:
563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	start_src:      TRIG_NOW | TRIG_EXT
573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	scan_begin_src: TRIG_FOLLOW
583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	scan_end_src:   TRIG_COUNT
593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	convert_src:    TRIG_TIMER | TRIG_EXT
603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	stop_src:       TRIG_NONE | TRIG_COUNT
613726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess*/
643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6525436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#include "../comedidev.h"
673726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#include <linux/ioport.h>
693726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#include <linux/delay.h>
703726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#include "8253.h"
723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#include "comedi_fc.h"
733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_SIZE           8
753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define TIMER_BASE            1000
762696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define N_CHAN_AI             8	/*  number of analog input channels */
773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* Registers for the das800 */
793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_LSB            0
813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   FIFO_EMPTY            0x1
823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   FIFO_OVF              0x2
833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_MSB            1
843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_CONTROL1       2
853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   CONTROL1_INTE         0x8
863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_CONV_CONTROL   2
873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   ITE                   0x1
883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   CASC                  0x2
893726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   DTEN                  0x4
903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   IEOC                  0x8
913726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   EACS                  0x10
923726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   CONV_HCEN             0x80
933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_SCAN_LIMITS    2
943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_STATUS         2
953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   IRQ                   0x8
963726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   BUSY                  0x80
973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_GAIN           3
982696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define   CIO_FFOV              0x8	/*  fifo overflow for cio-das802/16 */
992696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define   CIO_ENHF              0x90	/*  interrupt fifo half full for cio-das802/16 */
1003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   CONTROL1              0x80
1013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   CONV_CONTROL          0xa0
1023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   SCAN_LIMITS           0xc0
1033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   ID                    0xe0
1043726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_8254           4
1053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_STATUS2        7
1063726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   STATUS2_HCEN          0x80
1073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define   STATUS2_INTE          0X20
1083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess#define DAS800_ID             7
1093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
110febc2ed696fe88e3e438554f94dc0d2901a37c1fBill Pembertonstruct das800_board {
1113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	const char *name;
1123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int ai_speed;
1139ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ai_range;
1143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int resolution;
115febc2ed696fe88e3e438554f94dc0d2901a37c1fBill Pemberton};
1163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1172696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* analog input ranges */
1189ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_das800_ai = {
1193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	1,
1203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
1233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
1243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1259ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_das801_ai = {
1263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	9,
1273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 10),
1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.5, 0.5),
1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1),
1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.05, 0.05),
1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.1),
1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.01, 0.01),
1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.02),
1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
1383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
1393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1409ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_cio_das801_ai = {
1413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	9,
1423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
1440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
1450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 10),
1460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.5, 0.5),
1470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1),
1480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.05, 0.05),
1490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.1),
1500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.005, 0.005),
1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.01),
1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
1533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
1543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1559ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_das802_ai = {
1563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	9,
1573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
1590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
1600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 10),
1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-2.5, 2.5),
1620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 5),
1630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-1.25, 1.25),
1640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 2.5),
1650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.625, 0.625),
1660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1.25),
1670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
1683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
1693726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1709ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_das80216_ai = {
1713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	8,
1723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
1740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 10),
1750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
1760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 5),
1770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-2.5, 2.5),
1780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 2.5),
1790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-1.25, 1.25),
1800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1.25),
1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
1823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
1833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
1843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hessenum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 };
1853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
186febc2ed696fe88e3e438554f94dc0d2901a37c1fBill Pembertonstatic const struct das800_board das800_boards[] = {
1873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-800",
1890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 25000,
1900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das800_ai,
1910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
1920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
1933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "cio-das800",
1950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 20000,
1960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das800_ai,
1970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
1980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
1993726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
2000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-801",
2010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 25000,
2020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das801_ai,
2030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
2053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
2060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "cio-das801",
2070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 20000,
2080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_cio_das801_ai,
2090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
2113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
2120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-802",
2130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 25000,
2140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das802_ai,
2150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
2173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
2180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "cio-das802",
2190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 20000,
2200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das802_ai,
2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
2233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	{
2240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "cio-das802/16",
2250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 10000,
2260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range = &range_das80216_ai,
2270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 16,
2280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
2293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
2303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/*
2323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess * Useful for shorthand access to the particular board structure
2333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess */
234febc2ed696fe88e3e438554f94dc0d2901a37c1fBill Pemberton#define thisboard ((const struct das800_board *)dev->board_ptr)
2353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
236938f185d4eea489ad802554e2faef9c99e377aa5Bill Pembertonstruct das800_private {
2373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	volatile unsigned int count;	/* number of data points left to be taken */
2383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	volatile int forever;	/* flag indicating whether we should take data forever */
2393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
2403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
2413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	volatile int do_bits;	/* digital output bits */
242938f185d4eea489ad802554e2faef9c99e377aa5Bill Pemberton};
2433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
244938f185d4eea489ad802554e2faef9c99e377aa5Bill Pemberton#define devpriv ((struct das800_private *)dev->private)
2453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_attach(struct comedi_device *dev,
2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			 struct comedi_devconfig *it);
248da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_detach(struct comedi_device *dev);
249da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
2503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
251139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das800 = {
25268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "das800",
25368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
25468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das800_attach,
25568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das800_detach,
2568629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton	.num_names = ARRAY_SIZE(das800_boards),
25768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &das800_boards[0].name,
25868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct das800_board),
2593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
2603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
26170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das800_interrupt(int irq, void *d);
262814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void enable_das800(struct comedi_device *dev);
263814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void disable_das800(struct comedi_device *dev);
2640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_do_cmdtest(struct comedi_device *dev,
2650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
2660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd);
2670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_do_cmd(struct comedi_device *dev,
2680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
2690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_rinsn(struct comedi_device *dev,
2700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
2710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
2720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_di_rbits(struct comedi_device *dev,
2730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
2740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
2750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_do_wbits(struct comedi_device *dev,
2760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
2770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
278814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das800_probe(struct comedi_device *dev);
279814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das800_set_frequency(struct comedi_device *dev);
2803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* checks and probes das-800 series board type */
282814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das800_probe(struct comedi_device *dev)
2833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
2843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int id_bits;
2853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
2863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int board;
2873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing */
2895f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
2903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(ID, dev->iobase + DAS800_GAIN);	/* select base address + 7 to be ID register */
2913726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	id_bits = inb(dev->iobase + DAS800_ID) & 0x3;	/* get id bits */
2925f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
2933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	board = thisboard - das800_boards;
2953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
2963726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	switch (id_bits) {
2973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case 0x0:
2983726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == das800) {
299e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: DAS-800\n");
3003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
3023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == ciodas800) {
303e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: CIO-DAS800\n");
3043726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
306e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "Board model (probed): DAS-800\n");
3073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return das800;
3083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
3093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case 0x2:
3103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == das801) {
311e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: DAS-801\n");
3123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
3143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == ciodas801) {
315e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: CIO-DAS801\n");
3163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
318e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "Board model (probed): DAS-801\n");
3193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return das801;
3203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
3213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case 0x3:
3223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == das802) {
323e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: DAS-802\n");
3243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
3263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == ciodas802) {
327e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: CIO-DAS802\n");
3283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
3303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (board == ciodas80216) {
331e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			dev_dbg(dev->hw_dev, "Board model: CIO-DAS802/16\n");
3323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return board;
3333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
334e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "Board model (probed): DAS-802\n");
3353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return das802;
3363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
3373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	default:
338e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "Board model: probe returned 0x%x (unknown)\n",
339e75aca92867eb687f6a2e0663db124f3fe3b4f1cRavishankar karkala Mallikarjunayya			id_bits);
3403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return board;
3413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
3423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
3433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return -1;
3443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
3453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
3463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/*
3473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess * A convenient macro that defines init_module() and cleanup_module(),
3483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess * as necessary.
3493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess */
3507114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_das800_init_module(void)
3517114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
3527114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_das800);
3537114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
3547114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
3557114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_das800_cleanup_module(void)
3567114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
3577114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_das800);
3587114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
3597114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
3607114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_das800_init_module);
3617114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_das800_cleanup_module);
3623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
3633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* interrupt service routine */
36470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das800_interrupt(int irq, void *d)
3653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
3663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	short i;		/* loop index */
367790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short dataPoint = 0;
36871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
36934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
370d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
3713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int status;
3723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
3732696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	static const int max_loops = 128;	/*  half-fifo size for cio-das802/16 */
3742696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  flags */
3753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int fifo_empty = 0;
3763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int fifo_overflow = 0;
3773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
3783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	status = inb(dev->iobase + DAS800_STATUS);
3793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* if interrupt was not generated by board or driver not attached, quit */
3803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!(status & IRQ))
3813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return IRQ_NONE;
3823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!(dev->attached))
3833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return IRQ_HANDLED;
3843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
3853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* wait until here to initialize async, since we will get null dereference
3863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	 * if interrupt occurs before driver is fully attached!
3873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	 */
3883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	async = s->async;
3893726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
3902696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  if hardware conversions are not enabled, then quit */
3915f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
3923726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select base address + 7 to be STATUS2 register */
3933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN;
39425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* don't release spinlock yet since we want to make sure no one else disables hardware conversions */
3953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (status == 0) {
3965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
3973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return IRQ_HANDLED;
3983726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
3993726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */
4013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	for (i = 0; i < max_loops; i++) {
4023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* read 16 bits from dev->iobase and dev->iobase + 1 */
4033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		dataPoint = inb(dev->iobase + DAS800_LSB);
4043726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		dataPoint += inb(dev->iobase + DAS800_MSB) << 8;
4053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (thisboard->resolution == 12) {
4063726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			fifo_empty = dataPoint & FIFO_EMPTY;
4073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			fifo_overflow = dataPoint & FIFO_OVF;
4083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			if (fifo_overflow)
4093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				break;
4103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		} else {
4112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton			fifo_empty = 0;	/*  cio-das802/16 has no fifo empty status bit */
4123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
413882e5b32b5d68960f46331215fc3c301df508110Andrea Gelmini		if (fifo_empty)
4143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			break;
4153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* strip off extraneous bits for 12 bit cards */
4163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (thisboard->resolution == 12)
4173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			dataPoint = (dataPoint >> 4) & 0xfff;
4183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* if there are more data points to collect */
4193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (devpriv->count > 0 || devpriv->forever == 1) {
4203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			/* write data point to buffer */
4213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			cfc_write_to_buffer(s, dataPoint);
4223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			if (devpriv->count > 0)
4233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				devpriv->count--;
4243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
4253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	async->events |= COMEDI_CB_BLOCK;
4273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* check for fifo overflow */
4283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (thisboard->resolution == 12) {
4293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		fifo_overflow = dataPoint & FIFO_OVF;
4302696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton		/*  else cio-das802/16 */
4313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	} else {
4323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		fifo_overflow = inb(dev->iobase + DAS800_GAIN) & CIO_FFOV;
4333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (fifo_overflow) {
4355f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
4363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		comedi_error(dev, "DAS800 FIFO overflow");
4373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		das800_cancel(dev, dev->subdevices + 0);
4383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
4393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		comedi_event(dev, s);
4403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		async->events = 0;
4413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return IRQ_HANDLED;
4423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (devpriv->count > 0 || devpriv->forever == 1) {
4443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* Re-enable card's interrupt.
4453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		 * We already have spinlock, so indirect addressing is safe */
4463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be control register 1 */
4473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		outb(CONTROL1_INTE | devpriv->do_bits,
4480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->iobase + DAS800_CONTROL1);
4495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
4503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* otherwise, stop taking data */
4513726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	} else {
4525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
4533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		disable_das800(dev);	/* diable hardware triggered conversions */
4543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		async->events |= COMEDI_CB_EOA;
4553726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	comedi_event(dev, s);
4573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	async->events = 0;
4583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return IRQ_HANDLED;
4593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
4603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
461da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
4623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
46334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
4643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long iobase = it->options[0];
4653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned int irq = it->options[1];
4663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
4673726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int board;
4683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
469bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya	dev_info(dev->hw_dev, "comedi%d: das800: io 0x%lx\n", dev->minor,
470bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		 iobase);
471882e5b32b5d68960f46331215fc3c301df508110Andrea Gelmini	if (irq)
472bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "irq %u\n", irq);
4733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* allocate and initialize dev->private */
475938f185d4eea489ad802554e2faef9c99e377aa5Bill Pemberton	if (alloc_private(dev, sizeof(struct das800_private)) < 0)
4763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -ENOMEM;
4773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (iobase == 0) {
479bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		dev_err(dev->hw_dev, "io base address required for das800\n");
4803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -EINVAL;
4813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* check if io addresses are available */
4843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!request_region(iobase, DAS800_SIZE, "das800")) {
485bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		dev_err(dev->hw_dev, "I/O port conflict\n");
4863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -EIO;
4873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	dev->iobase = iobase;
4893726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	board = das800_probe(dev);
4913726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (board < 0) {
492bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "unable to determine board type\n");
4933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -ENODEV;
4943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
4953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	dev->board_ptr = das800_boards + board;
4963726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
4973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* grab our IRQ */
4983726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (irq == 1 || irq > 7) {
499bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya		dev_err(dev->hw_dev, "irq out of range\n");
5003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -EINVAL;
5013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
5023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (irq) {
5035f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(irq, das800_interrupt, 0, "das800", dev)) {
504bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya			dev_err(dev->hw_dev, "unable to allocate irq %u\n",
505bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya				irq);
5063726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return -EINVAL;
5073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
5083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
5093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	dev->irq = irq;
5103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	dev->board_name = thisboard->name;
5123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (alloc_subdevices(dev, 3) < 0)
5143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -ENOMEM;
5153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* analog input subdevice */
5173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s = dev->subdevices + 0;
5183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	dev->read_subdev = s;
5193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->type = COMEDI_SUBD_AI;
5203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
5213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->n_chan = 8;
5223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->len_chanlist = 8;
5233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->maxdata = (1 << thisboard->resolution) - 1;
5243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->range_table = thisboard->ai_range;
5253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->do_cmd = das800_ai_do_cmd;
5263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->do_cmdtest = das800_ai_do_cmdtest;
5273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->insn_read = das800_ai_rinsn;
5283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->cancel = das800_cancel;
5293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* di */
5313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s = dev->subdevices + 1;
5323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->type = COMEDI_SUBD_DI;
5333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->subdev_flags = SDF_READABLE;
5343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->n_chan = 3;
5353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->maxdata = 1;
5363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->range_table = &range_digital;
5373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->insn_bits = das800_di_rbits;
5383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* do */
5403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s = dev->subdevices + 2;
5413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->type = COMEDI_SUBD_DO;
5423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
5433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->n_chan = 4;
5443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->maxdata = 1;
5453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->range_table = &range_digital;
5463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	s->insn_bits = das800_do_wbits;
5473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	disable_das800(dev);
5493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* initialize digital out channels */
5515f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
5523726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be control register 1 */
5533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);
5545f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
5553726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
5573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
5583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
559da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_detach(struct comedi_device *dev)
5603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
561bb1defe4653567f7754af741e20a79796a81beaaRavishankar karkala Mallikarjunayya	dev_info(dev->hw_dev, "comedi%d: das800: remove\n", dev->minor);
5623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* only free stuff if it has been allocated by _attach */
5643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (dev->iobase)
5653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		release_region(dev->iobase, DAS800_SIZE);
5663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (dev->irq)
5675f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
5683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
5693726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess};
5703726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
571da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
5723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
5733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	devpriv->forever = 0;
5743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	devpriv->count = 0;
5753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	disable_das800(dev);
5763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
5773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
5783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* enable_das800 makes the card start taking hardware triggered conversions */
580da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void enable_das800(struct comedi_device *dev)
5813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
5823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
5835f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
5842696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  enable fifo-half full interrupts for cio-das802/16 */
5853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (thisboard->resolution == 16)
5863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
5873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be conversion control register */
5883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL);	/* enable hardware triggering */
5893726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be control register 1 */
5903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);	/* enable card's interrupt */
5915f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
5923726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
5933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
5943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* disable_das800 stops hardware triggered conversions */
595da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void disable_das800(struct comedi_device *dev)
5963726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
5973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
5985f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
5993726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be conversion control register */
6003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(0x0, dev->iobase + DAS800_CONV_CONTROL);	/* disable hardware triggering of conversions */
6015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
6023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
6033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_do_cmdtest(struct comedi_device *dev,
6050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
6060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
6073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
6083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int err = 0;
6093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int tmp;
6103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int gain, startChan;
6113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int i;
6123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* step 1: make sure trigger sources are trivially valid */
6143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	tmp = cmd->start_src;
6163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	cmd->start_src &= TRIG_NOW | TRIG_EXT;
6173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->start_src || tmp != cmd->start_src)
6183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	tmp = cmd->scan_begin_src;
6213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	cmd->scan_begin_src &= TRIG_FOLLOW;
6223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
6233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	tmp = cmd->convert_src;
6263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
6273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->convert_src || tmp != cmd->convert_src)
6283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	tmp = cmd->scan_end_src;
6313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	cmd->scan_end_src &= TRIG_COUNT;
6323726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
6333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	tmp = cmd->stop_src;
6363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
6373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->stop_src || tmp != cmd->stop_src)
6383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
6413726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return 1;
6423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* step 2: make sure trigger sources are unique and mutually compatible */
6443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
6463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
6483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
6503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6513726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6523726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
6533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return 2;
6543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6553726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* step 3: make sure arguments are trivially compatible */
6563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->start_arg != 0) {
6583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		cmd->start_arg = 0;
6593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
6613726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
6623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (cmd->convert_arg < thisboard->ai_speed) {
6633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			cmd->convert_arg = thisboard->ai_speed;
6643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			err++;
6653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
6663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
6673726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!cmd->chanlist_len) {
6683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		cmd->chanlist_len = 1;
6693726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6703726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
6713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->scan_end_arg != cmd->chanlist_len) {
6723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		cmd->scan_end_arg = cmd->chanlist_len;
6733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
6743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
6753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->stop_src == TRIG_COUNT) {
6763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (!cmd->stop_arg) {
6773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			cmd->stop_arg = 1;
6783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			err++;
6793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
6803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	} else {		/* TRIG_NONE */
6813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (cmd->stop_arg != 0) {
6823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			cmd->stop_arg = 0;
6833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			err++;
6843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
6853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
6863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
6883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return 3;
6893726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* step 4: fix up any arguments */
6913726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
6923726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
6933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		tmp = cmd->convert_arg;
6943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* calculate counter values that give desired timing */
6953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
6960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
6970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
6980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
6993726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (tmp != cmd->convert_arg)
7003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			err++;
7013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
7023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
7043726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return 4;
7053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  check channel/gain list against card's limitations */
7073726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (cmd->chanlist) {
7083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		gain = CR_RANGE(cmd->chanlist[0]);
7093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		startChan = CR_CHAN(cmd->chanlist[0]);
7103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		for (i = 1; i < cmd->chanlist_len; i++) {
7113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			if (CR_CHAN(cmd->chanlist[i]) !=
7120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (startChan + i) % N_CHAN_AI) {
7133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				comedi_error(dev,
7140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must be consecutive channels, counting upwards\n");
7153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				err++;
7163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			}
7173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			if (CR_RANGE(cmd->chanlist[i]) != gain) {
7183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				comedi_error(dev,
7190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must all have the same gain\n");
7203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				err++;
7213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			}
7223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
7233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
7243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
7263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return 5;
7273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
7293726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
7303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_do_cmd(struct comedi_device *dev,
7320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
7333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
7343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int startChan, endChan, scan, gain;
7353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int conv_bits;
7363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
737d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
7383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (!dev->irq) {
7403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		comedi_error(dev,
7410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for das-800, cannot do hardware conversions");
7423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -1;
7433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
7443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	disable_das800(dev);
7463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* set channel scan limits */
7483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	startChan = CR_CHAN(async->cmd.chanlist[0]);
7493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	endChan = (startChan + async->cmd.chanlist_len - 1) % 8;
7503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	scan = (endChan << 3) | startChan;
7513726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
7533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(SCAN_LIMITS, dev->iobase + DAS800_GAIN);	/* select base address + 2 to be scan limits register */
7543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(scan, dev->iobase + DAS800_SCAN_LIMITS);	/* set scan limits */
7555f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
7563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* set gain */
7583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	gain = CR_RANGE(async->cmd.chanlist[0]);
7593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (thisboard->resolution == 12 && gain > 0)
7603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		gain += 0x7;
7613726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	gain &= 0xf;
7623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(gain, dev->iobase + DAS800_GAIN);
7633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	switch (async->cmd.stop_src) {
7653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case TRIG_COUNT:
7663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len;
7673726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		devpriv->forever = 0;
7683726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
7693726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case TRIG_NONE:
7703726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		devpriv->forever = 1;
7713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		devpriv->count = 0;
7723726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
7733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	default:
7743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
7753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
7763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
7773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* enable auto channel scan, send interrupts on end of conversion
7783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	 * and set clock source to internal or external
7793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	 */
7803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	conv_bits = 0;
7813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	conv_bits |= EACS | IEOC;
7823726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (async->cmd.start_src == TRIG_EXT)
7833726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		conv_bits |= DTEN;
7843726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	switch (async->cmd.convert_src) {
7853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case TRIG_TIMER:
7863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		conv_bits |= CASC | ITE;
7873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* set conversion frequency */
7883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
7900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async->cmd.convert_arg),
7910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async->cmd.
7920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
7933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (das800_set_frequency(dev) < 0) {
7943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			comedi_error(dev, "Error setting up counters");
7953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return -1;
7963726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
7973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
7983726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	case TRIG_EXT:
7993726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
8003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	default:
8013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		break;
8023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
8033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8045f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
8053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be conversion control register */
8063726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(conv_bits, dev->iobase + DAS800_CONV_CONTROL);
8075f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
8083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	async->events = 0;
8093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	enable_das800(dev);
8103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
8113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
8123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_ai_rinsn(struct comedi_device *dev,
8140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
8150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
8163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
8173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int i, n;
8183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int chan;
8193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int range;
8203726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int lsb, msb;
8213726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int timeout = 1000;
8223726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
8233726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8243726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	disable_das800(dev);	/* disable hardware conversions (enables software conversions) */
8253726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8263726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* set multiplexer */
8273726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	chan = CR_CHAN(insn->chanspec);
8283726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8295f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
8303726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be control register 1 */
8313726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(chan | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);
8325f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
8333726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8343726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	/* set gain / range */
8353726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	range = CR_RANGE(insn->chanspec);
8363726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (thisboard->resolution == 12 && range)
8373726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		range += 0x7;
8383726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	range &= 0xf;
8393726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(range, dev->iobase + DAS800_GAIN);
8403726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8415f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(5);
8423726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8433726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	for (n = 0; n < insn->n; n++) {
8443726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		/* trigger conversion */
8453726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		outb_p(0, dev->iobase + DAS800_MSB);
8463726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8473726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		for (i = 0; i < timeout; i++) {
8483726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			if (!(inb(dev->iobase + DAS800_STATUS) & BUSY))
8493726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess				break;
8503726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
8513726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (i == timeout) {
8523726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			comedi_error(dev, "timeout");
8533726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			return -ETIME;
8543726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
8553726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		lsb = inb(dev->iobase + DAS800_LSB);
8563726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		msb = inb(dev->iobase + DAS800_MSB);
8573726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		if (thisboard->resolution == 12) {
8583726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			data[n] = (lsb >> 4) & 0xff;
8593726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			data[n] |= (msb << 4);
8603726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		} else {
8613726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess			data[n] = (msb << 8) | lsb;
8623726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		}
8633726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	}
8643726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8653726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return n;
8663726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
8673726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_di_rbits(struct comedi_device *dev,
8690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
8700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
8713726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
872790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
8733726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8743726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	bits = inb(dev->iobase + DAS800_STATUS) >> 4;
8753726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	bits &= 0x7;
8763726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	data[1] = bits;
8773726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	data[0] = 0;
8783726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8793726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 2;
8803726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
8813726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das800_do_wbits(struct comedi_device *dev,
8830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
8840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
8853726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
8863726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int wbits;
8873726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	unsigned long irq_flags;
8883726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8892696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  only set bits that have been masked */
8903726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	data[0] &= 0xf;
8913726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	wbits = devpriv->do_bits >> 4;
8923726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	wbits &= ~data[0];
8933726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	wbits |= data[0] & data[1];
8943726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	devpriv->do_bits = wbits << 4;
8953726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
8965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
8973726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be control register 1 */
8983726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1);
8995f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9003726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
9013726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	data[1] = wbits;
9023726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
9033726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 2;
9043726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
9053726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
9063726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess/* loads counters with divisor1, divisor2 from private structure */
907da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das800_set_frequency(struct comedi_device *dev)
9083726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess{
9093726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	int err = 0;
9103726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
9113726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
9123726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
9133726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2))
9143726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		err++;
9153726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	if (err)
9163726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess		return -1;
9173726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess
9183726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess	return 0;
9193726e56b17762b3f13410b9c41029a13fef8c67fFrank Mori Hess}
92090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
92190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
92290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
92390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
924