linux/drivers/staging/comedi/drivers/s626.c
<<
>>
Prefs
   1/*
   2  comedi/drivers/s626.c
   3  Sensoray s626 Comedi driver
   4
   5  COMEDI - Linux Control and Measurement Device Interface
   6  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   7
   8  Based on Sensoray Model 626 Linux driver Version 0.2
   9  Copyright (C) 2002-2004 Sensoray Co., Inc.
  10
  11  This program is free software; you can redistribute it and/or modify
  12  it under the terms of the GNU General Public License as published by
  13  the Free Software Foundation; either version 2 of the License, or
  14  (at your option) any later version.
  15
  16  This program is distributed in the hope that it will be useful,
  17  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19  GNU General Public License for more details.
  20
  21  You should have received a copy of the GNU General Public License
  22  along with this program; if not, write to the Free Software
  23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24
  25*/
  26
  27/*
  28Driver: s626
  29Description: Sensoray 626 driver
  30Devices: [Sensoray] 626 (s626)
  31Authors: Gianluca Palli <gpalli@deis.unibo.it>,
  32Updated: Fri, 15 Feb 2008 10:28:42 +0000
  33Status: experimental
  34
  35Configuration options:
  36  [0] - PCI bus of device (optional)
  37  [1] - PCI slot of device (optional)
  38  If bus/slot is not specified, the first supported
  39  PCI device found will be used.
  40
  41INSN_CONFIG instructions:
  42  analog input:
  43   none
  44
  45  analog output:
  46   none
  47
  48  digital channel:
  49   s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
  50   supported configuration options:
  51   INSN_CONFIG_DIO_QUERY
  52   COMEDI_INPUT
  53   COMEDI_OUTPUT
  54
  55  encoder:
  56   Every channel must be configured before reading.
  57
  58   Example code
  59
  60   insn.insn=INSN_CONFIG;   //configuration instruction
  61   insn.n=1;                //number of operation (must be 1)
  62   insn.data=&initialvalue; //initial value loaded into encoder
  63                            //during configuration
  64   insn.subdev=5;           //encoder subdevice
  65   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
  66                                                        //to configure
  67
  68   comedi_do_insn(cf,&insn); //executing configuration
  69*/
  70
  71#include <linux/interrupt.h>
  72#include <linux/kernel.h>
  73#include <linux/types.h>
  74
  75#include "../comedidev.h"
  76
  77#include "comedi_pci.h"
  78
  79#include "comedi_fc.h"
  80#include "s626.h"
  81
  82MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
  83MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
  84MODULE_LICENSE("GPL");
  85
  86struct s626_board {
  87        const char *name;
  88        int ai_chans;
  89        int ai_bits;
  90        int ao_chans;
  91        int ao_bits;
  92        int dio_chans;
  93        int dio_banks;
  94        int enc_chans;
  95};
  96
  97static const struct s626_board s626_boards[] = {
  98        {
  99         .name = "s626",
 100         .ai_chans = S626_ADC_CHANNELS,
 101         .ai_bits = 14,
 102         .ao_chans = S626_DAC_CHANNELS,
 103         .ao_bits = 13,
 104         .dio_chans = S626_DIO_CHANNELS,
 105         .dio_banks = S626_DIO_BANKS,
 106         .enc_chans = S626_ENCODER_CHANNELS,
 107         }
 108};
 109
 110#define thisboard ((const struct s626_board *)dev->board_ptr)
 111#define PCI_VENDOR_ID_S626 0x1131
 112#define PCI_DEVICE_ID_S626 0x7146
 113
 114/*
 115 * For devices with vendor:device id == 0x1131:0x7146 you must specify
 116 * also subvendor:subdevice ids, because otherwise it will conflict with
 117 * Philips SAA7146 media/dvb based cards.
 118 */
 119static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
 120        {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, 0x6000, 0x0272, 0, 0, 0},
 121        {0}
 122};
 123
 124MODULE_DEVICE_TABLE(pci, s626_pci_table);
 125
 126static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it);
 127static int s626_detach(struct comedi_device *dev);
 128
 129static struct comedi_driver driver_s626 = {
 130        .driver_name = "s626",
 131        .module = THIS_MODULE,
 132        .attach = s626_attach,
 133        .detach = s626_detach,
 134};
 135
 136struct s626_private {
 137        struct pci_dev *pdev;
 138        void *base_addr;
 139        int got_regions;
 140        short allocatedBuf;
 141        uint8_t ai_cmd_running; /*  ai_cmd is running */
 142        uint8_t ai_continous;   /*  continous aquisition */
 143        int ai_sample_count;    /*  number of samples to aquire */
 144        unsigned int ai_sample_timer;
 145        /*  time between samples in  units of the timer */
 146        int ai_convert_count;   /*  conversion counter */
 147        unsigned int ai_convert_timer;
 148        /*  time between conversion in  units of the timer */
 149        uint16_t CounterIntEnabs;
 150        /* Counter interrupt enable  mask for MISC2 register. */
 151        uint8_t AdcItems;       /* Number of items in ADC poll  list. */
 152        struct bufferDMA RPSBuf;        /* DMA buffer used to hold ADC (RPS1) program. */
 153        struct bufferDMA ANABuf;
 154        /* DMA buffer used to receive ADC data and hold DAC data. */
 155        uint32_t *pDacWBuf;
 156        /* Pointer to logical adrs of DMA buffer used to hold DAC  data. */
 157        uint16_t Dacpol;        /* Image of DAC polarity register. */
 158        uint8_t TrimSetpoint[12];       /* Images of TrimDAC setpoints */
 159        uint16_t ChargeEnabled; /* Image of MISC2 Battery */
 160        /* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */
 161        uint16_t WDInterval;    /* Image of MISC2 watchdog interval control bits. */
 162        uint32_t I2CAdrs;
 163        /* I2C device address for onboard EEPROM (board rev dependent). */
 164        /*   short         I2Cards; */
 165        unsigned int ao_readback[S626_DAC_CHANNELS];
 166};
 167
 168struct dio_private {
 169        uint16_t RDDIn;
 170        uint16_t WRDOut;
 171        uint16_t RDEdgSel;
 172        uint16_t WREdgSel;
 173        uint16_t RDCapSel;
 174        uint16_t WRCapSel;
 175        uint16_t RDCapFlg;
 176        uint16_t RDIntSel;
 177        uint16_t WRIntSel;
 178};
 179
 180static struct dio_private dio_private_A = {
 181        .RDDIn = LP_RDDINA,
 182        .WRDOut = LP_WRDOUTA,
 183        .RDEdgSel = LP_RDEDGSELA,
 184        .WREdgSel = LP_WREDGSELA,
 185        .RDCapSel = LP_RDCAPSELA,
 186        .WRCapSel = LP_WRCAPSELA,
 187        .RDCapFlg = LP_RDCAPFLGA,
 188        .RDIntSel = LP_RDINTSELA,
 189        .WRIntSel = LP_WRINTSELA,
 190};
 191
 192static struct dio_private dio_private_B = {
 193        .RDDIn = LP_RDDINB,
 194        .WRDOut = LP_WRDOUTB,
 195        .RDEdgSel = LP_RDEDGSELB,
 196        .WREdgSel = LP_WREDGSELB,
 197        .RDCapSel = LP_RDCAPSELB,
 198        .WRCapSel = LP_WRCAPSELB,
 199        .RDCapFlg = LP_RDCAPFLGB,
 200        .RDIntSel = LP_RDINTSELB,
 201        .WRIntSel = LP_WRINTSELB,
 202};
 203
 204static struct dio_private dio_private_C = {
 205        .RDDIn = LP_RDDINC,
 206        .WRDOut = LP_WRDOUTC,
 207        .RDEdgSel = LP_RDEDGSELC,
 208        .WREdgSel = LP_WREDGSELC,
 209        .RDCapSel = LP_RDCAPSELC,
 210        .WRCapSel = LP_WRCAPSELC,
 211        .RDCapFlg = LP_RDCAPFLGC,
 212        .RDIntSel = LP_RDINTSELC,
 213        .WRIntSel = LP_WRINTSELC,
 214};
 215
 216/* to group dio devices (48 bits mask and data are not allowed ???)
 217static struct dio_private *dio_private_word[]={
 218  &dio_private_A,
 219  &dio_private_B,
 220  &dio_private_C,
 221};
 222*/
 223
 224#define devpriv ((struct s626_private *)dev->private)
 225#define diopriv ((struct dio_private *)s->private)
 226
 227COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
 228
 229/* ioctl routines */
 230static int s626_ai_insn_config(struct comedi_device *dev,
 231                               struct comedi_subdevice *s,
 232                               struct comedi_insn *insn, unsigned int *data);
 233/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
 234static int s626_ai_insn_read(struct comedi_device *dev,
 235                             struct comedi_subdevice *s,
 236                             struct comedi_insn *insn, unsigned int *data);
 237static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
 238static int s626_ai_cmdtest(struct comedi_device *dev,
 239                           struct comedi_subdevice *s, struct comedi_cmd *cmd);
 240static int s626_ai_cancel(struct comedi_device *dev,
 241                          struct comedi_subdevice *s);
 242static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 243                         struct comedi_insn *insn, unsigned int *data);
 244static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 245                         struct comedi_insn *insn, unsigned int *data);
 246static int s626_dio_insn_bits(struct comedi_device *dev,
 247                              struct comedi_subdevice *s,
 248                              struct comedi_insn *insn, unsigned int *data);
 249static int s626_dio_insn_config(struct comedi_device *dev,
 250                                struct comedi_subdevice *s,
 251                                struct comedi_insn *insn, unsigned int *data);
 252static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan);
 253static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop,
 254                              unsigned int mask);
 255static int s626_dio_clear_irq(struct comedi_device *dev);
 256static int s626_enc_insn_config(struct comedi_device *dev,
 257                                struct comedi_subdevice *s,
 258                                struct comedi_insn *insn, unsigned int *data);
 259static int s626_enc_insn_read(struct comedi_device *dev,
 260                              struct comedi_subdevice *s,
 261                              struct comedi_insn *insn, unsigned int *data);
 262static int s626_enc_insn_write(struct comedi_device *dev,
 263                               struct comedi_subdevice *s,
 264                               struct comedi_insn *insn, unsigned int *data);
 265static int s626_ns_to_timer(int *nanosec, int round_mode);
 266static int s626_ai_load_polllist(uint8_t * ppl, struct comedi_cmd *cmd);
 267static int s626_ai_inttrig(struct comedi_device *dev,
 268                           struct comedi_subdevice *s, unsigned int trignum);
 269static irqreturn_t s626_irq_handler(int irq, void *d);
 270static unsigned int s626_ai_reg_to_uint(int data);
 271/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data); */
 272
 273/* end ioctl routines */
 274
 275/* internal routines */
 276static void s626_dio_init(struct comedi_device *dev);
 277static void ResetADC(struct comedi_device *dev, uint8_t * ppl);
 278static void LoadTrimDACs(struct comedi_device *dev);
 279static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
 280                         uint8_t DacData);
 281static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr);
 282static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val);
 283static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata);
 284static void SendDAC(struct comedi_device *dev, uint32_t val);
 285static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage);
 286static void DEBItransfer(struct comedi_device *dev);
 287static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr);
 288static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata);
 289static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
 290                        uint16_t wdata);
 291static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
 292                      size_t bsize);
 293
 294/*  COUNTER OBJECT ------------------------------------------------ */
 295struct enc_private {
 296        /*  Pointers to functions that differ for A and B counters: */
 297        uint16_t(*GetEnable) (struct comedi_device * dev, struct enc_private *);        /* Return clock enable. */
 298        uint16_t(*GetIntSrc) (struct comedi_device * dev, struct enc_private *);        /* Return interrupt source. */
 299        uint16_t(*GetLoadTrig) (struct comedi_device * dev, struct enc_private *);      /* Return preload trigger source. */
 300        uint16_t(*GetMode) (struct comedi_device * dev, struct enc_private *);  /* Return standardized operating mode. */
 301        void (*PulseIndex) (struct comedi_device * dev, struct enc_private *);  /* Generate soft index strobe. */
 302        void (*SetEnable) (struct comedi_device * dev, struct enc_private *, uint16_t enab);    /* Program clock enable. */
 303        void (*SetIntSrc) (struct comedi_device * dev, struct enc_private *, uint16_t IntSource);       /* Program interrupt source. */
 304        void (*SetLoadTrig) (struct comedi_device * dev, struct enc_private *, uint16_t Trig);  /* Program preload trigger source. */
 305        void (*SetMode) (struct comedi_device * dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);     /* Program standardized operating mode. */
 306        void (*ResetCapFlags) (struct comedi_device * dev, struct enc_private *);       /* Reset event capture flags. */
 307
 308        uint16_t MyCRA;         /*    Address of CRA register. */
 309        uint16_t MyCRB;         /*    Address of CRB register. */
 310        uint16_t MyLatchLsw;    /*    Address of Latch least-significant-word */
 311        /*    register. */
 312        uint16_t MyEventBits[4];        /*    Bit translations for IntSrc -->RDMISC2. */
 313};
 314
 315#define encpriv ((struct enc_private *)(dev->subdevices+5)->private)
 316
 317/* counters routines */
 318static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
 319                            int tick);
 320static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k);
 321static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k);
 322static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k);
 323static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k);
 324static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k);
 325static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
 326                      uint16_t Setup, uint16_t DisableIntSrc);
 327static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
 328                      uint16_t Setup, uint16_t DisableIntSrc);
 329static void SetEnable_A(struct comedi_device *dev, struct enc_private *k,
 330                        uint16_t enab);
 331static void SetEnable_B(struct comedi_device *dev, struct enc_private *k,
 332                        uint16_t enab);
 333static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k);
 334static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k);
 335static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
 336                           uint16_t value);
 337/* static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ); */
 338static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k,
 339                          uint16_t Trig);
 340static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k,
 341                          uint16_t Trig);
 342static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k);
 343static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k);
 344static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
 345                        uint16_t IntSource);
 346static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
 347                        uint16_t IntSource);
 348static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k);
 349static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k);
 350/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) ; */
 351/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) ; */
 352/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ); */
 353/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) ; */
 354/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
 355/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k );  */
 356/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
 357/* static uint16_t GetIndexSrc( struct comedi_device *dev,struct enc_private *k );  */
 358static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k);
 359static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k);
 360static void Preload(struct comedi_device *dev, struct enc_private *k,
 361                    uint32_t value);
 362static void CountersInit(struct comedi_device *dev);
 363/* end internal routines */
 364
 365/*  Counter objects constructor. */
 366
 367/*  Counter overflow/index event flag masks for RDMISC2. */
 368#define INDXMASK(C)             (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
 369#define OVERMASK(C)             (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
 370#define EVBITS(C)               { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
 371
 372/*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
 373/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
 374
 375/* struct enc_private; */
 376static struct enc_private enc_private_data[] = {
 377        {
 378         .GetEnable = GetEnable_A,
 379         .GetIntSrc = GetIntSrc_A,
 380         .GetLoadTrig = GetLoadTrig_A,
 381         .GetMode = GetMode_A,
 382         .PulseIndex = PulseIndex_A,
 383         .SetEnable = SetEnable_A,
 384         .SetIntSrc = SetIntSrc_A,
 385         .SetLoadTrig = SetLoadTrig_A,
 386         .SetMode = SetMode_A,
 387         .ResetCapFlags = ResetCapFlags_A,
 388         .MyCRA = LP_CR0A,
 389         .MyCRB = LP_CR0B,
 390         .MyLatchLsw = LP_CNTR0ALSW,
 391         .MyEventBits = EVBITS(0),
 392         },
 393        {
 394         .GetEnable = GetEnable_A,
 395         .GetIntSrc = GetIntSrc_A,
 396         .GetLoadTrig = GetLoadTrig_A,
 397         .GetMode = GetMode_A,
 398         .PulseIndex = PulseIndex_A,
 399         .SetEnable = SetEnable_A,
 400         .SetIntSrc = SetIntSrc_A,
 401         .SetLoadTrig = SetLoadTrig_A,
 402         .SetMode = SetMode_A,
 403         .ResetCapFlags = ResetCapFlags_A,
 404         .MyCRA = LP_CR1A,
 405         .MyCRB = LP_CR1B,
 406         .MyLatchLsw = LP_CNTR1ALSW,
 407         .MyEventBits = EVBITS(1),
 408         },
 409        {
 410         .GetEnable = GetEnable_A,
 411         .GetIntSrc = GetIntSrc_A,
 412         .GetLoadTrig = GetLoadTrig_A,
 413         .GetMode = GetMode_A,
 414         .PulseIndex = PulseIndex_A,
 415         .SetEnable = SetEnable_A,
 416         .SetIntSrc = SetIntSrc_A,
 417         .SetLoadTrig = SetLoadTrig_A,
 418         .SetMode = SetMode_A,
 419         .ResetCapFlags = ResetCapFlags_A,
 420         .MyCRA = LP_CR2A,
 421         .MyCRB = LP_CR2B,
 422         .MyLatchLsw = LP_CNTR2ALSW,
 423         .MyEventBits = EVBITS(2),
 424         },
 425        {
 426         .GetEnable = GetEnable_B,
 427         .GetIntSrc = GetIntSrc_B,
 428         .GetLoadTrig = GetLoadTrig_B,
 429         .GetMode = GetMode_B,
 430         .PulseIndex = PulseIndex_B,
 431         .SetEnable = SetEnable_B,
 432         .SetIntSrc = SetIntSrc_B,
 433         .SetLoadTrig = SetLoadTrig_B,
 434         .SetMode = SetMode_B,
 435         .ResetCapFlags = ResetCapFlags_B,
 436         .MyCRA = LP_CR0A,
 437         .MyCRB = LP_CR0B,
 438         .MyLatchLsw = LP_CNTR0BLSW,
 439         .MyEventBits = EVBITS(3),
 440         },
 441        {
 442         .GetEnable = GetEnable_B,
 443         .GetIntSrc = GetIntSrc_B,
 444         .GetLoadTrig = GetLoadTrig_B,
 445         .GetMode = GetMode_B,
 446         .PulseIndex = PulseIndex_B,
 447         .SetEnable = SetEnable_B,
 448         .SetIntSrc = SetIntSrc_B,
 449         .SetLoadTrig = SetLoadTrig_B,
 450         .SetMode = SetMode_B,
 451         .ResetCapFlags = ResetCapFlags_B,
 452         .MyCRA = LP_CR1A,
 453         .MyCRB = LP_CR1B,
 454         .MyLatchLsw = LP_CNTR1BLSW,
 455         .MyEventBits = EVBITS(4),
 456         },
 457        {
 458         .GetEnable = GetEnable_B,
 459         .GetIntSrc = GetIntSrc_B,
 460         .GetLoadTrig = GetLoadTrig_B,
 461         .GetMode = GetMode_B,
 462         .PulseIndex = PulseIndex_B,
 463         .SetEnable = SetEnable_B,
 464         .SetIntSrc = SetIntSrc_B,
 465         .SetLoadTrig = SetLoadTrig_B,
 466         .SetMode = SetMode_B,
 467         .ResetCapFlags = ResetCapFlags_B,
 468         .MyCRA = LP_CR2A,
 469         .MyCRB = LP_CR2B,
 470         .MyLatchLsw = LP_CNTR2BLSW,
 471         .MyEventBits = EVBITS(5),
 472         },
 473};
 474
 475/*  enab/disable a function or test status bit(s) that are accessed */
 476/*  through Main Control Registers 1 or 2. */
 477#define MC_ENABLE(REGADRS, CTRLWORD)    writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS))
 478
 479#define MC_DISABLE(REGADRS, CTRLWORD)   writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS))
 480
 481#define MC_TEST(REGADRS, CTRLWORD)      ((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0)
 482
 483/* #define WR7146(REGARDS,CTRLWORD)
 484    writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
 485#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS))
 486
 487/* #define RR7146(REGARDS)
 488    readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
 489#define RR7146(REGARDS)         readl(devpriv->base_addr+(REGARDS))
 490
 491#define BUGFIX_STREG(REGADRS)   (REGADRS - 4)
 492
 493/*  Write a time slot control record to TSL2. */
 494#define VECTPORT(VECTNUM)               (P_TSL2 + ((VECTNUM) << 2))
 495#define SETVECT(VECTNUM, VECTVAL)       WR7146(VECTPORT(VECTNUM), (VECTVAL))
 496
 497/*  Code macros used for constructing I2C command bytes. */
 498#define I2C_B2(ATTR, VAL)       (((ATTR) << 6) | ((VAL) << 24))
 499#define I2C_B1(ATTR, VAL)       (((ATTR) << 4) | ((VAL) << 16))
 500#define I2C_B0(ATTR, VAL)       (((ATTR) << 2) | ((VAL) <<  8))
 501
 502static const struct comedi_lrange s626_range_table = { 2, {
 503                                                           RANGE(-5, 5),
 504                                                           RANGE(-10, 10),
 505                                                           }
 506};
 507
 508static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 509{
 510/*   uint8_t    PollList; */
 511/*   uint16_t   AdcData; */
 512/*   uint16_t   StartVal; */
 513/*   uint16_t   index; */
 514/*   unsigned int data[16]; */
 515        int result;
 516        int i;
 517        int ret;
 518        resource_size_t resourceStart;
 519        dma_addr_t appdma;
 520        struct comedi_subdevice *s;
 521        const struct pci_device_id *ids;
 522        struct pci_dev *pdev = NULL;
 523
 524        if (alloc_private(dev, sizeof(struct s626_private)) < 0)
 525                return -ENOMEM;
 526
 527        for (i = 0; i < (ARRAY_SIZE(s626_pci_table) - 1) && !pdev; i++) {
 528                ids = &s626_pci_table[i];
 529                do {
 530                        pdev = pci_get_subsys(ids->vendor, ids->device,
 531                                              ids->subvendor, ids->subdevice,
 532                                              pdev);
 533
 534                        if ((it->options[0] || it->options[1]) && pdev) {
 535                                /* matches requested bus/slot */
 536                                if (pdev->bus->number == it->options[0] &&
 537                                    PCI_SLOT(pdev->devfn) == it->options[1])
 538                                        break;
 539                        } else
 540                                break;
 541                } while (1);
 542        }
 543        devpriv->pdev = pdev;
 544
 545        if (pdev == NULL) {
 546                printk("s626_attach: Board not present!!!\n");
 547                return -ENODEV;
 548        }
 549
 550        result = comedi_pci_enable(pdev, "s626");
 551        if (result < 0) {
 552                printk("s626_attach: comedi_pci_enable fails\n");
 553                return -ENODEV;
 554        }
 555        devpriv->got_regions = 1;
 556
 557        resourceStart = pci_resource_start(devpriv->pdev, 0);
 558
 559        devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
 560        if (devpriv->base_addr == NULL) {
 561                printk("s626_attach: IOREMAP failed\n");
 562                return -ENODEV;
 563        }
 564
 565        if (devpriv->base_addr) {
 566                /* disable master interrupt */
 567                writel(0, devpriv->base_addr + P_IER);
 568
 569                /* soft reset */
 570                writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
 571
 572                /* DMA FIXME DMA// */
 573                DEBUG("s626_attach: DMA ALLOCATION\n");
 574
 575                /* adc buffer allocation */
 576                devpriv->allocatedBuf = 0;
 577
 578                devpriv->ANABuf.LogicalBase =
 579                    pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
 580
 581                if (devpriv->ANABuf.LogicalBase == NULL) {
 582                        printk("s626_attach: DMA Memory mapping error\n");
 583                        return -ENOMEM;
 584                }
 585
 586                devpriv->ANABuf.PhysicalBase = appdma;
 587
 588                DEBUG
 589                    ("s626_attach: AllocDMAB ADC Logical=%p, bsize=%d, Physical=0x%x\n",
 590                     devpriv->ANABuf.LogicalBase, DMABUF_SIZE,
 591                     (uint32_t) devpriv->ANABuf.PhysicalBase);
 592
 593                devpriv->allocatedBuf++;
 594
 595                devpriv->RPSBuf.LogicalBase =
 596                    pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
 597
 598                if (devpriv->RPSBuf.LogicalBase == NULL) {
 599                        printk("s626_attach: DMA Memory mapping error\n");
 600                        return -ENOMEM;
 601                }
 602
 603                devpriv->RPSBuf.PhysicalBase = appdma;
 604
 605                DEBUG
 606                    ("s626_attach: AllocDMAB RPS Logical=%p, bsize=%d, Physical=0x%x\n",
 607                     devpriv->RPSBuf.LogicalBase, DMABUF_SIZE,
 608                     (uint32_t) devpriv->RPSBuf.PhysicalBase);
 609
 610                devpriv->allocatedBuf++;
 611
 612        }
 613
 614        dev->board_ptr = s626_boards;
 615        dev->board_name = thisboard->name;
 616
 617        if (alloc_subdevices(dev, 6) < 0)
 618                return -ENOMEM;
 619
 620        dev->iobase = (unsigned long)devpriv->base_addr;
 621        dev->irq = devpriv->pdev->irq;
 622
 623        /* set up interrupt handler */
 624        if (dev->irq == 0) {
 625                printk(" unknown irq (bad)\n");
 626        } else {
 627                ret = request_irq(dev->irq, s626_irq_handler, IRQF_SHARED,
 628                                  "s626", dev);
 629
 630                if (ret < 0) {
 631                        printk(" irq not available\n");
 632                        dev->irq = 0;
 633                }
 634        }
 635
 636        DEBUG("s626_attach: -- it opts  %d,%d -- \n",
 637              it->options[0], it->options[1]);
 638
 639        s = dev->subdevices + 0;
 640        /* analog input subdevice */
 641        dev->read_subdev = s;
 642        /* we support single-ended (ground) and differential */
 643        s->type = COMEDI_SUBD_AI;
 644        s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
 645        s->n_chan = thisboard->ai_chans;
 646        s->maxdata = (0xffff >> 2);
 647        s->range_table = &s626_range_table;
 648        s->len_chanlist = thisboard->ai_chans;  /* This is the maximum chanlist
 649                                                   length that the board can
 650                                                   handle */
 651        s->insn_config = s626_ai_insn_config;
 652        s->insn_read = s626_ai_insn_read;
 653        s->do_cmd = s626_ai_cmd;
 654        s->do_cmdtest = s626_ai_cmdtest;
 655        s->cancel = s626_ai_cancel;
 656
 657        s = dev->subdevices + 1;
 658        /* analog output subdevice */
 659        s->type = COMEDI_SUBD_AO;
 660        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
 661        s->n_chan = thisboard->ao_chans;
 662        s->maxdata = (0x3fff);
 663        s->range_table = &range_bipolar10;
 664        s->insn_write = s626_ao_winsn;
 665        s->insn_read = s626_ao_rinsn;
 666
 667        s = dev->subdevices + 2;
 668        /* digital I/O subdevice */
 669        s->type = COMEDI_SUBD_DIO;
 670        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
 671        s->n_chan = S626_DIO_CHANNELS;
 672        s->maxdata = 1;
 673        s->io_bits = 0xffff;
 674        s->private = &dio_private_A;
 675        s->range_table = &range_digital;
 676        s->insn_config = s626_dio_insn_config;
 677        s->insn_bits = s626_dio_insn_bits;
 678
 679        s = dev->subdevices + 3;
 680        /* digital I/O subdevice */
 681        s->type = COMEDI_SUBD_DIO;
 682        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
 683        s->n_chan = 16;
 684        s->maxdata = 1;
 685        s->io_bits = 0xffff;
 686        s->private = &dio_private_B;
 687        s->range_table = &range_digital;
 688        s->insn_config = s626_dio_insn_config;
 689        s->insn_bits = s626_dio_insn_bits;
 690
 691        s = dev->subdevices + 4;
 692        /* digital I/O subdevice */
 693        s->type = COMEDI_SUBD_DIO;
 694        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
 695        s->n_chan = 16;
 696        s->maxdata = 1;
 697        s->io_bits = 0xffff;
 698        s->private = &dio_private_C;
 699        s->range_table = &range_digital;
 700        s->insn_config = s626_dio_insn_config;
 701        s->insn_bits = s626_dio_insn_bits;
 702
 703        s = dev->subdevices + 5;
 704        /* encoder (counter) subdevice */
 705        s->type = COMEDI_SUBD_COUNTER;
 706        s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
 707        s->n_chan = thisboard->enc_chans;
 708        s->private = enc_private_data;
 709        s->insn_config = s626_enc_insn_config;
 710        s->insn_read = s626_enc_insn_read;
 711        s->insn_write = s626_enc_insn_write;
 712        s->maxdata = 0xffffff;
 713        s->range_table = &range_unknown;
 714
 715        /* stop ai_command */
 716        devpriv->ai_cmd_running = 0;
 717
 718        if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) {
 719                dma_addr_t pPhysBuf;
 720                uint16_t chan;
 721
 722                /*  enab DEBI and audio pins, enable I2C interface. */
 723                MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
 724                /*  Configure DEBI operating mode. */
 725                WR7146(P_DEBICFG, DEBI_CFG_SLAVE16      /*  Local bus is 16 */
 726                       /*  bits wide. */
 727                       | (DEBI_TOUT << DEBI_CFG_TOUT_BIT)
 728
 729                       /*  Declare DEBI */
 730                       /*  transfer timeout */
 731                       /*  interval. */
 732                       |DEBI_SWAP       /*  Set up byte lane */
 733                       /*  steering. */
 734                       | DEBI_CFG_INTEL);       /*  Intel-compatible */
 735                /*  local bus (DEBI */
 736                /*  never times out). */
 737                DEBUG("s626_attach: %d debi init -- %d\n",
 738                      DEBI_CFG_SLAVE16 | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
 739                      DEBI_SWAP | DEBI_CFG_INTEL,
 740                      DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ |
 741                      DEBI_CFG_16Q);
 742
 743                /* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */
 744                /* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */
 745
 746                /*  Paging is disabled. */
 747                WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);  /*  Disable MMU paging. */
 748
 749                /*  Init GPIO so that ADC Start* is negated. */
 750                WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
 751
 752                /* IsBoardRevA is a boolean that indicates whether the board is RevA.
 753                 *
 754                 * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
 755                 * EEPROM ADDRESS SELECTION.  Initialize the I2C interface, which
 756                 * is used to access the onboard serial EEPROM.  The EEPROM's I2C
 757                 * DeviceAddress is hardwired to a value that is dependent on the
 758                 * 626 board revision.  On all board revisions, the EEPROM stores
 759                 * TrimDAC calibration constants for analog I/O.  On RevB and
 760                 * higher boards, the DeviceAddress is hardwired to 0 to enable
 761                 * the EEPROM to also store the PCI SubVendorID and SubDeviceID;
 762                 * this is the address at which the SAA7146 expects a
 763                 * configuration EEPROM to reside.  On RevA boards, the EEPROM
 764                 * device address, which is hardwired to 4, prevents the SAA7146
 765                 * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
 766                 * default values, instead.
 767                 */
 768
 769                /*     devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */
 770                /*  DeviceType (0xA0) */
 771                /*  and DeviceAddress<<1. */
 772
 773                devpriv->I2CAdrs = 0xA0;        /*  I2C device address for onboard */
 774                /*  eeprom(revb) */
 775
 776                /*  Issue an I2C ABORT command to halt any I2C operation in */
 777                /* progress and reset BUSY flag. */
 778                WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
 779                /*  Write I2C control: abort any I2C activity. */
 780                MC_ENABLE(P_MC2, MC2_UPLD_IIC);
 781                /*  Invoke command  upload */
 782                while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) ;
 783                /*  and wait for upload to complete. */
 784
 785                /* Per SAA7146 data sheet, write to STATUS reg twice to
 786                 * reset all  I2C error flags. */
 787                for (i = 0; i < 2; i++) {
 788                        WR7146(P_I2CSTAT, I2C_CLKSEL);
 789                        /*  Write I2C control: reset  error flags. */
 790                        MC_ENABLE(P_MC2, MC2_UPLD_IIC); /*  Invoke command upload */
 791                        while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;
 792                        /* and wait for upload to complete. */
 793                }
 794
 795                /* Init audio interface functional attributes: set DAC/ADC
 796                 * serial clock rates, invert DAC serial clock so that
 797                 * DAC data setup times are satisfied, enable DAC serial
 798                 * clock out.
 799                 */
 800
 801                WR7146(P_ACON2, ACON2_INIT);
 802
 803                /* Set up TSL1 slot list, which is used to control the
 804                 * accumulation of ADC data: RSD1 = shift data in on SD1.
 805                 * SIB_A1  = store data uint8_t at next available location in
 806                 * FB BUFFER1  register. */
 807                WR7146(P_TSL1, RSD1 | SIB_A1);
 808                /*  Fetch ADC high data uint8_t. */
 809                WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
 810                /*  Fetch ADC low data uint8_t; end of TSL1. */
 811
 812                /*  enab TSL1 slot list so that it executes all the time. */
 813                WR7146(P_ACON1, ACON1_ADCSTART);
 814
 815                /*  Initialize RPS registers used for ADC. */
 816
 817                /* Physical start of RPS program. */
 818                WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
 819
 820                WR7146(P_RPSPAGE1, 0);
 821                /*  RPS program performs no explicit mem writes. */
 822                WR7146(P_RPS1_TOUT, 0); /*  Disable RPS timeouts. */
 823
 824                /* SAA7146 BUG WORKAROUND.  Initialize SAA7146 ADC interface
 825                 * to a known state by invoking ADCs until FB BUFFER 1
 826                 * register shows that it is correctly receiving ADC data.
 827                 * This is necessary because the SAA7146 ADC interface does
 828                 * not start up in a defined state after a PCI reset.
 829                 */
 830
 831/*     PollList = EOPL;                 // Create a simple polling */
 832/*                                      // list for analog input */
 833/*                                      // channel 0. */
 834/*     ResetADC( dev, &PollList ); */
 835
 836/*     s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
 837/*                                                //Get initial ADC */
 838/*                                                //value. */
 839
 840/*     StartVal = data[0]; */
 841
 842/*     // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
 843/*     // Invoke ADCs until the new ADC value differs from the initial */
 844/*     // value or a timeout occurs.  The timeout protects against the */
 845/*     // possibility that the driver is restarting and the ADC data is a */
 846/*     // fixed value resulting from the applied ADC analog input being */
 847/*     // unusually quiet or at the rail. */
 848
 849/*     for ( index = 0; index < 500; index++ ) */
 850/*       { */
 851/*      s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
 852/*      AdcData = data[0];      //ReadADC(  &AdcData ); */
 853/*      if ( AdcData != StartVal ) */
 854/*        break; */
 855/*       } */
 856
 857                /*  end initADC */
 858
 859                /*  init the DAC interface */
 860
 861                /* Init Audio2's output DMAC attributes: burst length = 1
 862                 * DWORD,  threshold = 1 DWORD.
 863                 */
 864                WR7146(P_PCI_BT_A, 0);
 865
 866                /* Init Audio2's output DMA physical addresses.  The protection
 867                 * address is set to 1 DWORD past the base address so that a
 868                 * single DWORD will be transferred each time a DMA transfer is
 869                 * enabled. */
 870
 871                pPhysBuf =
 872                    devpriv->ANABuf.PhysicalBase +
 873                    (DAC_WDMABUF_OS * sizeof(uint32_t));
 874
 875                WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);      /*  Buffer base adrs. */
 876                WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); /*  Protection address. */
 877
 878                /* Cache Audio2's output DMA buffer logical address.  This is
 879                 * where DAC data is buffered for A2 output DMA transfers. */
 880                devpriv->pDacWBuf =
 881                    (uint32_t *) devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS;
 882
 883                /* Audio2's output channels does not use paging.  The protection
 884                 * violation handling bit is set so that the DMAC will
 885                 * automatically halt and its PCI address pointer will be reset
 886                 * when the protection address is reached. */
 887
 888                WR7146(P_PAGEA2_OUT, 8);
 889
 890                /* Initialize time slot list 2 (TSL2), which is used to control
 891                 * the clock generation for and serialization of data to be sent
 892                 * to the DAC devices.  Slot 0 is a NOP that is used to trap TSL
 893                 * execution; this permits other slots to be safely modified
 894                 * without first turning off the TSL sequencer (which is
 895                 * apparently impossible to do).  Also, SD3 (which is driven by a
 896                 * pull-up resistor) is shifted in and stored to the MSB of
 897                 * FB_BUFFER2 to be used as evidence that the slot sequence has
 898                 * not yet finished executing.
 899                 */
 900
 901                SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
 902                /*  Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */
 903
 904                /* Initialize slot 1, which is constant.  Slot 1 causes a
 905                 * DWORD to be transferred from audio channel 2's output FIFO
 906                 * to the FIFO's output buffer so that it can be serialized
 907                 * and sent to the DAC during subsequent slots.  All remaining
 908                 * slots are dynamically populated as required by the target
 909                 * DAC device.
 910                 */
 911                SETVECT(1, LF_A2);
 912                /*  Slot 1: Fetch DWORD from Audio2's output FIFO. */
 913
 914                /*  Start DAC's audio interface (TSL2) running. */
 915                WR7146(P_ACON1, ACON1_DACSTART);
 916
 917                /* end init DAC interface */
 918
 919                /* Init Trim DACs to calibrated values.  Do it twice because the
 920                 * SAA7146 audio channel does not always reset properly and
 921                 * sometimes causes the first few TrimDAC writes to malfunction.
 922                 */
 923
 924                LoadTrimDACs(dev);
 925                LoadTrimDACs(dev);      /*  Insurance. */
 926
 927                /* Manually init all gate array hardware in case this is a soft
 928                 * reset (we have no way of determining whether this is a warm
 929                 * or cold start).  This is necessary because the gate array will
 930                 * reset only in response to a PCI hard reset; there is no soft
 931                 * reset function. */
 932
 933                /* Init all DAC outputs to 0V and init all DAC setpoint and
 934                 * polarity images.
 935                 */
 936                for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
 937                        SetDAC(dev, chan, 0);
 938
 939                /* Init image of WRMISC2 Battery Charger Enabled control bit.
 940                 * This image is used when the state of the charger control bit,
 941                 * which has no direct hardware readback mechanism, is queried.
 942                 */
 943                devpriv->ChargeEnabled = 0;
 944
 945                /* Init image of watchdog timer interval in WRMISC2.  This image
 946                 * maintains the value of the control bits of MISC2 are
 947                 * continuously reset to zero as long as the WD timer is disabled.
 948                 */
 949                devpriv->WDInterval = 0;
 950
 951                /* Init Counter Interrupt enab mask for RDMISC2.  This mask is
 952                 * applied against MISC2 when testing to determine which timer
 953                 * events are requesting interrupt service.
 954                 */
 955                devpriv->CounterIntEnabs = 0;
 956
 957                /*  Init counters. */
 958                CountersInit(dev);
 959
 960                /* Without modifying the state of the Battery Backup enab, disable
 961                 * the watchdog timer, set DIO channels 0-5 to operate in the
 962                 * standard DIO (vs. counter overflow) mode, disable the battery
 963                 * charger, and reset the watchdog interval selector to zero.
 964                 */
 965                WriteMISC2(dev, (uint16_t) (DEBIread(dev,
 966                                                     LP_RDMISC2) &
 967                                            MISC2_BATT_ENABLE));
 968
 969                /*  Initialize the digital I/O subsystem. */
 970                s626_dio_init(dev);
 971
 972                /* enable interrupt test */
 973                /*  writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */
 974        }
 975
 976        DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor,
 977              (uint32_t) devpriv->base_addr);
 978
 979        return 1;
 980}
 981
 982static unsigned int s626_ai_reg_to_uint(int data)
 983{
 984        unsigned int tempdata;
 985
 986        tempdata = (data >> 18);
 987        if (tempdata & 0x2000)
 988                tempdata &= 0x1fff;
 989        else
 990                tempdata += (1 << 13);
 991
 992        return tempdata;
 993}
 994
 995/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */
 996/*   return 0; */
 997/* } */
 998
 999static irqreturn_t s626_irq_handler(int irq, void *d)
