]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/me4000.c
staging: comedi: export alloc_subdevices as comedi_alloc_subdevices
[~andy/linux] / 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    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22  */
23 /*
24 Driver: me4000
25 Description: Meilhaus ME-4000 series boards
26 Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
27 Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
28 Updated: Mon, 18 Mar 2002 15:34:01 -0800
29 Status: broken (no support for loading firmware)
30
31 Supports:
32
33     - Analog Input
34     - Analog Output
35     - Digital I/O
36     - Counter
37
38 Configuration Options:
39
40     [0] - PCI bus number (optional)
41     [1] - PCI slot number (optional)
42
43     If bus/slot is not specified, the first available PCI
44     device will be used.
45
46 The firmware required by these boards is available in the
47 comedi_nonfree_firmware tarball available from
48 http://www.comedi.org.  However, the driver's support for
49 loading the firmware through comedi_config is currently
50 broken.
51
52  */
53
54 #include <linux/interrupt.h>
55 #include "../comedidev.h"
56
57 #include <linux/delay.h>
58 #include <linux/list.h>
59 #include <linux/spinlock.h>
60
61 #include "me4000.h"
62 #if 0
63 /* file removed due to GPL incompatibility */
64 #include "me4000_fw.h"
65 #endif
66
67 static const struct me4000_board me4000_boards[] = {
68         {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} },
69
70         {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
71         {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
72         {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
73         {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
74
75         {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
76         {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
77         {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
78         {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
79
80         {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
81         {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
82         {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
83         {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
84
85         {0},
86 };
87
88 #define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
89
90 /*-----------------------------------------------------------------------------
91   Meilhaus function prototypes
92   ---------------------------------------------------------------------------*/
93 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
94 static int init_board_info(struct comedi_device *dev,
95                            struct pci_dev *pci_dev_p);
96 static int init_ao_context(struct comedi_device *dev);
97 static int init_ai_context(struct comedi_device *dev);
98 static int init_dio_context(struct comedi_device *dev);
99 static int init_cnt_context(struct comedi_device *dev);
100 static int xilinx_download(struct comedi_device *dev);
101 static int reset_board(struct comedi_device *dev);
102
103 static int ai_write_chanlist(struct comedi_device *dev,
104                              struct comedi_subdevice *s,
105                              struct comedi_cmd *cmd);
106
107 /*-----------------------------------------------------------------------------
108   Meilhaus inline functions
109   ---------------------------------------------------------------------------*/
110
111 static inline void me4000_outb(struct comedi_device *dev, unsigned char value,
112                                unsigned long port)
113 {
114         PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
115         outb(value, port);
116 }
117
118 static inline void me4000_outl(struct comedi_device *dev, unsigned long value,
119                                unsigned long port)
120 {
121         PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
122         outl(value, port);
123 }
124
125 static inline unsigned long me4000_inl(struct comedi_device *dev,
126                                        unsigned long port)
127 {
128         unsigned long value;
129         value = inl(port);
130         PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
131         return value;
132 }
133
134 static inline unsigned char me4000_inb(struct comedi_device *dev,
135                                        unsigned long port)
136 {
137         unsigned char value;
138         value = inb(port);
139         PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
140         return value;
141 }
142
143 static const struct comedi_lrange me4000_ai_range = {
144         4,
145         {
146          UNI_RANGE(2.5),
147          UNI_RANGE(10),
148          BIP_RANGE(2.5),
149          BIP_RANGE(10),
150          }
151 };
152
153 static const struct comedi_lrange me4000_ao_range = {
154         1,
155         {
156          BIP_RANGE(10),
157          }
158 };
159
160 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
161 {
162         struct pci_dev *pci_device = NULL;
163         int result, i;
164         struct me4000_board *board;
165
166         CALL_PDEBUG("In me4000_probe()\n");
167
168         /* Allocate private memory */
169         if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
170                 return -ENOMEM;
171
172         /*
173          * Probe the device to determine what device in the series it is.
174          */
175         for_each_pci_dev(pci_device) {
176                 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
177                         for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
178                                 if (me4000_boards[i].device_id ==
179                                     pci_device->device) {
180                                         /*
181                                          * Was a particular
182                                          * bus/slot requested?
183                                          */
184                                         if ((it->options[0] != 0)
185                                             || (it->options[1] != 0)) {
186                                                 /*
187                                                  * Are we on the wrong
188                                                  * bus/slot?
189                                                  */
190                                                 if (pci_device->bus->number !=
191                                                     it->options[0]
192                                                     ||
193                                                     PCI_SLOT(pci_device->devfn)
194                                                     != it->options[1]) {
195                                                         continue;
196                                                 }
197                                         }
198                                         dev->board_ptr = me4000_boards + i;
199                                         board =
200                                             (struct me4000_board *)
201                                             dev->board_ptr;
202                                         info->pci_dev_p = pci_device;
203                                         goto found;
204                                 }
205                         }
206                 }
207         }
208
209         printk(KERN_ERR
210                "comedi%d: me4000: me4000_probe(): "
211                "No supported board found (req. bus/slot : %d/%d)\n",
212                dev->minor, it->options[0], it->options[1]);
213         return -ENODEV;
214
215 found:
216
217         printk(KERN_INFO
218                "comedi%d: me4000: me4000_probe(): "
219                "Found %s at PCI bus %d, slot %d\n",
220                dev->minor, me4000_boards[i].name, pci_device->bus->number,
221                PCI_SLOT(pci_device->devfn));
222
223         /* Set data in device structure */
224         dev->board_name = board->name;
225
226         /* Enable PCI device and request regions */
227         result = comedi_pci_enable(pci_device, dev->board_name);
228         if (result) {
229                 printk(KERN_ERR
230                        "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
231                        "device and request I/O regions\n", dev->minor);
232                 return result;
233         }
234
235         /* Get the PCI base registers */
236         result = get_registers(dev, pci_device);
237         if (result) {
238                 printk(KERN_ERR
239                        "comedi%d: me4000: me4000_probe(): "
240                        "Cannot get registers\n", dev->minor);
241                 return result;
242         }
243         /* Initialize board info */
244         result = init_board_info(dev, pci_device);
245         if (result) {
246                 printk(KERN_ERR
247                        "comedi%d: me4000: me4000_probe(): "
248                        "Cannot init baord info\n", dev->minor);
249                 return result;
250         }
251
252         /* Init analog output context */
253         result = init_ao_context(dev);
254         if (result) {
255                 printk(KERN_ERR
256                        "comedi%d: me4000: me4000_probe(): "
257                        "Cannot init ao context\n", dev->minor);
258                 return result;
259         }
260
261         /* Init analog input context */
262         result = init_ai_context(dev);
263         if (result) {
264                 printk(KERN_ERR
265                        "comedi%d: me4000: me4000_probe(): "
266                        "Cannot init ai context\n", dev->minor);
267                 return result;
268         }
269
270         /* Init digital I/O context */
271         result = init_dio_context(dev);
272         if (result) {
273                 printk(KERN_ERR
274                        "comedi%d: me4000: me4000_probe(): "
275                        "Cannot init dio context\n", dev->minor);
276                 return result;
277         }
278
279         /* Init counter context */
280         result = init_cnt_context(dev);
281         if (result) {
282                 printk(KERN_ERR
283                        "comedi%d: me4000: me4000_probe(): "
284                        "Cannot init cnt context\n", dev->minor);
285                 return result;
286         }
287
288         /* Download the xilinx firmware */
289         result = xilinx_download(dev);
290         if (result) {
291                 printk(KERN_ERR
292                        "comedi%d: me4000: me4000_probe(): "
293                        "Can't download firmware\n", dev->minor);
294                 return result;
295         }
296
297         /* Make a hardware reset */
298         result = reset_board(dev);
299         if (result) {
300                 printk(KERN_ERR
301                        "comedi%d: me4000: me4000_probe(): Can't reset board\n",
302                        dev->minor);
303                 return result;
304         }
305
306         return 0;
307 }
308
309 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
310 {
311
312         CALL_PDEBUG("In get_registers()\n");
313
314     /*--------------------------- plx regbase -------------------------------*/
315
316         info->plx_regbase = pci_resource_start(pci_dev_p, 1);
317         if (info->plx_regbase == 0) {
318                 printk(KERN_ERR
319                        "comedi%d: me4000: get_registers(): "
320                        "PCI base address 1 is not available\n", dev->minor);
321                 return -ENODEV;
322         }
323         info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
324
325     /*--------------------------- me4000 regbase ----------------------------*/
326
327         info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
328         if (info->me4000_regbase == 0) {
329                 printk(KERN_ERR
330                        "comedi%d: me4000: get_registers(): "
331                        "PCI base address 2 is not available\n", dev->minor);
332                 return -ENODEV;
333         }
334         info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
335
336     /*--------------------------- timer regbase ------------------------------*/
337
338         info->timer_regbase = pci_resource_start(pci_dev_p, 3);
339         if (info->timer_regbase == 0) {
340                 printk(KERN_ERR
341                        "comedi%d: me4000: get_registers(): "
342                        "PCI base address 3 is not available\n", dev->minor);
343                 return -ENODEV;
344         }
345         info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
346
347     /*--------------------------- program regbase ----------------------------*/
348
349         info->program_regbase = pci_resource_start(pci_dev_p, 5);
350         if (info->program_regbase == 0) {
351                 printk(KERN_ERR
352                        "comedi%d: me4000: get_registers(): "
353                        "PCI base address 5 is not available\n", dev->minor);
354                 return -ENODEV;
355         }
356         info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
357
358         return 0;
359 }
360
361 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
362 {
363         int result;
364
365         CALL_PDEBUG("In init_board_info()\n");
366
367         /* Init spin locks */
368         /* spin_lock_init(&info->preload_lock); */
369         /* spin_lock_init(&info->ai_ctrl_lock); */
370
371         /* Get the serial number */
372         result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
373         if (result != PCIBIOS_SUCCESSFUL)
374                 return result;
375
376         /* Get the hardware revision */
377         result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
378         if (result != PCIBIOS_SUCCESSFUL)
379                 return result;
380
381         /* Get the vendor id */
382         info->vendor_id = pci_dev_p->vendor;
383
384         /* Get the device id */
385         info->device_id = pci_dev_p->device;
386
387         /* Get the irq assigned to the board */
388         info->irq = pci_dev_p->irq;
389
390         return 0;
391 }
392
393 static int init_ao_context(struct comedi_device *dev)
394 {
395         int i;
396
397         CALL_PDEBUG("In init_ao_context()\n");
398
399         for (i = 0; i < thisboard->ao.count; i++) {
400                 /* spin_lock_init(&info->ao_context[i].use_lock); */
401                 info->ao_context[i].irq = info->irq;
402
403                 switch (i) {
404                 case 0:
405                         info->ao_context[i].ctrl_reg =
406                             info->me4000_regbase + ME4000_AO_00_CTRL_REG;
407                         info->ao_context[i].status_reg =
408                             info->me4000_regbase + ME4000_AO_00_STATUS_REG;
409                         info->ao_context[i].fifo_reg =
410                             info->me4000_regbase + ME4000_AO_00_FIFO_REG;
411                         info->ao_context[i].single_reg =
412                             info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
413                         info->ao_context[i].timer_reg =
414                             info->me4000_regbase + ME4000_AO_00_TIMER_REG;
415                         info->ao_context[i].irq_status_reg =
416                             info->me4000_regbase + ME4000_IRQ_STATUS_REG;
417                         info->ao_context[i].preload_reg =
418                             info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
419                         break;
420                 case 1:
421                         info->ao_context[i].ctrl_reg =
422                             info->me4000_regbase + ME4000_AO_01_CTRL_REG;
423                         info->ao_context[i].status_reg =
424                             info->me4000_regbase + ME4000_AO_01_STATUS_REG;
425                         info->ao_context[i].fifo_reg =
426                             info->me4000_regbase + ME4000_AO_01_FIFO_REG;
427                         info->ao_context[i].single_reg =
428                             info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
429                         info->ao_context[i].timer_reg =
430                             info->me4000_regbase + ME4000_AO_01_TIMER_REG;
431                         info->ao_context[i].irq_status_reg =
432                             info->me4000_regbase + ME4000_IRQ_STATUS_REG;
433                         info->ao_context[i].preload_reg =
434                             info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
435                         break;
436                 case 2:
437                         info->ao_context[i].ctrl_reg =
438                             info->me4000_regbase + ME4000_AO_02_CTRL_REG;
439                         info->ao_context[i].status_reg =
440                             info->me4000_regbase + ME4000_AO_02_STATUS_REG;
441                         info->ao_context[i].fifo_reg =
442                             info->me4000_regbase + ME4000_AO_02_FIFO_REG;
443                         info->ao_context[i].single_reg =
444                             info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
445                         info->ao_context[i].timer_reg =
446                             info->me4000_regbase + ME4000_AO_02_TIMER_REG;
447                         info->ao_context[i].irq_status_reg =
448                             info->me4000_regbase + ME4000_IRQ_STATUS_REG;
449                         info->ao_context[i].preload_reg =
450                             info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
451                         break;
452                 case 3:
453                         info->ao_context[i].ctrl_reg =
454                             info->me4000_regbase + ME4000_AO_03_CTRL_REG;
455                         info->ao_context[i].status_reg =
456                             info->me4000_regbase + ME4000_AO_03_STATUS_REG;
457                         info->ao_context[i].fifo_reg =
458                             info->me4000_regbase + ME4000_AO_03_FIFO_REG;
459                         info->ao_context[i].single_reg =
460                             info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
461                         info->ao_context[i].timer_reg =
462                             info->me4000_regbase + ME4000_AO_03_TIMER_REG;
463                         info->ao_context[i].irq_status_reg =
464                             info->me4000_regbase + ME4000_IRQ_STATUS_REG;
465                         info->ao_context[i].preload_reg =
466                             info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
467                         break;
468                 default:
469                         break;
470                 }
471         }
472
473         return 0;
474 }
475
476 static int init_ai_context(struct comedi_device *dev)
477 {
478
479         CALL_PDEBUG("In init_ai_context()\n");
480
481         info->ai_context.irq = info->irq;
482
483         info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
484         info->ai_context.status_reg =
485             info->me4000_regbase + ME4000_AI_STATUS_REG;
486         info->ai_context.channel_list_reg =
487             info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
488         info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
489         info->ai_context.chan_timer_reg =
490             info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
491         info->ai_context.chan_pre_timer_reg =
492             info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
493         info->ai_context.scan_timer_low_reg =
494             info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
495         info->ai_context.scan_timer_high_reg =
496             info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
497         info->ai_context.scan_pre_timer_low_reg =
498             info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
499         info->ai_context.scan_pre_timer_high_reg =
500             info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
501         info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
502         info->ai_context.irq_status_reg =
503             info->me4000_regbase + ME4000_IRQ_STATUS_REG;
504         info->ai_context.sample_counter_reg =
505             info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
506
507         return 0;
508 }
509
510 static int init_dio_context(struct comedi_device *dev)
511 {
512
513         CALL_PDEBUG("In init_dio_context()\n");
514
515         info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
516         info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
517         info->dio_context.port_0_reg =
518             info->me4000_regbase + ME4000_DIO_PORT_0_REG;
519         info->dio_context.port_1_reg =
520             info->me4000_regbase + ME4000_DIO_PORT_1_REG;
521         info->dio_context.port_2_reg =
522             info->me4000_regbase + ME4000_DIO_PORT_2_REG;
523         info->dio_context.port_3_reg =
524             info->me4000_regbase + ME4000_DIO_PORT_3_REG;
525
526         return 0;
527 }
528
529 static int init_cnt_context(struct comedi_device *dev)
530 {
531
532         CALL_PDEBUG("In init_cnt_context()\n");
533
534         info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
535         info->cnt_context.counter_0_reg =
536             info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
537         info->cnt_context.counter_1_reg =
538             info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
539         info->cnt_context.counter_2_reg =
540             info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
541
542         return 0;
543 }
544
545 #define FIRMWARE_NOT_AVAILABLE 1
546 #if FIRMWARE_NOT_AVAILABLE
547 extern unsigned char *xilinx_firm;
548 #endif
549
550 static int xilinx_download(struct comedi_device *dev)
551 {
552         u32 value = 0;
553         wait_queue_head_t queue;
554         int idx = 0;
555         int size = 0;
556
557         CALL_PDEBUG("In xilinx_download()\n");
558
559         init_waitqueue_head(&queue);
560
561         /*
562          * Set PLX local interrupt 2 polarity to high.
563          * Interrupt is thrown by init pin of xilinx.
564          */
565         outl(0x10, info->plx_regbase + PLX_INTCSR);
566
567         /* Set /CS and /WRITE of the Xilinx */
568         value = inl(info->plx_regbase + PLX_ICR);
569         value |= 0x100;
570         outl(value, info->plx_regbase + PLX_ICR);
571
572         /* Init Xilinx with CS1 */
573         inb(info->program_regbase + 0xC8);
574
575         /* Wait until /INIT pin is set */
576         udelay(20);
577         if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
578                 printk(KERN_ERR
579                        "comedi%d: me4000: xilinx_download(): "
580                        "Can't init Xilinx\n", dev->minor);
581                 return -EIO;
582         }
583
584         /* Reset /CS and /WRITE of the Xilinx */
585         value = inl(info->plx_regbase + PLX_ICR);
586         value &= ~0x100;
587         outl(value, info->plx_regbase + PLX_ICR);
588         if (FIRMWARE_NOT_AVAILABLE) {
589                 comedi_error(dev, "xilinx firmware unavailable "
590                              "due to licensing, aborting");
591                 return -EIO;
592         } else {
593                 /* Download Xilinx firmware */
594                 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
595                     (xilinx_firm[2] << 8) + xilinx_firm[3];
596                 udelay(10);
597
598                 for (idx = 0; idx < size; idx++) {
599                         outb(xilinx_firm[16 + idx], info->program_regbase);
600                         udelay(10);
601
602                         /* Check if BUSY flag is low */
603                         if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
604                                 printk(KERN_ERR
605                                        "comedi%d: me4000: xilinx_download(): "
606                                        "Xilinx is still busy (idx = %d)\n",
607                                        dev->minor, idx);
608                                 return -EIO;
609                         }
610                 }
611         }
612
613         /* If done flag is high download was successful */
614         if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
615         } else {
616                 printk(KERN_ERR
617                        "comedi%d: me4000: xilinx_download(): "
618                        "DONE flag is not set\n", dev->minor);
619                 printk(KERN_ERR
620                        "comedi%d: me4000: xilinx_download(): "
621                        "Download not successful\n", dev->minor);
622                 return -EIO;
623         }
624
625         /* Set /CS and /WRITE */
626         value = inl(info->plx_regbase + PLX_ICR);
627         value |= 0x100;
628         outl(value, info->plx_regbase + PLX_ICR);
629
630         return 0;
631 }
632
633 static int reset_board(struct comedi_device *dev)
634 {
635         unsigned long icr;
636
637         CALL_PDEBUG("In reset_board()\n");
638
639         /* Make a hardware reset */
640         icr = me4000_inl(dev, info->plx_regbase + PLX_ICR);
641         icr |= 0x40000000;
642         me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
643         icr &= ~0x40000000;
644         me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
645
646         /* 0x8000 to the DACs means an output voltage of 0V */
647         me4000_outl(dev, 0x8000,
648                     info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
649         me4000_outl(dev, 0x8000,
650                     info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
651         me4000_outl(dev, 0x8000,
652                     info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
653         me4000_outl(dev, 0x8000,
654                     info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
655
656         /* Set both stop bits in the analog input control register */
657         me4000_outl(dev,
658                     ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
659                     info->me4000_regbase + ME4000_AI_CTRL_REG);
660
661         /* Set both stop bits in the analog output control register */
662         me4000_outl(dev,
663                     ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
664                     info->me4000_regbase + ME4000_AO_00_CTRL_REG);
665         me4000_outl(dev,
666                     ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
667                     info->me4000_regbase + ME4000_AO_01_CTRL_REG);
668         me4000_outl(dev,
669                     ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
670                     info->me4000_regbase + ME4000_AO_02_CTRL_REG);
671         me4000_outl(dev,
672                     ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
673                     info->me4000_regbase + ME4000_AO_03_CTRL_REG);
674
675         /* Enable interrupts on the PLX */
676         me4000_outl(dev, 0x43, info->plx_regbase + PLX_INTCSR);
677
678         /* Set the adustment register for AO demux */
679         me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE,
680                     info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
681
682         /*
683          * Set digital I/O direction for port 0
684          * to output on isolated versions
685          */
686         if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) {
687                 me4000_outl(dev, 0x1,
688                             info->me4000_regbase + ME4000_DIO_CTRL_REG);
689         }
690
691         return 0;
692 }
693
694 /*=============================================================================
695   Analog input section
696   ===========================================================================*/
697
698 static int me4000_ai_insn_read(struct comedi_device *dev,
699                                struct comedi_subdevice *subdevice,
700                                struct comedi_insn *insn, unsigned int *data)
701 {
702
703         int chan = CR_CHAN(insn->chanspec);
704         int rang = CR_RANGE(insn->chanspec);
705         int aref = CR_AREF(insn->chanspec);
706
707         unsigned long entry = 0;
708         unsigned long tmp;
709         long lval;
710
711         CALL_PDEBUG("In me4000_ai_insn_read()\n");
712
713         if (insn->n == 0) {
714                 return 0;
715         } else if (insn->n > 1) {
716                 printk(KERN_ERR
717                        "comedi%d: me4000: me4000_ai_insn_read(): "
718                        "Invalid instruction length %d\n", dev->minor, insn->n);
719                 return -EINVAL;
720         }
721
722         switch (rang) {
723         case 0:
724                 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
725                 break;
726         case 1:
727                 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
728                 break;
729         case 2:
730                 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
731                 break;
732         case 3:
733                 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
734                 break;
735         default:
736                 printk(KERN_ERR
737                        "comedi%d: me4000: me4000_ai_insn_read(): "
738                        "Invalid range specified\n", dev->minor);
739                 return -EINVAL;
740         }
741
742         switch (aref) {
743         case AREF_GROUND:
744         case AREF_COMMON:
745                 if (chan >= thisboard->ai.count) {
746                         printk(KERN_ERR
747                                "comedi%d: me4000: me4000_ai_insn_read(): "
748                                "Analog input is not available\n", dev->minor);
749                         return -EINVAL;
750                 }
751                 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
752                 break;
753
754         case AREF_DIFF:
755                 if (rang == 0 || rang == 1) {
756                         printk(KERN_ERR
757                                "comedi%d: me4000: me4000_ai_insn_read(): "
758                                "Range must be bipolar when aref = diff\n",
759                                dev->minor);
760                         return -EINVAL;
761                 }
762
763                 if (chan >= thisboard->ai.diff_count) {
764                         printk(KERN_ERR
765                                "comedi%d: me4000: me4000_ai_insn_read(): "
766                                "Analog input is not available\n", dev->minor);
767                         return -EINVAL;
768                 }
769                 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
770                 break;
771         default:
772                 printk(KERN_ERR
773                        "comedi%d: me4000: me4000_ai_insn_read(): "
774                        "Invalid aref specified\n", dev->minor);
775                 return -EINVAL;
776         }
777
778         entry |= ME4000_AI_LIST_LAST_ENTRY;
779
780         /* Clear channel list, data fifo and both stop bits */
781         tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
782         tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
783                  ME4000_AI_CTRL_BIT_DATA_FIFO |
784                  ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
785         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
786
787         /* Set the acquisition mode to single */
788         tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
789                  ME4000_AI_CTRL_BIT_MODE_2);
790         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
791
792         /* Enable channel list and data fifo */
793         tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
794         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
795
796         /* Generate channel list entry */
797         me4000_outl(dev, entry, info->ai_context.channel_list_reg);
798
799         /* Set the timer to maximum sample rate */
800         me4000_outl(dev, ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
801         me4000_outl(dev, ME4000_AI_MIN_TICKS,
802                     info->ai_context.chan_pre_timer_reg);
803
804         /* Start conversion by dummy read */
805         me4000_inl(dev, info->ai_context.start_reg);
806
807         /* Wait until ready */
808         udelay(10);
809         if (!
810             (me4000_inl(dev, info->ai_context.status_reg) &
811              ME4000_AI_STATUS_BIT_EF_DATA)) {
812                 printk(KERN_ERR
813                        "comedi%d: me4000: me4000_ai_insn_read(): "
814                        "Value not available after wait\n", dev->minor);
815                 return -EIO;
816         }
817
818         /* Read value from data fifo */
819         lval = me4000_inl(dev, info->ai_context.data_reg) & 0xFFFF;
820         data[0] = lval ^ 0x8000;
821
822         return 1;
823 }
824
825 static int me4000_ai_cancel(struct comedi_device *dev,
826                             struct comedi_subdevice *s)
827 {
828         unsigned long tmp;
829
830         CALL_PDEBUG("In me4000_ai_cancel()\n");
831
832         /* Stop any running conversion */
833         tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
834         tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
835         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
836
837         /* Clear the control register */
838         me4000_outl(dev, 0x0, info->ai_context.ctrl_reg);
839
840         return 0;
841 }
842
843 static int ai_check_chanlist(struct comedi_device *dev,
844                              struct comedi_subdevice *s, struct comedi_cmd *cmd)
845 {
846         int aref;
847         int i;
848
849         CALL_PDEBUG("In ai_check_chanlist()\n");
850
851         /* Check whether a channel list is available */
852         if (!cmd->chanlist_len) {
853                 printk(KERN_ERR
854                        "comedi%d: me4000: ai_check_chanlist(): "
855                        "No channel list available\n", dev->minor);
856                 return -EINVAL;
857         }
858
859         /* Check the channel list size */
860         if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
861                 printk(KERN_ERR
862                        "comedi%d: me4000: ai_check_chanlist(): "
863                        "Channel list is to large\n", dev->minor);
864                 return -EINVAL;
865         }
866
867         /* Check the pointer */
868         if (!cmd->chanlist) {
869                 printk(KERN_ERR
870                        "comedi%d: me4000: ai_check_chanlist(): "
871                        "NULL pointer to channel list\n", dev->minor);
872                 return -EFAULT;
873         }
874
875         /* Check whether aref is equal for all entries */
876         aref = CR_AREF(cmd->chanlist[0]);
877         for (i = 0; i < cmd->chanlist_len; i++) {
878                 if (CR_AREF(cmd->chanlist[i]) != aref) {
879                         printk(KERN_ERR
880                                "comedi%d: me4000: ai_check_chanlist(): "
881                                "Mode is not equal for all entries\n",
882                                dev->minor);
883                         return -EINVAL;
884                 }
885         }
886
887         /* Check whether channels are available for this ending */
888         if (aref == SDF_DIFF) {
889                 for (i = 0; i < cmd->chanlist_len; i++) {
890                         if (CR_CHAN(cmd->chanlist[i]) >=
891                             thisboard->ai.diff_count) {
892                                 printk(KERN_ERR
893                                        "comedi%d: me4000: ai_check_chanlist():"
894                                        " Channel number to high\n", dev->minor);
895                                 return -EINVAL;
896                         }
897                 }
898         } else {
899                 for (i = 0; i < cmd->chanlist_len; i++) {
900                         if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
901                                 printk(KERN_ERR
902                                        "comedi%d: me4000: ai_check_chanlist(): "
903                                        "Channel number to high\n", dev->minor);
904                                 return -EINVAL;
905                         }
906                 }
907         }
908
909         /* Check if bipolar is set for all entries when in differential mode */
910         if (aref == SDF_DIFF) {
911                 for (i = 0; i < cmd->chanlist_len; i++) {
912                         if (CR_RANGE(cmd->chanlist[i]) != 1 &&
913                             CR_RANGE(cmd->chanlist[i]) != 2) {
914                                 printk(KERN_ERR
915                                        "comedi%d: me4000: ai_check_chanlist(): "
916                                        "Bipolar is not selected in "
917                                        "differential mode\n",
918                                        dev->minor);
919                                 return -EINVAL;
920                         }
921                 }
922         }
923
924         return 0;
925 }
926
927 static int ai_round_cmd_args(struct comedi_device *dev,
928                              struct comedi_subdevice *s,
929                              struct comedi_cmd *cmd,
930                              unsigned int *init_ticks,
931                              unsigned int *scan_ticks, unsigned int *chan_ticks)
932 {
933
934         int rest;
935
936         CALL_PDEBUG("In ai_round_cmd_args()\n");
937
938         *init_ticks = 0;
939         *scan_ticks = 0;
940         *chan_ticks = 0;
941
942         PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd->start_arg);
943         PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
944                cmd->scan_begin_arg);
945         PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd->convert_arg);
946
947         if (cmd->start_arg) {
948                 *init_ticks = (cmd->start_arg * 33) / 1000;
949                 rest = (cmd->start_arg * 33) % 1000;
950
951                 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
952                         if (rest > 33)
953                                 (*init_ticks)++;
954                 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
955                         if (rest)
956                                 (*init_ticks)++;
957                 }
958         }
959
960         if (cmd->scan_begin_arg) {
961                 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
962                 rest = (cmd->scan_begin_arg * 33) % 1000;
963
964                 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
965                         if (rest > 33)
966                                 (*scan_ticks)++;
967                 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
968                         if (rest)
969                                 (*scan_ticks)++;
970                 }
971         }
972
973         if (cmd->convert_arg) {
974                 *chan_ticks = (cmd->convert_arg * 33) / 1000;
975                 rest = (cmd->convert_arg * 33) % 1000;
976
977                 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
978                         if (rest > 33)
979                                 (*chan_ticks)++;
980                 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
981                         if (rest)
982                                 (*chan_ticks)++;
983                 }
984         }
985
986         PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks);
987         PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks);
988         PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks);
989
990         return 0;
991 }
992
993 static void ai_write_timer(struct comedi_device *dev,
994                            unsigned int init_ticks,
995                            unsigned int scan_ticks, unsigned int chan_ticks)
996 {
997
998         CALL_PDEBUG("In ai_write_timer()\n");
999
1000         me4000_outl(dev, init_ticks - 1,
1001                     info->ai_context.scan_pre_timer_low_reg);
1002         me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg);
1003
1004         if (scan_ticks) {
1005                 me4000_outl(dev, scan_ticks - 1,
1006                             info->ai_context.scan_timer_low_reg);
1007                 me4000_outl(dev, 0x0, info->ai_context.scan_timer_high_reg);
1008         }
1009
1010         me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
1011         me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
1012 }
1013
1014 static int ai_prepare(struct comedi_device *dev,
1015                       struct comedi_subdevice *s,
1016                       struct comedi_cmd *cmd,
1017                       unsigned int init_ticks,
1018                       unsigned int scan_ticks, unsigned int chan_ticks)
1019 {
1020
1021         unsigned long tmp = 0;
1022
1023         CALL_PDEBUG("In ai_prepare()\n");
1024
1025         /* Write timer arguments */
1026         ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
1027
1028         /* Reset control register */
1029         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1030
1031         /* Start sources */
1032         if ((cmd->start_src == TRIG_EXT &&
1033              cmd->scan_begin_src == TRIG_TIMER &&
1034              cmd->convert_src == TRIG_TIMER) ||
1035             (cmd->start_src == TRIG_EXT &&
1036              cmd->scan_begin_src == TRIG_FOLLOW &&
1037              cmd->convert_src == TRIG_TIMER)) {
1038                 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
1039                     ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1040                     ME4000_AI_CTRL_BIT_DATA_FIFO;
1041         } else if (cmd->start_src == TRIG_EXT &&
1042                    cmd->scan_begin_src == TRIG_EXT &&
1043                    cmd->convert_src == TRIG_TIMER) {
1044                 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
1045                     ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1046                     ME4000_AI_CTRL_BIT_DATA_FIFO;
1047         } else if (cmd->start_src == TRIG_EXT &&
1048                    cmd->scan_begin_src == TRIG_EXT &&
1049                    cmd->convert_src == TRIG_EXT) {
1050                 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1051                     ME4000_AI_CTRL_BIT_MODE_1 |
1052                     ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1053                     ME4000_AI_CTRL_BIT_DATA_FIFO;
1054         } else {
1055                 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1056                     ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1057                     ME4000_AI_CTRL_BIT_DATA_FIFO;
1058         }
1059
1060         /* Stop triggers */
1061         if (cmd->stop_src == TRIG_COUNT) {
1062                 me4000_outl(dev, cmd->chanlist_len * cmd->stop_arg,
1063                             info->ai_context.sample_counter_reg);
1064                 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1065         } else if (cmd->stop_src == TRIG_NONE &&
1066                    cmd->scan_end_src == TRIG_COUNT) {
1067                 me4000_outl(dev, cmd->scan_end_arg,
1068                             info->ai_context.sample_counter_reg);
1069                 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1070         } else {
1071                 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
1072         }
1073
1074         /* Write the setup to the control register */
1075         me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1076
1077         /* Write the channel list */
1078         ai_write_chanlist(dev, s, cmd);
1079
1080         return 0;
1081 }
1082
1083 static int ai_write_chanlist(struct comedi_device *dev,
1084                              struct comedi_subdevice *s, struct comedi_cmd *cmd)
1085 {
1086         unsigned int entry;
1087         unsigned int chan;
1088         unsigned int rang;
1089         unsigned int aref;
1090         int i;
1091
1092         CALL_PDEBUG("In ai_write_chanlist()\n");
1093
1094         for (i = 0; i < cmd->chanlist_len; i++) {
1095                 chan = CR_CHAN(cmd->chanlist[i]);
1096                 rang = CR_RANGE(cmd->chanlist[i]);
1097                 aref = CR_AREF(cmd->chanlist[i]);
1098
1099                 entry = chan;
1100
1101                 if (rang == 0)
1102                         entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1103                 else if (rang == 1)
1104                         entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1105                 else if (rang == 2)
1106                         entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1107                 else
1108                         entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1109
1110                 if (aref == SDF_DIFF)
1111                         entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1112                 else
1113                         entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1114
1115                 me4000_outl(dev, entry, info->ai_context.channel_list_reg);
1116         }
1117
1118         return 0;
1119 }
1120
1121 static int me4000_ai_do_cmd(struct comedi_device *dev,
1122                             struct comedi_subdevice *s)
1123 {
1124         int err;
1125         unsigned int init_ticks = 0;
1126         unsigned int scan_ticks = 0;
1127         unsigned int chan_ticks = 0;
1128         struct comedi_cmd *cmd = &s->async->cmd;
1129
1130         CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1131
1132         /* Reset the analog input */
1133         err = me4000_ai_cancel(dev, s);
1134         if (err)
1135                 return err;
1136
1137         /* Round the timer arguments */
1138         err = ai_round_cmd_args(dev,
1139                                 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1140         if (err)
1141                 return err;
1142
1143         /* Prepare the AI for acquisition */
1144         err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1145         if (err)
1146                 return err;
1147
1148         /* Start acquistion by dummy read */
1149         me4000_inl(dev, info->ai_context.start_reg);
1150
1151         return 0;
1152 }
1153
1154 /*
1155  * me4000_ai_do_cmd_test():
1156  *
1157  * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1158  * - success
1159  * - invalid source
1160  * - source conflict
1161  * - invalid argument
1162  * - argument conflict
1163  * - invalid chanlist
1164  * So I tried to adopt this scheme.
1165  */
1166 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1167                                  struct comedi_subdevice *s,
1168                                  struct comedi_cmd *cmd)
1169 {
1170
1171         unsigned int init_ticks;
1172         unsigned int chan_ticks;
1173         unsigned int scan_ticks;
1174         int err = 0;
1175
1176         CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1177
1178         PDEBUG("me4000_ai_do_cmd_test(): subdev         = %d\n", cmd->subdev);
1179         PDEBUG("me4000_ai_do_cmd_test(): flags          = %08X\n", cmd->flags);
1180         PDEBUG("me4000_ai_do_cmd_test(): start_src      = %08X\n",
1181                cmd->start_src);
1182         PDEBUG("me4000_ai_do_cmd_test(): start_arg      = %d\n",
1183                cmd->start_arg);
1184         PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
1185                cmd->scan_begin_src);
1186         PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
1187                cmd->scan_begin_arg);
1188         PDEBUG("me4000_ai_do_cmd_test(): convert_src    = %08X\n",
1189                cmd->convert_src);
1190         PDEBUG("me4000_ai_do_cmd_test(): convert_arg    = %d\n",
1191                cmd->convert_arg);
1192         PDEBUG("me4000_ai_do_cmd_test(): scan_end_src   = %08X\n",
1193                cmd->scan_end_src);
1194         PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg   = %d\n",
1195                cmd->scan_end_arg);
1196         PDEBUG("me4000_ai_do_cmd_test(): stop_src       = %08X\n",
1197                cmd->stop_src);
1198         PDEBUG("me4000_ai_do_cmd_test(): stop_arg       = %d\n", cmd->stop_arg);
1199         PDEBUG("me4000_ai_do_cmd_test(): chanlist       = %d\n",
1200                (unsigned int)cmd->chanlist);
1201         PDEBUG("me4000_ai_do_cmd_test(): chanlist_len   = %d\n",
1202                cmd->chanlist_len);
1203
1204         /* Only rounding flags are implemented */
1205         cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1206
1207         /* Round the timer arguments */
1208         ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1209
1210         /*
1211          * Stage 1. Check if the trigger sources are generally valid.
1212          */
1213         switch (cmd->start_src) {
1214         case TRIG_NOW:
1215         case TRIG_EXT:
1216                 break;
1217         case TRIG_ANY:
1218                 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1219                 err++;
1220                 break;
1221         default:
1222                 printk(KERN_ERR
1223                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1224                        "Invalid start source\n", dev->minor);
1225                 cmd->start_src = TRIG_NOW;
1226                 err++;
1227         }
1228         switch (cmd->scan_begin_src) {
1229         case TRIG_FOLLOW:
1230         case TRIG_TIMER:
1231         case TRIG_EXT:
1232                 break;
1233         case TRIG_ANY:
1234                 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1235                 err++;
1236                 break;
1237         default:
1238                 printk(KERN_ERR
1239                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1240                        "Invalid scan begin source\n", dev->minor);
1241                 cmd->scan_begin_src = TRIG_FOLLOW;
1242                 err++;
1243         }
1244         switch (cmd->convert_src) {
1245         case TRIG_TIMER:
1246         case TRIG_EXT:
1247                 break;
1248         case TRIG_ANY:
1249                 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1250                 err++;
1251                 break;
1252         default:
1253                 printk(KERN_ERR
1254                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1255                        "Invalid convert source\n", dev->minor);
1256                 cmd->convert_src = TRIG_TIMER;
1257                 err++;
1258         }
1259         switch (cmd->scan_end_src) {
1260         case TRIG_NONE:
1261         case TRIG_COUNT:
1262                 break;
1263         case TRIG_ANY:
1264                 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1265                 err++;
1266                 break;
1267         default:
1268                 printk(KERN_ERR
1269                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1270                        "Invalid scan end source\n", dev->minor);
1271                 cmd->scan_end_src = TRIG_NONE;
1272                 err++;
1273         }
1274         switch (cmd->stop_src) {
1275         case TRIG_NONE:
1276         case TRIG_COUNT:
1277                 break;
1278         case TRIG_ANY:
1279                 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1280                 err++;
1281                 break;
1282         default:
1283                 printk(KERN_ERR
1284                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1285                        "Invalid stop source\n", dev->minor);
1286                 cmd->stop_src = TRIG_NONE;
1287                 err++;
1288         }
1289         if (err)
1290                 return 1;
1291
1292         /*
1293          * Stage 2. Check for trigger source conflicts.
1294          */
1295         if (cmd->start_src == TRIG_NOW &&
1296             cmd->scan_begin_src == TRIG_TIMER &&
1297             cmd->convert_src == TRIG_TIMER) {
1298         } else if (cmd->start_src == TRIG_NOW &&
1299                    cmd->scan_begin_src == TRIG_FOLLOW &&
1300                    cmd->convert_src == TRIG_TIMER) {
1301         } else if (cmd->start_src == TRIG_EXT &&
1302                    cmd->scan_begin_src == TRIG_TIMER &&
1303                    cmd->convert_src == TRIG_TIMER) {
1304         } else if (cmd->start_src == TRIG_EXT &&
1305                    cmd->scan_begin_src == TRIG_FOLLOW &&
1306                    cmd->convert_src == TRIG_TIMER) {
1307         } else if (cmd->start_src == TRIG_EXT &&
1308                    cmd->scan_begin_src == TRIG_EXT &&
1309                    cmd->convert_src == TRIG_TIMER) {
1310         } else if (cmd->start_src == TRIG_EXT &&
1311                    cmd->scan_begin_src == TRIG_EXT &&
1312                    cmd->convert_src == TRIG_EXT) {
1313         } else {
1314                 printk(KERN_ERR
1315                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1316                        "Invalid start trigger combination\n", dev->minor);
1317                 cmd->start_src = TRIG_NOW;
1318                 cmd->scan_begin_src = TRIG_FOLLOW;
1319                 cmd->convert_src = TRIG_TIMER;
1320                 err++;
1321         }
1322
1323         if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1324         } else if (cmd->stop_src == TRIG_COUNT &&
1325                    cmd->scan_end_src == TRIG_NONE) {
1326         } else if (cmd->stop_src == TRIG_NONE &&
1327                    cmd->scan_end_src == TRIG_COUNT) {
1328         } else if (cmd->stop_src == TRIG_COUNT &&
1329                    cmd->scan_end_src == TRIG_COUNT) {
1330         } else {
1331                 printk(KERN_ERR
1332                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1333                        "Invalid stop trigger combination\n", dev->minor);
1334                 cmd->stop_src = TRIG_NONE;
1335                 cmd->scan_end_src = TRIG_NONE;
1336                 err++;
1337         }
1338         if (err)
1339                 return 2;
1340
1341         /*
1342          * Stage 3. Check if arguments are generally valid.
1343          */
1344         if (cmd->chanlist_len < 1) {
1345                 printk(KERN_ERR
1346                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1347                        "No channel list\n", dev->minor);
1348                 cmd->chanlist_len = 1;
1349                 err++;
1350         }
1351         if (init_ticks < 66) {
1352                 printk(KERN_ERR
1353                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1354                        "Start arg to low\n", dev->minor);
1355                 cmd->start_arg = 2000;
1356                 err++;
1357         }
1358         if (scan_ticks && scan_ticks < 67) {
1359                 printk(KERN_ERR
1360                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1361                        "Scan begin arg to low\n", dev->minor);
1362                 cmd->scan_begin_arg = 2031;
1363                 err++;
1364         }
1365         if (chan_ticks < 66) {
1366                 printk(KERN_ERR
1367                        "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1368                        "Convert arg to low\n", dev->minor);
1369                 cmd->convert_arg = 2000;
1370                 err++;
1371         }
1372
1373         if (err)
1374                 return 3;
1375
1376         /*
1377          * Stage 4. Check for argument conflicts.
1378          */
1379         if (cmd->start_src == TRIG_NOW &&
1380             cmd->scan_begin_src == TRIG_TIMER &&
1381             cmd->convert_src == TRIG_TIMER) {
1382
1383                 /* Check timer arguments */
1384                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1385                         printk(KERN_ERR
1386                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1387                                "Invalid start arg\n", dev->minor);
1388                         cmd->start_arg = 2000;  /*  66 ticks at least */
1389                         err++;
1390                 }
1391                 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1392                         printk(KERN_ERR
1393                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1394                                "Invalid convert arg\n", dev->minor);
1395                         cmd->convert_arg = 2000;        /*  66 ticks at least */
1396                         err++;
1397                 }
1398                 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1399                         printk(KERN_ERR
1400                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1401                                "Invalid scan end arg\n", dev->minor);
1402
1403                         /*  At least one tick more */
1404                         cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1405                         err++;
1406                 }
1407         } else if (cmd->start_src == TRIG_NOW &&
1408                    cmd->scan_begin_src == TRIG_FOLLOW &&
1409                    cmd->convert_src == TRIG_TIMER) {
1410
1411                 /* Check timer arguments */
1412                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1413                         printk(KERN_ERR
1414                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1415                                "Invalid start arg\n", dev->minor);
1416                         cmd->start_arg = 2000;  /*  66 ticks at least */
1417                         err++;
1418                 }
1419                 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1420                         printk(KERN_ERR
1421                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1422                                "Invalid convert arg\n", dev->minor);
1423                         cmd->convert_arg = 2000;        /*  66 ticks at least */
1424                         err++;
1425                 }
1426         } else if (cmd->start_src == TRIG_EXT &&
1427                    cmd->scan_begin_src == TRIG_TIMER &&
1428                    cmd->convert_src == TRIG_TIMER) {
1429
1430                 /* Check timer arguments */
1431                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1432                         printk(KERN_ERR
1433                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1434                                "Invalid start arg\n", dev->minor);
1435                         cmd->start_arg = 2000;  /*  66 ticks at least */
1436                         err++;
1437                 }
1438                 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1439                         printk(KERN_ERR
1440                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1441                                "Invalid convert arg\n", dev->minor);
1442                         cmd->convert_arg = 2000;        /*  66 ticks at least */
1443                         err++;
1444                 }
1445                 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1446                         printk(KERN_ERR
1447                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1448                                "Invalid scan end arg\n", dev->minor);
1449
1450                         /*  At least one tick more */
1451                         cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1452                         err++;
1453                 }
1454         } else if (cmd->start_src == TRIG_EXT &&
1455                    cmd->scan_begin_src == TRIG_FOLLOW &&
1456                    cmd->convert_src == TRIG_TIMER) {
1457
1458                 /* Check timer arguments */
1459                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1460                         printk(KERN_ERR
1461                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1462                                "Invalid start arg\n", dev->minor);
1463                         cmd->start_arg = 2000;  /*  66 ticks at least */
1464                         err++;
1465                 }
1466                 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1467                         printk(KERN_ERR
1468                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1469                                "Invalid convert arg\n", dev->minor);
1470                         cmd->convert_arg = 2000;        /*  66 ticks at least */
1471                         err++;
1472                 }
1473         } else if (cmd->start_src == TRIG_EXT &&
1474                    cmd->scan_begin_src == TRIG_EXT &&
1475                    cmd->convert_src == TRIG_TIMER) {
1476
1477                 /* Check timer arguments */
1478                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1479                         printk(KERN_ERR
1480                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1481                                "Invalid start arg\n", dev->minor);
1482                         cmd->start_arg = 2000;  /*  66 ticks at least */
1483                         err++;
1484                 }
1485                 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1486                         printk(KERN_ERR
1487                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1488                                "Invalid convert arg\n", dev->minor);
1489                         cmd->convert_arg = 2000;        /*  66 ticks at least */
1490                         err++;
1491                 }
1492         } else if (cmd->start_src == TRIG_EXT &&
1493                    cmd->scan_begin_src == TRIG_EXT &&
1494                    cmd->convert_src == TRIG_EXT) {
1495
1496                 /* Check timer arguments */
1497                 if (init_ticks < ME4000_AI_MIN_TICKS) {
1498                         printk(KERN_ERR
1499                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1500                                "Invalid start arg\n", dev->minor);
1501                         cmd->start_arg = 2000;  /*  66 ticks at least */
1502                         err++;
1503                 }
1504         }
1505         if (cmd->stop_src == TRIG_COUNT) {
1506                 if (cmd->stop_arg == 0) {
1507                         printk(KERN_ERR
1508                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1509                                "Invalid stop arg\n", dev->minor);
1510                         cmd->stop_arg = 1;
1511                         err++;
1512                 }
1513         }
1514         if (cmd->scan_end_src == TRIG_COUNT) {
1515                 if (cmd->scan_end_arg == 0) {
1516                         printk(KERN_ERR
1517                                "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1518                                "Invalid scan end arg\n", dev->minor);
1519                         cmd->scan_end_arg = 1;
1520                         err++;
1521                 }
1522         }
1523
1524         if (err)
1525                 return 4;
1526
1527         /*
1528          * Stage 5. Check the channel list.
1529          */
1530         if (ai_check_chanlist(dev, s, cmd))
1531                 return 5;
1532
1533         return 0;
1534 }
1535
1536 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1537 {
1538         unsigned int tmp;
1539         struct comedi_device *dev = dev_id;
1540         struct comedi_subdevice *s = dev->subdevices;
1541         struct me4000_ai_context *ai_context = &info->ai_context;
1542         int i;
1543         int c = 0;
1544         long lval;
1545
1546         ISR_PDEBUG("me4000_ai_isr() is executed\n");
1547
1548         if (!dev->attached) {
1549                 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1550                 return IRQ_NONE;
1551         }
1552
1553         /* Reset all events */
1554         s->async->events = 0;
1555
1556         /* Check if irq number is right */
1557         if (irq != ai_context->irq) {
1558                 printk(KERN_ERR
1559                        "comedi%d: me4000: me4000_ai_isr(): "
1560                        "Incorrect interrupt num: %d\n", dev->minor, irq);
1561                 return IRQ_HANDLED;
1562         }
1563
1564         if (me4000_inl(dev,
1565                        ai_context->irq_status_reg) &
1566             ME4000_IRQ_STATUS_BIT_AI_HF) {
1567                 ISR_PDEBUG
1568                     ("me4000_ai_isr(): Fifo half full interrupt occurred\n");
1569
1570                 /* Read status register to find out what happened */
1571                 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1572
1573                 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1574                     !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1575                     (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1576                         ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1577                         c = ME4000_AI_FIFO_COUNT;
1578
1579                         /*
1580                          * FIFO overflow, so stop conversion
1581                          * and disable all interrupts
1582                          */
1583                         tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1584                         tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1585                                  ME4000_AI_CTRL_BIT_SC_IRQ);
1586                         me4000_outl(dev, tmp, ai_context->ctrl_reg);
1587
1588                         s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1589
1590                         printk(KERN_ERR
1591                                "comedi%d: me4000: me4000_ai_isr(): "
1592                                "FIFO overflow\n", dev->minor);
1593                 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1594                            && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1595                            && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1596                         ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1597
1598                         s->async->events |= COMEDI_CB_BLOCK;
1599
1600                         c = ME4000_AI_FIFO_COUNT / 2;
1601                 } else {
1602                         printk(KERN_ERR
1603                                "comedi%d: me4000: me4000_ai_isr(): "
1604                                "Can't determine state of fifo\n", dev->minor);
1605                         c = 0;
1606
1607                         /*
1608                          * Undefined state, so stop conversion
1609                          * and disable all interrupts
1610                          */
1611                         tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1612                         tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1613                                  ME4000_AI_CTRL_BIT_SC_IRQ);
1614                         me4000_outl(dev, tmp, ai_context->ctrl_reg);
1615
1616                         s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1617
1618                         printk(KERN_ERR
1619                                "comedi%d: me4000: me4000_ai_isr(): "
1620                                "Undefined FIFO state\n", dev->minor);
1621                 }
1622
1623                 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c);
1624
1625                 for (i = 0; i < c; i++) {
1626                         /* Read value from data fifo */
1627                         lval = inl(ai_context->data_reg) & 0xFFFF;
1628                         lval ^= 0x8000;
1629
1630                         if (!comedi_buf_put(s->async, lval)) {
1631                                 /*
1632                                  * Buffer overflow, so stop conversion
1633                                  * and disable all interrupts
1634                                  */
1635                                 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1636                                 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1637                                          ME4000_AI_CTRL_BIT_SC_IRQ);
1638                                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1639
1640                                 s->async->events |= COMEDI_CB_OVERFLOW;
1641
1642                                 printk(KERN_ERR
1643                                        "comedi%d: me4000: me4000_ai_isr(): "
1644                                        "Buffer overflow\n", dev->minor);
1645
1646                                 break;
1647                         }
1648                 }
1649
1650                 /* Work is done, so reset the interrupt */
1651                 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1652                 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1653                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1654                 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1655                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1656         }
1657
1658         if (me4000_inl(dev,
1659                        ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1660                 ISR_PDEBUG
1661                     ("me4000_ai_isr(): Sample counter interrupt occurred\n");
1662
1663                 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1664
1665                 /*
1666                  * Acquisition is complete, so stop
1667                  * conversion and disable all interrupts
1668                  */
1669                 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1670                 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1671                 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1672                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1673
1674                 /* Poll data until fifo empty */
1675                 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1676                         /* Read value from data fifo */
1677                         lval = inl(ai_context->data_reg) & 0xFFFF;
1678                         lval ^= 0x8000;
1679
1680                         if (!comedi_buf_put(s->async, lval)) {
1681                                 printk(KERN_ERR
1682                                        "comedi%d: me4000: me4000_ai_isr(): "
1683                                        "Buffer overflow\n", dev->minor);
1684                                 s->async->events |= COMEDI_CB_OVERFLOW;
1685                                 break;
1686                         }
1687                 }
1688
1689                 /* Work is done, so reset the interrupt */
1690                 ISR_PDEBUG
1691                     ("me4000_ai_isr(): Reset interrupt from sample counter\n");
1692                 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1693                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1694                 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1695                 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1696         }
1697
1698         ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events);
1699
1700         if (s->async->events)
1701                 comedi_event(dev, s);
1702
1703         return IRQ_HANDLED;
1704 }
1705
1706 /*=============================================================================
1707   Analog output section
1708   ===========================================================================*/
1709
1710 static int me4000_ao_insn_write(struct comedi_device *dev,
1711                                 struct comedi_subdevice *s,
1712                                 struct comedi_insn *insn, unsigned int *data)
1713 {
1714
1715         int chan = CR_CHAN(insn->chanspec);
1716         int rang = CR_RANGE(insn->chanspec);
1717         int aref = CR_AREF(insn->chanspec);
1718         unsigned long tmp;
1719
1720         CALL_PDEBUG("In me4000_ao_insn_write()\n");
1721
1722         if (insn->n == 0) {
1723                 return 0;
1724         } else if (insn->n > 1) {
1725                 printk(KERN_ERR
1726                        "comedi%d: me4000: me4000_ao_insn_write(): "
1727                        "Invalid instruction length %d\n", dev->minor, insn->n);
1728                 return -EINVAL;
1729         }
1730
1731         if (chan >= thisboard->ao.count) {
1732                 printk(KERN_ERR
1733                        "comedi%d: me4000: me4000_ao_insn_write(): "
1734                        "Invalid channel %d\n", dev->minor, insn->n);
1735                 return -EINVAL;
1736         }
1737
1738         if (rang != 0) {
1739                 printk(KERN_ERR
1740                        "comedi%d: me4000: me4000_ao_insn_write(): "
1741                        "Invalid range %d\n", dev->minor, insn->n);
1742                 return -EINVAL;
1743         }
1744
1745         if (aref != AREF_GROUND && aref != AREF_COMMON) {
1746                 printk(KERN_ERR
1747                        "comedi%d: me4000: me4000_ao_insn_write(): "
1748                        "Invalid aref %d\n", dev->minor, insn->n);
1749                 return -EINVAL;
1750         }
1751
1752         /* Stop any running conversion */
1753         tmp = me4000_inl(dev, info->ao_context[chan].ctrl_reg);
1754         tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1755         me4000_outl(dev, tmp, info->ao_context[chan].ctrl_reg);
1756
1757         /* Clear control register and set to single mode */
1758         me4000_outl(dev, 0x0, info->ao_context[chan].ctrl_reg);
1759
1760         /* Write data value */
1761         me4000_outl(dev, data[0], info->ao_context[chan].single_reg);
1762
1763         /* Store in the mirror */
1764         info->ao_context[chan].mirror = data[0];
1765
1766         return 1;
1767 }
1768
1769 static int me4000_ao_insn_read(struct comedi_device *dev,
1770                                struct comedi_subdevice *s,
1771                                struct comedi_insn *insn, unsigned int *data)
1772 {
1773         int chan = CR_CHAN(insn->chanspec);
1774
1775         if (insn->n == 0) {
1776                 return 0;
1777         } else if (insn->n > 1) {
1778                 printk
1779                     ("comedi%d: me4000: me4000_ao_insn_read(): "
1780                      "Invalid instruction length\n", dev->minor);
1781                 return -EINVAL;
1782         }
1783
1784         data[0] = info->ao_context[chan].mirror;
1785
1786         return 1;
1787 }
1788
1789 /*=============================================================================
1790   Digital I/O section
1791   ===========================================================================*/
1792
1793 static int me4000_dio_insn_bits(struct comedi_device *dev,
1794                                 struct comedi_subdevice *s,
1795                                 struct comedi_insn *insn, unsigned int *data)
1796 {
1797
1798         CALL_PDEBUG("In me4000_dio_insn_bits()\n");
1799
1800         /* Length of data must be 2 (mask and new data, see below) */
1801         if (insn->n == 0)
1802                 return 0;
1803
1804         if (insn->n != 2) {
1805                 printk
1806                     ("comedi%d: me4000: me4000_dio_insn_bits(): "
1807                      "Invalid instruction length\n", dev->minor);
1808                 return -EINVAL;
1809         }
1810
1811         /*
1812          * The insn data consists of a mask in data[0] and the new data
1813          * in data[1]. The mask defines which bits we are concerning about.
1814          * The new data must be anded with the mask.
1815          * Each channel corresponds to a bit.
1816          */
1817         if (data[0]) {
1818                 /* Check if requested ports are configured for output */
1819                 if ((s->io_bits & data[0]) != data[0])
1820                         return -EIO;
1821
1822                 s->state &= ~data[0];
1823                 s->state |= data[0] & data[1];
1824
1825                 /* Write out the new digital output lines */
1826                 me4000_outl(dev, (s->state >> 0) & 0xFF,
1827                             info->dio_context.port_0_reg);
1828                 me4000_outl(dev, (s->state >> 8) & 0xFF,
1829                             info->dio_context.port_1_reg);
1830                 me4000_outl(dev, (s->state >> 16) & 0xFF,
1831                             info->dio_context.port_2_reg);
1832                 me4000_outl(dev, (s->state >> 24) & 0xFF,
1833                             info->dio_context.port_3_reg);
1834         }
1835
1836         /* On return, data[1] contains the value of
1837            the digital input and output lines. */
1838         data[1] =
1839             ((me4000_inl(dev, info->dio_context.port_0_reg) & 0xFF) << 0) |
1840             ((me4000_inl(dev, info->dio_context.port_1_reg) & 0xFF) << 8) |
1841             ((me4000_inl(dev, info->dio_context.port_2_reg) & 0xFF) << 16) |
1842             ((me4000_inl(dev, info->dio_context.port_3_reg) & 0xFF) << 24);
1843
1844         return 2;
1845 }
1846
1847 static int me4000_dio_insn_config(struct comedi_device *dev,
1848                                   struct comedi_subdevice *s,
1849                                   struct comedi_insn *insn, unsigned int *data)
1850 {
1851         unsigned long tmp;
1852         int chan = CR_CHAN(insn->chanspec);
1853
1854         CALL_PDEBUG("In me4000_dio_insn_config()\n");
1855
1856         switch (data[0]) {
1857         default:
1858                 return -EINVAL;
1859         case INSN_CONFIG_DIO_QUERY:
1860                 data[1] =
1861                     (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1862                 return insn->n;
1863         case INSN_CONFIG_DIO_INPUT:
1864         case INSN_CONFIG_DIO_OUTPUT:
1865                 break;
1866         }
1867
1868         /*
1869          * The input or output configuration of each digital line is
1870          * configured by a special insn_config instruction.  chanspec
1871          * contains the channel to be changed, and data[0] contains the
1872          * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1873          * On the ME-4000 it is only possible to switch port wise (8 bit)
1874          */
1875
1876         tmp = me4000_inl(dev, info->dio_context.ctrl_reg);
1877
1878         if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1879                 if (chan < 8) {
1880                         s->io_bits |= 0xFF;
1881                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1882                                  ME4000_DIO_CTRL_BIT_MODE_1);
1883                         tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1884                 } else if (chan < 16) {
1885                         /*
1886                          * Chech for optoisolated ME-4000 version.
1887                          * If one the first port is a fixed output
1888                          * port and the second is a fixed input port.
1889                          */
1890                         if (!me4000_inl(dev, info->dio_context.dir_reg))
1891                                 return -ENODEV;
1892
1893                         s->io_bits |= 0xFF00;
1894                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1895                                  ME4000_DIO_CTRL_BIT_MODE_3);
1896                         tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1897                 } else if (chan < 24) {
1898                         s->io_bits |= 0xFF0000;
1899                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1900                                  ME4000_DIO_CTRL_BIT_MODE_5);
1901                         tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1902                 } else if (chan < 32) {
1903                         s->io_bits |= 0xFF000000;
1904                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1905                                  ME4000_DIO_CTRL_BIT_MODE_7);
1906                         tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1907                 } else {
1908                         return -EINVAL;
1909                 }
1910         } else {
1911                 if (chan < 8) {
1912                         /*
1913                          * Chech for optoisolated ME-4000 version.
1914                          * If one the first port is a fixed output
1915                          * port and the second is a fixed input port.
1916                          */
1917                         if (!me4000_inl(dev, info->dio_context.dir_reg))
1918                                 return -ENODEV;
1919
1920                         s->io_bits &= ~0xFF;
1921                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1922                                  ME4000_DIO_CTRL_BIT_MODE_1);
1923                 } else if (chan < 16) {
1924                         s->io_bits &= ~0xFF00;
1925                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1926                                  ME4000_DIO_CTRL_BIT_MODE_3);
1927                 } else if (chan < 24) {
1928                         s->io_bits &= ~0xFF0000;
1929                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1930                                  ME4000_DIO_CTRL_BIT_MODE_5);
1931                 } else if (chan < 32) {
1932                         s->io_bits &= ~0xFF000000;
1933                         tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1934                                  ME4000_DIO_CTRL_BIT_MODE_7);
1935                 } else {
1936                         return -EINVAL;
1937                 }
1938         }
1939
1940         me4000_outl(dev, tmp, info->dio_context.ctrl_reg);
1941
1942         return 1;
1943 }
1944
1945 /*=============================================================================
1946   Counter section
1947   ===========================================================================*/
1948
1949 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1950 {
1951
1952         CALL_PDEBUG("In cnt_reset()\n");
1953
1954         switch (channel) {
1955         case 0:
1956                 me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg);
1957                 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
1958                 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
1959                 break;
1960         case 1:
1961                 me4000_outb(dev, 0x70, info->cnt_context.ctrl_reg);
1962                 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
1963                 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
1964                 break;
1965         case 2:
1966                 me4000_outb(dev, 0xB0, info->cnt_context.ctrl_reg);
1967                 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
1968                 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
1969                 break;
1970         default:
1971                 printk(KERN_ERR
1972                        "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1973                        dev->minor);
1974                 return -EINVAL;
1975         }
1976
1977         return 0;
1978 }
1979
1980 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1981                       unsigned int mode)
1982 {
1983         int tmp = 0;
1984
1985         CALL_PDEBUG("In cnt_config()\n");
1986
1987         switch (channel) {
1988         case 0:
1989                 tmp |= ME4000_CNT_COUNTER_0;
1990                 break;
1991         case 1:
1992                 tmp |= ME4000_CNT_COUNTER_1;
1993                 break;
1994         case 2:
1995                 tmp |= ME4000_CNT_COUNTER_2;
1996                 break;
1997         default:
1998                 printk(KERN_ERR
1999                        "comedi%d: me4000: cnt_config(): Invalid channel\n",
2000                        dev->minor);
2001                 return -EINVAL;
2002         }
2003
2004         switch (mode) {
2005         case 0:
2006                 tmp |= ME4000_CNT_MODE_0;
2007                 break;
2008         case 1:
2009                 tmp |= ME4000_CNT_MODE_1;
2010                 break;
2011         case 2:
2012                 tmp |= ME4000_CNT_MODE_2;
2013                 break;
2014         case 3:
2015                 tmp |= ME4000_CNT_MODE_3;
2016                 break;
2017         case 4:
2018                 tmp |= ME4000_CNT_MODE_4;
2019                 break;
2020         case 5:
2021                 tmp |= ME4000_CNT_MODE_5;
2022                 break;
2023         default:
2024                 printk(KERN_ERR
2025                        "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2026                        dev->minor);
2027                 return -EINVAL;
2028         }
2029
2030         /* Write the control word */
2031         tmp |= 0x30;
2032         me4000_outb(dev, tmp, info->cnt_context.ctrl_reg);
2033
2034         return 0;
2035 }
2036
2037 static int me4000_cnt_insn_config(struct comedi_device *dev,
2038                                   struct comedi_subdevice *s,
2039                                   struct comedi_insn *insn, unsigned int *data)
2040 {
2041
2042         int err;
2043
2044         CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2045
2046         switch (data[0]) {
2047         case GPCT_RESET:
2048                 if (insn->n != 1) {
2049                         printk(KERN_ERR
2050                                "comedi%d: me4000: me4000_cnt_insn_config(): "
2051                                "Invalid instruction length%d\n",
2052                                dev->minor, insn->n);
2053                         return -EINVAL;
2054                 }
2055
2056                 err = cnt_reset(dev, insn->chanspec);
2057                 if (err)
2058                         return err;
2059                 break;
2060         case GPCT_SET_OPERATION:
2061                 if (insn->n != 2) {
2062                         printk(KERN_ERR
2063                                "comedi%d: me4000: me4000_cnt_insn_config(): "
2064                                "Invalid instruction length%d\n",
2065                                dev->minor, insn->n);
2066                         return -EINVAL;
2067                 }
2068
2069                 err = cnt_config(dev, insn->chanspec, data[1]);
2070                 if (err)
2071                         return err;
2072                 break;
2073         default:
2074                 printk(KERN_ERR
2075                        "comedi%d: me4000: me4000_cnt_insn_config(): "
2076                        "Invalid instruction\n", dev->minor);
2077                 return -EINVAL;
2078         }
2079
2080         return 2;
2081 }
2082
2083 static int me4000_cnt_insn_read(struct comedi_device *dev,
2084                                 struct comedi_subdevice *s,
2085                                 struct comedi_insn *insn, unsigned int *data)
2086 {
2087
2088         unsigned short tmp;
2089
2090         CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2091
2092         if (insn->n == 0)
2093                 return 0;
2094
2095         if (insn->n > 1) {
2096                 printk(KERN_ERR
2097                        "comedi%d: me4000: me4000_cnt_insn_read(): "
2098                        "Invalid instruction length %d\n",
2099                        dev->minor, insn->n);
2100                 return -EINVAL;
2101         }
2102
2103         switch (insn->chanspec) {
2104         case 0:
2105                 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2106                 data[0] = tmp;
2107                 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2108                 data[0] |= tmp << 8;
2109                 break;
2110         case 1:
2111                 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2112                 data[0] = tmp;
2113                 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2114                 data[0] |= tmp << 8;
2115                 break;
2116         case 2:
2117                 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2118                 data[0] = tmp;
2119                 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2120                 data[0] |= tmp << 8;
2121                 break;
2122         default:
2123                 printk(KERN_ERR
2124                        "comedi%d: me4000: me4000_cnt_insn_read(): "
2125                        "Invalid channel %d\n",
2126                        dev->minor, insn->chanspec);
2127                 return -EINVAL;
2128         }
2129
2130         return 1;
2131 }
2132
2133 static int me4000_cnt_insn_write(struct comedi_device *dev,
2134                                  struct comedi_subdevice *s,
2135                                  struct comedi_insn *insn, unsigned int *data)
2136 {
2137
2138         unsigned short tmp;
2139
2140         CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2141
2142         if (insn->n == 0) {
2143                 return 0;
2144         } else if (insn->n > 1) {
2145                 printk(KERN_ERR
2146                        "comedi%d: me4000: me4000_cnt_insn_write(): "
2147                        "Invalid instruction length %d\n",
2148                        dev->minor, insn->n);
2149                 return -EINVAL;
2150         }
2151
2152         switch (insn->chanspec) {
2153         case 0:
2154                 tmp = data[0] & 0xFF;
2155                 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2156                 tmp = (data[0] >> 8) & 0xFF;
2157                 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2158                 break;
2159         case 1:
2160                 tmp = data[0] & 0xFF;
2161                 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2162                 tmp = (data[0] >> 8) & 0xFF;
2163                 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2164                 break;
2165         case 2:
2166                 tmp = data[0] & 0xFF;
2167                 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2168                 tmp = (data[0] >> 8) & 0xFF;
2169                 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2170                 break;
2171         default:
2172                 printk(KERN_ERR
2173                        "comedi%d: me4000: me4000_cnt_insn_write(): "
2174                        "Invalid channel %d\n",
2175                        dev->minor, insn->chanspec);
2176                 return -EINVAL;
2177         }
2178
2179         return 1;
2180 }
2181
2182 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2183 {
2184         struct comedi_subdevice *s;
2185         int result;
2186
2187         CALL_PDEBUG("In me4000_attach()\n");
2188
2189         result = me4000_probe(dev, it);
2190         if (result)
2191                 return result;
2192
2193         /*
2194          * Allocate the subdevice structures.  alloc_subdevice() is a
2195          * convenient macro defined in comedidev.h.  It relies on
2196          * n_subdevices being set correctly.
2197          */
2198         if (comedi_alloc_subdevices(dev, 4) < 0)
2199                 return -ENOMEM;
2200
2201     /*=========================================================================
2202       Analog input subdevice
2203       ========================================================================*/
2204
2205         s = dev->subdevices + 0;
2206
2207         if (thisboard->ai.count) {
2208                 s->type = COMEDI_SUBD_AI;
2209                 s->subdev_flags =
2210                     SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2211                 s->n_chan = thisboard->ai.count;
2212                 s->maxdata = 0xFFFF;    /*  16 bit ADC */
2213                 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2214                 s->range_table = &me4000_ai_range;
2215                 s->insn_read = me4000_ai_insn_read;
2216
2217                 if (info->irq > 0) {
2218                         if (request_irq(info->irq, me4000_ai_isr,
2219                                         IRQF_SHARED, "ME-4000", dev)) {
2220                                 printk
2221                                     ("comedi%d: me4000: me4000_attach(): "
2222                                      "Unable to allocate irq\n", dev->minor);
2223                         } else {
2224                                 dev->read_subdev = s;
2225                                 s->subdev_flags |= SDF_CMD_READ;
2226                                 s->cancel = me4000_ai_cancel;
2227                                 s->do_cmdtest = me4000_ai_do_cmd_test;
2228                                 s->do_cmd = me4000_ai_do_cmd;
2229                         }
2230                 } else {
2231                         printk(KERN_WARNING
2232                                "comedi%d: me4000: me4000_attach(): "
2233                                "No interrupt available\n", dev->minor);
2234                 }
2235         } else {
2236                 s->type = COMEDI_SUBD_UNUSED;
2237         }
2238
2239     /*=========================================================================
2240       Analog output subdevice
2241       ========================================================================*/
2242
2243         s = dev->subdevices + 1;
2244
2245         if (thisboard->ao.count) {
2246                 s->type = COMEDI_SUBD_AO;
2247                 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2248                 s->n_chan = thisboard->ao.count;
2249                 s->maxdata = 0xFFFF;    /*  16 bit DAC */
2250                 s->range_table = &me4000_ao_range;
2251                 s->insn_write = me4000_ao_insn_write;
2252                 s->insn_read = me4000_ao_insn_read;
2253         } else {
2254                 s->type = COMEDI_SUBD_UNUSED;
2255         }
2256
2257     /*=========================================================================
2258       Digital I/O subdevice
2259       ========================================================================*/
2260
2261         s = dev->subdevices + 2;
2262
2263         if (thisboard->dio.count) {
2264                 s->type = COMEDI_SUBD_DIO;
2265                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2266                 s->n_chan = thisboard->dio.count * 8;
2267                 s->maxdata = 1;
2268                 s->range_table = &range_digital;
2269                 s->insn_bits = me4000_dio_insn_bits;
2270                 s->insn_config = me4000_dio_insn_config;
2271         } else {
2272                 s->type = COMEDI_SUBD_UNUSED;
2273         }
2274
2275         /*
2276          * Check for optoisolated ME-4000 version. If one the first
2277          * port is a fixed output port and the second is a fixed input port.
2278          */
2279         if (!me4000_inl(dev, info->dio_context.dir_reg)) {
2280                 s->io_bits |= 0xFF;
2281                 me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
2282                             info->dio_context.dir_reg);
2283         }
2284
2285     /*=========================================================================
2286       Counter subdevice
2287       ========================================================================*/
2288
2289         s = dev->subdevices + 3;
2290
2291         if (thisboard->cnt.count) {
2292                 s->type = COMEDI_SUBD_COUNTER;
2293                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2294                 s->n_chan = thisboard->cnt.count;
2295                 s->maxdata = 0xFFFF;    /*  16 bit counters */
2296                 s->insn_read = me4000_cnt_insn_read;
2297                 s->insn_write = me4000_cnt_insn_write;
2298                 s->insn_config = me4000_cnt_insn_config;
2299         } else {
2300                 s->type = COMEDI_SUBD_UNUSED;
2301         }
2302
2303         return 0;
2304 }
2305
2306 static void me4000_detach(struct comedi_device *dev)
2307 {
2308         if (info) {
2309                 if (info->pci_dev_p) {
2310                         reset_board(dev);
2311                         if (info->plx_regbase)
2312                                 comedi_pci_disable(info->pci_dev_p);
2313                         pci_dev_put(info->pci_dev_p);
2314                 }
2315         }
2316 }
2317
2318 static struct comedi_driver me4000_driver = {
2319         .driver_name    = "me4000",
2320         .module         = THIS_MODULE,
2321         .attach         = me4000_attach,
2322         .detach         = me4000_detach,
2323 };
2324
2325 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2326                                       const struct pci_device_id *ent)
2327 {
2328         return comedi_pci_auto_config(dev, &me4000_driver);
2329 }
2330
2331 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2332 {
2333         comedi_pci_auto_unconfig(dev);
2334 }
2335
2336 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2337         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
2338         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
2339         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
2340         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
2341         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
2342         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
2343         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
2344         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
2345         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
2346         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
2347         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
2348         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
2349         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
2350         { 0 }
2351 };
2352 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2353
2354 static struct pci_driver me4000_pci_driver = {
2355         .name           = "me4000",
2356         .id_table       = me4000_pci_table,
2357         .probe          = me4000_pci_probe,
2358         .remove         = __devexit_p(me4000_pci_remove),
2359 };
2360 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2361
2362 MODULE_AUTHOR("Comedi http://www.comedi.org");
2363 MODULE_DESCRIPTION("Comedi low-level driver");
2364 MODULE_LICENSE("GPL");