Staging: comedi: Remove lsampl_t and sampl_t typedefs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / drivers / amplc_pci224.c
CommitLineData
ea1aeae4
IA
1/*
2 comedi/drivers/amplc_pci224.c
3 Driver for Amplicon PCI224 and PCI234 AO boards.
4
5 Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
6
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24*/
25/*
26Driver: amplc_pci224
27Description: Amplicon PCI224, PCI234
28Author: Ian Abbott <abbotti@mev.co.uk>
29Devices: [Amplicon] PCI224 (amplc_pci224 or pci224),
30 PCI234 (amplc_pci224 or pci234)
31Updated: Wed, 22 Oct 2008 12:25:08 +0100
32Status: works, but see caveats
33
34Supports:
35
36 - ao_insn read/write
37 - ao_do_cmd mode with the following sources:
38
39 - start_src TRIG_INT TRIG_EXT
40 - scan_begin_src TRIG_TIMER TRIG_EXT
41 - convert_src TRIG_NOW
42 - scan_end_src TRIG_COUNT
43 - stop_src TRIG_COUNT TRIG_EXT TRIG_NONE
44
45 The channel list must contain at least one channel with no repeated
46 channels. The scan end count must equal the number of channels in
47 the channel list.
48
49 There is only one external trigger source so only one of start_src,
50 scan_begin_src or stop_src may use TRIG_EXT.
51
52Configuration options - PCI224:
53 [0] - PCI bus of device (optional).
54 [1] - PCI slot of device (optional).
55 If bus/slot is not specified, the first available PCI device
56 will be used.
57 [2] - Select available ranges according to jumper LK1. All channels
58 are set to the same range:
59 0=Jumper position 1-2 (factory default), 4 software-selectable
60 internal voltage references, giving 4 bipolar and 4 unipolar
61 ranges:
62 [-10V,+10V], [-5V,+5V], [-2.5V,+2.5V], [-1.25V,+1.25V],
63 [0,+10V], [0,+5V], [0,+2.5V], [0,1.25V].
64 1=Jumper position 2-3, 1 external voltage reference, giving
65 1 bipolar and 1 unipolar range:
66 [-Vext,+Vext], [0,+Vext].
67
68Configuration options - PCI234:
69 [0] - PCI bus of device (optional).
70 [1] - PCI slot of device (optional).
71 If bus/slot is not specified, the first available PCI device
72 will be used.
73 [2] - Select internal or external voltage reference according to
74 jumper LK1. This affects all channels:
75 0=Jumper position 1-2 (factory default), Vref=5V internal.
76 1=Jumper position 2-3, Vref=Vext external.
77 [3] - Select channel 0 range according to jumper LK2:
78 0=Jumper position 2-3 (factory default), range [-2*Vref,+2*Vref]
79 (10V bipolar when options[2]=0).
80 1=Jumper position 1-2, range [-Vref,+Vref]
81 (5V bipolar when options[2]=0).
82 [4] - Select channel 1 range according to jumper LK3: cf. options[3].
83 [5] - Select channel 2 range according to jumper LK4: cf. options[3].
84 [6] - Select channel 3 range according to jumper LK5: cf. options[3].
85
86Passing a zero for an option is the same as leaving it unspecified.
87
88Caveats:
89
90 1) All channels on the PCI224 share the same range. Any change to the
91 range as a result of insn_write or a streaming command will affect
92 the output voltages of all channels, including those not specified
93 by the instruction or command.
94
95 2) For the analog output command, the first scan may be triggered
96 falsely at the start of acquisition. This occurs when the DAC scan
97 trigger source is switched from 'none' to 'timer' (scan_begin_src =
98 TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start
99 of acquisition and the trigger source is at logic level 1 at the
100 time of the switch. This is very likely for TRIG_TIMER. For
101 TRIG_EXT, it depends on the state of the external line and whether
102 the CR_INVERT flag has been set. The remaining scans are triggered
103 correctly.
104*/
105
106#include "../comedidev.h"
107
108#include "comedi_pci.h"
109
110#include "comedi_fc.h"
111#include "8253.h"
112
113#define DRIVER_NAME "amplc_pci224"
114
115/*
116 * PCI IDs.
117 */
118/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
119#define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
120#define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
121#define PCI_DEVICE_ID_INVALID 0xffff
122
123/*
124 * PCI224/234 i/o space 1 (PCIBAR2) registers.
125 */
126#define PCI224_IO1_SIZE 0x20 /* Size of i/o space 1 (8-bit registers) */
127#define PCI224_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
128#define PCI224_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
129#define PCI224_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
130#define PCI224_Z2_CTC 0x17 /* 82C54 counter/timer control word */
131#define PCI224_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */
132#define PCI224_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */
133#define PCI224_INT_SCE 0x1E /* ISR Interrupt source mask register */
134 /* /Interrupt status */
135
136/*
137 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
138 */
139#define PCI224_IO2_SIZE 0x10 /* Size of i/o space 2 (16-bit registers). */
140#define PCI224_DACDATA 0x00 /* (w-o) DAC FIFO data. */
141#define PCI224_SOFTTRIG 0x00 /* (r-o) DAC software scan trigger. */
142#define PCI224_DACCON 0x02 /* (r/w) DAC status/configuration. */
143#define PCI224_FIFOSIZ 0x04 /* (w-o) FIFO size for wraparound mode. */
144#define PCI224_DACCEN 0x06 /* (w-o) DAC channel enable register. */
145
146/*
147 * DACCON values.
148 */
149/* (r/w) Scan trigger. */
150#define PCI224_DACCON_TRIG_MASK (7 << 0)
151#define PCI224_DACCON_TRIG_NONE (0 << 0) /* none */
152#define PCI224_DACCON_TRIG_SW (1 << 0) /* software trig */
153#define PCI224_DACCON_TRIG_EXTP (2 << 0) /* ext +ve edge */
154#define PCI224_DACCON_TRIG_EXTN (3 << 0) /* ext -ve edge */
155#define PCI224_DACCON_TRIG_Z2CT0 (4 << 0) /* Z2 CT0 out */
156#define PCI224_DACCON_TRIG_Z2CT1 (5 << 0) /* Z2 CT1 out */
157#define PCI224_DACCON_TRIG_Z2CT2 (6 << 0) /* Z2 CT2 out */
158/* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
159#define PCI224_DACCON_POLAR_MASK (1 << 3)
160#define PCI224_DACCON_POLAR_UNI (0 << 3) /* range [0,Vref] */
161#define PCI224_DACCON_POLAR_BI (1 << 3) /* range [-Vref,Vref] */
162/* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
163#define PCI224_DACCON_VREF_MASK (3 << 4)
164#define PCI224_DACCON_VREF_1_25 (0 << 4) /* Vref = 1.25V */
165#define PCI224_DACCON_VREF_2_5 (1 << 4) /* Vref = 2.5V */
166#define PCI224_DACCON_VREF_5 (2 << 4) /* Vref = 5V */
167#define PCI224_DACCON_VREF_10 (3 << 4) /* Vref = 10V */
168/* (r/w) Wraparound mode enable (to play back stored waveform). */
169#define PCI224_DACCON_FIFOWRAP (1 << 7)
170/* (r/w) FIFO enable. It MUST be set! */
171#define PCI224_DACCON_FIFOENAB (1 << 8)
172/* (r/w) FIFO interrupt trigger level (most values are not very useful). */
173#define PCI224_DACCON_FIFOINTR_MASK (7 << 9)
174#define PCI224_DACCON_FIFOINTR_EMPTY (0 << 9) /* when empty */
175#define PCI224_DACCON_FIFOINTR_NEMPTY (1 << 9) /* when not empty */
176#define PCI224_DACCON_FIFOINTR_NHALF (2 << 9) /* when not half full */
177#define PCI224_DACCON_FIFOINTR_HALF (3 << 9) /* when half full */
178#define PCI224_DACCON_FIFOINTR_NFULL (4 << 9) /* when not full */
179#define PCI224_DACCON_FIFOINTR_FULL (5 << 9) /* when full */
180/* (r-o) FIFO fill level. */
181#define PCI224_DACCON_FIFOFL_MASK (7 << 12)
182#define PCI224_DACCON_FIFOFL_EMPTY (1 << 12) /* 0 */
183#define PCI224_DACCON_FIFOFL_ONETOHALF (0 << 12) /* [1,2048] */
184#define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12) /* [2049,4095] */
185#define PCI224_DACCON_FIFOFL_FULL (6 << 12) /* 4096 */
186/* (r-o) DAC busy flag. */
187#define PCI224_DACCON_BUSY (1 << 15)
188/* (w-o) FIFO reset. */
189#define PCI224_DACCON_FIFORESET (1 << 12)
190/* (w-o) Global reset (not sure what it does). */
191#define PCI224_DACCON_GLOBALRESET (1 << 13)
192
193/*
194 * DAC FIFO size.
195 */
196#define PCI224_FIFO_SIZE 4096
197
198/*
199 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
200 * The maximum room available depends on the reported fill level and how much
201 * has been written!
202 */
203#define PCI224_FIFO_ROOM_EMPTY PCI224_FIFO_SIZE
204#define PCI224_FIFO_ROOM_ONETOHALF (PCI224_FIFO_SIZE / 2)
205#define PCI224_FIFO_ROOM_HALFTOFULL 1
206#define PCI224_FIFO_ROOM_FULL 0
207
208/*
209 * Counter/timer clock input configuration sources.
210 */
211#define CLK_CLK 0 /* reserved (channel-specific clock) */
212#define CLK_10MHZ 1 /* internal 10 MHz clock */
213#define CLK_1MHZ 2 /* internal 1 MHz clock */
214#define CLK_100KHZ 3 /* internal 100 kHz clock */
215#define CLK_10KHZ 4 /* internal 10 kHz clock */
216#define CLK_1KHZ 5 /* internal 1 kHz clock */
217#define CLK_OUTNM1 6 /* output of channel-1 modulo total */
218#define CLK_EXT 7 /* external clock */
219/* Macro to construct clock input configuration register value. */
220#define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
221/* Timebases in ns. */
222#define TIMEBASE_10MHZ 100
223#define TIMEBASE_1MHZ 1000
224#define TIMEBASE_100KHZ 10000
225#define TIMEBASE_10KHZ 100000
226#define TIMEBASE_1KHZ 1000000
227
228/*
229 * Counter/timer gate input configuration sources.
230 */
231#define GAT_VCC 0 /* VCC (i.e. enabled) */
232#define GAT_GND 1 /* GND (i.e. disabled) */
233#define GAT_EXT 2 /* reserved (external gate input) */
234#define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
235/* Macro to construct gate input configuration register value. */
236#define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
237
238/*
239 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
240 *
241 * Channel's Channel's
242 * clock input gate input
243 * Channel CLK_OUTNM1 GAT_NOUTNM2
244 * ------- ---------- -----------
245 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
246 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
247 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
248 */
249
250/*
251 * Interrupt enable/status bits
252 */
253#define PCI224_INTR_EXT 0x01 /* rising edge on external input */
254#define PCI224_INTR_DAC 0x04 /* DAC (FIFO) interrupt */
255#define PCI224_INTR_Z2CT1 0x20 /* rising edge on Z2-CT1 output */
256
257#define PCI224_INTR_EDGE_BITS (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
258#define PCI224_INTR_LEVEL_BITS PCI224_INTR_DACFIFO
259
260/*
261 * Handy macros.
262 */
263
264/* Combine old and new bits. */
265#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
266
267/* A generic null function pointer value. */
268#define NULLFUNC 0
269
270/* Current CPU. XXX should this be hard_smp_processor_id()? */
271#define THISCPU smp_processor_id()
272
273/* State bits for use with atomic bit operations. */
274#define AO_CMD_STARTED 0
275
276/*
277 * Range tables.
278 */
279
280/* The software selectable internal ranges for PCI224 (option[2] == 0). */
281static const comedi_lrange range_pci224_internal = {
282 8,
283 {
284 BIP_RANGE(10),
285 BIP_RANGE(5),
286 BIP_RANGE(2.5),
287 BIP_RANGE(1.25),
288 UNI_RANGE(10),
289 UNI_RANGE(5),
290 UNI_RANGE(2.5),
291 UNI_RANGE(1.25),
292 }
293};
294
295static const unsigned short hwrange_pci224_internal[8] = {
296 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
297 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
298 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
299 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
300 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
301 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
302 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
303 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
304};
305
306/* The software selectable external ranges for PCI224 (option[2] == 1). */
307static const comedi_lrange range_pci224_external = {
308 2,
309 {
310 RANGE_ext(-1, 1), /* bipolar [-Vref,+Vref] */
311 RANGE_ext(0, 1), /* unipolar [0,+Vref] */
312 }
313};
314
315static const unsigned short hwrange_pci224_external[2] = {
316 PCI224_DACCON_POLAR_BI,
317 PCI224_DACCON_POLAR_UNI,
318};
319
320/* The hardware selectable Vref*2 external range for PCI234
321 * (option[2] == 1, option[3+n] == 0). */
322static const comedi_lrange range_pci234_ext2 = {
323 1,
324 {
325 RANGE_ext(-2, 2),
326 }
327};
328
329/* The hardware selectable Vref external range for PCI234
330 * (option[2] == 1, option[3+n] == 1). */
331static const comedi_lrange range_pci234_ext = {
332 1,
333 {
334 RANGE_ext(-1, 1),
335 }
336};
337
338/* This serves for all the PCI234 ranges. */
339static const unsigned short hwrange_pci234[1] = {
340 PCI224_DACCON_POLAR_BI, /* bipolar - hardware ignores it! */
341};
342
343/*
344 * Board descriptions.
345 */
346
347enum pci224_model { any_model, pci224_model, pci234_model };
348
349typedef struct pci224_board_struct {
350 const char *name;
351 unsigned short devid;
352 enum pci224_model model;
353 unsigned int ao_chans;
354 unsigned int ao_bits;
355} pci224_board;
356
357static const pci224_board pci224_boards[] = {
358 {
359 name: "pci224",
360 devid: PCI_DEVICE_ID_AMPLICON_PCI224,
361 model: pci224_model,
362 ao_chans:16,
363 ao_bits: 12,
364 },
365 {
366 name: "pci234",
367 devid: PCI_DEVICE_ID_AMPLICON_PCI234,
368 model: pci234_model,
369 ao_chans:4,
370 ao_bits: 16,
371 },
372 {
373 name: DRIVER_NAME,
374 devid: PCI_DEVICE_ID_INVALID,
375 model: any_model, /* wildcard */
376 },
377};
378
379/*
380 * PCI driver table.
381 */
382
383static DEFINE_PCI_DEVICE_TABLE(pci224_pci_table) = {
384 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224,
385 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
386 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234,
387 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
388 {0}
389};
390
391MODULE_DEVICE_TABLE(pci, pci224_pci_table);
392
393/*
394 * Useful for shorthand access to the particular board structure
395 */
396#define thisboard ((pci224_board *)dev->board_ptr)
397
398/* this structure is for data unique to this hardware driver. If
399 several hardware drivers keep similar information in this structure,
400 feel free to suggest moving the variable to the comedi_device struct. */
401typedef struct {
402 struct pci_dev *pci_dev; /* PCI device */
403 const unsigned short *hwrange;
404 unsigned long iobase1;
405 unsigned long state;
406 spinlock_t ao_spinlock;
790c5541
BP
407 unsigned int *ao_readback;
408 short *ao_scan_vals;
ea1aeae4
IA
409 unsigned char *ao_scan_order;
410 int intr_cpuid;
411 short intr_running;
412 unsigned short daccon;
413 unsigned int cached_div1;
414 unsigned int cached_div2;
415 unsigned int ao_stop_count;
416 short ao_stop_continuous;
417 unsigned short ao_enab; /* max 16 channels so 'short' will do */
418 unsigned char intsce;
419} pci224_private;
420
421#define devpriv ((pci224_private *)dev->private)
422
423/*
424 * The comedi_driver structure tells the Comedi core module
425 * which functions to call to configure/deconfigure (attach/detach)
426 * the board, and also about the kernel module that contains
427 * the device code.
428 */
429static int pci224_attach(comedi_device * dev, comedi_devconfig * it);
430static int pci224_detach(comedi_device * dev);
431static comedi_driver driver_amplc_pci224 = {
432 driver_name:DRIVER_NAME,
433 module:THIS_MODULE,
434 attach:pci224_attach,
435 detach:pci224_detach,
436 board_name:&pci224_boards[0].name,
437 offset:sizeof(pci224_board),
438 num_names:sizeof(pci224_boards) / sizeof(pci224_board),
439};
440
441COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
442
443/*
444 * Called from the 'insn_write' function to perform a single write.
445 */
446static void
790c5541 447pci224_ao_set_data(comedi_device * dev, int chan, int range, unsigned int data)
ea1aeae4
IA
448{
449 unsigned short mangled;
450
451 /* Store unmangled data for readback. */
452 devpriv->ao_readback[chan] = data;
453 /* Enable the channel. */
454 outw(1 << chan, dev->iobase + PCI224_DACCEN);
455 /* Set range and reset FIFO. */
456 devpriv->daccon = COMBINE(devpriv->daccon, devpriv->hwrange[range],
457 (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK));
458 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
459 dev->iobase + PCI224_DACCON);
460 /*
461 * Mangle the data. The hardware expects:
462 * - bipolar: 16-bit 2's complement
463 * - unipolar: 16-bit unsigned
464 */
465 mangled = (unsigned short)data << (16 - thisboard->ao_bits);
466 if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
467 PCI224_DACCON_POLAR_BI) {
468 mangled ^= 0x8000;
469 }
470 /* Write mangled data to the FIFO. */
471 outw(mangled, dev->iobase + PCI224_DACDATA);
472 /* Trigger the conversion. */
473 inw(dev->iobase + PCI224_SOFTTRIG);
474}
475
476/*
477 * 'insn_write' function for AO subdevice.
478 */
479static int
480pci224_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
790c5541 481 comedi_insn * insn, unsigned int * data)
ea1aeae4
IA
482{
483 int i;
484 int chan, range;
485
486 /* Unpack channel and range. */
487 chan = CR_CHAN(insn->chanspec);
488 range = CR_RANGE(insn->chanspec);
489
490 /* Writing a list of values to an AO channel is probably not
491 * very useful, but that's how the interface is defined. */
492 for (i = 0; i < insn->n; i++) {
493 pci224_ao_set_data(dev, chan, range, data[i]);
494 }
495 return i;
496}
497
498/*
499 * 'insn_read' function for AO subdevice.
500 *
501 * N.B. The value read will not be valid if the DAC channel has
502 * never been written successfully since the device was attached
503 * or since the channel has been used by an AO streaming write
504 * command.
505 */
506static int
507pci224_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
790c5541 508 comedi_insn * insn, unsigned int * data)
ea1aeae4
IA
509{
510 int i;
511 int chan;
512
513 chan = CR_CHAN(insn->chanspec);
514
515 for (i = 0; i < insn->n; i++) {
516 data[i] = devpriv->ao_readback[chan];
517 }
518
519 return i;
520}
521
522/*
523 * Just a wrapper for the inline function 'i8253_cascade_ns_to_timer'.
524 */
525static void
526pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
527 unsigned int *nanosec, int round_mode)
528{
529 i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode);
530}
531
532/*
533 * Kills a command running on the AO subdevice.
534 */
535static void pci224_ao_stop(comedi_device * dev, comedi_subdevice * s)
536{
537 unsigned long flags;
538
539 if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state)) {
540 return;
541 }
542
543 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
544 /* Kill the interrupts. */
545 devpriv->intsce = 0;
546 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
547 /*
548 * Interrupt routine may or may not be running. We may or may not
549 * have been called from the interrupt routine (directly or
550 * indirectly via a comedi_events() callback routine). It's highly
551 * unlikely that we've been called from some other interrupt routine
552 * but who knows what strange things coders get up to!
553 *
554 * If the interrupt routine is currently running, wait for it to
555 * finish, unless we appear to have been called via the interrupt
556 * routine.
557 */
558 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
559 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
560 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
561 }
562 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
563 /* Reconfigure DAC for insn_write usage. */
564 outw(0, dev->iobase + PCI224_DACCEN); /* Disable channels. */
565 devpriv->daccon = COMBINE(devpriv->daccon,
566 PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
567 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
568 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
569 dev->iobase + PCI224_DACCON);
570}
571
572/*
573 * Handles start of acquisition for the AO subdevice.
574 */
575static void pci224_ao_start(comedi_device * dev, comedi_subdevice * s)
576{
577 comedi_cmd *cmd = &s->async->cmd;
578 unsigned long flags;
579
580 set_bit(AO_CMD_STARTED, &devpriv->state);
581 if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
582 /* An empty acquisition! */
583 pci224_ao_stop(dev, s);
584 s->async->events |= COMEDI_CB_EOA;
585 comedi_event(dev, s);
586 } else {
587 /* Enable interrupts. */
588 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
589 if (cmd->stop_src == TRIG_EXT) {
590 devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
591 } else {
592 devpriv->intsce = PCI224_INTR_DAC;
593 }
594 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
595 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
596 }
597}
598
599/*
600 * Handles interrupts from the DAC FIFO.
601 */
602static void pci224_ao_handle_fifo(comedi_device * dev, comedi_subdevice * s)
603{
604 comedi_cmd *cmd = &s->async->cmd;
605 unsigned int num_scans;
606 unsigned int room;
607 unsigned short dacstat;
608 unsigned int i, n;
609 unsigned int bytes_per_scan;
610
611 if (cmd->chanlist_len) {
790c5541 612 bytes_per_scan = cmd->chanlist_len * sizeof(short);
ea1aeae4
IA
613 } else {
614 /* Shouldn't get here! */
790c5541 615 bytes_per_scan = sizeof(short);
ea1aeae4
IA
616 }
617 /* Determine number of scans available in buffer. */
618 num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
619 if (!devpriv->ao_stop_continuous) {
620 /* Fixed number of scans. */
621 if (num_scans > devpriv->ao_stop_count) {
622 num_scans = devpriv->ao_stop_count;
623 }
624 }
625
626 /* Determine how much room is in the FIFO (in samples). */
627 dacstat = inw(dev->iobase + PCI224_DACCON);
628 switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
629 case PCI224_DACCON_FIFOFL_EMPTY:
630 room = PCI224_FIFO_ROOM_EMPTY;
631 if (!devpriv->ao_stop_continuous
632 && devpriv->ao_stop_count == 0) {
633 /* FIFO empty at end of counted acquisition. */
634 pci224_ao_stop(dev, s);
635 s->async->events |= COMEDI_CB_EOA;
636 comedi_event(dev, s);
637 return;
638 }
639 break;
640 case PCI224_DACCON_FIFOFL_ONETOHALF:
641 room = PCI224_FIFO_ROOM_ONETOHALF;
642 break;
643 case PCI224_DACCON_FIFOFL_HALFTOFULL:
644 room = PCI224_FIFO_ROOM_HALFTOFULL;
645 break;
646 default:
647 room = PCI224_FIFO_ROOM_FULL;
648 break;
649 }
650 if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
651 /* FIFO is less than half-full. */
652 if (num_scans == 0) {
653 /* Nothing left to put in the FIFO. */
654 pci224_ao_stop(dev, s);
655 s->async->events |= COMEDI_CB_OVERFLOW;
656 rt_printk(KERN_ERR "comedi%d: "
657 "AO buffer underrun\n", dev->minor);
658 }
659 }
660 /* Determine how many new scans can be put in the FIFO. */
661 if (cmd->chanlist_len) {
662 room /= cmd->chanlist_len;
663 }
664 /* Determine how many scans to process. */
665 if (num_scans > room) {
666 num_scans = room;
667 }
668 /* Process scans. */
669 for (n = 0; n < num_scans; n++) {
670 cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
671 bytes_per_scan);
672 for (i = 0; i < cmd->chanlist_len; i++) {
673 outw(devpriv->ao_scan_vals[devpriv->
674 ao_scan_order[i]],
675 dev->iobase + PCI224_DACDATA);
676 }
677 }
678 if (!devpriv->ao_stop_continuous) {
679 devpriv->ao_stop_count -= num_scans;
680 if (devpriv->ao_stop_count == 0) {
681 /*
682 * Change FIFO interrupt trigger level to wait
683 * until FIFO is empty.
684 */
685 devpriv->daccon = COMBINE(devpriv->daccon,
686 PCI224_DACCON_FIFOINTR_EMPTY,
687 PCI224_DACCON_FIFOINTR_MASK);
688 outw(devpriv->daccon,
689 dev->iobase + PCI224_DACCON);
690 }
691 }
692 if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
693 PCI224_DACCON_TRIG_NONE) {
694 unsigned short trig;
695
696 /*
697 * This is the initial DAC FIFO interrupt at the
698 * start of the acquisition. The DAC's scan trigger
699 * has been set to 'none' up until now.
700 *
701 * Now that data has been written to the FIFO, the
702 * DAC's scan trigger source can be set to the
703 * correct value.
704 *
705 * BUG: The first scan will be triggered immediately
706 * if the scan trigger source is at logic level 1.
707 */
708 if (cmd->scan_begin_src == TRIG_TIMER) {
709 trig = PCI224_DACCON_TRIG_Z2CT0;
710 } else {
711 /* cmd->scan_begin_src == TRIG_EXT */
712 if (cmd->scan_begin_arg & CR_INVERT) {
713 trig = PCI224_DACCON_TRIG_EXTN;
714 } else {
715 trig = PCI224_DACCON_TRIG_EXTP;
716 }
717 }
718 devpriv->daccon = COMBINE(devpriv->daccon, trig,
719 PCI224_DACCON_TRIG_MASK);
720 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
721 }
722 if (s->async->events) {
723 comedi_event(dev, s);
724 }
725}
726
727/*
728 * Internal trigger function to start acquisition on AO subdevice.
729 */
730static int
731pci224_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
732 unsigned int trignum)
733{
734 if (trignum != 0)
735 return -EINVAL;
736
737 s->async->inttrig = NULLFUNC;
738 pci224_ao_start(dev, s);
739
740 return 1;
741}
742
743#define MAX_SCAN_PERIOD 0xFFFFFFFFU
744#define MIN_SCAN_PERIOD 2500
745#define CONVERT_PERIOD 625
746
747/*
748 * 'do_cmdtest' function for AO subdevice.
749 */
750static int
751pci224_ao_cmdtest(comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
752{
753 int err = 0;
754 unsigned int tmp;
755
756 /* Step 1: make sure trigger sources are trivially valid. */
757
758 tmp = cmd->start_src;
759 cmd->start_src &= TRIG_INT | TRIG_EXT;
760 if (!cmd->start_src || tmp != cmd->start_src)
761 err++;
762
763 tmp = cmd->scan_begin_src;
764 cmd->scan_begin_src &= TRIG_EXT | TRIG_TIMER;
765 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
766 err++;
767
768 tmp = cmd->convert_src;
769 cmd->convert_src &= TRIG_NOW;
770 if (!cmd->convert_src || tmp != cmd->convert_src)
771 err++;
772
773 tmp = cmd->scan_end_src;
774 cmd->scan_end_src &= TRIG_COUNT;
775 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
776 err++;
777
778 tmp = cmd->stop_src;
779 cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
780 if (!cmd->stop_src || tmp != cmd->stop_src)
781 err++;
782
783 if (err)
784 return 1;
785
786 /* Step 2: make sure trigger sources are unique and mutually
787 * compatible. */
788
789 /* these tests are true if more than one _src bit is set */
790 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
791 err++;
792 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
793 err++;
794 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
795 err++;
796 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
797 err++;
798 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
799 err++;
800
801 /* There's only one external trigger signal (which makes these
802 * tests easier). Only one thing can use it. */
803 tmp = 0;
804 if (cmd->start_src & TRIG_EXT)
805 tmp++;
806 if (cmd->scan_begin_src & TRIG_EXT)
807 tmp++;
808 if (cmd->stop_src & TRIG_EXT)
809 tmp++;
810 if (tmp > 1)
811 err++;
812
813 if (err)
814 return 2;
815
816 /* Step 3: make sure arguments are trivially compatible. */
817
818 switch (cmd->start_src) {
819 case TRIG_INT:
820 if (cmd->start_arg != 0) {
821 cmd->start_arg = 0;
822 err++;
823 }
824 break;
825 case TRIG_EXT:
826 /* Force to external trigger 0. */
827 if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) {
828 cmd->start_arg = COMBINE(cmd->start_arg, 0,
829 ~CR_FLAGS_MASK);
830 err++;
831 }
832 /* The only flag allowed is CR_EDGE, which is ignored. */
833 if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
834 cmd->start_arg = COMBINE(cmd->start_arg, 0,
835 CR_FLAGS_MASK & ~CR_EDGE);
836 err++;
837 }
838 break;
839 }
840
841 switch (cmd->scan_begin_src) {
842 case TRIG_TIMER:
843 if (cmd->scan_begin_arg > MAX_SCAN_PERIOD) {
844 cmd->scan_begin_arg = MAX_SCAN_PERIOD;
845 err++;
846 }
847 tmp = cmd->chanlist_len * CONVERT_PERIOD;
848 if (tmp < MIN_SCAN_PERIOD) {
849 tmp = MIN_SCAN_PERIOD;
850 }
851 if (cmd->scan_begin_arg < tmp) {
852 cmd->scan_begin_arg = tmp;
853 err++;
854 }
855 break;
856 case TRIG_EXT:
857 /* Force to external trigger 0. */
858 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
859 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
860 ~CR_FLAGS_MASK);
861 err++;
862 }
863 /* Only allow flags CR_EDGE and CR_INVERT. Ignore CR_EDGE. */
864 if ((cmd->scan_begin_arg & CR_FLAGS_MASK &
865 ~(CR_EDGE | CR_INVERT)) != 0) {
866 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
867 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
868 err++;
869 }
870 break;
871 }
872
873 /* cmd->convert_src == TRIG_NOW */
874 if (cmd->convert_arg != 0) {
875 cmd->convert_arg = 0;
876 err++;
877 }
878
879 /* cmd->scan_end_arg == TRIG_COUNT */
880 if (cmd->scan_end_arg != cmd->chanlist_len) {
881 cmd->scan_end_arg = cmd->chanlist_len;
882 err++;
883 }
884
885 switch (cmd->stop_src) {
886 case TRIG_COUNT:
887 /* Any count allowed. */
888 break;
889 case TRIG_EXT:
890 /* Force to external trigger 0. */
891 if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) {
892 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
893 ~CR_FLAGS_MASK);
894 err++;
895 }
896 /* The only flag allowed is CR_EDGE, which is ignored. */
897 if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
898 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
899 CR_FLAGS_MASK & ~CR_EDGE);
900 }
901 break;
902 case TRIG_NONE:
903 if (cmd->stop_arg != 0) {
904 cmd->stop_arg = 0;
905 err++;
906 }
907 break;
908 }
909
910 if (err)
911 return 3;
912
913 /* Step 4: fix up any arguments. */
914
915 if (cmd->scan_begin_src == TRIG_TIMER) {
916 unsigned int div1, div2, round;
917 int round_mode = cmd->flags & TRIG_ROUND_MASK;
918
919 tmp = cmd->scan_begin_arg;
920 /* Check whether to use a single timer. */
921 switch (round_mode) {
922 case TRIG_ROUND_NEAREST:
923 default:
924 round = TIMEBASE_10MHZ / 2;
925 break;
926 case TRIG_ROUND_DOWN:
927 round = 0;
928 break;
929 case TRIG_ROUND_UP:
930 round = TIMEBASE_10MHZ - 1;
931 break;
932 }
933 /* Be careful to avoid overflow! */
934 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
935 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
936 TIMEBASE_10MHZ;
937 if (div2 <= 0x10000) {
938 /* A single timer will suffice. */
939 if (div2 < 2)
940 div2 = 2;
941 cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
942 if (cmd->scan_begin_arg < div2 ||
943 cmd->scan_begin_arg < TIMEBASE_10MHZ) {
944 /* Overflow! */
945 cmd->scan_begin_arg = MAX_SCAN_PERIOD;
946 }
947 } else {
948 /* Use two timers. */
949 div1 = devpriv->cached_div1;
950 div2 = devpriv->cached_div2;
951 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
952 &cmd->scan_begin_arg, round_mode);
953 devpriv->cached_div1 = div1;
954 devpriv->cached_div2 = div2;
955 }
956 if (tmp != cmd->scan_begin_arg) {
957 err++;
958 }
959 }
960
961 if (err)
962 return 4;
963
964 /* Step 5: check channel list. */
965
966 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
967 unsigned int range;
968 enum { range_err = 1, dupchan_err = 2, };
969 unsigned errors;
970 unsigned int n;
971 unsigned int ch;
972
973 /*
974 * Check all channels have the same range index. Don't care
975 * about analogue reference, as we can't configure it.
976 *
977 * Check the list has no duplicate channels.
978 */
979 range = CR_RANGE(cmd->chanlist[0]);
980 errors = 0;
981 tmp = 0;
982 for (n = 0; n < cmd->chanlist_len; n++) {
983 ch = CR_CHAN(cmd->chanlist[n]);
984 if (tmp & (1U << ch)) {
985 errors |= dupchan_err;
986 }
987 tmp |= (1U << ch);
988 if (CR_RANGE(cmd->chanlist[n]) != range) {
989 errors |= range_err;
990 }
991 }
992 if (errors) {
993 if (errors & dupchan_err) {
994 DPRINTK("comedi%d: " DRIVER_NAME
995 ": ao_cmdtest: "
996 "entries in chanlist must contain no "
997 "duplicate channels\n", dev->minor);
998 }
999 if (errors & range_err) {
1000 DPRINTK("comedi%d: " DRIVER_NAME
1001 ": ao_cmdtest: "
1002 "entries in chanlist must all have "
1003 "the same range index\n", dev->minor);
1004 }
1005 err++;
1006 }
1007 }
1008
1009 if (err)
1010 return 5;
1011
1012 return 0;
1013}
1014
1015/*
1016 * 'do_cmd' function for AO subdevice.
1017 */
1018static int pci224_ao_cmd(comedi_device * dev, comedi_subdevice * s)
1019{
1020 comedi_cmd *cmd = &s->async->cmd;
1021 int range;
1022 unsigned int i, j;
1023 unsigned int ch;
1024 unsigned int rank;
1025 unsigned long flags;
1026
1027 /* Cannot handle null/empty chanlist. */
1028 if (cmd->chanlist == NULL || cmd->chanlist_len == 0) {
1029 return -EINVAL;
1030 }
1031
1032 /* Determine which channels are enabled and their load order. */
1033 devpriv->ao_enab = 0;
1034
1035 for (i = 0; i < cmd->chanlist_len; i++) {
1036 ch = CR_CHAN(cmd->chanlist[i]);
1037 devpriv->ao_enab |= 1U << ch;
1038 rank = 0;
1039 for (j = 0; j < cmd->chanlist_len; j++) {
1040 if (CR_CHAN(cmd->chanlist[j]) < ch) {
1041 rank++;
1042 }
1043 }
1044 devpriv->ao_scan_order[rank] = i;
1045 }
1046
1047 /* Set enabled channels. */
1048 outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
1049
1050 /* Determine range and polarity. All channels the same. */
1051 range = CR_RANGE(cmd->chanlist[0]);
1052
1053 /*
1054 * Set DAC range and polarity.
1055 * Set DAC scan trigger source to 'none'.
1056 * Set DAC FIFO interrupt trigger level to 'not half full'.
1057 * Reset DAC FIFO.
1058 *
1059 * N.B. DAC FIFO interrupts are currently disabled.
1060 */
1061 devpriv->daccon = COMBINE(devpriv->daccon,
1062 (devpriv->hwrange[range] | PCI224_DACCON_TRIG_NONE |
1063 PCI224_DACCON_FIFOINTR_NHALF),
1064 (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
1065 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK));
1066 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1067 dev->iobase + PCI224_DACCON);
1068
1069 if (cmd->scan_begin_src == TRIG_TIMER) {
1070 unsigned int div1, div2, round;
1071 unsigned int ns = cmd->scan_begin_arg;
1072 int round_mode = cmd->flags & TRIG_ROUND_MASK;
1073
1074 /* Check whether to use a single timer. */
1075 switch (round_mode) {
1076 case TRIG_ROUND_NEAREST:
1077 default:
1078 round = TIMEBASE_10MHZ / 2;
1079 break;
1080 case TRIG_ROUND_DOWN:
1081 round = 0;
1082 break;
1083 case TRIG_ROUND_UP:
1084 round = TIMEBASE_10MHZ - 1;
1085 break;
1086 }
1087 /* Be careful to avoid overflow! */
1088 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
1089 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
1090 TIMEBASE_10MHZ;
1091 if (div2 <= 0x10000) {
1092 /* A single timer will suffice. */
1093 if (div2 < 2)
1094 div2 = 2;
1095 div2 &= 0xffff;
1096 div1 = 1; /* Flag that single timer to be used. */
1097 } else {
1098 /* Use two timers. */
1099 div1 = devpriv->cached_div1;
1100 div2 = devpriv->cached_div2;
1101 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
1102 &ns, round_mode);
1103 }
1104
1105 /*
1106 * The output of timer Z2-0 will be used as the scan trigger
1107 * source.
1108 */
1109 /* Make sure Z2-0 is gated on. */
1110 outb(GAT_CONFIG(0, GAT_VCC),
1111 devpriv->iobase1 + PCI224_ZGAT_SCE);
1112 if (div1 == 1) {
1113 /* Not cascading. Z2-0 needs 10 MHz clock. */
1114 outb(CLK_CONFIG(0, CLK_10MHZ),
1115 devpriv->iobase1 + PCI224_ZCLK_SCE);
1116 } else {
1117 /* Cascading with Z2-2. */
1118 /* Make sure Z2-2 is gated on. */
1119 outb(GAT_CONFIG(2, GAT_VCC),
1120 devpriv->iobase1 + PCI224_ZGAT_SCE);
1121 /* Z2-2 needs 10 MHz clock. */
1122 outb(CLK_CONFIG(2, CLK_10MHZ),
1123 devpriv->iobase1 + PCI224_ZCLK_SCE);
1124 /* Load Z2-2 mode (2) and counter (div1). */
1125 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0,
1126 2, div1, 2);
1127 /* Z2-0 is clocked from Z2-2's output. */
1128 outb(CLK_CONFIG(0, CLK_OUTNM1),
1129 devpriv->iobase1 + PCI224_ZCLK_SCE);
1130 }
1131 /* Load Z2-0 mode (2) and counter (div2). */
1132 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, 0, div2, 2);
1133 }
1134
1135 /*
1136 * Sort out end of acquisition.
1137 */
1138 switch (cmd->stop_src) {
1139 case TRIG_COUNT:
1140 /* Fixed number of scans. */
1141 devpriv->ao_stop_continuous = 0;
1142 devpriv->ao_stop_count = cmd->stop_arg;
1143 break;
1144 default:
1145 /* Continuous scans. */
1146 devpriv->ao_stop_continuous = 1;
1147 devpriv->ao_stop_count = 0;
1148 break;
1149 }
1150
1151 /*
1152 * Sort out start of acquisition.
1153 */
1154 switch (cmd->start_src) {
1155 case TRIG_INT:
1156 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1157 s->async->inttrig = &pci224_ao_inttrig_start;
1158 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1159 break;
1160 case TRIG_EXT:
1161 /* Enable external interrupt trigger to start acquisition. */
1162 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1163 devpriv->intsce |= PCI224_INTR_EXT;
1164 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
1165 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1166 break;
1167 }
1168
1169 return 0;
1170}
1171
1172/*
1173 * 'cancel' function for AO subdevice.
1174 */
1175static int pci224_ao_cancel(comedi_device * dev, comedi_subdevice * s)
1176{
1177 pci224_ao_stop(dev, s);
1178 return 0;
1179}
1180
1181/*
1182 * 'munge' data for AO command.
1183 */
1184static void
1185pci224_ao_munge(comedi_device * dev, comedi_subdevice * s, void *data,
1186 unsigned int num_bytes, unsigned int chan_index)
1187{
1188 comedi_async *async = s->async;
790c5541 1189 short *array = data;
ea1aeae4
IA
1190 unsigned int length = num_bytes / sizeof(*array);
1191 unsigned int offset;
1192 unsigned int shift;
1193 unsigned int i;
1194
1195 /* The hardware expects 16-bit numbers. */
1196 shift = 16 - thisboard->ao_bits;
1197 /* Channels will be all bipolar or all unipolar. */
1198 if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] &
1199 PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
1200 /* Unipolar */
1201 offset = 0;
1202 } else {
1203 /* Bipolar */
1204 offset = 32768;
1205 }
1206 /* Munge the data. */
1207 for (i = 0; i < length; i++) {
1208 array[i] = (array[i] << shift) - offset;
1209 }
1210}
1211
1212/*
1213 * Interrupt handler.
1214 */
1215static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG)
1216{
1217 comedi_device *dev = d;
1218 comedi_subdevice *s = &dev->subdevices[0];
1219 comedi_cmd *cmd;
1220 unsigned char intstat, valid_intstat;
1221 unsigned char curenab;
1222 int retval = 0;
1223 unsigned long flags;
1224
1225 intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
1226 if (intstat) {
1227 retval = 1;
1228 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1229 valid_intstat = devpriv->intsce & intstat;
1230 /* Temporarily disable interrupt sources. */
1231 curenab = devpriv->intsce & ~intstat;
1232 outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
1233 devpriv->intr_running = 1;
1234 devpriv->intr_cpuid = THISCPU;
1235 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1236 if (valid_intstat != 0) {
1237 cmd = &s->async->cmd;
1238 if (valid_intstat & PCI224_INTR_EXT) {
1239 devpriv->intsce &= ~PCI224_INTR_EXT;
1240 if (cmd->start_src == TRIG_EXT) {
1241 pci224_ao_start(dev, s);
1242 } else if (cmd->stop_src == TRIG_EXT) {
1243 pci224_ao_stop(dev, s);
1244 }
1245 }
1246 if (valid_intstat & PCI224_INTR_DAC) {
1247 pci224_ao_handle_fifo(dev, s);
1248 }
1249 }
1250 /* Reenable interrupt sources. */
1251 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1252 if (curenab != devpriv->intsce) {
1253 outb(devpriv->intsce,
1254 devpriv->iobase1 + PCI224_INT_SCE);
1255 }
1256 devpriv->intr_running = 0;
1257 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1258 }
1259 return IRQ_RETVAL(retval);
1260}
1261
1262/*
1263 * This function looks for a PCI device matching the requested board name,
1264 * bus and slot.
1265 */
1266static int
1267pci224_find_pci(comedi_device * dev, int bus, int slot,
1268 struct pci_dev **pci_dev_p)
1269{
1270 struct pci_dev *pci_dev = NULL;
1271
1272 *pci_dev_p = NULL;
1273
1274 /* Look for matching PCI device. */
1275 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
1276 pci_dev != NULL;
1277 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID,
1278 pci_dev)) {
1279 /* If bus/slot specified, check them. */
1280 if (bus || slot) {
1281 if (bus != pci_dev->bus->number
1282 || slot != PCI_SLOT(pci_dev->devfn))
1283 continue;
1284 }
1285 if (thisboard->model == any_model) {
1286 /* Match any supported model. */
1287 int i;
1288
1289 for (i = 0; i < ARRAY_SIZE(pci224_boards); i++) {
1290 if (pci_dev->device == pci224_boards[i].devid) {
1291 /* Change board_ptr to matched board. */
1292 dev->board_ptr = &pci224_boards[i];
1293 break;
1294 }
1295 }
1296 if (i == ARRAY_SIZE(pci224_boards))
1297 continue;
1298 } else {
1299 /* Match specific model name. */
1300 if (thisboard->devid != pci_dev->device)
1301 continue;
1302 }
1303
1304 /* Found a match. */
1305 *pci_dev_p = pci_dev;
1306 return 0;
1307 }
1308 /* No match found. */
1309 if (bus || slot) {
1310 printk(KERN_ERR "comedi%d: error! "
1311 "no %s found at pci %02x:%02x!\n",
1312 dev->minor, thisboard->name, bus, slot);
1313 } else {
1314 printk(KERN_ERR "comedi%d: error! no %s found!\n",
1315 dev->minor, thisboard->name);
1316 }
1317 return -EIO;
1318}
1319
1320/*
1321 * Attach is called by the Comedi core to configure the driver
1322 * for a particular board. If you specified a board_name array
1323 * in the driver structure, dev->board_ptr contains that
1324 * address.
1325 */
1326static int pci224_attach(comedi_device * dev, comedi_devconfig * it)
1327{
1328 comedi_subdevice *s;
1329 struct pci_dev *pci_dev;
1330 unsigned int irq;
1331 int bus = 0, slot = 0;
1332 unsigned n;
1333 int ret;
1334
1335 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME);
1336
1337 bus = it->options[0];
1338 slot = it->options[1];
1339 if ((ret = alloc_private(dev, sizeof(pci224_private))) < 0) {
1340 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1341 dev->minor);
1342 return ret;
1343 }
1344 if ((ret = pci224_find_pci(dev, bus, slot, &pci_dev)) < 0)
1345 return ret;
1346 devpriv->pci_dev = pci_dev;
1347
1348 if ((ret = comedi_pci_enable(pci_dev, DRIVER_NAME)) < 0) {
1349 printk(KERN_ERR
1350 "comedi%d: error! cannot enable PCI device "
1351 "and request regions!\n", dev->minor);
1352 return ret;
1353 }
1354 spin_lock_init(&devpriv->ao_spinlock);
1355
1356 devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1357 dev->iobase = pci_resource_start(pci_dev, 3);
1358 irq = pci_dev->irq;
1359
1360 /* Allocate readback buffer for AO channels. */
1361 devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) *
1362 thisboard->ao_chans, GFP_KERNEL);
1363 if (!devpriv->ao_readback) {
1364 return -ENOMEM;
1365 }
1366
1367 /* Allocate buffer to hold values for AO channel scan. */
1368 devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
1369 thisboard->ao_chans, GFP_KERNEL);
1370 if (!devpriv->ao_scan_vals) {
1371 return -ENOMEM;
1372 }
1373
1374 /* Allocate buffer to hold AO channel scan order. */
1375 devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
1376 thisboard->ao_chans, GFP_KERNEL);
1377 if (!devpriv->ao_scan_order) {
1378 return -ENOMEM;
1379 }
1380
1381 /* Disable interrupt sources. */
1382 devpriv->intsce = 0;
1383 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1384
1385 /* Initialize the DAC hardware. */
1386 outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1387 outw(0, dev->iobase + PCI224_DACCEN);
1388 outw(0, dev->iobase + PCI224_FIFOSIZ);
1389 devpriv->daccon = (PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1390 PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY);
1391 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1392 dev->iobase + PCI224_DACCON);
1393
1394 /* Allocate subdevices. There is only one! */
1395 if ((ret = alloc_subdevices(dev, 1)) < 0) {
1396 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1397 dev->minor);
1398 return ret;
1399 }
1400
1401 s = dev->subdevices + 0;
1402 /* Analog output subdevice. */
1403 s->type = COMEDI_SUBD_AO;
1404 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1405 s->n_chan = thisboard->ao_chans;
1406 s->maxdata = (1 << thisboard->ao_bits) - 1;
1407 s->insn_write = &pci224_ao_insn_write;
1408 s->insn_read = &pci224_ao_insn_read;
1409 s->len_chanlist = s->n_chan;
1410
1411 dev->write_subdev = s;
1412 s->do_cmd = &pci224_ao_cmd;
1413 s->do_cmdtest = &pci224_ao_cmdtest;
1414 s->cancel = &pci224_ao_cancel;
1415 s->munge = &pci224_ao_munge;
1416
1417 /* Sort out channel range options. */
1418 if (thisboard->model == pci234_model) {
1419 /* PCI234 range options. */
1420 const comedi_lrange **range_table_list;
1421
1422 s->range_table_list = range_table_list =
1423 kmalloc(sizeof(comedi_lrange *) * s->n_chan,
1424 GFP_KERNEL);
1425 if (!s->range_table_list) {
1426 return -ENOMEM;
1427 }
1428 for (n = 2; n < 3 + s->n_chan; n++) {
1429 if (it->options[n] < 0 || it->options[n] > 1) {
1430 printk(KERN_WARNING "comedi%d: %s: warning! "
1431 "bad options[%u]=%d\n",
1432 dev->minor, DRIVER_NAME, n,
1433 it->options[n]);
1434 }
1435 }
1436 for (n = 0; n < s->n_chan; n++) {
1437 if (n < COMEDI_NDEVCONFOPTS - 3 &&
1438 it->options[3 + n] == 1) {
1439 if (it->options[2] == 1) {
1440 range_table_list[n] = &range_pci234_ext;
1441 } else {
1442 range_table_list[n] = &range_bipolar5;
1443 }
1444 } else {
1445 if (it->options[2] == 1) {
1446 range_table_list[n] =
1447 &range_pci234_ext2;
1448 } else {
1449 range_table_list[n] = &range_bipolar10;
1450 }
1451 }
1452 }
1453 devpriv->hwrange = hwrange_pci234;
1454 } else {
1455 /* PCI224 range options. */
1456 if (it->options[2] == 1) {
1457 s->range_table = &range_pci224_external;
1458 devpriv->hwrange = hwrange_pci224_external;
1459 } else {
1460 if (it->options[2] != 0) {
1461 printk(KERN_WARNING "comedi%d: %s: warning! "
1462 "bad options[2]=%d\n",
1463 dev->minor, DRIVER_NAME,
1464 it->options[2]);
1465 }
1466 s->range_table = &range_pci224_internal;
1467 devpriv->hwrange = hwrange_pci224_internal;
1468 }
1469 }
1470
1471 dev->board_name = thisboard->name;
1472
1473 if (irq) {
1474 ret = comedi_request_irq(irq, pci224_interrupt, IRQF_SHARED,
1475 DRIVER_NAME, dev);
1476 if (ret < 0) {
1477 printk(KERN_ERR "comedi%d: error! "
1478 "unable to allocate irq %u\n", dev->minor, irq);
1479 return ret;
1480 } else {
1481 dev->irq = irq;
1482 }
1483 }
1484
1485 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1486 printk("(pci %s) ", pci_name(pci_dev));
1487 if (irq) {
1488 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1489 } else {
1490 printk("(no irq) ");
1491 }
1492
1493 printk("attached\n");
1494
1495 return 1;
1496}
1497
1498/*
1499 * _detach is called to deconfigure a device. It should deallocate
1500 * resources.
1501 * This function is also called when _attach() fails, so it should be
1502 * careful not to release resources that were not necessarily
1503 * allocated by _attach(). dev->private and dev->subdevices are
1504 * deallocated automatically by the core.
1505 */
1506static int pci224_detach(comedi_device * dev)
1507{
1508 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
1509
1510 if (dev->irq) {
1511 comedi_free_irq(dev->irq, dev);
1512 }
1513 if (dev->subdevices) {
1514 comedi_subdevice *s;
1515
1516 s = dev->subdevices + 0;
1517 /* AO subdevice */
1518 if (s->range_table_list) {
1519 kfree(s->range_table_list);
1520 }
1521 }
1522 if (devpriv) {
1523 if (devpriv->ao_readback) {
1524 kfree(devpriv->ao_readback);
1525 }
1526 if (devpriv->ao_scan_vals) {
1527 kfree(devpriv->ao_scan_vals);
1528 }
1529 if (devpriv->ao_scan_order) {
1530 kfree(devpriv->ao_scan_order);
1531 }
1532 if (devpriv->pci_dev) {
1533 if (dev->iobase) {
1534 comedi_pci_disable(devpriv->pci_dev);
1535 }
1536 pci_dev_put(devpriv->pci_dev);
1537 }
1538 }
1539 if (dev->board_name) {
1540 printk(KERN_INFO "comedi%d: %s removed\n",
1541 dev->minor, dev->board_name);
1542 }
1543
1544 return 0;
1545}