[go: nahoru, domu]

148f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen/*
279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * das6402.c
379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Comedi driver for DAS6402 compatible boards
479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Copyright(c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *
679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Rewrite of an experimental driver by:
779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Copyright (C) 1999 Oystein Svendsen <svendsen@pvv.org>
879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *
979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * This program is free software; you can redistribute it and/or modify
1079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * it under the terms of the GNU General Public License as published by
1179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * the Free Software Foundation; either version 2 of the License, or
1279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * (at your option) any later version.
1379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *
1479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * This program is distributed in the hope that it will be useful,
1579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * but WITHOUT ANY WARRANTY; without even the implied warranty of
1679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * GNU General Public License for more details.
1848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen */
1948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
2048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen/*
2179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Driver: das6402
2279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Description: Keithley Metrabyte DAS6402 (& compatibles)
2379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Devices: (Keithley Metrabyte) DAS6402-12 (das6402-12)
2479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *	    (Keithley Metrabyte) DAS6402-16 (das6402-16)
2579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
2679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Updated: Fri, 14 Mar 2014 10:18:43 -0700
2779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Status: unknown
2879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *
2979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Configuration Options:
3079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *   [0] - I/O base address
3179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten *   [1] - IRQ (optional, needed for async command support)
3279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten */
3348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
3479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#include <linux/module.h>
3579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#include <linux/interrupt.h>
3648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
3779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#include "../comedidev.h"
3879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#include "8253.h"
3948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
4048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen/*
4179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Register I/O map
4279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten */
4379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AI_DATA_REG		0x00
4479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AI_MUX_REG		0x02
4579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AI_MUX_LO(x)		(((x) & 0x3f) << 0)
4679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AI_MUX_HI(x)		(((x) & 0x3f) << 8)
4779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_DI_DO_REG		0x03
4879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AO_DATA_REG(x)		(0x04 + ((x) * 2))
4979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AO_LSB_REG(x)		(0x04 + ((x) * 2))
5079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AO_MSB_REG(x)		(0x05 + ((x) * 2))
5179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_REG		0x08
5279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_FFNE		(1 << 0)
5379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_FHALF		(1 << 1)
5479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_FFULL		(1 << 2)
5579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_XINT		(1 << 3)
5679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_INT		(1 << 4)
5779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_XTRIG		(1 << 5)
5879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_INDGT		(1 << 6)
5979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_10MHZ		(1 << 7)
6079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_CLRINT		(1 << 0)
6179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_CLRXTR		(1 << 1)
6279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_CLRXIN		(1 << 2)
6379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_EXTEND		(1 << 4)
6479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_ARMED		(1 << 5)
6579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_POSTMODE	(1 << 6)
6679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_STATUS_W_10MHZ		(1 << 7)
6779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_REG		0x09
6879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_SOFT_TRIG		(0 << 0)
6979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_EXT_FALL_TRIG	(1 << 0)
7079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_EXT_RISE_TRIG	(2 << 0)
7179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_PACER_TRIG		(3 << 0)
7279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_BURSTEN		(1 << 2)
7379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_XINTE		(1 << 3)
7479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_IRQ(x)		((x) << 4)
7579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_CTRL_INTE		(1 << 7)
7679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TRIG_REG		0x0a
7779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TRIG_TGEN		(1 << 0)
7879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TRIG_TGSEL		(1 << 1)
7979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TRIG_TGPOL		(1 << 2)
8079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TRIG_PRETRIG		(1 << 3)
8179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AO_RANGE(_chan, _range)	((_range) << ((_chan) ? 6 : 4))
8279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_AO_RANGE_MASK(_chan)	(3 << ((_chan) ? 6 : 4))
8379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_REG		0x0b
8479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_RANGE(x)		((x) << 0)
8579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_POLLED		(0 << 2)
8679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_FIFONEPTY		(1 << 2)
8779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_FIFOHFULL		(2 << 2)
8879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_EOB		(3 << 2)
8979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_ENHANCED		(1 << 4)
9079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_SE			(1 << 5)
9179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_UNI		(1 << 6)
9279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_DMA1		(0 << 7)
9379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_MODE_DMA3		(1 << 7)
9479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten#define DAS6402_TIMER_BASE		0x0c
9579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
9679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic const struct comedi_lrange das6402_ai_ranges = {
9779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	8, {
9879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(10),
9979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(5),
10079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(2.5),
10179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(1.25),
10279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(10),
10379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(5),
10479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(2.5),
10579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(1.25)
10679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
10779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten};
10848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
10979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten/*
11079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * Analog output ranges are programmable on the DAS6402/12.
11179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * For the DAS6402/16 the range bits have no function, the
11279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten * DAC ranges are selected by switches on the board.
11379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten */
11479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic const struct comedi_lrange das6402_ao_ranges = {
11579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	4, {
11679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(5),
11779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		BIP_RANGE(10),
11879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(5),
11979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		UNI_RANGE(10)
12079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
12179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten};
12248f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
12379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstruct das6402_boardinfo {
12479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	const char *name;
12579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int maxdata;
12679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten};
12748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
128bee2d6a82cc31ebcc44a0ec9484ec1670c07ca6aMichele Curtistatic struct das6402_boardinfo das6402_boards[] = {
12979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	{
13079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		.name		= "das6402-12",
13179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		.maxdata	= 0x0fff,
13279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}, {
13379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		.name		= "das6402-16",
13479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		.maxdata	= 0xffff,
13579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	},
13679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten};
13748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
138c7b8bb98a46e475ae848642cf60160fc7135cd52Bill Pembertonstruct das6402_private {
13979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int irq;
14079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
14179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int count;
14279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int divider1;
14379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int divider2;
14448f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
14579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int ao_range;
146c7b8bb98a46e475ae848642cf60160fc7135cd52Bill Pemberton};
14748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
14879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_set_mode(struct comedi_device *dev,
14979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			     unsigned int mode)
15071e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten{
15179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_MODE_ENHANCED | mode, dev->iobase + DAS6402_MODE_REG);
15271e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten}
15348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
15479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_set_extended(struct comedi_device *dev,
15579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				 unsigned int val)
15648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
15779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_STATUS_W_EXTEND, dev->iobase + DAS6402_STATUS_REG);
15879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_STATUS_W_EXTEND | val, dev->iobase + DAS6402_STATUS_REG);
15979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(val, dev->iobase + DAS6402_STATUS_REG);
16048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
16148f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
16279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_clear_all_interrupts(struct comedi_device *dev)
16379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
16479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_STATUS_W_CLRINT |
16579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	     DAS6402_STATUS_W_CLRXTR |
16679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	     DAS6402_STATUS_W_CLRXIN, dev->iobase + DAS6402_STATUS_REG);
16779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
16879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
16979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_ai_clear_eoc(struct comedi_device *dev)
17079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
17179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_STATUS_W_CLRINT, dev->iobase + DAS6402_STATUS_REG);
17279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
17379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
17479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_enable_counter(struct comedi_device *dev, bool load)
17548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
1769a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten	struct das6402_private *devpriv = dev->private;
17779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned long timer_iobase = dev->iobase + DAS6402_TIMER_BASE;
17848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
17979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (load) {
18079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 0, I8254_MODE0 | I8254_BINARY);
18179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 1, I8254_MODE2 | I8254_BINARY);
18279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 2, I8254_MODE2 | I8254_BINARY);
18348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
18479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_write(timer_iobase, 0, 0, devpriv->count);
18579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_write(timer_iobase, 0, 1, devpriv->divider1);
18679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_write(timer_iobase, 0, 2, devpriv->divider2);
18748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
18879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	} else {
18979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 0, I8254_MODE0 | I8254_BINARY);
19079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 1, I8254_MODE0 | I8254_BINARY);
19179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		i8254_set_mode(timer_iobase, 0, 2, I8254_MODE0 | I8254_BINARY);
19248f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen	}
19379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
19448f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
19579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic irqreturn_t das6402_interrupt(int irq, void *d)
19679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
19779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	struct comedi_device *dev = d;
19879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
19979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_clear_all_interrupts(dev);
20048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
20148f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen	return IRQ_HANDLED;
20248f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
20348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
20479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ai_cmd(struct comedi_device *dev,
20579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			  struct comedi_subdevice *s)
20648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
20779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return -EINVAL;
20879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
20948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
21079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ai_cmdtest(struct comedi_device *dev,
21179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			      struct comedi_subdevice *s,
21279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			      struct comedi_cmd *cmd)
21379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
21479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return -EINVAL;
21548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
21648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
2170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das6402_ai_cancel(struct comedi_device *dev,
2180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
21948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
22079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_CTRL_SOFT_TRIG, dev->iobase + DAS6402_CTRL_REG);
22179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
22279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return 0;
22379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
22479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
22579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_ai_soft_trig(struct comedi_device *dev)
22679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
22779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outw(0, dev->iobase + DAS6402_AI_DATA_REG);
22879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
22979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
23079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ai_eoc(struct comedi_device *dev,
23179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			  struct comedi_subdevice *s,
23279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			  struct comedi_insn *insn,
23379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			  unsigned long context)
23479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
23579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int status;
23679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
23779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	status = inb(dev->iobase + DAS6402_STATUS_REG);
23879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (status & DAS6402_STATUS_FFNE)
23979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		return 0;
24079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return -EBUSY;
24179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
24279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
24379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ai_insn_read(struct comedi_device *dev,
24479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_subdevice *s,
24579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_insn *insn,
24679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				unsigned int *data)
24779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
24879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
24979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int range = CR_RANGE(insn->chanspec);
25079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int aref = CR_AREF(insn->chanspec);
25179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int val;
25279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	int ret;
25379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	int i;
25479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
25579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	val = DAS6402_MODE_RANGE(range) | DAS6402_MODE_POLLED;
25679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (aref == AREF_DIFF) {
25779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		if (chan > s->n_chan / 2)
25879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			return -EINVAL;
25979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	} else {
26079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		val |= DAS6402_MODE_SE;
26179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
26279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (comedi_range_is_unipolar(s, range))
26379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		val |= DAS6402_MODE_UNI;
26479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
26579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* enable software conversion trigger */
26679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_CTRL_SOFT_TRIG, dev->iobase + DAS6402_CTRL_REG);
26779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
26879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_set_mode(dev, val);
26979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
27079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* load the mux for single channel conversion */
27179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outw(DAS6402_AI_MUX_HI(chan) | DAS6402_AI_MUX_LO(chan),
27279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	     dev->iobase + DAS6402_AI_MUX_REG);
27379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
27479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
27579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		das6402_ai_clear_eoc(dev);
27679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		das6402_ai_soft_trig(dev);
27779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
27879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		ret = comedi_timeout(dev, s, insn, das6402_ai_eoc, 0);
27979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		if (ret)
28079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			break;
28179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
28279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		val = inw(dev->iobase + DAS6402_AI_DATA_REG);
28379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
28479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		if (s->maxdata == 0x0fff)
28579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			val >>= 4;
28679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
28779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		data[i] = val;
28879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
28979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
29079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_ai_clear_eoc(dev);
29179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
29279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return insn->n;
29379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
29479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
29579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ao_insn_write(struct comedi_device *dev,
29679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				 struct comedi_subdevice *s,
29779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				 struct comedi_insn *insn,
29879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				 unsigned int *data)
29979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
3009a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten	struct das6402_private *devpriv = dev->private;
30179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
30279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int range = CR_RANGE(insn->chanspec);
30379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int val;
30479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	int i;
30579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
30679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* set the range for this channel */
30779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	val = devpriv->ao_range;
30879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	val &= ~DAS6402_AO_RANGE_MASK(chan);
30979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	val |= DAS6402_AO_RANGE(chan, range);
31079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (val != devpriv->ao_range) {
31179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		devpriv->ao_range = val;
31279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		outb(val, dev->iobase + DAS6402_TRIG_REG);
31379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
3149a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten
31548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen	/*
31679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * The DAS6402/16 has a jumper to select either individual
31779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * update (UPDATE) or simultaneous updating (XFER) of both
31879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * DAC's. In UPDATE mode, when the MSB is written, that DAC
31979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * is updated. In XFER mode, after both DAC's are loaded,
32079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * a read cycle of any DAC register will update both DAC's
32179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * simultaneously.
32279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 *
32379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * If you have XFER mode enabled a (*insn_read) will need
32479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * to be performed in order to update the DAC's with the
32579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * last value written.
32648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen	 */
32779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
32879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		val = data[i];
32979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
3303dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten		s->readback[chan] = val;
33179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
33279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		if (s->maxdata == 0x0fff) {
33379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			/*
33479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 * DAS6402/12 has the two 8-bit DAC registers, left
33579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 * justified (the 4 LSB bits are don't care). Data
33679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 * can be written as one word.
33779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 */
33879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			val <<= 4;
33979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			outw(val, dev->iobase + DAS6402_AO_DATA_REG(chan));
34079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		} else {
34179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			/*
34279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 * DAS6402/16 uses both 8-bit DAC registers and needs
34379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 * to be written LSB then MSB.
34479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			 */
34579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			outb(val & 0xff,
34679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			     dev->iobase + DAS6402_AO_LSB_REG(chan));
34779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			outb((val >> 8) & 0xff,
34879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			     dev->iobase + DAS6402_AO_LSB_REG(chan));
34979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		}
35079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
35148f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
35279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return insn->n;
35348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
35448f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
35579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_ao_insn_read(struct comedi_device *dev,
35679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_subdevice *s,
35779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_insn *insn,
35879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				unsigned int *data)
35948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
36079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
3619a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten
36279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/*
36379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * If XFER mode is enabled, reading any DAC register
36479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 * will update both DAC's simultaneously.
36579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	 */
36679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	inw(dev->iobase + DAS6402_AO_LSB_REG(chan));
36748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
3683dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten	return comedi_readback_insn_read(dev, s, insn, data);
36979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
37048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
37179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_di_insn_bits(struct comedi_device *dev,
37279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_subdevice *s,
37379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_insn *insn,
37479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				unsigned int *data)
37579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
37679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	data[1] = inb(dev->iobase + DAS6402_DI_DO_REG);
37748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
37879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return insn->n;
37948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
38048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
38179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic int das6402_do_insn_bits(struct comedi_device *dev,
38279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_subdevice *s,
38379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				struct comedi_insn *insn,
38479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				unsigned int *data)
38548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
38679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (comedi_dio_update_state(s, data))
38779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		outb(s->state, dev->iobase + DAS6402_DI_DO_REG);
38848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
38979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	data[1] = s->state;
39048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
39179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	return insn->n;
39279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten}
39348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
39479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweetenstatic void das6402_reset(struct comedi_device *dev)
39579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten{
39679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	struct das6402_private *devpriv = dev->private;
39748f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
39879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* enable "Enhanced" mode */
39979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_MODE_ENHANCED, dev->iobase + DAS6402_MODE_REG);
40048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
40179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* enable 10MHz pacer clock */
40279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_set_extended(dev, DAS6402_STATUS_W_10MHZ);
40348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
40479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* enable software conversion trigger */
40579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(DAS6402_CTRL_SOFT_TRIG, dev->iobase + DAS6402_CTRL_REG);
40648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
40779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* default ADC to single-ended unipolar 10V inputs */
40879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_set_mode(dev, DAS6402_MODE_RANGE(0) |
40979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			      DAS6402_MODE_POLLED |
41079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			      DAS6402_MODE_SE |
41179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			      DAS6402_MODE_UNI);
41248f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
41379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* default mux for single channel conversion (channel 0) */
41479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outw(DAS6402_AI_MUX_HI(0) | DAS6402_AI_MUX_LO(0),
41579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	     dev->iobase + DAS6402_AI_MUX_REG);
41648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
41779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* set both DAC's for unipolar 5V output range */
41879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	devpriv->ao_range = DAS6402_AO_RANGE(0, 2) | DAS6402_AO_RANGE(1, 2);
41979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(devpriv->ao_range, dev->iobase + DAS6402_TRIG_REG);
42048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
42179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* set both DAC's to 0V */
42279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outw(0, dev->iobase + DAS6402_AO_DATA_REG(0));
42379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outw(0, dev->iobase + DAS6402_AO_DATA_REG(0));
42479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	inw(dev->iobase + DAS6402_AO_LSB_REG(0));
42548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
42679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_enable_counter(dev, false);
42779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
42879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* set all digital outputs low */
42979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	outb(0, dev->iobase + DAS6402_DI_DO_REG);
43079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
43179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_clear_all_interrupts(dev);
43248f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
43348f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
4340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das6402_attach(struct comedi_device *dev,
4350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
43648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen{
43719924ce0c1fab868671d2fb845e402ab1bd848e3Ian Abbott	const struct das6402_boardinfo *board = dev->board_ptr;
4389a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten	struct das6402_private *devpriv;
43934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
44079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	int ret;
4419a1a6cf8ae5ca58171e117335b9983e3cfa2185cH Hartley Sweeten
4420bdab509bf9c6d838dc0a3b1d68bbf841fc20b5aH Hartley Sweeten	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
443c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten	if (!devpriv)
444c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten		return -ENOMEM;
44548f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
44679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	ret = comedi_request_region(dev, it->options[0], 0x10);
4478b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten	if (ret)
44848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen		return ret;
44948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
45079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	das6402_reset(dev);
45179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
45279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* IRQs 2,3,5,6,7, 10,11,15 are valid for "enhanced" mode */
45379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if ((1 << it->options[1]) & 0x8cec) {
45479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		ret = request_irq(it->options[1], das6402_interrupt, 0,
45579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				  dev->board_name, dev);
45679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		if (ret == 0) {
45779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			dev->irq = it->options[1];
45879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
45979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			switch (dev->irq) {
46079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			case 10:
46179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				devpriv->irq = 4;
46279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				break;
46379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			case 11:
46479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				devpriv->irq = 1;
46579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				break;
46679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			case 15:
46779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				devpriv->irq = 6;
46879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				break;
46979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			default:
47079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				devpriv->irq = dev->irq;
47179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten				break;
47279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten			}
47379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		}
47479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
47579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
47679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 4);
47779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (ret)
47879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		return ret;
47979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
48079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* Analog Input subdevice */
48192cfef5d90148f1a91fba528971ed6ae39b1c14bH Hartley Sweeten	s = &dev->subdevices[0];
48279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->type		= COMEDI_SUBD_AI;
48379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_DIFF;
48479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->n_chan	= 64;
48579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->maxdata	= board->maxdata;
48679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->range_table	= &das6402_ai_ranges;
48779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->insn_read	= das6402_ai_insn_read;
48879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	if (dev->irq) {
48979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		dev->read_subdev = s;
49079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		s->subdev_flags	|= SDF_CMD_READ;
49179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		s->len_chanlist	= s->n_chan;
49279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		s->do_cmdtest	= das6402_ai_cmdtest;
49379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		s->do_cmd	= das6402_ai_cmd;
49479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten		s->cancel	= das6402_ai_cancel;
49579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	}
49648f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
49779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* Analog Output subdevice */
49879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s = &dev->subdevices[1];
49979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->type		= COMEDI_SUBD_AO;
50079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->subdev_flags	= SDF_WRITEABLE;
50179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->n_chan	= 2;
50279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->maxdata	= board->maxdata;
50379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->range_table	= &das6402_ao_ranges;
50479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->insn_write	= das6402_ao_insn_write;
50579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->insn_read	= das6402_ao_insn_read;
50679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
5073dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten	ret = comedi_alloc_subdev_readback(s);
5083dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten	if (ret)
5093dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten		return ret;
5103dd0b514d95b2063c211d5b00940202921cce3eaH Hartley Sweeten
51179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* Digital Input subdevice */
51279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s = &dev->subdevices[2];
51379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->type		= COMEDI_SUBD_DI;
51479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->subdev_flags	= SDF_READABLE;
51579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->n_chan	= 8;
51679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->maxdata	= 1;
51779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->range_table	= &range_digital;
51879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->insn_bits	= das6402_di_insn_bits;
51979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten
52079e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	/* Digital Input subdevice */
52179e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s = &dev->subdevices[3];
52279e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->type		= COMEDI_SUBD_DO;
52379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->subdev_flags	= SDF_WRITEABLE;
52479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->n_chan	= 8;
52579e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->maxdata	= 1;
52679e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->range_table	= &range_digital;
52779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	s->insn_bits	= das6402_do_insn_bits;
52848f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen
52948f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen	return 0;
53048f16b6aeafdfb77b1698173f225b20b825eebf7Oystein Svendsen}
53190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
53271e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweetenstatic struct comedi_driver das6402_driver = {
53371e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten	.driver_name	= "das6402",
53471e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten	.module		= THIS_MODULE,
53571e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten	.attach		= das6402_attach,
5363d1fe3f785c80e17f62acf8f92570ae9210bd588H Hartley Sweeten	.detach		= comedi_legacy_detach,
53779e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	.board_name	= &das6402_boards[0].name,
53879e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	.num_names	= ARRAY_SIZE(das6402_boards),
53979e5e6addbb18bf56075f0ff552094a28636dd03H Hartley Sweeten	.offset		= sizeof(struct das6402_boardinfo),
54071e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten};
54171e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweetenmodule_comedi_driver(das6402_driver)
54271e7271b15d55d8ab668745f680d03044bcf7db0H Hartley Sweeten
54379e5e6addbb18bf56075f0ff552094a28636dd03H Hartley SweetenMODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
54479e5e6addbb18bf56075f0ff552094a28636dd03H Hartley SweetenMODULE_DESCRIPTION("Comedi driver for DAS6402 compatible boards");
54590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
546