1000{
1001        struct comedi_device *dev = d;
1002        struct comedi_subdevice *s;
1003        struct comedi_cmd *cmd;
1004        struct enc_private *k;
1005        unsigned long flags;
1006        int32_t *readaddr;
1007        uint32_t irqtype, irqstatus;
1008        int i = 0;
1009        short tempdata;
1010        uint8_t group;
1011        uint16_t irqbit;
1012
1013        DEBUG("s626_irq_handler: interrupt request recieved!!!\n");
1014
1015        if (dev->attached == 0)
1016                return IRQ_NONE;
1017        /*  lock to avoid race with comedi_poll */
1018        spin_lock_irqsave(&dev->spinlock, flags);
1019
1020        /* save interrupt enable register state */
1021        irqstatus = readl(devpriv->base_addr + P_IER);
1022
1023        /* read interrupt type */
1024        irqtype = readl(devpriv->base_addr + P_ISR);
1025
1026        /* disable master interrupt */
1027        writel(0, devpriv->base_addr + P_IER);
1028
1029        /* clear interrupt */
1030        writel(irqtype, devpriv->base_addr + P_ISR);
1031
1032        /* do somethings */
1033        DEBUG("s626_irq_handler: interrupt type %d\n", irqtype);
1034
1035        switch (irqtype) {
1036        case IRQ_RPS1:          /*  end_of_scan occurs */
1037
1038                DEBUG("s626_irq_handler: RPS1 irq detected\n");
1039
1040                /*  manage ai subdevice */
1041                s = dev->subdevices;
1042                cmd = &(s->async->cmd);
1043
1044                /* Init ptr to DMA buffer that holds new ADC data.  We skip the
1045                 * first uint16_t in the buffer because it contains junk data from
1046                 * the final ADC of the previous poll list scan.
1047                 */
1048                readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1;
1049
1050                /*  get the data and hand it over to comedi */
1051                for (i = 0; i < (s->async->cmd.chanlist_len); i++) {
1052                        /*  Convert ADC data to 16-bit integer values and copy to application */
1053                        /*  buffer. */
1054                        tempdata = s626_ai_reg_to_uint((int)*readaddr);
1055                        readaddr++;
1056
1057                        /* put data into read buffer */
1058                        /*  comedi_buf_put(s->async, tempdata); */
1059                        if (cfc_write_to_buffer(s, tempdata) == 0)
1060                                printk
1061                                    ("s626_irq_handler: cfc_write_to_buffer error!\n");
1062
1063                        DEBUG("s626_irq_handler: ai channel %d acquired: %d\n",
1064                              i, tempdata);
1065                }
1066
1067                /* end of scan occurs */
1068                s->async->events |= COMEDI_CB_EOS;
1069
1070                if (!(devpriv->ai_continous))
1071                        devpriv->ai_sample_count--;
1072                if (devpriv->ai_sample_count <= 0) {
1073                        devpriv->ai_cmd_running = 0;
1074
1075                        /*  Stop RPS program. */
1076                        MC_DISABLE(P_MC1, MC1_ERPS1);
1077
1078                        /* send end of acquisition */
1079                        s->async->events |= COMEDI_CB_EOA;
1080
1081                        /* disable master interrupt */
1082                        irqstatus = 0;
1083                }
1084
1085                if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT) {
1086                        DEBUG
1087                            ("s626_irq_handler: enable interrupt on dio channel %d\n",
1088                             cmd->scan_begin_arg);
1089
1090                        s626_dio_set_irq(dev, cmd->scan_begin_arg);
1091
1092                        DEBUG("s626_irq_handler: External trigger is set!!!\n");
1093                }
1094                /*  tell comedi that data is there */
1095                DEBUG("s626_irq_handler: events %d\n", s->async->events);
1096                comedi_event(dev, s);
1097                break;
1098        case IRQ_GPIO3: /* check dio and conter interrupt */
1099
1100                DEBUG("s626_irq_handler: GPIO3 irq detected\n");
1101
1102                /*  manage ai subdevice */
1103                s = dev->subdevices;
1104                cmd = &(s->async->cmd);
1105
1106                /* s626_dio_clear_irq(dev); */
1107
1108                for (group = 0; group < S626_DIO_BANKS; group++) {
1109                        irqbit = 0;
1110                        /* read interrupt type */
1111                        irqbit = DEBIread(dev,
1112                                          ((struct dio_private *)(dev->
1113                                                                  subdevices +
1114                                                                  2 +
1115                                                                  group)->
1116                                           private)->RDCapFlg);
1117
1118                        /* check if interrupt is generated from dio channels */
1119                        if (irqbit) {
1120                                s626_dio_reset_irq(dev, group, irqbit);
1121                                DEBUG
1122                                    ("s626_irq_handler: check interrupt on dio group %d %d\n",
1123                                     group, i);
1124                                if (devpriv->ai_cmd_running) {
1125                                        /* check if interrupt is an ai acquisition start trigger */
1126                                        if ((irqbit >> (cmd->start_arg -
1127                                                        (16 * group)))
1128                                            == 1 && cmd->start_src == TRIG_EXT) {
1129                                                DEBUG
1130                                                    ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",
1131                                                     cmd->start_arg);
1132
1133                                                /*  Start executing the RPS program. */
1134                                                MC_ENABLE(P_MC1, MC1_ERPS1);
1135
1136                                                DEBUG
1137                                                    ("s626_irq_handler: aquisition start triggered!!!\n");
1138
1139                                                if (cmd->scan_begin_src ==
1140                                                    TRIG_EXT) {
1141                                                        DEBUG
1142                                                            ("s626_ai_cmd: enable interrupt on dio channel %d\n",
1143                                                             cmd->
1144                                                             scan_begin_arg);
1145
1146                                                        s626_dio_set_irq(dev,
1147                                                                         cmd->scan_begin_arg);
1148
1149                                                        DEBUG
1150                                                            ("s626_irq_handler: External scan trigger is set!!!\n");
1151                                                }
1152                                        }
1153                                        if ((irqbit >> (cmd->scan_begin_arg -
1154                                                        (16 * group)))
1155                                            == 1
1156                                            && cmd->scan_begin_src ==
1157                                            TRIG_EXT) {
1158                                                DEBUG
1159                                                    ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",
1160                                                     cmd->scan_begin_arg);
1161
1162                                                /*  Trigger ADC scan loop start by setting RPS Signal 0. */
1163                                                MC_ENABLE(P_MC2, MC2_ADC_RPS);
1164
1165                                                DEBUG
1166                                                    ("s626_irq_handler: scan triggered!!! %d\n",
1167                                                     devpriv->ai_sample_count);
1168                                                if (cmd->convert_src ==
1169                                                    TRIG_EXT) {
1170
1171                                                        DEBUG
1172                                                            ("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",
1173                                                             cmd->convert_arg -
1174                                                             (16 * group),
1175                                                             group);
1176
1177                                                        devpriv->ai_convert_count
1178                                                            = cmd->chanlist_len;
1179
1180                                                        s626_dio_set_irq(dev,
1181                                                                         cmd->convert_arg);
1182
1183                                                        DEBUG
1184                                                            ("s626_irq_handler: External convert trigger is set!!!\n");
1185                                                }
1186
1187                                                if (cmd->convert_src ==
1188                                                    TRIG_TIMER) {
1189                                                        k = &encpriv[5];
1190                                                        devpriv->ai_convert_count
1191                                                            = cmd->chanlist_len;
1192                                                        k->SetEnable(dev, k,
1193                                                                     CLKENAB_ALWAYS);
1194                                                }
1195                                        }
1196                                        if ((irqbit >> (cmd->convert_arg -
1197                                                        (16 * group)))
1198                                            == 1
1199                                            && cmd->convert_src == TRIG_EXT) {
1200                                                DEBUG
1201                                                    ("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",
1202                                                     cmd->convert_arg);
1203
1204                                                /*  Trigger ADC scan loop start by setting RPS Signal 0. */
1205                                                MC_ENABLE(P_MC2, MC2_ADC_RPS);
1206
1207                                                DEBUG
1208                                                    ("s626_irq_handler: adc convert triggered!!!\n");
1209
1210                                                devpriv->ai_convert_count--;
1211
1212                                                if (devpriv->ai_convert_count >
1213                                                    0) {
1214
1215                                                        DEBUG
1216                                                            ("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",
1217                                                             cmd->convert_arg -
1218                                                             (16 * group),
1219                                                             group);
1220
1221                                                        s626_dio_set_irq(dev,
1222                                                                         cmd->convert_arg);
1223
1224                                                        DEBUG
1225                                                            ("s626_irq_handler: External trigger is set!!!\n");
1226                                                }
1227                                        }
1228                                }
1229                                break;
1230                        }
1231                }
1232
1233                /* read interrupt type */
1234                irqbit = DEBIread(dev, LP_RDMISC2);
1235
1236                /* check interrupt on counters */
1237                DEBUG("s626_irq_handler: check counters interrupt %d\n",
1238                      irqbit);
1239
1240                if (irqbit & IRQ_COINT1A) {
1241                        DEBUG
1242                            ("s626_irq_handler: interrupt on counter 1A overflow\n");
1243                        k = &encpriv[0];
1244
1245                        /* clear interrupt capture flag */
1246                        k->ResetCapFlags(dev, k);
1247                }
1248                if (irqbit & IRQ_COINT2A) {
1249                        DEBUG
1250                            ("s626_irq_handler: interrupt on counter 2A overflow\n");
1251                        k = &encpriv[1];
1252
1253                        /* clear interrupt capture flag */
1254                        k->ResetCapFlags(dev, k);
1255                }
1256                if (irqbit & IRQ_COINT3A) {
1257                        DEBUG
1258                            ("s626_irq_handler: interrupt on counter 3A overflow\n");
1259                        k = &encpriv[2];
1260
1261                        /* clear interrupt capture flag */
1262                        k->ResetCapFlags(dev, k);
1263                }
1264                if (irqbit & IRQ_COINT1B) {
1265                        DEBUG
1266                            ("s626_irq_handler: interrupt on counter 1B overflow\n");
1267                        k = &encpriv[3];
1268
1269                        /* clear interrupt capture flag */
1270                        k->ResetCapFlags(dev, k);
1271                }
1272                if (irqbit & IRQ_COINT2B) {
1273                        DEBUG
1274                            ("s626_irq_handler: interrupt on counter 2B overflow\n");
1275                        k = &encpriv[4];
1276
1277                        /* clear interrupt capture flag */
1278                        k->ResetCapFlags(dev, k);
1279
1280                        if (devpriv->ai_convert_count > 0) {
1281                                devpriv->ai_convert_count--;
1282                                if (devpriv->ai_convert_count == 0)
1283                                        k->SetEnable(dev, k, CLKENAB_INDEX);
1284
1285                                if (cmd->convert_src == TRIG_TIMER) {
1286                                        DEBUG
1287                                            ("s626_irq_handler: conver timer trigger!!! %d\n",
1288                                             devpriv->ai_convert_count);
1289
1290                                        /*  Trigger ADC scan loop start by setting RPS Signal 0. */
1291                                        MC_ENABLE(P_MC2, MC2_ADC_RPS);
1292                                }
1293                        }
1294                }
1295                if (irqbit & IRQ_COINT3B) {
1296                        DEBUG
1297                            ("s626_irq_handler: interrupt on counter 3B overflow\n");
1298                        k = &encpriv[5];
1299
1300                        /* clear interrupt capture flag */
1301                        k->ResetCapFlags(dev, k);
1302
1303                        if (cmd->scan_begin_src == TRIG_TIMER) {
1304                                DEBUG
1305                                    ("s626_irq_handler: scan timer trigger!!!\n");
1306
1307                                /*  Trigger ADC scan loop start by setting RPS Signal 0. */
1308                                MC_ENABLE(P_MC2, MC2_ADC_RPS);
1309                        }
1310
1311                        if (cmd->convert_src == TRIG_TIMER) {
1312                                DEBUG
1313                                    ("s626_irq_handler: convert timer trigger is set\n");
1314                                k = &encpriv[4];
1315                                devpriv->ai_convert_count = cmd->chanlist_len;
1316                                k->SetEnable(dev, k, CLKENAB_ALWAYS);
1317                        }
1318                }
1319        }
1320
1321        /* enable interrupt */
1322        writel(irqstatus, devpriv->base_addr + P_IER);
1323
1324        DEBUG("s626_irq_handler: exit interrupt service routine.\n");
1325
1326        spin_unlock_irqrestore(&dev->spinlock, flags);
1327        return IRQ_HANDLED;
1328}
1329
1330static int s626_detach(struct comedi_device *dev)
1331{
1332        if (devpriv) {
1333                /* stop ai_command */
1334                devpriv->ai_cmd_running = 0;
1335
1336                if (devpriv->base_addr) {
1337                        /* interrupt mask */
1338                        WR7146(P_IER, 0);       /*  Disable master interrupt. */
1339                        WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1);    /*  Clear board's IRQ status flag. */
1340
1341                        /*  Disable the watchdog timer and battery charger. */
1342                        WriteMISC2(dev, 0);
1343
1344                        /*  Close all interfaces on 7146 device. */
1345                        WR7146(P_MC1, MC1_SHUTDOWN);
1346                        WR7146(P_ACON1, ACON1_BASE);
1347
1348                        CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE);
1349                        CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE);
1350                }
1351
1352                if (dev->irq)
1353                        free_irq(dev->irq, dev);
1354
1355                if (devpriv->base_addr)
1356                        iounmap(devpriv->base_addr);
1357
1358                if (devpriv->pdev) {
1359                        if (devpriv->got_regions)
1360                                comedi_pci_disable(devpriv->pdev);
1361                        pci_dev_put(devpriv->pdev);
1362                }
1363        }
1364
1365        DEBUG("s626_detach: S626 detached!\n");
1366
1367        return 0;
1368}
1369
1370/*
1371 * this functions build the RPS program for hardware driven acquistion
1372 */
1373void ResetADC(struct comedi_device *dev, uint8_t * ppl)
1374{
1375        register uint32_t *pRPS;
1376        uint32_t JmpAdrs;
1377        uint16_t i;
1378        uint16_t n;
1379        uint32_t LocalPPL;
1380        struct comedi_cmd *cmd = &(dev->subdevices->async->cmd);
1381
1382        /*  Stop RPS program in case it is currently running. */
1383        MC_DISABLE(P_MC1, MC1_ERPS1);
1384
1385        /*  Set starting logical address to write RPS commands. */
1386        pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase;
1387
1388        /*  Initialize RPS instruction pointer. */
1389        WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
1390
1391        /*  Construct RPS program in RPSBuf DMA buffer */
1392
1393        if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
1394                DEBUG("ResetADC: scan_begin pause inserted\n");
1395                /*  Wait for Start trigger. */
1396                *pRPS++ = RPS_PAUSE | RPS_SIGADC;
1397                *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
1398        }
1399
1400        /* SAA7146 BUG WORKAROUND Do a dummy DEBI Write.  This is necessary
1401         * because the first RPS DEBI Write following a non-RPS DEBI write
1402         * seems to always fail.  If we don't do this dummy write, the ADC
1403         * gain might not be set to the value required for the first slot in
1404         * the poll list; the ADC gain would instead remain unchanged from
1405         * the previously programmed value.
1406         */
1407        *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
1408        /* Write DEBI Write command and address to shadow RAM. */
1409
1410        *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
1411        *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
1412        /*  Write DEBI immediate data  to shadow RAM: */
1413
1414        *pRPS++ = GSEL_BIPOLAR5V;
1415        /*  arbitrary immediate data  value. */
1416
1417        *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
1418        /*  Reset "shadow RAM  uploaded" flag. */
1419        *pRPS++ = RPS_UPLOAD | RPS_DEBI;        /*  Invoke shadow RAM upload. */
1420        *pRPS++ = RPS_PAUSE | RPS_DEBI; /*  Wait for shadow upload to finish. */
1421
1422        /* Digitize all slots in the poll list. This is implemented as a
1423         * for loop to limit the slot count to 16 in case the application
1424         * forgot to set the EOPL flag in the final slot.
1425         */
1426        for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) {
1427                /* Convert application's poll list item to private board class
1428                 * format.  Each app poll list item is an uint8_t with form
1429                 * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
1430                 * +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
1431                 */
1432                LocalPPL =
1433                    (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V :
1434                                   GSEL_BIPOLAR10V);
1435
1436                /*  Switch ADC analog gain. */
1437                *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); /*  Write DEBI command */
1438                /*  and address to */
1439                /*  shadow RAM. */
1440                *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
1441                *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);  /*  Write DEBI */
1442                /*  immediate data to */
1443                /*  shadow RAM. */
1444                *pRPS++ = LocalPPL;
1445                *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;     /*  Reset "shadow RAM uploaded" */
1446                /*  flag. */
1447                *pRPS++ = RPS_UPLOAD | RPS_DEBI;        /*  Invoke shadow RAM upload. */
1448                *pRPS++ = RPS_PAUSE | RPS_DEBI; /*  Wait for shadow upload to */
1449                /*  finish. */
1450
1451                /*  Select ADC analog input channel. */
1452                *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
1453                /*  Write DEBI command and address to  shadow RAM. */
1454                *pRPS++ = DEBI_CMD_WRWORD | LP_ISEL;
1455                *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
1456                /*  Write DEBI immediate data to shadow RAM. */
1457                *pRPS++ = LocalPPL;
1458                *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
1459                /*  Reset "shadow RAM uploaded"  flag. */
1460
1461                *pRPS++ = RPS_UPLOAD | RPS_DEBI;
1462                /*  Invoke shadow RAM upload. */
1463
1464                *pRPS++ = RPS_PAUSE | RPS_DEBI;
1465                /*  Wait for shadow upload to finish. */
1466
1467                /* Delay at least 10 microseconds for analog input settling.
1468                 * Instead of padding with NOPs, we use RPS_JUMP instructions
1469                 * here; this allows us to produce a longer delay than is
1470                 * possible with NOPs because each RPS_JUMP flushes the RPS'
1471                 * instruction prefetch pipeline.
1472                 */
1473                JmpAdrs =
1474                    (uint32_t) devpriv->RPSBuf.PhysicalBase +
1475                    (uint32_t) ((unsigned long)pRPS -
1476                                (unsigned long)devpriv->RPSBuf.LogicalBase);
1477                for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) {
1478                        JmpAdrs += 8;   /*  Repeat to implement time delay: */
1479                        *pRPS++ = RPS_JUMP;     /*  Jump to next RPS instruction. */
1480                        *pRPS++ = JmpAdrs;
1481                }
1482
1483                if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
1484                        DEBUG("ResetADC: convert pause inserted\n");
1485                        /*  Wait for Start trigger. */
1486                        *pRPS++ = RPS_PAUSE | RPS_SIGADC;
1487                        *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
1488                }
1489                /*  Start ADC by pulsing GPIO1. */
1490                *pRPS++ = RPS_LDREG | (P_GPIO >> 2);    /*  Begin ADC Start pulse. */
1491                *pRPS++ = GPIO_BASE | GPIO1_LO;
1492                *pRPS++ = RPS_NOP;
1493                /*  VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
1494                *pRPS++ = RPS_LDREG | (P_GPIO >> 2);    /*  End ADC Start pulse. */
1495                *pRPS++ = GPIO_BASE | GPIO1_HI;
1496
1497                /* Wait for ADC to complete (GPIO2 is asserted high when ADC not
1498                 * busy) and for data from previous conversion to shift into FB
1499                 * BUFFER 1 register.
1500                 */
1501                *pRPS++ = RPS_PAUSE | RPS_GPIO2;        /*  Wait for ADC done. */
1502
1503                /*  Transfer ADC data from FB BUFFER 1 register to DMA buffer. */
1504                *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);
1505                *pRPS++ =
1506                    (uint32_t) devpriv->ANABuf.PhysicalBase +
1507                    (devpriv->AdcItems << 2);
1508
1509                /*  If this slot's EndOfPollList flag is set, all channels have */
1510                /*  now been processed. */
1511                if (*ppl++ & EOPL) {
1512                        devpriv->AdcItems++;    /*  Adjust poll list item count. */
1513                        break;  /*  Exit poll list processing loop. */
1514                }
1515        }
1516        DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems);
1517
1518        /* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US.  Allow the
1519         * ADC to stabilize for 2 microseconds before starting the final
1520         * (dummy) conversion.  This delay is necessary to allow sufficient
1521         * time between last conversion finished and the start of the dummy
1522         * conversion.  Without this delay, the last conversion's data value
1523         * is sometimes set to the previous conversion's data value.
1524         */
1525        for (n = 0; n < (2 * RPSCLK_PER_US); n++)
1526                *pRPS++ = RPS_NOP;
1527
1528        /* Start a dummy conversion to cause the data from the last
1529         * conversion of interest to be shifted in.
1530         */
1531        *pRPS++ = RPS_LDREG | (P_GPIO >> 2);    /*  Begin ADC Start pulse. */
1532        *pRPS++ = GPIO_BASE | GPIO1_LO;
1533        *pRPS++ = RPS_NOP;
1534        /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
1535        *pRPS++ = RPS_LDREG | (P_GPIO >> 2);    /*  End ADC Start pulse. */
1536        *pRPS++ = GPIO_BASE | GPIO1_HI;
1537
1538        /* Wait for the data from the last conversion of interest to arrive
1539         * in FB BUFFER 1 register.
1540         */
1541        *pRPS++ = RPS_PAUSE | RPS_GPIO2;        /*  Wait for ADC done. */
1542
1543        /*  Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */
1544        *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);        /*  */
1545        *pRPS++ =
1546            (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2);
1547
1548        /*  Indicate ADC scan loop is finished. */
1549        /*  *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;  // Signal ReadADC() that scan is done. */
1550
1551        /* invoke interrupt */
1552        if (devpriv->ai_cmd_running == 1) {
1553                DEBUG("ResetADC: insert irq in ADC RPS task\n");
1554                *pRPS++ = RPS_IRQ;
1555        }
1556        /*  Restart RPS program at its beginning. */
1557        *pRPS++ = RPS_JUMP;     /*  Branch to start of RPS program. */
1558        *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase;
1559
1560        /*  End of RPS program build */
1561}
1562
1563/* TO COMPLETE, IF NECESSARY */
1564static int s626_ai_insn_config(struct comedi_device *dev,
1565                               struct comedi_subdevice *s,
1566                               struct comedi_insn *insn, unsigned int *data)
1567{
1568
1569        return -EINVAL;
1570}
1571
1572/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */
1573/* { */
1574/*   register uint8_t   i; */
1575/*   register int32_t   *readaddr; */
1576
1577/*   DEBUG("as626_ai_rinsn: ai_rinsn enter \n");  */
1578
1579/*   Trigger ADC scan loop start by setting RPS Signal 0. */
1580/*   MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
1581
1582/*   Wait until ADC scan loop is finished (RPS Signal 0 reset). */
1583/*   while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
1584
1585/* Init ptr to DMA buffer that holds new ADC data.  We skip the
1586 * first uint16_t in the buffer because it contains junk data from
1587 * the final ADC of the previous poll list scan.
1588 */
1589/*   readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */
1590
1591/*  Convert ADC data to 16-bit integer values and copy to application buffer. */
1592/*   for ( i = 0; i < devpriv->AdcItems; i++ ) { */
1593/*     *data = s626_ai_reg_to_uint( *readaddr++ ); */
1594/*     DEBUG("s626_ai_rinsn: data %d \n",*data); */
1595/*     data++; */
1596/*   } */
1597
1598/*   DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */
1599/*   return i; */
1600/* } */
1601
1602static int s626_ai_insn_read(struct comedi_device *dev,
1603                             struct comedi_subdevice *s,
1604                             struct comedi_insn *insn, unsigned int *data)
1605{
1606        uint16_t chan = CR_CHAN(insn->chanspec);
1607        uint16_t range = CR_RANGE(insn->chanspec);
1608        uint16_t AdcSpec = 0;
1609        uint32_t GpioImage;
1610        int n;
1611
1612        /* interrupt call test  */
1613/*   writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); */
1614        /* Writing a logical 1 into any of the RPS_PSR bits causes the
1615         * corresponding interrupt to be generated if enabled
1616         */
1617
1618        DEBUG("s626_ai_insn_read: entering\n");
1619
1620        /* Convert application's ADC specification into form
1621         *  appropriate for register programming.
1622         */
1623        if (range == 0)
1624                AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V);
1625        else
1626                AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V);
1627
1628        /*  Switch ADC analog gain. */
1629        DEBIwrite(dev, LP_GSEL, AdcSpec);       /*  Set gain. */
1630
1631        /*  Select ADC analog input channel. */
1632        DEBIwrite(dev, LP_ISEL, AdcSpec);       /*  Select channel. */
1633
1634        for (n = 0; n < insn->n; n++) {
1635
1636                /*  Delay 10 microseconds for analog input settling. */
1637                udelay(10);
1638
1639                /*  Start ADC by pulsing GPIO1 low. */
1640                GpioImage = RR7146(P_GPIO);
1641                /*  Assert ADC Start command */
1642                WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1643                /*    and stretch it out. */
1644                WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1645                WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1646                /*  Negate ADC Start command. */
1647                WR7146(P_GPIO, GpioImage | GPIO1_HI);
1648
1649                /*  Wait for ADC to complete (GPIO2 is asserted high when */
1650                /*  ADC not busy) and for data from previous conversion to */
1651                /*  shift into FB BUFFER 1 register. */
1652
1653                /*  Wait for ADC done. */
1654                while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
1655
1656                /*  Fetch ADC data. */
1657                if (n != 0)
1658                        data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
1659
1660                /* Allow the ADC to stabilize for 4 microseconds before
1661                 * starting the next (final) conversion.  This delay is
1662                 * necessary to allow sufficient time between last
1663                 * conversion finished and the start of the next
1664                 * conversion.  Without this delay, the last conversion's
1665                 * data value is sometimes set to the previous
1666                 * conversion's data value.
1667                 */
1668                udelay(4);
1669        }
1670
1671        /* Start a dummy conversion to cause the data from the
1672         * previous conversion to be shifted in. */
1673        GpioImage = RR7146(P_GPIO);
1674
1675        /* Assert ADC Start command */
1676        WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1677        /*    and stretch it out. */
1678        WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1679        WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
1680        /*  Negate ADC Start command. */
1681        WR7146(P_GPIO, GpioImage | GPIO1_HI);
1682
1683        /*  Wait for the data to arrive in FB BUFFER 1 register. */
1684
1685        /*  Wait for ADC done. */
1686        while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
1687
1688        /*  Fetch ADC data from audio interface's input shift register. */
1689
1690        /*  Fetch ADC data. */
1691        if (n != 0)
1692                data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
1693
1694        DEBUG("s626_ai_insn_read: samples %d, data %d\n", n, data[n - 1]);
1695
1696        return n;
1697}
1698
1699static int s626_ai_load_polllist(uint8_t * ppl, struct comedi_cmd *cmd)
1700{
1701
1702        int n;
1703
1704        for (n = 0; n < cmd->chanlist_len; n++) {
1705                if (CR_RANGE((cmd->chanlist)[n]) == 0)
1706                        ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V);
1707                else
1708                        ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V);
1709        }
1710        if (n != 0)
1711                ppl[n - 1] |= EOPL;
1712
1713        return n;
1714}
1715
1716static int s626_ai_inttrig(struct comedi_device *dev,
1717                           struct comedi_subdevice *s, unsigned int trignum)
1718{
1719        if (trignum != 0)
1720                return -EINVAL;
1721
1722        DEBUG("s626_ai_inttrig: trigger adc start...");
1723
1724        /*  Start executing the RPS program. */
1725        MC_ENABLE(P_MC1, MC1_ERPS1);
1726
1727        s->async->inttrig = NULL;
1728
1729        DEBUG(" done\n");
1730
1731        return 1;
1732}
1733
1734/*  TO COMPLETE  */
1735static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1736{
1737
1738        uint8_t ppl[16];
1739        struct comedi_cmd *cmd = &s->async->cmd;
1740        struct enc_private *k;
1741        int tick;
1742
1743        DEBUG("s626_ai_cmd: entering command function\n");
1744
1745        if (devpriv->ai_cmd_running) {
1746                printk("s626_ai_cmd: Another ai_cmd is running %d\n",
1747                       dev->minor);
1748                return -EBUSY;
1749        }
1750        /* disable interrupt */
1751        writel(0, devpriv->base_addr + P_IER);
1752
1753        /* clear interrupt request */
1754        writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR);
1755
1756        /* clear any pending interrupt */
1757        s626_dio_clear_irq(dev);
1758        /*   s626_enc_clear_irq(dev); */
1759
1760        /* reset ai_cmd_running flag */
1761        devpriv->ai_cmd_running = 0;
1762
1763        /*  test if cmd is valid */
1764        if (cmd == NULL) {
1765                DEBUG("s626_ai_cmd: NULL command\n");
1766                return -EINVAL;
1767        } else {
1768                DEBUG("s626_ai_cmd: command recieved!!!\n");
1769        }
1770
1771        if (dev->irq == 0) {
1772                comedi_error(dev,
1773                             "s626_ai_cmd: cannot run command without an irq");
1774                return -EIO;
1775        }
1776
1777        s626_ai_load_polllist(ppl, cmd);
1778        devpriv->ai_cmd_running = 1;
1779        devpriv->ai_convert_count = 0;
1780
1781        switch (cmd->scan_begin_src) {
1782        case TRIG_FOLLOW:
1783                break;
1784        case TRIG_TIMER:
1785                /*  set a conter to generate adc trigger at scan_begin_arg interval */
1786                k = &encpriv[5];
1787                tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg,
1788                                        cmd->flags & TRIG_ROUND_MASK);
1789
1790                /* load timer value and enable interrupt */
1791                s626_timer_load(dev, k, tick);
1792                k->SetEnable(dev, k, CLKENAB_ALWAYS);
1793
1794                DEBUG("s626_ai_cmd: scan trigger timer is set with value %d\n",
1795                      tick);
1796
1797                break;
1798        case TRIG_EXT:
1799                /*  set the digital line and interrupt for scan trigger */
1800                if (cmd->start_src != TRIG_EXT)
1801                        s626_dio_set_irq(dev, cmd->scan_begin_arg);
1802
1803                DEBUG("s626_ai_cmd: External scan trigger is set!!!\n");
1804
1805                break;
1806        }
1807
1808        switch (cmd->convert_src) {
1809        case TRIG_NOW:
1810                break;
1811        case TRIG_TIMER:
1812                /*  set a conter to generate adc trigger at convert_arg interval */
1813                k = &encpriv[4];
1814                tick = s626_ns_to_timer((int *)&cmd->convert_arg,
1815                                        cmd->flags & TRIG_ROUND_MASK);
1816
1817                /* load timer value and enable interrupt */
1818                s626_timer_load(dev, k, tick);
1819                k->SetEnable(dev, k, CLKENAB_INDEX);
1820
1821                DEBUG
1822                    ("s626_ai_cmd: convert trigger timer is set with value %d\n",
1823                     tick);
1824                break;
1825        case TRIG_EXT:
1826                /*  set the digital line and interrupt for convert trigger */
1827                if (cmd->scan_begin_src != TRIG_EXT
1828                    && cmd->start_src == TRIG_EXT)
1829                        s626_dio_set_irq(dev, cmd->convert_arg);
1830
1831                DEBUG("s626_ai_cmd: External convert trigger is set!!!\n");
1832
1833                break;
1834        }
1835
1836        switch (cmd->stop_src) {
1837        case TRIG_COUNT:
1838                /*  data arrives as one packet */
1839                devpriv->ai_sample_count = cmd->stop_arg;
1840                devpriv->ai_continous = 0;
1841                break;
1842        case TRIG_NONE:
1843                /*  continous aquisition */
1844                devpriv->ai_continous = 1;
1845                devpriv->ai_sample_count = 0;
1846                break;
1847        }
1848
1849        ResetADC(dev, ppl);
1850
1851        switch (cmd->start_src) {
1852        case TRIG_NOW:
1853                /*  Trigger ADC scan loop start by setting RPS Signal 0. */
1854                /*  MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
1855
1856                /*  Start executing the RPS program. */
1857                MC_ENABLE(P_MC1, MC1_ERPS1);
1858
1859                DEBUG("s626_ai_cmd: ADC triggered\n");
1860                s->async->inttrig = NULL;
1861                break;
1862        case TRIG_EXT:
1863                /* configure DIO channel for acquisition trigger */
1864                s626_dio_set_irq(dev, cmd->start_arg);
1865
1866                DEBUG("s626_ai_cmd: External start trigger is set!!!\n");
1867
1868                s->async->inttrig = NULL;
1869                break;
1870        case TRIG_INT:
1871                s->async->inttrig = s626_ai_inttrig;
1872                break;
1873        }
1874
1875        /* enable interrupt */
1876        writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER);
1877
1878        DEBUG("s626_ai_cmd: command function terminated\n");
1879
1880        return 0;
1881}
1882
1883static int s626_ai_cmdtest(struct comedi_device *dev,
1884                           struct comedi_subdevice *s, struct comedi_cmd *cmd)
1885{
1886        int err = 0;
1887        int tmp;
1888
1889        /* cmdtest tests a particular command to see if it is valid.  Using
1890         * the cmdtest ioctl, a user can create a valid cmd and then have it
1891         * executes by the cmd ioctl.
1892         *
1893         * cmdtest returns 1,2,3,4 or 0, depending on which tests the
1894         * command passes. */
1895
1896        /* step 1: make sure trigger sources are trivially valid */
1897
1898        tmp = cmd->start_src;
1899        cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT;
1900        if (!cmd->start_src || tmp != cmd->start_src)
1901                err++;
1902
1903        tmp = cmd->scan_begin_src;
1904        cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
1905        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1906                err++;
1907
1908        tmp = cmd->convert_src;
1909        cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
1910        if (!cmd->convert_src || tmp != cmd->convert_src)
1911                err++;
1912
1913        tmp = cmd->scan_end_src;
1914        cmd->scan_end_src &= TRIG_COUNT;
1915        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1916                err++;
1917
1918        tmp = cmd->stop_src;
1919        cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1920        if (!cmd->stop_src || tmp != cmd->stop_src)
1921                err++;
1922
1923        if (err)
1924                return 1;
1925
1926        /* step 2: make sure trigger sources are unique and mutually
1927           compatible */
1928
1929        /* note that mutual compatiblity is not an issue here */
1930        if (cmd->scan_begin_src != TRIG_TIMER &&
1931            cmd->scan_begin_src != TRIG_EXT
1932            && cmd->scan_begin_src != TRIG_FOLLOW)
1933                err++;
1934        if (cmd->convert_src != TRIG_TIMER &&
1935            cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
1936                err++;
1937        if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1938                err++;
1939
1940        if (err)
1941                return 2;
1942
1943        /* step 3: make sure arguments are trivially compatible */
1944
1945        if (cmd->start_src != TRIG_EXT && cmd->start_arg != 0) {
1946                cmd->start_arg = 0;
1947                err++;
1948        }
1949
1950        if (cmd->start_src == TRIG_EXT && cmd->start_arg > 39) {
1951                cmd->start_arg = 39;
1952                err++;
1953        }
1954
1955        if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg > 39) {
1956                cmd->scan_begin_arg = 39;
1957                err++;
1958        }
1959
1960        if (cmd->convert_src == TRIG_EXT && cmd->convert_arg > 39) {
1961                cmd->convert_arg = 39;
1962                err++;
1963        }
1964#define MAX_SPEED       200000  /* in nanoseconds */
1965#define MIN_SPEED       2000000000      /* in nanoseconds */
1966
1967        if (cmd->scan_begin_src == TRIG_TIMER) {
1968                if (cmd->scan_begin_arg < MAX_SPEED) {
1969                        cmd->scan_begin_arg = MAX_SPEED;
1970                        err++;
1971                }
1972                if (cmd->scan_begin_arg > MIN_SPEED) {
1973                        cmd->scan_begin_arg = MIN_SPEED;
1974                        err++;
1975                }
1976        } else {
1977                /* external trigger */
1978                /* should be level/edge, hi/lo specification here */
1979                /* should specify multiple external triggers */
1980/*     if(cmd->scan_begin_arg>9){ */
1981/*       cmd->scan_begin_arg=9; */
1982/*       err++; */
1983/*     } */
1984        }
1985        if (cmd->convert_src == TRIG_TIMER) {
1986                if (cmd->convert_arg < MAX_SPEED) {
1987                        cmd->convert_arg = MAX_SPEED;
1988                        err++;
1989                }
1990                if (cmd->convert_arg > MIN_SPEED) {
1991                        cmd->convert_arg = MIN_SPEED;
1992                        err++;
1993                }
1994        } else {
1995                /* external trigger */
1996                /* see above */
1997/*     if(cmd->convert_arg>9){ */
1998/*       cmd->convert_arg=9; */
1999/*       err++; */
2000/*     } */
2001        }
2002
2003        if (cmd->scan_end_arg != cmd->chanlist_len) {
2004                cmd->scan_end_arg = cmd->chanlist_len;
2005                err++;
2006        }
2007        if (cmd->stop_src == TRIG_COUNT) {
2008                if (cmd->stop_arg > 0x00ffffff) {
2009                        cmd->stop_arg = 0x00ffffff;
2010                        err++;
2011                }
2012        } else {
2013                /* TRIG_NONE */
2014                if (cmd->stop_arg != 0) {
2015                        cmd->stop_arg = 0;
2016                        err++;
2017                }
2018        }
2019
2020        if (err)
2021                return 3;
2022
2023        /* step 4: fix up any arguments */
2024
2025        if (cmd->scan_begin_src == TRIG_TIMER) {
2026                tmp = cmd->scan_begin_arg;
2027                s626_ns_to_timer((int *)&cmd->scan_begin_arg,
2028                                 cmd->flags & TRIG_ROUND_MASK);
2029                if (tmp != cmd->scan_begin_arg)
2030                        err++;
2031        }
2032        if (cmd->convert_src == TRIG_TIMER) {
2033                tmp = cmd->convert_arg;
2034                s626_ns_to_timer((int *)&cmd->convert_arg,
2035                                 cmd->flags & TRIG_ROUND_MASK);
2036                if (tmp != cmd->convert_arg)
2037                        err++;
2038                if (cmd->scan_begin_src == TRIG_TIMER &&
2039                    cmd->scan_begin_arg <
2040                    cmd->convert_arg * cmd->scan_end_arg) {
2041                        cmd->scan_begin_arg =
2042                            cmd->convert_arg * cmd->scan_end_arg;
2043                        err++;
2044                }
2045        }
2046
2047        if (err)
2048                return 4;
2049
2050        return 0;
2051}
2052
2053static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2054{
2055        /*  Stop RPS program in case it is currently running. */
2056        MC_DISABLE(P_MC1, MC1_ERPS1);
2057
2058        /* disable master interrupt */
2059        writel(0, devpriv->base_addr + P_IER);
2060
2061        devpriv->ai_cmd_running = 0;
2062
2063        return 0;
2064}
2065
2066/* This function doesn't require a particular form, this is just what
2067 * happens to be used in some of the drivers.  It should convert ns
2068 * nanoseconds to a counter value suitable for programming the device.
2069 * Also, it should adjust ns so that it cooresponds to the actual time
2070 * that the device will use. */
2071static int s626_ns_to_timer(int *nanosec, int round_mode)
2072{
2073        int divider, base;
2074
2075        base = 500;             /* 2MHz internal clock */
2076
2077        switch (round_mode) {
2078        case TRIG_ROUND_NEAREST:
2079        default:
2080                divider = (*nanosec + base / 2) / base;
2081                break;
2082        case TRIG_ROUND_DOWN:
2083                divider = (*nanosec) / base;
2084                break;
2085        case TRIG_ROUND_UP:
2086                divider = (*nanosec + base - 1) / base;
2087                break;
2088        }
2089
2090        *nanosec = base * divider;
2091        return divider - 1;
2092}
2093
2094static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
2095                         struct comedi_insn *insn, unsigned int *data)
2096{
2097
2098        int i;
2099        uint16_t chan = CR_CHAN(insn->chanspec);
2100        int16_t dacdata;
2101
2102        for (i = 0; i < insn->n; i++) {
2103                dacdata = (int16_t) data[i];
2104                devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i];
2105                dacdata -= (0x1fff);
2106
2107                SetDAC(dev, chan, dacdata);
2108        }
2109
2110        return i;
2111}
2112
2113static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
2114                         struct comedi_insn *insn, unsigned int *data)
2115{
2116        int i;
2117
2118        for (i = 0; i < insn->n; i++)
2119                data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
2120
2121        return i;
2122}
2123
2124/* *************** DIGITAL I/O FUNCTIONS ***************
2125 * All DIO functions address a group of DIO channels by means of
2126 * "group" argument.  group may be 0, 1 or 2, which correspond to DIO
2127 * ports A, B and C, respectively.
2128 */
2129
2130static void s626_dio_init(struct comedi_device *dev)
2131{
2132        uint16_t group;
2133        struct comedi_subdevice *s;
2134
2135        /*  Prepare to treat writes to WRCapSel as capture disables. */
2136        DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
2137
2138        /*  For each group of sixteen channels ... */
2139        for (group = 0; group < S626_DIO_BANKS; group++) {
2140                s = dev->subdevices + 2 + group;
2141                DEBIwrite(dev, diopriv->WRIntSel, 0);   /*  Disable all interrupts. */
2142                DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF);      /*  Disable all event */
2143                /*  captures. */
2144                DEBIwrite(dev, diopriv->WREdgSel, 0);   /*  Init all DIOs to */
2145                /*  default edge */
2146                /*  polarity. */
2147                DEBIwrite(dev, diopriv->WRDOut, 0);     /*  Program all outputs */
2148                /*  to inactive state. */
2149        }
2150        DEBUG("s626_dio_init: DIO initialized \n");
2151}
2152
2153/* DIO devices are slightly special.  Although it is possible to
2154 * implement the insn_read/insn_write interface, it is much more
2155 * useful to applications if you implement the insn_bits interface.
2156 * This allows packed reading/writing of the DIO channels.  The comedi
2157 * core can convert between insn_bits and insn_read/write */
2158
2159static int s626_dio_insn_bits(struct comedi_device *dev,
2160                              struct comedi_subdevice *s,
2161                              struct comedi_insn *insn, unsigned int *data)
2162{
2163
2164        /* Length of data must be 2 (mask and new data, see below) */
2165        if (insn->n == 0)
2166                return 0;
2167
2168        if (insn->n != 2) {
2169                printk
2170                    ("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n",
2171                     dev->minor);
2172                return -EINVAL;
2173        }
2174
2175        /*
2176         * The insn data consists of a mask in data[0] and the new data in
2177         * data[1]. The mask defines which bits we are concerning about.
2178         * The new data must be anded with the mask.  Each channel
2179         * corresponds to a bit.
2180         */
2181        if (data[0]) {
2182                /* Check if requested ports are configured for output */
2183                if ((s->io_bits & data[0]) != data[0])
2184                        return -EIO;
2185
2186                s->state &= ~data[0];
2187                s->state |= data[0] & data[1];
2188
2189                /* Write out the new digital output lines */
2190
2191                DEBIwrite(dev, diopriv->WRDOut, s->state);
2192        }
2193        data[1] = DEBIread(dev, diopriv->RDDIn);
2194
2195        return 2;
2196}
2197
2198static int s626_dio_insn_config(struct comedi_device *dev,
2199                                struct comedi_subdevice *s,
2200                                struct comedi_insn *insn, unsigned int *data)
2201{
2202
2203        switch (data[0]) {
2204        case INSN_CONFIG_DIO_QUERY:
2205                data[1] =
2206                    (s->
2207                     io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
2208                    COMEDI_INPUT;
2209                return insn->n;
2210                break;
2211        case COMEDI_INPUT:
2212                s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
2213                break;
2214        case COMEDI_OUTPUT:
2215                s->io_bits |= 1 << CR_CHAN(insn->chanspec);
2216                break;
2217        default:
2218                return -EINVAL;
2219                break;
2220        }
2221        DEBIwrite(dev, diopriv->WRDOut, s->io_bits);
2222
2223        return 1;
2224}
2225
2226static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
2227{
2228        unsigned int group;
2229        unsigned int bitmask;
2230        unsigned int status;
2231
2232        /* select dio bank */
2233        group = chan / 16;
2234        bitmask = 1 << (chan - (16 * group));
2235        DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",
2236              chan - (16 * group), group);
2237
2238        /* set channel to capture positive edge */
2239        status = DEBIread(dev,
2240                          ((struct dio_private *)(dev->subdevices + 2 +
2241                                                  group)->private)->RDEdgSel);
2242        DEBIwrite(dev,
2243                  ((struct dio_private *)(dev->subdevices + 2 +
2244                                          group)->private)->WREdgSel,
2245                  bitmask | status);
2246
2247        /* enable interrupt on selected channel */
2248        status = DEBIread(dev,
2249                          ((struct dio_private *)(dev->subdevices + 2 +
2250                                                  group)->private)->RDIntSel);
2251        DEBIwrite(dev,
2252                  ((struct dio_private *)(dev->subdevices + 2 +
2253                                          group)->private)->WRIntSel,
2254                  bitmask | status);
2255
2256        /* enable edge capture write command */
2257        DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
2258
2259        /* enable edge capture on selected channel */
2260        status = DEBIread(dev,
2261                          ((struct dio_private *)(dev->subdevices + 2 +
2262                                                  group)->private)->RDCapSel);
2263        DEBIwrite(dev,
2264                  ((struct dio_private *)(dev->subdevices + 2 +
2265                                          group)->private)->WRCapSel,
2266                  bitmask | status);
2267
2268        return 0;
2269}
2270
2271static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
2272                              unsigned int mask)
2273{
2274        DEBUG
2275            ("s626_dio_reset_irq: disable  interrupt on dio channel %d group %d\n",
2276             mask, group);
2277
2278        /* disable edge capture write command */
2279        DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
2280
2281        /* enable edge capture on selected channel */
2282        DEBIwrite(dev,
2283                  ((struct dio_private *)(dev->subdevices + 2 +
2284                                          group)->private)->WRCapSel, mask);
2285
2286        return 0;
2287}
2288
2289static int s626_dio_clear_irq(struct comedi_device *dev)
2290{
2291        unsigned int group;
2292
2293        /* disable edge capture write command */
2294        DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
2295
2296        for (group = 0; group < S626_DIO_BANKS; group++) {
2297                /* clear pending events and interrupt */
2298                DEBIwrite(dev,
2299                          ((struct dio_private *)(dev->subdevices + 2 +
2300                                                  group)->private)->WRCapSel,
2301                          0xffff);
2302        }
2303
2304        return 0;
2305}
2306
2307/* Now this function initializes the value of the counter (data[0])
2308   and set the subdevice. To complete with trigger and interrupt
2309   configuration */
2310static int s626_enc_insn_config(struct comedi_device *dev,
2311                                struct comedi_subdevice *s,
2312                                struct comedi_insn *insn, unsigned int *data)
2313{
2314        uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /*  Preload upon */
2315            /*  index. */
2316            (INDXSRC_SOFT << BF_INDXSRC) |      /*  Disable hardware index. */
2317            (CLKSRC_COUNTER << BF_CLKSRC) |     /*  Operating mode is Counter. */
2318            (CLKPOL_POS << BF_CLKPOL) | /*  Active high clock. */
2319            /* ( CNTDIR_UP << BF_CLKPOL ) |      // Count direction is Down. */
2320            (CLKMULT_1X << BF_CLKMULT) |        /*  Clock multiplier is 1x. */
2321            (CLKENAB_INDEX << BF_CLKENAB);
2322        /*   uint16_t DisableIntSrc=TRUE; */
2323        /*  uint32_t Preloadvalue;              //Counter initial value */
2324        uint16_t valueSrclatch = LATCHSRC_AB_READ;
2325        uint16_t enab = CLKENAB_ALWAYS;
2326        struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
2327
2328        DEBUG("s626_enc_insn_config: encoder config\n");
2329
2330        /*   (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
2331
2332        k->SetMode(dev, k, Setup, TRUE);
2333        Preload(dev, k, *(insn->data));
2334        k->PulseIndex(dev, k);
2335        SetLatchSource(dev, k, valueSrclatch);
2336        k->SetEnable(dev, k, (uint16_t) (enab != 0));
2337
2338        return insn->n;
2339}
2340
2341static int s626_enc_insn_read(struct comedi_device *dev,
2342                              struct comedi_subdevice *s,
2343                              struct comedi_insn *insn, unsigned int *data)
2344{
2345
2346        int n;
2347        struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
2348
2349        DEBUG("s626_enc_insn_read: encoder read channel %d \n",
2350              CR_CHAN(insn->chanspec));
2351
2352        for (n = 0; n < insn->n; n++)
2353                data[n] = ReadLatch(dev, k);
2354
2355        DEBUG("s626_enc_insn_read: encoder sample %d\n", data[n]);
2356
2357        return n;
2358}
2359
2360static int s626_enc_insn_write(struct comedi_device *dev,
2361                               struct comedi_subdevice *s,
2362                               struct comedi_insn *insn, unsigned int *data)
2363{
2364
2365        struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
2366
2367        DEBUG("s626_enc_insn_write: encoder write channel %d \n",
2368              CR_CHAN(insn->chanspec));
2369
2370        /*  Set the preload register */
2371        Preload(dev, k, data[0]);
2372
2373        /*  Software index pulse forces the preload register to load */
2374        /*  into the counter */
2375        k->SetLoadTrig(dev, k, 0);
2376        k->PulseIndex(dev, k);
2377        k->SetLoadTrig(dev, k, 2);
2378
2379        DEBUG("s626_enc_insn_write: End encoder write\n");
2380
2381        return 1;
2382}
2383
2384static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
2385                            int tick)
2386{
2387        uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /*  Preload upon */
2388            /*  index. */
2389            (INDXSRC_SOFT << BF_INDXSRC) |      /*  Disable hardware index. */
2390            (CLKSRC_TIMER << BF_CLKSRC) |       /*  Operating mode is Timer. */
2391            (CLKPOL_POS << BF_CLKPOL) | /*  Active high clock. */
2392            (CNTDIR_DOWN << BF_CLKPOL) |        /*  Count direction is Down. */
2393            (CLKMULT_1X << BF_CLKMULT) |        /*  Clock multiplier is 1x. */
2394            (CLKENAB_INDEX << BF_CLKENAB);
2395        uint16_t valueSrclatch = LATCHSRC_A_INDXA;
2396        /*   uint16_t enab=CLKENAB_ALWAYS; */
2397
2398        k->SetMode(dev, k, Setup, FALSE);
2399
2400        /*  Set the preload register */
2401        Preload(dev, k, tick);
2402
2403        /*  Software index pulse forces the preload register to load */
2404        /*  into the counter */
2405        k->SetLoadTrig(dev, k, 0);
2406        k->PulseIndex(dev, k);
2407
2408        /* set reload on counter overflow */
2409        k->SetLoadTrig(dev, k, 1);
2410
2411        /* set interrupt on overflow */
2412        k->SetIntSrc(dev, k, INTSRC_OVER);
2413
2414        SetLatchSource(dev, k, valueSrclatch);
2415        /*   k->SetEnable(dev,k,(uint16_t)(enab != 0)); */
2416}
2417
2418/* ***********  DAC FUNCTIONS *********** */
2419
2420/*  Slot 0 base settings. */
2421#define VECT0   (XSD2 | RSD3 | SIB_A2)
2422/*  Slot 0 always shifts in  0xFF and store it to  FB_BUFFER2. */
2423
2424/*  TrimDac LogicalChan-to-PhysicalChan mapping table. */
2425static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
2426
2427/*  TrimDac LogicalChan-to-EepromAdrs mapping table. */
2428static uint8_t trimadrs[] =
2429    { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
2430
2431static void LoadTrimDACs(struct comedi_device *dev)
2432{
2433        register uint8_t i;
2434
2435        /*  Copy TrimDac setpoint values from EEPROM to TrimDacs. */
2436        for (i = 0; i < ARRAY_SIZE(trimchan); i++)
2437                WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
2438}
2439
2440static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
2441                         uint8_t DacData)
2442{
2443        uint32_t chan;
2444
2445        /*  Save the new setpoint in case the application needs to read it back later. */
2446        devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData;
2447
2448        /*  Map logical channel number to physical channel number. */
2449        chan = (uint32_t) trimchan[LogicalChan];
2450
2451        /* Set up TSL2 records for TrimDac write operation.  All slots shift
2452         * 0xFF in from pulled-up SD3 so that the end of the slot sequence
2453         * can be detected.
2454         */
2455
2456        SETVECT(2, XSD2 | XFIFO_1 | WS3);
2457        /* Slot 2: Send high uint8_t to target TrimDac. */
2458        SETVECT(3, XSD2 | XFIFO_0 | WS3);
2459        /* Slot 3: Send low uint8_t to target TrimDac. */
2460        SETVECT(4, XSD2 | XFIFO_3 | WS1);
2461        /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running. */
2462        SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS);
2463        /* Slot 5: Send NOP low  uint8_t to DAC0. */
2464
2465        /* Construct and transmit target DAC's serial packet:
2466         * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the
2467         * DAC channel's address, and D<7:0> is the DAC setpoint.  Append a
2468         * WORD value (that writes a channel 0 NOP command to a non-existent
2469         * main DAC channel) that serves to keep the clock running after the
2470         * packet has been sent to the target DAC.
2471         */
2472
2473        /*  Address the DAC channel within the trimdac device. */
2474        SendDAC(dev, ((uint32_t) chan << 8)
2475                | (uint32_t) DacData);  /*  Include DAC setpoint data. */
2476}
2477
2478/* **************  EEPROM ACCESS FUNCTIONS  ************** */
2479/*  Read uint8_t from EEPROM. */
2480
2481static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
2482{
2483        uint8_t rtnval;
2484
2485        /*  Send EEPROM target address. */
2486        if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW)
2487                         /* Byte2 = I2C command: write to I2C EEPROM  device. */
2488                         | I2C_B1(I2C_ATTRSTOP, addr)
2489                         /* Byte1 = EEPROM internal target address. */
2490                         | I2C_B0(I2C_ATTRNOP, 0))) {   /*  Byte0 = Not sent. */
2491                /*  Abort function and declare error if handshake failed. */
2492                DEBUG("I2Cread: error handshake I2Cread  a\n");
2493                return 0;
2494        }
2495        /*  Execute EEPROM read. */
2496        if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR)
2497
2498                         /*  Byte2 = I2C */
2499                         /*  command: read */
2500                         /*  from I2C EEPROM */
2501                         /*  device. */
2502                         |I2C_B1(I2C_ATTRSTOP, 0)
2503
2504                         /*  Byte1 receives */
2505                         /*  uint8_t from */
2506                         /*  EEPROM. */
2507                         |I2C_B0(I2C_ATTRNOP, 0))) {    /*  Byte0 = Not  sent. */
2508
2509                /*  Abort function and declare error if handshake failed. */
2510                DEBUG("I2Cread: error handshake I2Cread b\n");
2511                return 0;
2512        }
2513        /*  Return copy of EEPROM value. */
2514        rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16);
2515        return rtnval;
2516}
2517
2518static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
2519{
2520        /*  Write I2C command to I2C Transfer Control shadow register. */
2521        WR7146(P_I2CCTRL, val);
2522
2523        /*  Upload I2C shadow registers into working registers and wait for */
2524        /*  upload confirmation. */
2525
2526        MC_ENABLE(P_MC2, MC2_UPLD_IIC);
2527        while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;
2528
2529        /*  Wait until I2C bus transfer is finished or an error occurs. */
2530        while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ;
2531
2532        /*  Return non-zero if I2C error occured. */
2533        return RR7146(P_I2CCTRL) & I2C_ERR;
2534
2535}
2536
2537/*  Private helper function: Write setpoint to an application DAC channel. */
2538
2539static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
2540{
2541        register uint16_t signmask;
2542        register uint32_t WSImage;
2543
2544        /*  Adjust DAC data polarity and set up Polarity Control Register */
2545        /*  image. */
2546        signmask = 1 << chan;
2547        if (dacdata < 0) {
2548                dacdata = -dacdata;
2549                devpriv->Dacpol |= signmask;
2550        } else
2551                devpriv->Dacpol &= ~signmask;
2552
2553        /*  Limit DAC setpoint value to valid range. */
2554        if ((uint16_t) dacdata > 0x1FFF)
2555                dacdata = 0x1FFF;
2556
2557        /* Set up TSL2 records (aka "vectors") for DAC update.  Vectors V2
2558         * and V3 transmit the setpoint to the target DAC.  V4 and V5 send
2559         * data to a non-existent TrimDac channel just to keep the clock
2560         * running after sending data to the target DAC.  This is necessary
2561         * to eliminate the clock glitch that would otherwise occur at the
2562         * end of the target DAC's serial data stream.  When the sequence
2563         * restarts at V0 (after executing V5), the gate array automatically
2564         * disables gating for the DAC clock and all DAC chip selects.
2565         */
2566
2567        WSImage = (chan & 2) ? WS1 : WS2;
2568        /* Choose DAC chip select to be asserted. */
2569        SETVECT(2, XSD2 | XFIFO_1 | WSImage);
2570        /* Slot 2: Transmit high data byte to target DAC. */
2571        SETVECT(3, XSD2 | XFIFO_0 | WSImage);
2572        /* Slot 3: Transmit low data byte to target DAC. */
2573        SETVECT(4, XSD2 | XFIFO_3 | WS3);
2574        /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
2575        SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS);
2576        /* Slot 5: running after writing target DAC's low data byte. */
2577
2578        /*  Construct and transmit target DAC's serial packet:
2579         * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>,
2580         * and D<12:0> is the DAC setpoint.  Append a WORD value (that writes
2581         * to a  non-existent TrimDac channel) that serves to keep the clock
2582         * running after the packet has been sent to the target DAC.
2583         */
2584        SendDAC(dev, 0x0F000000
2585                /* Continue clock after target DAC data (write to non-existent trimdac). */
2586                | 0x00004000
2587                /* Address the two main dual-DAC devices (TSL's chip select enables
2588                 * target device). */
2589                | ((uint32_t) (chan & 1) << 15)
2590                /*  Address the DAC channel within the  device. */
2591                | (uint32_t) dacdata);  /*  Include DAC setpoint data. */
2592
2593}
2594
2595/* Private helper function: Transmit serial data to DAC via Audio
2596 * channel 2.  Assumes: (1) TSL2 slot records initialized, and (2)
2597 * Dacpol contains valid target image.
2598 */
2599
2600static void SendDAC(struct comedi_device *dev, uint32_t val)
2601{
2602
2603        /* START THE SERIAL CLOCK RUNNING ------------- */
2604
2605        /* Assert DAC polarity control and enable gating of DAC serial clock
2606         * and audio bit stream signals.  At this point in time we must be
2607         * assured of being in time slot 0.  If we are not in slot 0, the
2608         * serial clock and audio stream signals will be disabled; this is
2609         * because the following DEBIwrite statement (which enables signals
2610         * to be passed through the gate array) would execute before the
2611         * trailing edge of WS1/WS3 (which turns off the signals), thus
2612         * causing the signals to be inactive during the DAC write.
2613         */
2614        DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol);
2615
2616        /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */
2617
2618        /* Copy DAC setpoint value to DAC's output DMA buffer. */
2619
2620        /* WR7146( (uint32_t)devpriv->pDacWBuf, val ); */
2621        *devpriv->pDacWBuf = val;
2622
2623        /* enab the output DMA transfer.  This will cause the DMAC to copy
2624         * the DAC's data value to A2's output FIFO.  The DMA transfer will
2625         * then immediately terminate because the protection address is
2626         * reached upon transfer of the first DWORD value.
2627         */
2628        MC_ENABLE(P_MC1, MC1_A2OUT);
2629
2630        /*  While the DMA transfer is executing ... */
2631
2632        /* Reset Audio2 output FIFO's underflow flag (along with any other
2633         * FIFO underflow/overflow flags).  When set, this flag will
2634         * indicate that we have emerged from slot 0.
2635         */
2636        WR7146(P_ISR, ISR_AFOU);
2637
2638        /* Wait for the DMA transfer to finish so that there will be data
2639         * available in the FIFO when time slot 1 tries to transfer a DWORD
2640         * from the FIFO to the output buffer register.  We test for DMA
2641         * Done by polling the DMAC enable flag; this flag is automatically
2642         * cleared when the transfer has finished.
2643         */
2644        while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ;
2645
2646        /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
2647
2648        /* FIFO data is now available, so we enable execution of time slots
2649         * 1 and higher by clearing the EOS flag in slot 0.  Note that SD3
2650         * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
2651         * detection.
2652         */
2653        SETVECT(0, XSD2 | RSD3 | SIB_A2);
2654
2655        /* Wait for slot 1 to execute to ensure that the Packet will be
2656         * transmitted.  This is detected by polling the Audio2 output FIFO
2657         * underflow flag, which will be set when slot 1 execution has
2658         * finished transferring the DAC's data DWORD from the output FIFO
2659         * to the output buffer register.
2660         */
2661        while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ;
2662
2663        /* Set up to trap execution at slot 0 when the TSL sequencer cycles
2664         * back to slot 0 after executing the EOS in slot 5.  Also,
2665         * simultaneously shift out and in the 0x00 that is ALWAYS the value
2666         * stored in the last byte to be shifted out of the FIFO's DWORD
2667         * buffer register.
2668         */
2669        SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS);
2670
2671        /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
2672
2673        /* Wait for the TSL to finish executing all time slots before
2674         * exiting this function.  We must do this so that the next DAC
2675         * write doesn't start, thereby enabling clock/chip select signals:
2676         *
2677         * 1. Before the TSL sequence cycles back to slot 0, which disables
2678         *    the clock/cs signal gating and traps slot // list execution.
2679         *    we have not yet finished slot 5 then the clock/cs signals are
2680         *    still gated and we have not finished transmitting the stream.
2681         *
2682         * 2. While slots 2-5 are executing due to a late slot 0 trap.  In
2683         *    this case, the slot sequence is currently repeating, but with
2684         *    clock/cs signals disabled.  We must wait for slot 0 to trap
2685         *    execution before setting up the next DAC setpoint DMA transfer
2686         *    and enabling the clock/cs signals.  To detect the end of slot 5,
2687         *    we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
2688         *    the TSL has not yet finished executing slot 5 ...
2689         */
2690        if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) {
2691                /* The trap was set on time and we are still executing somewhere
2692                 * in slots 2-5, so we now wait for slot 0 to execute and trap
2693                 * TSL execution.  This is detected when FB_BUFFER2 MSB changes
2694                 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
2695                 * out/in on SD2 the 0x00 that is always referenced by slot 5.
2696                 */
2697                while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ;
2698        }
2699        /* Either (1) we were too late setting the slot 0 trap; the TSL
2700         * sequencer restarted slot 0 before we could set the EOS trap flag,
2701         * or (2) we were not late and execution is now trapped at slot 0.
2702         * In either case, we must now change slot 0 so that it will store
2703         * value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
2704         * In order to do this, we reprogram slot 0 so that it will shift in
2705         * SD3, which is driven only by a pull-up resistor.
2706         */
2707        SETVECT(0, RSD3 | SIB_A2 | EOS);
2708
2709        /* Wait for slot 0 to execute, at which time the TSL is setup for
2710         * the next DAC write.  This is detected when FB_BUFFER2 MSB changes
2711         * from 0x00 to 0xFF.
2712         */
2713        while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ;
2714}
2715
2716static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage)
2717{
2718        DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);        /*  enab writes to */
2719        /*  MISC2 register. */
2720        DEBIwrite(dev, LP_WRMISC2, NewImage);   /*  Write new image to MISC2. */
2721        DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE);       /*  Disable writes to MISC2. */
2722}
2723
2724/*  Initialize the DEBI interface for all transfers. */
2725
2726static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
2727{
2728        uint16_t retval;
2729
2730        /*  Set up DEBI control register value in shadow RAM. */
2731        WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
2732
2733        /*  Execute the DEBI transfer. */
2734        DEBItransfer(dev);
2735
2736        /*  Fetch target register value. */
2737        retval = (uint16_t) RR7146(P_DEBIAD);
2738
2739        /*  Return register value. */
2740        return retval;
2741}
2742
2743/*  Execute a DEBI transfer.  This must be called from within a */
2744/*  critical section. */
2745static void DEBItransfer(struct comedi_device *dev)
2746{
2747        /*  Initiate upload of shadow RAM to DEBI control register. */
2748        MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
2749
2750        /*  Wait for completion of upload from shadow RAM to DEBI control */
2751        /*  register. */
2752        while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ;
2753
2754        /*  Wait until DEBI transfer is done. */
2755        while (RR7146(P_PSR) & PSR_DEBI_S) ;
2756}
2757
2758/*  Write a value to a gate array register. */
2759static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
2760{
2761
2762        /*  Set up DEBI control register value in shadow RAM. */
2763        WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
2764        WR7146(P_DEBIAD, wdata);
2765
2766        /*  Execute the DEBI transfer. */
2767        DEBItransfer(dev);
2768}
2769
2770/* Replace the specified bits in a gate array register.  Imports: mask
2771 * specifies bits that are to be preserved, wdata is new value to be
2772 * or'd with the masked original.
2773 */
2774static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
2775                        uint16_t wdata)
2776{
2777
2778        /*  Copy target gate array register into P_DEBIAD register. */
2779        WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
2780        /* Set up DEBI control reg value in shadow RAM. */
2781        DEBItransfer(dev);      /*  Execute the DEBI Read transfer. */
2782
2783        /*  Write back the modified image. */
2784        WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
2785        /* Set up DEBI control reg value in shadow  RAM. */
2786
2787        WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask));
2788        /* Modify the register image. */
2789        DEBItransfer(dev);      /*  Execute the DEBI Write transfer. */
2790}
2791
2792static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
2793                      size_t bsize)
2794{
2795        void *vbptr;
2796        dma_addr_t vpptr;
2797
2798        DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n");
2799        if (pdma == NULL)
2800                return;
2801        /* find the matching allocation from the board struct */
2802
2803        vbptr = pdma->LogicalBase;
2804        vpptr = pdma->PhysicalBase;
2805        if (vbptr) {
2806                pci_free_consistent(devpriv->pdev, bsize, vbptr, vpptr);
2807                pdma->LogicalBase = 0;
2808                pdma->PhysicalBase = 0;
2809
2810                DEBUG("CloseDMAB(): Logical=%p, bsize=%d, Physical=0x%x\n",
2811                      vbptr, bsize, (uint32_t) vpptr);
2812        }
2813}
2814
2815/* ******  COUNTER FUNCTIONS  ******* */
2816/* All counter functions address a specific counter by means of the
2817 * "Counter" argument, which is a logical counter number.  The Counter
2818 * argument may have any of the following legal values: 0=0A, 1=1A,
2819 * 2=2A, 3=0B, 4=1B, 5=2B.
2820 */
2821
2822/* Forward declarations for functions that are common to both A and B counters: */
2823
2824/* ******  PRIVATE COUNTER FUNCTIONS ****** */
2825
2826/*  Read a counter's output latch. */
2827
2828static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k)
2829{
2830        register uint32_t value;
2831        /* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */
2832
2833        /*  Latch counts and fetch LSW of latched counts value. */
2834        value = (uint32_t) DEBIread(dev, k->MyLatchLsw);
2835
2836        /*  Fetch MSW of latched counts and combine with LSW. */
2837        value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16);
2838
2839        /*  DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n"); */
2840
2841        /*  Return latched counts. */
2842        return value;
2843}
2844
2845/*  Reset a counter's index and overflow event capture flags. */
2846
2847static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k)
2848{
2849        DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
2850                    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
2851}
2852
2853static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k)
2854{
2855        DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
2856                    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
2857}
2858
2859/*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
2860/*  for both A and B counters. */
2861
2862static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k)
2863{
2864        register uint16_t cra;
2865        register uint16_t crb;
2866        register uint16_t setup;
2867
2868        /*  Fetch CRA and CRB register images. */
2869        cra = DEBIread(dev, k->MyCRA);
2870        crb = DEBIread(dev, k->MyCRB);
2871
2872        /*  Populate the standardized counter setup bit fields.  Note: */
2873        /*  IndexSrc is restricted to ENC_X or IndxPol. */
2874        setup = ((cra & STDMSK_LOADSRC) /*  LoadSrc  = LoadSrcA. */
2875                 |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)      /*  LatchSrc = LatchSrcA. */
2876                 |((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC)  /*  IntSrc   = IntSrcA. */
2877                 |((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) /*  IndxSrc  = IndxSrcA<1>. */
2878                 |((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL)       /*  IndxPol  = IndxPolA. */
2879                 |((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB));     /*  ClkEnab  = ClkEnabA. */
2880
2881        /*  Adjust mode-dependent parameters. */
2882        if (cra & (2 << CRABIT_CLKSRC_A))       /*  If Timer mode (ClkSrcA<1> == 1): */
2883                setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)       /*    Indicate Timer mode. */
2884                          |((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) /*    Set ClkPol to indicate count direction (ClkSrcA<0>). */
2885                          |(MULT_X1 << STDBIT_CLKMULT));        /*    ClkMult must be 1x in Timer mode. */
2886
2887        else                    /*  If Counter mode (ClkSrcA<1> == 0): */
2888                setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)     /*    Indicate Counter mode. */
2889                          |((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) /*    Pass through ClkPol. */
2890                          |(((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ?       /*    Force ClkMult to 1x if not legal, else pass through. */
2891                            (MULT_X1 << STDBIT_CLKMULT) :
2892                            ((cra >> (CRABIT_CLKMULT_A -
2893                                      STDBIT_CLKMULT)) & STDMSK_CLKMULT)));
2894
2895        /*  Return adjusted counter setup. */
2896        return setup;
2897}
2898
2899static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k)
2900{
2901        register uint16_t cra;
2902        register uint16_t crb;
2903        register uint16_t setup;
2904
2905        /*  Fetch CRA and CRB register images. */
2906        cra = DEBIread(dev, k->MyCRA);
2907        crb = DEBIread(dev, k->MyCRB);
2908
2909        /*  Populate the standardized counter setup bit fields.  Note: */
2910        /*  IndexSrc is restricted to ENC_X or IndxPol. */
2911        setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC)   /*  IntSrc   = IntSrcB. */
2912                 |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)      /*  LatchSrc = LatchSrcB. */
2913                 |((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC)       /*  LoadSrc  = LoadSrcB. */
2914                 |((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL)       /*  IndxPol  = IndxPolB. */
2915                 |((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB)       /*  ClkEnab  = ClkEnabB. */
2916                 |((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC));       /*  IndxSrc  = IndxSrcB<1>. */
2917
2918        /*  Adjust mode-dependent parameters. */
2919        if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B))  /*  If Extender mode (ClkMultB == MULT_X0): */
2920                setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC)    /*    Indicate Extender mode. */
2921                          |(MULT_X1 << STDBIT_CLKMULT)  /*    Indicate multiplier is 1x. */
2922                          |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));       /*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
2923
2924        else if (cra & (2 << CRABIT_CLKSRC_B))  /*  If Timer mode (ClkSrcB<1> == 1): */
2925                setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)       /*    Indicate Timer mode. */
2926                          |(MULT_X1 << STDBIT_CLKMULT)  /*    Indicate multiplier is 1x. */
2927                          |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));       /*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
2928
2929        else                    /*  If Counter mode (ClkSrcB<1> == 0): */
2930                setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)     /*    Indicate Timer mode. */
2931                          |((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT)      /*    Clock multiplier is passed through. */
2932                          |((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL));       /*    Clock polarity is passed through. */
2933
2934        /*  Return adjusted counter setup. */
2935        return setup;
2936}
2937
2938/*
2939 * Set the operating mode for the specified counter.  The setup
2940 * parameter is treated as a COUNTER_SETUP data type.  The following
2941 * parameters are programmable (all other parms are ignored): ClkMult,
2942 * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
2943 */
2944
2945static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
2946                      uint16_t Setup, uint16_t DisableIntSrc)
2947{
2948        register uint16_t cra;
2949        register uint16_t crb;
2950        register uint16_t setup = Setup;        /*  Cache the Standard Setup. */
2951
2952        /*  Initialize CRA and CRB images. */
2953        cra = ((setup & CRAMSK_LOADSRC_A)       /*  Preload trigger is passed through. */
2954               |((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))));       /*  IndexSrc is restricted to ENC_X or IndxPol. */
2955
2956        crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A   /*  Reset any pending CounterA event captures. */
2957               | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)));    /*  Clock enable is passed through. */
2958
2959        /*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
2960        if (!DisableIntSrc)
2961                cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
2962                                                    CRABIT_INTSRC_A));
2963
2964        /*  Populate all mode-dependent attributes of CRA & CRB images. */
2965        switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
2966        case CLKSRC_EXTENDER:   /*  Extender Mode: Force to Timer mode */
2967                /*  (Extender valid only for B counters). */
2968
2969        case CLKSRC_TIMER:      /*  Timer Mode: */
2970                cra |= ((2 << CRABIT_CLKSRC_A)  /*    ClkSrcA<1> selects system clock */
2971                        |((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) /*      with count direction (ClkSrcA<0>) obtained from ClkPol. */
2972                        |(1 << CRABIT_CLKPOL_A) /*    ClkPolA behaves as always-on clock enable. */
2973                        |(MULT_X1 << CRABIT_CLKMULT_A));        /*    ClkMult must be 1x. */
2974                break;
2975
2976        default:                /*  Counter Mode: */
2977                cra |= (CLKSRC_COUNTER  /*    Select ENC_C and ENC_D as clock/direction inputs. */
2978                        | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL))        /*    Clock polarity is passed through. */
2979                        |(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?   /*    Force multiplier to x1 if not legal, otherwise pass through. */
2980                          (MULT_X1 << CRABIT_CLKMULT_A) :
2981                          ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A -
2982                                                        STDBIT_CLKMULT))));
2983        }
2984
2985        /*  Force positive index polarity if IndxSrc is software-driven only, */
2986        /*  otherwise pass it through. */
2987        if (~setup & STDMSK_INDXSRC)
2988                cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A -
2989                                                     STDBIT_INDXPOL));
2990
2991        /*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
2992        /*  enable mask to indicate the counter interrupt is disabled. */
2993        if (DisableIntSrc)
2994                devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
2995
2996        /*  While retaining CounterB and LatchSrc configurations, program the */
2997        /*  new counter operating mode. */
2998        DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra);
2999        DEBIreplace(dev, k->MyCRB,
3000                    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
3001}
3002
3003static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
3004                      uint16_t Setup, uint16_t DisableIntSrc)
3005{
3006        register uint16_t cra;
3007        register uint16_t crb;
3008        register uint16_t setup = Setup;        /*  Cache the Standard Setup. */
3009
3010        /*  Initialize CRA and CRB images. */
3011        cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC));  /*  IndexSrc field is restricted to ENC_X or IndxPol. */
3012
3013        crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B   /*  Reset event captures and disable interrupts. */
3014               | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB))      /*  Clock enable is passed through. */
3015               |((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)));     /*  Preload trigger source is passed through. */
3016
3017        /*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
3018        if (!DisableIntSrc)
3019                crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
3020                                                    CRBBIT_INTSRC_B));
3021
3022        /*  Populate all mode-dependent attributes of CRA & CRB images. */
3023        switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
3024        case CLKSRC_TIMER:      /*  Timer Mode: */
3025                cra |= ((2 << CRABIT_CLKSRC_B)  /*    ClkSrcB<1> selects system clock */
3026                        |((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));       /*      with direction (ClkSrcB<0>) obtained from ClkPol. */
3027                crb |= ((1 << CRBBIT_CLKPOL_B)  /*    ClkPolB behaves as always-on clock enable. */
3028                        |(MULT_X1 << CRBBIT_CLKMULT_B));        /*    ClkMultB must be 1x. */
3029                break;
3030
3031        case CLKSRC_EXTENDER:   /*  Extender Mode: */
3032                cra |= ((2 << CRABIT_CLKSRC_B)  /*    ClkSrcB source is OverflowA (same as "timer") */
3033                        |((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));       /*      with direction obtained from ClkPol. */
3034                crb |= ((1 << CRBBIT_CLKPOL_B)  /*    ClkPolB controls IndexB -- always set to active. */
3035                        |(MULT_X0 << CRBBIT_CLKMULT_B));        /*    ClkMultB selects OverflowA as the clock source. */
3036                break;
3037
3038        default:                /*  Counter Mode: */
3039                cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B);     /*    Select ENC_C and ENC_D as clock/direction inputs. */
3040                crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B))  /*    ClkPol is passed through. */
3041                        |(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?   /*    Force ClkMult to x1 if not legal, otherwise pass through. */
3042                          (MULT_X1 << CRBBIT_CLKMULT_B) :
3043                          ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B -
3044                                                        STDBIT_CLKMULT))));
3045        }
3046
3047        /*  Force positive index polarity if IndxSrc is software-driven only, */
3048        /*  otherwise pass it through. */
3049        if (~setup & STDMSK_INDXSRC)
3050                crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL -
3051                                                     CRBBIT_INDXPOL_B));
3052
3053        /*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
3054        /*  enable mask to indicate the counter interrupt is disabled. */
3055        if (DisableIntSrc)
3056                devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
3057
3058        /*  While retaining CounterA and LatchSrc configurations, program the */
3059        /*  new counter operating mode. */
3060        DEBIreplace(dev, k->MyCRA,
3061                    (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra);
3062        DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb);
3063}
3064
3065/*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
3066
3067static void SetEnable_A(struct comedi_device *dev, struct enc_private *k,
3068                        uint16_t enab)
3069{
3070        DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
3071        DEBIreplace(dev, k->MyCRB,
3072                    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)),
3073                    (uint16_t) (enab << CRBBIT_CLKENAB_A));
3074}
3075
3076static void SetEnable_B(struct comedi_device *dev, struct enc_private *k,
3077                        uint16_t enab)
3078{
3079        DEBIreplace(dev, k->MyCRB,
3080                    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
3081                    (uint16_t) (enab << CRBBIT_CLKENAB_B));
3082}
3083
3084static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k)
3085{
3086        return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
3087}
3088
3089static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k)
3090{
3091        return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
3092}
3093
3094/* Return/set a counter pair's latch trigger source.  0: On read
3095 * access, 1: A index latches A, 2: B index latches B, 3: A overflow
3096 * latches B.
3097 */
3098
3099static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
3100                           uint16_t value)
3101{
3102        DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
3103        DEBIreplace(dev, k->MyCRB,
3104                    (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)),
3105                    (uint16_t) (value << CRBBIT_LATCHSRC));
3106
3107        DEBUG("SetLatchSource: SetLatchSource exit \n");
3108}
3109
3110/*
3111 * static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k )
3112 * {
3113 *      return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3;
3114 * }
3115 */
3116
3117/*
3118 * Return/set the event that will trigger transfer of the preload
3119 * register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
3120 * 2=OverflowA (B counters only), 3=disabled.
3121 */
3122
3123static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k,
3124                          uint16_t Trig)
3125{
3126        DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
3127                    (uint16_t) (Trig << CRABIT_LOADSRC_A));
3128}
3129
3130static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k,
3131                          uint16_t Trig)
3132{
3133        DEBIreplace(dev, k->MyCRB,
3134                    (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
3135                    (uint16_t) (Trig << CRBBIT_LOADSRC_B));
3136}
3137
3138static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k)
3139{
3140        return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
3141}
3142
3143static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k)
3144{
3145        return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
3146}
3147
3148/* Return/set counter interrupt source and clear any captured
3149 * index/overflow events.  IntSource: 0=Disabled, 1=OverflowOnly,
3150 * 2=IndexOnly, 3=IndexAndOverflow.
3151 */
3152
3153static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
3154                        uint16_t IntSource)
3155{
3156        /*  Reset any pending counter overflow or index captures. */
3157        DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
3158                    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
3159
3160        /*  Program counter interrupt source. */
3161        DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A,
3162                    (uint16_t) (IntSource << CRABIT_INTSRC_A));
3163
3164        /*  Update MISC2 interrupt enable mask. */
3165        devpriv->CounterIntEnabs =
3166            (devpriv->CounterIntEnabs & ~k->
3167             MyEventBits[3]) | k->MyEventBits[IntSource];
3168}
3169
3170static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
3171                        uint16_t IntSource)
3172{
3173        uint16_t crb;
3174
3175        /*  Cache writeable CRB register image. */
3176        crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;
3177
3178        /*  Reset any pending counter overflow or index captures. */
3179        DEBIwrite(dev, k->MyCRB,
3180                  (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B));
3181
3182        /*  Program counter interrupt source. */
3183        DEBIwrite(dev, k->MyCRB,
3184                  (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource <<
3185                                                          CRBBIT_INTSRC_B)));
3186
3187        /*  Update MISC2 interrupt enable mask. */
3188        devpriv->CounterIntEnabs =
3189            (devpriv->CounterIntEnabs & ~k->
3190             MyEventBits[3]) | k->MyEventBits[IntSource];
3191}
3192
3193static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k)
3194{
3195        return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
3196}
3197
3198static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k)
3199{
3200        return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
3201}
3202
3203/*  Return/set the clock multiplier. */
3204
3205/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
3206/* { */
3207/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
3208/* } */
3209
3210/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k )  */
3211/* { */
3212/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
3213/* } */
3214
3215/* Return/set the clock polarity. */
3216
3217/* static void SetClkPol( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
3218/* { */
3219/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
3220/* } */
3221
3222/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k )  */
3223/* { */
3224/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
3225/* } */
3226
3227/* Return/set the clock source.  */
3228
3229/* static void SetClkSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
3230/* { */
3231/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
3232/* } */
3233
3234/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k )  */
3235/* { */
3236/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
3237/* } */
3238
3239/* Return/set the index polarity. */
3240
3241/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
3242/* { */
3243/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
3244/* } */
3245
3246/* static uint16_t GetIndexPol(struct comedi_device *dev, struct enc_private *k )  */
3247/* { */
3248/*   return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
3249/* } */
3250
3251/*  Return/set the index source. */
3252
3253/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
3254/* { */
3255/*   DEBUG("SetIndexSrc: set index src enter 3700\n"); */
3256/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
3257/* } */
3258
3259/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k )  */
3260/* { */
3261/*   return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
3262/* } */
3263
3264/*  Generate an index pulse. */
3265
3266static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k)
3267{
3268        register uint16_t cra;
3269
3270        DEBUG("PulseIndex_A: pulse index enter\n");
3271
3272        cra = DEBIread(dev, k->MyCRA);  /*  Pulse index. */
3273        DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A));
3274        DEBUG("PulseIndex_A: pulse index step1\n");
3275        DEBIwrite(dev, k->MyCRA, cra);
3276}
3277
3278static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k)
3279{
3280        register uint16_t crb;
3281
3282        crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;        /*  Pulse index. */
3283        DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B));
3284        DEBIwrite(dev, k->MyCRB, crb);
3285}
3286
3287/*  Write value into counter preload register. */
3288
3289static void Preload(struct comedi_device *dev, struct enc_private *k,
3290                    uint32_t value)
3291{
3292        DEBUG("Preload: preload enter\n");
3293        DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);   /*  Write value to preload register. */
3294        DEBUG("Preload: preload step 1\n");
3295        DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2),
3296                  (uint16_t) (value >> 16));
3297}
3298
3299static void CountersInit(struct comedi_device *dev)
3300{
3301        int chan;
3302        struct enc_private *k;
3303        uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /*  Preload upon */
3304            /*  index. */
3305            (INDXSRC_SOFT << BF_INDXSRC) |      /*  Disable hardware index. */
3306            (CLKSRC_COUNTER << BF_CLKSRC) |     /*  Operating mode is counter. */
3307            (CLKPOL_POS << BF_CLKPOL) | /*  Active high clock. */
3308            (CNTDIR_UP << BF_CLKPOL) |  /*  Count direction is up. */
3309            (CLKMULT_1X << BF_CLKMULT) |        /*  Clock multiplier is 1x. */
3310            (CLKENAB_INDEX << BF_CLKENAB);      /*  Enabled by index */
3311
3312        /*  Disable all counter interrupts and clear any captured counter events. */
3313        for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
3314                k = &encpriv[chan];
3315                k->SetMode(dev, k, Setup, TRUE);
3316                k->SetIntSrc(dev, k, 0);
3317                k->ResetCapFlags(dev, k);
3318                k->SetEnable(dev, k, CLKENAB_ALWAYS);
3319        }
3320        DEBUG("CountersInit: counters initialized \n");
3321
3322}
3323