staging: comedi: me4000: absorb ai_prepare()
[deliverable/linux.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>
e55c95a3 44#include <linux/delay.h>
33782dd5 45#include <linux/interrupt.h>
e55c95a3 46
f2e8e285 47#include "../comedi_pci.h"
33782dd5 48
d92d39d9 49#include "comedi_8254.h"
58af6b92 50#include "plx9052.h"
81dd1811 51
ac584af5 52#define ME4000_FIRMWARE "me4000_firmware.bin"
e55c95a3 53
81dd1811
HS
54/*
55 * ME4000 Register map and bit defines
56 */
57#define ME4000_AO_CHAN(x) ((x) * 0x18)
58
59#define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x))
7e92a5eb
HS
60#define ME4000_AO_CTRL_MODE_0 BIT(0)
61#define ME4000_AO_CTRL_MODE_1 BIT(1)
62#define ME4000_AO_CTRL_STOP BIT(2)
63#define ME4000_AO_CTRL_ENABLE_FIFO BIT(3)
64#define ME4000_AO_CTRL_ENABLE_EX_TRIG BIT(4)
65#define ME4000_AO_CTRL_EX_TRIG_EDGE BIT(5)
66#define ME4000_AO_CTRL_IMMEDIATE_STOP BIT(7)
67#define ME4000_AO_CTRL_ENABLE_DO BIT(8)
68#define ME4000_AO_CTRL_ENABLE_IRQ BIT(9)
69#define ME4000_AO_CTRL_RESET_IRQ BIT(10)
81dd1811 70#define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x))
4831748e
HS
71#define ME4000_AO_STATUS_FSM BIT(0)
72#define ME4000_AO_STATUS_FF BIT(1)
73#define ME4000_AO_STATUS_HF BIT(2)
74#define ME4000_AO_STATUS_EF BIT(3)
81dd1811
HS
75#define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x))
76#define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x))
77#define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x))
78#define ME4000_AI_CTRL_REG 0x74
79#define ME4000_AI_STATUS_REG 0x74
da772ad9
HS
80#define ME4000_AI_CTRL_MODE_0 BIT(0)
81#define ME4000_AI_CTRL_MODE_1 BIT(1)
82#define ME4000_AI_CTRL_MODE_2 BIT(2)
83#define ME4000_AI_CTRL_SAMPLE_HOLD BIT(3)
84#define ME4000_AI_CTRL_IMMEDIATE_STOP BIT(4)
85#define ME4000_AI_CTRL_STOP BIT(5)
86#define ME4000_AI_CTRL_CHANNEL_FIFO BIT(6)
87#define ME4000_AI_CTRL_DATA_FIFO BIT(7)
88#define ME4000_AI_CTRL_FULLSCALE BIT(8)
89#define ME4000_AI_CTRL_OFFSET BIT(9)
90#define ME4000_AI_CTRL_EX_TRIG_ANALOG BIT(10)
91#define ME4000_AI_CTRL_EX_TRIG BIT(11)
92#define ME4000_AI_CTRL_EX_TRIG_FALLING BIT(12)
93#define ME4000_AI_CTRL_EX_IRQ BIT(13)
94#define ME4000_AI_CTRL_EX_IRQ_RESET BIT(14)
95#define ME4000_AI_CTRL_LE_IRQ BIT(15)
96#define ME4000_AI_CTRL_LE_IRQ_RESET BIT(16)
97#define ME4000_AI_CTRL_HF_IRQ BIT(17)
98#define ME4000_AI_CTRL_HF_IRQ_RESET BIT(18)
99#define ME4000_AI_CTRL_SC_IRQ BIT(19)
100#define ME4000_AI_CTRL_SC_IRQ_RESET BIT(20)
101#define ME4000_AI_CTRL_SC_RELOAD BIT(21)
a9b586a5
HS
102#define ME4000_AI_STATUS_EF_CHANNEL BIT(22)
103#define ME4000_AI_STATUS_HF_CHANNEL BIT(23)
104#define ME4000_AI_STATUS_FF_CHANNEL BIT(24)
105#define ME4000_AI_STATUS_EF_DATA BIT(25)
106#define ME4000_AI_STATUS_HF_DATA BIT(26)
107#define ME4000_AI_STATUS_FF_DATA BIT(27)
108#define ME4000_AI_STATUS_LE BIT(28)
109#define ME4000_AI_STATUS_FSM BIT(29)
da772ad9 110#define ME4000_AI_CTRL_EX_TRIG_BOTH BIT(31)
81dd1811 111#define ME4000_AI_CHANNEL_LIST_REG 0x78
a0861f87 112#define ME4000_AI_LIST_INPUT_DIFFERENTIAL BIT(5)
245bd462 113#define ME4000_AI_LIST_RANGE(x) ((3 - ((x) & 3)) << 6)
a0861f87 114#define ME4000_AI_LIST_LAST_ENTRY BIT(8)
81dd1811
HS
115#define ME4000_AI_DATA_REG 0x7c
116#define ME4000_AI_CHAN_TIMER_REG 0x80
117#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84
118#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88
119#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8c
120#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90
121#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94
122#define ME4000_AI_START_REG 0x98
123#define ME4000_IRQ_STATUS_REG 0x9c
2ec0019a
HS
124#define ME4000_IRQ_STATUS_EX BIT(0)
125#define ME4000_IRQ_STATUS_LE BIT(1)
126#define ME4000_IRQ_STATUS_AI_HF BIT(2)
127#define ME4000_IRQ_STATUS_AO_0_HF BIT(3)
128#define ME4000_IRQ_STATUS_AO_1_HF BIT(4)
129#define ME4000_IRQ_STATUS_AO_2_HF BIT(5)
130#define ME4000_IRQ_STATUS_AO_3_HF BIT(6)
131#define ME4000_IRQ_STATUS_SC BIT(7)
81dd1811
HS
132#define ME4000_DIO_PORT_0_REG 0xa0
133#define ME4000_DIO_PORT_1_REG 0xa4
134#define ME4000_DIO_PORT_2_REG 0xa8
135#define ME4000_DIO_PORT_3_REG 0xac
136#define ME4000_DIO_DIR_REG 0xb0
137#define ME4000_AO_LOADSETREG_XX 0xb4
138#define ME4000_DIO_CTRL_REG 0xb8
55fb972e
HS
139#define ME4000_DIO_CTRL_MODE_0 BIT(0)
140#define ME4000_DIO_CTRL_MODE_1 BIT(1)
141#define ME4000_DIO_CTRL_MODE_2 BIT(2)
142#define ME4000_DIO_CTRL_MODE_3 BIT(3)
143#define ME4000_DIO_CTRL_MODE_4 BIT(4)
144#define ME4000_DIO_CTRL_MODE_5 BIT(5)
145#define ME4000_DIO_CTRL_MODE_6 BIT(6)
146#define ME4000_DIO_CTRL_MODE_7 BIT(7)
147#define ME4000_DIO_CTRL_FUNCTION_0 BIT(8)
148#define ME4000_DIO_CTRL_FUNCTION_1 BIT(9)
149#define ME4000_DIO_CTRL_FIFO_HIGH_0 BIT(10)
150#define ME4000_DIO_CTRL_FIFO_HIGH_1 BIT(11)
151#define ME4000_DIO_CTRL_FIFO_HIGH_2 BIT(12)
152#define ME4000_DIO_CTRL_FIFO_HIGH_3 BIT(13)
81dd1811
HS
153#define ME4000_AO_DEMUX_ADJUST_REG 0xbc
154#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c
155#define ME4000_AI_SAMPLE_COUNTER_REG 0xc0
156
81dd1811
HS
157#define ME4000_AI_FIFO_COUNT 2048
158
159#define ME4000_AI_MIN_TICKS 66
160#define ME4000_AI_MIN_SAMPLE_TIME 2000
81dd1811
HS
161
162#define ME4000_AI_CHANNEL_LIST_COUNT 1024
163
3674a87e 164struct me4000_private {
cc6f3336 165 unsigned long plx_regbase;
272e426e 166 unsigned int ai_ctrl_mode;
0f97f5c9
HS
167 unsigned int ai_init_ticks;
168 unsigned int ai_scan_ticks;
169 unsigned int ai_chan_ticks;
cc6f3336
HS
170};
171
8c355509
HS
172enum me4000_boardid {
173 BOARD_ME4650,
174 BOARD_ME4660,
175 BOARD_ME4660I,
176 BOARD_ME4660S,
177 BOARD_ME4660IS,
178 BOARD_ME4670,
179 BOARD_ME4670I,
180 BOARD_ME4670S,
181 BOARD_ME4670IS,
182 BOARD_ME4680,
183 BOARD_ME4680I,
184 BOARD_ME4680S,
185 BOARD_ME4680IS,
186};
187
06b60981
HS
188struct me4000_board {
189 const char *name;
06b60981 190 int ai_nchan;
56f71de6 191 unsigned int can_do_diff_ai:1;
e5f66350 192 unsigned int can_do_sh_ai:1; /* sample & hold (8 channels) */
13a463ae 193 unsigned int ex_trig_analog:1;
aed9b663 194 unsigned int has_ao:1;
77714d31 195 unsigned int has_ao_fifo:1;
13a463ae 196 unsigned int has_counter:1;
06b60981
HS
197};
198
27f4caaa 199static const struct me4000_board me4000_boards[] = {
8c355509 200 [BOARD_ME4650] = {
035d432a 201 .name = "ME-4650",
6ba8dfef 202 .ai_nchan = 16,
8c355509
HS
203 },
204 [BOARD_ME4660] = {
035d432a 205 .name = "ME-4660",
6ba8dfef 206 .ai_nchan = 32,
56f71de6 207 .can_do_diff_ai = 1,
eedf4299 208 .has_counter = 1,
8c355509
HS
209 },
210 [BOARD_ME4660I] = {
035d432a 211 .name = "ME-4660i",
6ba8dfef 212 .ai_nchan = 32,
56f71de6 213 .can_do_diff_ai = 1,
eedf4299 214 .has_counter = 1,
8c355509
HS
215 },
216 [BOARD_ME4660S] = {
035d432a 217 .name = "ME-4660s",
6ba8dfef 218 .ai_nchan = 32,
56f71de6 219 .can_do_diff_ai = 1,
e5f66350 220 .can_do_sh_ai = 1,
eedf4299 221 .has_counter = 1,
8c355509
HS
222 },
223 [BOARD_ME4660IS] = {
035d432a 224 .name = "ME-4660is",
6ba8dfef 225 .ai_nchan = 32,
56f71de6 226 .can_do_diff_ai = 1,
e5f66350 227 .can_do_sh_ai = 1,
eedf4299 228 .has_counter = 1,
8c355509
HS
229 },
230 [BOARD_ME4670] = {
035d432a 231 .name = "ME-4670",
6ba8dfef 232 .ai_nchan = 32,
56f71de6 233 .can_do_diff_ai = 1,
6ba8dfef 234 .ex_trig_analog = 1,
aed9b663 235 .has_ao = 1,
eedf4299 236 .has_counter = 1,
8c355509
HS
237 },
238 [BOARD_ME4670I] = {
035d432a 239 .name = "ME-4670i",
6ba8dfef 240 .ai_nchan = 32,
56f71de6 241 .can_do_diff_ai = 1,
6ba8dfef 242 .ex_trig_analog = 1,
aed9b663 243 .has_ao = 1,
eedf4299 244 .has_counter = 1,
8c355509
HS
245 },
246 [BOARD_ME4670S] = {
035d432a 247 .name = "ME-4670s",
6ba8dfef 248 .ai_nchan = 32,
56f71de6 249 .can_do_diff_ai = 1,
e5f66350 250 .can_do_sh_ai = 1,
6ba8dfef 251 .ex_trig_analog = 1,
aed9b663 252 .has_ao = 1,
eedf4299 253 .has_counter = 1,
8c355509
HS
254 },
255 [BOARD_ME4670IS] = {
035d432a 256 .name = "ME-4670is",
6ba8dfef 257 .ai_nchan = 32,
56f71de6 258 .can_do_diff_ai = 1,
e5f66350 259 .can_do_sh_ai = 1,
6ba8dfef 260 .ex_trig_analog = 1,
aed9b663 261 .has_ao = 1,
eedf4299 262 .has_counter = 1,
8c355509
HS
263 },
264 [BOARD_ME4680] = {
035d432a 265 .name = "ME-4680",
6ba8dfef 266 .ai_nchan = 32,
56f71de6 267 .can_do_diff_ai = 1,
6ba8dfef 268 .ex_trig_analog = 1,
aed9b663 269 .has_ao = 1,
77714d31 270 .has_ao_fifo = 1,
eedf4299 271 .has_counter = 1,
8c355509
HS
272 },
273 [BOARD_ME4680I] = {
035d432a 274 .name = "ME-4680i",
6ba8dfef 275 .ai_nchan = 32,
56f71de6 276 .can_do_diff_ai = 1,
6ba8dfef 277 .ex_trig_analog = 1,
aed9b663 278 .has_ao = 1,
77714d31 279 .has_ao_fifo = 1,
eedf4299 280 .has_counter = 1,
8c355509
HS
281 },
282 [BOARD_ME4680S] = {
035d432a 283 .name = "ME-4680s",
6ba8dfef 284 .ai_nchan = 32,
56f71de6 285 .can_do_diff_ai = 1,
e5f66350 286 .can_do_sh_ai = 1,
6ba8dfef 287 .ex_trig_analog = 1,
aed9b663 288 .has_ao = 1,
77714d31 289 .has_ao_fifo = 1,
eedf4299 290 .has_counter = 1,
8c355509
HS
291 },
292 [BOARD_ME4680IS] = {
035d432a 293 .name = "ME-4680is",
6ba8dfef 294 .ai_nchan = 32,
56f71de6 295 .can_do_diff_ai = 1,
e5f66350 296 .can_do_sh_ai = 1,
6ba8dfef 297 .ex_trig_analog = 1,
aed9b663 298 .has_ao = 1,
77714d31 299 .has_ao_fifo = 1,
eedf4299 300 .has_counter = 1,
035d432a 301 },
e55c95a3
GG
302};
303
245bd462
HS
304/*
305 * NOTE: the ranges here are inverted compared to the values
306 * written to the ME4000_AI_CHANNEL_LIST_REG,
307 *
308 * The ME4000_AI_LIST_RANGE() macro handles the inversion.
309 */
9ced1de6 310static const struct comedi_lrange me4000_ai_range = {
93626a45
HS
311 4, {
312 UNI_RANGE(2.5),
313 UNI_RANGE(10),
314 BIP_RANGE(2.5),
315 BIP_RANGE(10)
316 }
e55c95a3
GG
317};
318
ac584af5
HS
319static int me4000_xilinx_download(struct comedi_device *dev,
320 const u8 *data, size_t size,
321 unsigned long context)
e55c95a3 322{
fe531d12 323 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
3674a87e 324 struct me4000_private *devpriv = dev->private;
fe531d12 325 unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
ac584af5
HS
326 unsigned int file_length;
327 unsigned int val;
328 unsigned int i;
e55c95a3 329
fe531d12
HS
330 if (!xilinx_iobase)
331 return -ENODEV;
332
e55c95a3
GG
333 /*
334 * Set PLX local interrupt 2 polarity to high.
335 * Interrupt is thrown by init pin of xilinx.
336 */
3674a87e 337 outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR);
e55c95a3
GG
338
339 /* Set /CS and /WRITE of the Xilinx */
3674a87e 340 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
ac584af5 341 val |= PLX9052_CNTRL_UIO2_DATA;
3674a87e 342 outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
e55c95a3
GG
343
344 /* Init Xilinx with CS1 */
fe531d12 345 inb(xilinx_iobase + 0xC8);
e55c95a3
GG
346
347 /* Wait until /INIT pin is set */
348 udelay(20);
3674a87e 349 val = inl(devpriv->plx_regbase + PLX9052_INTCSR);
ac584af5 350 if (!(val & PLX9052_INTCSR_LI2STAT)) {
5da80ee8 351 dev_err(dev->class_dev, "Can't init Xilinx\n");
e55c95a3
GG
352 return -EIO;
353 }
354
355 /* Reset /CS and /WRITE of the Xilinx */
3674a87e 356 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
ac584af5 357 val &= ~PLX9052_CNTRL_UIO2_DATA;
3674a87e 358 outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
e55c95a3 359
ac584af5
HS
360 /* Download Xilinx firmware */
361 file_length = (((unsigned int)data[0] & 0xff) << 24) +
362 (((unsigned int)data[1] & 0xff) << 16) +
363 (((unsigned int)data[2] & 0xff) << 8) +
364 ((unsigned int)data[3] & 0xff);
365 udelay(10);
e55c95a3 366
ac584af5
HS
367 for (i = 0; i < file_length; i++) {
368 outb(data[16 + i], xilinx_iobase);
369 udelay(10);
370
371 /* Check if BUSY flag is low */
3674a87e 372 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
ac584af5
HS
373 if (val & PLX9052_CNTRL_UIO1_DATA) {
374 dev_err(dev->class_dev,
375 "Xilinx is still busy (i = %d)\n", i);
376 return -EIO;
e55c95a3
GG
377 }
378 }
379
380 /* If done flag is high download was successful */
3674a87e 381 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
ac584af5 382 if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
5da80ee8
HS
383 dev_err(dev->class_dev, "DONE flag is not set\n");
384 dev_err(dev->class_dev, "Download not successful\n");
e55c95a3
GG
385 return -EIO;
386 }
387
388 /* Set /CS and /WRITE */
3674a87e 389 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
ac584af5 390 val |= PLX9052_CNTRL_UIO2_DATA;
3674a87e 391 outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
e55c95a3
GG
392
393 return 0;
394}
395
2f348ecd 396static void me4000_reset(struct comedi_device *dev)
e55c95a3 397{
3674a87e 398 struct me4000_private *devpriv = dev->private;
ac2832f8 399 unsigned int val;
e1d7ccb7 400 int chan;
e55c95a3 401
e55c95a3 402 /* Make a hardware reset */
3674a87e 403 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
4564cfd0 404 val |= PLX9052_CNTRL_PCI_RESET;
3674a87e 405 outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
4564cfd0 406 val &= ~PLX9052_CNTRL_PCI_RESET;
3674a87e 407 outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
e55c95a3
GG
408
409 /* 0x8000 to the DACs means an output voltage of 0V */
e1d7ccb7
HS
410 for (chan = 0; chan < 4; chan++)
411 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
e55c95a3
GG
412
413 /* Set both stop bits in the analog input control register */
da772ad9 414 outl(ME4000_AI_CTRL_IMMEDIATE_STOP | ME4000_AI_CTRL_STOP,
6c7d2c8b 415 dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
416
417 /* Set both stop bits in the analog output control register */
7e92a5eb 418 val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP;
e1d7ccb7
HS
419 for (chan = 0; chan < 4; chan++)
420 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
421
422 /* Enable interrupts on the PLX */
58af6b92
HS
423 outl(PLX9052_INTCSR_LI1ENAB |
424 PLX9052_INTCSR_LI1POL |
3674a87e 425 PLX9052_INTCSR_PCIENAB, devpriv->plx_regbase + PLX9052_INTCSR);
e55c95a3
GG
426
427 /* Set the adustment register for AO demux */
d6cbe537 428 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
6c7d2c8b 429 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
e55c95a3 430
b6241fda
GS
431 /*
432 * Set digital I/O direction for port 0
433 * to output on isolated versions
434 */
362bcbde
HS
435 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
436 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
e55c95a3
GG
437}
438
023c129f
HS
439static int me4000_ai_eoc(struct comedi_device *dev,
440 struct comedi_subdevice *s,
441 struct comedi_insn *insn,
442 unsigned long context)
443{
444 unsigned int status;
445
446 status = inl(dev->iobase + ME4000_AI_STATUS_REG);
a9b586a5 447 if (status & ME4000_AI_STATUS_EF_DATA)
023c129f
HS
448 return 0;
449 return -EBUSY;
450}
e55c95a3 451
71b5f4f1 452static int me4000_ai_insn_read(struct comedi_device *dev,
1a023870
HS
453 struct comedi_subdevice *s,
454 struct comedi_insn *insn,
455 unsigned int *data)
e55c95a3 456{
959717a3 457 unsigned int chan = CR_CHAN(insn->chanspec);
e9784261 458 unsigned int range = CR_RANGE(insn->chanspec);
959717a3 459 unsigned int aref = CR_AREF(insn->chanspec);
e9784261 460 unsigned int entry;
ac2832f8 461 unsigned int tmp;
023c129f 462 int ret;
fb7891e4 463 int i;
e55c95a3 464
e9784261 465 entry = chan | ME4000_AI_LIST_RANGE(range);
271f5aa0 466 if (aref == AREF_DIFF) {
1a023870
HS
467 if (!(s->subdev_flags && SDF_DIFF)) {
468 dev_err(dev->class_dev,
469 "Differential inputs are not available\n");
470 return -EINVAL;
471 }
472
e9784261 473 if (!comedi_range_is_bipolar(s, range)) {
5da80ee8
HS
474 dev_err(dev->class_dev,
475 "Range must be bipolar when aref = diff\n");
e55c95a3
GG
476 return -EINVAL;
477 }
478
1a023870 479 if (chan >= (s->n_chan / 2)) {
5da80ee8
HS
480 dev_err(dev->class_dev,
481 "Analog input is not available\n");
e55c95a3
GG
482 return -EINVAL;
483 }
271f5aa0 484 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
e55c95a3
GG
485 }
486
487 entry |= ME4000_AI_LIST_LAST_ENTRY;
488
489 /* Clear channel list, data fifo and both stop bits */
b08bfa38 490 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
da772ad9
HS
491 tmp &= ~(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO |
492 ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP);
b08bfa38 493 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
494
495 /* Set the acquisition mode to single */
da772ad9
HS
496 tmp &= ~(ME4000_AI_CTRL_MODE_0 | ME4000_AI_CTRL_MODE_1 |
497 ME4000_AI_CTRL_MODE_2);
b08bfa38 498 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
499
500 /* Enable channel list and data fifo */
da772ad9 501 tmp |= ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO;
b08bfa38 502 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
503
504 /* Generate channel list entry */
b08bfa38 505 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
e55c95a3
GG
506
507 /* Set the timer to maximum sample rate */
b08bfa38
HS
508 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
509 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
e55c95a3 510
fb7891e4
HS
511 for (i = 0; i < insn->n; i++) {
512 unsigned int val;
e55c95a3 513
fb7891e4
HS
514 /* start conversion by dummy read */
515 inl(dev->iobase + ME4000_AI_START_REG);
e55c95a3 516
fb7891e4
HS
517 ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0);
518 if (ret)
519 return ret;
520
521 /* read two's complement value and munge to offset binary */
522 val = inl(dev->iobase + ME4000_AI_DATA_REG);
523 data[i] = comedi_offset_munge(s, val);
524 }
e55c95a3 525
fb7891e4 526 return insn->n;
e55c95a3
GG
527}
528
0a85b6f0
MT
529static int me4000_ai_cancel(struct comedi_device *dev,
530 struct comedi_subdevice *s)
e55c95a3 531{
ac2832f8 532 unsigned int tmp;
e55c95a3 533
e55c95a3 534 /* Stop any running conversion */
b08bfa38 535 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
da772ad9 536 tmp &= ~(ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP);
b08bfa38 537 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
538
539 /* Clear the control register */
b08bfa38 540 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
541
542 return 0;
543}
544
926e5073
HS
545static int me4000_ai_check_chanlist(struct comedi_device *dev,
546 struct comedi_subdevice *s,
547 struct comedi_cmd *cmd)
e55c95a3 548{
926e5073 549 unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
e55c95a3
GG
550 int i;
551
e55c95a3 552 for (i = 0; i < cmd->chanlist_len; i++) {
926e5073
HS
553 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
554 unsigned int range = CR_RANGE(cmd->chanlist[i]);
555 unsigned int aref = CR_AREF(cmd->chanlist[i]);
556
557 if (aref != aref0) {
558 dev_dbg(dev->class_dev,
5da80ee8 559 "Mode is not equal for all entries\n");
e55c95a3
GG
560 return -EINVAL;
561 }
e55c95a3 562
a7dab198 563 if (aref == AREF_DIFF) {
4ec85dad
HS
564 if (!(s->subdev_flags && SDF_DIFF)) {
565 dev_err(dev->class_dev,
566 "Differential inputs are not available\n");
567 return -EINVAL;
568 }
569
570 if (chan >= (s->n_chan / 2)) {
926e5073 571 dev_dbg(dev->class_dev,
5da80ee8 572 "Channel number to high\n");
e55c95a3
GG
573 return -EINVAL;
574 }
e55c95a3 575
926e5073
HS
576 if (!comedi_range_is_bipolar(s, range)) {
577 dev_dbg(dev->class_dev,
6c7d2c8b 578 "Bipolar is not selected in differential mode\n");
e55c95a3
GG
579 return -EINVAL;
580 }
581 }
582 }
583
584 return 0;
585}
586
c72c4c6e
HS
587static void me4000_ai_round_cmd_args(struct comedi_device *dev,
588 struct comedi_subdevice *s,
0f97f5c9 589 struct comedi_cmd *cmd)
e55c95a3 590{
0f97f5c9 591 struct me4000_private *devpriv = dev->private;
e55c95a3
GG
592 int rest;
593
0f97f5c9
HS
594 devpriv->ai_init_ticks = 0;
595 devpriv->ai_scan_ticks = 0;
596 devpriv->ai_chan_ticks = 0;
e55c95a3 597
e55c95a3 598 if (cmd->start_arg) {
0f97f5c9 599 devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000;
e55c95a3
GG
600 rest = (cmd->start_arg * 33) % 1000;
601
1e00dedc 602 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
82675f35 603 if (rest > 33)
0f97f5c9 604 devpriv->ai_init_ticks++;
1e00dedc 605 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
e55c95a3 606 if (rest)
0f97f5c9 607 devpriv->ai_init_ticks++;
e55c95a3
GG
608 }
609 }
610
611 if (cmd->scan_begin_arg) {
0f97f5c9 612 devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
e55c95a3
GG
613 rest = (cmd->scan_begin_arg * 33) % 1000;
614
1e00dedc 615 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
82675f35 616 if (rest > 33)
0f97f5c9 617 devpriv->ai_scan_ticks++;
1e00dedc 618 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
e55c95a3 619 if (rest)
0f97f5c9 620 devpriv->ai_scan_ticks++;
e55c95a3
GG
621 }
622 }
623
624 if (cmd->convert_arg) {
0f97f5c9 625 devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000;
e55c95a3
GG
626 rest = (cmd->convert_arg * 33) % 1000;
627
1e00dedc 628 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
82675f35 629 if (rest > 33)
0f97f5c9 630 devpriv->ai_chan_ticks++;
1e00dedc 631 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
e55c95a3 632 if (rest)
0f97f5c9 633 devpriv->ai_chan_ticks++;
e55c95a3
GG
634 }
635 }
e55c95a3
GG
636}
637
0f97f5c9 638static void ai_write_timer(struct comedi_device *dev)
e55c95a3 639{
0f97f5c9
HS
640 struct me4000_private *devpriv = dev->private;
641
642 outl(devpriv->ai_init_ticks - 1,
643 dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
b08bfa38 644 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
e55c95a3 645
0f97f5c9
HS
646 if (devpriv->ai_scan_ticks) {
647 outl(devpriv->ai_scan_ticks - 1,
648 dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
b08bfa38 649 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
e55c95a3
GG
650 }
651
0f97f5c9
HS
652 outl(devpriv->ai_chan_ticks - 1,
653 dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
654 outl(devpriv->ai_chan_ticks - 1,
655 dev->iobase + ME4000_AI_CHAN_TIMER_REG);
e55c95a3
GG
656}
657
518c5b64
HS
658static int me4000_ai_write_chanlist(struct comedi_device *dev,
659 struct comedi_subdevice *s,
660 struct comedi_cmd *cmd)
4b2f15f1 661{
4b2f15f1
HS
662 int i;
663
664 for (i = 0; i < cmd->chanlist_len; i++) {
518c5b64
HS
665 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
666 unsigned int range = CR_RANGE(cmd->chanlist[i]);
667 unsigned int aref = CR_AREF(cmd->chanlist[i]);
668 unsigned int entry;
4b2f15f1 669
518c5b64 670 entry = chan | ME4000_AI_LIST_RANGE(range);
4b2f15f1 671
8d44945d 672 if (aref == AREF_DIFF)
4b2f15f1 673 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
4b2f15f1 674
518c5b64
HS
675 if (i == (cmd->chanlist_len - 1))
676 entry |= ME4000_AI_LIST_LAST_ENTRY;
677
4b2f15f1
HS
678 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
679 }
680
681 return 0;
682}
683
11e480c3
HS
684static int me4000_ai_do_cmd(struct comedi_device *dev,
685 struct comedi_subdevice *s)
e55c95a3 686{
272e426e 687 struct me4000_private *devpriv = dev->private;
11e480c3 688 struct comedi_cmd *cmd = &s->async->cmd;
272e426e 689 unsigned int ctrl;
11e480c3
HS
690 int err;
691
692 /* Reset the analog input */
693 err = me4000_ai_cancel(dev, s);
694 if (err)
695 return err;
e55c95a3 696
e55c95a3 697 /* Write timer arguments */
0f97f5c9 698 ai_write_timer(dev);
e55c95a3
GG
699
700 /* Reset control register */
272e426e 701 outl(0, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
702
703 /* Start sources */
272e426e
HS
704 ctrl = devpriv->ai_ctrl_mode |
705 ME4000_AI_CTRL_CHANNEL_FIFO |
706 ME4000_AI_CTRL_DATA_FIFO;
e55c95a3
GG
707
708 /* Stop triggers */
709 if (cmd->stop_src == TRIG_COUNT) {
d6cbe537 710 outl(cmd->chanlist_len * cmd->stop_arg,
6c7d2c8b 711 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
272e426e 712 ctrl |= ME4000_AI_CTRL_SC_IRQ;
e55c95a3 713 } else if (cmd->stop_src == TRIG_NONE &&
0a85b6f0 714 cmd->scan_end_src == TRIG_COUNT) {
d6cbe537 715 outl(cmd->scan_end_arg,
6c7d2c8b 716 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
272e426e 717 ctrl |= ME4000_AI_CTRL_SC_IRQ;
e55c95a3 718 }
272e426e 719 ctrl |= ME4000_AI_CTRL_HF_IRQ;
e55c95a3
GG
720
721 /* Write the setup to the control register */
272e426e 722 outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
723
724 /* Write the channel list */
518c5b64 725 me4000_ai_write_chanlist(dev, s, cmd);
e55c95a3 726
e55c95a3 727 /* Start acquistion by dummy read */
b08bfa38 728 inl(dev->iobase + ME4000_AI_START_REG);
e55c95a3
GG
729
730 return 0;
731}
732
71b5f4f1 733static int me4000_ai_do_cmd_test(struct comedi_device *dev,
0a85b6f0
MT
734 struct comedi_subdevice *s,
735 struct comedi_cmd *cmd)
e55c95a3 736{
0f97f5c9 737 struct me4000_private *devpriv = dev->private;
e55c95a3
GG
738 int err = 0;
739
27020ffe
HS
740 /* Step 1 : check if triggers are trivially valid */
741
51ec1db9
IA
742 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
743 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
27020ffe 744 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
51ec1db9
IA
745 err |= comedi_check_trigger_src(&cmd->convert_src,
746 TRIG_TIMER | TRIG_EXT);
747 err |= comedi_check_trigger_src(&cmd->scan_end_src,
27020ffe 748 TRIG_NONE | TRIG_COUNT);
51ec1db9 749 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
27020ffe 750
82675f35 751 if (err)
e55c95a3 752 return 1;
e55c95a3 753
27020ffe
HS
754 /* Step 2a : make sure trigger sources are unique */
755
51ec1db9
IA
756 err |= comedi_check_trigger_is_unique(cmd->start_src);
757 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
758 err |= comedi_check_trigger_is_unique(cmd->convert_src);
759 err |= comedi_check_trigger_is_unique(cmd->scan_end_src);
760 err |= comedi_check_trigger_is_unique(cmd->stop_src);
27020ffe
HS
761
762 /* Step 2b : and mutually compatible */
763
e55c95a3 764 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
765 cmd->scan_begin_src == TRIG_TIMER &&
766 cmd->convert_src == TRIG_TIMER) {
272e426e 767 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
e55c95a3 768 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
769 cmd->scan_begin_src == TRIG_FOLLOW &&
770 cmd->convert_src == TRIG_TIMER) {
272e426e 771 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
e55c95a3 772 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
773 cmd->scan_begin_src == TRIG_TIMER &&
774 cmd->convert_src == TRIG_TIMER) {
272e426e 775 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
e55c95a3 776 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
777 cmd->scan_begin_src == TRIG_FOLLOW &&
778 cmd->convert_src == TRIG_TIMER) {
272e426e 779 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
e55c95a3 780 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
781 cmd->scan_begin_src == TRIG_EXT &&
782 cmd->convert_src == TRIG_TIMER) {
272e426e 783 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2;
e55c95a3 784 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
785 cmd->scan_begin_src == TRIG_EXT &&
786 cmd->convert_src == TRIG_EXT) {
272e426e
HS
787 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 |
788 ME4000_AI_CTRL_MODE_1;
e55c95a3 789 } else {
27020ffe 790 err |= -EINVAL;
e55c95a3
GG
791 }
792
82675f35 793 if (err)
e55c95a3 794 return 2;
e55c95a3 795
8c6c5a69
HS
796 /* Step 3: check if arguments are trivially valid */
797
51ec1db9 798 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
025b9187 799
e55c95a3 800 if (cmd->chanlist_len < 1) {
e55c95a3 801 cmd->chanlist_len = 1;
8c6c5a69 802 err |= -EINVAL;
e55c95a3 803 }
c72c4c6e
HS
804
805 /* Round the timer arguments */
0f97f5c9 806 me4000_ai_round_cmd_args(dev, s, cmd);
c72c4c6e 807
0f97f5c9 808 if (devpriv->ai_init_ticks < 66) {
e55c95a3 809 cmd->start_arg = 2000;
8c6c5a69 810 err |= -EINVAL;
e55c95a3 811 }
0f97f5c9 812 if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) {
e55c95a3 813 cmd->scan_begin_arg = 2031;
8c6c5a69 814 err |= -EINVAL;
e55c95a3 815 }
0f97f5c9 816 if (devpriv->ai_chan_ticks < 66) {
e55c95a3 817 cmd->convert_arg = 2000;
8c6c5a69 818 err |= -EINVAL;
e55c95a3 819 }
82675f35 820
76af50dd 821 if (cmd->stop_src == TRIG_COUNT)
51ec1db9 822 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
76af50dd 823 else /* TRIG_NONE */
51ec1db9 824 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
76af50dd 825
82675f35 826 if (err)
e55c95a3 827 return 3;
e55c95a3
GG
828
829 /*
830 * Stage 4. Check for argument conflicts.
831 */
832 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
833 cmd->scan_begin_src == TRIG_TIMER &&
834 cmd->convert_src == TRIG_TIMER) {
e55c95a3 835 /* Check timer arguments */
0f97f5c9 836 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 837 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 838 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
839 err++;
840 }
0f97f5c9 841 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 842 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 843 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
844 err++;
845 }
0f97f5c9
HS
846 if (devpriv->ai_scan_ticks <=
847 cmd->chanlist_len * devpriv->ai_chan_ticks) {
5da80ee8 848 dev_err(dev->class_dev, "Invalid scan end arg\n");
b6241fda
GS
849
850 /* At least one tick more */
851 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
e55c95a3
GG
852 err++;
853 }
854 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
855 cmd->scan_begin_src == TRIG_FOLLOW &&
856 cmd->convert_src == TRIG_TIMER) {
e55c95a3 857 /* Check timer arguments */
0f97f5c9 858 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 859 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 860 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
861 err++;
862 }
0f97f5c9 863 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 864 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 865 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
866 err++;
867 }
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 /* Check timer arguments */
0f97f5c9 872 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 873 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 874 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
875 err++;
876 }
0f97f5c9 877 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 878 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 879 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
880 err++;
881 }
0f97f5c9
HS
882 if (devpriv->ai_scan_ticks <=
883 cmd->chanlist_len * devpriv->ai_chan_ticks) {
5da80ee8 884 dev_err(dev->class_dev, "Invalid scan end arg\n");
b6241fda
GS
885
886 /* At least one tick more */
887 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
e55c95a3
GG
888 err++;
889 }
890 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
891 cmd->scan_begin_src == TRIG_FOLLOW &&
892 cmd->convert_src == TRIG_TIMER) {
e55c95a3 893 /* Check timer arguments */
0f97f5c9 894 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 895 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 896 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
897 err++;
898 }
0f97f5c9 899 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 900 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 901 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
902 err++;
903 }
904 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
905 cmd->scan_begin_src == TRIG_EXT &&
906 cmd->convert_src == TRIG_TIMER) {
e55c95a3 907 /* Check timer arguments */
0f97f5c9 908 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 909 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 910 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
911 err++;
912 }
0f97f5c9 913 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 914 dev_err(dev->class_dev, "Invalid convert arg\n");
b6c77757 915 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
916 err++;
917 }
918 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
919 cmd->scan_begin_src == TRIG_EXT &&
920 cmd->convert_src == TRIG_EXT) {
e55c95a3 921 /* Check timer arguments */
0f97f5c9 922 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
5da80ee8 923 dev_err(dev->class_dev, "Invalid start arg\n");
b6c77757 924 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
925 err++;
926 }
927 }
e55c95a3
GG
928 if (cmd->scan_end_src == TRIG_COUNT) {
929 if (cmd->scan_end_arg == 0) {
5da80ee8 930 dev_err(dev->class_dev, "Invalid scan end arg\n");
e55c95a3
GG
931 cmd->scan_end_arg = 1;
932 err++;
933 }
934 }
82675f35
BP
935
936 if (err)
e55c95a3 937 return 4;
e55c95a3 938
926e5073
HS
939 /* Step 5: check channel list if it exists */
940 if (cmd->chanlist && cmd->chanlist_len > 0)
941 err |= me4000_ai_check_chanlist(dev, s, cmd);
942
943 if (err)
e55c95a3
GG
944 return 5;
945
946 return 0;
947}
948
70265d24 949static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
e55c95a3
GG
950{
951 unsigned int tmp;
71b5f4f1 952 struct comedi_device *dev = dev_id;
b3403f2e 953 struct comedi_subdevice *s = dev->read_subdev;
e55c95a3
GG
954 int i;
955 int c = 0;
ac2832f8 956 unsigned int lval;
e55c95a3 957
ef5bbfcb 958 if (!dev->attached)
e55c95a3 959 return IRQ_NONE;
e55c95a3 960
b08bfa38 961 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
2ec0019a 962 ME4000_IRQ_STATUS_AI_HF) {
e55c95a3 963 /* Read status register to find out what happened */
a9b586a5 964 tmp = inl(dev->iobase + ME4000_AI_STATUS_REG);
e55c95a3 965
a9b586a5
HS
966 if (!(tmp & ME4000_AI_STATUS_FF_DATA) &&
967 !(tmp & ME4000_AI_STATUS_HF_DATA) &&
968 (tmp & ME4000_AI_STATUS_EF_DATA)) {
e55c95a3
GG
969 c = ME4000_AI_FIFO_COUNT;
970
b6241fda
GS
971 /*
972 * FIFO overflow, so stop conversion
973 * and disable all interrupts
974 */
da772ad9
HS
975 tmp |= ME4000_AI_CTRL_IMMEDIATE_STOP;
976 tmp &= ~(ME4000_AI_CTRL_HF_IRQ |
977 ME4000_AI_CTRL_SC_IRQ);
b08bfa38 978 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 979
3e6cb74f 980 s->async->events |= COMEDI_CB_ERROR;
e55c95a3 981
5da80ee8 982 dev_err(dev->class_dev, "FIFO overflow\n");
a9b586a5
HS
983 } else if ((tmp & ME4000_AI_STATUS_FF_DATA) &&
984 !(tmp & ME4000_AI_STATUS_HF_DATA) &&
985 (tmp & ME4000_AI_STATUS_EF_DATA)) {
e55c95a3
GG
986 c = ME4000_AI_FIFO_COUNT / 2;
987 } else {
5da80ee8
HS
988 dev_err(dev->class_dev,
989 "Can't determine state of fifo\n");
e55c95a3
GG
990 c = 0;
991
b6241fda
GS
992 /*
993 * Undefined state, so stop conversion
994 * and disable all interrupts
995 */
da772ad9
HS
996 tmp |= ME4000_AI_CTRL_IMMEDIATE_STOP;
997 tmp &= ~(ME4000_AI_CTRL_HF_IRQ |
998 ME4000_AI_CTRL_SC_IRQ);
b08bfa38 999 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3 1000
3e6cb74f 1001 s->async->events |= COMEDI_CB_ERROR;
e55c95a3 1002
5da80ee8 1003 dev_err(dev->class_dev, "Undefined FIFO state\n");
e55c95a3
GG
1004 }
1005
e55c95a3
GG
1006 for (i = 0; i < c; i++) {
1007 /* Read value from data fifo */
b08bfa38 1008 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
e55c95a3
GG
1009 lval ^= 0x8000;
1010
de88924f 1011 if (!comedi_buf_write_samples(s, &lval, 1)) {
b6241fda
GS
1012 /*
1013 * Buffer overflow, so stop conversion
1014 * and disable all interrupts
1015 */
da772ad9
HS
1016 tmp |= ME4000_AI_CTRL_IMMEDIATE_STOP;
1017 tmp &= ~(ME4000_AI_CTRL_HF_IRQ |
1018 ME4000_AI_CTRL_SC_IRQ);
b08bfa38 1019 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1020 break;
1021 }
1022 }
1023
1024 /* Work is done, so reset the interrupt */
da772ad9 1025 tmp |= ME4000_AI_CTRL_HF_IRQ_RESET;
b08bfa38 1026 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
da772ad9 1027 tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET;
b08bfa38 1028 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1029 }
1030
b08bfa38 1031 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
2ec0019a 1032 ME4000_IRQ_STATUS_SC) {
de88924f 1033 s->async->events |= COMEDI_CB_EOA;
e55c95a3 1034
b6241fda
GS
1035 /*
1036 * Acquisition is complete, so stop
1037 * conversion and disable all interrupts
1038 */
b08bfa38 1039 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
da772ad9
HS
1040 tmp |= ME4000_AI_CTRL_IMMEDIATE_STOP;
1041 tmp &= ~(ME4000_AI_CTRL_HF_IRQ | ME4000_AI_CTRL_SC_IRQ);
b08bfa38 1042 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1043
1044 /* Poll data until fifo empty */
a9b586a5
HS
1045 while (inl(dev->iobase + ME4000_AI_STATUS_REG) &
1046 ME4000_AI_STATUS_EF_DATA) {
e55c95a3 1047 /* Read value from data fifo */
b08bfa38 1048 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
e55c95a3
GG
1049 lval ^= 0x8000;
1050
de88924f 1051 if (!comedi_buf_write_samples(s, &lval, 1))
e55c95a3 1052 break;
e55c95a3
GG
1053 }
1054
1055 /* Work is done, so reset the interrupt */
da772ad9 1056 tmp |= ME4000_AI_CTRL_SC_IRQ_RESET;
b08bfa38 1057 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
da772ad9 1058 tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET;
b08bfa38 1059 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
e55c95a3
GG
1060 }
1061
3fa1eb64 1062 comedi_handle_events(dev, s);
e55c95a3
GG
1063
1064 return IRQ_HANDLED;
1065}
1066
71b5f4f1 1067static int me4000_ao_insn_write(struct comedi_device *dev,
0a85b6f0 1068 struct comedi_subdevice *s,
97e658d1
HS
1069 struct comedi_insn *insn,
1070 unsigned int *data)
e55c95a3 1071{
959717a3 1072 unsigned int chan = CR_CHAN(insn->chanspec);
ac2832f8 1073 unsigned int tmp;
e55c95a3 1074
e55c95a3 1075 /* Stop any running conversion */
e1d7ccb7 1076 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
7e92a5eb 1077 tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP;
e1d7ccb7 1078 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
1079
1080 /* Clear control register and set to single mode */
e1d7ccb7 1081 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
e55c95a3
GG
1082
1083 /* Write data value */
e1d7ccb7 1084 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
e55c95a3
GG
1085
1086 /* Store in the mirror */
081b6ee6 1087 s->readback[chan] = data[0];
e55c95a3
GG
1088
1089 return 1;
1090}
1091
71b5f4f1 1092static int me4000_dio_insn_bits(struct comedi_device *dev,
0a85b6f0 1093 struct comedi_subdevice *s,
b523c2b2
HS
1094 struct comedi_insn *insn,
1095 unsigned int *data)
e55c95a3 1096{
b523c2b2 1097 if (comedi_dio_update_state(s, data)) {
d6cbe537 1098 outl((s->state >> 0) & 0xFF,
6c7d2c8b 1099 dev->iobase + ME4000_DIO_PORT_0_REG);
d6cbe537 1100 outl((s->state >> 8) & 0xFF,
6c7d2c8b 1101 dev->iobase + ME4000_DIO_PORT_1_REG);
d6cbe537 1102 outl((s->state >> 16) & 0xFF,
6c7d2c8b 1103 dev->iobase + ME4000_DIO_PORT_2_REG);
d6cbe537 1104 outl((s->state >> 24) & 0xFF,
6c7d2c8b 1105 dev->iobase + ME4000_DIO_PORT_3_REG);
e55c95a3
GG
1106 }
1107
da755d15
HS
1108 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1109 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1110 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1111 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
e55c95a3 1112
a2714e3e 1113 return insn->n;
e55c95a3
GG
1114}
1115
71b5f4f1 1116static int me4000_dio_insn_config(struct comedi_device *dev,
0a85b6f0 1117 struct comedi_subdevice *s,
5dacadcc
HS
1118 struct comedi_insn *insn,
1119 unsigned int *data)
e55c95a3 1120{
5dacadcc
HS
1121 unsigned int chan = CR_CHAN(insn->chanspec);
1122 unsigned int mask;
1123 unsigned int tmp;
1124 int ret;
e55c95a3 1125
5dacadcc
HS
1126 if (chan < 8)
1127 mask = 0x000000ff;
1128 else if (chan < 16)
1129 mask = 0x0000ff00;
1130 else if (chan < 24)
1131 mask = 0x00ff0000;
1132 else
1133 mask = 0xff000000;
e55c95a3 1134
5dacadcc
HS
1135 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
1136 if (ret)
1137 return ret;
e55c95a3 1138
da755d15 1139 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
55fb972e
HS
1140 tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 |
1141 ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 |
1142 ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 |
1143 ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7);
5dacadcc 1144 if (s->io_bits & 0x000000ff)
55fb972e 1145 tmp |= ME4000_DIO_CTRL_MODE_0;
5dacadcc 1146 if (s->io_bits & 0x0000ff00)
55fb972e 1147 tmp |= ME4000_DIO_CTRL_MODE_2;
5dacadcc 1148 if (s->io_bits & 0x00ff0000)
55fb972e 1149 tmp |= ME4000_DIO_CTRL_MODE_4;
5dacadcc 1150 if (s->io_bits & 0xff000000)
55fb972e 1151 tmp |= ME4000_DIO_CTRL_MODE_6;
e55c95a3 1152
5dacadcc
HS
1153 /*
1154 * Check for optoisolated ME-4000 version.
1155 * If one the first port is a fixed output
1156 * port and the second is a fixed input port.
1157 */
1158 if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1159 s->io_bits |= 0x000000ff;
1160 s->io_bits &= ~0x0000ff00;
55fb972e
HS
1161 tmp |= ME4000_DIO_CTRL_MODE_0;
1162 tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3);
e55c95a3
GG
1163 }
1164
da755d15 1165 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
e55c95a3 1166
5dacadcc 1167 return insn->n;
e55c95a3
GG
1168}
1169
a690b7e5 1170static int me4000_auto_attach(struct comedi_device *dev,
8c355509 1171 unsigned long context)
ba5cb4ba 1172{
750af5e5 1173 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
49ef9c85 1174 const struct me4000_board *board = NULL;
3674a87e 1175 struct me4000_private *devpriv;
ba5cb4ba
HS
1176 struct comedi_subdevice *s;
1177 int result;
4b2f15f1 1178
8c355509 1179 if (context < ARRAY_SIZE(me4000_boards))
49ef9c85
HS
1180 board = &me4000_boards[context];
1181 if (!board)
5f8f8d43 1182 return -ENODEV;
49ef9c85
HS
1183 dev->board_ptr = board;
1184 dev->board_name = board->name;
4b2f15f1 1185
3674a87e
HS
1186 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1187 if (!devpriv)
c34fa261 1188 return -ENOMEM;
4b2f15f1 1189
818f569f 1190 result = comedi_pci_enable(dev);
ba5cb4ba
HS
1191 if (result)
1192 return result;
1193
3674a87e 1194 devpriv->plx_regbase = pci_resource_start(pcidev, 1);
ba5cb4ba 1195 dev->iobase = pci_resource_start(pcidev, 2);
3674a87e 1196 if (!devpriv->plx_regbase || !dev->iobase)
4b2f15f1
HS
1197 return -ENODEV;
1198
ac584af5
HS
1199 result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
1200 me4000_xilinx_download, 0);
1201 if (result < 0)
4b2f15f1
HS
1202 return result;
1203
2f348ecd 1204 me4000_reset(dev);
4b2f15f1 1205
a9b7ff93
HS
1206 if (pcidev->irq > 0) {
1207 result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED,
6c7d2c8b 1208 dev->board_name, dev);
a9b7ff93
HS
1209 if (result == 0)
1210 dev->irq = pcidev->irq;
1211 }
1212
8b6c5694
HS
1213 result = comedi_alloc_subdevices(dev, 4);
1214 if (result)
1215 return result;
3af09830 1216
14aa4789 1217 /* Analog Input subdevice */
8aaf2717 1218 s = &dev->subdevices[0];
14aa4789 1219 s->type = COMEDI_SUBD_AI;
31bebc03 1220 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
56f71de6 1221 if (board->can_do_diff_ai)
31bebc03 1222 s->subdev_flags |= SDF_DIFF;
14aa4789
HS
1223 s->n_chan = board->ai_nchan;
1224 s->maxdata = 0xffff;
1225 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1226 s->range_table = &me4000_ai_range;
1227 s->insn_read = me4000_ai_insn_read;
1228
1229 if (dev->irq) {
1230 dev->read_subdev = s;
1231 s->subdev_flags |= SDF_CMD_READ;
1232 s->cancel = me4000_ai_cancel;
1233 s->do_cmdtest = me4000_ai_do_cmd_test;
1234 s->do_cmd = me4000_ai_do_cmd;
3af09830
HS
1235 }
1236
1237 /*=========================================================================
1238 Analog output subdevice
1239 ========================================================================*/
1240
8aaf2717 1241 s = &dev->subdevices[1];
3af09830 1242
aed9b663 1243 if (board->has_ao) {
3af09830 1244 s->type = COMEDI_SUBD_AO;
ef49d832 1245 s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
aed9b663 1246 s->n_chan = 4;
3af09830 1247 s->maxdata = 0xFFFF; /* 16 bit DAC */
4683f9f8 1248 s->range_table = &range_bipolar10;
3af09830 1249 s->insn_write = me4000_ao_insn_write;
081b6ee6
HS
1250
1251 result = comedi_alloc_subdev_readback(s);
1252 if (result)
1253 return result;
3af09830
HS
1254 } else {
1255 s->type = COMEDI_SUBD_UNUSED;
1256 }
1257
d8553701 1258 /* Digital I/O subdevice */
8aaf2717 1259 s = &dev->subdevices[2];
d8553701
HS
1260 s->type = COMEDI_SUBD_DIO;
1261 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1262 s->n_chan = 32;
1263 s->maxdata = 1;
1264 s->range_table = &range_digital;
1265 s->insn_bits = me4000_dio_insn_bits;
1266 s->insn_config = me4000_dio_insn_config;
3af09830
HS
1267
1268 /*
1269 * Check for optoisolated ME-4000 version. If one the first
1270 * port is a fixed output port and the second is a fixed input port.
1271 */
da755d15 1272 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
3af09830 1273 s->io_bits |= 0xFF;
55fb972e 1274 outl(ME4000_DIO_CTRL_MODE_0,
6c7d2c8b 1275 dev->iobase + ME4000_DIO_DIR_REG);
3af09830
HS
1276 }
1277
d92d39d9 1278 /* Counter subdevice (8254) */
8aaf2717 1279 s = &dev->subdevices[3];
49ef9c85 1280 if (board->has_counter) {
d92d39d9
HS
1281 unsigned long timer_base = pci_resource_start(pcidev, 3);
1282
1283 if (!timer_base)
1284 return -ENODEV;
1285
1286 dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
1287 if (!dev->pacer)
1288 return -ENOMEM;
1289
1290 comedi_8254_subdevice_init(s, dev->pacer);
3af09830
HS
1291 } else {
1292 s->type = COMEDI_SUBD_UNUSED;
1293 }
1294
1295 return 0;
1296}
1297
484ecc95 1298static void me4000_detach(struct comedi_device *dev)
3af09830 1299{
7f072f54
HS
1300 if (dev->iobase)
1301 me4000_reset(dev);
aac307f9 1302 comedi_pci_detach(dev);
3af09830
HS
1303}
1304
75e6301b 1305static struct comedi_driver me4000_driver = {
3af09830
HS
1306 .driver_name = "me4000",
1307 .module = THIS_MODULE,
750af5e5 1308 .auto_attach = me4000_auto_attach,
3af09830
HS
1309 .detach = me4000_detach,
1310};
1311
a690b7e5 1312static int me4000_pci_probe(struct pci_dev *dev,
b8f4ac23 1313 const struct pci_device_id *id)
727b286b 1314{
b8f4ac23 1315 return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data);
727b286b
AT
1316}
1317
41e043fc 1318static const struct pci_device_id me4000_pci_table[] = {
8c355509
HS
1319 { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 },
1320 { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 },
1321 { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I },
1322 { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S },
1323 { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS },
1324 { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 },
1325 { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I },
1326 { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S },
1327 { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS },
1328 { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 },
1329 { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I },
1330 { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S },
1331 { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS },
1332 { 0 }
3af09830
HS
1333};
1334MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1335
75e6301b
HS
1336static struct pci_driver me4000_pci_driver = {
1337 .name = "me4000",
3af09830 1338 .id_table = me4000_pci_table,
75e6301b 1339 .probe = me4000_pci_probe,
9901a4d7 1340 .remove = comedi_pci_auto_unconfig,
727b286b 1341};
75e6301b 1342module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
90f703d3
AT
1343
1344MODULE_AUTHOR("Comedi http://www.comedi.org");
1345MODULE_DESCRIPTION("Comedi low-level driver");
1346MODULE_LICENSE("GPL");
ac584af5 1347MODULE_FIRMWARE(ME4000_FIRMWARE);
This page took 0.913837 seconds and 5 git commands to generate.