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