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