addi_apci_2032.c revision 9901a4d75d007686e8f6473189cafc4b216b7449
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" 335b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten#include "addi_watchdog.h" 343d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten#include "comedi_fc.h" 353d41c44370a9a1e78e53c9997289347ec97d46eeH Hartley Sweeten 36d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten/* 37d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten * PCI bar 1 I/O Register map 38d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten */ 397180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_DO_REG 0x00 407180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_REG 0x04 417180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_VCC_ENA (1 << 0) 427180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_CTRL_CC_ENA (1 << 1) 437180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_REG 0x08 447180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_VCC (1 << 0) 457180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_INT_STATUS_CC (1 << 1) 467180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_REG 0x0c 477180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_STATUS_IRQ (1 << 0) 487180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten#define APCI2032_WDOG_REG 0x10 4923fb174746057b6d13539735241390eb9e3fdb46H Hartley Sweeten 505c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbottstruct apci2032_int_private { 515c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spinlock_t spinlock; 52215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott unsigned int stop_count; 535c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bool active; 545c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned char enabled_isns; 555c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott}; 565c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 57d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweetenstatic int apci2032_do_insn_bits(struct comedi_device *dev, 58d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten struct comedi_subdevice *s, 59d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten struct comedi_insn *insn, 60d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int *data) 61d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 62d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int mask = data[0]; 63d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten unsigned int bits = data[1]; 64d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 657180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten s->state = inl(dev->iobase + APCI2032_DO_REG); 66d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten if (mask) { 67d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten s->state &= ~mask; 68d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten s->state |= (bits & mask); 69d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 707180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(s->state, dev->iobase + APCI2032_DO_REG); 71d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten } 72d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 73d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten data[1] = s->state; 74d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 75d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten return insn->n; 76d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 77d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 7805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_insn_bits(struct comedi_device *dev, 7905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s, 8005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_insn *insn, 8105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten unsigned int *data) 82b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten{ 83b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott data[1] = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3; 8405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return insn->n; 8505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten} 86b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 875c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbottstatic void apci2032_int_stop(struct comedi_device *dev, 885c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct comedi_subdevice *s) 895c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott{ 905c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 915c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 925c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv->active = false; 935c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv->enabled_isns = 0; 945c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG); 955c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott} 965c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 97215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbottstatic bool apci2032_int_start(struct comedi_device *dev, 98215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct comedi_subdevice *s, 99215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott unsigned char enabled_isns) 100215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott{ 101215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct apci2032_int_private *subpriv = s->private; 102215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott struct comedi_cmd *cmd = &s->async->cmd; 103215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott bool do_event; 104215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 105215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->enabled_isns = enabled_isns; 106215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count = cmd->stop_arg; 107215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (cmd->stop_src == TRIG_COUNT && subpriv->stop_count == 0) { 108215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott /* An empty acquisition! */ 109215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott s->async->events |= COMEDI_CB_EOA; 110215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->active = false; 111215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = true; 112215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } else { 113215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->active = true; 114215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott outl(enabled_isns, dev->iobase + APCI2032_INT_CTRL_REG); 115215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = false; 116215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 117215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 118215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott return do_event; 119215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott} 120215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 12105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmdtest(struct comedi_device *dev, 12205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s, 12305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_cmd *cmd) 12405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten{ 12505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten int err = 0; 126b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 12705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 1 : check if triggers are trivially valid */ 128b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 12905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); 1305c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); 1315c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); 13205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 133215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 134b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 13505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 13605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 1; 137b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 13805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 2a : make sure trigger sources are unique */ 139215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_is_unique(cmd->stop_src); 140215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 14105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 2b : and mutually compatible */ 14205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 14305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 14405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 2; 14505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 14605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Step 3: check if arguments are trivially valid */ 14705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 14805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 1495c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 15005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 1515c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 152215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (cmd->stop_src == TRIG_NONE) 153215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 15405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 15505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 15605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 3; 15705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 15805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* step 4: ignored */ 15905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 16005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (err) 16105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 4; 16205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 16305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 164b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten} 165b3b7dab7580982a7d0b55395a8b116808447f85aH Hartley Sweeten 16605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cmd(struct comedi_device *dev, 16705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s) 168d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 16905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_cmd *cmd = &s->async->cmd; 1705c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 1715c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned char enabled_isns; 1725c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int n; 1735c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned long flags; 174215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott bool do_event; 1755c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 1765c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott enabled_isns = 0; 1775c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott for (n = 0; n < cmd->chanlist_len; n++) 1785c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott enabled_isns |= 1 << CR_CHAN(cmd->chanlist[n]); 17905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 1805c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_irqsave(&subpriv->spinlock, flags); 181215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott do_event = apci2032_int_start(dev, s, enabled_isns); 1825c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock_irqrestore(&subpriv->spinlock, flags); 18305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 184215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (do_event) 185215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott comedi_event(dev, s); 186215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott 18705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 188d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 1897180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten 19005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic int apci2032_int_cancel(struct comedi_device *dev, 19105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s) 192d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten{ 1935c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv = s->private; 1945c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned long flags; 1955c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 1965c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_irqsave(&subpriv->spinlock, flags); 1975c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (subpriv->active) 1985c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott apci2032_int_stop(dev, s); 1995c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock_irqrestore(&subpriv->spinlock, flags); 200d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten 20105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return 0; 202d02178b7fb1f2545ebe1004dc8f1f4436a9d37c1H Hartley Sweeten} 203317285d71acccbda2fbab7e53d6b33c52a151a32H Hartley Sweeten 20405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweetenstatic irqreturn_t apci2032_interrupt(int irq, void *d) 20525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 20605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_device *dev = d; 20705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten struct comedi_subdevice *s = dev->read_subdev; 2085c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv; 20905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten unsigned int val; 2105c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bool do_event = false; 21105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2120774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott if (!dev->attached) 2130774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott return IRQ_NONE; 2140774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott 21505fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Check if VCC OR CC interrupt has occurred */ 21605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten val = inl(dev->iobase + APCI2032_STATUS_REG) & APCI2032_STATUS_IRQ; 21705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (!val) 21805fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return IRQ_NONE; 21905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2205c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv = s->private; 2215c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock(&subpriv->spinlock); 2225c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 223b652bd83a0528c43e935cb6f2f8df024b7a85c5eIan Abbott val = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3; 224ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott /* Disable triggered interrupt sources. */ 225ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott outl(~val & 3, dev->iobase + APCI2032_INT_CTRL_REG); 226ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott /* 227ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * Note: We don't reenable the triggered interrupt sources because they 228ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * are level-sensitive, hardware error status interrupt sources and 229ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott * they'd keep triggering interrupts repeatedly. 230ef6543dbad12c1086f3bc3565d8266352521d8a3Ian Abbott */ 23105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 2325c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (subpriv->active && (val & subpriv->enabled_isns) != 0) { 2335c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned short bits; 2345c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int n, len; 2355c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott unsigned int *chanlist; 2365c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2375c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott /* Bits in scan data correspond to indices in channel list. */ 2385c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bits = 0; 2395c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott len = s->async->cmd.chanlist_len; 2405c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott chanlist = &s->async->cmd.chanlist[0]; 2415c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott for (n = 0; n < len; n++) 2425c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if ((val & (1U << CR_CHAN(chanlist[n]))) != 0) 2435c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott bits |= 1U << n; 2445c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2455c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (comedi_buf_put(s->async, bits)) { 2465c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; 247215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (s->async->cmd.stop_src == TRIG_COUNT && 248215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count > 0) { 249215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott subpriv->stop_count--; 250215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott if (subpriv->stop_count == 0) { 251215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott /* end of acquisition */ 252215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott s->async->events |= COMEDI_CB_EOA; 253215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott apci2032_int_stop(dev, s); 254215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 255215caceb3dac9eb7d431c9da21394c6ccb778b15Ian Abbott } 2565c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } else { 2575c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott apci2032_int_stop(dev, s); 2585c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->async->events |= COMEDI_CB_OVERFLOW; 2595c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } 2605c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott do_event = true; 2615c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott } 2625c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 2635c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_unlock(&subpriv->spinlock); 2645c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (do_event) 2655c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott comedi_event(dev, s); 26605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 26705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten return IRQ_HANDLED; 26825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 26925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 270791c9792ff2d12a02f0ab1c47fd7f7a94828b05bH Hartley Sweetenstatic int apci2032_reset(struct comedi_device *dev) 27125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 2727180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(0x0, dev->iobase + APCI2032_DO_REG); 2737180eb30deee6c05b8924348a7ac7d4deefcf56eH Hartley Sweeten outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG); 2745b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten 2755b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten addi_watchdog_reset(dev->iobase + APCI2032_WDOG_REG); 27625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 27725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return 0; 27825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 27925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 28025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic int apci2032_auto_attach(struct comedi_device *dev, 28125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten unsigned long context_unused) 28225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 28325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten struct pci_dev *pcidev = comedi_to_pci_dev(dev); 28425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten struct comedi_subdevice *s; 2850c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten int ret; 28625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 287c0c3c7dfc1fd5c970b9893e68796314e8551124fH Hartley Sweeten dev->board_name = dev->driver->driver_name; 28825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 28925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten ret = comedi_pci_enable(pcidev, dev->board_name); 29025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret) 29125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return ret; 29270ff406599a5debfa6e5ef243e5e093f63a9ed69H Hartley Sweeten dev->iobase = pci_resource_start(pcidev, 1); 2930774c2b5c1e0025cb016393d8552171c0ec55c39Ian Abbott apci2032_reset(dev); 29425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 29525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (pcidev->irq > 0) { 29605fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten ret = request_irq(pcidev->irq, apci2032_interrupt, 29705fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten IRQF_SHARED, dev->board_name, dev); 29825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret == 0) 29925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten dev->irq = pcidev->irq; 30025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten } 30125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 30205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten ret = comedi_alloc_subdevices(dev, 3); 30325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (ret) 30425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return ret; 30525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 3060c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten /* Initialize the digital output subdevice */ 30725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten s = &dev->subdevices[0]; 308cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->type = COMEDI_SUBD_DO; 309cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->subdev_flags = SDF_WRITEABLE; 310cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->n_chan = 32; 311cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->maxdata = 1; 312cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->range_table = &range_digital; 313cf11088242f0f73cb616ab66fb16c2da3d626fffH Hartley Sweeten s->insn_bits = apci2032_do_insn_bits; 31425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 3150c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten /* Initialize the watchdog subdevice */ 3160c33bdd01abf1d6722792b2022b974116151a572H Hartley Sweeten s = &dev->subdevices[1]; 3175b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten ret = addi_watchdog_init(s, dev->iobase + APCI2032_WDOG_REG); 3185b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten if (ret) 3195b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten return ret; 32025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 32105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten /* Initialize the interrupt subdevice */ 32205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s = &dev->subdevices[2]; 3235f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->type = COMEDI_SUBD_DI; 3245f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->subdev_flags = SDF_READABLE; 3255f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->n_chan = 2; 3265f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->maxdata = 1; 3275f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->range_table = &range_digital; 3285f6c2a954d17544c68ce83d016ea456207cadeacIan Abbott s->insn_bits = apci2032_int_insn_bits; 32905fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten if (dev->irq) { 3305c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott struct apci2032_int_private *subpriv; 3315c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott 33205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten dev->read_subdev = s; 3335c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); 3345c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (!subpriv) 3355c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott return -ENOMEM; 3365c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott spin_lock_init(&subpriv->spinlock); 3375c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->private = subpriv; 338b82fe57c4d059a8ff1190ead1693d66b868353b2Ian Abbott s->subdev_flags = SDF_READABLE | SDF_CMD_READ; 3395c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott s->len_chanlist = 2; 34005fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->do_cmdtest = apci2032_int_cmdtest; 34105fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->do_cmd = apci2032_int_cmd; 34205fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten s->cancel = apci2032_int_cancel; 34305fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten } 34405fcdcede016a74ce7350af94aede6a49eebd5c9H Hartley Sweeten 34525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten return 0; 34625adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 34725adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 34825adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweetenstatic void apci2032_detach(struct comedi_device *dev) 34925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten{ 35025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten struct pci_dev *pcidev = comedi_to_pci_dev(dev); 35125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 352dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten if (dev->iobase) 353dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten apci2032_reset(dev); 354dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten if (dev->irq) 355dce10abc499ec5e53ea01683fdb2181f24d6776dH Hartley Sweeten free_irq(dev->irq, dev); 3565c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott if (dev->read_subdev) 3575c2d4cba9586ddc3505f51bddf935ddc65a0e0bbIan Abbott kfree(dev->read_subdev->private); 3585b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten if (dev->subdevices) 3595b62fe2a03e9d25569c0fa0b81b96ac6f0c9b5fdH Hartley Sweeten addi_watchdog_cleanup(&dev->subdevices[1]); 36025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (pcidev) { 36125adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten if (dev->iobase) 36225adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten comedi_pci_disable(pcidev); 36325adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten } 36425adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten} 36525adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten 36620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweetenstatic struct comedi_driver apci2032_driver = { 36720a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .driver_name = "addi_apci_2032", 36820a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten .module = THIS_MODULE, 36925adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten .auto_attach = apci2032_auto_attach, 37025adf2ccf68814fade52f70ed2888b65db1e5156H Hartley Sweeten .detach = apci2032_detach, 37120a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten}; 37220a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten 373a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int apci2032_pci_probe(struct pci_dev *dev, 37420a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten const struct pci_device_id *ent) 37520a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten{ 37620a22b706b8ee37d1a2282f2c9bf7f2c73a5a7a5H Hartley Sweeten return comedi_pci_auto_config(dev, &apci2032_driver); 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, 3899901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe .remove = comedi_pci_auto_unconfig, 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