~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/staging/comedi/drivers/s626.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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