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#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
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
169struct me4000_info {
170 unsigned long plx_regbase;
171};
172
173enum 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
189struct 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 dio_nchan;
198 int has_counter;
199};
200
201static const struct me4000_board me4000_boards[] = {
202 [BOARD_ME4650] = {
203 .name = "ME-4650",
204 .ai_nchan = 16,
205 .dio_nchan = 32,
206 },
207 [BOARD_ME4660] = {
208 .name = "ME-4660",
209 .ai_nchan = 32,
210 .ai_diff_nchan = 16,
211 .dio_nchan = 32,
212 .has_counter = 1,
213 },
214 [BOARD_ME4660I] = {
215 .name = "ME-4660i",
216 .ai_nchan = 32,
217 .ai_diff_nchan = 16,
218 .dio_nchan = 32,
219 .has_counter = 1,
220 },
221 [BOARD_ME4660S] = {
222 .name = "ME-4660s",
223 .ai_nchan = 32,
224 .ai_diff_nchan = 16,
225 .ai_sh_nchan = 8,
226 .dio_nchan = 32,
227 .has_counter = 1,
228 },
229 [BOARD_ME4660IS] = {
230 .name = "ME-4660is",
231 .ai_nchan = 32,
232 .ai_diff_nchan = 16,
233 .ai_sh_nchan = 8,
234 .dio_nchan = 32,
235 .has_counter = 1,
236 },
237 [BOARD_ME4670] = {
238 .name = "ME-4670",
239 .ao_nchan = 4,
240 .ai_nchan = 32,
241 .ai_diff_nchan = 16,
242 .ex_trig_analog = 1,
243 .dio_nchan = 32,
244 .has_counter = 1,
245 },
246 [BOARD_ME4670I] = {
247 .name = "ME-4670i",
248 .ao_nchan = 4,
249 .ai_nchan = 32,
250 .ai_diff_nchan = 16,
251 .ex_trig_analog = 1,
252 .dio_nchan = 32,
253 .has_counter = 1,
254 },
255 [BOARD_ME4670S] = {
256 .name = "ME-4670s",
257 .ao_nchan = 4,
258 .ai_nchan = 32,
259 .ai_diff_nchan = 16,
260 .ai_sh_nchan = 8,
261 .ex_trig_analog = 1,
262 .dio_nchan = 32,
263 .has_counter = 1,
264 },
265 [BOARD_ME4670IS] = {
266 .name = "ME-4670is",
267 .ao_nchan = 4,
268 .ai_nchan = 32,
269 .ai_diff_nchan = 16,
270 .ai_sh_nchan = 8,
271 .ex_trig_analog = 1,
272 .dio_nchan = 32,
273 .has_counter = 1,
274 },
275 [BOARD_ME4680] = {
276 .name = "ME-4680",
277 .ao_nchan = 4,
278 .ao_fifo = 4,
279 .ai_nchan = 32,
280 .ai_diff_nchan = 16,
281 .ex_trig_analog = 1,
282 .dio_nchan = 32,
283 .has_counter = 1,
284 },
285 [BOARD_ME4680I] = {
286 .name = "ME-4680i",
287 .ao_nchan = 4,
288 .ao_fifo = 4,
289 .ai_nchan = 32,
290 .ai_diff_nchan = 16,
291 .ex_trig_analog = 1,
292 .dio_nchan = 32,
293 .has_counter = 1,
294 },
295 [BOARD_ME4680S] = {
296 .name = "ME-4680s",
297 .ao_nchan = 4,
298 .ao_fifo = 4,
299 .ai_nchan = 32,
300 .ai_diff_nchan = 16,
301 .ai_sh_nchan = 8,
302 .ex_trig_analog = 1,
303 .dio_nchan = 32,
304 .has_counter = 1,
305 },
306 [BOARD_ME4680IS] = {
307 .name = "ME-4680is",
308 .ao_nchan = 4,
309 .ao_fifo = 4,
310 .ai_nchan = 32,
311 .ai_diff_nchan = 16,
312 .ai_sh_nchan = 8,
313 .ex_trig_analog = 1,
314 .dio_nchan = 32,
315 .has_counter = 1,
316 },
317};
318
319static const struct comedi_lrange me4000_ai_range = {
320 4, {
321 UNI_RANGE(2.5),
322 UNI_RANGE(10),
323 BIP_RANGE(2.5),
324 BIP_RANGE(10)
325 }
326};
327
328static int me4000_xilinx_download(struct comedi_device *dev,
329 const u8 *data, size_t size,
330 unsigned long context)
331{
332 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
333 struct me4000_info *info = dev->private;
334 unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
335 unsigned int file_length;
336 unsigned int val;
337 unsigned int i;
338
339 if (!xilinx_iobase)
340 return -ENODEV;
341
342
343
344
345
346 outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
347
348
349 val = inl(info->plx_regbase + PLX9052_CNTRL);
350 val |= PLX9052_CNTRL_UIO2_DATA;
351 outl(val, info->plx_regbase + PLX9052_CNTRL);
352
353
354 inb(xilinx_iobase + 0xC8);
355
356
357 udelay(20);
358 val = inl(info->plx_regbase + PLX9052_INTCSR);
359 if (!(val & PLX9052_INTCSR_LI2STAT)) {
360 dev_err(dev->class_dev, "Can't init Xilinx\n");
361 return -EIO;
362 }
363
364
365 val = inl(info->plx_regbase + PLX9052_CNTRL);
366 val &= ~PLX9052_CNTRL_UIO2_DATA;
367 outl(val, info->plx_regbase + PLX9052_CNTRL);
368
369
370 file_length = (((unsigned int)data[0] & 0xff) << 24) +
371 (((unsigned int)data[1] & 0xff) << 16) +
372 (((unsigned int)data[2] & 0xff) << 8) +
373 ((unsigned int)data[3] & 0xff);
374 udelay(10);
375
376 for (i = 0; i < file_length; i++) {
377 outb(data[16 + i], xilinx_iobase);
378 udelay(10);
379
380
381 val = inl(info->plx_regbase + PLX9052_CNTRL);
382 if (val & PLX9052_CNTRL_UIO1_DATA) {
383 dev_err(dev->class_dev,
384 "Xilinx is still busy (i = %d)\n", i);
385 return -EIO;
386 }
387 }
388
389
390 val = inl(info->plx_regbase + PLX9052_CNTRL);
391 if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
392 dev_err(dev->class_dev, "DONE flag is not set\n");
393 dev_err(dev->class_dev, "Download not successful\n");
394 return -EIO;
395 }
396
397
398 val = inl(info->plx_regbase + PLX9052_CNTRL);
399 val |= PLX9052_CNTRL_UIO2_DATA;
400 outl(val, info->plx_regbase + PLX9052_CNTRL);
401
402 return 0;
403}
404
405static void me4000_reset(struct comedi_device *dev)
406{
407 struct me4000_info *info = dev->private;
408 unsigned int val;
409 int chan;
410
411
412 val = inl(info->plx_regbase + PLX9052_CNTRL);
413 val |= PLX9052_CNTRL_PCI_RESET;
414 outl(val, info->plx_regbase + PLX9052_CNTRL);
415 val &= ~PLX9052_CNTRL_PCI_RESET;
416 outl(val, info->plx_regbase + PLX9052_CNTRL);
417
418
419 for (chan = 0; chan < 4; chan++)
420 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
421
422
423 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
424 dev->iobase + ME4000_AI_CTRL_REG);
425
426
427 val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
428 for (chan = 0; chan < 4; chan++)
429 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
430
431
432 outl(PLX9052_INTCSR_LI1ENAB |
433 PLX9052_INTCSR_LI1POL |
434 PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR);
435
436
437 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
438 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
439
440
441
442
443
444 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
445 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
446}
447
448
449
450
451
452static int me4000_ai_insn_read(struct comedi_device *dev,
453 struct comedi_subdevice *subdevice,
454 struct comedi_insn *insn, unsigned int *data)
455{
456 const struct me4000_board *board = dev->board_ptr;
457 int chan = CR_CHAN(insn->chanspec);
458 int rang = CR_RANGE(insn->chanspec);
459 int aref = CR_AREF(insn->chanspec);
460
461 unsigned int entry = 0;
462 unsigned int tmp;
463 unsigned int lval;
464
465 if (insn->n == 0) {
466 return 0;
467 } else if (insn->n > 1) {
468 dev_err(dev->class_dev, "Invalid instruction length %d\n",
469 insn->n);
470 return -EINVAL;
471 }
472
473 switch (rang) {
474 case 0:
475 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
476 break;
477 case 1:
478 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
479 break;
480 case 2:
481 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
482 break;
483 case 3:
484 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
485 break;
486 default:
487 dev_err(dev->class_dev, "Invalid range specified\n");
488 return -EINVAL;
489 }
490
491 switch (aref) {
492 case AREF_GROUND:
493 case AREF_COMMON:
494 if (chan >= board->ai_nchan) {
495 dev_err(dev->class_dev,
496 "Analog input is not available\n");
497 return -EINVAL;
498 }
499 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
500 break;
501
502 case AREF_DIFF:
503 if (rang == 0 || rang == 1) {
504 dev_err(dev->class_dev,
505 "Range must be bipolar when aref = diff\n");
506 return -EINVAL;
507 }
508
509 if (chan >= board->ai_diff_nchan) {
510 dev_err(dev->class_dev,
511 "Analog input is not available\n");
512 return -EINVAL;
513 }
514 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
515 break;
516 default:
517 dev_err(dev->class_dev, "Invalid aref specified\n");
518 return -EINVAL;
519 }
520
521 entry |= ME4000_AI_LIST_LAST_ENTRY;
522
523
524 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
525 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
526 ME4000_AI_CTRL_BIT_DATA_FIFO |
527 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
528 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
529
530
531 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
532 ME4000_AI_CTRL_BIT_MODE_2);
533 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
534
535
536 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
537 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
538
539
540 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
541
542
543 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
544 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
545
546
547 inl(dev->iobase + ME4000_AI_START_REG);
548
549
550 udelay(10);
551 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
552 ME4000_AI_STATUS_BIT_EF_DATA)) {
553 dev_err(dev->class_dev, "Value not available after wait\n");
554 return -EIO;
555 }
556
557
558 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
559 data[0] = lval ^ 0x8000;
560
561 return 1;
562}
563
564static int me4000_ai_cancel(struct comedi_device *dev,
565 struct comedi_subdevice *s)
566{
567 unsigned int tmp;
568
569
570 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
571 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
572 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
573
574
575 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
576
577 return 0;
578}
579
580static int me4000_ai_check_chanlist(struct comedi_device *dev,
581 struct comedi_subdevice *s,
582 struct comedi_cmd *cmd)
583{
584 const struct me4000_board *board = dev->board_ptr;
585 unsigned int max_diff_chan = board->ai_diff_nchan;
586 unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
587 int i;
588
589 for (i = 0; i < cmd->chanlist_len; i++) {
590 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
591 unsigned int range = CR_RANGE(cmd->chanlist[i]);
592 unsigned int aref = CR_AREF(cmd->chanlist[i]);
593
594 if (aref != aref0) {
595 dev_dbg(dev->class_dev,
596 "Mode is not equal for all entries\n");
597 return -EINVAL;
598 }
599
600 if (aref == AREF_DIFF) {
601 if (chan >= max_diff_chan) {
602 dev_dbg(dev->class_dev,
603 "Channel number to high\n");
604 return -EINVAL;
605 }
606
607 if (!comedi_range_is_bipolar(s, range)) {
608 dev_dbg(dev->class_dev,
609 "Bipolar is not selected in differential mode\n");
610 return -EINVAL;
611 }
612 }
613 }
614
615 return 0;
616}
617
618static int ai_round_cmd_args(struct comedi_device *dev,
619 struct comedi_subdevice *s,
620 struct comedi_cmd *cmd,
621 unsigned int *init_ticks,
622 unsigned int *scan_ticks, unsigned int *chan_ticks)
623{
624 int rest;
625
626 *init_ticks = 0;
627 *scan_ticks = 0;
628 *chan_ticks = 0;
629
630 if (cmd->start_arg) {
631 *init_ticks = (cmd->start_arg * 33) / 1000;
632 rest = (cmd->start_arg * 33) % 1000;
633
634 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
635 if (rest > 33)
636 (*init_ticks)++;
637 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
638 if (rest)
639 (*init_ticks)++;
640 }
641 }
642
643 if (cmd->scan_begin_arg) {
644 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
645 rest = (cmd->scan_begin_arg * 33) % 1000;
646
647 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
648 if (rest > 33)
649 (*scan_ticks)++;
650 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
651 if (rest)
652 (*scan_ticks)++;
653 }
654 }
655
656 if (cmd->convert_arg) {
657 *chan_ticks = (cmd->convert_arg * 33) / 1000;
658 rest = (cmd->convert_arg * 33) % 1000;
659
660 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
661 if (rest > 33)
662 (*chan_ticks)++;
663 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
664 if (rest)
665 (*chan_ticks)++;
666 }
667 }
668
669 return 0;
670}
671
672static void ai_write_timer(struct comedi_device *dev,
673 unsigned int init_ticks,
674 unsigned int scan_ticks, unsigned int chan_ticks)
675{
676 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
677 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
678
679 if (scan_ticks) {
680 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
681 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
682 }
683
684 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
685 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
686}
687
688static int ai_write_chanlist(struct comedi_device *dev,
689 struct comedi_subdevice *s, struct comedi_cmd *cmd)
690{
691 unsigned int entry;
692 unsigned int chan;
693 unsigned int rang;
694 unsigned int aref;
695 int i;
696
697 for (i = 0; i < cmd->chanlist_len; i++) {
698 chan = CR_CHAN(cmd->chanlist[i]);
699 rang = CR_RANGE(cmd->chanlist[i]);
700 aref = CR_AREF(cmd->chanlist[i]);
701
702 entry = chan;
703
704 if (rang == 0)
705 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
706 else if (rang == 1)
707 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
708 else if (rang == 2)
709 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
710 else
711 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
712
713 if (aref == AREF_DIFF)
714 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
715 else
716 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
717
718 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
719 }
720
721 return 0;
722}
723
724static int ai_prepare(struct comedi_device *dev,
725 struct comedi_subdevice *s,
726 struct comedi_cmd *cmd,
727 unsigned int init_ticks,
728 unsigned int scan_ticks, unsigned int chan_ticks)
729{
730 unsigned int tmp = 0;
731
732
733 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
734
735
736 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
737
738
739 if ((cmd->start_src == TRIG_EXT &&
740 cmd->scan_begin_src == TRIG_TIMER &&
741 cmd->convert_src == TRIG_TIMER) ||
742 (cmd->start_src == TRIG_EXT &&
743 cmd->scan_begin_src == TRIG_FOLLOW &&
744 cmd->convert_src == TRIG_TIMER)) {
745 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
746 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
747 ME4000_AI_CTRL_BIT_DATA_FIFO;
748 } else if (cmd->start_src == TRIG_EXT &&
749 cmd->scan_begin_src == TRIG_EXT &&
750 cmd->convert_src == TRIG_TIMER) {
751 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
752 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
753 ME4000_AI_CTRL_BIT_DATA_FIFO;
754 } else if (cmd->start_src == TRIG_EXT &&
755 cmd->scan_begin_src == TRIG_EXT &&
756 cmd->convert_src == TRIG_EXT) {
757 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
758 ME4000_AI_CTRL_BIT_MODE_1 |
759 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
760 ME4000_AI_CTRL_BIT_DATA_FIFO;
761 } else {
762 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
763 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
764 ME4000_AI_CTRL_BIT_DATA_FIFO;
765 }
766
767
768 if (cmd->stop_src == TRIG_COUNT) {
769 outl(cmd->chanlist_len * cmd->stop_arg,
770 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
771 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
772 } else if (cmd->stop_src == TRIG_NONE &&
773 cmd->scan_end_src == TRIG_COUNT) {
774 outl(cmd->scan_end_arg,
775 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
776 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
777 } else {
778 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
779 }
780
781
782 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
783
784
785 ai_write_chanlist(dev, s, cmd);
786
787 return 0;
788}
789
790static int me4000_ai_do_cmd(struct comedi_device *dev,
791 struct comedi_subdevice *s)
792{
793 int err;
794 unsigned int init_ticks = 0;
795 unsigned int scan_ticks = 0;
796 unsigned int chan_ticks = 0;
797 struct comedi_cmd *cmd = &s->async->cmd;
798
799
800 err = me4000_ai_cancel(dev, s);
801 if (err)
802 return err;
803
804
805 err = ai_round_cmd_args(dev,
806 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
807 if (err)
808 return err;
809
810
811 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
812 if (err)
813 return err;
814
815
816 inl(dev->iobase + ME4000_AI_START_REG);
817
818 return 0;
819}
820
821static int me4000_ai_do_cmd_test(struct comedi_device *dev,
822 struct comedi_subdevice *s,
823 struct comedi_cmd *cmd)
824{
825 unsigned int init_ticks;
826 unsigned int chan_ticks;
827 unsigned int scan_ticks;
828 int err = 0;
829
830
831 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
832
833
834
835 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
836 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
837 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
838 err |= comedi_check_trigger_src(&cmd->convert_src,
839 TRIG_TIMER | TRIG_EXT);
840 err |= comedi_check_trigger_src(&cmd->scan_end_src,
841 TRIG_NONE | TRIG_COUNT);
842 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
843
844 if (err)
845 return 1;
846
847
848
849 err |= comedi_check_trigger_is_unique(cmd->start_src);
850 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
851 err |= comedi_check_trigger_is_unique(cmd->convert_src);
852 err |= comedi_check_trigger_is_unique(cmd->scan_end_src);
853 err |= comedi_check_trigger_is_unique(cmd->stop_src);
854
855
856
857 if (cmd->start_src == TRIG_NOW &&
858 cmd->scan_begin_src == TRIG_TIMER &&
859 cmd->convert_src == TRIG_TIMER) {
860 } else if (cmd->start_src == TRIG_NOW &&
861 cmd->scan_begin_src == TRIG_FOLLOW &&
862 cmd->convert_src == TRIG_TIMER) {
863 } else if (cmd->start_src == TRIG_EXT &&
864 cmd->scan_begin_src == TRIG_TIMER &&
865 cmd->convert_src == TRIG_TIMER) {
866 } else if (cmd->start_src == TRIG_EXT &&
867 cmd->scan_begin_src == TRIG_FOLLOW &&
868 cmd->convert_src == TRIG_TIMER) {
869 } else if (cmd->start_src == TRIG_EXT &&
870 cmd->scan_begin_src == TRIG_EXT &&
871 cmd->convert_src == TRIG_TIMER) {
872 } else if (cmd->start_src == TRIG_EXT &&
873 cmd->scan_begin_src == TRIG_EXT &&
874 cmd->convert_src == TRIG_EXT) {
875 } else {
876 err |= -EINVAL;
877 }
878
879 if (err)
880 return 2;
881
882
883
884 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
885
886 if (cmd->chanlist_len < 1) {
887 cmd->chanlist_len = 1;
888 err |= -EINVAL;
889 }
890 if (init_ticks < 66) {
891 cmd->start_arg = 2000;
892 err |= -EINVAL;
893 }
894 if (scan_ticks && scan_ticks < 67) {
895 cmd->scan_begin_arg = 2031;
896 err |= -EINVAL;
897 }
898 if (chan_ticks < 66) {
899 cmd->convert_arg = 2000;
900 err |= -EINVAL;
901 }
902
903 if (cmd->stop_src == TRIG_COUNT)
904 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
905 else
906 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
907
908 if (err)
909 return 3;
910
911
912
913
914 if (cmd->start_src == TRIG_NOW &&
915 cmd->scan_begin_src == TRIG_TIMER &&
916 cmd->convert_src == TRIG_TIMER) {
917
918 if (init_ticks < ME4000_AI_MIN_TICKS) {
919 dev_err(dev->class_dev, "Invalid start arg\n");
920 cmd->start_arg = 2000;
921 err++;
922 }
923 if (chan_ticks < ME4000_AI_MIN_TICKS) {
924 dev_err(dev->class_dev, "Invalid convert arg\n");
925 cmd->convert_arg = 2000;
926 err++;
927 }
928 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
929 dev_err(dev->class_dev, "Invalid scan end arg\n");
930
931
932 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
933 err++;
934 }
935 } else if (cmd->start_src == TRIG_NOW &&
936 cmd->scan_begin_src == TRIG_FOLLOW &&
937 cmd->convert_src == TRIG_TIMER) {
938
939 if (init_ticks < ME4000_AI_MIN_TICKS) {
940 dev_err(dev->class_dev, "Invalid start arg\n");
941 cmd->start_arg = 2000;
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;
947 err++;
948 }
949 } else if (cmd->start_src == TRIG_EXT &&
950 cmd->scan_begin_src == TRIG_TIMER &&
951 cmd->convert_src == TRIG_TIMER) {
952
953 if (init_ticks < ME4000_AI_MIN_TICKS) {
954 dev_err(dev->class_dev, "Invalid start arg\n");
955 cmd->start_arg = 2000;
956 err++;
957 }
958 if (chan_ticks < ME4000_AI_MIN_TICKS) {
959 dev_err(dev->class_dev, "Invalid convert arg\n");
960 cmd->convert_arg = 2000;
961 err++;
962 }
963 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
964 dev_err(dev->class_dev, "Invalid scan end arg\n");
965
966
967 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
968 err++;
969 }
970 } else if (cmd->start_src == TRIG_EXT &&
971 cmd->scan_begin_src == TRIG_FOLLOW &&
972 cmd->convert_src == TRIG_TIMER) {
973
974 if (init_ticks < ME4000_AI_MIN_TICKS) {
975 dev_err(dev->class_dev, "Invalid start arg\n");
976 cmd->start_arg = 2000;
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;
982 err++;
983 }
984 } else if (cmd->start_src == TRIG_EXT &&
985 cmd->scan_begin_src == TRIG_EXT &&
986 cmd->convert_src == TRIG_TIMER) {
987
988 if (init_ticks < ME4000_AI_MIN_TICKS) {
989 dev_err(dev->class_dev, "Invalid start arg\n");
990 cmd->start_arg = 2000;
991 err++;
992 }
993 if (chan_ticks < ME4000_AI_MIN_TICKS) {
994 dev_err(dev->class_dev, "Invalid convert arg\n");
995 cmd->convert_arg = 2000;
996 err++;
997 }
998 } else if (cmd->start_src == TRIG_EXT &&
999 cmd->scan_begin_src == TRIG_EXT &&
1000 cmd->convert_src == TRIG_EXT) {
1001
1002 if (init_ticks < ME4000_AI_MIN_TICKS) {
1003 dev_err(dev->class_dev, "Invalid start arg\n");
1004 cmd->start_arg = 2000;
1005 err++;
1006 }
1007 }
1008 if (cmd->scan_end_src == TRIG_COUNT) {
1009 if (cmd->scan_end_arg == 0) {
1010 dev_err(dev->class_dev, "Invalid scan end arg\n");
1011 cmd->scan_end_arg = 1;
1012 err++;
1013 }
1014 }
1015
1016 if (err)
1017 return 4;
1018
1019
1020 if (cmd->chanlist && cmd->chanlist_len > 0)
1021 err |= me4000_ai_check_chanlist(dev, s, cmd);
1022
1023 if (err)
1024 return 5;
1025
1026 return 0;
1027}
1028
1029static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1030{
1031 unsigned int tmp;
1032 struct comedi_device *dev = dev_id;
1033 struct comedi_subdevice *s = dev->read_subdev;
1034 int i;
1035 int c = 0;
1036 unsigned int lval;
1037
1038 if (!dev->attached)
1039 return IRQ_NONE;
1040
1041 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1042 ME4000_IRQ_STATUS_BIT_AI_HF) {
1043
1044 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1045
1046 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1047 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1048 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1049 c = ME4000_AI_FIFO_COUNT;
1050
1051
1052
1053
1054
1055 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1056 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1057 ME4000_AI_CTRL_BIT_SC_IRQ);
1058 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1059
1060 s->async->events |= COMEDI_CB_ERROR;
1061
1062 dev_err(dev->class_dev, "FIFO overflow\n");
1063 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1064 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1065 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1066 c = ME4000_AI_FIFO_COUNT / 2;
1067 } else {
1068 dev_err(dev->class_dev,
1069 "Can't determine state of fifo\n");
1070 c = 0;
1071
1072
1073
1074
1075
1076 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1077 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1078 ME4000_AI_CTRL_BIT_SC_IRQ);
1079 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1080
1081 s->async->events |= COMEDI_CB_ERROR;
1082
1083 dev_err(dev->class_dev, "Undefined FIFO state\n");
1084 }
1085
1086 for (i = 0; i < c; i++) {
1087
1088 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1089 lval ^= 0x8000;
1090
1091 if (!comedi_buf_write_samples(s, &lval, 1)) {
1092
1093
1094
1095
1096 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1097 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1098 ME4000_AI_CTRL_BIT_SC_IRQ);
1099 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1100 break;
1101 }
1102 }
1103
1104
1105 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1106 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1107 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1108 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1109 }
1110
1111 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1112 ME4000_IRQ_STATUS_BIT_SC) {
1113 s->async->events |= COMEDI_CB_EOA;
1114
1115
1116
1117
1118
1119 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1120 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1121 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1122 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1123
1124
1125 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1126 ME4000_AI_STATUS_BIT_EF_DATA) {
1127
1128 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1129 lval ^= 0x8000;
1130
1131 if (!comedi_buf_write_samples(s, &lval, 1))
1132 break;
1133 }
1134
1135
1136 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1137 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1138 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1139 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1140 }
1141
1142 comedi_handle_events(dev, s);
1143
1144 return IRQ_HANDLED;
1145}
1146
1147static int me4000_ao_insn_write(struct comedi_device *dev,
1148 struct comedi_subdevice *s,
1149 struct comedi_insn *insn,
1150 unsigned int *data)
1151{
1152 int chan = CR_CHAN(insn->chanspec);
1153 unsigned int tmp;
1154
1155
1156 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1157 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1158 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1159
1160
1161 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1162
1163
1164 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1165
1166
1167 s->readback[chan] = data[0];
1168
1169 return 1;
1170}
1171
1172static int me4000_dio_insn_bits(struct comedi_device *dev,
1173 struct comedi_subdevice *s,
1174 struct comedi_insn *insn,
1175 unsigned int *data)
1176{
1177 if (comedi_dio_update_state(s, data)) {
1178 outl((s->state >> 0) & 0xFF,
1179 dev->iobase + ME4000_DIO_PORT_0_REG);
1180 outl((s->state >> 8) & 0xFF,
1181 dev->iobase + ME4000_DIO_PORT_1_REG);
1182 outl((s->state >> 16) & 0xFF,
1183 dev->iobase + ME4000_DIO_PORT_2_REG);
1184 outl((s->state >> 24) & 0xFF,
1185 dev->iobase + ME4000_DIO_PORT_3_REG);
1186 }
1187
1188 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1189 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1190 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1191 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1192
1193 return insn->n;
1194}
1195
1196static int me4000_dio_insn_config(struct comedi_device *dev,
1197 struct comedi_subdevice *s,
1198 struct comedi_insn *insn,
1199 unsigned int *data)
1200{
1201 unsigned int chan = CR_CHAN(insn->chanspec);
1202 unsigned int mask;
1203 unsigned int tmp;
1204 int ret;
1205
1206 if (chan < 8)
1207 mask = 0x000000ff;
1208 else if (chan < 16)
1209 mask = 0x0000ff00;
1210 else if (chan < 24)
1211 mask = 0x00ff0000;
1212 else
1213 mask = 0xff000000;
1214
1215 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
1216 if (ret)
1217 return ret;
1218
1219 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1220 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 |
1221 ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 |
1222 ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 |
1223 ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7);
1224 if (s->io_bits & 0x000000ff)
1225 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1226 if (s->io_bits & 0x0000ff00)
1227 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1228 if (s->io_bits & 0x00ff0000)
1229 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1230 if (s->io_bits & 0xff000000)
1231 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1232
1233
1234
1235
1236
1237
1238 if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1239 s->io_bits |= 0x000000ff;
1240 s->io_bits &= ~0x0000ff00;
1241 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1242 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1243 ME4000_DIO_CTRL_BIT_MODE_3);
1244 }
1245
1246 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1247
1248 return insn->n;
1249}
1250
1251static int me4000_auto_attach(struct comedi_device *dev,
1252 unsigned long context)
1253{
1254 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1255 const struct me4000_board *board = NULL;
1256 struct me4000_info *info;
1257 struct comedi_subdevice *s;
1258 int result;
1259
1260 if (context < ARRAY_SIZE(me4000_boards))
1261 board = &me4000_boards[context];
1262 if (!board)
1263 return -ENODEV;
1264 dev->board_ptr = board;
1265 dev->board_name = board->name;
1266
1267 info = comedi_alloc_devpriv(dev, sizeof(*info));
1268 if (!info)
1269 return -ENOMEM;
1270
1271 result = comedi_pci_enable(dev);
1272 if (result)
1273 return result;
1274
1275 info->plx_regbase = pci_resource_start(pcidev, 1);
1276 dev->iobase = pci_resource_start(pcidev, 2);
1277 if (!info->plx_regbase || !dev->iobase)
1278 return -ENODEV;
1279
1280 result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
1281 me4000_xilinx_download, 0);
1282 if (result < 0)
1283 return result;
1284
1285 me4000_reset(dev);
1286
1287 if (pcidev->irq > 0) {
1288 result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED,
1289 dev->board_name, dev);
1290 if (result == 0)
1291 dev->irq = pcidev->irq;
1292 }
1293
1294 result = comedi_alloc_subdevices(dev, 4);
1295 if (result)
1296 return result;
1297
1298
1299
1300
1301
1302 s = &dev->subdevices[0];
1303
1304 if (board->ai_nchan) {
1305 s->type = COMEDI_SUBD_AI;
1306 s->subdev_flags =
1307 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1308 s->n_chan = board->ai_nchan;
1309 s->maxdata = 0xFFFF;
1310 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1311 s->range_table = &me4000_ai_range;
1312 s->insn_read = me4000_ai_insn_read;
1313
1314 if (dev->irq) {
1315 dev->read_subdev = s;
1316 s->subdev_flags |= SDF_CMD_READ;
1317 s->cancel = me4000_ai_cancel;
1318 s->do_cmdtest = me4000_ai_do_cmd_test;
1319 s->do_cmd = me4000_ai_do_cmd;
1320 }
1321 } else {
1322 s->type = COMEDI_SUBD_UNUSED;
1323 }
1324
1325
1326
1327
1328
1329 s = &dev->subdevices[1];
1330
1331 if (board->ao_nchan) {
1332 s->type = COMEDI_SUBD_AO;
1333 s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
1334 s->n_chan = board->ao_nchan;
1335 s->maxdata = 0xFFFF;
1336 s->range_table = &range_bipolar10;
1337 s->insn_write = me4000_ao_insn_write;
1338
1339 result = comedi_alloc_subdev_readback(s);
1340 if (result)
1341 return result;
1342 } else {
1343 s->type = COMEDI_SUBD_UNUSED;
1344 }
1345
1346
1347
1348
1349
1350 s = &dev->subdevices[2];
1351
1352 if (board->dio_nchan) {
1353 s->type = COMEDI_SUBD_DIO;
1354 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1355 s->n_chan = board->dio_nchan;
1356 s->maxdata = 1;
1357 s->range_table = &range_digital;
1358 s->insn_bits = me4000_dio_insn_bits;
1359 s->insn_config = me4000_dio_insn_config;
1360 } else {
1361 s->type = COMEDI_SUBD_UNUSED;
1362 }
1363
1364
1365
1366
1367
1368 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1369 s->io_bits |= 0xFF;
1370 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1371 dev->iobase + ME4000_DIO_DIR_REG);
1372 }
1373
1374
1375 s = &dev->subdevices[3];
1376 if (board->has_counter) {
1377 unsigned long timer_base = pci_resource_start(pcidev, 3);
1378
1379 if (!timer_base)
1380 return -ENODEV;
1381
1382 dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
1383 if (!dev->pacer)
1384 return -ENOMEM;
1385
1386 comedi_8254_subdevice_init(s, dev->pacer);
1387 } else {
1388 s->type = COMEDI_SUBD_UNUSED;
1389 }
1390
1391 return 0;
1392}
1393
1394static void me4000_detach(struct comedi_device *dev)
1395{
1396 if (dev->iobase)
1397 me4000_reset(dev);
1398 comedi_pci_detach(dev);
1399}
1400
1401static struct comedi_driver me4000_driver = {
1402 .driver_name = "me4000",
1403 .module = THIS_MODULE,
1404 .auto_attach = me4000_auto_attach,
1405 .detach = me4000_detach,
1406};
1407
1408static int me4000_pci_probe(struct pci_dev *dev,
1409 const struct pci_device_id *id)
1410{
1411 return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data);
1412}
1413
1414static const struct pci_device_id me4000_pci_table[] = {
1415 { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 },
1416 { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 },
1417 { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I },
1418 { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S },
1419 { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS },
1420 { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 },
1421 { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I },
1422 { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S },
1423 { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS },
1424 { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 },
1425 { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I },
1426 { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S },
1427 { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS },
1428 { 0 }
1429};
1430MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1431
1432static struct pci_driver me4000_pci_driver = {
1433 .name = "me4000",
1434 .id_table = me4000_pci_table,
1435 .probe = me4000_pci_probe,
1436 .remove = comedi_pci_auto_unconfig,
1437};
1438module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1439
1440MODULE_AUTHOR("Comedi http://www.comedi.org");
1441MODULE_DESCRIPTION("Comedi low-level driver");
1442MODULE_LICENSE("GPL");
1443MODULE_FIRMWARE(ME4000_FIRMWARE);
1444