]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/staging/comedi/drivers/me_daq.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6.git] / drivers / staging / comedi / drivers / me_daq.c
1 /*
2
3    comedi/drivers/me_daq.c
4
5    Hardware driver for Meilhaus data acquisition cards:
6
7      ME-2000i, ME-2600i, ME-3000vm1
8
9    Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>
10
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*
27 Driver: me_daq
28 Description: Meilhaus PCI data acquisition cards
29 Author: Michael Hillmann <hillmann@syscongroup.de>
30 Devices: [Meilhaus] ME-2600i (me_daq), ME-2000i
31 Status: experimental
32
33 Supports:
34
35     Analog Output
36
37 Configuration options:
38
39     [0] - PCI bus number (optional)
40     [1] - PCI slot number (optional)
41
42     If bus/slot is not specified, the first available PCI
43     device will be used.
44
45 The 2600 requires a firmware upload, which can be accomplished
46 using the -i or --init-data option of comedi_config.
47 The firmware can be
48 found in the comedi_nonfree_firmware tarball available
49 from http://www.comedi.org
50
51 */
52
53 #include <linux/interrupt.h>
54 #include <linux/sched.h>
55 #include "../comedidev.h"
56
57 #include "comedi_pci.h"
58
59 /*#include "me2600_fw.h" */
60
61 #define ME_DRIVER_NAME          "me_daq"
62
63 #define PCI_VENDOR_ID_MEILHAUS  0x1402
64 #define ME2000_DEVICE_ID        0x2000
65 #define ME2600_DEVICE_ID        0x2600
66
67 #define PLX_INTCSR              0x4C    /* PLX interrupt status register */
68 #define XILINX_DOWNLOAD_RESET   0x42    /* Xilinx registers */
69
70 #define ME_CONTROL_1                    0x0000  /* - | W */
71 #define   INTERRUPT_ENABLE              (1<<15)
72 #define   COUNTER_B_IRQ                 (1<<12)
73 #define   COUNTER_A_IRQ                 (1<<11)
74 #define   CHANLIST_READY_IRQ            (1<<10)
75 #define   EXT_IRQ                       (1<<9)
76 #define   ADFIFO_HALFFULL_IRQ           (1<<8)
77 #define   SCAN_COUNT_ENABLE             (1<<5)
78 #define   SIMULTANEOUS_ENABLE           (1<<4)
79 #define   TRIGGER_FALLING_EDGE          (1<<3)
80 #define   CONTINUOUS_MODE               (1<<2)
81 #define   DISABLE_ADC                   (0<<0)
82 #define   SOFTWARE_TRIGGERED_ADC        (1<<0)
83 #define   SCAN_TRIGGERED_ADC            (2<<0)
84 #define   EXT_TRIGGERED_ADC             (3<<0)
85 #define ME_ADC_START                    0x0000  /* R | - */
86 #define ME_CONTROL_2                    0x0002  /* - | W */
87 #define   ENABLE_ADFIFO                 (1<<10)
88 #define   ENABLE_CHANLIST               (1<<9)
89 #define   ENABLE_PORT_B                 (1<<7)
90 #define   ENABLE_PORT_A                 (1<<6)
91 #define   ENABLE_COUNTER_B              (1<<4)
92 #define   ENABLE_COUNTER_A              (1<<3)
93 #define   ENABLE_DAC                    (1<<1)
94 #define   BUFFERED_DAC                  (1<<0)
95 #define ME_DAC_UPDATE                   0x0002  /* R | - */
96 #define ME_STATUS                       0x0004  /* R | - */
97 #define   COUNTER_B_IRQ_PENDING         (1<<12)
98 #define   COUNTER_A_IRQ_PENDING         (1<<11)
99 #define   CHANLIST_READY_IRQ_PENDING    (1<<10)
100 #define   EXT_IRQ_PENDING               (1<<9)
101 #define   ADFIFO_HALFFULL_IRQ_PENDING   (1<<8)
102 #define   ADFIFO_FULL                   (1<<4)
103 #define   ADFIFO_HALFFULL               (1<<3)
104 #define   ADFIFO_EMPTY                  (1<<2)
105 #define   CHANLIST_FULL                 (1<<1)
106 #define   FST_ACTIVE                    (1<<0)
107 #define ME_RESET_INTERRUPT              0x0004  /* - | W */
108 #define ME_DIO_PORT_A                   0x0006  /* R | W */
109 #define ME_DIO_PORT_B                   0x0008  /* R | W */
110 #define ME_TIMER_DATA_0                 0x000A  /* - | W */
111 #define ME_TIMER_DATA_1                 0x000C  /* - | W */
112 #define ME_TIMER_DATA_2                 0x000E  /* - | W */
113 #define ME_CHANNEL_LIST                 0x0010  /* - | W */
114 #define   ADC_UNIPOLAR                  (1<<6)
115 #define   ADC_GAIN_0                    (0<<4)
116 #define   ADC_GAIN_1                    (1<<4)
117 #define   ADC_GAIN_2                    (2<<4)
118 #define   ADC_GAIN_3                    (3<<4)
119 #define ME_READ_AD_FIFO                 0x0010  /* R | - */
120 #define ME_DAC_CONTROL                  0x0012  /* - | W */
121 #define   DAC_UNIPOLAR_D                (0<<4)
122 #define   DAC_BIPOLAR_D                 (1<<4)
123 #define   DAC_UNIPOLAR_C                (0<<5)
124 #define   DAC_BIPOLAR_C                 (1<<5)
125 #define   DAC_UNIPOLAR_B                (0<<6)
126 #define   DAC_BIPOLAR_B                 (1<<6)
127 #define   DAC_UNIPOLAR_A                (0<<7)
128 #define   DAC_BIPOLAR_A                 (1<<7)
129 #define   DAC_GAIN_0_D                  (0<<8)
130 #define   DAC_GAIN_1_D                  (1<<8)
131 #define   DAC_GAIN_0_C                  (0<<9)
132 #define   DAC_GAIN_1_C                  (1<<9)
133 #define   DAC_GAIN_0_B                  (0<<10)
134 #define   DAC_GAIN_1_B                  (1<<10)
135 #define   DAC_GAIN_0_A                  (0<<11)
136 #define   DAC_GAIN_1_A                  (1<<11)
137 #define ME_DAC_CONTROL_UPDATE           0x0012  /* R | - */
138 #define ME_DAC_DATA_A                   0x0014  /* - | W */
139 #define ME_DAC_DATA_B                   0x0016  /* - | W */
140 #define ME_DAC_DATA_C                   0x0018  /* - | W */
141 #define ME_DAC_DATA_D                   0x001A  /* - | W */
142 #define ME_COUNTER_ENDDATA_A            0x001C  /* - | W */
143 #define ME_COUNTER_ENDDATA_B            0x001E  /* - | W */
144 #define ME_COUNTER_STARTDATA_A          0x0020  /* - | W */
145 #define ME_COUNTER_VALUE_A              0x0020  /* R | - */
146 #define ME_COUNTER_STARTDATA_B          0x0022  /* - | W */
147 #define ME_COUNTER_VALUE_B              0x0022  /* R | - */
148
149 /* Function prototypes */
150 static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it);
151 static int me_detach(struct comedi_device *dev);
152
153 static const struct comedi_lrange me2000_ai_range = {
154         8,
155         {
156          BIP_RANGE(10),
157          BIP_RANGE(5),
158          BIP_RANGE(2.5),
159          BIP_RANGE(1.25),
160          UNI_RANGE(10),
161          UNI_RANGE(5),
162          UNI_RANGE(2.5),
163          UNI_RANGE(1.25)
164          }
165 };
166
167 static const struct comedi_lrange me2600_ai_range = {
168         8,
169         {
170          BIP_RANGE(10),
171          BIP_RANGE(5),
172          BIP_RANGE(2.5),
173          BIP_RANGE(1.25),
174          UNI_RANGE(10),
175          UNI_RANGE(5),
176          UNI_RANGE(2.5),
177          UNI_RANGE(1.25)
178          }
179 };
180
181 static const struct comedi_lrange me2600_ao_range = {
182         3,
183         {
184          BIP_RANGE(10),
185          BIP_RANGE(5),
186          UNI_RANGE(10)
187          }
188 };
189
190 static DEFINE_PCI_DEVICE_TABLE(me_pci_table) = {
191         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
192         { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
193         {0}
194 };
195
196 MODULE_DEVICE_TABLE(pci, me_pci_table);
197
198 /* Board specification structure */
199 struct me_board {
200         const char *name;       /* driver name */
201         int device_id;
202         int ao_channel_nbr;     /* DA config */
203         int ao_resolution;
204         int ao_resolution_mask;
205         const struct comedi_lrange *ao_range_list;
206         int ai_channel_nbr;     /* AD config */
207         int ai_resolution;
208         int ai_resolution_mask;
209         const struct comedi_lrange *ai_range_list;
210         int dio_channel_nbr;    /* DIO config */
211 };
212
213 static const struct me_board me_boards[] = {
214         {
215          /* -- ME-2600i -- */
216          .name = ME_DRIVER_NAME,
217          .device_id = ME2600_DEVICE_ID,
218          /* Analog Output */
219          .ao_channel_nbr = 4,
220          .ao_resolution = 12,
221          .ao_resolution_mask = 0x0fff,
222          .ao_range_list = &me2600_ao_range,
223          .ai_channel_nbr = 16,
224          /* Analog Input */
225          .ai_resolution = 12,
226          .ai_resolution_mask = 0x0fff,
227          .ai_range_list = &me2600_ai_range,
228          .dio_channel_nbr = 32,
229          },
230         {
231          /* -- ME-2000i -- */
232          .name = ME_DRIVER_NAME,
233          .device_id = ME2000_DEVICE_ID,
234          /* Analog Output */
235          .ao_channel_nbr = 0,
236          .ao_resolution = 0,
237          .ao_resolution_mask = 0,
238          .ao_range_list = NULL,
239          .ai_channel_nbr = 16,
240          /* Analog Input */
241          .ai_resolution = 12,
242          .ai_resolution_mask = 0x0fff,
243          .ai_range_list = &me2000_ai_range,
244          .dio_channel_nbr = 32,
245          }
246 };
247
248 #define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board))
249
250 static struct comedi_driver me_driver = {
251         .driver_name = ME_DRIVER_NAME,
252         .module = THIS_MODULE,
253         .attach = me_attach,
254         .detach = me_detach,
255 };
256
257 static int __devinit me_driver_pci_probe(struct pci_dev *dev,
258                                          const struct pci_device_id *ent)
259 {
260         return comedi_pci_auto_config(dev, me_driver.driver_name);
261 }
262
263 static void __devexit me_driver_pci_remove(struct pci_dev *dev)
264 {
265         comedi_pci_auto_unconfig(dev);
266 }
267
268 static struct pci_driver me_driver_pci_driver = {
269         .id_table = me_pci_table,
270         .probe = &me_driver_pci_probe,
271         .remove = __devexit_p(&me_driver_pci_remove)
272 };
273
274 static int __init me_driver_init_module(void)
275 {
276         int retval;
277
278         retval = comedi_driver_register(&me_driver);
279         if (retval < 0)
280                 return retval;
281
282         me_driver_pci_driver.name = (char *)me_driver.driver_name;
283         return pci_register_driver(&me_driver_pci_driver);
284 }
285
286 static void __exit me_driver_cleanup_module(void)
287 {
288         pci_unregister_driver(&me_driver_pci_driver);
289         comedi_driver_unregister(&me_driver);
290 }
291
292 module_init(me_driver_init_module);
293 module_exit(me_driver_cleanup_module);
294
295 /* Private data structure */
296 struct me_private_data {
297         struct pci_dev *pci_device;
298         void __iomem *plx_regbase;      /* PLX configuration base address */
299         void __iomem *me_regbase;       /* Base address of the Meilhaus card */
300         unsigned long plx_regbase_size; /* Size of PLX configuration space */
301         unsigned long me_regbase_size;  /* Size of Meilhaus space */
302
303         unsigned short control_1;       /* Mirror of CONTROL_1 register */
304         unsigned short control_2;       /* Mirror of CONTROL_2 register */
305         unsigned short dac_control;     /* Mirror of the DAC_CONTROL register */
306         int ao_readback[4];     /* Mirror of analog output data */
307 };
308
309 #define dev_private ((struct me_private_data *)dev->private)
310
311 /*
312  * ------------------------------------------------------------------
313  *
314  * Helpful functions
315  *
316  * ------------------------------------------------------------------
317  */
318 static inline void sleep(unsigned sec)
319 {
320         current->state = TASK_INTERRUPTIBLE;
321         schedule_timeout(sec * HZ);
322 }
323
324 /*
325  * ------------------------------------------------------------------
326  *
327  * DIGITAL INPUT/OUTPUT SECTION
328  *
329  * ------------------------------------------------------------------
330  */
331 static int me_dio_insn_config(struct comedi_device *dev,
332                               struct comedi_subdevice *s,
333                               struct comedi_insn *insn, unsigned int *data)
334 {
335         int bits;
336         int mask = 1 << CR_CHAN(insn->chanspec);
337
338         /* calculate port */
339         if (mask & 0x0000ffff) {        /* Port A in use */
340                 bits = 0x0000ffff;
341
342                 /* Enable Port A */
343                 dev_private->control_2 |= ENABLE_PORT_A;
344                 writew(dev_private->control_2,
345                        dev_private->me_regbase + ME_CONTROL_2);
346         } else {                /* Port B in use */
347
348                 bits = 0xffff0000;
349
350                 /* Enable Port B */
351                 dev_private->control_2 |= ENABLE_PORT_B;
352                 writew(dev_private->control_2,
353                        dev_private->me_regbase + ME_CONTROL_2);
354         }
355
356         if (data[0]) {
357                 /* Config port as output */
358                 s->io_bits |= bits;
359         } else {
360                 /* Config port as input */
361                 s->io_bits &= ~bits;
362         }
363
364         return 1;
365 }
366
367 /* Digital instant input/outputs */
368 static int me_dio_insn_bits(struct comedi_device *dev,
369                             struct comedi_subdevice *s,
370                             struct comedi_insn *insn, unsigned int *data)
371 {
372         unsigned int mask = data[0];
373         s->state &= ~mask;
374         s->state |= (mask & data[1]);
375
376         mask &= s->io_bits;
377         if (mask & 0x0000ffff) {        /* Port A */
378                 writew((s->state & 0xffff),
379                        dev_private->me_regbase + ME_DIO_PORT_A);
380         } else {
381                 data[1] &= ~0x0000ffff;
382                 data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_A);
383         }
384
385         if (mask & 0xffff0000) {        /* Port B */
386                 writew(((s->state >> 16) & 0xffff),
387                        dev_private->me_regbase + ME_DIO_PORT_B);
388         } else {
389                 data[1] &= ~0xffff0000;
390                 data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16;
391         }
392
393         return 2;
394 }
395
396 /*
397  * ------------------------------------------------------------------
398  *
399  * ANALOG INPUT SECTION
400  *
401  * ------------------------------------------------------------------
402  */
403
404 /* Analog instant input */
405 static int me_ai_insn_read(struct comedi_device *dev,
406                            struct comedi_subdevice *subdevice,
407                            struct comedi_insn *insn, unsigned int *data)
408 {
409         unsigned short value;
410         int chan = CR_CHAN((&insn->chanspec)[0]);
411         int rang = CR_RANGE((&insn->chanspec)[0]);
412         int aref = CR_AREF((&insn->chanspec)[0]);
413         int i;
414
415         /* stop any running conversion */
416         dev_private->control_1 &= 0xFFFC;
417         writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
418
419         /* clear chanlist and ad fifo */
420         dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST);
421         writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
422
423         /* reset any pending interrupt */
424         writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
425
426         /* enable the chanlist and ADC fifo */
427         dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST);
428         writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
429
430         /* write to channel list fifo */
431         /* b3:b0 are the channel number */
432         value = chan & 0x0f;
433         /* b5:b4 are the channel gain */
434         value |= (rang & 0x03) << 4;
435         /* b6 channel polarity */
436         value |= (rang & 0x04) << 4;
437         /* b7 single or differential */
438         value |= ((aref & AREF_DIFF) ? 0x80 : 0);
439         writew(value & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
440
441         /* set ADC mode to software trigger */
442         dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;
443         writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
444
445         /* start conversion by reading from ADC_START */
446         readw(dev_private->me_regbase + ME_ADC_START);
447
448         /* wait for ADC fifo not empty flag */
449         for (i = 100000; i > 0; i--)
450                 if (!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004))
451                         break;
452
453         /* get value from ADC fifo */
454         if (i) {
455                 data[0] =
456                     (readw(dev_private->me_regbase +
457                            ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF;
458         } else {
459                 printk(KERN_ERR "comedi%d: Cannot get single value\n",
460                        dev->minor);
461                 return -EIO;
462         }
463
464         /* stop any running conversion */
465         dev_private->control_1 &= 0xFFFC;
466         writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
467
468         return 1;
469 }
470
471 /*
472  * ------------------------------------------------------------------
473  *
474  * HARDWARE TRIGGERED ANALOG INPUT SECTION
475  *
476  * ------------------------------------------------------------------
477  */
478
479 /* Cancel analog input autoscan */
480 static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
481 {
482         /* disable interrupts */
483
484         /* stop any running conversion */
485         dev_private->control_1 &= 0xFFFC;
486         writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
487
488         return 0;
489 }
490
491 /* Test analog input command */
492 static int me_ai_do_cmd_test(struct comedi_device *dev,
493                              struct comedi_subdevice *s, struct comedi_cmd *cmd)
494 {
495         return 0;
496 }
497
498 /* Analog input command */
499 static int me_ai_do_cmd(struct comedi_device *dev,
500                         struct comedi_subdevice *subdevice)
501 {
502         return 0;
503 }
504
505 /*
506  * ------------------------------------------------------------------
507  *
508  * ANALOG OUTPUT SECTION
509  *
510  * ------------------------------------------------------------------
511  */
512
513 /* Analog instant output */
514 static int me_ao_insn_write(struct comedi_device *dev,
515                             struct comedi_subdevice *s,
516                             struct comedi_insn *insn, unsigned int *data)
517 {
518         int chan;
519         int rang;
520         int i;
521
522         /* Enable all DAC */
523         dev_private->control_2 |= ENABLE_DAC;
524         writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
525
526         /* and set DAC to "buffered" mode */
527         dev_private->control_2 |= BUFFERED_DAC;
528         writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
529
530         /* Set dac-control register */
531         for (i = 0; i < insn->n; i++) {
532                 chan = CR_CHAN((&insn->chanspec)[i]);
533                 rang = CR_RANGE((&insn->chanspec)[i]);
534
535                 /* clear bits for this channel */
536                 dev_private->dac_control &= ~(0x0880 >> chan);
537                 if (rang == 0)
538                         dev_private->dac_control |=
539                             ((DAC_BIPOLAR_A | DAC_GAIN_1_A) >> chan);
540                 else if (rang == 1)
541                         dev_private->dac_control |=
542                             ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan);
543         }
544         writew(dev_private->dac_control,
545                dev_private->me_regbase + ME_DAC_CONTROL);
546
547         /* Update dac-control register */
548         readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE);
549
550         /* Set data register */
551         for (i = 0; i < insn->n; i++) {
552                 chan = CR_CHAN((&insn->chanspec)[i]);
553                 writew((data[0] & s->maxdata),
554                        dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1));
555                 dev_private->ao_readback[chan] = (data[0] & s->maxdata);
556         }
557
558         /* Update dac with data registers */
559         readw(dev_private->me_regbase + ME_DAC_UPDATE);
560
561         return i;
562 }
563
564 /* Analog output readback */
565 static int me_ao_insn_read(struct comedi_device *dev,
566                            struct comedi_subdevice *s, struct comedi_insn *insn,
567                            unsigned int *data)
568 {
569         int i;
570
571         for (i = 0; i < insn->n; i++) {
572                 data[i] =
573                     dev_private->ao_readback[CR_CHAN((&insn->chanspec)[i])];
574         }
575
576         return 1;
577 }
578
579 /*
580  * ------------------------------------------------------------------
581  *
582  * INITIALISATION SECTION
583  *
584  * ------------------------------------------------------------------
585  */
586
587 /* Xilinx firmware download for card: ME-2600i */
588 static int me2600_xilinx_download(struct comedi_device *dev,
589                                   unsigned char *me2600_firmware,
590                                   unsigned int length)
591 {
592         unsigned int value;
593         unsigned int file_length;
594         unsigned int i;
595
596         /* disable irq's on PLX */
597         writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
598
599         /* First, make a dummy read to reset xilinx */
600         value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET);
601
602         /* Wait until reset is over */
603         sleep(1);
604
605         /* Write a dummy value to Xilinx */
606         writeb(0x00, dev_private->me_regbase + 0x0);
607         sleep(1);
608
609         /*
610          * Format of the firmware
611          * Build longs from the byte-wise coded header
612          * Byte 1-3:   length of the array
613          * Byte 4-7:   version
614          * Byte 8-11:  date
615          * Byte 12-15: reserved
616          */
617         if (length < 16)
618                 return -EINVAL;
619         file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) +
620             (((unsigned int)me2600_firmware[1] & 0xff) << 16) +
621             (((unsigned int)me2600_firmware[2] & 0xff) << 8) +
622             ((unsigned int)me2600_firmware[3] & 0xff);
623
624         /*
625          * Loop for writing firmware byte by byte to xilinx
626          * Firmware data start at offfset 16
627          */
628         for (i = 0; i < file_length; i++)
629                 writeb((me2600_firmware[16 + i] & 0xff),
630                        dev_private->me_regbase + 0x0);
631
632         /* Write 5 dummy values to xilinx */
633         for (i = 0; i < 5; i++)
634                 writeb(0x00, dev_private->me_regbase + 0x0);
635
636         /* Test if there was an error during download -> INTB was thrown */
637         value = readl(dev_private->plx_regbase + PLX_INTCSR);
638         if (value & 0x20) {
639                 /* Disable interrupt */
640                 writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
641                 printk(KERN_ERR "comedi%d: Xilinx download failed\n",
642                        dev->minor);
643                 return -EIO;
644         }
645
646         /* Wait until the Xilinx is ready for real work */
647         sleep(1);
648
649         /* Enable PLX-Interrupts */
650         writel(0x43, dev_private->plx_regbase + PLX_INTCSR);
651
652         return 0;
653 }
654
655 /* Reset device */
656 static int me_reset(struct comedi_device *dev)
657 {
658         /* Reset board */
659         writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
660         writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
661         writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
662         writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL);
663
664         /* Save values in the board context */
665         dev_private->dac_control = 0;
666         dev_private->control_1 = 0;
667         dev_private->control_2 = 0;
668
669         return 0;
670 }
671
672 /*
673  * Attach
674  *
675  * - Register PCI device
676  * - Declare device driver capability
677  */
678 static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
679 {
680         struct pci_dev *pci_device = NULL;
681         struct comedi_subdevice *subdevice;
682         struct me_board *board;
683         resource_size_t plx_regbase_tmp;
684         unsigned long plx_regbase_size_tmp;
685         resource_size_t me_regbase_tmp;
686         unsigned long me_regbase_size_tmp;
687         resource_size_t swap_regbase_tmp;
688         unsigned long swap_regbase_size_tmp;
689         resource_size_t regbase_tmp;
690         int result, error, i;
691
692         /* Allocate private memory */
693         if (alloc_private(dev, sizeof(struct me_private_data)) < 0)
694                 return -ENOMEM;
695
696         /* Probe the device to determine what device in the series it is. */
697         for_each_pci_dev(pci_device) {
698                 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
699                         for (i = 0; i < me_board_nbr; i++) {
700                                 if (me_boards[i].device_id ==
701                                     pci_device->device) {
702                                         /*
703                                          * was a particular bus/slot requested?
704                                          */
705                                         if ((it->options[0] != 0)
706                                             || (it->options[1] != 0)) {
707                                                 /*
708                                                  * are we on the wrong bus/slot?
709                                                  */
710                                                 if (pci_device->bus->number !=
711                                                     it->options[0]
712                                                     ||
713                                                     PCI_SLOT(pci_device->devfn)
714                                                     != it->options[1]) {
715                                                         continue;
716                                                 }
717                                         }
718
719                                         dev->board_ptr = me_boards + i;
720                                         board =
721                                             (struct me_board *)dev->board_ptr;
722                                         dev_private->pci_device = pci_device;
723                                         goto found;
724                                 }
725                         }
726                 }
727         }
728
729         printk(KERN_ERR
730                "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
731                dev->minor, it->options[0], it->options[1]);
732         return -EIO;
733
734 found:
735         printk(KERN_INFO "comedi%d: found %s at PCI bus %d, slot %d\n",
736                dev->minor, me_boards[i].name,
737                pci_device->bus->number, PCI_SLOT(pci_device->devfn));
738
739         /* Enable PCI device and request PCI regions */
740         if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) {
741                 printk(KERN_ERR "comedi%d: Failed to enable PCI device and "
742                        "request regions\n", dev->minor);
743                 return -EIO;
744         }
745
746         /* Set data in device structure */
747         dev->board_name = board->name;
748
749         /* Read PLX register base address [PCI_BASE_ADDRESS #0]. */
750         plx_regbase_tmp = pci_resource_start(pci_device, 0);
751         plx_regbase_size_tmp = pci_resource_len(pci_device, 0);
752         dev_private->plx_regbase =
753             ioremap(plx_regbase_tmp, plx_regbase_size_tmp);
754         dev_private->plx_regbase_size = plx_regbase_size_tmp;
755         if (!dev_private->plx_regbase) {
756                 printk("comedi%d: Failed to remap I/O memory\n", dev->minor);
757                 return -ENOMEM;
758         }
759
760         /* Read Swap base address [PCI_BASE_ADDRESS #5]. */
761
762         swap_regbase_tmp = pci_resource_start(pci_device, 5);
763         swap_regbase_size_tmp = pci_resource_len(pci_device, 5);
764
765         if (!swap_regbase_tmp)
766                 printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor);
767
768         /*---------------------------------------------- Workaround start ---*/
769         if (plx_regbase_tmp & 0x0080) {
770                 printk(KERN_ERR "comedi%d: PLX-Bug detected\n", dev->minor);
771
772                 if (swap_regbase_tmp) {
773                         regbase_tmp = plx_regbase_tmp;
774                         plx_regbase_tmp = swap_regbase_tmp;
775                         swap_regbase_tmp = regbase_tmp;
776
777                         result = pci_write_config_dword(pci_device,
778                                                         PCI_BASE_ADDRESS_0,
779                                                         plx_regbase_tmp);
780                         if (result != PCIBIOS_SUCCESSFUL)
781                                 return -EIO;
782
783                         result = pci_write_config_dword(pci_device,
784                                                         PCI_BASE_ADDRESS_5,
785                                                         swap_regbase_tmp);
786                         if (result != PCIBIOS_SUCCESSFUL)
787                                 return -EIO;
788                 } else {
789                         plx_regbase_tmp -= 0x80;
790                         result = pci_write_config_dword(pci_device,
791                                                         PCI_BASE_ADDRESS_0,
792                                                         plx_regbase_tmp);
793                         if (result != PCIBIOS_SUCCESSFUL)
794                                 return -EIO;
795                 }
796         }
797         /*--------------------------------------------- Workaround end -----*/
798
799         /* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */
800
801         me_regbase_tmp = pci_resource_start(pci_device, 2);
802         me_regbase_size_tmp = pci_resource_len(pci_device, 2);
803         dev_private->me_regbase_size = me_regbase_size_tmp;
804         dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp);
805         if (!dev_private->me_regbase) {
806                 printk(KERN_ERR "comedi%d: Failed to remap I/O memory\n",
807                        dev->minor);
808                 return -ENOMEM;
809         }
810         /* Download firmware and reset card */
811         if (board->device_id == ME2600_DEVICE_ID) {
812                 unsigned char *aux_data;
813                 int aux_len;
814
815                 aux_data = comedi_aux_data(it->options, 0);
816                 aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
817
818                 if (!aux_data || aux_len < 1) {
819                         comedi_error(dev, "You must provide me2600 firmware "
820                                      "using the --init-data option of "
821                                      "comedi_config");
822                         return -EINVAL;
823                 }
824                 me2600_xilinx_download(dev, aux_data, aux_len);
825         }
826
827         me_reset(dev);
828
829         /* device driver capabilities */
830         error = alloc_subdevices(dev, 3);
831         if (error < 0)
832                 return error;
833
834         subdevice = dev->subdevices + 0;
835         subdevice->type = COMEDI_SUBD_AI;
836         subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
837         subdevice->n_chan = board->ai_channel_nbr;
838         subdevice->maxdata = board->ai_resolution_mask;
839         subdevice->len_chanlist = board->ai_channel_nbr;
840         subdevice->range_table = board->ai_range_list;
841         subdevice->cancel = me_ai_cancel;
842         subdevice->insn_read = me_ai_insn_read;
843         subdevice->do_cmdtest = me_ai_do_cmd_test;
844         subdevice->do_cmd = me_ai_do_cmd;
845
846         subdevice = dev->subdevices + 1;
847         subdevice->type = COMEDI_SUBD_AO;
848         subdevice->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
849         subdevice->n_chan = board->ao_channel_nbr;
850         subdevice->maxdata = board->ao_resolution_mask;
851         subdevice->len_chanlist = board->ao_channel_nbr;
852         subdevice->range_table = board->ao_range_list;
853         subdevice->insn_read = me_ao_insn_read;
854         subdevice->insn_write = me_ao_insn_write;
855
856         subdevice = dev->subdevices + 2;
857         subdevice->type = COMEDI_SUBD_DIO;
858         subdevice->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
859         subdevice->n_chan = board->dio_channel_nbr;
860         subdevice->maxdata = 1;
861         subdevice->len_chanlist = board->dio_channel_nbr;
862         subdevice->range_table = &range_digital;
863         subdevice->insn_bits = me_dio_insn_bits;
864         subdevice->insn_config = me_dio_insn_config;
865         subdevice->io_bits = 0;
866
867         printk(KERN_INFO "comedi%d: " ME_DRIVER_NAME " attached.\n",
868                dev->minor);
869         return 0;
870 }
871
872 /* Detach */
873 static int me_detach(struct comedi_device *dev)
874 {
875         if (dev_private) {
876                 if (dev_private->me_regbase) {
877                         me_reset(dev);
878                         iounmap(dev_private->me_regbase);
879                 }
880                 if (dev_private->plx_regbase)
881                         iounmap(dev_private->plx_regbase);
882                 if (dev_private->pci_device) {
883                         if (dev_private->plx_regbase_size)
884                                 comedi_pci_disable(dev_private->pci_device);
885
886                         pci_dev_put(dev_private->pci_device);
887                 }
888         }
889         return 0;
890 }
891
892 MODULE_AUTHOR("Comedi http://www.comedi.org");
893 MODULE_DESCRIPTION("Comedi low-level driver");
894 MODULE_LICENSE("GPL");