linux/drivers/staging/comedi/drivers/pcl818.c
<<
>>
Prefs
   1/*
   2   comedi/drivers/pcl818.c
   3
   4   Author:  Michal Dobes <dobes@tesnet.cz>
   5
   6   hardware driver for Advantech cards:
   7    card:   PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718
   8    driver: pcl818l,  pcl818h,  pcl818hd,  pcl818hg,  pcl818,  pcl718
   9*/
  10/*
  11Driver: pcl818
  12Description: Advantech PCL-818 cards, PCL-718
  13Author: Michal Dobes <dobes@tesnet.cz>
  14Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
  15  PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
  16  PCL-718 (pcl718)
  17Status: works
  18
  19All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
  20Differences are only at maximal sample speed, range list and FIFO
  21support.
  22The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
  23only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
  24PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
  25but this code is untested.
  26A word or two about DMA. Driver support DMA operations at two ways:
  271) DMA uses two buffers and after one is filled then is generated
  28   INT and DMA restart with second buffer. With this mode I'm unable run
  29   more that 80Ksamples/secs without data dropouts on K6/233.
  302) DMA uses one buffer and run in autoinit mode and the data are
  31   from DMA buffer moved on the fly with 2kHz interrupts from RTC.
  32   This mode is used if the interrupt 8 is available for allocation.
  33   If not, then first DMA mode is used. With this I can run at
  34   full speed one card (100ksamples/secs) or two cards with
  35   60ksamples/secs each (more is problem on account of ISA limitations).
  36   To use this mode you must have compiled  kernel with disabled
  37   "Enhanced Real Time Clock Support".
  38   Maybe you can have problems if you use xntpd or similar.
  39   If you've data dropouts with DMA mode 2 then:
  40    a) disable IDE DMA
  41    b) switch text mode console to fb.
  42
  43   Options for PCL-818L:
  44    [0] - IO Base
  45    [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
  46    [2] - DMA   (0=disable, 1, 3)
  47    [3] - 0, 10=10MHz clock for 8254
  48              1= 1MHz clock for 8254
  49    [4] - 0,  5=A/D input  -5V.. +5V
  50          1, 10=A/D input -10V..+10V
  51    [5] - 0,  5=D/A output 0-5V  (internal reference -5V)
  52          1, 10=D/A output 0-10V (internal reference -10V)
  53          2    =D/A output unknow (external reference)
  54
  55   Options for PCL-818, PCL-818H:
  56    [0] - IO Base
  57    [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
  58    [2] - DMA   (0=disable, 1, 3)
  59    [3] - 0, 10=10MHz clock for 8254
  60              1= 1MHz clock for 8254
  61    [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
  62          1, 10=D/A output 0-10V (internal reference -10V)
  63          2    =D/A output unknow (external reference)
  64
  65   Options for PCL-818HD, PCL-818HG:
  66    [0] - IO Base
  67    [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
  68    [2] - DMA/FIFO  (-1=use FIFO, 0=disable both FIFO and DMA,
  69                      1=use DMA ch 1, 3=use DMA ch 3)
  70    [3] - 0, 10=10MHz clock for 8254
  71              1= 1MHz clock for 8254
  72    [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
  73          1, 10=D/A output 0-10V (internal reference -10V)
  74          2    =D/A output unknow (external reference)
  75
  76   Options for PCL-718:
  77    [0] - IO Base
  78    [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
  79    [2] - DMA   (0=disable, 1, 3)
  80    [3] - 0, 10=10MHz clock for 8254
  81              1= 1MHz clock for 8254
  82    [4] -     0=A/D Range is +/-10V
  83              1=             +/-5V
  84              2=             +/-2.5V
  85              3=             +/-1V
  86              4=             +/-0.5V
  87              5=             user defined bipolar
  88              6=             0-10V
  89              7=             0-5V
  90              8=             0-2V
  91              9=             0-1V
  92             10=             user defined unipolar
  93    [5] - 0,  5=D/A outputs 0-5V  (internal reference -5V)
  94          1, 10=D/A outputs 0-10V (internal reference -10V)
  95              2=D/A outputs unknow (external reference)
  96    [6] - 0, 60=max  60kHz A/D sampling
  97          1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
  98
  99*/
 100
 101#include "../comedidev.h"
 102
 103#include <linux/ioport.h>
 104#include <linux/mc146818rtc.h>
 105#include <linux/delay.h>
 106#include <asm/dma.h>
 107
 108#include "8253.h"
 109
 110/* #define PCL818_MODE13_AO 1 */
 111
 112/* boards constants */
 113
 114#define boardPCL818L 0
 115#define boardPCL818H 1
 116#define boardPCL818HD 2
 117#define boardPCL818HG 3
 118#define boardPCL818 4
 119#define boardPCL718 5
 120
 121/* IO space len */
 122#define PCLx1x_RANGE 16
 123/* IO space len if we use FIFO */
 124#define PCLx1xFIFO_RANGE 32
 125
 126/* W: clear INT request */
 127#define PCL818_CLRINT 8
 128/* R: return status byte */
 129#define PCL818_STATUS 8
 130/* R: A/D high byte W: A/D range control */
 131#define PCL818_RANGE 1
 132/* R: next mux scan channel W: mux scan channel & range control pointer */
 133#define PCL818_MUX 2
 134/* R/W: operation control register */
 135#define PCL818_CONTROL 9
 136/* W: counter enable */
 137#define PCL818_CNTENABLE 10
 138
 139/* R: low byte of A/D W: soft A/D trigger */
 140#define PCL818_AD_LO 0
 141/* R: high byte of A/D W: A/D range control */
 142#define PCL818_AD_HI 1
 143/* W: D/A low&high byte */
 144#define PCL818_DA_LO 4
 145#define PCL818_DA_HI 5
 146/* R: low&high byte of DI */
 147#define PCL818_DI_LO 3
 148#define PCL818_DI_HI 11
 149/* W: low&high byte of DO */
 150#define PCL818_DO_LO 3
 151#define PCL818_DO_HI 11
 152/* W: PCL718 second D/A */
 153#define PCL718_DA2_LO 6
 154#define PCL718_DA2_HI 7
 155/* counters */
 156#define PCL818_CTR0 12
 157#define PCL818_CTR1 13
 158#define PCL818_CTR2 14
 159/* W: counter control */
 160#define PCL818_CTRCTL 15
 161
 162/* W: fifo enable/disable */
 163#define PCL818_FI_ENABLE 6
 164/* W: fifo interrupt clear */
 165#define PCL818_FI_INTCLR 20
 166/* W: fifo interrupt clear */
 167#define PCL818_FI_FLUSH 25
 168/* R: fifo status */
 169#define PCL818_FI_STATUS 25
 170/* R: one record from FIFO */
 171#define PCL818_FI_DATALO 23
 172#define PCL818_FI_DATAHI 23
 173
 174/* type of interrupt handler */
 175#define INT_TYPE_AI1_INT 1
 176#define INT_TYPE_AI1_DMA 2
 177#define INT_TYPE_AI1_FIFO 3
 178#define INT_TYPE_AI3_INT 4
 179#define INT_TYPE_AI3_DMA 5
 180#define INT_TYPE_AI3_FIFO 6
 181#ifdef PCL818_MODE13_AO
 182#define INT_TYPE_AO1_INT 7
 183#define INT_TYPE_AO3_INT 8
 184#endif
 185
 186#ifdef unused
 187/* RTC stuff... */
 188#define INT_TYPE_AI1_DMA_RTC 9
 189#define INT_TYPE_AI3_DMA_RTC 10
 190
 191#define RTC_IRQ         8
 192#define RTC_IO_EXTENT   0x10
 193#endif
 194
 195#define MAGIC_DMA_WORD 0x5a5a
 196
 197static const struct comedi_lrange range_pcl818h_ai = { 9, {
 198                                                           BIP_RANGE(5),
 199                                                           BIP_RANGE(2.5),
 200                                                           BIP_RANGE(1.25),
 201                                                           BIP_RANGE(0.625),
 202                                                           UNI_RANGE(10),
 203                                                           UNI_RANGE(5),
 204                                                           UNI_RANGE(2.5),
 205                                                           UNI_RANGE(1.25),
 206                                                           BIP_RANGE(10),
 207                                                           }
 208};
 209
 210static const struct comedi_lrange range_pcl818hg_ai = { 10, {
 211                                                             BIP_RANGE(5),
 212                                                             BIP_RANGE(0.5),
 213                                                             BIP_RANGE(0.05),
 214                                                             BIP_RANGE(0.005),
 215                                                             UNI_RANGE(10),
 216                                                             UNI_RANGE(1),
 217                                                             UNI_RANGE(0.1),
 218                                                             UNI_RANGE(0.01),
 219                                                             BIP_RANGE(10),
 220                                                             BIP_RANGE(1),
 221                                                             BIP_RANGE(0.1),
 222                                                             BIP_RANGE(0.01),
 223                                                             }
 224};
 225
 226static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
 227                                                             BIP_RANGE(5),
 228                                                             BIP_RANGE(2.5),
 229                                                             BIP_RANGE(1.25),
 230                                                             BIP_RANGE(0.625),
 231                                                             }
 232};
 233
 234static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
 235                                                             BIP_RANGE(10),
 236                                                             BIP_RANGE(5),
 237                                                             BIP_RANGE(2.5),
 238                                                             BIP_RANGE(1.25),
 239                                                             }
 240};
 241
 242static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
 243static const struct comedi_lrange range718_bipolar0_5 =
 244    { 1, {BIP_RANGE(0.5),} };
 245static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
 246static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
 247
 248static int pcl818_attach(struct comedi_device *dev,
 249                         struct comedi_devconfig *it);
 250static int pcl818_detach(struct comedi_device *dev);
 251
 252#ifdef unused
 253static int RTC_lock = 0;        /* RTC lock */
 254static int RTC_timer_lock = 0;  /* RTC int lock */
 255#endif
 256
 257struct pcl818_board {
 258
 259        const char *name;       /*  driver name */
 260        int n_ranges;           /*  len of range list */
 261        int n_aichan_se;        /*  num of A/D chans in single ended  mode */
 262        int n_aichan_diff;      /*  num of A/D chans in diferencial mode */
 263        unsigned int ns_min;    /*  minimal alllowed delay between samples (in ns) */
 264        int n_aochan;           /*  num of D/A chans */
 265        int n_dichan;           /*  num of DI chans */
 266        int n_dochan;           /*  num of DO chans */
 267        const struct comedi_lrange *ai_range_type;      /*  default A/D rangelist */
 268        const struct comedi_lrange *ao_range_type;      /*  default D/A rangelist */
 269        unsigned int io_range;  /*  len of IO space */
 270        unsigned int IRQbits;   /*  allowed interrupts */
 271        unsigned int DMAbits;   /*  allowed DMA chans */
 272        int ai_maxdata;         /*  maxdata for A/D */
 273        int ao_maxdata;         /*  maxdata for D/A */
 274        unsigned char fifo;     /*  1=board has FIFO */
 275        int is_818;
 276};
 277
 278static const struct pcl818_board boardtypes[] = {
 279        {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
 280         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 281         0x0a, 0xfff, 0xfff, 0, 1},
 282        {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
 283         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 284         0x0a, 0xfff, 0xfff, 0, 1},
 285        {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
 286         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 287         0x0a, 0xfff, 0xfff, 1, 1},
 288        {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
 289         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 290         0x0a, 0xfff, 0xfff, 1, 1},
 291        {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
 292         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 293         0x0a, 0xfff, 0xfff, 0, 1},
 294        {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
 295         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 296         0x0a, 0xfff, 0xfff, 0, 0},
 297        /* pcm3718 */
 298        {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
 299         &range_unipolar5, PCLx1x_RANGE, 0x00fc,
 300         0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
 301};
 302
 303#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
 304
 305static struct comedi_driver driver_pcl818 = {
 306        .driver_name = "pcl818",
 307        .module = THIS_MODULE,
 308        .attach = pcl818_attach,
 309        .detach = pcl818_detach,
 310        .board_name = &boardtypes[0].name,
 311        .num_names = n_boardtypes,
 312        .offset = sizeof(struct pcl818_board),
 313};
 314
 315COMEDI_INITCLEANUP(driver_pcl818);
 316
 317struct pcl818_private {
 318
 319        unsigned int dma;       /*  used DMA, 0=don't use DMA */
 320        int dma_rtc;            /*  1=RTC used with DMA, 0=no RTC alloc */
 321        unsigned int io_range;
 322#ifdef unused
 323        unsigned long rtc_iobase;       /*  RTC port region */
 324        unsigned int rtc_iosize;
 325        unsigned int rtc_irq;
 326        struct timer_list rtc_irq_timer;        /*  timer for RTC sanity check */
 327        unsigned long rtc_freq; /*  RTC int freq */
 328        int rtc_irq_blocked;    /*  1=we now do AI with DMA&RTC */
 329#endif
 330        unsigned long dmabuf[2];        /*  pointers to begin of DMA buffers */
 331        unsigned int dmapages[2];       /*  len of DMA buffers in PAGE_SIZEs */
 332        unsigned int hwdmaptr[2];       /*  hardware address of DMA buffers */
 333        unsigned int hwdmasize[2];      /*  len of DMA buffers in Bytes */
 334        unsigned int dmasamplsize;      /*  size in samples hwdmasize[0]/2 */
 335        unsigned int last_top_dma;      /*  DMA pointer in last RTC int */
 336        int next_dma_buf;       /*  which DMA buffer will be used next round */
 337        long dma_runs_to_end;   /*  how many we must permorm DMA transfer to end of record */
 338        unsigned long last_dma_run;     /*  how many bytes we must transfer on last DMA page */
 339        unsigned char neverending_ai;   /*  if=1, then we do neverending record (you must use cancel()) */
 340        unsigned int ns_min;    /*  manimal alllowed delay between samples (in us) for actual card */
 341        int i8253_osc_base;     /*  1/frequency of on board oscilator in ns */
 342        int irq_free;           /*  1=have allocated IRQ */
 343        int irq_blocked;        /*  1=IRQ now uses any subdev */
 344        int irq_was_now_closed; /*  when IRQ finish, there's stored int818_mode for last interrupt */
 345        int ai_mode;            /*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
 346        struct comedi_subdevice *last_int_sub;  /*  ptr to subdevice which now finish */
 347        int ai_act_scan;        /*  how many scans we finished */
 348        int ai_act_chan;        /*  actual position in actual scan */
 349        unsigned int act_chanlist[16];  /*  MUX setting for actual AI operations */
 350        unsigned int act_chanlist_len;  /*  how long is actual MUX list */
 351        unsigned int act_chanlist_pos;  /*  actual position in MUX list */
 352        unsigned int ai_scans;  /*  len of scanlist */
 353        unsigned int ai_n_chan; /*  how many channels is measured */
 354        unsigned int *ai_chanlist;      /*  actaul chanlist */
 355        unsigned int ai_flags;  /*  flaglist */
 356        unsigned int ai_data_len;       /*  len of data buffer */
 357        short *ai_data;         /*  data buffer */
 358        unsigned int ai_timer1; /*  timers */
 359        unsigned int ai_timer2;
 360        struct comedi_subdevice *sub_ai;        /*  ptr to AI subdevice */
 361        unsigned char usefifo;  /*  1=use fifo */
 362        unsigned int ao_readback[2];
 363};
 364
 365static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,      /*  used for gain list programming */
 366        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
 367};
 368
 369#define devpriv ((struct pcl818_private *)dev->private)
 370#define this_board ((const struct pcl818_board *)dev->board_ptr)
 371
 372/*
 373==============================================================================
 374*/
 375static void setup_channel_list(struct comedi_device *dev,
 376                               struct comedi_subdevice *s,
 377                               unsigned int *chanlist, unsigned int n_chan,
 378                               unsigned int seglen);
 379static int check_channel_list(struct comedi_device *dev,
 380                              struct comedi_subdevice *s,
 381                              unsigned int *chanlist, unsigned int n_chan);
 382
 383static int pcl818_ai_cancel(struct comedi_device *dev,
 384                            struct comedi_subdevice *s);
 385static void start_pacer(struct comedi_device *dev, int mode,
 386                        unsigned int divisor1, unsigned int divisor2);
 387
 388#ifdef unused
 389static int set_rtc_irq_bit(unsigned char bit);
 390static void rtc_dropped_irq(unsigned long data);
 391static int rtc_setfreq_irq(int freq);
 392#endif
 393
 394/*
 395==============================================================================
 396   ANALOG INPUT MODE0, 818 cards, slow version
 397*/
 398static int pcl818_ai_insn_read(struct comedi_device *dev,
 399                               struct comedi_subdevice *s,
 400                               struct comedi_insn *insn, unsigned int *data)
 401{
 402        int n;
 403        int timeout;
 404
 405        /* software trigger, DMA and INT off */
 406        outb(0, dev->iobase + PCL818_CONTROL);
 407
 408        /* select channel */
 409        outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
 410
 411        /* select gain */
 412        outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
 413
 414        for (n = 0; n < insn->n; n++) {
 415
 416                /* clear INT (conversion end) flag */
 417                outb(0, dev->iobase + PCL818_CLRINT);
 418
 419                /* start conversion */
 420                outb(0, dev->iobase + PCL818_AD_LO);
 421
 422                timeout = 100;
 423                while (timeout--) {
 424                        if (inb(dev->iobase + PCL818_STATUS) & 0x10)
 425                                goto conv_finish;
 426                        udelay(1);
 427                }
 428                comedi_error(dev, "A/D insn timeout");
 429                /* clear INT (conversion end) flag */
 430                outb(0, dev->iobase + PCL818_CLRINT);
 431                return -EIO;
 432
 433conv_finish:
 434                data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
 435                           (inb(dev->iobase + PCL818_AD_LO) >> 4));
 436        }
 437
 438        return n;
 439}
 440
 441/*
 442==============================================================================
 443   ANALOG OUTPUT MODE0, 818 cards
 444   only one sample per call is supported
 445*/
 446static int pcl818_ao_insn_read(struct comedi_device *dev,
 447                               struct comedi_subdevice *s,
 448                               struct comedi_insn *insn, unsigned int *data)
 449{
 450        int n;
 451        int chan = CR_CHAN(insn->chanspec);
 452
 453        for (n = 0; n < insn->n; n++) {
 454                data[n] = devpriv->ao_readback[chan];
 455        }
 456
 457        return n;
 458}
 459
 460static int pcl818_ao_insn_write(struct comedi_device *dev,
 461                                struct comedi_subdevice *s,
 462                                struct comedi_insn *insn, unsigned int *data)
 463{
 464        int n;
 465        int chan = CR_CHAN(insn->chanspec);
 466
 467        for (n = 0; n < insn->n; n++) {
 468                devpriv->ao_readback[chan] = data[n];
 469                outb((data[n] & 0x000f) << 4, dev->iobase +
 470                     (chan ? PCL718_DA2_LO : PCL818_DA_LO));
 471                outb((data[n] & 0x0ff0) >> 4, dev->iobase +
 472                     (chan ? PCL718_DA2_HI : PCL818_DA_HI));
 473        }
 474
 475        return n;
 476}
 477
 478/*
 479==============================================================================
 480   DIGITAL INPUT MODE0, 818 cards
 481
 482   only one sample per call is supported
 483*/
 484static int pcl818_di_insn_bits(struct comedi_device *dev,
 485                               struct comedi_subdevice *s,
 486                               struct comedi_insn *insn, unsigned int *data)
 487{
 488        if (insn->n != 2)
 489                return -EINVAL;
 490
 491        data[1] = inb(dev->iobase + PCL818_DI_LO) |
 492            (inb(dev->iobase + PCL818_DI_HI) << 8);
 493
 494        return 2;
 495}
 496
 497/*
 498==============================================================================
 499   DIGITAL OUTPUT MODE0, 818 cards
 500
 501   only one sample per call is supported
 502*/
 503static int pcl818_do_insn_bits(struct comedi_device *dev,
 504                               struct comedi_subdevice *s,
 505                               struct comedi_insn *insn, unsigned int *data)
 506{
 507        if (insn->n != 2)
 508                return -EINVAL;
 509
 510        s->state &= ~data[0];
 511        s->state |= (data[0] & data[1]);
 512
 513        outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
 514        outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
 515
 516        data[1] = s->state;
 517
 518        return 2;
 519}
 520
 521/*
 522==============================================================================
 523   analog input interrupt mode 1 & 3, 818 cards
 524   one sample per interrupt version
 525*/
 526static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
 527{
 528        struct comedi_device *dev = d;
 529        struct comedi_subdevice *s = dev->subdevices + 0;
 530        int low;
 531        int timeout = 50;       /* wait max 50us */
 532
 533        while (timeout--) {
 534                if (inb(dev->iobase + PCL818_STATUS) & 0x10)
 535                        goto conv_finish;
 536                udelay(1);
 537        }
 538        outb(0, dev->iobase + PCL818_STATUS);   /* clear INT request */
 539        comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
 540        pcl818_ai_cancel(dev, s);
 541        s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 542        comedi_event(dev, s);
 543        return IRQ_HANDLED;
 544
 545conv_finish:
 546        low = inb(dev->iobase + PCL818_AD_LO);
 547        comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));        /*  get one sample */
 548        outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
 549
 550        if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
 551                printk
 552                    ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
 553                     (low & 0xf),
 554                     devpriv->act_chanlist[devpriv->act_chanlist_pos]);
 555                pcl818_ai_cancel(dev, s);
 556                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 557                comedi_event(dev, s);
 558                return IRQ_HANDLED;
 559        }
 560        if (s->async->cur_chan == 0) {
 561                /*  printk("E"); */
 562                devpriv->ai_act_scan--;
 563        }
 564
 565        if (!devpriv->neverending_ai) {
 566                if (devpriv->ai_act_scan == 0) {        /* all data sampled */
 567                        pcl818_ai_cancel(dev, s);
 568                        s->async->events |= COMEDI_CB_EOA;
 569                }
 570        }
 571        comedi_event(dev, s);
 572        return IRQ_HANDLED;
 573}
 574
 575/*
 576==============================================================================
 577   analog input dma mode 1 & 3, 818 cards
 578*/
 579static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 580{
 581        struct comedi_device *dev = d;
 582        struct comedi_subdevice *s = dev->subdevices + 0;
 583        int i, len, bufptr;
 584        unsigned long flags;
 585        short *ptr;
 586
 587        disable_dma(devpriv->dma);
 588        devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
 589        if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {       /*  switch dma bufs */
 590                set_dma_mode(devpriv->dma, DMA_MODE_READ);
 591                flags = claim_dma_lock();
 592                set_dma_addr(devpriv->dma,
 593                             devpriv->hwdmaptr[devpriv->next_dma_buf]);
 594                if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
 595                        set_dma_count(devpriv->dma,
 596                                      devpriv->hwdmasize[devpriv->
 597                                                         next_dma_buf]);
 598                } else {
 599                        set_dma_count(devpriv->dma, devpriv->last_dma_run);
 600                }
 601                release_dma_lock(flags);
 602                enable_dma(devpriv->dma);
 603        }
 604        printk("comedi: A/D mode1/3 IRQ \n");
 605
 606        devpriv->dma_runs_to_end--;
 607        outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
 608        ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
 609
 610        len = devpriv->hwdmasize[0] >> 1;
 611        bufptr = 0;
 612
 613        for (i = 0; i < len; i++) {
 614                if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
 615                        printk
 616                            ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
 617                             (ptr[bufptr] & 0xf),
 618                             devpriv->act_chanlist[devpriv->act_chanlist_pos],
 619                             devpriv->act_chanlist_pos);
 620                        pcl818_ai_cancel(dev, s);
 621                        s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 622                        comedi_event(dev, s);
 623                        return IRQ_HANDLED;
 624                }
 625
 626                comedi_buf_put(s->async, ptr[bufptr++] >> 4);   /*  get one sample */
 627
 628                devpriv->act_chanlist_pos++;
 629                if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
 630                        devpriv->ai_act_scan--;
 631                        devpriv->act_chanlist_pos = 0;
 632                }
 633
 634                if (!devpriv->neverending_ai)
 635                        if (devpriv->ai_act_scan == 0) {        /* all data sampled */
 636                                pcl818_ai_cancel(dev, s);
 637                                s->async->events |= COMEDI_CB_EOA;
 638                                comedi_event(dev, s);
 639                                /*  printk("done int ai13 dma\n"); */
 640                                return IRQ_HANDLED;
 641                        }
 642        }
 643
 644        if (len > 0)
 645                comedi_event(dev, s);
 646        return IRQ_HANDLED;
 647}
 648
 649#ifdef unused
 650/*
 651==============================================================================
 652   analog input dma mode 1 & 3 over RTC, 818 cards
 653*/
 654static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
 655{
 656        struct comedi_device *dev = d;
 657        struct comedi_subdevice *s = dev->subdevices + 0;
 658        unsigned long tmp;
 659        unsigned int top1, top2, i, bufptr;
 660        long ofs_dats;
 661        short *dmabuf = (short *)devpriv->dmabuf[0];
 662
 663        /* outb(2,0x378); */
 664        switch (devpriv->ai_mode) {
 665        case INT_TYPE_AI1_DMA_RTC:
 666        case INT_TYPE_AI3_DMA_RTC:
 667                tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
 668                mod_timer(&devpriv->rtc_irq_timer,
 669                          jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
 670
 671                for (i = 0; i < 10; i++) {
 672                        top1 = get_dma_residue(devpriv->dma);
 673                        top2 = get_dma_residue(devpriv->dma);
 674                        if (top1 == top2)
 675                                break;
 676                }
 677
 678                if (top1 != top2)
 679                        return IRQ_HANDLED;
 680                top1 = devpriv->hwdmasize[0] - top1;    /*  where is now DMA in buffer */
 681                top1 >>= 1;
 682                ofs_dats = top1 - devpriv->last_top_dma;        /*  new samples from last call */
 683                if (ofs_dats < 0)
 684                        ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
 685                if (!ofs_dats)
 686                        return IRQ_HANDLED;     /*  exit=no new samples from last call */
 687                /*  obsluz data */
 688                i = devpriv->last_top_dma - 1;
 689                i &= (devpriv->dmasamplsize - 1);
 690
 691                if (dmabuf[i] != MAGIC_DMA_WORD) {      /*  DMA overflow! */
 692                        comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
 693                        /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
 694                        pcl818_ai_cancel(dev, s);
 695                        s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 696                        comedi_event(dev, s);
 697                        return IRQ_HANDLED;
 698                }
 699                /* printk("r %ld ",ofs_dats); */
 700
 701                bufptr = devpriv->last_top_dma;
 702
 703                for (i = 0; i < ofs_dats; i++) {
 704                        if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {       /*  dropout! */
 705                                printk
 706                                    ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
 707                                     (dmabuf[bufptr] & 0xf),
 708                                     devpriv->
 709                                     act_chanlist[devpriv->act_chanlist_pos]);
 710                                pcl818_ai_cancel(dev, s);
 711                                s->async->events |=
 712                                    COMEDI_CB_EOA | COMEDI_CB_ERROR;
 713                                comedi_event(dev, s);
 714                                return IRQ_HANDLED;
 715                        }
 716
 717                        comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);        /*  get one sample */
 718                        bufptr &= (devpriv->dmasamplsize - 1);
 719
 720                        if (s->async->cur_chan == 0) {
 721                                devpriv->ai_act_scan--;
 722                        }
 723
 724                        if (!devpriv->neverending_ai)
 725                                if (devpriv->ai_act_scan == 0) {        /* all data sampled */
 726                                        pcl818_ai_cancel(dev, s);
 727                                        s->async->events |= COMEDI_CB_EOA;
 728                                        comedi_event(dev, s);
 729                                        /* printk("done int ai13 dma\n"); */
 730                                        return IRQ_HANDLED;
 731                                }
 732                }
 733
 734                devpriv->last_top_dma = bufptr;
 735                bufptr--;
 736                bufptr &= (devpriv->dmasamplsize - 1);
 737                dmabuf[bufptr] = MAGIC_DMA_WORD;
 738                comedi_event(dev, s);
 739                /* outb(0,0x378); */
 740                return IRQ_HANDLED;
 741        }
 742
 743        /* outb(0,0x378); */
 744        return IRQ_HANDLED;
 745}
 746#endif
 747
 748/*
 749==============================================================================
 750   analog input interrupt mode 1 & 3, 818HD/HG cards
 751*/
 752static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 753{
 754        struct comedi_device *dev = d;
 755        struct comedi_subdevice *s = dev->subdevices + 0;
 756        int i, len, lo;
 757
 758        outb(0, dev->iobase + PCL818_FI_INTCLR);        /*  clear fifo int request */
 759
 760        lo = inb(dev->iobase + PCL818_FI_STATUS);
 761
 762        if (lo & 4) {
 763                comedi_error(dev, "A/D mode1/3 FIFO overflow!");
 764                pcl818_ai_cancel(dev, s);
 765                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 766                comedi_event(dev, s);
 767                return IRQ_HANDLED;
 768        }
 769
 770        if (lo & 1) {
 771                comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
 772                pcl818_ai_cancel(dev, s);
 773                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 774                comedi_event(dev, s);
 775                return IRQ_HANDLED;
 776        }
 777
 778        if (lo & 2) {
 779                len = 512;
 780        } else {
 781                len = 0;
 782        }
 783
 784        for (i = 0; i < len; i++) {
 785                lo = inb(dev->iobase + PCL818_FI_DATALO);
 786                if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {   /*  dropout! */
 787                        printk
 788                            ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
 789                             (lo & 0xf),
 790                             devpriv->act_chanlist[devpriv->act_chanlist_pos]);
 791                        pcl818_ai_cancel(dev, s);
 792                        s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 793                        comedi_event(dev, s);
 794                        return IRQ_HANDLED;
 795                }
 796
 797                comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));       /*  get one sample */
 798
 799                if (s->async->cur_chan == 0) {
 800                        devpriv->ai_act_scan--;
 801                }
 802
 803                if (!devpriv->neverending_ai)
 804                        if (devpriv->ai_act_scan == 0) {        /* all data sampled */
 805                                pcl818_ai_cancel(dev, s);
 806                                s->async->events |= COMEDI_CB_EOA;
 807                                comedi_event(dev, s);
 808                                return IRQ_HANDLED;
 809                        }
 810        }
 811
 812        if (len > 0)
 813                comedi_event(dev, s);
 814        return IRQ_HANDLED;
 815}
 816
 817/*
 818==============================================================================
 819    INT procedure
 820*/
 821static irqreturn_t interrupt_pcl818(int irq, void *d)
 822{
 823        struct comedi_device *dev = d;
 824
 825        if (!dev->attached) {
 826                comedi_error(dev, "premature interrupt");
 827                return IRQ_HANDLED;
 828        }
 829        /* printk("I\n"); */
 830
 831        if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
 832                if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
 833                                                 devpriv->ai_act_scan > 0)) &&
 834                    (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
 835                     devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
 836                        /* The cleanup from ai_cancel() has been delayed
 837                           until now because the card doesn't seem to like
 838                           being reprogrammed while a DMA transfer is in
 839                           progress.
 840                         */
 841                        struct comedi_subdevice *s = dev->subdevices + 0;
 842                        devpriv->ai_act_scan = 0;
 843                        devpriv->neverending_ai = 0;
 844                        pcl818_ai_cancel(dev, s);
 845                }
 846
 847                outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
 848
 849                return IRQ_HANDLED;
 850        }
 851
 852        switch (devpriv->ai_mode) {
 853        case INT_TYPE_AI1_DMA:
 854        case INT_TYPE_AI3_DMA:
 855                return interrupt_pcl818_ai_mode13_dma(irq, d);
 856        case INT_TYPE_AI1_INT:
 857        case INT_TYPE_AI3_INT:
 858                return interrupt_pcl818_ai_mode13_int(irq, d);
 859        case INT_TYPE_AI1_FIFO:
 860        case INT_TYPE_AI3_FIFO:
 861                return interrupt_pcl818_ai_mode13_fifo(irq, d);
 862#ifdef PCL818_MODE13_AO
 863        case INT_TYPE_AO1_INT:
 864        case INT_TYPE_AO3_INT:
 865                return interrupt_pcl818_ao_mode13_int(irq, d);
 866#endif
 867        default:
 868                break;
 869        }
 870
 871        outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
 872
 873        if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
 874            || (!devpriv->ai_mode)) {
 875                comedi_error(dev, "bad IRQ!");
 876                return IRQ_NONE;
 877        }
 878
 879        comedi_error(dev, "IRQ from unknow source!");
 880        return IRQ_NONE;
 881}
 882
 883/*
 884==============================================================================
 885   ANALOG INPUT MODE 1 or 3 DMA , 818 cards
 886*/
 887static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 888                                    struct comedi_subdevice *s)
 889{
 890        unsigned int flags;
 891        unsigned int bytes;
 892
 893        printk("mode13dma_int, mode: %d\n", mode);
 894        disable_dma(devpriv->dma);      /*  disable dma */
 895        bytes = devpriv->hwdmasize[0];
 896        if (!devpriv->neverending_ai) {
 897                bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /*  how many */
 898                devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];       /*  how many DMA pages we must fiil */
 899                devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];  /* on last dma transfer must be moved */
 900                devpriv->dma_runs_to_end--;
 901                if (devpriv->dma_runs_to_end >= 0)
 902                        bytes = devpriv->hwdmasize[0];
 903        }
 904
 905        devpriv->next_dma_buf = 0;
 906        set_dma_mode(devpriv->dma, DMA_MODE_READ);
 907        flags = claim_dma_lock();
 908        clear_dma_ff(devpriv->dma);
 909        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
 910        set_dma_count(devpriv->dma, bytes);
 911        release_dma_lock(flags);
 912        enable_dma(devpriv->dma);
 913
 914        if (mode == 1) {
 915                devpriv->ai_mode = INT_TYPE_AI1_DMA;
 916                outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ+DMA */
 917        } else {
 918                devpriv->ai_mode = INT_TYPE_AI3_DMA;
 919                outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ+DMA */
 920        };
 921}
 922
 923#ifdef unused
 924/*
 925==============================================================================
 926   ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
 927*/
 928static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
 929                                    struct comedi_subdevice *s)
 930{
 931        unsigned int flags;
 932        short *pole;
 933
 934        set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
 935        flags = claim_dma_lock();
 936        clear_dma_ff(devpriv->dma);
 937        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
 938        set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
 939        release_dma_lock(flags);
 940        enable_dma(devpriv->dma);
 941        devpriv->last_top_dma = 0;      /* devpriv->hwdmasize[0]; */
 942        pole = (short *)devpriv->dmabuf[0];
 943        devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
 944        pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
 945#ifdef unused
 946        devpriv->rtc_freq = rtc_setfreq_irq(2048);
 947        devpriv->rtc_irq_timer.expires =
 948            jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
 949        devpriv->rtc_irq_timer.data = (unsigned long)dev;
 950        devpriv->rtc_irq_timer.function = rtc_dropped_irq;
 951
 952        add_timer(&devpriv->rtc_irq_timer);
 953#endif
 954
 955        if (mode == 1) {
 956                devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
 957                outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+DMA */
 958        } else {
 959                devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
 960                outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+DMA */
 961        };
 962}
 963#endif
 964
 965/*
 966==============================================================================
 967   ANALOG INPUT MODE 1 or 3, 818 cards
 968*/
 969static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 970                              struct comedi_subdevice *s)
 971{
 972        struct comedi_cmd *cmd = &s->async->cmd;
 973        int divisor1, divisor2;
 974        unsigned int seglen;
 975
 976        printk("pcl818_ai_cmd_mode()\n");
 977        if ((!dev->irq) && (!devpriv->dma_rtc)) {
 978                comedi_error(dev, "IRQ not defined!");
 979                return -EINVAL;
 980        }
 981
 982        if (devpriv->irq_blocked)
 983                return -EBUSY;
 984
 985        start_pacer(dev, -1, 0, 0);     /*  stop pacer */
 986
 987        seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
 988                                    devpriv->ai_n_chan);
 989        if (seglen < 1)
 990                return -EINVAL;
 991        setup_channel_list(dev, s, devpriv->ai_chanlist,
 992                           devpriv->ai_n_chan, seglen);
 993
 994        udelay(1);
 995
 996        devpriv->ai_act_scan = devpriv->ai_scans;
 997        devpriv->ai_act_chan = 0;
 998        devpriv->irq_blocked = 1;
 999        devpriv->irq_was_now_closed = 0;
