// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1032.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. * Project manager: Eric Stolz * * ADDI-DATA GmbH * Dieselstrasse 3 * D-77833 Ottersweier * Tel: +19(0)7223/9493-0 * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * [email protected] */ /* * Driver: addi_apci_1032 * Description: ADDI-DATA APCI-1032 Digital Input Board * Author: ADDI-DATA GmbH <[email protected]>, * H Hartley Sweeten <[email protected]> * Status: untested * Devices: [ADDI-DATA] APCI-1032 (addi_apci_1032) * * Configuration options: * None; devices are configured automatically. * * This driver models the APCI-1032 as a 32-channel, digital input subdevice * plus an additional digital input subdevice to handle change-of-state (COS) * interrupts (if an interrupt handler can be set up successfully). * * The COS subdevice supports comedi asynchronous read commands. * * Change-Of-State (COS) interrupt configuration: * * Channels 0 to 15 are interruptible. These channels can be configured * to generate interrupts based on AND/OR logic for the desired channels. * * OR logic: * - reacts to rising or falling edges * - interrupt is generated when any enabled channel meets the desired * interrupt condition * * AND logic: * - reacts to changes in level of the selected inputs * - interrupt is generated when all enabled channels meet the desired * interrupt condition * - after an interrupt, a change in level must occur on the selected * inputs to release the IRQ logic * * The COS subdevice must be configured before setting up a comedi * asynchronous command: * * data[0] : INSN_CONFIG_DIGITAL_TRIG * data[1] : trigger number (= 0) * data[2] : configuration operation: * - COMEDI_DIGITAL_TRIG_DISABLE = no interrupts * - COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts * - COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts * data[3] : left-shift for data[4] and data[5] * data[4] : rising-edge/high level channels * data[5] : falling-edge/low level channels */ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/comedi/comedi_pci.h> #include "amcc_s5933.h" /* * I/O Register Map */ #define APCI1032_DI_REG … #define APCI1032_MODE1_REG … #define APCI1032_MODE2_REG … #define APCI1032_STATUS_REG … #define APCI1032_CTRL_REG … #define APCI1032_CTRL_INT_MODE(x) … #define APCI1032_CTRL_INT_OR … #define APCI1032_CTRL_INT_AND … #define APCI1032_CTRL_INT_ENA … struct apci1032_private { … }; static int apci1032_reset(struct comedi_device *dev) { … } static int apci1032_cos_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { … } static int apci1032_cos_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { … } static int apci1032_cos_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { … } /* * Change-Of-State (COS) 'do_cmd' operation * * Enable the COS interrupt as configured by apci1032_cos_insn_config(). */ static int apci1032_cos_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { … } static int apci1032_cos_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { … } static irqreturn_t apci1032_interrupt(int irq, void *d) { … } static int apci1032_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { … } static int apci1032_auto_attach(struct comedi_device *dev, unsigned long context_unused) { … } static void apci1032_detach(struct comedi_device *dev) { … } static struct comedi_driver apci1032_driver = …; static int apci1032_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { … } static const struct pci_device_id apci1032_pci_table[] = …; MODULE_DEVICE_TABLE(pci, apci1032_pci_table); static struct pci_driver apci1032_pci_driver = …; module_comedi_pci_driver(…); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;