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