1000        devpriv->neverending_ai = 0;
1001        devpriv->act_chanlist_pos = 0;
1002        devpriv->dma_runs_to_end = 0;
1003
1004        if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
1005                devpriv->neverending_ai = 1;    /* well, user want neverending */
1006
1007        if (mode == 1) {
1008                i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1009                                          &divisor2, &cmd->convert_arg,
1010                                          TRIG_ROUND_NEAREST);
1011                if (divisor1 == 1) {    /* PCL718/818 crash if any divisor is set to 1 */
1012                        divisor1 = 2;
1013                        divisor2 /= 2;
1014                }
1015                if (divisor2 == 1) {
1016                        divisor2 = 2;
1017                        divisor1 /= 2;
1018                }
1019        }
1020
1021        outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
1022
1023        switch (devpriv->dma) {
1024        case 1:         /*  DMA */
1025        case 3:
1026                if (devpriv->dma_rtc == 0) {
1027                        pcl818_ai_mode13dma_int(mode, dev, s);
1028                }
1029#ifdef unused
1030                else {
1031                        pcl818_ai_mode13dma_rtc(mode, dev, s);
1032                }
1033#else
1034                else {
1035                        return -EINVAL;
1036                }
1037#endif
1038                break;
1039        case 0:
1040                if (!devpriv->usefifo) {
1041                        /* IRQ */
1042                        /* printk("IRQ\n"); */
1043                        if (mode == 1) {
1044                                devpriv->ai_mode = INT_TYPE_AI1_INT;
1045                                /* Pacer+IRQ */
1046                                outb(0x83 | (dev->irq << 4),
1047                                     dev->iobase + PCL818_CONTROL);
1048                        } else {
1049                                devpriv->ai_mode = INT_TYPE_AI3_INT;
1050                                /* Ext trig+IRQ */
1051                                outb(0x82 | (dev->irq << 4),
1052                                     dev->iobase + PCL818_CONTROL);
1053                        }
1054                } else {
1055                        /* FIFO */
1056                        /* enable FIFO */
1057                        outb(1, dev->iobase + PCL818_FI_ENABLE);
1058                        if (mode == 1) {
1059                                devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1060                                /* Pacer */
1061                                outb(0x03, dev->iobase + PCL818_CONTROL);
1062                        } else {
1063                                devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1064                                outb(0x02, dev->iobase + PCL818_CONTROL);
1065                        }
1066                }
1067        }
1068
1069        start_pacer(dev, mode, divisor1, divisor2);
1070
1071#ifdef unused
1072        switch (devpriv->ai_mode) {
1073        case INT_TYPE_AI1_DMA_RTC:
1074        case INT_TYPE_AI3_DMA_RTC:
1075                set_rtc_irq_bit(1);     /* start RTC */
1076                break;
1077        }
1078#endif
1079        printk("pcl818_ai_cmd_mode() end\n");
1080        return 0;
1081}
1082
1083#ifdef unused
1084/*
1085==============================================================================
1086   ANALOG OUTPUT MODE 1 or 3, 818 cards
1087*/
1088#ifdef PCL818_MODE13_AO
1089static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
1090                            struct comedi_subdevice *s, comedi_trig * it)
1091{
1092        int divisor1, divisor2;
1093
1094        if (!dev->irq) {
1095                comedi_error(dev, "IRQ not defined!");
1096                return -EINVAL;
1097        }
1098
1099        if (devpriv->irq_blocked)
1100                return -EBUSY;
1101
1102        start_pacer(dev, -1, 0, 0);     /*  stop pacer */
1103
1104        devpriv->int13_act_scan = it->n;
1105        devpriv->int13_act_chan = 0;
1106        devpriv->irq_blocked = 1;
1107        devpriv->irq_was_now_closed = 0;
1108        devpriv->neverending_ai = 0;
1109        devpriv->act_chanlist_pos = 0;
1110
1111        if (mode == 1) {
1112                i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1113                                          &divisor2, &it->trigvar,
1114                                          TRIG_ROUND_NEAREST);
1115                if (divisor1 == 1) {    /* PCL818 crash if any divisor is set to 1 */
1116                        divisor1 = 2;
1117                        divisor2 /= 2;
1118                }
1119                if (divisor2 == 1) {
1120                        divisor2 = 2;
1121                        divisor1 /= 2;
1122                }
1123        }
1124
1125        outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
1126        if (mode == 1) {
1127                devpriv->int818_mode = INT_TYPE_AO1_INT;
1128                outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ */
1129        } else {
1130                devpriv->int818_mode = INT_TYPE_AO3_INT;
1131                outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ */
1132        };
1133
1134        start_pacer(dev, mode, divisor1, divisor2);
1135
1136        return 0;
1137}
1138
1139/*
1140==============================================================================
1141   ANALOG OUTPUT MODE 1, 818 cards
1142*/
1143static int pcl818_ao_mode1(struct comedi_device *dev,
1144                           struct comedi_subdevice *s, comedi_trig * it)
1145{
1146        return pcl818_ao_mode13(1, dev, s, it);
1147}
1148
1149/*
1150==============================================================================
1151   ANALOG OUTPUT MODE 3, 818 cards
1152*/
1153static int pcl818_ao_mode3(struct comedi_device *dev,
1154                           struct comedi_subdevice *s, comedi_trig * it)
1155{
1156        return pcl818_ao_mode13(3, dev, s, it);
1157}
1158#endif
1159#endif
1160
1161/*
1162==============================================================================
1163 Start/stop pacer onboard pacer
1164*/
1165static void start_pacer(struct comedi_device *dev, int mode,
1166                        unsigned int divisor1, unsigned int divisor2)
1167{
1168        outb(0xb4, dev->iobase + PCL818_CTRCTL);
1169        outb(0x74, dev->iobase + PCL818_CTRCTL);
1170        udelay(1);
1171
1172        if (mode == 1) {
1173                outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1174                outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1175                outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1176                outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1177        }
1178}
1179
1180/*
1181==============================================================================
1182 Check if channel list from user is builded correctly
1183 If it's ok, then program scan/gain logic
1184*/
1185static int check_channel_list(struct comedi_device *dev,
1186                              struct comedi_subdevice *s,
1187                              unsigned int *chanlist, unsigned int n_chan)
1188{
1189        unsigned int chansegment[16];
1190        unsigned int i, nowmustbechan, seglen, segpos;
1191
1192        /* correct channel and range number check itself comedi/range.c */
1193        if (n_chan < 1) {
1194                comedi_error(dev, "range/channel list is empty!");
1195                return 0;
1196        }
1197
1198        if (n_chan > 1) {
1199                /*  first channel is everytime ok */
1200                chansegment[0] = chanlist[0];
1201                /*  build part of chanlist */
1202                for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1203
1204                        /* printk("%d. %d * %d\n",i,
1205                         * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1206
1207                        /* we detect loop, this must by finish */
1208
1209                        if (chanlist[0] == chanlist[i])
1210                                break;
1211                        nowmustbechan =
1212                            (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1213                        if (nowmustbechan != CR_CHAN(chanlist[i])) {    /*  channel list isn't continous :-( */
1214                                printk
1215                                    ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1216                                     dev->minor, i, CR_CHAN(chanlist[i]),
1217                                     nowmustbechan, CR_CHAN(chanlist[0]));
1218                                return 0;
1219                        }
1220                        /*  well, this is next correct channel in list */
1221                        chansegment[i] = chanlist[i];
1222                }
1223
1224                /*  check whole chanlist */
1225                for (i = 0, segpos = 0; i < n_chan; i++) {
1226                        /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */
1227                        if (chanlist[i] != chansegment[i % seglen]) {
1228                                printk
1229                                    ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1230                                     dev->minor, i, CR_CHAN(chansegment[i]),
1231                                     CR_RANGE(chansegment[i]),
1232                                     CR_AREF(chansegment[i]),
1233                                     CR_CHAN(chanlist[i % seglen]),
1234                                     CR_RANGE(chanlist[i % seglen]),
1235                                     CR_AREF(chansegment[i % seglen]));
1236                                return 0;       /*  chan/gain list is strange */
1237                        }
1238                }
1239        } else {
1240                seglen = 1;
1241        }
1242        printk("check_channel_list: seglen %d\n", seglen);
1243        return seglen;
1244}
1245
1246static void setup_channel_list(struct comedi_device *dev,
1247                               struct comedi_subdevice *s,
1248                               unsigned int *chanlist, unsigned int n_chan,
1249                               unsigned int seglen)
1250{
1251        int i;
1252
1253        devpriv->act_chanlist_len = seglen;
1254        devpriv->act_chanlist_pos = 0;
1255
1256        for (i = 0; i < seglen; i++) {  /*  store range list to card */
1257                devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1258                outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);       /* select channel */
1259                outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);        /* select gain */
1260        }
1261
1262        udelay(1);
1263
1264        /* select channel interval to scan */
1265        outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1266                                                               1] << 4),
1267             dev->iobase + PCL818_MUX);
1268}
1269
1270/*
1271==============================================================================
1272 Check if board is switched to SE (1) or DIFF(0) mode
1273*/
1274static int check_single_ended(unsigned int port)
1275{
1276        if (inb(port + PCL818_STATUS) & 0x20) {
1277                return 1;
1278        } else {
1279                return 0;
1280        }
1281}
1282
1283/*
1284==============================================================================
1285*/
1286static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1287                      struct comedi_cmd *cmd)
1288{
1289        int err = 0;
1290        int tmp, divisor1, divisor2;
1291
1292        /* step 1: make sure trigger sources are trivially valid */
1293
1294        tmp = cmd->start_src;
1295        cmd->start_src &= TRIG_NOW;
1296        if (!cmd->start_src || tmp != cmd->start_src)
1297                err++;
1298
1299        tmp = cmd->scan_begin_src;
1300        cmd->scan_begin_src &= TRIG_FOLLOW;
1301        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1302                err++;
1303
1304        tmp = cmd->convert_src;
1305        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1306        if (!cmd->convert_src || tmp != cmd->convert_src)
1307                err++;
1308
1309        tmp = cmd->scan_end_src;
1310        cmd->scan_end_src &= TRIG_COUNT;
1311        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1312                err++;
1313
1314        tmp = cmd->stop_src;
1315        cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1316        if (!cmd->stop_src || tmp != cmd->stop_src)
1317                err++;
1318
1319        if (err) {
1320                return 1;
1321        }
1322
1323        /* step 2: make sure trigger sources are unique and mutually compatible */
1324
1325        if (cmd->start_src != TRIG_NOW) {
1326                cmd->start_src = TRIG_NOW;
1327                err++;
1328        }
1329        if (cmd->scan_begin_src != TRIG_FOLLOW) {
1330                cmd->scan_begin_src = TRIG_FOLLOW;
1331                err++;
1332        }
1333        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1334                err++;
1335
1336        if (cmd->scan_end_src != TRIG_COUNT) {
1337                cmd->scan_end_src = TRIG_COUNT;
1338                err++;
1339        }
1340
1341        if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1342                err++;
1343
1344        if (err) {
1345                return 2;
1346        }
1347
1348        /* step 3: make sure arguments are trivially compatible */
1349
1350        if (cmd->start_arg != 0) {
1351                cmd->start_arg = 0;
1352                err++;
1353        }
1354
1355        if (cmd->scan_begin_arg != 0) {
1356                cmd->scan_begin_arg = 0;
1357                err++;
1358        }
1359
1360        if (cmd->convert_src == TRIG_TIMER) {
1361                if (cmd->convert_arg < this_board->ns_min) {
1362                        cmd->convert_arg = this_board->ns_min;
1363                        err++;
1364                }
1365        } else {                /* TRIG_EXT */
1366                if (cmd->convert_arg != 0) {
1367                        cmd->convert_arg = 0;
1368                        err++;
1369                }
1370        }
1371
1372        if (!cmd->chanlist_len) {
1373                cmd->chanlist_len = 1;
1374                err++;
1375        }
1376        if (cmd->chanlist_len > s->n_chan) {
1377                cmd->chanlist_len = s->n_chan;
1378                err++;
1379        }
1380        if (cmd->scan_end_arg != cmd->chanlist_len) {
1381                cmd->scan_end_arg = cmd->chanlist_len;
1382                err++;
1383        }
1384        if (cmd->stop_src == TRIG_COUNT) {
1385                if (!cmd->stop_arg) {
1386                        cmd->stop_arg = 1;
1387                        err++;
1388                }
1389        } else {                /* TRIG_NONE */
1390                if (cmd->stop_arg != 0) {
1391                        cmd->stop_arg = 0;
1392                        err++;
1393                }
1394        }
1395
1396        if (err) {
1397                return 3;
1398        }
1399
1400        /* step 4: fix up any arguments */
1401
1402        if (cmd->convert_src == TRIG_TIMER) {
1403                tmp = cmd->convert_arg;
1404                i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1405                                          &divisor2, &cmd->convert_arg,
1406                                          cmd->flags & TRIG_ROUND_MASK);
1407                if (cmd->convert_arg < this_board->ns_min)
1408                        cmd->convert_arg = this_board->ns_min;
1409                if (tmp != cmd->convert_arg)
1410                        err++;
1411        }
1412
1413        if (err) {
1414                return 4;
1415        }
1416
1417        /* step 5: complain about special chanlist considerations */
1418
1419        if (cmd->chanlist) {
1420                if (!check_channel_list(dev, s, cmd->chanlist,
1421                                        cmd->chanlist_len))
1422                        return 5;       /*  incorrect channels list */
1423        }
1424
1425        return 0;
1426}
1427
1428/*
1429==============================================================================
1430*/
1431static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1432{
1433        struct comedi_cmd *cmd = &s->async->cmd;
1434        int retval;
1435
1436        printk("pcl818_ai_cmd()\n");
1437        devpriv->ai_n_chan = cmd->chanlist_len;
1438        devpriv->ai_chanlist = cmd->chanlist;
1439        devpriv->ai_flags = cmd->flags;
1440        devpriv->ai_data_len = s->async->prealloc_bufsz;
1441        devpriv->ai_data = s->async->prealloc_buf;
1442        devpriv->ai_timer1 = 0;
1443        devpriv->ai_timer2 = 0;
1444
1445        if (cmd->stop_src == TRIG_COUNT) {
1446                devpriv->ai_scans = cmd->stop_arg;
1447        } else {
1448                devpriv->ai_scans = 0;
1449        }
1450
1451        if (cmd->scan_begin_src == TRIG_FOLLOW) {       /*  mode 1, 3 */
1452                if (cmd->convert_src == TRIG_TIMER) {   /*  mode 1 */
1453                        devpriv->ai_timer1 = cmd->convert_arg;
1454                        retval = pcl818_ai_cmd_mode(1, dev, s);
1455                        printk("pcl818_ai_cmd() end\n");
1456                        return retval;
1457                }
1458                if (cmd->convert_src == TRIG_EXT) {     /*  mode 3 */
1459                        return pcl818_ai_cmd_mode(3, dev, s);
1460                }
1461        }
1462
1463        return -1;
1464}
1465
1466/*
1467==============================================================================
1468 cancel any mode 1-4 AI
1469*/
1470static int pcl818_ai_cancel(struct comedi_device *dev,
1471                            struct comedi_subdevice *s)
1472{
1473        if (devpriv->irq_blocked > 0) {
1474                printk("pcl818_ai_cancel()\n");
1475                devpriv->irq_was_now_closed = 1;
1476
1477                switch (devpriv->ai_mode) {
1478#ifdef unused
1479                case INT_TYPE_AI1_DMA_RTC:
1480                case INT_TYPE_AI3_DMA_RTC:
1481                        set_rtc_irq_bit(0);     /*  stop RTC */
1482                        del_timer(&devpriv->rtc_irq_timer);
1483#endif
1484                case INT_TYPE_AI1_DMA:
1485                case INT_TYPE_AI3_DMA:
1486                        if (devpriv->neverending_ai ||
1487                            (!devpriv->neverending_ai &&
1488                             devpriv->ai_act_scan > 0)) {
1489                                /* wait for running dma transfer to end, do cleanup in interrupt */
1490                                goto end;
1491                        }
1492                        disable_dma(devpriv->dma);
1493                case INT_TYPE_AI1_INT:
1494                case INT_TYPE_AI3_INT:
1495                case INT_TYPE_AI1_FIFO:
1496                case INT_TYPE_AI3_FIFO:
1497#ifdef PCL818_MODE13_AO
1498                case INT_TYPE_AO1_INT:
1499                case INT_TYPE_AO3_INT:
1500#endif
1501                        outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);   /* Stop A/D */
1502                        udelay(1);
1503                        start_pacer(dev, -1, 0, 0);
1504                        outb(0, dev->iobase + PCL818_AD_LO);
1505                        inb(dev->iobase + PCL818_AD_LO);
1506                        inb(dev->iobase + PCL818_AD_HI);
1507                        outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
1508                        outb(0, dev->iobase + PCL818_CONTROL);  /* Stop A/D */
1509                        if (devpriv->usefifo) { /*  FIFO shutdown */
1510                                outb(0, dev->iobase + PCL818_FI_INTCLR);
1511                                outb(0, dev->iobase + PCL818_FI_FLUSH);
1512                                outb(0, dev->iobase + PCL818_FI_ENABLE);
1513                        }
1514                        devpriv->irq_blocked = 0;
1515                        devpriv->last_int_sub = s;
1516                        devpriv->neverending_ai = 0;
1517                        devpriv->ai_mode = 0;
1518                        devpriv->irq_was_now_closed = 0;
1519                        break;
1520                }
1521        }
1522
1523end:
1524        printk("pcl818_ai_cancel() end\n");
1525        return 0;
1526}
1527
1528/*
1529==============================================================================
1530 chech for PCL818
1531*/
1532static int pcl818_check(unsigned long iobase)
1533{
1534        outb(0x00, iobase + PCL818_MUX);
1535        udelay(1);
1536        if (inb(iobase + PCL818_MUX) != 0x00)
1537                return 1;       /* there isn't card */
1538        outb(0x55, iobase + PCL818_MUX);
1539        udelay(1);
1540        if (inb(iobase + PCL818_MUX) != 0x55)
1541                return 1;       /* there isn't card */
1542        outb(0x00, iobase + PCL818_MUX);
1543        udelay(1);
1544        outb(0x18, iobase + PCL818_CONTROL);
1545        udelay(1);
1546        if (inb(iobase + PCL818_CONTROL) != 0x18)
1547                return 1;       /* there isn't card */
1548        return 0;               /*  ok, card exist */
1549}
1550
1551/*
1552==============================================================================
1553 reset whole PCL-818 cards
1554*/
1555static void pcl818_reset(struct comedi_device *dev)
1556{
1557        if (devpriv->usefifo) { /*  FIFO shutdown */
1558                outb(0, dev->iobase + PCL818_FI_INTCLR);
1559                outb(0, dev->iobase + PCL818_FI_FLUSH);
1560                outb(0, dev->iobase + PCL818_FI_ENABLE);
1561        }
1562        outb(0, dev->iobase + PCL818_DA_LO);    /*  DAC=0V */
1563        outb(0, dev->iobase + PCL818_DA_HI);
1564        udelay(1);
1565        outb(0, dev->iobase + PCL818_DO_HI);    /*  DO=$0000 */
1566        outb(0, dev->iobase + PCL818_DO_LO);
1567        udelay(1);
1568        outb(0, dev->iobase + PCL818_CONTROL);
1569        outb(0, dev->iobase + PCL818_CNTENABLE);
1570        outb(0, dev->iobase + PCL818_MUX);
1571        outb(0, dev->iobase + PCL818_CLRINT);
1572        outb(0xb0, dev->iobase + PCL818_CTRCTL);        /* Stop pacer */
1573        outb(0x70, dev->iobase + PCL818_CTRCTL);
1574        outb(0x30, dev->iobase + PCL818_CTRCTL);
1575        if (this_board->is_818) {
1576                outb(0, dev->iobase + PCL818_RANGE);
1577        } else {
1578                outb(0, dev->iobase + PCL718_DA2_LO);
1579                outb(0, dev->iobase + PCL718_DA2_HI);
1580        }
1581}
1582
1583#ifdef unused
1584/*
1585==============================================================================
1586  Enable(1)/disable(0) periodic interrupts from RTC
1587*/
1588static int set_rtc_irq_bit(unsigned char bit)
1589{
1590        unsigned char val;
1591        unsigned long flags;
1592
1593        if (bit == 1) {
1594                RTC_timer_lock++;
1595                if (RTC_timer_lock > 1)
1596                        return 0;
1597        } else {
1598                RTC_timer_lock--;
1599                if (RTC_timer_lock < 0)
1600                        RTC_timer_lock = 0;
1601                if (RTC_timer_lock > 0)
1602                        return 0;
1603        }
1604
1605        save_flags(flags);
1606        cli();
1607        val = CMOS_READ(RTC_CONTROL);
1608        if (bit) {
1609                val |= RTC_PIE;
1610        } else {
1611                val &= ~RTC_PIE;
1612        }
1613        CMOS_WRITE(val, RTC_CONTROL);
1614        CMOS_READ(RTC_INTR_FLAGS);
1615        restore_flags(flags);
1616        return 0;
1617}
1618
1619/*
1620==============================================================================
1621  Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1622*/
1623static void rtc_dropped_irq(unsigned long data)
1624{
1625        struct comedi_device *dev = (void *)data;
1626        unsigned long flags, tmp;
1627
1628        switch (devpriv->int818_mode) {
1629        case INT_TYPE_AI1_DMA_RTC:
1630        case INT_TYPE_AI3_DMA_RTC:
1631                mod_timer(&devpriv->rtc_irq_timer,
1632                          jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1633                save_flags(flags);
1634                cli();
1635                tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);       /* restart */
1636                restore_flags(flags);
1637                break;
1638        };
1639}
1640
1641/*
1642==============================================================================
1643  Set frequency of interrupts from RTC
1644*/
1645static int rtc_setfreq_irq(int freq)
1646{
1647        int tmp = 0;
1648        int rtc_freq;
1649        unsigned char val;
1650        unsigned long flags;
1651
1652        if (freq < 2)
1653                freq = 2;
1654        if (freq > 8192)
1655                freq = 8192;
1656
1657        while (freq > (1 << tmp))
1658                tmp++;
1659
1660        rtc_freq = 1 << tmp;
1661
1662        save_flags(flags);
1663        cli();
1664        val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1665        val |= (16 - tmp);
1666        CMOS_WRITE(val, RTC_FREQ_SELECT);
1667        restore_flags(flags);
1668        return rtc_freq;
1669}
1670#endif
1671
1672/*
1673==============================================================================
1674  Free any resources that we have claimed
1675*/
1676static void free_resources(struct comedi_device *dev)
1677{
1678        /* printk("free_resource()\n"); */
1679        if (dev->private) {
1680                pcl818_ai_cancel(dev, devpriv->sub_ai);
1681                pcl818_reset(dev);
1682                if (devpriv->dma)
1683                        free_dma(devpriv->dma);
1684                if (devpriv->dmabuf[0])
1685                        free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1686                if (devpriv->dmabuf[1])
1687                        free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1688#ifdef unused
1689                if (devpriv->rtc_irq)
1690                        free_irq(devpriv->rtc_irq, dev);
1691                if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1692                        if (devpriv->rtc_iobase)
1693                                release_region(devpriv->rtc_iobase,
1694                                               devpriv->rtc_iosize);
1695                }
1696                if (devpriv->dma_rtc)
1697                        RTC_lock--;
1698#endif
1699        }
1700
1701        if (dev->irq)
1702                free_irq(dev->irq, dev);
1703        if (dev->iobase)
1704                release_region(dev->iobase, devpriv->io_range);
1705        /* printk("free_resource() end\n"); */
1706}
1707
1708/*
1709==============================================================================
1710
1711   Initialization
1712
1713*/
1714static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1715{
1716        int ret;
1717        unsigned long iobase;
1718        unsigned int irq;
1719        int dma;
1720        unsigned long pages;
1721        struct comedi_subdevice *s;
1722
1723        ret = alloc_private(dev, sizeof(struct pcl818_private));
1724        if (ret < 0)
1725                return ret;     /* Can't alloc mem */
1726
1727        /* claim our I/O space */
1728        iobase = it->options[0];
1729        printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1730               dev->minor, this_board->name, iobase);
1731        devpriv->io_range = this_board->io_range;
1732        if ((this_board->fifo) && (it->options[2] == -1)) {     /*  we've board with FIFO and we want to use FIFO */
1733                devpriv->io_range = PCLx1xFIFO_RANGE;
1734                devpriv->usefifo = 1;
1735        }
1736        if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1737                printk("I/O port conflict\n");
1738                return -EIO;
1739        }
1740
1741        dev->iobase = iobase;
1742
1743        if (pcl818_check(iobase)) {
1744                printk(", I can't detect board. FAIL!\n");
1745                return -EIO;
1746        }
1747
1748        /* set up some name stuff */
1749        dev->board_name = this_board->name;
1750        /* grab our IRQ */
1751        irq = 0;
1752        if (this_board->IRQbits != 0) { /* board support IRQ */
1753                irq = it->options[1];
1754                if (irq) {      /* we want to use IRQ */
1755                        if (((1 << irq) & this_board->IRQbits) == 0) {
1756                                printk
1757                                    (", IRQ %u is out of allowed range, DISABLING IT",
1758                                     irq);
1759                                irq = 0;        /* Bad IRQ */
1760                        } else {
1761                                if (request_irq
1762                                    (irq, interrupt_pcl818, 0, "pcl818", dev)) {
1763                                        printk
1764                                            (", unable to allocate IRQ %u, DISABLING IT",
1765                                             irq);
1766                                        irq = 0;        /* Can't use IRQ */
1767                                } else {
1768                                        printk(", irq=%u", irq);
1769                                }
1770                        }
1771                }
1772        }
1773
1774        dev->irq = irq;
1775        if (irq) {
1776                devpriv->irq_free = 1;
1777        } /* 1=we have allocated irq */
1778        else {
1779                devpriv->irq_free = 0;
1780        }
1781        devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1782        devpriv->ai_mode = 0;   /* mode of irq */
1783
1784#ifdef unused
1785        /* grab RTC for DMA operations */
1786        devpriv->dma_rtc = 0;
1787        if (it->options[2] > 0) {       /*  we want to use DMA */
1788                if (RTC_lock == 0) {
1789                        if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1790                                            "pcl818 (RTC)"))
1791                                goto no_rtc;
1792                }
1793                devpriv->rtc_iobase = RTC_PORT(0);
1794                devpriv->rtc_iosize = RTC_IO_EXTENT;
1795                RTC_lock++;
1796                if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1797                                 "pcl818 DMA (RTC)", dev)) {
1798                        devpriv->dma_rtc = 1;
1799                        devpriv->rtc_irq = RTC_IRQ;
1800                        printk(", dma_irq=%u", devpriv->rtc_irq);
1801                } else {
1802                        RTC_lock--;
1803                        if (RTC_lock == 0) {
1804                                if (devpriv->rtc_iobase)
1805                                        release_region(devpriv->rtc_iobase,
1806                                                       devpriv->rtc_iosize);
1807                        }
1808                        devpriv->rtc_iobase = 0;
1809                        devpriv->rtc_iosize = 0;
1810                }
1811        }
1812
1813no_rtc:
1814#endif
1815        /* grab our DMA */
1816        dma = 0;
1817        devpriv->dma = dma;
1818        if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1819                goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1820        if (this_board->DMAbits != 0) { /* board support DMA */
1821                dma = it->options[2];
1822                if (dma < 1)
1823                        goto no_dma;    /* DMA disabled */
1824                if (((1 << dma) & this_board->DMAbits) == 0) {
1825                        printk(", DMA is out of allowed range, FAIL!\n");
1826                        return -EINVAL; /* Bad DMA */
1827                }
1828                ret = request_dma(dma, "pcl818");
1829                if (ret) {
1830                        printk(", unable to allocate DMA %u, FAIL!\n", dma);
1831                        return -EBUSY;  /* DMA isn't free */
1832                }
1833                devpriv->dma = dma;
1834                printk(", dma=%u", dma);
1835                pages = 2;      /* we need 16KB */
1836                devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1837                if (!devpriv->dmabuf[0]) {
1838                        printk(", unable to allocate DMA buffer, FAIL!\n");
1839                        /* maybe experiment with try_to_free_pages() will help .... */
1840                        return -EBUSY;  /* no buffer :-( */
1841                }
1842                devpriv->dmapages[0] = pages;
1843                devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1844                devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1845                /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1846                if (devpriv->dma_rtc == 0) {    /*  we must do duble buff :-( */
1847                        devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1848                        if (!devpriv->dmabuf[1]) {
1849                                printk
1850                                    (", unable to allocate DMA buffer, FAIL!\n");
1851                                return -EBUSY;
1852                        }
1853                        devpriv->dmapages[1] = pages;
1854                        devpriv->hwdmaptr[1] =
1855                            virt_to_bus((void *)devpriv->dmabuf[1]);
1856                        devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1857                }
1858        }
1859
1860no_dma:
1861
1862        ret = alloc_subdevices(dev, 4);
1863        if (ret < 0)
1864                return ret;
1865
1866        s = dev->subdevices + 0;
1867        if (!this_board->n_aichan_se) {
1868                s->type = COMEDI_SUBD_UNUSED;
1869        } else {
1870                s->type = COMEDI_SUBD_AI;
1871                devpriv->sub_ai = s;
1872                s->subdev_flags = SDF_READABLE;
1873                if (check_single_ended(dev->iobase)) {
1874                        s->n_chan = this_board->n_aichan_se;
1875                        s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1876                        printk(", %dchans S.E. DAC", s->n_chan);
1877                } else {
1878                        s->n_chan = this_board->n_aichan_diff;
1879                        s->subdev_flags |= SDF_DIFF;
1880                        printk(", %dchans DIFF DAC", s->n_chan);
1881                }
1882                s->maxdata = this_board->ai_maxdata;
1883                s->len_chanlist = s->n_chan;
1884                s->range_table = this_board->ai_range_type;
1885                s->cancel = pcl818_ai_cancel;
1886                s->insn_read = pcl818_ai_insn_read;
1887                if ((irq) || (devpriv->dma_rtc)) {
1888                        dev->read_subdev = s;
1889                        s->subdev_flags |= SDF_CMD_READ;
1890                        s->do_cmdtest = ai_cmdtest;
1891                        s->do_cmd = ai_cmd;
1892                }
1893                if (this_board->is_818) {
1894                        if ((it->options[4] == 1) || (it->options[4] == 10))
1895                                s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1896                } else {
1897                        switch (it->options[4]) {
1898                        case 0:
1899                                s->range_table = &range_bipolar10;
1900                                break;
1901                        case 1:
1902                                s->range_table = &range_bipolar5;
1903                                break;
1904                        case 2:
1905                                s->range_table = &range_bipolar2_5;
1906                                break;
1907                        case 3:
1908                                s->range_table = &range718_bipolar1;
1909                                break;
1910                        case 4:
1911                                s->range_table = &range718_bipolar0_5;
1912                                break;
1913                        case 6:
1914                                s->range_table = &range_unipolar10;
1915                                break;
1916                        case 7:
1917                                s->range_table = &range_unipolar5;
1918                                break;
1919                        case 8:
1920                                s->range_table = &range718_unipolar2;
1921                                break;
1922                        case 9:
1923                                s->range_table = &range718_unipolar1;
1924                                break;
1925                        default:
1926                                s->range_table = &range_unknown;
1927                                break;
1928                        }
1929                }
1930        }
1931
1932        s = dev->subdevices + 1;
1933        if (!this_board->n_aochan) {
1934                s->type = COMEDI_SUBD_UNUSED;
1935        } else {
1936                s->type = COMEDI_SUBD_AO;
1937                s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1938                s->n_chan = this_board->n_aochan;
1939                s->maxdata = this_board->ao_maxdata;
1940                s->len_chanlist = this_board->n_aochan;
1941                s->range_table = this_board->ao_range_type;
1942                s->insn_read = pcl818_ao_insn_read;
1943                s->insn_write = pcl818_ao_insn_write;
1944#ifdef unused
1945#ifdef PCL818_MODE13_AO
1946                if (irq) {
1947                        s->trig[1] = pcl818_ao_mode1;
1948                        s->trig[3] = pcl818_ao_mode3;
1949                }
1950#endif
1951#endif
1952                if (this_board->is_818) {
1953                        if ((it->options[4] == 1) || (it->options[4] == 10))
1954                                s->range_table = &range_unipolar10;
1955                        if (it->options[4] == 2)
1956                                s->range_table = &range_unknown;
1957                } else {
1958                        if ((it->options[5] == 1) || (it->options[5] == 10))
1959                                s->range_table = &range_unipolar10;
1960                        if (it->options[5] == 2)
1961                                s->range_table = &range_unknown;
1962                }
1963        }
1964
1965        s = dev->subdevices + 2;
1966        if (!this_board->n_dichan) {
1967                s->type = COMEDI_SUBD_UNUSED;
1968        } else {
1969                s->type = COMEDI_SUBD_DI;
1970                s->subdev_flags = SDF_READABLE;
1971                s->n_chan = this_board->n_dichan;
1972                s->maxdata = 1;
1973                s->len_chanlist = this_board->n_dichan;
1974                s->range_table = &range_digital;
1975                s->insn_bits = pcl818_di_insn_bits;
1976        }
1977
1978        s = dev->subdevices + 3;
1979        if (!this_board->n_dochan) {
1980                s->type = COMEDI_SUBD_UNUSED;
1981        } else {
1982                s->type = COMEDI_SUBD_DO;
1983                s->subdev_flags = SDF_WRITABLE;
1984                s->n_chan = this_board->n_dochan;
1985                s->maxdata = 1;
1986                s->len_chanlist = this_board->n_dochan;
1987                s->range_table = &range_digital;
1988                s->insn_bits = pcl818_do_insn_bits;
1989        }
1990
1991        /* select 1/10MHz oscilator */
1992        if ((it->options[3] == 0) || (it->options[3] == 10)) {
1993                devpriv->i8253_osc_base = 100;
1994        } else {
1995                devpriv->i8253_osc_base = 1000;
1996        }
1997
1998        /* max sampling speed */
1999        devpriv->ns_min = this_board->ns_min;
2000
2001        if (!this_board->is_818) {
2002                if ((it->options[6] == 1) || (it->options[6] == 100))
2003                        devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
2004        }
2005
2006        pcl818_reset(dev);
2007
2008        printk("\n");
2009
2010        return 0;
2011}
2012
2013/*
2014==============================================================================
2015  Removes device
2016 */
2017static int pcl818_detach(struct comedi_device *dev)
2018{
2019        /*   printk("comedi%d: pcl818: remove\n", dev->minor); */
2020        free_resources(dev);
2021        return 0;
2022}
2023