addi_apci_2032.c revision ef6543dbad12c1086f3bc3565d8266352521d8a3
1d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten/*
2d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * addi_apci_2032.c
3d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
4d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * Project manager: Eric Stolz
5d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *
6d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	ADDI-DATA GmbH
7d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	Dieselstrasse 3
8d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	D-77833 Ottersweier
9d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	Tel: +19(0)7223/9493-0
10d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	Fax: +49(0)7223/9493-92
11d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	http://www.addi-data.com
12d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *	info@addi-data.com
13d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *
14d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * This program is free software; you can redistribute it and/or modify it
15d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * under the terms of the GNU General Public License as published by the
16d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * Free Software Foundation; either version 2 of the License, or (at your
17d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * option) any later version.
18d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *
19d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * This program is distributed in the hope that it will be useful, but WITHOUT
20d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * more details.
23d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *
24d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * You should have received a copy of the GNU General Public License along
25d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * with this program; if not, write to the Free Software Foundation, Inc.,
26d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten *
28d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * You should also find the complete GPL in the COPYING file accompanying
29d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * this source code.
30d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten */
31d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
323d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "../comedidev.h"
333d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "comedi_fc.h"
343d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten
35d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten/*
36d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * PCI bar 1 I/O Register map
37d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten */
387180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_DO_REG			0x00
397180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_REG		0x04
407180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_VCC_ENA	(1 << 0)
417180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_CC_ENA	(1 << 1)
427180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_REG		0x08
437180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_VCC		(1 << 0)
447180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_CC		(1 << 1)
457180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_REG		0x0c
467180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_IRQ		(1 << 0)
477180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_REG		0x10
487180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_RELOAD_REG	0x14
497180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_TIMEBASE		0x18
507180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_CTRL_REG		0x1c
517180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_CTRL_ENABLE	(1 << 0)
527180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_CTRL_SW_TRIG	(1 << 9)
537180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_STATUS_REG	0x20
547180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_STATUS_ENABLED	(1 << 0)
557180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_STATUS_SW_TRIG	(1 << 1)
56d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
5723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweetenstruct apci2032_private {
5823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	unsigned int wdog_ctrl;
5923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten};
6023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
61d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweetenstatic int apci2032_do_insn_bits(struct comedi_device *dev,
62d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				 struct comedi_subdevice *s,
63d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				 struct comedi_insn *insn,
64d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				 unsigned int *data)
65d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
66d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	unsigned int mask = data[0];
67d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	unsigned int bits = data[1];
68d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
697180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten	s->state = inl(dev->iobase + APCI2032_DO_REG);
70d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	if (mask) {
71d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten		s->state &= ~mask;
72d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten		s->state |= (bits & mask);
73d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
747180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten		outl(s->state, dev->iobase + APCI2032_DO_REG);
75d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	}
76d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
77d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	data[1] = s->state;
78d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
79d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	return insn->n;
80d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
81d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
8223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten/*
8323fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten * The watchdog subdevice is configured with two INSN_CONFIG instructions:
8423fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten *
8523fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten * Enable the watchdog and set the reload timeout:
8623fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten *	data[0] = INSN_CONFIG_ARM
8723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten *	data[1] = timeout reload value
8823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten *
8923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten * Disable the watchdog:
9023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten *	data[0] = INSN_CONFIG_DISARM
9123fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten */
9223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweetenstatic int apci2032_wdog_insn_config(struct comedi_device *dev,
93d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				     struct comedi_subdevice *s,
94d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				     struct comedi_insn *insn,
95d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				     unsigned int *data)
96d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
9723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	struct apci2032_private *devpriv = dev->private;
9823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	unsigned int reload;
9923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
10023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	switch (data[0]) {
10123fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	case INSN_CONFIG_ARM:
10223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		devpriv->wdog_ctrl = APCI2032_WDOG_CTRL_ENABLE;
10323fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		reload = data[1] & s->maxdata;
10423fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		outw(reload, dev->iobase + APCI2032_WDOG_RELOAD_REG);
10523fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
10623fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		/* Time base is 20ms, let the user know the timeout */
10723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
10823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten			20 * reload + 20);
10923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		break;
11023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	case INSN_CONFIG_DISARM:
11123fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		devpriv->wdog_ctrl = 0;
11223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		break;
11323fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	default:
114d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten		return -EINVAL;
115d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	}
116d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
11723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	outw(devpriv->wdog_ctrl, dev->iobase + APCI2032_WDOG_CTRL_REG);
11823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
119d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	return insn->n;
120d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
121d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
12223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweetenstatic int apci2032_wdog_insn_write(struct comedi_device *dev,
12323fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten				    struct comedi_subdevice *s,
12423fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten				    struct comedi_insn *insn,
12523fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten				    unsigned int *data)
126d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
12723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	struct apci2032_private *devpriv = dev->private;
12823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	int i;
12923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
13023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	if (devpriv->wdog_ctrl == 0) {
13123fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		dev_warn(dev->class_dev, "watchdog is disabled\n");
132d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten		return -EINVAL;
133d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	}
13423fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
13523fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	/* "ping" the watchdog */
13623fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
13723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		outw(devpriv->wdog_ctrl | APCI2032_WDOG_CTRL_SW_TRIG,
13823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten			dev->iobase + APCI2032_WDOG_CTRL_REG);
13923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	}
14023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
141d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	return insn->n;
142d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
143d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
14423fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweetenstatic int apci2032_wdog_insn_read(struct comedi_device *dev,
145d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				   struct comedi_subdevice *s,
146d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				   struct comedi_insn *insn,
147d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten				   unsigned int *data)
148d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
1497b5dd1cc988cf34341319c81bb0c7ddc21a2f8eeH Hartley Sweeten	int i;
1507b5dd1cc988cf34341319c81bb0c7ddc21a2f8eeH Hartley Sweeten
1517b5dd1cc988cf34341319c81bb0c7ddc21a2f8eeH Hartley Sweeten	for (i = 0; i < insn->n; i++)
1527b5dd1cc988cf34341319c81bb0c7ddc21a2f8eeH Hartley Sweeten		data[i] = inl(dev->iobase + APCI2032_WDOG_STATUS_REG);
1537b5dd1cc988cf34341319c81bb0c7ddc21a2f8eeH Hartley Sweeten
154d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten	return insn->n;
155d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
156d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
15705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_insn_bits(struct comedi_device *dev,
15805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				  struct comedi_subdevice *s,
15905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				  struct comedi_insn *insn,
16005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				  unsigned int *data)
161b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten{
162b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott	data[1] = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3;
16305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	return insn->n;
16405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten}
165b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
16605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmdtest(struct comedi_device *dev,
16705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				struct comedi_subdevice *s,
16805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				struct comedi_cmd *cmd)
16905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten{
17005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	int err = 0;
171b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
17205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Step 1 : check if triggers are trivially valid */
173b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
17405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
17505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
17605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
17705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
17805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
179b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
18005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (err)
18105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		return 1;
182b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
18305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Step 2a : make sure trigger sources are unique */
18405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Step 2b : and mutually compatible */
18505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
18605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (err)
18705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		return 2;
18805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
18905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Step 3: check if arguments are trivially valid */
19005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
19105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
19205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
19305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/*
19405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	 * 0 == no trigger
19505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	 * 1 == trigger on VCC interrupt
19605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	 * 2 == trigger on CC interrupt
19705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	 * 3 == trigger on either VCC or CC interrupt
19805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	 */
19905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 3);
20005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
20105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
20205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
20305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
20405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
20505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (err)
20605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		return 3;
20705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
20805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* step 4: ignored */
20905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
21005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (err)
21105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		return 4;
21205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
21305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	return 0;
214b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten}
215b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten
21605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmd(struct comedi_device *dev,
21705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten			    struct comedi_subdevice *s)
218d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
21905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	struct comedi_cmd *cmd = &s->async->cmd;
22005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
22105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	outl(cmd->scan_begin_arg, dev->iobase + APCI2032_INT_CTRL_REG);
22205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
22305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	return 0;
224d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
2257180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten
22605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cancel(struct comedi_device *dev,
22705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten			       struct comedi_subdevice *s)
228d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{
22905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
230d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten
23105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	return 0;
232d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten}
233317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten
23405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic irqreturn_t apci2032_interrupt(int irq, void *d)
23525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{
23605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	struct comedi_device *dev = d;
23705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	struct comedi_subdevice *s = dev->read_subdev;
23805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	unsigned int val;
23905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
2400774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott	if (!dev->attached)
2410774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott		return IRQ_NONE;
2420774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott
24305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Check if VCC OR CC interrupt has occurred */
24405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	val = inl(dev->iobase + APCI2032_STATUS_REG) & APCI2032_STATUS_IRQ;
24505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (!val)
24605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		return IRQ_NONE;
24705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
248b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott	val = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3;
249ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	/* Disable triggered interrupt sources. */
250ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	outl(~val & 3, dev->iobase + APCI2032_INT_CTRL_REG);
251ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	/*
252ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	 * Note: We don't reenable the triggered interrupt sources because they
253ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	 * are level-sensitive, hardware error status interrupt sources and
254ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	 * they'd keep triggering interrupts repeatedly.
255ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott	 */
25605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
257b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott	if (comedi_buf_put(s->async, val))
2586bf9a3babe630a9972b28fd3bb7d2cfcd40e6409Ian Abbott		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2596bf9a3babe630a9972b28fd3bb7d2cfcd40e6409Ian Abbott	else
2606bf9a3babe630a9972b28fd3bb7d2cfcd40e6409Ian Abbott		s->async->events |= COMEDI_CB_OVERFLOW;
26105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	comedi_event(dev, s);
26205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
26305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	return IRQ_HANDLED;
26425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten}
26525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
266791c9792ff2d12a02f0ab1c47fd7f7a94828b05bH Hartley Sweetenstatic int apci2032_reset(struct comedi_device *dev)
26725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{
2687180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten	outl(0x0, dev->iobase + APCI2032_DO_REG);
2697180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten	outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
2707180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten	outl(0x0, dev->iobase + APCI2032_WDOG_CTRL_REG);
2717180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten	outl(0x0, dev->iobase + APCI2032_WDOG_RELOAD_REG);
27225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
27325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	return 0;
27425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten}
27525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
27625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic int apci2032_auto_attach(struct comedi_device *dev,
27725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten				unsigned long context_unused)
27825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{
27925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
28023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	struct apci2032_private *devpriv;
28125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	struct comedi_subdevice *s;
2820c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten	int ret;
28325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
284c0c3c7dfc1fd5c970b9893e68796314e8551124fH Hartley Sweeten	dev->board_name = dev->driver->driver_name;
28525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
28623fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
28723fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	if (!devpriv)
28823fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten		return -ENOMEM;
28923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten	dev->private = devpriv;
29023fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten
29125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	ret = comedi_pci_enable(pcidev, dev->board_name);
29225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	if (ret)
29325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten		return ret;
29470ff406599a5debfa6e5ef243e5e093f63a9ed69H Hartley Sweeten	dev->iobase = pci_resource_start(pcidev, 1);
2950774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott	apci2032_reset(dev);
29625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
29725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	if (pcidev->irq > 0) {
29805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		ret = request_irq(pcidev->irq, apci2032_interrupt,
29905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten				  IRQF_SHARED, dev->board_name, dev);
30025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten		if (ret == 0)
30125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten			dev->irq = pcidev->irq;
30225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	}
30325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
30405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 3);
30525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	if (ret)
30625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten		return ret;
30725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
3080c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten	/* Initialize the digital output subdevice */
30925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	s = &dev->subdevices[0];
310cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->type		= COMEDI_SUBD_DO;
311cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->subdev_flags	= SDF_WRITEABLE;
312cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->n_chan	= 32;
313cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->maxdata	= 1;
314cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->range_table	= &range_digital;
315cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->insn_bits	= apci2032_do_insn_bits;
31625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
3170c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten	/* Initialize the watchdog subdevice */
3180c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten	s = &dev->subdevices[1];
319cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->type		= COMEDI_SUBD_TIMER;
320cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->subdev_flags	= SDF_WRITEABLE;
321cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->n_chan	= 1;
322cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->maxdata	= 0xff;
323cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->insn_write	= apci2032_wdog_insn_write;
324cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->insn_read	= apci2032_wdog_insn_read;
325cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten	s->insn_config	= apci2032_wdog_insn_config;
32625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
32705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	/* Initialize the interrupt subdevice */
32805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	s = &dev->subdevices[2];
32905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	if (dev->irq) {
33005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		dev->read_subdev = s;
331b82fe57c4d059a8ff1190ead1693d66b868353b2Ian Abbott		s->type		= COMEDI_SUBD_DI;
332b82fe57c4d059a8ff1190ead1693d66b868353b2Ian Abbott		s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
333b82fe57c4d059a8ff1190ead1693d66b868353b2Ian Abbott		s->n_chan	= 2;
33405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->maxdata	= 1;
33505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->range_table	= &range_digital;
33605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->insn_bits	= apci2032_int_insn_bits;
33705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->do_cmdtest	= apci2032_int_cmdtest;
33805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->do_cmd	= apci2032_int_cmd;
33905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->cancel	= apci2032_int_cancel;
34005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	} else {
34105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten		s->type		= COMEDI_SUBD_UNUSED;
34205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten	}
34305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten
34425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	return 0;
34525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten}
34625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
34725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic void apci2032_detach(struct comedi_device *dev)
34825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{
34925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
35025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
351dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten	if (dev->iobase)
352dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten		apci2032_reset(dev);
353dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten	if (dev->irq)
354dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten		free_irq(dev->irq, dev);
35525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	if (pcidev) {
35625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten		if (dev->iobase)
35725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten			comedi_pci_disable(pcidev);
35825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	}
35925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten}
36025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten
36120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct comedi_driver apci2032_driver = {
36220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.driver_name	= "addi_apci_2032",
36320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.module		= THIS_MODULE,
36425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	.auto_attach	= apci2032_auto_attach,
36525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten	.detach		= apci2032_detach,
36620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
36720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
368a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int apci2032_pci_probe(struct pci_dev *dev,
36920a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten					const struct pci_device_id *ent)
37020a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{
37120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	return comedi_pci_auto_config(dev, &apci2032_driver);
37220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}
37320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
37453b800198592b0ff96577ecc5f116f7d902a4362Bill Pembertonstatic void apci2032_pci_remove(struct pci_dev *dev)
37520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{
37620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	comedi_pci_auto_unconfig(dev);
37720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}
37820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten
37920a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = {
380317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) },
381317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten	{ 0 }
382317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten};
38320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley SweetenMODULE_DEVICE_TABLE(pci, apci2032_pci_table);
384317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten
38520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct pci_driver apci2032_pci_driver = {
38620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.name		= "addi_apci_2032",
38720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.id_table	= apci2032_pci_table,
38820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten	.probe		= apci2032_pci_probe,
389a471eace7baa40cdf16d3f26b2f78ddce613ca8fBill Pemberton	.remove		= apci2032_pci_remove,
39020a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten};
39120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenmodule_comedi_pci_driver(apci2032_driver, apci2032_pci_driver);
39290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
39390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
39490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
39590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
396