staging: comedi: me4000: use plx9052.h defines
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / drivers / me4000.c
CommitLineData
e55c95a3
GG
1/*
2 comedi/drivers/me4000.c
3 Source code for the Meilhaus ME-4000 board family.
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23/*
24Driver: me4000
25Description: Meilhaus ME-4000 series boards
26Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
27Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
28Updated: Mon, 18 Mar 2002 15:34:01 -0800
29Status: broken (no support for loading firmware)
30
31Supports:
32
33 - Analog Input
34 - Analog Output
35 - Digital I/O
36 - Counter
37
5f8f8d43 38Configuration Options: not applicable, uses PCI auto config
e55c95a3
GG
39
40The firmware required by these boards is available in the
41comedi_nonfree_firmware tarball available from
42http://www.comedi.org. However, the driver's support for
43loading the firmware through comedi_config is currently
44broken.
45
46 */
47
33782dd5 48#include <linux/pci.h>
e55c95a3 49#include <linux/delay.h>
33782dd5 50#include <linux/interrupt.h>
e55c95a3
GG
51#include <linux/list.h>
52#include <linux/spinlock.h>
53
33782dd5
HS
54#include "../comedidev.h"
55
27020ffe 56#include "comedi_fc.h"
db9132e0 57#include "8253.h"
58af6b92 58#include "plx9052.h"
81dd1811 59
e55c95a3
GG
60#if 0
61/* file removed due to GPL incompatibility */
62#include "me4000_fw.h"
63#endif
64
81dd1811
HS
65/*
66 * ME4000 Register map and bit defines
67 */
68#define ME4000_AO_CHAN(x) ((x) * 0x18)
69
70#define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x))
71#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0)
72#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1)
73#define ME4000_AO_CTRL_MASK_MODE (3 << 0)
74#define ME4000_AO_CTRL_BIT_STOP (1 << 2)
75#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3)
76#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4)
77#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5)
78#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7)
79#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8)
80#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9)
81#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10)
82#define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x))
83#define ME4000_AO_STATUS_BIT_FSM (1 << 0)
84#define ME4000_AO_STATUS_BIT_FF (1 << 1)
85#define ME4000_AO_STATUS_BIT_HF (1 << 2)
86#define ME4000_AO_STATUS_BIT_EF (1 << 3)
87#define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x))
88#define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x))
89#define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x))
90#define ME4000_AI_CTRL_REG 0x74
91#define ME4000_AI_STATUS_REG 0x74
92#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0)
93#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1)
94#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2)
95#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3)
96#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4)
97#define ME4000_AI_CTRL_BIT_STOP (1 << 5)
98#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6)
99#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7)
100#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8)
101#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9)
102#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10)
103#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11)
104#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12)
105#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13)
106#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14)
107#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15)
108#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16)
109#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17)
110#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18)
111#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19)
112#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20)
113#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21)
114#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22)
115#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23)
116#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24)
117#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25)
118#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26)
119#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27)
120#define ME4000_AI_STATUS_BIT_LE (1 << 28)
121#define ME4000_AI_STATUS_BIT_FSM (1 << 29)
122#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31)
123#define ME4000_AI_CHANNEL_LIST_REG 0x78
124#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5)
125#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5)
126#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6)
127#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6)
128#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6)
129#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6)
130#define ME4000_AI_LIST_LAST_ENTRY (1 << 8)
131#define ME4000_AI_DATA_REG 0x7c
132#define ME4000_AI_CHAN_TIMER_REG 0x80
133#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84
134#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88
135#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8c
136#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90
137#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94
138#define ME4000_AI_START_REG 0x98
139#define ME4000_IRQ_STATUS_REG 0x9c
140#define ME4000_IRQ_STATUS_BIT_EX (1 << 0)
141#define ME4000_IRQ_STATUS_BIT_LE (1 << 1)
142#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2)
143#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3)
144#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4)
145#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5)
146#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6)
147#define ME4000_IRQ_STATUS_BIT_SC (1 << 7)
148#define ME4000_DIO_PORT_0_REG 0xa0
149#define ME4000_DIO_PORT_1_REG 0xa4
150#define ME4000_DIO_PORT_2_REG 0xa8
151#define ME4000_DIO_PORT_3_REG 0xac
152#define ME4000_DIO_DIR_REG 0xb0
153#define ME4000_AO_LOADSETREG_XX 0xb4
154#define ME4000_DIO_CTRL_REG 0xb8
155#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0)
156#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1)
157#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2)
158#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3)
159#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4)
160#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5)
161#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6)
162#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7)
163#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8)
164#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9)
165#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10)
166#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11)
167#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12)
168#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13)
169#define ME4000_AO_DEMUX_ADJUST_REG 0xbc
170#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c
171#define ME4000_AI_SAMPLE_COUNTER_REG 0xc0
172
173/*
174 * PLX Register map and bit defines
175 */
81dd1811
HS
176#define PLX_ICR 0x50
177#define PLX_ICR_BIT_EEPROM_CLOCK_SET (1 << 24)
178#define PLX_ICR_BIT_EEPROM_CHIP_SELECT (1 << 25)
179#define PLX_ICR_BIT_EEPROM_WRITE (1 << 26)
180#define PLX_ICR_BIT_EEPROM_READ (1 << 27)
181#define PLX_ICR_BIT_EEPROM_VALID (1 << 28)
182#define PLX_ICR_MASK_EEPROM (0x1f << 24)
183
184#define EEPROM_DELAY 1
185
186#define ME4000_AI_FIFO_COUNT 2048
187
188#define ME4000_AI_MIN_TICKS 66
189#define ME4000_AI_MIN_SAMPLE_TIME 2000
190#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6
191
192#define ME4000_AI_CHANNEL_LIST_COUNT 1024
193
cc6f3336
HS
194struct me4000_info {
195 unsigned long plx_regbase;
196 unsigned long timer_regbase;
197
198 unsigned int ao_readback[4];
199};
200
8c355509
HS
201enum me4000_boardid {
202 BOARD_ME4650,
203 BOARD_ME4660,
204 BOARD_ME4660I,
205 BOARD_ME4660S,
206 BOARD_ME4660IS,
207 BOARD_ME4670,
208 BOARD_ME4670I,
209 BOARD_ME4670S,
210 BOARD_ME4670IS,
211 BOARD_ME4680,
212 BOARD_ME4680I,
213 BOARD_ME4680S,
214 BOARD_ME4680IS,
215};
216
06b60981
HS
217struct me4000_board {
218 const char *name;
06b60981
HS
219 int ao_nchan;
220 int ao_fifo;
221 int ai_nchan;
222 int ai_diff_nchan;
223 int ai_sh_nchan;
224 int ex_trig_analog;
225 int dio_nchan;
226 int has_counter;
227};
228
27f4caaa 229static const struct me4000_board me4000_boards[] = {
8c355509 230 [BOARD_ME4650] = {
035d432a 231 .name = "ME-4650",
6ba8dfef 232 .ai_nchan = 16,
898f5191 233 .dio_nchan = 32,
8c355509
HS
234 },
235 [BOARD_ME4660] = {
035d432a 236 .name = "ME-4660",
6ba8dfef
HS
237 .ai_nchan = 32,
238 .ai_diff_nchan = 16,
898f5191 239 .dio_nchan = 32,
eedf4299 240 .has_counter = 1,
8c355509
HS
241 },
242 [BOARD_ME4660I] = {
035d432a 243 .name = "ME-4660i",
6ba8dfef
HS
244 .ai_nchan = 32,
245 .ai_diff_nchan = 16,
898f5191 246 .dio_nchan = 32,
eedf4299 247 .has_counter = 1,
8c355509
HS
248 },
249 [BOARD_ME4660S] = {
035d432a 250 .name = "ME-4660s",
6ba8dfef
HS
251 .ai_nchan = 32,
252 .ai_diff_nchan = 16,
253 .ai_sh_nchan = 8,
898f5191 254 .dio_nchan = 32,
eedf4299 255 .has_counter = 1,
8c355509
HS
256 },
257 [BOARD_ME4660IS] = {
035d432a 258 .name = "ME-4660is",
6ba8dfef
HS
259 .ai_nchan = 32,
260 .ai_diff_nchan = 16,
261 .ai_sh_nchan = 8,
898f5191 262 .dio_nchan = 32,
eedf4299 263 .has_counter = 1,
8c355509
HS
264 },
265 [BOARD_ME4670] = {
035d432a 266 .name = "ME-4670",
2d504528 267 .ao_nchan = 4,
6ba8dfef
HS
268 .ai_nchan = 32,
269 .ai_diff_nchan = 16,
270 .ex_trig_analog = 1,
898f5191 271 .dio_nchan = 32,
eedf4299 272 .has_counter = 1,
8c355509
HS
273 },
274 [BOARD_ME4670I] = {
035d432a 275 .name = "ME-4670i",
2d504528 276 .ao_nchan = 4,
6ba8dfef
HS
277 .ai_nchan = 32,
278 .ai_diff_nchan = 16,
279 .ex_trig_analog = 1,
898f5191 280 .dio_nchan = 32,
eedf4299 281 .has_counter = 1,
8c355509
HS
282 },
283 [BOARD_ME4670S] = {
035d432a 284 .name = "ME-4670s",
2d504528 285 .ao_nchan = 4,
6ba8dfef
HS
286 .ai_nchan = 32,
287 .ai_diff_nchan = 16,
288 .ai_sh_nchan = 8,
289 .ex_trig_analog = 1,
898f5191 290 .dio_nchan = 32,
eedf4299 291 .has_counter = 1,
8c355509
HS
292 },
293 [BOARD_ME4670IS] = {
035d432a 294 .name = "ME-4670is",
2d504528 295 .ao_nchan = 4,
6ba8dfef
HS
296 .ai_nchan = 32,
297 .ai_diff_nchan = 16,
298 .ai_sh_nchan = 8,
299 .ex_trig_analog = 1,
898f5191 300 .dio_nchan = 32,
eedf4299 301 .has_counter = 1,
8c355509
HS
302 },
303 [BOARD_ME4680] = {
035d432a 304 .name = "ME-4680",
2d504528
HS
305 .ao_nchan = 4,
306 .ao_fifo = 4,
6ba8dfef
HS
307 .ai_nchan = 32,
308 .ai_diff_nchan = 16,
309 .ex_trig_analog = 1,
898f5191 310 .dio_nchan = 32,
eedf4299 311 .has_counter = 1,
8c355509
HS
312 },
313 [BOARD_ME4680I] = {
035d432a 314 .name = "ME-4680i",
2d504528
HS
315 .ao_nchan = 4,
316 .ao_fifo = 4,
6ba8dfef
HS
317 .ai_nchan = 32,
318 .ai_diff_nchan = 16,
319 .ex_trig_analog = 1,
898f5191 320 .dio_nchan = 32,
eedf4299 321 .has_counter = 1,
8c355509
HS
322 },
323 [BOARD_ME4680S] = {
035d432a 324 .name = "ME-4680s",
2d504528
HS
325 .ao_nchan = 4,
326 .ao_fifo = 4,
6ba8dfef
HS
327 .ai_nchan = 32,
328 .ai_diff_nchan = 16,
329 .ai_sh_nchan = 8,
330 .ex_trig_analog = 1,
898f5191 331 .dio_nchan = 32,
eedf4299 332 .has_counter = 1,
8c355509
HS
333 },
334 [BOARD_ME4680IS] = {
035d432a 335 .name = "ME-4680is",
2d504528
HS
336 .ao_nchan = 4,
337 .ao_fifo = 4,
6ba8dfef
HS
338 .ai_nchan = 32,
339 .ai_diff_nchan = 16,
340 .ai_sh_nchan = 8,
341 .ex_trig_analog = 1,
898f5191 342 .dio_nchan = 32,
eedf4299 343 .has_counter = 1,
035d432a 344 },
e55c95a3
GG
345};
346
9ced1de6 347static const struct comedi_lrange me4000_ai_range = {
e55c95a3
GG
348 4,
349 {
0a85b6f0
MT
350 UNI_RANGE(2.5),
351 UNI_RANGE(10),
352 BIP_RANGE(2.5),
353 BIP_RANGE(10),
354 }
e55c95a3
GG
355};
356
e55c95a3
GG
357#define FIRMWARE_NOT_AVAILABLE 1
358#if FIRMWARE_NOT_AVAILABLE
359extern unsigned char *xilinx_firm;
360#endif
361
71b5f4f1 362static int xilinx_download(struct comedi_device *dev)
e55c95a3 363{
fe531d12 364 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
09253b39 365 struct me4000_info *info = dev->private;
fe531d12 366 unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
e55c95a3
GG
367 u32 value = 0;
368 wait_queue_head_t queue;
369 int idx = 0;
370 int size = 0;
58af6b92 371 unsigned int intcsr;
e55c95a3 372
fe531d12
HS
373 if (!xilinx_iobase)
374 return -ENODEV;
375
e55c95a3
GG
376 init_waitqueue_head(&queue);
377
378 /*
379 * Set PLX local interrupt 2 polarity to high.
380 * Interrupt is thrown by init pin of xilinx.
381 */
58af6b92 382 outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
e55c95a3
GG
383
384 /* Set /CS and /WRITE of the Xilinx */
385 value = inl(info->plx_regbase + PLX_ICR);
386 value |= 0x100;
387 outl(value, info->plx_regbase + PLX_ICR);
388
389 /* Init Xilinx with CS1 */
fe531d12 390 inb(xilinx_iobase + 0xC8);
e55c95a3
GG
391
392 /* Wait until /INIT pin is set */
393 udelay(20);
58af6b92
HS
394 intcsr = inl(info->plx_regbase + PLX9052_INTCSR);
395 if (!(intcsr & PLX9052_INTCSR_LI2STAT)) {
5da80ee8 396 dev_err(dev->class_dev, "Can't init Xilinx\n");
e55c95a3
GG
397 return -EIO;
398 }
399
400 /* Reset /CS and /WRITE of the Xilinx */
401 value = inl(info->plx_regbase + PLX_ICR);
402 value &= ~0x100;
403 outl(value, info->plx_regbase + PLX_ICR);
404 if (FIRMWARE_NOT_AVAILABLE) {
5da80ee8
HS
405 dev_err(dev->class_dev,
406 "xilinx firmware unavailable due to licensing, aborting");
e55c95a3
GG
407 return -EIO;
408 } else {
409 /* Download Xilinx firmware */
410 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
0a85b6f0 411 (xilinx_firm[2] << 8) + xilinx_firm[3];
e55c95a3
GG
412 udelay(10);
413
414 for (idx = 0; idx < size; idx++) {
fe531d12 415 outb(xilinx_firm[16 + idx], xilinx_iobase);
e55c95a3
GG
416 udelay(10);
417
418 /* Check if BUSY flag is low */
419 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
5da80ee8
HS
420 dev_err(dev->class_dev,
421 "Xilinx is still busy (idx = %d)\n",
422 idx);
e55c95a3
GG
423 return -EIO;
424 }
425 }
426 }
427
428 /* If done flag is high download was successful */
429 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
430 } else {
5da80ee8
HS
431 dev_err(dev->class_dev, "DONE flag is not set\n");
432 dev_err(dev->class_dev, "Download not successful\n");
e55c95a3
GG
433 return -EIO;
434 }
435
436 /* Set /CS and /WRITE */
437 value = inl(info->plx_regbase + PLX_ICR);
438 value |= 0x100;
439 outl(value, info->plx_regbase + PLX_ICR);
440
441 return 0;
442}
443
2f348ecd 444static void me4000_reset(struct comedi_device *dev)
e55c95a3 445{
09253b39 446 struct me4000_info *info = dev->private;
e1d7ccb7
HS
447 unsigned long val;
448 int chan;
e55c95a3 449
e55c95a3 450 /* Make a hardware reset */
e1d7ccb7
HS
451 val = inl(info->plx_regbase + PLX_ICR);
452 val |= 0x40000000;
453 outl(val, info->plx_regbase + PLX_ICR);
454 val &= ~0x40000000;
455 outl(val , info->plx_regbase + PLX_ICR);
e55c95a3
GG
456
457 /* 0x8000 to the DACs means an output voltage of 0V */
e1d7ccb7
HS
458 for (chan = 0; chan < 4; chan++)
459 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
e55c95a3
GG
460
461 /* Set both stop bits in the analog input control register */
d6cbe537 462 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
362bcbde 463 dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
464
465 /* Set both stop bits in the analog output control register */
e1d7ccb7
HS
466 val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
467 for (chan = 0; chan < 4; chan++)
468 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
469
470 /* Enable interrupts on the PLX */
58af6b92
HS
471 outl(PLX9052_INTCSR_LI1ENAB |
472 PLX9052_INTCSR_LI1POL |
473 PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR);
e55c95a3
GG
474
475 /* Set the adustment register for AO demux */
d6cbe537 476 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
362bcbde 477 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
e55c95a3 478
b6241fda
GS
479 /*
480 * Set digital I/O direction for port 0
481 * to output on isolated versions
482 */
362bcbde
HS
483 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
484 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
e55c95a3
GG
485}
486
e55c95a3
GG
487/*=============================================================================
488 Analog input section
489 ===========================================================================*/
490
71b5f4f1 491static int me4000_ai_insn_read(struct comedi_device *dev,
0a85b6f0
MT
492 struct comedi_subdevice *subdevice,
493 struct comedi_insn *insn, unsigned int *data)
e55c95a3 494{
8407593a 495 const struct me4000_board *thisboard = comedi_board(dev);
e55c95a3
GG
496 int chan = CR_CHAN(insn->chanspec);
497 int rang = CR_RANGE(insn->chanspec);
498 int aref = CR_AREF(insn->chanspec);
499
500 unsigned long entry = 0;
501 unsigned long tmp;
502 long lval;
503
e55c95a3
GG
504 if (insn->n == 0) {
505 return 0;
506 } else if (insn->n > 1) {
5da80ee8
HS
507 dev_err(dev->class_dev, "Invalid instruction length %d\n",
508 insn->n);
e55c95a3
GG
509 return -EINVAL;
510 }
511
512 switch (rang) {
513 case 0:
514 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
515 break;
516 case 1:
517 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
518 break;
519 case 2:
520 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
521 break;
522 case 3:
523 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
524 break;
525 default:
5da80ee8 526 dev_err(dev->class_dev, "Invalid range specified\n");
e55c95a3
GG
527 return -EINVAL;
528 }
529
530 switch (aref) {
531 case AREF_GROUND:
532 case AREF_COMMON:
6ba8dfef 533 if (chan >= thisboard->ai_nchan) {
5da80ee8
HS
534 dev_err(dev->class_dev,
535 "Analog input is not available\n");
e55c95a3
GG
536 return -EINVAL;
537 }
538 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
539 break;
540
541 case AREF_DIFF:
542 if (rang == 0 || rang == 1) {
5da80ee8
HS
543 dev_err(dev->class_dev,
544 "Range must be bipolar when aref = diff\n");
e55c95a3
GG
545 return -EINVAL;
546 }
547
6ba8dfef 548 if (chan >= thisboard->ai_diff_nchan) {
5da80ee8
HS
549 dev_err(dev->class_dev,
550 "Analog input is not available\n");
e55c95a3
GG
551 return -EINVAL;
552 }
553 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
554 break;
555 default:
5da80ee8 556 dev_err(dev->class_dev, "Invalid aref specified\n");
e55c95a3
GG
557 return -EINVAL;
558 }
559
560 entry |= ME4000_AI_LIST_LAST_ENTRY;
561
562 /* Clear channel list, data fifo and both stop bits */
b08bfa38 563 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 564 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
0a85b6f0
MT
565 ME4000_AI_CTRL_BIT_DATA_FIFO |
566 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
b08bfa38 567 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
568
569 /* Set the acquisition mode to single */
570 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
0a85b6f0 571 ME4000_AI_CTRL_BIT_MODE_2);
b08bfa38 572 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
573
574 /* Enable channel list and data fifo */
575 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
b08bfa38 576 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
577
578 /* Generate channel list entry */
b08bfa38 579 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
e55c95a3
GG
580
581 /* Set the timer to maximum sample rate */
b08bfa38
HS
582 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
583 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
e55c95a3
GG
584
585 /* Start conversion by dummy read */
b08bfa38 586 inl(dev->iobase + ME4000_AI_START_REG);
e55c95a3
GG
587
588 /* Wait until ready */
589 udelay(10);
b08bfa38 590 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
0a85b6f0 591 ME4000_AI_STATUS_BIT_EF_DATA)) {
5da80ee8 592 dev_err(dev->class_dev, "Value not available after wait\n");
e55c95a3
GG
593 return -EIO;
594 }
595
596 /* Read value from data fifo */
b08bfa38 597 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
e55c95a3
GG
598 data[0] = lval ^ 0x8000;
599
600 return 1;
601}
602
0a85b6f0
MT
603static int me4000_ai_cancel(struct comedi_device *dev,
604 struct comedi_subdevice *s)
e55c95a3
GG
605{
606 unsigned long tmp;
607
e55c95a3 608 /* Stop any running conversion */
b08bfa38 609 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 610 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
b08bfa38 611 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
612
613 /* Clear the control register */
b08bfa38 614 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
615
616 return 0;
617}
618
71b5f4f1 619static int ai_check_chanlist(struct comedi_device *dev,
0a85b6f0 620 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e55c95a3 621{
8407593a 622 const struct me4000_board *thisboard = comedi_board(dev);
e55c95a3
GG
623 int aref;
624 int i;
625
e55c95a3
GG
626 /* Check whether a channel list is available */
627 if (!cmd->chanlist_len) {
5da80ee8 628 dev_err(dev->class_dev, "No channel list available\n");
e55c95a3
GG
629 return -EINVAL;
630 }
631
632 /* Check the channel list size */
633 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
5da80ee8 634 dev_err(dev->class_dev, "Channel list is to large\n");
e55c95a3
GG
635 return -EINVAL;
636 }
637
638 /* Check the pointer */
639 if (!cmd->chanlist) {
5da80ee8 640 dev_err(dev->class_dev, "NULL pointer to channel list\n");
e55c95a3
GG
641 return -EFAULT;
642 }
643
644 /* Check whether aref is equal for all entries */
645 aref = CR_AREF(cmd->chanlist[0]);
646 for (i = 0; i < cmd->chanlist_len; i++) {
647 if (CR_AREF(cmd->chanlist[i]) != aref) {
5da80ee8
HS
648 dev_err(dev->class_dev,
649 "Mode is not equal for all entries\n");
e55c95a3
GG
650 return -EINVAL;
651 }
652 }
653
654 /* Check whether channels are available for this ending */
655 if (aref == SDF_DIFF) {
656 for (i = 0; i < cmd->chanlist_len; i++) {
657 if (CR_CHAN(cmd->chanlist[i]) >=
6ba8dfef 658 thisboard->ai_diff_nchan) {
5da80ee8
HS
659 dev_err(dev->class_dev,
660 "Channel number to high\n");
e55c95a3
GG
661 return -EINVAL;
662 }
663 }
664 } else {
665 for (i = 0; i < cmd->chanlist_len; i++) {
6ba8dfef 666 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
5da80ee8
HS
667 dev_err(dev->class_dev,
668 "Channel number to high\n");
e55c95a3
GG
669 return -EINVAL;
670 }
671 }
672 }
673
674 /* Check if bipolar is set for all entries when in differential mode */
675 if (aref == SDF_DIFF) {
676 for (i = 0; i < cmd->chanlist_len; i++) {
677 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
0a85b6f0 678 CR_RANGE(cmd->chanlist[i]) != 2) {
5da80ee8
HS
679 dev_err(dev->class_dev,
680 "Bipolar is not selected in differential mode\n");
e55c95a3
GG
681 return -EINVAL;
682 }
683 }
684 }
685
686 return 0;
687}
688
71b5f4f1 689static int ai_round_cmd_args(struct comedi_device *dev,
0a85b6f0
MT
690 struct comedi_subdevice *s,
691 struct comedi_cmd *cmd,
692 unsigned int *init_ticks,
693 unsigned int *scan_ticks, unsigned int *chan_ticks)
e55c95a3
GG
694{
695
696 int rest;
697
e55c95a3
GG
698 *init_ticks = 0;
699 *scan_ticks = 0;
700 *chan_ticks = 0;
701
e55c95a3
GG
702 if (cmd->start_arg) {
703 *init_ticks = (cmd->start_arg * 33) / 1000;
704 rest = (cmd->start_arg * 33) % 1000;
705
91211dd1 706 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
82675f35 707 if (rest > 33)
e55c95a3 708 (*init_ticks)++;
91211dd1 709 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
e55c95a3
GG
710 if (rest)
711 (*init_ticks)++;
712 }
713 }
714
715 if (cmd->scan_begin_arg) {
716 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
717 rest = (cmd->scan_begin_arg * 33) % 1000;
718
91211dd1 719 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
82675f35 720 if (rest > 33)
e55c95a3 721 (*scan_ticks)++;
91211dd1 722 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
e55c95a3
GG
723 if (rest)
724 (*scan_ticks)++;
725 }
726 }
727
728 if (cmd->convert_arg) {
729 *chan_ticks = (cmd->convert_arg * 33) / 1000;
730 rest = (cmd->convert_arg * 33) % 1000;
731
91211dd1 732 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
82675f35 733 if (rest > 33)
e55c95a3 734 (*chan_ticks)++;
91211dd1 735 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
e55c95a3
GG
736 if (rest)
737 (*chan_ticks)++;
738 }
739 }
740
e55c95a3
GG
741 return 0;
742}
743
71b5f4f1 744static void ai_write_timer(struct comedi_device *dev,
0a85b6f0
MT
745 unsigned int init_ticks,
746 unsigned int scan_ticks, unsigned int chan_ticks)
e55c95a3 747{
b08bfa38
HS
748 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
749 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
e55c95a3
GG
750
751 if (scan_ticks) {
b08bfa38
HS
752 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
753 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
e55c95a3
GG
754 }
755
b08bfa38
HS
756 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
757 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
e55c95a3
GG
758}
759
4b2f15f1
HS
760static int ai_write_chanlist(struct comedi_device *dev,
761 struct comedi_subdevice *s, struct comedi_cmd *cmd)
762{
763 unsigned int entry;
764 unsigned int chan;
765 unsigned int rang;
766 unsigned int aref;
767 int i;
768
769 for (i = 0; i < cmd->chanlist_len; i++) {
770 chan = CR_CHAN(cmd->chanlist[i]);
771 rang = CR_RANGE(cmd->chanlist[i]);
772 aref = CR_AREF(cmd->chanlist[i]);
773
774 entry = chan;
775
776 if (rang == 0)
777 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
778 else if (rang == 1)
779 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
780 else if (rang == 2)
781 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
782 else
783 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
784
785 if (aref == SDF_DIFF)
786 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
787 else
788 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
789
790 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
791 }
792
793 return 0;
794}
795
71b5f4f1 796static int ai_prepare(struct comedi_device *dev,
0a85b6f0
MT
797 struct comedi_subdevice *s,
798 struct comedi_cmd *cmd,
799 unsigned int init_ticks,
800 unsigned int scan_ticks, unsigned int chan_ticks)
e55c95a3
GG
801{
802
803 unsigned long tmp = 0;
804
e55c95a3
GG
805 /* Write timer arguments */
806 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
807
808 /* Reset control register */
b08bfa38 809 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
810
811 /* Start sources */
812 if ((cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
813 cmd->scan_begin_src == TRIG_TIMER &&
814 cmd->convert_src == TRIG_TIMER) ||
815 (cmd->start_src == TRIG_EXT &&
816 cmd->scan_begin_src == TRIG_FOLLOW &&
817 cmd->convert_src == TRIG_TIMER)) {
e55c95a3 818 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
0a85b6f0
MT
819 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
820 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3 821 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
822 cmd->scan_begin_src == TRIG_EXT &&
823 cmd->convert_src == TRIG_TIMER) {
e55c95a3 824 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
0a85b6f0
MT
825 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
826 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3 827 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
828 cmd->scan_begin_src == TRIG_EXT &&
829 cmd->convert_src == TRIG_EXT) {
e55c95a3 830 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
0a85b6f0
MT
831 ME4000_AI_CTRL_BIT_MODE_1 |
832 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
833 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3
GG
834 } else {
835 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
0a85b6f0
MT
836 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
837 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3
GG
838 }
839
840 /* Stop triggers */
841 if (cmd->stop_src == TRIG_COUNT) {
d6cbe537 842 outl(cmd->chanlist_len * cmd->stop_arg,
b08bfa38 843 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
e55c95a3
GG
844 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
845 } else if (cmd->stop_src == TRIG_NONE &&
0a85b6f0 846 cmd->scan_end_src == TRIG_COUNT) {
d6cbe537 847 outl(cmd->scan_end_arg,
b08bfa38 848 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
e55c95a3
GG
849 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
850 } else {
851 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
852 }
853
854 /* Write the setup to the control register */
b08bfa38 855 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
856
857 /* Write the channel list */
858 ai_write_chanlist(dev, s, cmd);
859
860 return 0;
861}
862
0a85b6f0
MT
863static int me4000_ai_do_cmd(struct comedi_device *dev,
864 struct comedi_subdevice *s)
e55c95a3
GG
865{
866 int err;
867 unsigned int init_ticks = 0;
868 unsigned int scan_ticks = 0;
869 unsigned int chan_ticks = 0;
ea6d0d4c 870 struct comedi_cmd *cmd = &s->async->cmd;
e55c95a3 871
e55c95a3
GG
872 /* Reset the analog input */
873 err = me4000_ai_cancel(dev, s);
874 if (err)
875 return err;
876
877 /* Round the timer arguments */
878 err = ai_round_cmd_args(dev,
0a85b6f0 879 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
e55c95a3
GG
880 if (err)
881 return err;
882
883 /* Prepare the AI for acquisition */
884 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
885 if (err)
886 return err;
887
888 /* Start acquistion by dummy read */
b08bfa38 889 inl(dev->iobase + ME4000_AI_START_REG);
e55c95a3
GG
890
891 return 0;
892}
893
71b5f4f1 894static int me4000_ai_do_cmd_test(struct comedi_device *dev,
0a85b6f0
MT
895 struct comedi_subdevice *s,
896 struct comedi_cmd *cmd)
e55c95a3
GG
897{
898
899 unsigned int init_ticks;
900 unsigned int chan_ticks;
901 unsigned int scan_ticks;
902 int err = 0;
903
e55c95a3
GG
904 /* Only rounding flags are implemented */
905 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
906
907 /* Round the timer arguments */
908 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
909
27020ffe
HS
910 /* Step 1 : check if triggers are trivially valid */
911
912 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
913 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
914 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
915 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
916 err |= cfc_check_trigger_src(&cmd->scan_end_src,
917 TRIG_NONE | TRIG_COUNT);
918 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
919
82675f35 920 if (err)
e55c95a3 921 return 1;
e55c95a3 922
27020ffe
HS
923 /* Step 2a : make sure trigger sources are unique */
924
925 err |= cfc_check_trigger_is_unique(cmd->start_src);
926 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
927 err |= cfc_check_trigger_is_unique(cmd->convert_src);
928 err |= cfc_check_trigger_is_unique(cmd->scan_end_src);
929 err |= cfc_check_trigger_is_unique(cmd->stop_src);
930
931 /* Step 2b : and mutually compatible */
932
e55c95a3 933 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
934 cmd->scan_begin_src == TRIG_TIMER &&
935 cmd->convert_src == TRIG_TIMER) {
e55c95a3 936 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
937 cmd->scan_begin_src == TRIG_FOLLOW &&
938 cmd->convert_src == TRIG_TIMER) {
e55c95a3 939 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
940 cmd->scan_begin_src == TRIG_TIMER &&
941 cmd->convert_src == TRIG_TIMER) {
e55c95a3 942 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
943 cmd->scan_begin_src == TRIG_FOLLOW &&
944 cmd->convert_src == TRIG_TIMER) {
e55c95a3 945 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
946 cmd->scan_begin_src == TRIG_EXT &&
947 cmd->convert_src == TRIG_TIMER) {
e55c95a3 948 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
949 cmd->scan_begin_src == TRIG_EXT &&
950 cmd->convert_src == TRIG_EXT) {
e55c95a3 951 } else {
27020ffe 952 err |= -EINVAL;
e55c95a3
GG
953 }
954
955 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
956 } else if (cmd->stop_src == TRIG_COUNT &&
0a85b6f0 957 cmd->scan_end_src == TRIG_NONE) {
e55c95a3 958 } else if (cmd->stop_src == TRIG_NONE &&
0a85b6f0 959 cmd->scan_end_src == TRIG_COUNT) {
e55c95a3 960 } else if (cmd->stop_src == TRIG_COUNT &&
0a85b6f0 961 cmd->scan_end_src == TRIG_COUNT) {
e55c95a3 962 } else {
27020ffe 963 err |= -EINVAL;
e55c95a3 964 }
27020ffe 965
82675f35 966 if (err)
e55c95a3 967 return 2;
e55c95a3 968
8c6c5a69
HS
969 /* Step 3: check if arguments are trivially valid */
970
e55c95a3 971 if (cmd->chanlist_len < 1) {
e55c95a3 972 cmd->chanlist_len = 1;
8c6c5a69 973 err |= -EINVAL;
e55c95a3
GG
974 }
975 if (init_ticks < 66) {
e55c95a3 976 cmd->start_arg = 2000;
8c6c5a69 977 err |= -EINVAL;
e55c95a3
GG
978 }
979 if (scan_ticks && scan_ticks < 67) {
e55c95a3 980 cmd->scan_begin_arg = 2031;
8c6c5a69 981 err |= -EINVAL;
e55c95a3
GG
982 }
983 if (chan_ticks < 66) {
e55c95a3 984 cmd->convert_arg = 2000;
8c6c5a69 985 err |= -EINVAL;
e55c95a3 986 }
82675f35
BP
987
988 if (err)
e55c95a3 989 return 3;
e55c95a3
GG
990
991 /*
992 * Stage 4. Check for argument conflicts.
993 */
994 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
995 cmd->scan_begin_src == TRIG_TIMER &&
996 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
997
998 /* Check timer arguments */
999 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1000 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1001 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1002 err++;
1003 }
1004 if (chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1005 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 1006 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1007 err++;
1008 }
1009 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
5da80ee8 1010 dev_err(dev->class_dev, "Invalid scan end arg\n");
b6241fda
GS
1011
1012 /* At least one tick more */
1013 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
e55c95a3
GG
1014 err++;
1015 }
1016 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
1017 cmd->scan_begin_src == TRIG_FOLLOW &&
1018 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1019
1020 /* Check timer arguments */
1021 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1022 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1023 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1024 err++;
1025 }
1026 if (chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1027 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 1028 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1029 err++;
1030 }
1031 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1032 cmd->scan_begin_src == TRIG_TIMER &&
1033 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1034
1035 /* Check timer arguments */
1036 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1037 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1038 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1039 err++;
1040 }
1041 if (chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1042 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 1043 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1044 err++;
1045 }
1046 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
5da80ee8 1047 dev_err(dev->class_dev, "Invalid scan end arg\n");
b6241fda
GS
1048
1049 /* At least one tick more */
1050 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
e55c95a3
GG
1051 err++;
1052 }
1053 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1054 cmd->scan_begin_src == TRIG_FOLLOW &&
1055 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1056
1057 /* Check timer arguments */
1058 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1059 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1060 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1061 err++;
1062 }
1063 if (chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1064 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 1065 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1066 err++;
1067 }
1068 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1069 cmd->scan_begin_src == TRIG_EXT &&
1070 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1071
1072 /* Check timer arguments */
1073 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1074 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1075 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1076 err++;
1077 }
1078 if (chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1079 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 1080 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1081 err++;
1082 }
1083 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1084 cmd->scan_begin_src == TRIG_EXT &&
1085 cmd->convert_src == TRIG_EXT) {
e55c95a3
GG
1086
1087 /* Check timer arguments */
1088 if (init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 1089 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 1090 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1091 err++;
1092 }
1093 }
1094 if (cmd->stop_src == TRIG_COUNT) {
1095 if (cmd->stop_arg == 0) {
5da80ee8 1096 dev_err(dev->class_dev, "Invalid stop arg\n");
e55c95a3
GG
1097 cmd->stop_arg = 1;
1098 err++;
1099 }
1100 }
1101 if (cmd->scan_end_src == TRIG_COUNT) {
1102 if (cmd->scan_end_arg == 0) {
5da80ee8 1103 dev_err(dev->class_dev, "Invalid scan end arg\n");
e55c95a3
GG
1104 cmd->scan_end_arg = 1;
1105 err++;
1106 }
1107 }
82675f35
BP
1108
1109 if (err)
e55c95a3 1110 return 4;
e55c95a3
GG
1111
1112 /*
1113 * Stage 5. Check the channel list.
1114 */
1115 if (ai_check_chanlist(dev, s, cmd))
1116 return 5;
1117
1118 return 0;
1119}
1120
70265d24 1121static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
e55c95a3
GG
1122{
1123 unsigned int tmp;
71b5f4f1 1124 struct comedi_device *dev = dev_id;
8aaf2717 1125 struct comedi_subdevice *s = &dev->subdevices[0];
e55c95a3
GG
1126 int i;
1127 int c = 0;
1128 long lval;
1129
ef5bbfcb 1130 if (!dev->attached)
e55c95a3 1131 return IRQ_NONE;
e55c95a3
GG
1132
1133 /* Reset all events */
1134 s->async->events = 0;
1135
1136 /* Check if irq number is right */
109daa79 1137 if (irq != dev->irq) {
5da80ee8 1138 dev_err(dev->class_dev, "Incorrect interrupt num: %d\n", irq);
e55c95a3
GG
1139 return IRQ_HANDLED;
1140 }
1141
b08bfa38 1142 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
0a85b6f0 1143 ME4000_IRQ_STATUS_BIT_AI_HF) {
e55c95a3 1144 /* Read status register to find out what happened */
b08bfa38 1145 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1146
1147 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
0a85b6f0
MT
1148 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1149 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
e55c95a3
GG
1150 c = ME4000_AI_FIFO_COUNT;
1151
b6241fda
GS
1152 /*
1153 * FIFO overflow, so stop conversion
1154 * and disable all interrupts
1155 */
e55c95a3
GG
1156 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1157 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1158 ME4000_AI_CTRL_BIT_SC_IRQ);
b08bfa38 1159 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1160
1161 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1162
5da80ee8 1163 dev_err(dev->class_dev, "FIFO overflow\n");
e55c95a3 1164 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
0a85b6f0
MT
1165 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1166 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
e55c95a3
GG
1167 s->async->events |= COMEDI_CB_BLOCK;
1168
1169 c = ME4000_AI_FIFO_COUNT / 2;
1170 } else {
5da80ee8
HS
1171 dev_err(dev->class_dev,
1172 "Can't determine state of fifo\n");
e55c95a3
GG
1173 c = 0;
1174
b6241fda
GS
1175 /*
1176 * Undefined state, so stop conversion
1177 * and disable all interrupts
1178 */
e55c95a3
GG
1179 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1180 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1181 ME4000_AI_CTRL_BIT_SC_IRQ);
b08bfa38 1182 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1183
1184 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1185
5da80ee8 1186 dev_err(dev->class_dev, "Undefined FIFO state\n");
e55c95a3
GG
1187 }
1188
e55c95a3
GG
1189 for (i = 0; i < c; i++) {
1190 /* Read value from data fifo */
b08bfa38 1191 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
e55c95a3
GG
1192 lval ^= 0x8000;
1193
1194 if (!comedi_buf_put(s->async, lval)) {
b6241fda
GS
1195 /*
1196 * Buffer overflow, so stop conversion
1197 * and disable all interrupts
1198 */
e55c95a3
GG
1199 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1200 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1201 ME4000_AI_CTRL_BIT_SC_IRQ);
b08bfa38 1202 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1203
1204 s->async->events |= COMEDI_CB_OVERFLOW;
1205
5da80ee8 1206 dev_err(dev->class_dev, "Buffer overflow\n");
e55c95a3
GG
1207
1208 break;
1209 }
1210 }
1211
1212 /* Work is done, so reset the interrupt */
e55c95a3 1213 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
b08bfa38 1214 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 1215 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
b08bfa38 1216 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1217 }
1218
b08bfa38
HS
1219 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1220 ME4000_IRQ_STATUS_BIT_SC) {
e55c95a3
GG
1221 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1222
b6241fda
GS
1223 /*
1224 * Acquisition is complete, so stop
1225 * conversion and disable all interrupts
1226 */
b08bfa38 1227 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1228 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1229 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
b08bfa38 1230 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1231
1232 /* Poll data until fifo empty */
b08bfa38
HS
1233 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1234 ME4000_AI_STATUS_BIT_EF_DATA) {
e55c95a3 1235 /* Read value from data fifo */
b08bfa38 1236 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
e55c95a3
GG
1237 lval ^= 0x8000;
1238
1239 if (!comedi_buf_put(s->async, lval)) {
5da80ee8 1240 dev_err(dev->class_dev, "Buffer overflow\n");
e55c95a3
GG
1241 s->async->events |= COMEDI_CB_OVERFLOW;
1242 break;
1243 }
1244 }
1245
1246 /* Work is done, so reset the interrupt */
e55c95a3 1247 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
b08bfa38 1248 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 1249 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
b08bfa38 1250 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1251 }
1252
e55c95a3
GG
1253 if (s->async->events)
1254 comedi_event(dev, s);
1255
1256 return IRQ_HANDLED;
1257}
1258
1259/*=============================================================================
1260 Analog output section
1261 ===========================================================================*/
1262
71b5f4f1 1263static int me4000_ao_insn_write(struct comedi_device *dev,
0a85b6f0
MT
1264 struct comedi_subdevice *s,
1265 struct comedi_insn *insn, unsigned int *data)
e55c95a3 1266{
8407593a 1267 const struct me4000_board *thisboard = comedi_board(dev);
09253b39 1268 struct me4000_info *info = dev->private;
e55c95a3
GG
1269 int chan = CR_CHAN(insn->chanspec);
1270 int rang = CR_RANGE(insn->chanspec);
1271 int aref = CR_AREF(insn->chanspec);
1272 unsigned long tmp;
1273
e55c95a3
GG
1274 if (insn->n == 0) {
1275 return 0;
1276 } else if (insn->n > 1) {
5da80ee8
HS
1277 dev_err(dev->class_dev, "Invalid instruction length %d\n",
1278 insn->n);
e55c95a3
GG
1279 return -EINVAL;
1280 }
1281
2d504528 1282 if (chan >= thisboard->ao_nchan) {
5da80ee8 1283 dev_err(dev->class_dev, "Invalid channel %d\n", insn->n);
e55c95a3
GG
1284 return -EINVAL;
1285 }
1286
1287 if (rang != 0) {
5da80ee8 1288 dev_err(dev->class_dev, "Invalid range %d\n", insn->n);
e55c95a3
GG
1289 return -EINVAL;
1290 }
1291
1292 if (aref != AREF_GROUND && aref != AREF_COMMON) {
5da80ee8 1293 dev_err(dev->class_dev, "Invalid aref %d\n", insn->n);
e55c95a3
GG
1294 return -EINVAL;
1295 }
1296
1297 /* Stop any running conversion */
e1d7ccb7 1298 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3 1299 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
e1d7ccb7 1300 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
1301
1302 /* Clear control register and set to single mode */
e1d7ccb7 1303 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
1304
1305 /* Write data value */
e1d7ccb7 1306 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
e55c95a3
GG
1307
1308 /* Store in the mirror */
e1d7ccb7 1309 info->ao_readback[chan] = data[0];
e55c95a3
GG
1310
1311 return 1;
1312}
1313
71b5f4f1 1314static int me4000_ao_insn_read(struct comedi_device *dev,
0a85b6f0
MT
1315 struct comedi_subdevice *s,
1316 struct comedi_insn *insn, unsigned int *data)
e55c95a3 1317{
09253b39 1318 struct me4000_info *info = dev->private;
e55c95a3
GG
1319 int chan = CR_CHAN(insn->chanspec);
1320
1321 if (insn->n == 0) {
1322 return 0;
1323 } else if (insn->n > 1) {
5da80ee8 1324 dev_err(dev->class_dev, "Invalid instruction length\n");
e55c95a3
GG
1325 return -EINVAL;
1326 }
1327
e1d7ccb7 1328 data[0] = info->ao_readback[chan];
e55c95a3
GG
1329
1330 return 1;
1331}
1332
1333/*=============================================================================
1334 Digital I/O section
1335 ===========================================================================*/
1336
71b5f4f1 1337static int me4000_dio_insn_bits(struct comedi_device *dev,
0a85b6f0
MT
1338 struct comedi_subdevice *s,
1339 struct comedi_insn *insn, unsigned int *data)
e55c95a3 1340{
e55c95a3
GG
1341 /*
1342 * The insn data consists of a mask in data[0] and the new data
1343 * in data[1]. The mask defines which bits we are concerning about.
1344 * The new data must be anded with the mask.
1345 * Each channel corresponds to a bit.
1346 */
1347 if (data[0]) {
1348 /* Check if requested ports are configured for output */
1349 if ((s->io_bits & data[0]) != data[0])
1350 return -EIO;
1351
1352 s->state &= ~data[0];
1353 s->state |= data[0] & data[1];
1354
1355 /* Write out the new digital output lines */
d6cbe537 1356 outl((s->state >> 0) & 0xFF,
da755d15 1357 dev->iobase + ME4000_DIO_PORT_0_REG);
d6cbe537 1358 outl((s->state >> 8) & 0xFF,
da755d15 1359 dev->iobase + ME4000_DIO_PORT_1_REG);
d6cbe537 1360 outl((s->state >> 16) & 0xFF,
da755d15 1361 dev->iobase + ME4000_DIO_PORT_2_REG);
d6cbe537 1362 outl((s->state >> 24) & 0xFF,
da755d15 1363 dev->iobase + ME4000_DIO_PORT_3_REG);
e55c95a3
GG
1364 }
1365
1366 /* On return, data[1] contains the value of
1367 the digital input and output lines. */
da755d15
HS
1368 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1369 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1370 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1371 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
e55c95a3 1372
a2714e3e 1373 return insn->n;
e55c95a3
GG
1374}
1375
71b5f4f1 1376static int me4000_dio_insn_config(struct comedi_device *dev,
0a85b6f0
MT
1377 struct comedi_subdevice *s,
1378 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
1379{
1380 unsigned long tmp;
1381 int chan = CR_CHAN(insn->chanspec);
1382
f3445c1e
IA
1383 switch (data[0]) {
1384 default:
1385 return -EINVAL;
1386 case INSN_CONFIG_DIO_QUERY:
e55c95a3 1387 data[1] =
0a85b6f0 1388 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
e55c95a3 1389 return insn->n;
f3445c1e
IA
1390 case INSN_CONFIG_DIO_INPUT:
1391 case INSN_CONFIG_DIO_OUTPUT:
1392 break;
e55c95a3
GG
1393 }
1394
1395 /*
1396 * The input or output configuration of each digital line is
1397 * configured by a special insn_config instruction. chanspec
1398 * contains the channel to be changed, and data[0] contains the
f3445c1e 1399 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
e55c95a3
GG
1400 * On the ME-4000 it is only possible to switch port wise (8 bit)
1401 */
1402
da755d15 1403 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
e55c95a3 1404
f3445c1e 1405 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
e55c95a3
GG
1406 if (chan < 8) {
1407 s->io_bits |= 0xFF;
1408 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
0a85b6f0 1409 ME4000_DIO_CTRL_BIT_MODE_1);
e55c95a3
GG
1410 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1411 } else if (chan < 16) {
1412 /*
b6241fda
GS
1413 * Chech for optoisolated ME-4000 version.
1414 * If one the first port is a fixed output
1415 * port and the second is a fixed input port.
e55c95a3 1416 */
da755d15 1417 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
e55c95a3
GG
1418 return -ENODEV;
1419
1420 s->io_bits |= 0xFF00;
1421 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
0a85b6f0 1422 ME4000_DIO_CTRL_BIT_MODE_3);
e55c95a3
GG
1423 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1424 } else if (chan < 24) {
1425 s->io_bits |= 0xFF0000;
1426 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
0a85b6f0 1427 ME4000_DIO_CTRL_BIT_MODE_5);
e55c95a3
GG
1428 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1429 } else if (chan < 32) {
1430 s->io_bits |= 0xFF000000;
1431 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
0a85b6f0 1432 ME4000_DIO_CTRL_BIT_MODE_7);
e55c95a3
GG
1433 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1434 } else {
1435 return -EINVAL;
1436 }
1437 } else {
1438 if (chan < 8) {
1439 /*
b6241fda
GS
1440 * Chech for optoisolated ME-4000 version.
1441 * If one the first port is a fixed output
1442 * port and the second is a fixed input port.
e55c95a3 1443 */
da755d15 1444 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
e55c95a3
GG
1445 return -ENODEV;
1446
1447 s->io_bits &= ~0xFF;
1448 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
0a85b6f0 1449 ME4000_DIO_CTRL_BIT_MODE_1);
e55c95a3
GG
1450 } else if (chan < 16) {
1451 s->io_bits &= ~0xFF00;
1452 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
0a85b6f0 1453 ME4000_DIO_CTRL_BIT_MODE_3);
e55c95a3
GG
1454 } else if (chan < 24) {
1455 s->io_bits &= ~0xFF0000;
1456 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
0a85b6f0 1457 ME4000_DIO_CTRL_BIT_MODE_5);
e55c95a3
GG
1458 } else if (chan < 32) {
1459 s->io_bits &= ~0xFF000000;
1460 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
0a85b6f0 1461 ME4000_DIO_CTRL_BIT_MODE_7);
e55c95a3
GG
1462 } else {
1463 return -EINVAL;
1464 }
1465 }
1466
da755d15 1467 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
e55c95a3
GG
1468
1469 return 1;
1470}
1471
1472/*=============================================================================
1473 Counter section
1474 ===========================================================================*/
1475
71b5f4f1 1476static int me4000_cnt_insn_config(struct comedi_device *dev,
0a85b6f0 1477 struct comedi_subdevice *s,
83eef17c
HS
1478 struct comedi_insn *insn,
1479 unsigned int *data)
e55c95a3 1480{
83eef17c 1481 struct me4000_info *info = dev->private;
e55c95a3
GG
1482 int err;
1483
e55c95a3
GG
1484 switch (data[0]) {
1485 case GPCT_RESET:
83eef17c 1486 if (insn->n != 1)
e55c95a3 1487 return -EINVAL;
e55c95a3 1488
83eef17c
HS
1489 err = i8254_load(info->timer_regbase, 0, insn->chanspec, 0,
1490 I8254_MODE0 | I8254_BINARY);
e55c95a3
GG
1491 if (err)
1492 return err;
1493 break;
1494 case GPCT_SET_OPERATION:
83eef17c 1495 if (insn->n != 2)
e55c95a3 1496 return -EINVAL;
e55c95a3 1497
83eef17c
HS
1498 err = i8254_set_mode(info->timer_regbase, 0, insn->chanspec,
1499 (data[1] << 1) | I8254_BINARY);
e55c95a3
GG
1500 if (err)
1501 return err;
1502 break;
1503 default:
e55c95a3
GG
1504 return -EINVAL;
1505 }
1506
83eef17c 1507 return insn->n;
e55c95a3
GG
1508}
1509
71b5f4f1 1510static int me4000_cnt_insn_read(struct comedi_device *dev,
0a85b6f0
MT
1511 struct comedi_subdevice *s,
1512 struct comedi_insn *insn, unsigned int *data)
e55c95a3 1513{
09253b39 1514 struct me4000_info *info = dev->private;
e55c95a3 1515
82675f35 1516 if (insn->n == 0)
e55c95a3 1517 return 0;
82675f35 1518
e55c95a3 1519 if (insn->n > 1) {
5da80ee8
HS
1520 dev_err(dev->class_dev, "Invalid instruction length %d\n",
1521 insn->n);
e55c95a3
GG
1522 return -EINVAL;
1523 }
1524
db9132e0 1525 data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec);
e55c95a3
GG
1526
1527 return 1;
1528}
1529
71b5f4f1 1530static int me4000_cnt_insn_write(struct comedi_device *dev,
0a85b6f0
MT
1531 struct comedi_subdevice *s,
1532 struct comedi_insn *insn, unsigned int *data)
e55c95a3 1533{
09253b39 1534 struct me4000_info *info = dev->private;
e55c95a3 1535
e55c95a3
GG
1536 if (insn->n == 0) {
1537 return 0;
1538 } else if (insn->n > 1) {
5da80ee8
HS
1539 dev_err(dev->class_dev, "Invalid instruction length %d\n",
1540 insn->n);
e55c95a3
GG
1541 return -EINVAL;
1542 }
1543
db9132e0 1544 i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]);
e55c95a3
GG
1545
1546 return 1;
1547}
1548
a690b7e5 1549static int me4000_auto_attach(struct comedi_device *dev,
8c355509 1550 unsigned long context)
ba5cb4ba 1551{
750af5e5 1552 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
8c355509 1553 const struct me4000_board *thisboard = NULL;
ba5cb4ba 1554 struct me4000_info *info;
ba5cb4ba
HS
1555 struct comedi_subdevice *s;
1556 int result;
4b2f15f1 1557
8c355509
HS
1558 if (context < ARRAY_SIZE(me4000_boards))
1559 thisboard = &me4000_boards[context];
5f8f8d43
HS
1560 if (!thisboard)
1561 return -ENODEV;
1562 dev->board_ptr = thisboard;
ba5cb4ba 1563 dev->board_name = thisboard->name;
4b2f15f1 1564
c34fa261
HS
1565 info = kzalloc(sizeof(*info), GFP_KERNEL);
1566 if (!info)
1567 return -ENOMEM;
1568 dev->private = info;
4b2f15f1 1569
818f569f 1570 result = comedi_pci_enable(dev);
ba5cb4ba
HS
1571 if (result)
1572 return result;
1573
1574 info->plx_regbase = pci_resource_start(pcidev, 1);
ba5cb4ba 1575 dev->iobase = pci_resource_start(pcidev, 2);
ba5cb4ba 1576 info->timer_regbase = pci_resource_start(pcidev, 3);
39780a1c 1577 if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
4b2f15f1
HS
1578 return -ENODEV;
1579
4b2f15f1
HS
1580 result = xilinx_download(dev);
1581 if (result)
1582 return result;
1583
2f348ecd 1584 me4000_reset(dev);
4b2f15f1 1585
8b6c5694
HS
1586 result = comedi_alloc_subdevices(dev, 4);
1587 if (result)
1588 return result;
3af09830
HS
1589
1590 /*=========================================================================
1591 Analog input subdevice
1592 ========================================================================*/
1593
8aaf2717 1594 s = &dev->subdevices[0];
3af09830 1595
6ba8dfef 1596 if (thisboard->ai_nchan) {
3af09830
HS
1597 s->type = COMEDI_SUBD_AI;
1598 s->subdev_flags =
1599 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
6ba8dfef 1600 s->n_chan = thisboard->ai_nchan;
3af09830
HS
1601 s->maxdata = 0xFFFF; /* 16 bit ADC */
1602 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1603 s->range_table = &me4000_ai_range;
1604 s->insn_read = me4000_ai_insn_read;
1605
b179748d
HS
1606 if (pcidev->irq > 0) {
1607 if (request_irq(pcidev->irq, me4000_ai_isr,
1608 IRQF_SHARED, dev->board_name, dev)) {
1609 dev_warn(dev->class_dev,
1610 "request_irq failed\n");
3af09830
HS
1611 } else {
1612 dev->read_subdev = s;
1613 s->subdev_flags |= SDF_CMD_READ;
1614 s->cancel = me4000_ai_cancel;
1615 s->do_cmdtest = me4000_ai_do_cmd_test;
1616 s->do_cmd = me4000_ai_do_cmd;
b179748d
HS
1617
1618 dev->irq = pcidev->irq;
3af09830
HS
1619 }
1620 } else {
b179748d 1621 dev_warn(dev->class_dev, "No interrupt available\n");
3af09830
HS
1622 }
1623 } else {
1624 s->type = COMEDI_SUBD_UNUSED;
1625 }
1626
1627 /*=========================================================================
1628 Analog output subdevice
1629 ========================================================================*/
1630
8aaf2717 1631 s = &dev->subdevices[1];
3af09830 1632
2d504528 1633 if (thisboard->ao_nchan) {
3af09830
HS
1634 s->type = COMEDI_SUBD_AO;
1635 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2d504528 1636 s->n_chan = thisboard->ao_nchan;
3af09830 1637 s->maxdata = 0xFFFF; /* 16 bit DAC */
4683f9f8 1638 s->range_table = &range_bipolar10;
3af09830
HS
1639 s->insn_write = me4000_ao_insn_write;
1640 s->insn_read = me4000_ao_insn_read;
1641 } else {
1642 s->type = COMEDI_SUBD_UNUSED;
1643 }
1644
1645 /*=========================================================================
1646 Digital I/O subdevice
1647 ========================================================================*/
1648
8aaf2717 1649 s = &dev->subdevices[2];
3af09830 1650
898f5191 1651 if (thisboard->dio_nchan) {
3af09830
HS
1652 s->type = COMEDI_SUBD_DIO;
1653 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
898f5191 1654 s->n_chan = thisboard->dio_nchan;
3af09830
HS
1655 s->maxdata = 1;
1656 s->range_table = &range_digital;
1657 s->insn_bits = me4000_dio_insn_bits;
1658 s->insn_config = me4000_dio_insn_config;
1659 } else {
1660 s->type = COMEDI_SUBD_UNUSED;
1661 }
1662
1663 /*
1664 * Check for optoisolated ME-4000 version. If one the first
1665 * port is a fixed output port and the second is a fixed input port.
1666 */
da755d15 1667 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
3af09830 1668 s->io_bits |= 0xFF;
da755d15
HS
1669 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1670 dev->iobase + ME4000_DIO_DIR_REG);
3af09830
HS
1671 }
1672
1673 /*=========================================================================
1674 Counter subdevice
1675 ========================================================================*/
1676
8aaf2717 1677 s = &dev->subdevices[3];
3af09830 1678
eedf4299 1679 if (thisboard->has_counter) {
3af09830
HS
1680 s->type = COMEDI_SUBD_COUNTER;
1681 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
eedf4299 1682 s->n_chan = 3;
3af09830
HS
1683 s->maxdata = 0xFFFF; /* 16 bit counters */
1684 s->insn_read = me4000_cnt_insn_read;
1685 s->insn_write = me4000_cnt_insn_write;
1686 s->insn_config = me4000_cnt_insn_config;
1687 } else {
1688 s->type = COMEDI_SUBD_UNUSED;
1689 }
1690
1691 return 0;
1692}
1693
484ecc95 1694static void me4000_detach(struct comedi_device *dev)
3af09830 1695{
b179748d
HS
1696 if (dev->irq)
1697 free_irq(dev->irq, dev);
7f072f54
HS
1698 if (dev->iobase)
1699 me4000_reset(dev);
1700 comedi_pci_disable(dev);
3af09830
HS
1701}
1702
75e6301b 1703static struct comedi_driver me4000_driver = {
3af09830
HS
1704 .driver_name = "me4000",
1705 .module = THIS_MODULE,
750af5e5 1706 .auto_attach = me4000_auto_attach,
3af09830
HS
1707 .detach = me4000_detach,
1708};
1709
a690b7e5 1710static int me4000_pci_probe(struct pci_dev *dev,
b8f4ac23 1711 const struct pci_device_id *id)
727b286b 1712{
b8f4ac23 1713 return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data);
727b286b
AT
1714}
1715
3af09830 1716static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
8c355509
HS
1717 { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 },
1718 { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 },
1719 { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I },
1720 { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S },
1721 { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS },
1722 { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 },
1723 { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I },
1724 { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S },
1725 { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS },
1726 { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 },
1727 { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I },
1728 { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S },
1729 { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS },
1730 { 0 }
3af09830
HS
1731};
1732MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1733
75e6301b
HS
1734static struct pci_driver me4000_pci_driver = {
1735 .name = "me4000",
3af09830 1736 .id_table = me4000_pci_table,
75e6301b 1737 .probe = me4000_pci_probe,
9901a4d7 1738 .remove = comedi_pci_auto_unconfig,
727b286b 1739};
75e6301b 1740module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
90f703d3
AT
1741
1742MODULE_AUTHOR("Comedi http://www.comedi.org");
1743MODULE_DESCRIPTION("Comedi low-level driver");
1744MODULE_LICENSE("GPL");