linux/drivers/comedi/drivers/pcmmio.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * pcmmio.c
 * Driver for Winsystems PC-104 based multifunction IO board.
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 2007 Calin A. Culianu <[email protected]>
 */

/*
 * Driver: pcmmio
 * Description: A driver for the PCM-MIO multifunction board
 * Devices: [Winsystems] PCM-MIO (pcmmio)
 * Author: Calin Culianu <[email protected]>
 * Updated: Wed, May 16 2007 16:21:10 -0500
 * Status: works
 *
 * A driver for the PCM-MIO multifunction board from Winsystems. This
 * is a PC-104 based I/O board. It contains four subdevices:
 *
 *	subdevice 0 - 16 channels of 16-bit AI
 *	subdevice 1 - 8 channels of 16-bit AO
 *	subdevice 2 - first 24 channels of the 48 channel of DIO
 *			(with edge-triggered interrupt support)
 *	subdevice 3 - last 24 channels of the 48 channel DIO
 *			(no interrupt support for this bank of channels)
 *
 * Some notes:
 *
 * Synchronous reads and writes are the only things implemented for analog
 * input and output. The hardware itself can do streaming acquisition, etc.
 *
 * Asynchronous I/O for the DIO subdevices *is* implemented, however! They
 * are basically edge-triggered interrupts for any configuration of the
 * channels in subdevice 2.
 *
 * Also note that this interrupt support is untested.
 *
 * A few words about edge-detection IRQ support (commands on DIO):
 *
 * To use edge-detection IRQ support for the DIO subdevice, pass the IRQ
 * of the board to the comedi_config command. The board IRQ is not jumpered
 * but rather configured through software, so any IRQ from 1-15 is OK.
 *
 * Due to the genericity of the comedi API, you need to create a special
 * comedi_command in order to use edge-triggered interrupts for DIO.
 *
 * Use comedi_commands with TRIG_NOW.  Your callback will be called each
 * time an edge is detected on the specified DIO line(s), and the data
 * values will be two sample_t's, which should be concatenated to form
 * one 32-bit unsigned int. This value is the mask of channels that had
 * edges detected from your channel list. Note that the bits positions
 * in the mask correspond to positions in your chanlist when you
 * specified the command and *not* channel id's!
 *
 * To set the polarity of the edge-detection interrupts pass a nonzero value
 * for either CR_RANGE or CR_AREF for edge-up polarity, or a zero
 * value for both CR_RANGE and CR_AREF if you want edge-down polarity.
 *
 * Configuration Options:
 *   [0] - I/O port base address
 *   [1] - IRQ (optional -- for edge-detect interrupt support only,
 *		leave out if you don't need this feature)
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/comedi/comedidev.h>

/*
 * Register I/O map
 */
#define PCMMIO_AI_LSB_REG
#define PCMMIO_AI_MSB_REG
#define PCMMIO_AI_CMD_REG
#define PCMMIO_AI_CMD_SE
#define PCMMIO_AI_CMD_ODD_CHAN
#define PCMMIO_AI_CMD_CHAN_SEL(x)
#define PCMMIO_AI_CMD_RANGE(x)
#define PCMMIO_RESOURCE_REG
#define PCMMIO_RESOURCE_IRQ(x)
#define PCMMIO_AI_STATUS_REG
#define PCMMIO_AI_STATUS_DATA_READY
#define PCMMIO_AI_STATUS_DATA_DMA_PEND
#define PCMMIO_AI_STATUS_CMD_DMA_PEND
#define PCMMIO_AI_STATUS_IRQ_PEND
#define PCMMIO_AI_STATUS_DATA_DRQ_ENA
#define PCMMIO_AI_STATUS_REG_SEL
#define PCMMIO_AI_STATUS_CMD_DRQ_ENA
#define PCMMIO_AI_STATUS_IRQ_ENA
#define PCMMIO_AI_RES_ENA_REG
#define PCMMIO_AI_RES_ENA_CMD_REG_ACCESS
#define PCMMIO_AI_RES_ENA_AI_RES_ACCESS
#define PCMMIO_AI_RES_ENA_DIO_RES_ACCESS
#define PCMMIO_AI_2ND_ADC_OFFSET

#define PCMMIO_AO_LSB_REG
#define PCMMIO_AO_LSB_SPAN(x)
#define PCMMIO_AO_MSB_REG
#define PCMMIO_AO_CMD_REG
#define PCMMIO_AO_CMD_WR_SPAN
#define PCMMIO_AO_CMD_WR_CODE
#define PCMMIO_AO_CMD_UPDATE
#define PCMMIO_AO_CMD_UPDATE_ALL
#define PCMMIO_AO_CMD_WR_SPAN_UPDATE
#define PCMMIO_AO_CMD_WR_CODE_UPDATE
#define PCMMIO_AO_CMD_WR_SPAN_UPDATE_ALL
#define PCMMIO_AO_CMD_WR_CODE_UPDATE_ALL
#define PCMMIO_AO_CMD_RD_B1_SPAN
#define PCMMIO_AO_CMD_RD_B1_CODE
#define PCMMIO_AO_CMD_RD_B2_SPAN
#define PCMMIO_AO_CMD_RD_B2_CODE
#define PCMMIO_AO_CMD_NOP
#define PCMMIO_AO_CMD_CHAN_SEL(x)
#define PCMMIO_AO_CMD_CHAN_SEL_ALL
#define PCMMIO_AO_STATUS_REG
#define PCMMIO_AO_STATUS_DATA_READY
#define PCMMIO_AO_STATUS_DATA_DMA_PEND
#define PCMMIO_AO_STATUS_CMD_DMA_PEND
#define PCMMIO_AO_STATUS_IRQ_PEND
#define PCMMIO_AO_STATUS_DATA_DRQ_ENA
#define PCMMIO_AO_STATUS_REG_SEL
#define PCMMIO_AO_STATUS_CMD_DRQ_ENA
#define PCMMIO_AO_STATUS_IRQ_ENA
#define PCMMIO_AO_RESOURCE_ENA_REG
#define PCMMIO_AO_2ND_DAC_OFFSET

