linux/drivers/comedi/drivers/ni_labpc_common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * comedi/drivers/ni_labpc_common.c
   4 *
   5 * Common support code for "ni_labpc", "ni_labpc_pci" and "ni_labpc_cs".
   6 *
   7 * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/interrupt.h>
  12#include <linux/io.h>
  13#include <linux/delay.h>
  14#include <linux/slab.h>
  15#include <linux/comedi/comedidev.h>
  16#include <linux/comedi/comedi_8255.h>
  17#include <linux/comedi/comedi_8254.h>
  18
  19#include "ni_labpc.h"
  20#include "ni_labpc_regs.h"
  21#include "ni_labpc_isadma.h"
  22
  23enum scan_mode {
  24        MODE_SINGLE_CHAN,
  25        MODE_SINGLE_CHAN_INTERVAL,
  26        MODE_MULT_CHAN_UP,
  27        MODE_MULT_CHAN_DOWN,
  28};
  29
  30static const struct comedi_lrange range_labpc_plus_ai = {
  31        16, {
  32                BIP_RANGE(5),
  33                BIP_RANGE(4),
  34                BIP_RANGE(2.5),
  35                BIP_RANGE(1),
  36                BIP_RANGE(0.5),
  37                BIP_RANGE(0.25),
  38                BIP_RANGE(0.1),
  39                BIP_RANGE(0.05),
  40                UNI_RANGE(10),
  41                UNI_RANGE(8),
  42                UNI_RANGE(5),
  43                UNI_RANGE(2),
  44                UNI_RANGE(1),
  45                UNI_RANGE(0.5),
  46                UNI_RANGE(0.2),
  47                UNI_RANGE(0.1)
  48        }
  49};
  50
  51static const struct comedi_lrange range_labpc_1200_ai = {
  52        14, {
  53                BIP_RANGE(5),
  54                BIP_RANGE(2.5),
  55                BIP_RANGE(1),
  56                BIP_RANGE(0.5),
  57                BIP_RANGE(0.25),
  58                BIP_RANGE(0.1),
  59                BIP_RANGE(0.05),
  60                UNI_RANGE(10),
  61                UNI_RANGE(5),
  62                UNI_RANGE(2),
  63                UNI_RANGE(1),
  64                UNI_RANGE(0.5),
  65                UNI_RANGE(0.2),
  66                UNI_RANGE(0.1)
  67        }
  68};
  69
  70static const struct comedi_lrange range_labpc_ao = {
  71        2, {
  72                BIP_RANGE(5),
  73                UNI_RANGE(10)
  74        }
  75};
  76
  77/*
  78 * functions that do inb/outb and readb/writeb so we can use
  79 * function pointers to decide which to use
  80 */
  81static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg)
  82{
  83        return inb(dev->iobase + reg);
  84}
  85
  86static void labpc_outb(struct comedi_device *dev,
  87                       unsigned int byte, unsigned long reg)
  88{
  89        outb(byte, dev->iobase + reg);
  90}
  91
  92static unsigned int labpc_readb(struct comedi_device *dev, unsigned long reg)
  93{
  94        return readb(dev->mmio + reg);
  95}
  96
  97static void labpc_writeb(struct comedi_device *dev,
  98                         unsigned int byte, unsigned long reg)
  99{
 100        writeb(byte, dev->mmio + reg);
 101}
 102
 103static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 104{
 105        struct labpc_private *devpriv = dev->private;
 106        unsigned long flags;
 107
 108        spin_lock_irqsave(&dev->spinlock, flags);
 109        devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
 110        devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 111        spin_unlock_irqrestore(&dev->spinlock, flags);
 112
 113        devpriv->cmd3 = 0;
 114        devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
 115
 116        return 0;
 117}
 118
 119static void labpc_ai_set_chan_and_gain(struct comedi_device *dev,
 120                                       enum scan_mode mode,
 121                                       unsigned int chan,
 122                                       unsigned int range,
 123                                       unsigned int aref)
 124{
 125        const struct labpc_boardinfo *board = dev->board_ptr;
 126        struct labpc_private *devpriv = dev->private;
 127
 128        if (board->is_labpc1200) {
 129                /*
 130                 * The LabPC-1200 boards do not have a gain
 131                 * of '0x10'. Skip the range values that would
 132                 * result in this gain.
 133                 */
 134                range += (range > 0) + (range > 7);
 135        }
 136
 137        /* munge channel bits for differential/scan disabled mode */
 138        if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
 139            aref == AREF_DIFF)
 140                chan *= 2;
 141        devpriv->cmd1 = CMD1_MA(chan);
 142        devpriv->cmd1 |= CMD1_GAIN(range);
 143
 144        devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
 145}
 146
 147static void labpc_setup_cmd6_reg(struct comedi_device *dev,
 148                                 struct comedi_subdevice *s,
 149                                 enum scan_mode mode,
 150                                 enum transfer_type xfer,
 151                                 unsigned int range,
 152                                 unsigned int aref,
 153                                 bool ena_intr)
 154{
 155        const struct labpc_boardinfo *board = dev->board_ptr;
 156        struct labpc_private *devpriv = dev->private;
 157
 158        if (!board->is_labpc1200)
 159                return;
 160
 161        /* reference inputs to ground or common? */
 162        if (aref != AREF_GROUND)
 163                devpriv->cmd6 |= CMD6_NRSE;
 164        else
 165                devpriv->cmd6 &= ~CMD6_NRSE;
 166
 167        /* bipolar or unipolar range? */
 168        if (comedi_range_is_unipolar(s, range))
 169                devpriv->cmd6 |= CMD6_ADCUNI;
 170        else
 171                devpriv->cmd6 &= ~CMD6_ADCUNI;
 172
 173        /*  interrupt on fifo half full? */
 174        if (xfer == fifo_half_full_transfer)
 175                devpriv->cmd6 |= CMD6_HFINTEN;
 176        else
 177                devpriv->cmd6 &= ~CMD6_HFINTEN;
 178
 179        /* enable interrupt on counter a1 terminal count? */
 180        if (ena_intr)
 181                devpriv->cmd6 |= CMD6_DQINTEN;
 182        else
 183                devpriv->cmd6 &= ~CMD6_DQINTEN;
 184
 185        /* are we scanning up or down through channels? */
 186        if (mode == MODE_MULT_CHAN_UP)
 187                devpriv->cmd6 |= CMD6_SCANUP;
 188        else
 189                devpriv->cmd6 &= ~CMD6_SCANUP;
 190
 191        devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
 192}
 193
 194static unsigned int labpc_read_adc_fifo(struct comedi_device *dev)
 195{
 196        struct labpc_private *devpriv = dev->private;
 197        unsigned int lsb = devpriv->read_byte(dev, ADC_FIFO_REG);
 198        unsigned int msb = devpriv->read_byte(dev, ADC_FIFO_REG);
 199
 200        return (msb << 8) | lsb;
 201}
 202
 203static void labpc_clear_adc_fifo(struct comedi_device *dev)
 204{
 205        struct labpc_private *devpriv = dev->private;
 206
 207        devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 208        labpc_read_adc_fifo(dev);
 209}
 210
 211static int labpc_ai_eoc(struct comedi_device *dev,
 212                        struct comedi_subdevice *s,
 213                        struct comedi_insn *insn,
 214                        unsigned long context)
 215{
 216        struct labpc_private *devpriv = dev->private;
 217
 218        devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 219        if (devpriv->stat1 & STAT1_DAVAIL)
 220                return 0;
 221        return -EBUSY;
 222}
 223
 224static int labpc_ai_insn_read(struct comedi_device *dev,
 225                              struct comedi_subdevice *s,
 226                              struct comedi_insn *insn,
 227                              unsigned int *data)
 228{
 229        struct labpc_private *devpriv = dev->private;
 230        unsigned int chan = CR_CHAN(insn->chanspec);
 231        unsigned int range = CR_RANGE(insn->chanspec);
 232        unsigned int aref = CR_AREF(insn->chanspec);
 233        int ret;
 234        int i;
 235
 236        /* disable timed conversions, interrupt generation and dma */
 237        labpc_cancel(dev, s);
 238
 239        labpc_ai_set_chan_and_gain(dev, MODE_SINGLE_CHAN, chan, range, aref);
 240
 241        labpc_setup_cmd6_reg(dev, s, MODE_SINGLE_CHAN, fifo_not_empty_transfer,
 242                             range, aref, false);
 243
 244        /* setup cmd4 register */
 245        devpriv->cmd4 = 0;
 246        devpriv->cmd4 |= CMD4_ECLKRCV;
 247        /* single-ended/differential */
 248        if (aref == AREF_DIFF)
 249                devpriv->cmd4 |= CMD4_SEDIFF;
 250        devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 251
 252        /* initialize pacer counter to prevent any problems */
 253        comedi_8254_set_mode(devpriv->counter, 0, I8254_MODE2 | I8254_BINARY);
 254
 255        labpc_clear_adc_fifo(dev);
 256
 257        for (i = 0; i < insn->n; i++) {
 258                /* trigger conversion */
 259                devpriv->write_byte(dev, 0x1, ADC_START_CONVERT_REG);
 260
 261                ret = comedi_timeout(dev, s, insn, labpc_ai_eoc, 0);
 262                if (ret)
 263                        return ret;
 264
 265                data[i] = labpc_read_adc_fifo(dev);
 266        }
 267
 268        return insn->n;
 269}
 270
 271static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd,
 272                                      enum scan_mode mode)
 273{
 274        if (mode == MODE_SINGLE_CHAN || cmd->scan_begin_src == TRIG_FOLLOW)
 275                return true;
 276
 277        return false;
 278}
 279
 280static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
 281                                            enum scan_mode mode)
 282{
 283        if (cmd->convert_src != TRIG_TIMER)
 284                return 0;
 285
 286        if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
 287                return cmd->scan_begin_arg;
 288
 289        return cmd->convert_arg;
 290}
 291
 292static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
 293                                        enum scan_mode mode, unsigned int ns)
 294{
 295        if (cmd->convert_src != TRIG_TIMER)
 296                return;
 297
 298        if (mode == MODE_SINGLE_CHAN &&
 299            cmd->scan_begin_src == TRIG_TIMER) {
 300                cmd->scan_begin_arg = ns;
 301                if (cmd->convert_arg > cmd->scan_begin_arg)
 302                        cmd->convert_arg = cmd->scan_begin_arg;
 303        } else {
 304                cmd->convert_arg = ns;
 305        }
 306}
 307
 308static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
 309                                         enum scan_mode mode)
 310{
 311        if (cmd->scan_begin_src != TRIG_TIMER)
 312                return 0;
 313
 314        if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
 315                return 0;
 316
 317        return cmd->scan_begin_arg;
 318}
 319
 320static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
 321                                     enum scan_mode mode, unsigned int ns)
 322{
 323        if (cmd->scan_begin_src != TRIG_TIMER)
 324                return;
 325
 326        if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
 327                return;
 328
 329        cmd->scan_begin_arg = ns;
 330}
 331
 332/* figures out what counter values to use based on command */
 333static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
 334                             enum scan_mode mode)
 335{
 336        struct comedi_8254 *pacer = dev->pacer;
 337        unsigned int convert_period = labpc_ai_convert_period(cmd, mode);
 338        unsigned int scan_period = labpc_ai_scan_period(cmd, mode);
 339        unsigned int base_period;
 340
 341        /*
 342         * If both convert and scan triggers are TRIG_TIMER, then they
 343         * both rely on counter b0. If only one TRIG_TIMER is used, we
 344         * can use the generic cascaded timing functions.
 345         */
 346        if (convert_period && scan_period) {
 347                /*
 348                 * pick the lowest divisor value we can (for maximum input
 349                 * clock speed on convert and scan counters)
 350                 */
 351                pacer->next_div1 = (scan_period - 1) /
 352                                   (pacer->osc_base * I8254_MAX_COUNT) + 1;
 353
 354                comedi_check_trigger_arg_min(&pacer->next_div1, 2);
 355                comedi_check_trigger_arg_max(&pacer->next_div1,
 356                                             I8254_MAX_COUNT);
 357
 358                base_period = pacer->osc_base * pacer->next_div1;
 359
 360                /*  set a0 for conversion frequency and b1 for scan frequency */
 361                switch (cmd->flags & CMDF_ROUND_MASK) {
 362                default:
 363                case CMDF_ROUND_NEAREST:
 364                        pacer->next_div = DIV_ROUND_CLOSEST(convert_period,
 365                                                            base_period);
 366                        pacer->next_div2 = DIV_ROUND_CLOSEST(scan_period,
 367                                                             base_period);
 368                        break;
 369                case CMDF_ROUND_UP:
 370                        pacer->next_div = DIV_ROUND_UP(convert_period,
 371                                                       base_period);
 372                        pacer->next_div2 = DIV_ROUND_UP(scan_period,
 373                                                        base_period);
 374                        break;
 375                case CMDF_ROUND_DOWN:
 376                        pacer->next_div = convert_period / base_period;
 377                        pacer->next_div2 = scan_period / base_period;
 378                        break;
 379                }
 380                /*  make sure a0 and b1 values are acceptable */
 381                comedi_check_trigger_arg_min(&pacer->next_div, 2);
 382                comedi_check_trigger_arg_max(&pacer->next_div, I8254_MAX_COUNT);
 383                comedi_check_trigger_arg_min(&pacer->next_div2, 2);
 384                comedi_check_trigger_arg_max(&pacer->next_div2,
 385                                             I8254_MAX_COUNT);
 386
 387                /*  write corrected timings to command */
 388                labpc_set_ai_convert_period(cmd, mode,
 389                                            base_period * pacer->next_div);
 390                labpc_set_ai_scan_period(cmd, mode,
 391                                         base_period * pacer->next_div2);
 392        } else if (scan_period) {
 393                /*
 394                 * calculate cascaded counter values
 395                 * that give desired scan timing
 396                 * (pacer->next_div2 / pacer->next_div1)
 397                 */
 398                comedi_8254_cascade_ns_to_timer(pacer, &scan_period,
 399                                                cmd->flags);
 400                labpc_set_ai_scan_period(cmd, mode, scan_period);
 401        } else if (convert_period) {
 402                /*
 403                 * calculate cascaded counter values
 404                 * that give desired conversion timing
 405                 * (pacer->next_div / pacer->next_div1)
 406                 */
 407                comedi_8254_cascade_ns_to_timer(pacer, &convert_period,
 408                                                cmd->flags);
 409                /* transfer div2 value so correct timer gets updated */
 410                pacer->next_div = pacer->next_div2;
 411                labpc_set_ai_convert_period(cmd, mode, convert_period);
 412        }
 413}
 414
 415static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
 416{
 417        unsigned int chan0;
 418        unsigned int chan1;
 419
 420        if (cmd->chanlist_len == 1)
 421                return MODE_SINGLE_CHAN;
 422
 423        /* chanlist may be NULL during cmdtest */
 424        if (!cmd->chanlist)
 425                return MODE_MULT_CHAN_UP;
 426
 427        chan0 = CR_CHAN(cmd->chanlist[0]);
 428        chan1 = CR_CHAN(cmd->chanlist[1]);
 429
 430        if (chan0 < chan1)
 431                return MODE_MULT_CHAN_UP;
 432
 433        if (chan0 > chan1)
 434                return MODE_MULT_CHAN_DOWN;
 435
 436        return MODE_SINGLE_CHAN_INTERVAL;
 437}
 438
 439static int labpc_ai_check_chanlist(struct comedi_device *dev,
 440                                   struct comedi_subdevice *s,
 441                                   struct comedi_cmd *cmd)
 442{
 443        enum scan_mode mode = labpc_ai_scan_mode(cmd);
 444        unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
 445        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 446        unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
 447        int i;
 448
 449        for (i = 0; i < cmd->chanlist_len; i++) {
 450                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 451                unsigned int range = CR_RANGE(cmd->chanlist[i]);
 452                unsigned int aref = CR_AREF(cmd->chanlist[i]);
 453
 454                switch (mode) {
 455                case MODE_SINGLE_CHAN:
 456                        break;
 457                case MODE_SINGLE_CHAN_INTERVAL:
 458                        if (chan != chan0) {
 459                                dev_dbg(dev->class_dev,
 460                                        "channel scanning order specified in chanlist is not supported by hardware\n");
 461                                return -EINVAL;
 462                        }
 463                        break;
 464                case MODE_MULT_CHAN_UP:
 465                        if (chan != i) {
 466                                dev_dbg(dev->class_dev,
 467                                        "channel scanning order specified in chanlist is not supported by hardware\n");
 468                                return -EINVAL;
 469                        }
 470                        break;
 471                case MODE_MULT_CHAN_DOWN:
 472                        if (chan != (cmd->chanlist_len - i - 1)) {
 473                                dev_dbg(dev->class_dev,
 474                                        "channel scanning order specified in chanlist is not supported by hardware\n");
 475                                return -EINVAL;
 476                        }
 477                        break;
 478                }
 479
 480                if (range != range0) {
 481                        dev_dbg(dev->class_dev,
 482                                "entries in chanlist must all have the same range\n");
 483                        return -EINVAL;
 484                }
 485
 486                if (aref != aref0) {
 487                        dev_dbg(dev->class_dev,
 488                                "entries in chanlist must all have the same reference\n");
 489                        return -EINVAL;
 490                }
 491        }
 492
 493        return 0;
 494}
 495
 496static int labpc_ai_cmdtest(struct comedi_device *dev,
 497                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
 498{
 499        const struct labpc_boardinfo *board = dev->board_ptr;
 500        int err = 0;
 501        int tmp, tmp2;
 502        unsigned int stop_mask;
 503        enum scan_mode mode;
 504
 505        /* Step 1 : check if triggers are trivially valid */
 506
 507        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 508        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 509                                        TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
 510        err |= comedi_check_trigger_src(&cmd->convert_src,
 511                                        TRIG_TIMER | TRIG_EXT);
 512        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 513
 514        stop_mask = TRIG_COUNT | TRIG_NONE;
 515        if (board->is_labpc1200)
 516                stop_mask |= TRIG_EXT;
 517        err |= comedi_check_trigger_src(&cmd->stop_src, stop_mask);
 518
 519        if (err)
 520                return 1;
 521
 522        /* Step 2a : make sure trigger sources are unique */
 523
 524        err |= comedi_check_trigger_is_unique(cmd->start_src);
 525        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 526        err |= comedi_check_trigger_is_unique(cmd->convert_src);
 527        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 528
 529        /* Step 2b : and mutually compatible */
 530
 531        /* can't have external stop and start triggers at once */
 532        if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
 533                err++;
 534
 535        if (err)
 536                return 2;
 537
 538        /* Step 3: check if arguments are trivially valid */
 539
 540        switch (cmd->start_src) {
 541        case TRIG_NOW:
 542                err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 543                break;
 544        case TRIG_EXT:
 545                /* start_arg value is ignored */
 546                break;
 547        }
 548
 549        if (!cmd->chanlist_len)
 550                err |= -EINVAL;
 551        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 552                                           cmd->chanlist_len);
 553
 554        if (cmd->convert_src == TRIG_TIMER) {
 555                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 556                                                    board->ai_speed);
 557        }
 558
 559        /* make sure scan timing is not too fast */
 560        if (cmd->scan_begin_src == TRIG_TIMER) {
 561                if (cmd->convert_src == TRIG_TIMER) {
 562                        err |= comedi_check_trigger_arg_min(
 563                                        &cmd->scan_begin_arg,
 564                                        cmd->convert_arg * cmd->chanlist_len);
 565                }
 566                err |= comedi_check_trigger_arg_min(
 567                                        &cmd->scan_begin_arg,
 568                                        board->ai_speed * cmd->chanlist_len);
 569        }
 570
 571        switch (cmd->stop_src) {
 572        case TRIG_COUNT:
 573                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 574                break;
 575        case TRIG_NONE:
 576                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 577                break;
 578                /*
 579                 * TRIG_EXT doesn't care since it doesn't
 580                 * trigger off a numbered channel
 581                 */
 582        default:
 583                break;
 584        }
 585
 586        if (err)
 587                return 3;
 588
 589        /* step 4: fix up any arguments */
 590
 591        tmp = cmd->convert_arg;
 592        tmp2 = cmd->scan_begin_arg;
 593        mode = labpc_ai_scan_mode(cmd);
 594        labpc_adc_timing(dev, cmd, mode);
 595        if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg)
 596                err++;
 597
 598        if (err)
 599                return 4;
 600
 601        /* Step 5: check channel list if it exists */
 602        if (cmd->chanlist && cmd->chanlist_len > 0)
 603                err |= labpc_ai_check_chanlist(dev, s, cmd);
 604
 605        if (err)
 606                return 5;
 607
 608        return 0;
 609}
 610
 611static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 612{
 613        const struct labpc_boardinfo *board = dev->board_ptr;
 614        struct labpc_private *devpriv = dev->private;
 615        struct comedi_async *async = s->async;
 616        struct comedi_cmd *cmd = &async->cmd;
 617        enum scan_mode mode = labpc_ai_scan_mode(cmd);
 618        unsigned int chanspec = (mode == MODE_MULT_CHAN_UP) ?
 619                                cmd->chanlist[cmd->chanlist_len - 1] :
 620                                cmd->chanlist[0];
 621        unsigned int chan = CR_CHAN(chanspec);
 622        unsigned int range = CR_RANGE(chanspec);
 623        unsigned int aref = CR_AREF(chanspec);
 624        enum transfer_type xfer;
 625        unsigned long flags;
 626
 627        /* make sure board is disabled before setting up acquisition */
 628        labpc_cancel(dev, s);
 629
 630        /*  initialize software conversion count */
 631        if (cmd->stop_src == TRIG_COUNT)
 632                devpriv->count = cmd->stop_arg * cmd->chanlist_len;
 633
 634        /*  setup hardware conversion counter */
 635        if (cmd->stop_src == TRIG_EXT) {
 636                /*
 637                 * load counter a1 with count of 3
 638                 * (pc+ manual says this is minimum allowed) using mode 0
 639                 */
 640                comedi_8254_load(devpriv->counter, 1,
 641                                 3, I8254_MODE0 | I8254_BINARY);
 642        } else  {
 643                /* just put counter a1 in mode 0 to set its output low */
 644                comedi_8254_set_mode(devpriv->counter, 1,
 645                                     I8254_MODE0 | I8254_BINARY);
 646        }
 647
 648        /* figure out what method we will use to transfer data */
 649        if (devpriv->dma &&
 650            (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) {
 651                /*
 652                 * dma unsafe at RT priority,
 653                 * and too much setup time for CMDF_WAKE_EOS
 654                 */
 655                xfer = isa_dma_transfer;
 656        } else if (board->is_labpc1200 &&
 657                   (cmd->flags & CMDF_WAKE_EOS) == 0 &&
 658                   (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) {
 659                /*
 660                 * pc-plus has no fifo-half full interrupt
 661                 * wake-end-of-scan should interrupt on fifo not empty
 662                 * make sure we are taking more than just a few points
 663                 */
 664                xfer = fifo_half_full_transfer;
 665        } else {
 666                xfer = fifo_not_empty_transfer;
 667        }
 668        devpriv->current_transfer = xfer;
 669
 670        labpc_ai_set_chan_and_gain(dev, mode, chan, range, aref);
 671
 672        labpc_setup_cmd6_reg(dev, s, mode, xfer, range, aref,
 673                             (cmd->stop_src == TRIG_EXT));
 674
 675        /* manual says to set scan enable bit on second pass */
 676        if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) {
 677                devpriv->cmd1 |= CMD1_SCANEN;
 678                /*
 679                 * Need a brief delay before enabling scan, or scan
 680                 * list will get screwed when you switch between
 681                 * scan up to scan down mode - dunno why.
 682                 */
 683                udelay(1);
 684                devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
 685        }
 686
 687        devpriv->write_byte(dev, cmd->chanlist_len, INTERVAL_COUNT_REG);
 688        /*  load count */
 689        devpriv->write_byte(dev, 0x1, INTERVAL_STROBE_REG);
 690
 691        if (cmd->convert_src == TRIG_TIMER ||
 692            cmd->scan_begin_src == TRIG_TIMER) {
 693                struct comedi_8254 *pacer = dev->pacer;
 694                struct comedi_8254 *counter = devpriv->counter;
 695
 696                comedi_8254_update_divisors(pacer);
 697
 698                /* set up pacing */
 699                comedi_8254_load(pacer, 0, pacer->divisor1,
 700                                 I8254_MODE3 | I8254_BINARY);
 701
 702                /* set up conversion pacing */
 703                comedi_8254_set_mode(counter, 0, I8254_MODE2 | I8254_BINARY);
 704                if (labpc_ai_convert_period(cmd, mode))
 705                        comedi_8254_write(counter, 0, pacer->divisor);
 706
 707                /* set up scan pacing */
 708                if (labpc_ai_scan_period(cmd, mode))
 709                        comedi_8254_load(pacer, 1, pacer->divisor2,
 710                                         I8254_MODE2 | I8254_BINARY);
 711        }
 712
 713        labpc_clear_adc_fifo(dev);
 714
 715        if (xfer == isa_dma_transfer)
 716                labpc_setup_dma(dev, s);
 717
 718        /*  enable error interrupts */
 719        devpriv->cmd3 |= CMD3_ERRINTEN;
 720        /*  enable fifo not empty interrupt? */
 721        if (xfer == fifo_not_empty_transfer)
 722                devpriv->cmd3 |= CMD3_FIFOINTEN;
 723        devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
 724
 725        /*  setup any external triggering/pacing (cmd4 register) */
 726        devpriv->cmd4 = 0;
 727        if (cmd->convert_src != TRIG_EXT)
 728                devpriv->cmd4 |= CMD4_ECLKRCV;
 729        /*
 730         * XXX should discard first scan when using interval scanning
 731         * since manual says it is not synced with scan clock.
 732         */
 733        if (!labpc_use_continuous_mode(cmd, mode)) {
 734                devpriv->cmd4 |= CMD4_INTSCAN;
 735                if (cmd->scan_begin_src == TRIG_EXT)
 736                        devpriv->cmd4 |= CMD4_EOIRCV;
 737        }
 738        /*  single-ended/differential */
 739        if (aref == AREF_DIFF)
 740                devpriv->cmd4 |= CMD4_SEDIFF;
 741        devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 742
 743        /*  startup acquisition */
 744
 745        spin_lock_irqsave(&dev->spinlock, flags);
 746
 747        /* use 2 cascaded counters for pacing */
 748        devpriv->cmd2 |= CMD2_TBSEL;
 749
 750        devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
 751        if (cmd->start_src == TRIG_EXT)
 752                devpriv->cmd2 |= CMD2_HWTRIG;
 753        else
 754                devpriv->cmd2 |= CMD2_SWTRIG;
 755        if (cmd->stop_src == TRIG_EXT)
 756                devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG);
 757
 758        devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 759
 760        spin_unlock_irqrestore(&dev->spinlock, flags);
 761
 762        return 0;
 763}
 764
 765/* read all available samples from ai fifo */
 766static int labpc_drain_fifo(struct comedi_device *dev)
 767{
 768        struct labpc_private *devpriv = dev->private;
 769        struct comedi_async *async = dev->read_subdev->async;
 770        struct comedi_cmd *cmd = &async->cmd;
 771        unsigned short data;
 772        const int timeout = 10000;
 773        unsigned int i;
 774
 775        devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 776
 777        for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout;
 778             i++) {
 779                /*  quit if we have all the data we want */
 780                if (cmd->stop_src == TRIG_COUNT) {
 781                        if (devpriv->count == 0)
 782                                break;
 783                        devpriv->count--;
 784                }
 785                data = labpc_read_adc_fifo(dev);
 786                comedi_buf_write_samples(dev->read_subdev, &data, 1);
 787                devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 788        }
 789        if (i == timeout) {
 790                dev_err(dev->class_dev, "ai timeout, fifo never empties\n");
 791                async->events |= COMEDI_CB_ERROR;
 792                return -1;
 793        }
 794
 795        return 0;
 796}
 797
 798/*
 799 * Makes sure all data acquired by board is transferred to comedi (used
 800 * when acquisition is terminated by stop_src == TRIG_EXT).
 801 */
 802static void labpc_drain_dregs(struct comedi_device *dev)
 803{
 804        struct labpc_private *devpriv = dev->private;
 805
 806        if (devpriv->current_transfer == isa_dma_transfer)
 807                labpc_drain_dma(dev);
 808
 809        labpc_drain_fifo(dev);
 810}
 811
 812/* interrupt service routine */
 813static irqreturn_t labpc_interrupt(int irq, void *d)
 814{
 815        struct comedi_device *dev = d;
 816        const struct labpc_boardinfo *board = dev->board_ptr;
 817        struct labpc_private *devpriv = dev->private;
 818        struct comedi_subdevice *s = dev->read_subdev;
 819        struct comedi_async *async;
 820        struct comedi_cmd *cmd;
 821
 822        if (!dev->attached) {
 823                dev_err(dev->class_dev, "premature interrupt\n");
 824                return IRQ_HANDLED;
 825        }
 826
 827        async = s->async;
 828        cmd = &async->cmd;
 829
 830        /* read board status */
 831        devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
 832        if (board->is_labpc1200)
 833                devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
 834
 835        if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW |
 836                               STAT1_OVERRUN | STAT1_DAVAIL)) == 0 &&
 837            (devpriv->stat2 & STAT2_OUTA1) == 0 &&
 838            (devpriv->stat2 & STAT2_FIFONHF)) {
 839                return IRQ_NONE;
 840        }
 841
 842        if (devpriv->stat1 & STAT1_OVERRUN) {
 843                /* clear error interrupt */
 844                devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 845                async->events |= COMEDI_CB_ERROR;
 846                comedi_handle_events(dev, s);
 847                dev_err(dev->class_dev, "overrun\n");
 848                return IRQ_HANDLED;
 849        }
 850
 851        if (devpriv->current_transfer == isa_dma_transfer)
 852                labpc_handle_dma_status(dev);
 853        else
 854                labpc_drain_fifo(dev);
 855
 856        if (devpriv->stat1 & STAT1_CNTINT) {
 857                dev_err(dev->class_dev, "handled timer interrupt?\n");
 858                /*  clear it */
 859                devpriv->write_byte(dev, 0x1, TIMER_CLEAR_REG);
 860        }
 861
 862        if (devpriv->stat1 & STAT1_OVERFLOW) {
 863                /*  clear error interrupt */
 864                devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
 865                async->events |= COMEDI_CB_ERROR;
 866                comedi_handle_events(dev, s);
 867                dev_err(dev->class_dev, "overflow\n");
 868                return IRQ_HANDLED;
 869        }
 870        /*  handle external stop trigger */
 871        if (cmd->stop_src == TRIG_EXT) {
 872                if (devpriv->stat2 & STAT2_OUTA1) {
 873                        labpc_drain_dregs(dev);
 874                        async->events |= COMEDI_CB_EOA;
 875                }
 876        }
 877
 878        /* TRIG_COUNT end of acquisition */
 879        if (cmd->stop_src == TRIG_COUNT) {
 880                if (devpriv->count == 0)
 881                        async->events |= COMEDI_CB_EOA;
 882        }
 883
 884        comedi_handle_events(dev, s);
 885        return IRQ_HANDLED;
 886}
 887
 888static void labpc_ao_write(struct comedi_device *dev,
 889                           struct comedi_subdevice *s,
 890                           unsigned int chan, unsigned int val)
 891{
 892        struct labpc_private *devpriv = dev->private;
 893
 894        devpriv->write_byte(dev, val & 0xff, DAC_LSB_REG(chan));
 895        devpriv->write_byte(dev, (val >> 8) & 0xff, DAC_MSB_REG(chan));
 896
 897        s->readback[chan] = val;
 898}
 899
 900static int labpc_ao_insn_write(struct comedi_device *dev,
 901                               struct comedi_subdevice *s,
 902                               struct comedi_insn *insn,
 903                               unsigned int *data)
 904{
 905        const struct labpc_boardinfo *board = dev->board_ptr;
 906        struct labpc_private *devpriv = dev->private;
 907        unsigned int channel;
 908        unsigned int range;
 909        unsigned int i;
 910        unsigned long flags;
 911
 912        channel = CR_CHAN(insn->chanspec);
 913
 914        /*
 915         * Turn off pacing of analog output channel.
 916         * NOTE: hardware bug in daqcard-1200 means pacing cannot
 917         * be independently enabled/disabled for its the two channels.
 918         */
 919        spin_lock_irqsave(&dev->spinlock, flags);
 920        devpriv->cmd2 &= ~CMD2_LDAC(channel);
 921        devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
 922        spin_unlock_irqrestore(&dev->spinlock, flags);
 923
 924        /* set range */
 925        if (board->is_labpc1200) {
 926                range = CR_RANGE(insn->chanspec);
 927                if (comedi_range_is_unipolar(s, range))
 928                        devpriv->cmd6 |= CMD6_DACUNI(channel);
 929                else
 930                        devpriv->cmd6 &= ~CMD6_DACUNI(channel);
 931                /*  write to register */
 932                devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
 933        }
 934        /* send data */
 935        for (i = 0; i < insn->n; i++)
 936                labpc_ao_write(dev, s, channel, data[i]);
 937
 938        return insn->n;
 939}
 940
 941/* lowlevel write to eeprom/dac */
 942static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
 943                             unsigned int value_width)
 944{
 945        struct labpc_private *devpriv = dev->private;
 946        int i;
 947
 948        for (i = 1; i <= value_width; i++) {
 949                /*  clear serial clock */
 950                devpriv->cmd5 &= ~CMD5_SCLK;
 951                /*  send bits most significant bit first */
 952                if (value & (1 << (value_width - i)))
 953                        devpriv->cmd5 |= CMD5_SDATA;
 954                else
 955                        devpriv->cmd5 &= ~CMD5_SDATA;
 956                udelay(1);
 957                devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 958                /*  set clock to load bit */
 959                devpriv->cmd5 |= CMD5_SCLK;
 960                udelay(1);
 961                devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 962        }
 963}
 964
 965/* lowlevel read from eeprom */
 966static unsigned int labpc_serial_in(struct comedi_device *dev)
 967{
 968        struct labpc_private *devpriv = dev->private;
 969        unsigned int value = 0;
 970        int i;
 971        const int value_width = 8;      /*  number of bits wide values are */
 972
 973        for (i = 1; i <= value_width; i++) {
 974                /*  set serial clock */
 975                devpriv->cmd5 |= CMD5_SCLK;
 976                udelay(1);
 977                devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 978                /*  clear clock bit */
 979                devpriv->cmd5 &= ~CMD5_SCLK;
 980                udelay(1);
 981                devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
 982                /*  read bits most significant bit first */
 983                udelay(1);
 984                devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
 985                if (devpriv->stat2 & STAT2_PROMOUT)
 986                        value |= 1 << (value_width - i);
 987        }
 988
 989        return value;
 990}
 991
 992static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 993                                      unsigned int address)
 994{
 995        struct labpc_private *devpriv = dev->private;
 996        unsigned int value;
 997        /*  bits to tell eeprom to expect a read */
 998        const int read_instruction = 0x3;
 999        /*  8 bit write lengths to eeprom */
1000        const int write_length = 8;
1001
1002        /*  enable read/write to eeprom */
1003        devpriv->cmd5 &= ~CMD5_EEPROMCS;
1004        udelay(1);
1005        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1006        devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1007        udelay(1);
1008        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1009
1010        /*  send read instruction */
1011        labpc_serial_out(dev, read_instruction, write_length);
1012        /*  send 8 bit address to read from */
1013        labpc_serial_out(dev, address, write_length);
1014        /*  read result */
1015        value = labpc_serial_in(dev);
1016
1017        /*  disable read/write to eeprom */
1018        devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1019        udelay(1);
1020        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1021
1022        return value;
1023}
1024
1025static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
1026{
1027        struct labpc_private *devpriv = dev->private;
1028        unsigned int value;
1029        const int read_status_instruction = 0x5;
1030        const int write_length = 8;     /*  8 bit write lengths to eeprom */
1031
1032        /*  enable read/write to eeprom */
1033        devpriv->cmd5 &= ~CMD5_EEPROMCS;
1034        udelay(1);
1035        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1036        devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1037        udelay(1);
1038        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1039
1040        /*  send read status instruction */
1041        labpc_serial_out(dev, read_status_instruction, write_length);
1042        /*  read result */
1043        value = labpc_serial_in(dev);
1044
1045        /*  disable read/write to eeprom */
1046        devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1047        udelay(1);
1048        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1049
1050        return value;
1051}
1052
1053static void labpc_eeprom_write(struct comedi_device *dev,
1054                               unsigned int address, unsigned int value)
1055{
1056        struct labpc_private *devpriv = dev->private;
1057        const int write_enable_instruction = 0x6;
1058        const int write_instruction = 0x2;
1059        const int write_length = 8;     /*  8 bit write lengths to eeprom */
1060
1061        /*  enable read/write to eeprom */
1062        devpriv->cmd5 &= ~CMD5_EEPROMCS;
1063        udelay(1);
1064        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1065        devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1066        udelay(1);
1067        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1068
1069        /*  send write_enable instruction */
1070        labpc_serial_out(dev, write_enable_instruction, write_length);
1071        devpriv->cmd5 &= ~CMD5_EEPROMCS;
1072        udelay(1);
1073        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1074
1075        /*  send write instruction */
1076        devpriv->cmd5 |= CMD5_EEPROMCS;
1077        udelay(1);
1078        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1079        labpc_serial_out(dev, write_instruction, write_length);
1080        /*  send 8 bit address to write to */
1081        labpc_serial_out(dev, address, write_length);
1082        /*  write value */
1083        labpc_serial_out(dev, value, write_length);
1084        devpriv->cmd5 &= ~CMD5_EEPROMCS;
1085        udelay(1);
1086        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1087
1088        /*  disable read/write to eeprom */
1089        devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1090        udelay(1);
1091        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1092}
1093
1094/* writes to 8 bit calibration dacs */
1095static void write_caldac(struct comedi_device *dev, unsigned int channel,
1096                         unsigned int value)
1097{
1098        struct labpc_private *devpriv = dev->private;
1099
1100        /*  clear caldac load bit and make sure we don't write to eeprom */
1101        devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT);
1102        udelay(1);
1103        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1104
1105        /*  write 4 bit channel */
1106        labpc_serial_out(dev, channel, 4);
1107        /*  write 8 bit caldac value */
1108        labpc_serial_out(dev, value, 8);
1109
1110        /*  set and clear caldac bit to load caldac value */
1111        devpriv->cmd5 |= CMD5_CALDACLD;
1112        udelay(1);
1113        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1114        devpriv->cmd5 &= ~CMD5_CALDACLD;
1115        udelay(1);
1116        devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1117}
1118
1119static int labpc_calib_insn_write(struct comedi_device *dev,
1120                                  struct comedi_subdevice *s,
1121                                  struct comedi_insn *insn,
1122                                  unsigned int *data)
1123{
1124        unsigned int chan = CR_CHAN(insn->chanspec);
1125
1126        /*
1127         * Only write the last data value to the caldac. Preceding
1128         * data would be overwritten anyway.
1129         */
1130        if (insn->n > 0) {
1131                unsigned int val = data[insn->n - 1];
1132
1133                if (s->readback[chan] != val) {
1134                        write_caldac(dev, chan, val);
1135                        s->readback[chan] = val;
1136                }
1137        }
1138
1139        return insn->n;
1140}
1141
1142static int labpc_eeprom_ready(struct comedi_device *dev,
1143                              struct comedi_subdevice *s,
1144                              struct comedi_insn *insn,
1145                              unsigned long context)
1146{
1147        unsigned int status;
1148
1149        /* make sure there isn't already a write in progress */
1150        status = labpc_eeprom_read_status(dev);
1151        if ((status & 0x1) == 0)
1152                return 0;
1153        return -EBUSY;
1154}
1155
1156static int labpc_eeprom_insn_write(struct comedi_device *dev,
1157                                   struct comedi_subdevice *s,
1158                                   struct comedi_insn *insn,
1159                                   unsigned int *data)
1160{
1161        unsigned int chan = CR_CHAN(insn->chanspec);
1162        int ret;
1163
1164        /* only allow writes to user area of eeprom */
1165        if (chan < 16 || chan > 127)
1166                return -EINVAL;
1167
1168        /*
1169         * Only write the last data value to the eeprom. Preceding
1170         * data would be overwritten anyway.
1171         */
1172        if (insn->n > 0) {
1173                unsigned int val = data[insn->n - 1];
1174
1175                ret = comedi_timeout(dev, s, insn, labpc_eeprom_ready, 0);
1176                if (ret)
1177                        return ret;
1178
1179                labpc_eeprom_write(dev, chan, val);
1180                s->readback[chan] = val;
1181        }
1182
1183        return insn->n;
1184}
1185
1186int labpc_common_attach(struct comedi_device *dev,
1187                        unsigned int irq, unsigned long isr_flags)
1188{
1189        const struct labpc_boardinfo *board = dev->board_ptr;
1190        struct labpc_private *devpriv;
1191        struct comedi_subdevice *s;
1192        int ret;
1193        int i;
1194
1195        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1196        if (!devpriv)
1197                return -ENOMEM;
1198
1199        if (dev->mmio) {
1200                devpriv->read_byte = labpc_readb;
1201                devpriv->write_byte = labpc_writeb;
1202        } else {
1203                devpriv->read_byte = labpc_inb;
1204                devpriv->write_byte = labpc_outb;
1205        }
1206
1207        /* initialize board's command registers */
1208        devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
1209        devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
1210        devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
1211        devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
1212        if (board->is_labpc1200) {
1213                devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1214                devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
1215        }
1216
1217        if (irq) {
1218                ret = request_irq(irq, labpc_interrupt, isr_flags,
1219                                  dev->board_name, dev);
1220                if (ret == 0)
1221                        dev->irq = irq;
1222        }
1223
1224        if (dev->mmio) {
1225                dev->pacer = comedi_8254_mm_init(dev->mmio + COUNTER_B_BASE_REG,
1226                                                 I8254_OSC_BASE_2MHZ,
1227                                                 I8254_IO8, 0);
1228                devpriv->counter = comedi_8254_mm_init(dev->mmio +
1229                                                       COUNTER_A_BASE_REG,
1230                                                       I8254_OSC_BASE_2MHZ,
1231                                                       I8254_IO8, 0);
1232        } else {
1233                dev->pacer = comedi_8254_init(dev->iobase + COUNTER_B_BASE_REG,
1234                                              I8254_OSC_BASE_2MHZ,
1235                                              I8254_IO8, 0);
1236                devpriv->counter = comedi_8254_init(dev->iobase +
1237                                                    COUNTER_A_BASE_REG,
1238                                                    I8254_OSC_BASE_2MHZ,
1239                                                    I8254_IO8, 0);
1240        }
1241        if (!dev->pacer || !devpriv->counter)
1242                return -ENOMEM;
1243
1244        ret = comedi_alloc_subdevices(dev, 5);
1245        if (ret)
1246                return ret;
1247
1248        /* analog input subdevice */
1249        s = &dev->subdevices[0];
1250        s->type         = COMEDI_SUBD_AI;
1251        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
1252        s->n_chan       = 8;
1253        s->len_chanlist = 8;
1254        s->maxdata      = 0x0fff;
1255        s->range_table  = board->is_labpc1200 ?
1256                          &range_labpc_1200_ai : &range_labpc_plus_ai;
1257        s->insn_read    = labpc_ai_insn_read;
1258        if (dev->irq) {
1259                dev->read_subdev = s;
1260                s->subdev_flags |= SDF_CMD_READ;
1261                s->do_cmd       = labpc_ai_cmd;
1262                s->do_cmdtest   = labpc_ai_cmdtest;
1263                s->cancel       = labpc_cancel;
1264        }
1265
1266        /* analog output */
1267        s = &dev->subdevices[1];
1268        if (board->has_ao) {
1269                s->type         = COMEDI_SUBD_AO;
1270                s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1271                s->n_chan       = 2;
1272                s->maxdata      = 0x0fff;
1273                s->range_table  = &range_labpc_ao;
1274                s->insn_write   = labpc_ao_insn_write;
1275
1276                ret = comedi_alloc_subdev_readback(s);
1277                if (ret)
1278                        return ret;
1279
1280                /* initialize analog outputs to a known value */
1281                for (i = 0; i < s->n_chan; i++)
1282                        labpc_ao_write(dev, s, i, s->maxdata / 2);
1283        } else {
1284                s->type         = COMEDI_SUBD_UNUSED;
1285        }
1286
1287        /* 8255 dio */
1288        s = &dev->subdevices[2];
1289        if (dev->mmio)
1290                ret = subdev_8255_mm_init(dev, s, NULL, DIO_BASE_REG);
1291        else
1292                ret = subdev_8255_init(dev, s, NULL, DIO_BASE_REG);
1293        if (ret)
1294                return ret;
1295
1296        /*  calibration subdevices for boards that have one */
1297        s = &dev->subdevices[3];
1298        if (board->is_labpc1200) {
1299                s->type         = COMEDI_SUBD_CALIB;
1300                s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1301                s->n_chan       = 16;
1302                s->maxdata      = 0xff;
1303                s->insn_write   = labpc_calib_insn_write;
1304
1305                ret = comedi_alloc_subdev_readback(s);
1306                if (ret)
1307                        return ret;
1308
1309                for (i = 0; i < s->n_chan; i++) {
1310                        write_caldac(dev, i, s->maxdata / 2);
1311                        s->readback[i] = s->maxdata / 2;
1312                }
1313        } else {
1314                s->type         = COMEDI_SUBD_UNUSED;
1315        }
1316
1317        /* EEPROM (256 bytes) */
1318        s = &dev->subdevices[4];
1319        if (board->is_labpc1200) {
1320                s->type         = COMEDI_SUBD_MEMORY;
1321                s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1322                s->n_chan       = 256;
1323                s->maxdata      = 0xff;
1324                s->insn_write   = labpc_eeprom_insn_write;
1325
1326                ret = comedi_alloc_subdev_readback(s);
1327                if (ret)
1328                        return ret;
1329
1330                for (i = 0; i < s->n_chan; i++)
1331                        s->readback[i] = labpc_eeprom_read(dev, i);
1332        } else {
1333                s->type         = COMEDI_SUBD_UNUSED;
1334        }
1335
1336        return 0;
1337}
1338EXPORT_SYMBOL_GPL(labpc_common_attach);
1339
1340void labpc_common_detach(struct comedi_device *dev)
1341{
1342        struct labpc_private *devpriv = dev->private;
1343
1344        if (devpriv)
1345                kfree(devpriv->counter);
1346}
1347EXPORT_SYMBOL_GPL(labpc_common_detach);
1348
1349static int __init labpc_common_init(void)
1350{
1351        return 0;
1352}
1353module_init(labpc_common_init);
1354
1355static void __exit labpc_common_exit(void)
1356{
1357}
1358module_exit(labpc_common_exit);
1359
1360MODULE_AUTHOR("Comedi https://www.comedi.org");
1361MODULE_DESCRIPTION("Comedi helper for ni_labpc, ni_labpc_pci, ni_labpc_cs");
1362MODULE_LICENSE("GPL");
1363