linux/drivers/staging/comedi/drivers/cb_pcidda.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/cb_pcidda.c
   3    This intends to be a driver for the ComputerBoards / MeasurementComputing
   4    PCI-DDA series.
   5
   6         Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
   7    Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
   8
   9    COMEDI - Linux Control and Measurement Device Interface
  10    Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
  11
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 2 of the License, or
  15    (at your option) any later version.
  16
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21
  22    You should have received a copy of the GNU General Public License
  23    along with this program; if not, write to the Free Software
  24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25
  26*/
  27/*
  28Driver: cb_pcidda
  29Description: MeasurementComputing PCI-DDA series
  30Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
  31Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
  32Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
  33  PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
  34
  35Configuration options:
  36  [0] - PCI bus of device (optional)
  37  [1] - PCI slot of device (optional)
  38  If bus/slot is not specified, the first available PCI
  39  device will be used.
  40
  41Only simple analog output writing is supported.
  42
  43So far it has only been tested with:
  44  - PCI-DDA08/12
  45Please report success/failure with other different cards to
  46<comedi@comedi.org>.
  47*/
  48
  49#include "../comedidev.h"
  50
  51#include "comedi_pci.h"
  52#include "8255.h"
  53
  54#define PCI_VENDOR_ID_CB        0x1307  /*  PCI vendor number of ComputerBoards */
  55#define N_BOARDS        10      /*  Number of boards in cb_pcidda_boards */
  56#define EEPROM_SIZE     128     /*  number of entries in eeprom */
  57#define MAX_AO_CHANNELS 8       /*  maximum number of ao channels for supported boards */
  58
  59/* PCI-DDA base addresses */
  60#define DIGITALIO_BADRINDEX     2
  61        /*  DIGITAL I/O is pci_dev->resource[2] */
  62#define DIGITALIO_SIZE 8
  63        /*  DIGITAL I/O uses 8 I/O port addresses */
  64#define DAC_BADRINDEX   3
  65        /*  DAC is pci_dev->resource[3] */
  66
  67/* Digital I/O registers */
  68#define PORT1A 0                /*  PORT 1A DATA */
  69
  70#define PORT1B 1                /*  PORT 1B DATA */
  71
  72#define PORT1C 2                /*  PORT 1C DATA */
  73
  74#define CONTROL1 3              /*  CONTROL REGISTER 1 */
  75
  76#define PORT2A 4                /*  PORT 2A DATA */
  77
  78#define PORT2B 5                /*  PORT 2B DATA */
  79
  80#define PORT2C 6                /*  PORT 2C DATA */
  81
  82#define CONTROL2 7              /*  CONTROL REGISTER 2 */
  83
  84/* DAC registers */
  85#define DACONTROL       0       /*  D/A CONTROL REGISTER */
  86#define SU      0000001         /*  Simultaneous update enabled */
  87#define NOSU    0000000         /*  Simultaneous update disabled */
  88#define ENABLEDAC       0000002 /*  Enable specified DAC */
  89#define DISABLEDAC      0000000 /*  Disable specified DAC */
  90#define RANGE2V5        0000000 /*  2.5V */
  91#define RANGE5V 0000200         /*  5V */
  92#define RANGE10V        0000300 /*  10V */
  93#define UNIP    0000400         /*  Unipolar outputs */
  94#define BIP     0000000         /*  Bipolar outputs */
  95
  96#define DACALIBRATION1  4       /*  D/A CALIBRATION REGISTER 1 */
  97/* write bits */
  98#define SERIAL_IN_BIT   0x1     /*  serial data input for eeprom, caldacs, reference dac */
  99#define CAL_CHANNEL_MASK        (0x7 << 1)
 100#define CAL_CHANNEL_BITS(channel)       (((channel) << 1) & CAL_CHANNEL_MASK)
 101/* read bits */
 102#define CAL_COUNTER_MASK        0x1f
 103#define CAL_COUNTER_OVERFLOW_BIT        0x20    /*  calibration counter overflow status bit */
 104#define AO_BELOW_REF_BIT        0x40    /*  analog output is less than reference dac voltage */
 105#define SERIAL_OUT_BIT  0x80    /*  serial data out, for reading from eeprom */
 106
 107#define DACALIBRATION2  6       /*  D/A CALIBRATION REGISTER 2 */
 108#define SELECT_EEPROM_BIT       0x1     /*  send serial data in to eeprom */
 109#define DESELECT_REF_DAC_BIT    0x2     /*  don't send serial data to MAX542 reference dac */
 110#define DESELECT_CALDAC_BIT(n)  (0x4 << (n))    /*  don't send serial data to caldac n */
 111#define DUMMY_BIT       0x40    /*  manual says to set this bit with no explanation */
 112
 113#define DADATA  8               /*  FIRST D/A DATA REGISTER (0) */
 114
 115static const struct comedi_lrange cb_pcidda_ranges = {
 116        6,
 117        {
 118         BIP_RANGE(10),
 119         BIP_RANGE(5),
 120         BIP_RANGE(2.5),
 121         UNI_RANGE(10),
 122         UNI_RANGE(5),
 123         UNI_RANGE(2.5),
 124         }
 125};
 126
 127/*
 128 * Board descriptions for two imaginary boards.  Describing the
 129 * boards in this way is optional, and completely driver-dependent.
 130 * Some drivers use arrays such as this, other do not.
 131 */
 132struct cb_pcidda_board {
 133        const char *name;
 134        char status;            /*  Driver status: */
 135
 136        /*
 137         * 0 - tested
 138         * 1 - manual read, not tested
 139         * 2 - manual not read
 140         */
 141
 142        unsigned short device_id;
 143        int ao_chans;
 144        int ao_bits;
 145        const struct comedi_lrange *ranges;
 146};
 147
 148static const struct cb_pcidda_board cb_pcidda_boards[] = {
 149        {
 150         .name = "pci-dda02/12",
 151         .status = 1,
 152         .device_id = 0x20,
 153         .ao_chans = 2,
 154         .ao_bits = 12,
 155         .ranges = &cb_pcidda_ranges,
 156         },
 157        {
 158         .name = "pci-dda04/12",
 159         .status = 1,
 160         .device_id = 0x21,
 161         .ao_chans = 4,
 162         .ao_bits = 12,
 163         .ranges = &cb_pcidda_ranges,
 164         },
 165        {
 166         .name = "pci-dda08/12",
 167         .status = 0,
 168         .device_id = 0x22,
 169         .ao_chans = 8,
 170         .ao_bits = 12,
 171         .ranges = &cb_pcidda_ranges,
 172         },
 173        {
 174         .name = "pci-dda02/16",
 175         .status = 2,
 176         .device_id = 0x23,
 177         .ao_chans = 2,
 178         .ao_bits = 16,
 179         .ranges = &cb_pcidda_ranges,
 180         },
 181        {
 182         .name = "pci-dda04/16",
 183         .status = 2,
 184         .device_id = 0x24,
 185         .ao_chans = 4,
 186         .ao_bits = 16,
 187         .ranges = &cb_pcidda_ranges,
 188         },
 189        {
 190         .name = "pci-dda08/16",
 191         .status = 0,
 192         .device_id = 0x25,
 193         .ao_chans = 8,
 194         .ao_bits = 16,
 195         .ranges = &cb_pcidda_ranges,
 196         },
 197};
 198
 199static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
 200        {
 201        PCI_VENDOR_ID_CB, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 202        PCI_VENDOR_ID_CB, 0x0021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 203        PCI_VENDOR_ID_CB, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 204        PCI_VENDOR_ID_CB, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 205        PCI_VENDOR_ID_CB, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 206        PCI_VENDOR_ID_CB, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 207        0}
 208};
 209
 210MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
 211
 212/*
 213 * Useful for shorthand access to the particular board structure
 214 */
 215#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
 216
 217/* this structure is for data unique to this hardware driver.  If
 218   several hardware drivers keep similar information in this structure,
 219   feel free to suggest moving the variable to the struct comedi_device struct.  */
 220struct cb_pcidda_private {
 221        int data;
 222
 223        /* would be useful for a PCI device */
 224        struct pci_dev *pci_dev;
 225
 226        unsigned long digitalio;
 227        unsigned long dac;
 228
 229        /* unsigned long control_status; */
 230        /* unsigned long adc_fifo; */
 231
 232        unsigned int dac_cal1_bits;     /*  bits last written to da calibration register 1 */
 233        unsigned int ao_range[MAX_AO_CHANNELS]; /*  current range settings for output channels */
 234        u16 eeprom_data[EEPROM_SIZE];   /*  software copy of board's eeprom */
 235};
 236
 237/*
 238 * most drivers define the following macro to make it easy to
 239 * access the private structure.
 240 */
 241#define devpriv ((struct cb_pcidda_private *)dev->private)
 242
 243static int cb_pcidda_attach(struct comedi_device *dev,
 244                            struct comedi_devconfig *it);
 245static int cb_pcidda_detach(struct comedi_device *dev);
 246/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
 247static int cb_pcidda_ao_winsn(struct comedi_device *dev,
 248                              struct comedi_subdevice *s,
 249                              struct comedi_insn *insn, unsigned int *data);
 250
 251/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
 252/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
 253/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
 254
 255static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
 256static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
 257                                 unsigned int num_bits);
 258static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
 259                                          unsigned int address);
 260static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
 261                                unsigned int range);
 262
 263/*
 264 * The struct comedi_driver structure tells the Comedi core module
 265 * which functions to call to configure/deconfigure (attach/detach)
 266 * the board, and also about the kernel module that contains
 267 * the device code.
 268 */
 269static struct comedi_driver driver_cb_pcidda = {
 270        .driver_name = "cb_pcidda",
 271        .module = THIS_MODULE,
 272        .attach = cb_pcidda_attach,
 273        .detach = cb_pcidda_detach,
 274};
 275
 276/*
 277 * Attach is called by the Comedi core to configure the driver
 278 * for a particular board.
 279 */
 280static int cb_pcidda_attach(struct comedi_device *dev,
 281                            struct comedi_devconfig *it)
 282{
 283        struct comedi_subdevice *s;
 284        struct pci_dev *pcidev;
 285        int index;
 286
 287        printk("comedi%d: cb_pcidda: ", dev->minor);
 288
 289/*
 290 * Allocate the private structure area.
 291 */
 292        if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
 293                return -ENOMEM;
 294
 295/*
 296 * Probe the device to determine what device in the series it is.
 297 */
 298        printk("\n");
 299
 300        for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
 301             pcidev != NULL;
 302             pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
 303                if (pcidev->vendor == PCI_VENDOR_ID_CB) {
 304                        if (it->options[0] || it->options[1]) {
 305                                if (pcidev->bus->number != it->options[0] ||
 306                                    PCI_SLOT(pcidev->devfn) != it->options[1]) {
 307                                        continue;
 308                                }
 309                        }
 310                        for (index = 0; index < N_BOARDS; index++) {
 311                                if (cb_pcidda_boards[index].device_id ==
 312                                    pcidev->device) {
 313                                        goto found;
 314                                }
 315                        }
 316                }
 317        }
 318        if (!pcidev) {
 319                printk
 320                    ("Not a ComputerBoards/MeasurementComputing card on requested position\n");
 321                return -EIO;
 322        }
 323found:
 324        devpriv->pci_dev = pcidev;
 325        dev->board_ptr = cb_pcidda_boards + index;
 326        /*  "thisboard" macro can be used from here. */
 327        printk("Found %s at requested position\n", thisboard->name);
 328
 329        /*
 330         * Enable PCI device and request regions.
 331         */
 332        if (comedi_pci_enable(pcidev, thisboard->name)) {
 333                printk
 334                    ("cb_pcidda: failed to enable PCI device and request regions\n");
 335                return -EIO;
 336        }
 337
 338/*
 339 * Allocate the I/O ports.
 340 */
 341        devpriv->digitalio =
 342            pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX);
 343        devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX);
 344
 345/*
 346 * Warn about the status of the driver.
 347 */
 348        if (thisboard->status == 2)
 349                printk
 350                    ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
 351                     "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
 352                     "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
 353
 354/*
 355 * Initialize dev->board_name.
 356 */
 357        dev->board_name = thisboard->name;
 358
 359/*
 360 * Allocate the subdevice structures.
 361 */
 362        if (alloc_subdevices(dev, 3) < 0)
 363                return -ENOMEM;
 364
 365        s = dev->subdevices + 0;
 366        /* analog output subdevice */
 367        s->type = COMEDI_SUBD_AO;
 368        s->subdev_flags = SDF_WRITABLE;
 369        s->n_chan = thisboard->ao_chans;
 370        s->maxdata = (1 << thisboard->ao_bits) - 1;
 371        s->range_table = thisboard->ranges;
 372        s->insn_write = cb_pcidda_ao_winsn;
 373
 374        /* s->subdev_flags |= SDF_CMD_READ; */
 375        /* s->do_cmd = cb_pcidda_ai_cmd; */
 376        /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
 377
 378        /*  two 8255 digital io subdevices */
 379        s = dev->subdevices + 1;
 380        subdev_8255_init(dev, s, NULL, devpriv->digitalio);
 381        s = dev->subdevices + 2;
 382        subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
 383
 384        printk(" eeprom:");
 385        for (index = 0; index < EEPROM_SIZE; index++) {
 386                devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
 387                printk(" %i:0x%x ", index, devpriv->eeprom_data[index]);
 388        }
 389        printk("\n");
 390
 391        /*  set calibrations dacs */
 392        for (index = 0; index < thisboard->ao_chans; index++)
 393                cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
 394
 395        return 1;
 396}
 397
 398/*
 399 * _detach is called to deconfigure a device.  It should deallocate
 400 * resources.
 401 * This function is also called when _attach() fails, so it should be
 402 * careful not to release resources that were not necessarily
 403 * allocated by _attach().  dev->private and dev->subdevices are
 404 * deallocated automatically by the core.
 405 */
 406static int cb_pcidda_detach(struct comedi_device *dev)
 407{
 408/*
 409 * Deallocate the I/O ports.
 410 */
 411        if (devpriv) {
 412                if (devpriv->pci_dev) {
 413                        if (devpriv->dac) {
 414                                comedi_pci_disable(devpriv->pci_dev);
 415                        }
 416                        pci_dev_put(devpriv->pci_dev);
 417                }
 418        }
 419        /*  cleanup 8255 */
 420        if (dev->subdevices) {
 421                subdev_8255_cleanup(dev, dev->subdevices + 1);
 422                subdev_8255_cleanup(dev, dev->subdevices + 2);
 423        }
 424
 425        printk("comedi%d: cb_pcidda: remove\n", dev->minor);
 426
 427        return 0;
 428}
 429
 430/*
 431 * I will program this later... ;-)
 432 */
 433#if 0
 434static int cb_pcidda_ai_cmd(struct comedi_device *dev,
 435                            struct comedi_subdevice *s)
 436{
 437        printk("cb_pcidda_ai_cmd\n");
 438        printk("subdev: %d\n", cmd->subdev);
 439        printk("flags: %d\n", cmd->flags);
 440        printk("start_src: %d\n", cmd->start_src);
 441        printk("start_arg: %d\n", cmd->start_arg);
 442        printk("scan_begin_src: %d\n", cmd->scan_begin_src);
 443        printk("convert_src: %d\n", cmd->convert_src);
 444        printk("convert_arg: %d\n", cmd->convert_arg);
 445        printk("scan_end_src: %d\n", cmd->scan_end_src);
 446        printk("scan_end_arg: %d\n", cmd->scan_end_arg);
 447        printk("stop_src: %d\n", cmd->stop_src);
 448        printk("stop_arg: %d\n", cmd->stop_arg);
 449        printk("chanlist_len: %d\n", cmd->chanlist_len);
 450}
 451#endif
 452
 453#if 0
 454static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
 455                                struct comedi_subdevice *s,
 456                                struct comedi_cmd *cmd)
 457{
 458        int err = 0;
 459        int tmp;
 460
 461        /* cmdtest tests a particular command to see if it is valid.
 462         * Using the cmdtest ioctl, a user can create a valid cmd
 463         * and then have it executes by the cmd ioctl.
 464         *
 465         * cmdtest returns 1,2,3,4 or 0, depending on which tests
 466         * the command passes. */
 467
 468        /* step 1: make sure trigger sources are trivially valid */
 469
 470        tmp = cmd->start_src;
 471        cmd->start_src &= TRIG_NOW;
 472        if (!cmd->start_src || tmp != cmd->start_src)
 473                err++;
 474
 475        tmp = cmd->scan_begin_src;
 476        cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
 477        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
 478                err++;
 479
 480        tmp = cmd->convert_src;
 481        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
 482        if (!cmd->convert_src || tmp != cmd->convert_src)
 483                err++;
 484
 485        tmp = cmd->scan_end_src;
 486        cmd->scan_end_src &= TRIG_COUNT;
 487        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
 488                err++;
 489
 490        tmp = cmd->stop_src;
 491        cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
 492        if (!cmd->stop_src || tmp != cmd->stop_src)
 493                err++;
 494
 495        if (err)
 496                return 1;
 497
 498        /* step 2: make sure trigger sources are unique and mutually compatible */
 499
 500        /* note that mutual compatiblity is not an issue here */
 501        if (cmd->scan_begin_src != TRIG_TIMER
 502            && cmd->scan_begin_src != TRIG_EXT)
 503                err++;
 504        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
 505                err++;
 506        if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
 507                err++;
 508
 509        if (err)
 510                return 2;
 511
 512        /* step 3: make sure arguments are trivially compatible */
 513
 514        if (cmd->start_arg != 0) {
 515                cmd->start_arg = 0;
 516                err++;
 517        }
 518#define MAX_SPEED       10000   /* in nanoseconds */
 519#define MIN_SPEED       1000000000      /* in nanoseconds */
 520
 521        if (cmd->scan_begin_src == TRIG_TIMER) {
 522                if (cmd->scan_begin_arg < MAX_SPEED) {
 523                        cmd->scan_begin_arg = MAX_SPEED;
 524                        err++;
 525                }
 526                if (cmd->scan_begin_arg > MIN_SPEED) {
 527                        cmd->scan_begin_arg = MIN_SPEED;
 528                        err++;
 529                }
 530        } else {
 531                /* external trigger */
 532                /* should be level/edge, hi/lo specification here */
 533                /* should specify multiple external triggers */
 534                if (cmd->scan_begin_arg > 9) {
 535                        cmd->scan_begin_arg = 9;
 536                        err++;
 537                }
 538        }
 539        if (cmd->convert_src == TRIG_TIMER) {
 540                if (cmd->convert_arg < MAX_SPEED) {
 541                        cmd->convert_arg = MAX_SPEED;
 542                        err++;
 543                }
 544                if (cmd->convert_arg > MIN_SPEED) {
 545                        cmd->convert_arg = MIN_SPEED;
 546                        err++;
 547                }
 548        } else {
 549                /* external trigger */
 550                /* see above */
 551                if (cmd->convert_arg > 9) {
 552                        cmd->convert_arg = 9;
 553                        err++;
 554                }
 555        }
 556
 557        if (cmd->scan_end_arg != cmd->chanlist_len) {
 558                cmd->scan_end_arg = cmd->chanlist_len;
 559                err++;
 560        }
 561        if (cmd->stop_src == TRIG_COUNT) {
 562                if (cmd->stop_arg > 0x00ffffff) {
 563                        cmd->stop_arg = 0x00ffffff;
 564                        err++;
 565                }
 566        } else {
 567                /* TRIG_NONE */
 568                if (cmd->stop_arg != 0) {
 569                        cmd->stop_arg = 0;
 570                        err++;
 571                }
 572        }
 573
 574        if (err)
 575                return 3;
 576
 577        /* step 4: fix up any arguments */
 578
 579        if (cmd->scan_begin_src == TRIG_TIMER) {
 580                tmp = cmd->scan_begin_arg;
 581                cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
 582                                      cmd->flags & TRIG_ROUND_MASK);
 583                if (tmp != cmd->scan_begin_arg)
 584                        err++;
 585        }
 586        if (cmd->convert_src == TRIG_TIMER) {
 587                tmp = cmd->convert_arg;
 588                cb_pcidda_ns_to_timer(&cmd->convert_arg,
 589                                      cmd->flags & TRIG_ROUND_MASK);
 590                if (tmp != cmd->convert_arg)
 591                        err++;
 592                if (cmd->scan_begin_src == TRIG_TIMER &&
 593                    cmd->scan_begin_arg <
 594                    cmd->convert_arg * cmd->scan_end_arg) {
 595                        cmd->scan_begin_arg =
 596                            cmd->convert_arg * cmd->scan_end_arg;
 597                        err++;
 598                }
 599        }
 600
 601        if (err)
 602                return 4;
 603
 604        return 0;
 605}
 606#endif
 607
 608/* This function doesn't require a particular form, this is just
 609 * what happens to be used in some of the drivers.  It should
 610 * convert ns nanoseconds to a counter value suitable for programming
 611 * the device.  Also, it should adjust ns so that it cooresponds to
 612 * the actual time that the device will use. */
 613#if 0
 614static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
 615{
 616        /* trivial timer */
 617        return *ns;
 618}
 619#endif
 620
 621static int cb_pcidda_ao_winsn(struct comedi_device *dev,
 622                              struct comedi_subdevice *s,
 623                              struct comedi_insn *insn, unsigned int *data)
 624{
 625        unsigned int command;
 626        unsigned int channel, range;
 627
 628        channel = CR_CHAN(insn->chanspec);
 629        range = CR_RANGE(insn->chanspec);
 630
 631        /*  adjust calibration dacs if range has changed */
 632        if (range != devpriv->ao_range[channel])
 633                cb_pcidda_calibrate(dev, channel, range);
 634
 635        /* output channel configuration */
 636        command = NOSU | ENABLEDAC;
 637
 638        /* output channel range */
 639        switch (range) {
 640        case 0:
 641                command |= BIP | RANGE10V;
 642                break;
 643        case 1:
 644                command |= BIP | RANGE5V;
 645                break;
 646        case 2:
 647                command |= BIP | RANGE2V5;
 648                break;
 649        case 3:
 650                command |= UNIP | RANGE10V;
 651                break;
 652        case 4:
 653                command |= UNIP | RANGE5V;
 654                break;
 655        case 5:
 656                command |= UNIP | RANGE2V5;
 657                break;
 658        };
 659
 660        /* output channel specification */
 661        command |= channel << 2;
 662        outw(command, devpriv->dac + DACONTROL);
 663
 664        /* write data */
 665        outw(data[0], devpriv->dac + DADATA + channel * 2);
 666
 667        /* return the number of samples read/written */
 668        return 1;
 669}
 670
 671/* lowlevel read from eeprom */
 672static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
 673{
 674        unsigned int value = 0;
 675        int i;
 676        const int value_width = 16;     /*  number of bits wide values are */
 677
 678        for (i = 1; i <= value_width; i++) {
 679                /*  read bits most significant bit first */
 680                if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
 681                        value |= 1 << (value_width - i);
 682                }
 683        }
 684
 685        return value;
 686}
 687
 688/* lowlevel write to eeprom/dac */
 689static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
 690                                 unsigned int num_bits)
 691{
 692        int i;
 693
 694        for (i = 1; i <= num_bits; i++) {
 695                /*  send bits most significant bit first */
 696                if (value & (1 << (num_bits - i)))
 697                        devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
 698                else
 699                        devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
 700                outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
 701        }
 702}
 703
 704/* reads a 16 bit value from board's eeprom */
 705static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
 706                                          unsigned int address)
 707{
 708        unsigned int i;
 709        unsigned int cal2_bits;
 710        unsigned int value;
 711        const int max_num_caldacs = 4;  /*  one caldac for every two dac channels */
 712        const int read_instruction = 0x6;       /*  bits to send to tell eeprom we want to read */
 713        const int instruction_length = 3;
 714        const int address_length = 8;
 715
 716        /*  send serial output stream to eeprom */
 717        cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
 718        /*  deactivate caldacs (one caldac for every two channels) */
 719        for (i = 0; i < max_num_caldacs; i++) {
 720                cal2_bits |= DESELECT_CALDAC_BIT(i);
 721        }
 722        outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
 723
 724        /*  tell eeprom we want to read */
 725        cb_pcidda_serial_out(dev, read_instruction, instruction_length);
 726        /*  send address we want to read from */
 727        cb_pcidda_serial_out(dev, address, address_length);
 728
 729        value = cb_pcidda_serial_in(dev);
 730
 731        /*  deactivate eeprom */
 732        cal2_bits &= ~SELECT_EEPROM_BIT;
 733        outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
 734
 735        return value;
 736}
 737
 738/* writes to 8 bit calibration dacs */
 739static void cb_pcidda_write_caldac(struct comedi_device *dev,
 740                                   unsigned int caldac, unsigned int channel,
 741                                   unsigned int value)
 742{
 743        unsigned int cal2_bits;
 744        unsigned int i;
 745        const int num_channel_bits = 3; /*  caldacs use 3 bit channel specification */
 746        const int num_caldac_bits = 8;  /*  8 bit calibration dacs */
 747        const int max_num_caldacs = 4;  /*  one caldac for every two dac channels */
 748
 749        /* write 3 bit channel */
 750        cb_pcidda_serial_out(dev, channel, num_channel_bits);
 751        /*  write 8 bit caldac value */
 752        cb_pcidda_serial_out(dev, value, num_caldac_bits);
 753
 754/*
 755* latch stream into appropriate caldac deselect reference dac
 756*/
 757        cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
 758        /*  deactivate caldacs (one caldac for every two channels) */
 759        for (i = 0; i < max_num_caldacs; i++) {
 760                cal2_bits |= DESELECT_CALDAC_BIT(i);
 761        }
 762        /*  activate the caldac we want */
 763        cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
 764        outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
 765        /*  deactivate caldac */
 766        cal2_bits |= DESELECT_CALDAC_BIT(caldac);
 767        outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
 768}
 769
 770/* returns caldac that calibrates given analog out channel */
 771static unsigned int caldac_number(unsigned int channel)
 772{
 773        return channel / 2;
 774}
 775
 776/* returns caldac channel that provides fine gain for given ao channel */
 777static unsigned int fine_gain_channel(unsigned int ao_channel)
 778{
 779        return 4 * (ao_channel % 2);
 780}
 781
 782/* returns caldac channel that provides coarse gain for given ao channel */
 783static unsigned int coarse_gain_channel(unsigned int ao_channel)
 784{
 785        return 1 + 4 * (ao_channel % 2);
 786}
 787
 788/* returns caldac channel that provides coarse offset for given ao channel */
 789static unsigned int coarse_offset_channel(unsigned int ao_channel)
 790{
 791        return 2 + 4 * (ao_channel % 2);
 792}
 793
 794/* returns caldac channel that provides fine offset for given ao channel */
 795static unsigned int fine_offset_channel(unsigned int ao_channel)
 796{
 797        return 3 + 4 * (ao_channel % 2);
 798}
 799
 800/* returns eeprom address that provides offset for given ao channel and range */
 801static unsigned int offset_eeprom_address(unsigned int ao_channel,
 802                                          unsigned int range)
 803{
 804        return 0x7 + 2 * range + 12 * ao_channel;
 805}
 806
 807/* returns eeprom address that provides gain calibration for given ao channel and range */
 808static unsigned int gain_eeprom_address(unsigned int ao_channel,
 809                                        unsigned int range)
 810{
 811        return 0x8 + 2 * range + 12 * ao_channel;
 812}
 813
 814/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
 815static unsigned int eeprom_coarse_byte(unsigned int word)
 816{
 817        return (word >> 8) & 0xff;
 818}
 819
 820/* returns lower byte of eeprom entry, which gives the fine adjustment values */
 821static unsigned int eeprom_fine_byte(unsigned int word)
 822{
 823        return word & 0xff;
 824}
 825
 826/* set caldacs to eeprom values for given channel and range */
 827static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
 828                                unsigned int range)
 829{
 830        unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
 831
 832        /*  remember range so we can tell when we need to readjust calibration */
 833        devpriv->ao_range[channel] = range;
 834
 835        /*  get values from eeprom data */
 836        coarse_offset =
 837            eeprom_coarse_byte(devpriv->eeprom_data
 838                               [offset_eeprom_address(channel, range)]);
 839        fine_offset =
 840            eeprom_fine_byte(devpriv->eeprom_data
 841                             [offset_eeprom_address(channel, range)]);
 842        coarse_gain =
 843            eeprom_coarse_byte(devpriv->eeprom_data
 844                               [gain_eeprom_address(channel, range)]);
 845        fine_gain =
 846            eeprom_fine_byte(devpriv->eeprom_data
 847                             [gain_eeprom_address(channel, range)]);
 848
 849        /*  set caldacs */
 850        cb_pcidda_write_caldac(dev, caldac_number(channel),
 851                               coarse_offset_channel(channel), coarse_offset);
 852        cb_pcidda_write_caldac(dev, caldac_number(channel),
 853                               fine_offset_channel(channel), fine_offset);
 854        cb_pcidda_write_caldac(dev, caldac_number(channel),
 855                               coarse_gain_channel(channel), coarse_gain);
 856        cb_pcidda_write_caldac(dev, caldac_number(channel),
 857                               fine_gain_channel(channel), fine_gain);
 858}
 859
 860/*
 861 * A convenient macro that defines init_module() and cleanup_module(),
 862 * as necessary.
 863 */
 864COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table);
 865