File Index
Files and directories
Sign in
FILE

amplc_pci224.c

File preview with syntax highlighting.

linux-6.19.14/drivers/comedi/drivers/amplc_pci224.c C
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * comedi/drivers/amplc_pci224.c
   4 * Driver for Amplicon PCI224 and PCI234 AO boards.
   5 *
   6 * Copyright (C) 2005 MEV Ltd. <https://www.mev.co.uk/>
   7 *
   8 * COMEDI - Linux Control and Measurement Device Interface
   9 * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
  10 */
  11
  12/*
  13 * Driver: amplc_pci224
  14 * Description: Amplicon PCI224, PCI234
  15 * Author: Ian Abbott <abbotti@mev.co.uk>
  16 * Devices: [Amplicon] PCI224 (amplc_pci224), PCI234
  17 * Updated: Thu, 31 Jul 2014 11:08:03 +0000
  18 * Status: works, but see caveats
  19 *
  20 * Supports:
  21 *
  22 *   - ao_insn read/write
  23 *   - ao_do_cmd mode with the following sources:
  24 *
  25 *     - start_src         TRIG_INT        TRIG_EXT
  26 *     - scan_begin_src    TRIG_TIMER      TRIG_EXT
  27 *     - convert_src       TRIG_NOW
  28 *     - scan_end_src      TRIG_COUNT
  29 *     - stop_src          TRIG_COUNT      TRIG_EXT        TRIG_NONE
  30 *
  31 *     The channel list must contain at least one channel with no repeated
  32 *     channels.  The scan end count must equal the number of channels in
  33 *     the channel list.
  34 *
  35 *     There is only one external trigger source so only one of start_src,
  36 *     scan_begin_src or stop_src may use TRIG_EXT.
  37 *
  38 * Configuration options:
  39 *   none
  40 *
  41 * Manual configuration of PCI cards is not supported; they are configured
  42 * automatically.
  43 *
  44 * Output range selection - PCI224:
  45 *
  46 *   Output ranges on PCI224 are partly software-selectable and partly
  47 *   hardware-selectable according to jumper LK1.  All channels are set
  48 *   to the same range:
  49 *
  50 *   - LK1 position 1-2 (factory default) corresponds to the following
  51 *     comedi ranges:
  52 *
  53 *       0: [-10V,+10V]; 1: [-5V,+5V]; 2: [-2.5V,+2.5V], 3: [-1.25V,+1.25V],
  54 *       4: [0,+10V],    5: [0,+5V],   6: [0,+2.5V],     7: [0,+1.25V]
  55 *
  56 *   - LK1 position 2-3 corresponds to the following Comedi ranges, using
  57 *     an external voltage reference:
  58 *
  59 *       0: [-Vext,+Vext],
  60 *       1: [0,+Vext]
  61 *
  62 * Output range selection - PCI234:
  63 *
  64 *   Output ranges on PCI234 are hardware-selectable according to jumper
  65 *   LK1 which affects all channels, and jumpers LK2, LK3, LK4 and LK5
  66 *   which affect channels 0, 1, 2 and 3 individually.  LK1 chooses between
  67 *   an internal 5V reference and an external voltage reference (Vext).
  68 *   LK2/3/4/5 choose (per channel) to double the reference or not according
  69 *   to the following table:
  70 *
  71 *     LK1 position   LK2/3/4/5 pos  Comedi range
  72 *     -------------  -------------  --------------
  73 *     2-3 (factory)  1-2 (factory)  0: [-10V,+10V]
  74 *     2-3 (factory)  2-3            1: [-5V,+5V]
  75 *     1-2            1-2 (factory)  2: [-2*Vext,+2*Vext]
  76 *     1-2            2-3            3: [-Vext,+Vext]
  77 *
  78 * Caveats:
  79 *
  80 *   1) All channels on the PCI224 share the same range.  Any change to the
  81 *      range as a result of insn_write or a streaming command will affect
  82 *      the output voltages of all channels, including those not specified
  83 *      by the instruction or command.
  84 *
  85 *   2) For the analog output command,  the first scan may be triggered
  86 *      falsely at the start of acquisition.  This occurs when the DAC scan
  87 *      trigger source is switched from 'none' to 'timer' (scan_begin_src =
  88 *      TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start
  89 *      of acquisition and the trigger source is at logic level 1 at the
  90 *      time of the switch.  This is very likely for TRIG_TIMER.  For
  91 *      TRIG_EXT, it depends on the state of the external line and whether
  92 *      the CR_INVERT flag has been set.  The remaining scans are triggered
  93 *      correctly.
  94 */
  95
  96#include <linux/module.h>
  97#include <linux/interrupt.h>
  98#include <linux/slab.h>
  99#include <linux/comedi/comedi_pci.h>
 100#include <linux/comedi/comedi_8254.h>
 101
 102/*
 103 * PCI224/234 i/o space 1 (PCIBAR2) registers.
 104 */
 105#define PCI224_Z2_BASE	0x14	/* 82C54 counter/timer */
 106#define PCI224_ZCLK_SCE	0x1A	/* Group Z Clock Configuration Register */
 107#define PCI224_ZGAT_SCE	0x1D	/* Group Z Gate Configuration Register */
 108#define PCI224_INT_SCE	0x1E	/* ISR Interrupt source mask register */
 109				/* /Interrupt status */
 110
 111/*
 112 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
 113 */
 114#define PCI224_DACDATA	0x00	/* (w-o) DAC FIFO data. */
 115#define PCI224_SOFTTRIG	0x00	/* (r-o) DAC software scan trigger. */
 116#define PCI224_DACCON	0x02	/* (r/w) DAC status/configuration. */
 117#define PCI224_FIFOSIZ	0x04	/* (w-o) FIFO size for wraparound mode. */
 118#define PCI224_DACCEN	0x06	/* (w-o) DAC channel enable register. */
 119
 120/*
 121 * DACCON values.
 122 */
 123/* (r/w) Scan trigger. */
 124#define PCI224_DACCON_TRIG(x)		(((x) & 0x7) << 0)
 125#define PCI224_DACCON_TRIG_MASK		PCI224_DACCON_TRIG(7)
 126#define PCI224_DACCON_TRIG_NONE		PCI224_DACCON_TRIG(0)	/* none */
 127#define PCI224_DACCON_TRIG_SW		PCI224_DACCON_TRIG(1)	/* soft trig */
 128#define PCI224_DACCON_TRIG_EXTP		PCI224_DACCON_TRIG(2)	/* ext + edge */
 129#define PCI224_DACCON_TRIG_EXTN		PCI224_DACCON_TRIG(3)	/* ext - edge */
 130#define PCI224_DACCON_TRIG_Z2CT0	PCI224_DACCON_TRIG(4)	/* Z2 CT0 out */
 131#define PCI224_DACCON_TRIG_Z2CT1	PCI224_DACCON_TRIG(5)	/* Z2 CT1 out */
 132#define PCI224_DACCON_TRIG_Z2CT2	PCI224_DACCON_TRIG(6)	/* Z2 CT2 out */
 133/* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
 134#define PCI224_DACCON_POLAR(x)		(((x) & 0x1) << 3)
 135#define PCI224_DACCON_POLAR_MASK	PCI224_DACCON_POLAR(1)
 136#define PCI224_DACCON_POLAR_UNI		PCI224_DACCON_POLAR(0)	/* [0,+V] */
 137#define PCI224_DACCON_POLAR_BI		PCI224_DACCON_POLAR(1)	/* [-V,+V] */
 138/* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
 139#define PCI224_DACCON_VREF(x)		(((x) & 0x3) << 4)
 140#define PCI224_DACCON_VREF_MASK		PCI224_DACCON_VREF(3)
 141#define PCI224_DACCON_VREF_1_25		PCI224_DACCON_VREF(0)	/* 1.25V */
 142#define PCI224_DACCON_VREF_2_5		PCI224_DACCON_VREF(1)	/* 2.5V */
 143#define PCI224_DACCON_VREF_5		PCI224_DACCON_VREF(2)	/* 5V */
 144#define PCI224_DACCON_VREF_10		PCI224_DACCON_VREF(3)	/* 10V */
 145/* (r/w) Wraparound mode enable (to play back stored waveform). */
 146#define PCI224_DACCON_FIFOWRAP		BIT(7)
 147/* (r/w) FIFO enable.  It MUST be set! */
 148#define PCI224_DACCON_FIFOENAB		BIT(8)
 149/* (r/w) FIFO interrupt trigger level (most values are not very useful). */
 150#define PCI224_DACCON_FIFOINTR(x)	(((x) & 0x7) << 9)
 151#define PCI224_DACCON_FIFOINTR_MASK	PCI224_DACCON_FIFOINTR(7)
 152#define PCI224_DACCON_FIFOINTR_EMPTY	PCI224_DACCON_FIFOINTR(0) /* empty */
 153#define PCI224_DACCON_FIFOINTR_NEMPTY	PCI224_DACCON_FIFOINTR(1) /* !empty */
 154#define PCI224_DACCON_FIFOINTR_NHALF	PCI224_DACCON_FIFOINTR(2) /* !half */
 155#define PCI224_DACCON_FIFOINTR_HALF	PCI224_DACCON_FIFOINTR(3) /* half */
 156#define PCI224_DACCON_FIFOINTR_NFULL	PCI224_DACCON_FIFOINTR(4) /* !full */
 157#define PCI224_DACCON_FIFOINTR_FULL	PCI224_DACCON_FIFOINTR(5) /* full */
 158/* (r-o) FIFO fill level. */
 159#define PCI224_DACCON_FIFOFL(x)		(((x) & 0x7) << 12)
 160#define PCI224_DACCON_FIFOFL_MASK	PCI224_DACCON_FIFOFL(7)
 161#define PCI224_DACCON_FIFOFL_EMPTY	PCI224_DACCON_FIFOFL(1)	/* 0 */
 162#define PCI224_DACCON_FIFOFL_ONETOHALF	PCI224_DACCON_FIFOFL(0)	/* 1-2048 */
 163#define PCI224_DACCON_FIFOFL_HALFTOFULL	PCI224_DACCON_FIFOFL(4)	/* 2049-4095 */
 164#define PCI224_DACCON_FIFOFL_FULL	PCI224_DACCON_FIFOFL(6)	/* 4096 */
 165/* (r-o) DAC busy flag. */
 166#define PCI224_DACCON_BUSY		BIT(15)
 167/* (w-o) FIFO reset. */
 168#define PCI224_DACCON_FIFORESET		BIT(12)
 169/* (w-o) Global reset (not sure what it does). */
 170#define PCI224_DACCON_GLOBALRESET	BIT(13)
 171
 172/*
 173 * DAC FIFO size.
 174 */
 175#define PCI224_FIFO_SIZE	4096
 176
 177/*
 178 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
 179 * The maximum room available depends on the reported fill level and how much
 180 * has been written!
 181 */
 182#define PCI224_FIFO_ROOM_EMPTY		PCI224_FIFO_SIZE
 183#define PCI224_FIFO_ROOM_ONETOHALF	(PCI224_FIFO_SIZE / 2)
 184#define PCI224_FIFO_ROOM_HALFTOFULL	1
 185#define PCI224_FIFO_ROOM_FULL		0
 186
 187/*
 188 * Counter/timer clock input configuration sources.
 189 */
 190#define CLK_CLK		0	/* reserved (channel-specific clock) */
 191#define CLK_10MHZ	1	/* internal 10 MHz clock */
 192#define CLK_1MHZ	2	/* internal 1 MHz clock */
 193#define CLK_100KHZ	3	/* internal 100 kHz clock */
 194#define CLK_10KHZ	4	/* internal 10 kHz clock */
 195#define CLK_1KHZ	5	/* internal 1 kHz clock */
 196#define CLK_OUTNM1	6	/* output of channel-1 modulo total */
 197#define CLK_EXT		7	/* external clock */
 198
 199static unsigned int pci224_clk_config(unsigned int chan, unsigned int src)
 200{
 201	return ((chan & 3) << 3) | (src & 7);
 202}
 203
 204/*
 205 * Counter/timer gate input configuration sources.
 206 */
 207#define GAT_VCC		0	/* VCC (i.e. enabled) */
 208#define GAT_GND		1	/* GND (i.e. disabled) */
 209#define GAT_EXT		2	/* reserved (external gate input) */
 210#define GAT_NOUTNM2	3	/* inverted output of channel-2 modulo total */
 211
 212static unsigned int pci224_gat_config(unsigned int chan, unsigned int src)
 213{
 214	return ((chan & 3) << 3) | (src & 7);
 215}
 216
 217/*
 218 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
 219 *
 220 *              Channel's       Channel's
 221 *              clock input     gate input
 222 * Channel      CLK_OUTNM1      GAT_NOUTNM2
 223 * -------      ----------      -----------
 224 * Z2-CT0       Z2-CT2-OUT      /Z2-CT1-OUT
 225 * Z2-CT1       Z2-CT0-OUT      /Z2-CT2-OUT
 226 * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
 227 */
 228
 229/*
 230 * Interrupt enable/status bits
 231 */
 232#define PCI224_INTR_EXT		0x01	/* rising edge on external input */
 233#define PCI224_INTR_DAC		0x04	/* DAC (FIFO) interrupt */
 234#define PCI224_INTR_Z2CT1	0x20	/* rising edge on Z2-CT1 output */
 235
 236#define PCI224_INTR_EDGE_BITS	(PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
 237#define PCI224_INTR_LEVEL_BITS	PCI224_INTR_DACFIFO
 238
 239/*
 240 * Handy macros.
 241 */
 242
 243/* Combine old and new bits. */
 244#define COMBINE(old, new, mask)	(((old) & ~(mask)) | ((new) & (mask)))
 245
 246/* Current CPU.  XXX should this be hard_smp_processor_id()? */
 247#define THISCPU		smp_processor_id()
 248
 249/* State bits for use with atomic bit operations. */
 250#define AO_CMD_STARTED	0
 251
 252/*
 253 * Range tables.
 254 */
 255
 256/*
 257 * The ranges for PCI224.
 258 *
 259 * These are partly hardware-selectable by jumper LK1 and partly
 260 * software-selectable.
 261 *
 262 * All channels share the same hardware range.
 263 */
 264static const struct comedi_lrange range_pci224 = {
 265	10, {
 266		/* jumper LK1 in position 1-2 (factory default) */
 267		BIP_RANGE(10),
 268		BIP_RANGE(5),
 269		BIP_RANGE(2.5),
 270		BIP_RANGE(1.25),
 271		UNI_RANGE(10),
 272		UNI_RANGE(5),
 273		UNI_RANGE(2.5),
 274		UNI_RANGE(1.25),
 275		/* jumper LK1 in position 2-3 */
 276		RANGE_ext(-1, 1),	/* bipolar [-Vext,+Vext] */
 277		RANGE_ext(0, 1),	/* unipolar [0,+Vext] */
 278	}
 279};
 280
 281static const unsigned short hwrange_pci224[10] = {
 282	/* jumper LK1 in position 1-2 (factory default) */
 283	PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
 284	PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
 285	PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
 286	PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
 287	PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
 288	PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
 289	PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
 290	PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
 291	/* jumper LK1 in position 2-3 */
 292	PCI224_DACCON_POLAR_BI,
 293	PCI224_DACCON_POLAR_UNI,
 294};
 295
 296/* Used to check all channels set to the same range on PCI224. */
 297static const unsigned char range_check_pci224[10] = {
 298	0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 299};
 300
 301/*
 302 * The ranges for PCI234.
 303 *
 304 * These are all hardware-selectable by jumper LK1 affecting all channels,
 305 * and jumpers LK2, LK3, LK4 and LK5 affecting channels 0, 1, 2 and 3
 306 * individually.
 307 */
 308static const struct comedi_lrange range_pci234 = {
 309	4, {
 310		/* LK1: 1-2 (fact def), LK2/3/4/5: 2-3 (fac def) */
 311		BIP_RANGE(10),
 312		/* LK1: 1-2 (fact def), LK2/3/4/5: 1-2 */
 313		BIP_RANGE(5),
 314		/* LK1: 2-3, LK2/3/4/5: 2-3 (fac def) */
 315		RANGE_ext(-2, 2),	/* bipolar [-2*Vext,+2*Vext] */
 316		/* LK1: 2-3, LK2/3/4/5: 1-2 */
 317		RANGE_ext(-1, 1),	/* bipolar [-Vext,+Vext] */
 318	}
 319};
 320
 321/* N.B. PCI234 ignores the polarity bit, but software uses it. */
 322static const unsigned short hwrange_pci234[4] = {
 323	PCI224_DACCON_POLAR_BI,
 324	PCI224_DACCON_POLAR_BI,
 325	PCI224_DACCON_POLAR_BI,
 326	PCI224_DACCON_POLAR_BI,
 327};
 328
 329/* Used to check all channels use same LK1 setting on PCI234. */
 330static const unsigned char range_check_pci234[4] = {
 331	0, 0, 1, 1,
 332};
 333
 334/*
 335 * Board descriptions.
 336 */
 337
 338enum pci224_model { pci224_model, pci234_model };
 339
 340struct pci224_board {
 341	const char *name;
 342	unsigned int ao_chans;
 343	unsigned int ao_bits;
 344	const struct comedi_lrange *ao_range;
 345	const unsigned short *ao_hwrange;
 346	const unsigned char *ao_range_check;
 347};
 348
 349static const struct pci224_board pci224_boards[] = {
 350	[pci224_model] = {
 351		.name		= "pci224",
 352		.ao_chans	= 16,
 353		.ao_bits	= 12,
 354		.ao_range	= &range_pci224,
 355		.ao_hwrange	= &hwrange_pci224[0],
 356		.ao_range_check	= &range_check_pci224[0],
 357	},
 358	[pci234_model] = {
 359		.name		= "pci234",
 360		.ao_chans	= 4,
 361		.ao_bits	= 16,
 362		.ao_range	= &range_pci234,
 363		.ao_hwrange	= &hwrange_pci234[0],
 364		.ao_range_check	= &range_check_pci234[0],
 365	},
 366};
 367
 368struct pci224_private {
 369	unsigned long iobase1;
 370	unsigned long state;
 371	spinlock_t ao_spinlock;	/* spinlock for AO command handling */
 372	unsigned short *ao_scan_vals;
 373	unsigned char *ao_scan_order;
 374	int intr_cpuid;
 375	short intr_running;
 376	unsigned short daccon;
 377	unsigned short ao_enab;	/* max 16 channels so 'short' will do */
 378	unsigned char intsce;
 379};
 380
 381/*
 382 * Called from the 'insn_write' function to perform a single write.
 383 */
 384static void
 385pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
 386		   unsigned int data)
 387{
 388	const struct pci224_board *board = dev->board_ptr;
 389	struct pci224_private *devpriv = dev->private;
 390	unsigned short mangled;
 391
 392	/* Enable the channel. */
 393	outw(1 << chan, dev->iobase + PCI224_DACCEN);
 394	/* Set range and reset FIFO. */
 395	devpriv->daccon = COMBINE(devpriv->daccon, board->ao_hwrange[range],
 396				  PCI224_DACCON_POLAR_MASK |
 397				  PCI224_DACCON_VREF_MASK);
 398	outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 399	     dev->iobase + PCI224_DACCON);
 400	/*
 401	 * Mangle the data.  The hardware expects:
 402	 * - bipolar: 16-bit 2's complement
 403	 * - unipolar: 16-bit unsigned
 404	 */
 405	mangled = (unsigned short)data << (16 - board->ao_bits);
 406	if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
 407	    PCI224_DACCON_POLAR_BI) {
 408		mangled ^= 0x8000;
 409	}
 410	/* Write mangled data to the FIFO. */
 411	outw(mangled, dev->iobase + PCI224_DACDATA);
 412	/* Trigger the conversion. */
 413	inw(dev->iobase + PCI224_SOFTTRIG);
 414}
 415
 416static int pci224_ao_insn_write(struct comedi_device *dev,
 417				struct comedi_subdevice *s,
 418				struct comedi_insn *insn,
 419				unsigned int *data)
 420{
 421	unsigned int chan = CR_CHAN(insn->chanspec);
 422	unsigned int range = CR_RANGE(insn->chanspec);
 423	unsigned int val = s->readback[chan];
 424	int i;
 425
 426	for (i = 0; i < insn->n; i++) {
 427		val = data[i];
 428		pci224_ao_set_data(dev, chan, range, val);
 429	}
 430	s->readback[chan] = val;
 431
 432	return insn->n;
 433}
 434
 435/*
 436 * Kills a command running on the AO subdevice.
 437 */
 438static void pci224_ao_stop(struct comedi_device *dev,
 439			   struct comedi_subdevice *s)
 440{
 441	struct pci224_private *devpriv = dev->private;
 442	unsigned long flags;
 443
 444	if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
 445		return;
 446
 447	spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 448	/* Kill the interrupts. */
 449	devpriv->intsce = 0;
 450	outb(0, devpriv->iobase1 + PCI224_INT_SCE);
 451	/*
 452	 * Interrupt routine may or may not be running.  We may or may not
 453	 * have been called from the interrupt routine (directly or
 454	 * indirectly via a comedi_events() callback routine).  It's highly
 455	 * unlikely that we've been called from some other interrupt routine
 456	 * but who knows what strange things coders get up to!
 457	 *
 458	 * If the interrupt routine is currently running, wait for it to
 459	 * finish, unless we appear to have been called via the interrupt
 460	 * routine.
 461	 */
 462	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
 463		spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 464		spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 465	}
 466	spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 467	/* Reconfigure DAC for insn_write usage. */
 468	outw(0, dev->iobase + PCI224_DACCEN);	/* Disable channels. */
 469	devpriv->daccon =
 470	     COMBINE(devpriv->daccon,
 471		     PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
 472		     PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
 473	outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 474	     dev->iobase + PCI224_DACCON);
 475}
 476
 477/*
 478 * Handles start of acquisition for the AO subdevice.
 479 */
 480static void pci224_ao_start(struct comedi_device *dev,
 481			    struct comedi_subdevice *s)
 482{
 483	struct pci224_private *devpriv = dev->private;
 484	struct comedi_cmd *cmd = &s->async->cmd;
 485	unsigned long flags;
 486
 487	set_bit(AO_CMD_STARTED, &devpriv->state);
 488
 489	/* Enable interrupts. */
 490	spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 491	if (cmd->stop_src == TRIG_EXT)
 492		devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
 493	else
 494		devpriv->intsce = PCI224_INTR_DAC;
 495
 496	outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
 497	spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 498}
 499
 500/*
 501 * Handles interrupts from the DAC FIFO.
 502 */
 503static void pci224_ao_handle_fifo(struct comedi_device *dev,
 504				  struct comedi_subdevice *s)
 505{
 506	struct pci224_private *devpriv = dev->private;
 507	struct comedi_cmd *cmd = &s->async->cmd;
 508	unsigned int num_scans = comedi_nscans_left(s, 0);
 509	unsigned int room;
 510	unsigned short dacstat;
 511	unsigned int i, n;
 512
 513	/* Determine how much room is in the FIFO (in samples). */
 514	dacstat = inw(dev->iobase + PCI224_DACCON);
 515	switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
 516	case PCI224_DACCON_FIFOFL_EMPTY:
 517		room = PCI224_FIFO_ROOM_EMPTY;
 518		if (cmd->stop_src == TRIG_COUNT &&
 519		    s->async->scans_done >= cmd->stop_arg) {
 520			/* FIFO empty at end of counted acquisition. */
 521			s->async->events |= COMEDI_CB_EOA;
 522			comedi_handle_events(dev, s);
 523			return;
 524		}
 525		break;
 526	case PCI224_DACCON_FIFOFL_ONETOHALF:
 527		room = PCI224_FIFO_ROOM_ONETOHALF;
 528		break;
 529	case PCI224_DACCON_FIFOFL_HALFTOFULL:
 530		room = PCI224_FIFO_ROOM_HALFTOFULL;
 531		break;
 532	default:
 533		room = PCI224_FIFO_ROOM_FULL;
 534		break;
 535	}
 536	if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
 537		/* FIFO is less than half-full. */
 538		if (num_scans == 0) {
 539			/* Nothing left to put in the FIFO. */
 540			dev_err(dev->class_dev, "AO buffer underrun\n");
 541			s->async->events |= COMEDI_CB_OVERFLOW;
 542		}
 543	}
 544	/* Determine how many new scans can be put in the FIFO. */
 545	room /= cmd->chanlist_len;
 546
 547	/* Determine how many scans to process. */
 548	if (num_scans > room)
 549		num_scans = room;
 550
 551	/* Process scans. */
 552	for (n = 0; n < num_scans; n++) {
 553		comedi_buf_read_samples(s, &devpriv->ao_scan_vals[0],
 554					cmd->chanlist_len);
 555		for (i = 0; i < cmd->chanlist_len; i++) {
 556			outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
 557			     dev->iobase + PCI224_DACDATA);
 558		}
 559	}
 560	if (cmd->stop_src == TRIG_COUNT &&
 561	    s->async->scans_done >= cmd->stop_arg) {
 562		/*
 563		 * Change FIFO interrupt trigger level to wait
 564		 * until FIFO is empty.
 565		 */
 566		devpriv->daccon = COMBINE(devpriv->daccon,
 567					  PCI224_DACCON_FIFOINTR_EMPTY,
 568					  PCI224_DACCON_FIFOINTR_MASK);
 569		outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 570	}
 571	if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
 572	    PCI224_DACCON_TRIG_NONE) {
 573		unsigned short trig;
 574
 575		/*
 576		 * This is the initial DAC FIFO interrupt at the
 577		 * start of the acquisition.  The DAC's scan trigger
 578		 * has been set to 'none' up until now.
 579		 *
 580		 * Now that data has been written to the FIFO, the
 581		 * DAC's scan trigger source can be set to the
 582		 * correct value.
 583		 *
 584		 * BUG: The first scan will be triggered immediately
 585		 * if the scan trigger source is at logic level 1.
 586		 */
 587		if (cmd->scan_begin_src == TRIG_TIMER) {
 588			trig = PCI224_DACCON_TRIG_Z2CT0;
 589		} else {
 590			/* cmd->scan_begin_src == TRIG_EXT */
 591			if (cmd->scan_begin_arg & CR_INVERT)
 592				trig = PCI224_DACCON_TRIG_EXTN;
 593			else
 594				trig = PCI224_DACCON_TRIG_EXTP;
 595		}
 596		devpriv->daccon =
 597		    COMBINE(devpriv->daccon, trig, PCI224_DACCON_TRIG_MASK);
 598		outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 599	}
 600
 601	comedi_handle_events(dev, s);
 602}
 603
 604static int pci224_ao_inttrig_start(struct comedi_device *dev,
 605				   struct comedi_subdevice *s,
 606				   unsigned int trig_num)
 607{
 608	struct comedi_cmd *cmd = &s->async->cmd;
 609
 610	if (trig_num != cmd->start_arg)
 611		return -EINVAL;
 612
 613	s->async->inttrig = NULL;
 614	pci224_ao_start(dev, s);
 615
 616	return 1;
 617}
 618
 619static int pci224_ao_check_chanlist(struct comedi_device *dev,
 620				    struct comedi_subdevice *s,
 621				    struct comedi_cmd *cmd)
 622{
 623	const struct pci224_board *board = dev->board_ptr;
 624	unsigned int range_check_0;
 625	unsigned int chan_mask = 0;
 626	int i;
 627
 628	range_check_0 = board->ao_range_check[CR_RANGE(cmd->chanlist[0])];
 629	for (i = 0; i < cmd->chanlist_len; i++) {
 630		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 631
 632		if (chan_mask & (1 << chan)) {
 633			dev_dbg(dev->class_dev,
 634				"%s: entries in chanlist must contain no duplicate channels\n",
 635				__func__);
 636			return -EINVAL;
 637		}
 638		chan_mask |= 1 << chan;
 639
 640		if (board->ao_range_check[CR_RANGE(cmd->chanlist[i])] !=
 641		    range_check_0) {
 642			dev_dbg(dev->class_dev,
 643				"%s: entries in chanlist have incompatible ranges\n",
 644				__func__);
 645			return -EINVAL;
 646		}
 647	}
 648
 649	return 0;
 650}
 651
 652#define MAX_SCAN_PERIOD		0xFFFFFFFFU
 653#define MIN_SCAN_PERIOD		2500
 654#define CONVERT_PERIOD		625
 655
 656/*
 657 * 'do_cmdtest' function for AO subdevice.
 658 */
 659static int
 660pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 661		  struct comedi_cmd *cmd)
 662{
 663	int err = 0;
 664	unsigned int arg;
 665
 666	/* Step 1 : check if triggers are trivially valid */
 667
 668	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
 669	err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 670					TRIG_EXT | TRIG_TIMER);
 671	err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 672	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 673	err |= comedi_check_trigger_src(&cmd->stop_src,
 674					TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 675
 676	if (err)
 677		return 1;
 678
 679	/* Step 2a : make sure trigger sources are unique */
 680
 681	err |= comedi_check_trigger_is_unique(cmd->start_src);
 682	err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 683	err |= comedi_check_trigger_is_unique(cmd->stop_src);
 684
 685	/* Step 2b : and mutually compatible */
 686
 687	/*
 688	 * There's only one external trigger signal (which makes these
 689	 * tests easier).  Only one thing can use it.
 690	 */
 691	arg = 0;
 692	if (cmd->start_src & TRIG_EXT)
 693		arg++;
 694	if (cmd->scan_begin_src & TRIG_EXT)
 695		arg++;
 696	if (cmd->stop_src & TRIG_EXT)
 697		arg++;
 698	if (arg > 1)
 699		err |= -EINVAL;
 700
 701	if (err)
 702		return 2;
 703
 704	/* Step 3: check if arguments are trivially valid */
 705
 706	switch (cmd->start_src) {
 707	case TRIG_INT:
 708		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 709		break;
 710	case TRIG_EXT:
 711		/* Force to external trigger 0. */
 712		if (cmd->start_arg & ~CR_FLAGS_MASK) {
 713			cmd->start_arg =
 714			    COMBINE(cmd->start_arg, 0, ~CR_FLAGS_MASK);
 715			err |= -EINVAL;
 716		}
 717		/* The only flag allowed is CR_EDGE, which is ignored. */
 718		if (cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) {
 719			cmd->start_arg = COMBINE(cmd->start_arg, 0,
 720						 CR_FLAGS_MASK & ~CR_EDGE);
 721			err |= -EINVAL;
 722		}
 723		break;
 724	}
 725
 726	switch (cmd->scan_begin_src) {
 727	case TRIG_TIMER:
 728		err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
 729						    MAX_SCAN_PERIOD);
 730
 731		arg = cmd->chanlist_len * CONVERT_PERIOD;
 732		if (arg < MIN_SCAN_PERIOD)
 733			arg = MIN_SCAN_PERIOD;
 734		err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 735		break;
 736	case TRIG_EXT:
 737		/* Force to external trigger 0. */
 738		if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
 739			cmd->scan_begin_arg =
 740			    COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK);
 741			err |= -EINVAL;
 742		}
 743		/* Only allow flags CR_EDGE and CR_INVERT.  Ignore CR_EDGE. */
 744		if (cmd->scan_begin_arg & CR_FLAGS_MASK &
 745		    ~(CR_EDGE | CR_INVERT)) {
 746			cmd->scan_begin_arg =
 747			    COMBINE(cmd->scan_begin_arg, 0,
 748				    CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
 749			err |= -EINVAL;
 750		}
 751		break;
 752	}
 753
 754	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 755	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 756					   cmd->chanlist_len);
 757
 758	switch (cmd->stop_src) {
 759	case TRIG_COUNT:
 760		err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 761		break;
 762	case TRIG_EXT:
 763		/* Force to external trigger 0. */
 764		if (cmd->stop_arg & ~CR_FLAGS_MASK) {
 765			cmd->stop_arg =
 766			    COMBINE(cmd->stop_arg, 0, ~CR_FLAGS_MASK);
 767			err |= -EINVAL;
 768		}
 769		/* The only flag allowed is CR_EDGE, which is ignored. */
 770		if (cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) {
 771			cmd->stop_arg =
 772			    COMBINE(cmd->stop_arg, 0, CR_FLAGS_MASK & ~CR_EDGE);
 773		}
 774		break;
 775	case TRIG_NONE:
 776		err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 777		break;
 778	}
 779
 780	if (err)
 781		return 3;
 782
 783	/* Step 4: fix up any arguments. */
 784
 785	if (cmd->scan_begin_src == TRIG_TIMER) {
 786		arg = cmd->scan_begin_arg;
 787		/* Use two timers. */
 788		comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 789		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 790	}
 791
 792	if (err)
 793		return 4;
 794
 795	/* Step 5: check channel list if it exists */
 796	if (cmd->chanlist && cmd->chanlist_len > 0)
 797		err |= pci224_ao_check_chanlist(dev, s, cmd);
 798
 799	if (err)
 800		return 5;
 801
 802	return 0;
 803}
 804
 805static void pci224_ao_start_pacer(struct comedi_device *dev,
 806				  struct comedi_subdevice *s)
 807{
 808	struct pci224_private *devpriv = dev->private;
 809
 810	/*
 811	 * The output of timer Z2-0 will be used as the scan trigger
 812	 * source.
 813	 */
 814	/* Make sure Z2-0 is gated on.  */
 815	outb(pci224_gat_config(0, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
 816	/* Cascading with Z2-2. */
 817	/* Make sure Z2-2 is gated on.  */
 818	outb(pci224_gat_config(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
 819	/* Z2-2 needs 10 MHz clock. */
 820	outb(pci224_clk_config(2, CLK_10MHZ),
 821	     devpriv->iobase1 + PCI224_ZCLK_SCE);
 822	/* Z2-0 is clocked from Z2-2's output. */
 823	outb(pci224_clk_config(0, CLK_OUTNM1),
 824	     devpriv->iobase1 + PCI224_ZCLK_SCE);
 825
 826	comedi_8254_pacer_enable(dev->pacer, 2, 0, false);
 827}
 828
 829static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 830{
 831	const struct pci224_board *board = dev->board_ptr;
 832	struct pci224_private *devpriv = dev->private;
 833	struct comedi_cmd *cmd = &s->async->cmd;
 834	int range;
 835	unsigned int i, j;
 836	unsigned int ch;
 837	unsigned int rank;
 838	unsigned long flags;
 839
 840	/* Cannot handle null/empty chanlist. */
 841	if (!cmd->chanlist || cmd->chanlist_len == 0)
 842		return -EINVAL;
 843
 844	/* Determine which channels are enabled and their load order.  */
 845	devpriv->ao_enab = 0;
 846
 847	for (i = 0; i < cmd->chanlist_len; i++) {
 848		ch = CR_CHAN(cmd->chanlist[i]);
 849		devpriv->ao_enab |= 1U << ch;
 850		rank = 0;
 851		for (j = 0; j < cmd->chanlist_len; j++) {
 852			if (CR_CHAN(cmd->chanlist[j]) < ch)
 853				rank++;
 854		}
 855		devpriv->ao_scan_order[rank] = i;
 856	}
 857
 858	/* Set enabled channels. */
 859	outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
 860
 861	/* Determine range and polarity.  All channels the same.  */
 862	range = CR_RANGE(cmd->chanlist[0]);
 863
 864	/*
 865	 * Set DAC range and polarity.
 866	 * Set DAC scan trigger source to 'none'.
 867	 * Set DAC FIFO interrupt trigger level to 'not half full'.
 868	 * Reset DAC FIFO.
 869	 *
 870	 * N.B. DAC FIFO interrupts are currently disabled.
 871	 */
 872	devpriv->daccon =
 873	    COMBINE(devpriv->daccon,
 874		    board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE |
 875		    PCI224_DACCON_FIFOINTR_NHALF,
 876		    PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
 877		    PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
 878	outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 879	     dev->iobase + PCI224_DACCON);
 880
 881	if (cmd->scan_begin_src == TRIG_TIMER) {
 882		comedi_8254_update_divisors(dev->pacer);
 883		pci224_ao_start_pacer(dev, s);
 884	}
 885
 886	spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 887	if (cmd->start_src == TRIG_INT) {
 888		s->async->inttrig = pci224_ao_inttrig_start;
 889	} else {	/* TRIG_EXT */
 890		/* Enable external interrupt trigger to start acquisition. */
 891		devpriv->intsce |= PCI224_INTR_EXT;
 892		outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
 893	}
 894	spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 895
 896	return 0;
 897}
 898
 899/*
 900 * 'cancel' function for AO subdevice.
 901 */
 902static int pci224_ao_cancel(struct comedi_device *dev,
 903			    struct comedi_subdevice *s)
 904{
 905	pci224_ao_stop(dev, s);
 906	return 0;
 907}
 908
 909/*
 910 * 'munge' data for AO command.
 911 */
 912static void
 913pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 914		void *data, unsigned int num_bytes, unsigned int chan_index)
 915{
 916	const struct pci224_board *board = dev->board_ptr;
 917	struct comedi_cmd *cmd = &s->async->cmd;
 918	unsigned short *array = data;
 919	unsigned int length = num_bytes / sizeof(*array);
 920	unsigned int offset;
 921	unsigned int shift;
 922	unsigned int i;
 923
 924	/* The hardware expects 16-bit numbers. */
 925	shift = 16 - board->ao_bits;
 926	/* Channels will be all bipolar or all unipolar. */
 927	if ((board->ao_hwrange[CR_RANGE(cmd->chanlist[0])] &
 928	     PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
 929		/* Unipolar */
 930		offset = 0;
 931	} else {
 932		/* Bipolar */
 933		offset = 32768;
 934	}
 935	/* Munge the data. */
 936	for (i = 0; i < length; i++)
 937		array[i] = (array[i] << shift) - offset;
 938}
 939
 940/*
 941 * Interrupt handler.
 942 */
 943static irqreturn_t pci224_interrupt(int irq, void *d)
 944{
 945	struct comedi_device *dev = d;
 946	struct pci224_private *devpriv = dev->private;
 947	struct comedi_subdevice *s = dev->write_subdev;
 948	struct comedi_cmd *cmd;
 949	unsigned char intstat, valid_intstat;
 950	unsigned char curenab;
 951	int retval = 0;
 952	unsigned long flags;
 953
 954	intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
 955	if (intstat) {
 956		retval = 1;
 957		spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 958		valid_intstat = devpriv->intsce & intstat;
 959		/* Temporarily disable interrupt sources. */
 960		curenab = devpriv->intsce & ~intstat;
 961		outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
 962		devpriv->intr_running = 1;
 963		devpriv->intr_cpuid = THISCPU;
 964		spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 965		if (valid_intstat) {
 966			cmd = &s->async->cmd;
 967			if (valid_intstat & PCI224_INTR_EXT) {
 968				devpriv->intsce &= ~PCI224_INTR_EXT;
 969				if (cmd->start_src == TRIG_EXT)
 970					pci224_ao_start(dev, s);
 971				else if (cmd->stop_src == TRIG_EXT)
 972					pci224_ao_stop(dev, s);
 973			}
 974			if (valid_intstat & PCI224_INTR_DAC)
 975				pci224_ao_handle_fifo(dev, s);
 976		}
 977		/* Reenable interrupt sources. */
 978		spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 979		if (curenab != devpriv->intsce) {
 980			outb(devpriv->intsce,
 981			     devpriv->iobase1 + PCI224_INT_SCE);
 982		}
 983		devpriv->intr_running = 0;
 984		spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 985	}
 986	return IRQ_RETVAL(retval);
 987}
 988
 989static int
 990pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
 991{
 992	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
 993	const struct pci224_board *board = NULL;
 994	struct pci224_private *devpriv;
 995	struct comedi_subdevice *s;
 996	unsigned int irq;
 997	int ret;
 998
 999	if (context_model < ARRAY_SIZE(pci224_boards))
1000		board = &pci224_boards[context_model];
1001	if (!board || !board->name) {
1002		dev_err(dev->class_dev,
1003			"amplc_pci224: BUG! cannot determine board type!\n");
1004		return -EINVAL;
1005	}
1006	dev->board_ptr = board;
1007	dev->board_name = board->name;
1008
1009	dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n",
1010		 pci_name(pci_dev), dev->board_name);
1011
1012	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1013	if (!devpriv)
1014		return -ENOMEM;
1015
1016	ret = comedi_pci_enable(dev);
1017	if (ret)
1018		return ret;
1019
1020	spin_lock_init(&devpriv->ao_spinlock);
1021
1022	devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1023	dev->iobase = pci_resource_start(pci_dev, 3);
1024	irq = pci_dev->irq;
1025
1026	/* Allocate buffer to hold values for AO channel scan. */
1027	devpriv->ao_scan_vals = kmalloc_array(board->ao_chans,
1028					      sizeof(devpriv->ao_scan_vals[0]),
1029					      GFP_KERNEL);
1030	if (!devpriv->ao_scan_vals)
1031		return -ENOMEM;
1032
1033	/* Allocate buffer to hold AO channel scan order. */
1034	devpriv->ao_scan_order =
1035				kmalloc_array(board->ao_chans,
1036					      sizeof(devpriv->ao_scan_order[0]),
1037					      GFP_KERNEL);
1038	if (!devpriv->ao_scan_order)
1039		return -ENOMEM;
1040
1041	/* Disable interrupt sources. */
1042	devpriv->intsce = 0;
1043	outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1044
1045	/* Initialize the DAC hardware. */
1046	outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1047	outw(0, dev->iobase + PCI224_DACCEN);
1048	outw(0, dev->iobase + PCI224_FIFOSIZ);
1049	devpriv->daccon = PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1050			  PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY;
1051	outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1052	     dev->iobase + PCI224_DACCON);
1053
1054	dev->pacer = comedi_8254_io_alloc(devpriv->iobase1 + PCI224_Z2_BASE,
1055					  I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1056	if (IS_ERR(dev->pacer))
1057		return PTR_ERR(dev->pacer);
1058
1059	ret = comedi_alloc_subdevices(dev, 1);
1060	if (ret)
1061		return ret;
1062
1063	s = &dev->subdevices[0];
1064	/* Analog output subdevice. */
1065	s->type = COMEDI_SUBD_AO;
1066	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1067	s->n_chan = board->ao_chans;
1068	s->maxdata = (1 << board->ao_bits) - 1;
1069	s->range_table = board->ao_range;
1070	s->insn_write = pci224_ao_insn_write;
1071	s->len_chanlist = s->n_chan;
1072	dev->write_subdev = s;
1073	s->do_cmd = pci224_ao_cmd;
1074	s->do_cmdtest = pci224_ao_cmdtest;
1075	s->cancel = pci224_ao_cancel;
1076	s->munge = pci224_ao_munge;
1077
1078	ret = comedi_alloc_subdev_readback(s);
1079	if (ret)
1080		return ret;
1081
1082	if (irq) {
1083		ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1084				  dev->board_name, dev);
1085		if (ret < 0) {
1086			dev_err(dev->class_dev,
1087				"error! unable to allocate irq %u\n", irq);
1088			return ret;
1089		}
1090		dev->irq = irq;
1091	}
1092
1093	return 0;
1094}
1095
1096static void pci224_detach(struct comedi_device *dev)
1097{
1098	struct pci224_private *devpriv = dev->private;
1099
1100	comedi_pci_detach(dev);
1101	if (devpriv) {
1102		kfree(devpriv->ao_scan_vals);
1103		kfree(devpriv->ao_scan_order);
1104	}
1105}
1106
1107static struct comedi_driver amplc_pci224_driver = {
1108	.driver_name	= "amplc_pci224",
1109	.module		= THIS_MODULE,
1110	.detach		= pci224_detach,
1111	.auto_attach	= pci224_auto_attach,
1112	.board_name	= &pci224_boards[0].name,
1113	.offset		= sizeof(struct pci224_board),
1114	.num_names	= ARRAY_SIZE(pci224_boards),
1115};
1116
1117static int amplc_pci224_pci_probe(struct pci_dev *dev,
1118				  const struct pci_device_id *id)
1119{
1120	return comedi_pci_auto_config(dev, &amplc_pci224_driver,
1121				      id->driver_data);
1122}
1123
1124static const struct pci_device_id amplc_pci224_pci_table[] = {
1125	{ PCI_VDEVICE(AMPLICON, 0x0007), pci224_model },
1126	{ PCI_VDEVICE(AMPLICON, 0x0008), pci234_model },
1127	{ 0 }
1128};
1129MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1130
1131static struct pci_driver amplc_pci224_pci_driver = {
1132	.name		= "amplc_pci224",
1133	.id_table	= amplc_pci224_pci_table,
1134	.probe		= amplc_pci224_pci_probe,
1135	.remove		= comedi_pci_auto_unconfig,
1136};
1137module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1138
1139MODULE_AUTHOR("Comedi https://www.comedi.org");
1140MODULE_DESCRIPTION("Comedi driver for Amplicon PCI224 and PCI234 AO boards");
1141MODULE_LICENSE("GPL");
~/ Read-only file preview.