/*
 * WinSystems WS16C48
 *
 * Offset    Page 0       Page 1       Page 2       Page 3
 * ------  -----------  -----------  -----------  -----------
 *  0x10   Port 0 I/O   Port 0 I/O   Port 0 I/O   Port 0 I/O
 *  0x11   Port 1 I/O   Port 1 I/O   Port 1 I/O   Port 1 I/O
 *  0x12   Port 2 I/O   Port 2 I/O   Port 2 I/O   Port 2 I/O
 *  0x13   Port 3 I/O   Port 3 I/O   Port 3 I/O   Port 3 I/O
 *  0x14   Port 4 I/O   Port 4 I/O   Port 4 I/O   Port 4 I/O
 *  0x15   Port 5 I/O   Port 5 I/O   Port 5 I/O   Port 5 I/O
 *  0x16   INT_PENDING  INT_PENDING  INT_PENDING  INT_PENDING
 *  0x17    Page/Lock    Page/Lock    Page/Lock    Page/Lock
 *  0x18       N/A         POL_0       ENAB_0       INT_ID0
 *  0x19       N/A         POL_1       ENAB_1       INT_ID1
 *  0x1a       N/A         POL_2       ENAB_2       INT_ID2
 */
#define PCMMIO_PORT_REG(x)
#define PCMMIO_INT_PENDING_REG
#define PCMMIO_PAGE_LOCK_REG
#define PCMMIO_LOCK_PORT(x)
#define PCMMIO_PAGE(x)
#define PCMMIO_PAGE_MASK
#define PCMMIO_PAGE_POL
#define PCMMIO_PAGE_ENAB
#define PCMMIO_PAGE_INT_ID
#define PCMMIO_PAGE_REG(x)

static const struct comedi_lrange pcmmio_ai_ranges =;

static const struct comedi_lrange pcmmio_ao_ranges =;

struct pcmmio_private {};

static void pcmmio_dio_write(struct comedi_device *dev, unsigned int val,
			     int page, int port)
{}

static unsigned int pcmmio_dio_read(struct comedi_device *dev,
				    int page, int port)
{}

/*
 * Each channel can be individually programmed for input or output.
 * Writing a '0' to a channel causes the corresponding output pin
 * to go to a high-z state (pulled high by an external 10K resistor).
 * This allows it to be used as an input. When used in the input mode,
 * a read reflects the inverted state of the I/O pin, such that a
 * high on the pin will read as a '0' in the register. Writing a '1'
 * to a bit position causes the pin to sink current (up to 12mA),
 * effectively pulling it low.
 */
static int pcmmio_dio_insn_bits(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_insn *insn,
				unsigned int *data)
{}

static int pcmmio_dio_insn_config(struct comedi_device *dev,
				  struct comedi_subdevice *s,
				  struct comedi_insn *insn,
				  unsigned int *data)
{}

static void pcmmio_reset(struct comedi_device *dev)
{}

/* devpriv->spinlock is already locked */
static void pcmmio_stop_intr(struct comedi_device *dev,
			     struct comedi_subdevice *s)
{}

static void pcmmio_handle_dio_intr(struct comedi_device *dev,
				   struct comedi_subdevice *s,
				   unsigned int triggered)
{}

static irqreturn_t interrupt_pcmmio(int irq, void *d)
{}

/* devpriv->spinlock is already locked */
static void pcmmio_start_intr(struct comedi_device *dev,
			      struct comedi_subdevice *s)
{}

static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{}

static int pcmmio_inttrig_start_intr(struct comedi_device *dev,
				     struct comedi_subdevice *s,
				     unsigned int trig_num)
{}

/*
 * 'do_cmd' function for an 'INTERRUPT' subdevice.
 */
static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{}

static int pcmmio_cmdtest(struct comedi_device *dev,
			  struct comedi_subdevice *s,
			  struct comedi_cmd *cmd)
{}

static int pcmmio_ai_eoc(struct comedi_device *dev,
			 struct comedi_subdevice *s,
			 struct comedi_insn *insn,
			 unsigned long context)
{}

static int pcmmio_ai_insn_read(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{}

static int pcmmio_ao_eoc(struct comedi_device *dev,
			 struct comedi_subdevice *s,
			 struct comedi_insn *insn,
			 unsigned long context)
{}

static int pcmmio_ao_insn_write(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_insn *insn,
				unsigned int *data)
{}

static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{}

static struct comedi_driver pcmmio_driver =;
module_comedi_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();