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