addi_apci_2032.c revision 818f569fe930c5b8a05d1a44ece3c63c99c13c88
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 3233782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/pci.h> 33abac8b54a353b9a1ac7d09ff790812655f618896H Hartley Sweeten#include <linux/interrupt.h> 34abac8b54a353b9a1ac7d09ff790812655f618896H Hartley Sweeten 353d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "../comedidev.h" 365b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten#include "addi_watchdog.h" 373d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "comedi_fc.h" 383d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten 39d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten/* 40d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * PCI bar 1 I/O Register map 41d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten */ 427180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_DO_REG 0x00 437180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_REG 0x04 447180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_VCC_ENA (1 << 0) 457180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_CC_ENA (1 << 1) 467180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_REG 0x08 477180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_VCC (1 << 0) 487180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_CC (1 << 1) 497180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_REG 0x0c 507180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_IRQ (1 << 0) 517180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_REG 0x10 5223fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten 535c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbottstruct apci2032_int_private { 545c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spinlock_t spinlock; 55215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott unsigned int stop_count; 565c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bool active; 575c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned char enabled_isns; 585c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott}; 595c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 60d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweetenstatic int apci2032_do_insn_bits(struct comedi_device *dev, 61d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten struct comedi_subdevice *s, 62d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten struct comedi_insn *insn, 63d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int *data) 64d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 65d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int mask = data[0]; 66d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int bits = data[1]; 67d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 687180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten s->state = inl(dev->iobase + APCI2032_DO_REG); 69d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten if (mask) { 70d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten s->state &= ~mask; 71d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten s->state |= (bits & mask); 72d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 737180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(s->state, dev->iobase + APCI2032_DO_REG); 74d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten } 75d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 76d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten data[1] = s->state; 77d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 78d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten return insn->n; 79d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 80d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 8105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_insn_bits(struct comedi_device *dev, 8205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s, 8305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_insn *insn, 8405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten unsigned int *data) 85b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten{ 86b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott data[1] = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3; 8705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return insn->n; 8805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten} 89b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 905c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbottstatic void apci2032_int_stop(struct comedi_device *dev, 915c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct comedi_subdevice *s) 925c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott{ 935c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 945c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 955c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv->active = false; 965c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv->enabled_isns = 0; 975c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG); 985c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott} 995c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 100215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbottstatic bool apci2032_int_start(struct comedi_device *dev, 101215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct comedi_subdevice *s, 102215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott unsigned char enabled_isns) 103215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott{ 104215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct apci2032_int_private *subpriv = s->private; 105215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct comedi_cmd *cmd = &s->async->cmd; 106215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott bool do_event; 107215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 108215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->enabled_isns = enabled_isns; 109215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count = cmd->stop_arg; 110215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (cmd->stop_src == TRIG_COUNT && subpriv->stop_count == 0) { 111215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott /* An empty acquisition! */ 112215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott s->async->events |= COMEDI_CB_EOA; 113215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->active = false; 114215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = true; 115215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } else { 116215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->active = true; 117215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott outl(enabled_isns, dev->iobase + APCI2032_INT_CTRL_REG); 118215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = false; 119215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 120215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 121215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott return do_event; 122215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott} 123215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 12405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmdtest(struct comedi_device *dev, 12505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s, 12605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_cmd *cmd) 12705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten{ 12805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten int err = 0; 129b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 13005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 1 : check if triggers are trivially valid */ 131b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 13205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); 1335c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); 1345c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); 13505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 136215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 137b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 13805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 13905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 1; 140b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 14105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 2a : make sure trigger sources are unique */ 142215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_is_unique(cmd->stop_src); 143215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 14405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 2b : and mutually compatible */ 14505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 14605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 14705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 2; 14805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 14905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 3: check if arguments are trivially valid */ 15005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 15105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 1525c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 15305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 1545c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 155215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (cmd->stop_src == TRIG_NONE) 156215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 15705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 15805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 15905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 3; 16005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 16105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* step 4: ignored */ 16205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 16305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 16405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 4; 16505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 16605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 167b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten} 168b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 16905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmd(struct comedi_device *dev, 17005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s) 171d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 17205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_cmd *cmd = &s->async->cmd; 1735c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 1745c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned char enabled_isns; 1755c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int n; 1765c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned long flags; 177215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott bool do_event; 1785c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 1795c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott enabled_isns = 0; 1805c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott for (n = 0; n < cmd->chanlist_len; n++) 1815c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott enabled_isns |= 1 << CR_CHAN(cmd->chanlist[n]); 18205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 1835c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_irqsave(&subpriv->spinlock, flags); 184215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = apci2032_int_start(dev, s, enabled_isns); 1855c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock_irqrestore(&subpriv->spinlock, flags); 18605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 187215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (do_event) 188215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott comedi_event(dev, s); 189215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 19005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 191d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 1927180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten 19305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cancel(struct comedi_device *dev, 19405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s) 195d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 1965c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 1975c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned long flags; 1985c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 1995c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_irqsave(&subpriv->spinlock, flags); 2005c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (subpriv->active) 2015c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott apci2032_int_stop(dev, s); 2025c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock_irqrestore(&subpriv->spinlock, flags); 203d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 20405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 205d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 206317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten 20705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic irqreturn_t apci2032_interrupt(int irq, void *d) 20825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 20905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_device *dev = d; 21005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s = dev->read_subdev; 2115c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv; 21205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten unsigned int val; 2135c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bool do_event = false; 21405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2150774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott if (!dev->attached) 2160774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott return IRQ_NONE; 2170774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott 21805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Check if VCC OR CC interrupt has occurred */ 21905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten val = inl(dev->iobase + APCI2032_STATUS_REG) & APCI2032_STATUS_IRQ; 22005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (!val) 22105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return IRQ_NONE; 22205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2235c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv = s->private; 2245c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock(&subpriv->spinlock); 2255c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 226b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott val = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3; 227ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott /* Disable triggered interrupt sources. */ 228ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott outl(~val & 3, dev->iobase + APCI2032_INT_CTRL_REG); 229ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott /* 230ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * Note: We don't reenable the triggered interrupt sources because they 231ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * are level-sensitive, hardware error status interrupt sources and 232ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * they'd keep triggering interrupts repeatedly. 233ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott */ 23405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2355c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (subpriv->active && (val & subpriv->enabled_isns) != 0) { 2365c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned short bits; 2375c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int n, len; 2385c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int *chanlist; 2395c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2405c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott /* Bits in scan data correspond to indices in channel list. */ 2415c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bits = 0; 2425c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott len = s->async->cmd.chanlist_len; 2435c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott chanlist = &s->async->cmd.chanlist[0]; 2445c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott for (n = 0; n < len; n++) 2455c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if ((val & (1U << CR_CHAN(chanlist[n]))) != 0) 2465c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bits |= 1U << n; 2475c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2485c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (comedi_buf_put(s->async, bits)) { 2495c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; 250215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (s->async->cmd.stop_src == TRIG_COUNT && 251215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count > 0) { 252215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count--; 253215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (subpriv->stop_count == 0) { 254215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott /* end of acquisition */ 255215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott s->async->events |= COMEDI_CB_EOA; 256215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott apci2032_int_stop(dev, s); 257215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 258215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 2595c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } else { 2605c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott apci2032_int_stop(dev, s); 2615c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->async->events |= COMEDI_CB_OVERFLOW; 2625c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } 2635c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott do_event = true; 2645c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } 2655c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2665c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock(&subpriv->spinlock); 2675c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (do_event) 2685c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott comedi_event(dev, s); 26905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 27005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return IRQ_HANDLED; 27125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 27225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 273791c9792ff2d12a02f0ab1c47fd7f7a94828b05bH Hartley Sweetenstatic int apci2032_reset(struct comedi_device *dev) 27425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 2757180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(0x0, dev->iobase + APCI2032_DO_REG); 2767180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG); 2775b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten 2785b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten addi_watchdog_reset(dev->iobase + APCI2032_WDOG_REG); 27925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 28025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return 0; 28125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 28225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 28325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic int apci2032_auto_attach(struct comedi_device *dev, 28425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten unsigned long context_unused) 28525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 28625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten struct pci_dev *pcidev = comedi_to_pci_dev(dev); 28725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten struct comedi_subdevice *s; 2880c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten int ret; 28925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 290c0c3c7dfc1fd5c970b9893e68796314e8551124fH Hartley Sweeten dev->board_name = dev->driver->driver_name; 29125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 292818f569fe930c5b8a05d1a44ece3c63c99c13c88H Hartley Sweeten ret = comedi_pci_enable(dev); 29325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret) 29425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return ret; 29570ff406599a5debfa6e5ef243e5e093f63a9ed69H Hartley Sweeten dev->iobase = pci_resource_start(pcidev, 1); 2960774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott apci2032_reset(dev); 29725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 29825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (pcidev->irq > 0) { 29905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten ret = request_irq(pcidev->irq, apci2032_interrupt, 30005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten IRQF_SHARED, dev->board_name, dev); 30125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret == 0) 30225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten dev->irq = pcidev->irq; 30325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten } 30425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 30505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten ret = comedi_alloc_subdevices(dev, 3); 30625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret) 30725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return ret; 30825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 3090c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten /* Initialize the digital output subdevice */ 31025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten s = &dev->subdevices[0]; 311cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->type = COMEDI_SUBD_DO; 312cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->subdev_flags = SDF_WRITEABLE; 313cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->n_chan = 32; 314cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->maxdata = 1; 315cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->range_table = &range_digital; 316cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->insn_bits = apci2032_do_insn_bits; 31725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 3180c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten /* Initialize the watchdog subdevice */ 3190c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten s = &dev->subdevices[1]; 3205b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten ret = addi_watchdog_init(s, dev->iobase + APCI2032_WDOG_REG); 3215b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten if (ret) 3225b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten return ret; 32325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 32405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Initialize the interrupt subdevice */ 32505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s = &dev->subdevices[2]; 3265f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->type = COMEDI_SUBD_DI; 3275f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->subdev_flags = SDF_READABLE; 3285f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->n_chan = 2; 3295f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->maxdata = 1; 3305f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->range_table = &range_digital; 3315f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->insn_bits = apci2032_int_insn_bits; 33205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (dev->irq) { 3335c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv; 3345c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 33505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten dev->read_subdev = s; 3365c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); 3375c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (!subpriv) 3385c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott return -ENOMEM; 3395c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_init(&subpriv->spinlock); 3405c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->private = subpriv; 341b82fe57c4d059a8ff1190ead1693d66b868353b2Ian Abbott s->subdev_flags = SDF_READABLE | SDF_CMD_READ; 3425c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->len_chanlist = 2; 34305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->do_cmdtest = apci2032_int_cmdtest; 34405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->do_cmd = apci2032_int_cmd; 34505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->cancel = apci2032_int_cancel; 34605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten } 34705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 34825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return 0; 34925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 35025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 35125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic void apci2032_detach(struct comedi_device *dev) 35225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 353dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten if (dev->iobase) 354dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten apci2032_reset(dev); 355dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten if (dev->irq) 356dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten free_irq(dev->irq, dev); 3575c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (dev->read_subdev) 3585c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott kfree(dev->read_subdev->private); 3595b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten if (dev->subdevices) 3605b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten addi_watchdog_cleanup(&dev->subdevices[1]); 3617f072f54ae5dc9965cbe450419b1389d13e2b849H Hartley Sweeten comedi_pci_disable(dev); 36225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 36325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 36420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct comedi_driver apci2032_driver = { 36520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .driver_name = "addi_apci_2032", 36620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .module = THIS_MODULE, 36725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten .auto_attach = apci2032_auto_attach, 36825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten .detach = apci2032_detach, 36920a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}; 37020a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten 371a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int apci2032_pci_probe(struct pci_dev *dev, 372b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten const struct pci_device_id *id) 37320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{ 374b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten return comedi_pci_auto_config(dev, &apci2032_driver, id->driver_data); 37520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten} 37620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten 37720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = { 378317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) }, 379317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten { 0 } 380317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten}; 38120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley SweetenMODULE_DEVICE_TABLE(pci, apci2032_pci_table); 382317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten 38320a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct pci_driver apci2032_pci_driver = { 38420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .name = "addi_apci_2032", 38520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .id_table = apci2032_pci_table, 38620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .probe = apci2032_pci_probe, 3879901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe .remove = comedi_pci_auto_unconfig, 38820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}; 38920a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenmodule_comedi_pci_driver(apci2032_driver, apci2032_pci_driver); 39090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 39190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 39290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 39390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 394