3 Sensoray s626 Comedi driver
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8 Based on Sensoray Model 626 Linux driver Version 0.2
9 Copyright (C) 2002-2004 Sensoray Co., Inc.
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.
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.
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.
28 Driver: s626.o (s626.ko)
29 Description: Sensoray 626 driver
30 Devices: Sensoray s626
31 Authors: Gianluca Palli <gpalli@deis.unibo.it>,
32 Updated: Thu, 12 Jul 2005
35 Configuration Options:
43 s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
44 supported configuration options:
50 Every channel must be configured before reading.
54 insn.insn=INSN_CONFIG; //configuration instruction
55 insn.n=1; //number of operation (must be 1)
56 insn.data=&initialvalue; //initial value loaded into encoder
57 //during configuration
58 insn.subdev=5; //encoder subdevice
59 insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
62 comedi_do_insn(cf,&insn); //executing configuration
65 #include <linux/kernel.h>
66 #include <linux/types.h>
68 #include <linux/comedidev.h>
70 #include <linux/pci.h> /* for PCI devices */
72 #include "comedi_fc.h"
75 MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
76 MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
77 MODULE_LICENSE("GPL");
79 typedef struct s626_board_struct{
90 static const s626_board s626_boards[] = {
93 ai_chans: S626_ADC_CHANNELS,
95 ao_chans: S626_DAC_CHANNELS,
97 dio_chans: S626_DIO_CHANNELS,
98 dio_banks: S626_DIO_BANKS,
99 enc_chans: S626_ENCODER_CHANNELS,
103 #define thisboard ((const s626_board *)dev->board_ptr)
104 #define PCI_VENDOR_ID_S626 0x1131
105 #define PCI_DEVICE_ID_S626 0x7146
107 static struct pci_device_id s626_pci_table[] __devinitdata = {
108 { PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
112 MODULE_DEVICE_TABLE(pci, s626_pci_table);
114 static int s626_attach(comedi_device *dev,comedi_devconfig *it);
115 static int s626_detach(comedi_device *dev);
117 static comedi_driver driver_s626={
125 struct pci_dev *pdev;
129 uint8_t ai_cmd_running; // ai_cmd is running
130 uint8_t ai_continous; // continous aquisition
131 int ai_sample_count; // number of samples to aquire
132 unsigned int ai_sample_timer; // time between samples in
133 // units of the timer
134 int ai_convert_count; // conversion counter
135 unsigned int ai_convert_timer; // time between conversion in
136 // units of the timer
137 uint16_t CounterIntEnabs; //Counter interrupt enable
138 //mask for MISC2 register.
139 uint8_t AdcItems; //Number of items in ADC poll
141 DMABUF RPSBuf; //DMA buffer used to hold ADC
143 DMABUF ANABuf; //DMA buffer used to receive
144 //ADC data and hold DAC data.
145 uint32_t *pDacWBuf; //Pointer to logical adrs of
146 //DMA buffer used to hold DAC
148 uint16_t Dacpol; //Image of DAC polarity
150 uint8_t TrimSetpoint[12]; //Images of TrimDAC setpoints.
152 uint16_t ChargeEnabled; //Image of MISC2 Battery
153 //Charge Enabled (0 or
154 //WRMISC2_CHARGE_ENABLE).
155 uint16_t WDInterval; //Image of MISC2 watchdog
156 //interval control bits.
157 uint32_t I2CAdrs; //I2C device address for
158 //onboard EEPROM (board rev
161 lsampl_t ao_readback[S626_DAC_CHANNELS];
176 static dio_private dio_private_A={
179 RDEdgSel: LP_RDEDGSELA,
180 WREdgSel: LP_WREDGSELA,
181 RDCapSel: LP_RDCAPSELA,
182 WRCapSel: LP_WRCAPSELA,
183 RDCapFlg: LP_RDCAPFLGA,
184 RDIntSel: LP_RDINTSELA,
185 WRIntSel: LP_WRINTSELA,
188 static dio_private dio_private_B={
191 RDEdgSel: LP_RDEDGSELB,
192 WREdgSel: LP_WREDGSELB,
193 RDCapSel: LP_RDCAPSELB,
194 WRCapSel: LP_WRCAPSELB,
195 RDCapFlg: LP_RDCAPFLGB,
196 RDIntSel: LP_RDINTSELB,
197 WRIntSel: LP_WRINTSELB,
200 static dio_private dio_private_C={
203 RDEdgSel: LP_RDEDGSELC,
204 WREdgSel: LP_WREDGSELC,
205 RDCapSel: LP_RDCAPSELC,
206 WRCapSel: LP_WRCAPSELC,
207 RDCapFlg: LP_RDCAPFLGC,
208 RDIntSel: LP_RDINTSELC,
209 WRIntSel: LP_WRINTSELC,
212 /* to group dio devices (48 bits mask and data are not allowed ???)
213 static dio_private *dio_private_word[]={
220 #define devpriv ((s626_private *)dev->private)
221 #define diopriv ((dio_private *)s->private)
223 COMEDI_INITCLEANUP_NOMODULE(driver_s626);
226 static int s626_ai_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
227 /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */
228 static int s626_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
229 static int s626_ai_cmd(comedi_device *dev,comedi_subdevice *s);
230 static int s626_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd);
231 static int s626_ai_cancel(comedi_device *dev,comedi_subdevice *s);
232 static int s626_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
233 static int s626_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
234 static int s626_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
235 static int s626_dio_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
236 static int s626_dio_set_irq(comedi_device *dev, unsigned int chan);
237 static int s626_dio_reset_irq(comedi_device *dev, unsigned int gruop, unsigned int mask);
238 static int s626_dio_clear_irq(comedi_device *dev);
239 static int s626_enc_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
240 static int s626_enc_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
241 static int s626_enc_insn_write(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
242 static int s626_ns_to_timer(int *nanosec,int round_mode);
243 static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
244 static int s626_ai_inttrig(comedi_device *dev,comedi_subdevice *s,
245 unsigned int trignum);
246 static irqreturn_t s626_irq_handler(int irq,void *d PT_REGS_ARG);
247 static lsampl_t s626_ai_reg_to_uint(int data);
248 /* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */
253 static void s626_dio_init(comedi_device *dev);
254 static void ResetADC(comedi_device *dev,uint8_t *ppl );
255 static void LoadTrimDACs(comedi_device *dev);
256 static void WriteTrimDAC(comedi_device *dev,uint8_t LogicalChan, uint8_t DacData );
257 static uint8_t I2Cread(comedi_device *dev, uint8_t addr );
258 static uint32_t I2Chandshake(comedi_device *dev,uint32_t val );
259 static void SetDAC(comedi_device *dev,uint16_t chan, short dacdata );
260 static void SendDAC(comedi_device *dev,uint32_t val );
261 static void WriteMISC2(comedi_device *dev,uint16_t NewImage );
262 static void DEBItransfer(comedi_device *dev);
263 static uint16_t DEBIread(comedi_device *dev,uint16_t addr );
264 static void DEBIwrite(comedi_device *dev,uint16_t addr, uint16_t wdata );
265 static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask, uint16_t wdata );
266 static void CloseDMAB (comedi_device *dev,DMABUF * pdma,size_t bsize);
268 // COUNTER OBJECT ------------------------------------------------
269 typedef struct enc_private_struct {
270 // Pointers to functions that differ for A and B counters:
271 uint16_t (*GetEnable)(comedi_device *dev,struct enc_private_struct *); //Return clock enable.
272 uint16_t (*GetIntSrc)(comedi_device *dev,struct enc_private_struct *); //Return interrupt source.
273 uint16_t (*GetLoadTrig)(comedi_device *dev,struct enc_private_struct *); //Return preload trigger source.
274 uint16_t (*GetMode)(comedi_device *dev,struct enc_private_struct *); //Return standardized operating mode.
275 void (*PulseIndex)(comedi_device *dev,struct enc_private_struct *); //Generate soft index strobe.
276 void (*SetEnable)(comedi_device *dev,struct enc_private_struct *,uint16_t enab); //Program clock enable.
277 void (*SetIntSrc)(comedi_device *dev,struct enc_private_struct *,uint16_t IntSource); //Program interrupt source.
278 void (*SetLoadTrig)(comedi_device *dev,struct enc_private_struct *,uint16_t Trig); //Program preload trigger source.
279 void (*SetMode)(comedi_device *dev,struct enc_private_struct *,uint16_t Setup,uint16_t DisableIntSrc); //Program standardized operating mode.
280 void (*ResetCapFlags)(comedi_device *dev,struct enc_private_struct *); //Reset event capture flags.
282 uint16_t MyCRA; // Address of CRA register.
283 uint16_t MyCRB; // Address of CRB register.
284 uint16_t MyLatchLsw; // Address of Latch least-significant-word
286 uint16_t MyEventBits[4]; // Bit translations for IntSrc -->RDMISC2.
287 } enc_private; //counter object
289 #define encpriv ((enc_private *)(dev->subdevices+5)->private)
292 static void s626_timer_load(comedi_device *dev, enc_private *k, int tick);
293 static uint32_t ReadLatch(comedi_device *dev, enc_private *k );
294 static void ResetCapFlags_A( comedi_device *dev, enc_private *k );
295 static void ResetCapFlags_B(comedi_device *dev, enc_private *k);
296 static uint16_t GetMode_A( comedi_device *dev, enc_private *k );
297 static uint16_t GetMode_B(comedi_device *dev, enc_private *k);
298 static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc );
299 static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc );
300 static void SetEnable_A( comedi_device *dev,enc_private *k, uint16_t enab );
301 static void SetEnable_B( comedi_device *dev,enc_private *k, uint16_t enab );
302 static uint16_t GetEnable_A(comedi_device *dev, enc_private *k );
303 static uint16_t GetEnable_B( comedi_device *dev,enc_private *k );
304 static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value );
305 /* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */
306 static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig );
307 static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig );
308 static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k );
309 static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k );
310 static void SetIntSrc_B(comedi_device *dev, enc_private *k, uint16_t IntSource );
311 static void SetIntSrc_A(comedi_device *dev, enc_private *k, uint16_t IntSource );
312 static uint16_t GetIntSrc_A(comedi_device *dev, enc_private *k );
313 static uint16_t GetIntSrc_B(comedi_device *dev, enc_private *k );
314 /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */
315 /* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */
316 /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */
317 /* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) ; */
318 /* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */
319 /* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ); */
320 /* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */
321 /* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k ); */
322 static void PulseIndex_A(comedi_device *dev, enc_private *k );
323 static void PulseIndex_B( comedi_device *dev,enc_private *k );
324 static void Preload( comedi_device *dev,enc_private *k, uint32_t value );
325 static void CountersInit(comedi_device *dev);
326 //end internal routines
328 /////////////////////////////////////////////////////////////////////////
329 // Counter objects constructor.
331 // Counter overflow/index event flag masks for RDMISC2.
332 #define INDXMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 + 4 ) ) )
333 #define OVERMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) )
334 #define EVBITS(C) { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
336 // Translation table to map IntSrc into equivalent RDMISC2 event flag
338 //static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) };
341 static enc_private enc_private_data[]={
343 GetEnable: GetEnable_A,
344 GetIntSrc: GetIntSrc_A,
345 GetLoadTrig: GetLoadTrig_A,
347 PulseIndex: PulseIndex_A,
348 SetEnable: SetEnable_A,
349 SetIntSrc: SetIntSrc_A,
350 SetLoadTrig: SetLoadTrig_A,
352 ResetCapFlags: ResetCapFlags_A,
355 MyLatchLsw: LP_CNTR0ALSW,
356 MyEventBits: EVBITS(0),
359 GetEnable: GetEnable_A,
360 GetIntSrc: GetIntSrc_A,
361 GetLoadTrig: GetLoadTrig_A,
363 PulseIndex: PulseIndex_A,
364 SetEnable: SetEnable_A,
365 SetIntSrc: SetIntSrc_A,
366 SetLoadTrig: SetLoadTrig_A,
368 ResetCapFlags: ResetCapFlags_A,
371 MyLatchLsw: LP_CNTR1ALSW,
372 MyEventBits: EVBITS(1),
375 GetEnable: GetEnable_A,
376 GetIntSrc: GetIntSrc_A,
377 GetLoadTrig: GetLoadTrig_A,
379 PulseIndex: PulseIndex_A,
380 SetEnable: SetEnable_A,
381 SetIntSrc: SetIntSrc_A,
382 SetLoadTrig: SetLoadTrig_A,
384 ResetCapFlags: ResetCapFlags_A,
387 MyLatchLsw: LP_CNTR2ALSW,
388 MyEventBits: EVBITS(2),
391 GetEnable: GetEnable_B,
392 GetIntSrc: GetIntSrc_B,
393 GetLoadTrig: GetLoadTrig_B,
395 PulseIndex: PulseIndex_B,
396 SetEnable: SetEnable_B,
397 SetIntSrc: SetIntSrc_B,
398 SetLoadTrig: SetLoadTrig_B,
400 ResetCapFlags: ResetCapFlags_B,
403 MyLatchLsw: LP_CNTR0BLSW,
404 MyEventBits: EVBITS(3),
407 GetEnable: GetEnable_B,
408 GetIntSrc: GetIntSrc_B,
409 GetLoadTrig: GetLoadTrig_B,
411 PulseIndex: PulseIndex_B,
412 SetEnable: SetEnable_B,
413 SetIntSrc: SetIntSrc_B,
414 SetLoadTrig: SetLoadTrig_B,
416 ResetCapFlags: ResetCapFlags_B,
419 MyLatchLsw: LP_CNTR1BLSW,
420 MyEventBits: EVBITS(4),
423 GetEnable: GetEnable_B,
424 GetIntSrc: GetIntSrc_B,
425 GetLoadTrig: GetLoadTrig_B,
427 PulseIndex: PulseIndex_B,
428 SetEnable: SetEnable_B,
429 SetIntSrc: SetIntSrc_B,
430 SetLoadTrig: SetLoadTrig_B,
432 ResetCapFlags: ResetCapFlags_B,
435 MyLatchLsw: LP_CNTR2BLSW,
436 MyEventBits: EVBITS(5),
440 // enab/disable a function or test status bit(s) that are accessed
441 // through Main Control Registers 1 or 2.
442 #define MC_ENABLE( REGADRS, CTRLWORD ) writel( ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) )
444 #define MC_DISABLE( REGADRS, CTRLWORD ) writel( (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) )
446 #define MC_TEST( REGADRS, CTRLWORD ) ( ( readl(devpriv->base_addr+( REGADRS )) & CTRLWORD ) != 0 )
448 /* #define WR7146(REGARDS,CTRLWORD)
449 writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
450 #define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,devpriv->base_addr+(REGARDS))
452 /* #define RR7146(REGARDS)
453 readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
454 #define RR7146(REGARDS) readl(devpriv->base_addr+(REGARDS))
456 #define BUGFIX_STREG(REGADRS) ( REGADRS - 4 )
458 // Write a time slot control record to TSL2.
459 #define VECTPORT( VECTNUM ) (P_TSL2 + ( (VECTNUM) << 2 ))
460 #define SETVECT( VECTNUM, VECTVAL ) WR7146(VECTPORT( VECTNUM ), (VECTVAL))
462 // Code macros used for constructing I2C command bytes.
463 #define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
464 #define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
465 #define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) )
467 static const comedi_lrange s626_range_table={ 2,{
472 static int s626_attach(comedi_device *dev,comedi_devconfig *it)
474 /* uint8_t PollList; */
475 /* uint16_t AdcData; */
476 /* uint16_t StartVal; */
477 /* uint16_t index; */
478 /* unsigned int data[16]; */
482 resource_size_t resourceStart;
485 struct pci_dev *pdev;
487 if(alloc_private(dev,sizeof(s626_private))<0)
490 pdev=pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, NULL);
491 devpriv->pdev = pdev;
494 printk("s626_attach: Board not present!!!");
498 if((result = pci_enable_device(pdev))<0){
499 printk("s626_attach: pci_enable_device fails\n");
503 if((result = pci_request_regions(pdev, "s626"))<0){
504 printk("s626_attach: pci_request_regions fails\n");
507 devpriv->got_regions = 1;
509 resourceStart=pci_resource_start(devpriv->pdev,0);
511 devpriv->base_addr=ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
512 if (devpriv->base_addr==NULL) {
513 printk("s626_attach: IOREMAP failed\n");
517 if (devpriv->base_addr){
518 //disable master interrupt
519 writel(0,devpriv->base_addr+P_IER);
522 writel(MC1_SOFT_RESET,devpriv->base_addr+P_MC1);
525 DEBUG("s626_attach: DMA ALLOCATION\n");
527 //adc buffer allocation
528 devpriv->allocatedBuf=0;
530 if((devpriv->ANABuf.LogicalBase = pci_alloc_consistent (devpriv->pdev, DMABUF_SIZE, &appdma))==NULL){
531 printk("s626_attach: DMA Memory mapping error\n");
535 devpriv->ANABuf.PhysicalBase=(void*)appdma;
537 DEBUG("s626_attach: AllocDMAB ADC Logical=0x%x, bsize=%d, Physical=0x%x\n",
538 (uint32_t) devpriv->ANABuf.LogicalBase, DMABUF_SIZE, (uint32_t)devpriv->ANABuf.PhysicalBase);
540 devpriv->allocatedBuf++;
542 if((devpriv->RPSBuf.LogicalBase = pci_alloc_consistent (devpriv->pdev, DMABUF_SIZE, &appdma)) ==NULL){
543 printk("s626_attach: DMA Memory mapping error\n");
547 devpriv->RPSBuf.PhysicalBase=(void*)appdma;
549 DEBUG("s626_attach: AllocDMAB RPS Logical=0x%x, bsize=%d, Physical=0x%x\n",
550 (uint32_t) devpriv->RPSBuf.LogicalBase, DMABUF_SIZE, (uint32_t)devpriv->RPSBuf.PhysicalBase);
552 devpriv->allocatedBuf++;
556 dev->board_ptr = s626_boards;
557 dev->board_name = thisboard->name;
559 if(alloc_subdevices(dev, 6)<0)
562 dev->iobase = (unsigned long)devpriv->base_addr;
563 dev->irq = devpriv->pdev->irq;
565 //set up interrupt handler
567 printk(" unknown irq (bad)\n");
569 if( (ret=comedi_request_irq(dev->irq,s626_irq_handler,IRQF_SHARED,"s626",dev))<0 ){
570 printk(" irq not available\n");
575 DEBUG("s626_attach: -- it opts %d -- \n",it->options[0]);
578 /* analog input subdevice */
579 dev->read_subdev = s;
580 /* we support single-ended (ground) and differential */
581 s->type=COMEDI_SUBD_AI;
582 s->subdev_flags = SDF_READABLE | SDF_DIFF |SDF_CMD_READ;
583 s->n_chan=thisboard->ai_chans;
584 s->maxdata=(0xffff >> 2);
585 s->range_table=&s626_range_table;
586 s->len_chanlist=thisboard->ai_chans; /* This is the maximum chanlist
587 length that the board can
589 s->insn_config = s626_ai_insn_config;
590 s->insn_read = s626_ai_insn_read;
591 s->do_cmd = s626_ai_cmd;
592 s->do_cmdtest = s626_ai_cmdtest;
593 s->cancel = s626_ai_cancel;
596 /* analog output subdevice */
597 s->type=COMEDI_SUBD_AO;
598 s->subdev_flags=SDF_WRITABLE|SDF_READABLE;
599 s->n_chan=thisboard->ao_chans;
601 s->range_table=&range_bipolar10;
602 s->insn_write = s626_ao_winsn;
603 s->insn_read = s626_ao_rinsn;
606 /* digital I/O subdevice */
607 s->type=COMEDI_SUBD_DIO;
608 s->subdev_flags=SDF_WRITABLE|SDF_READABLE;
609 s->n_chan=S626_DIO_CHANNELS;
612 s->private=&dio_private_A;
613 s->range_table=&range_digital;
614 s->insn_config=s626_dio_insn_config;
615 s->insn_bits = s626_dio_insn_bits;
618 /* digital I/O subdevice */
619 s->type=COMEDI_SUBD_DIO;
620 s->subdev_flags=SDF_WRITABLE|SDF_READABLE;
624 s->private=&dio_private_B;
625 s->range_table=&range_digital;
626 s->insn_config=s626_dio_insn_config;
627 s->insn_bits = s626_dio_insn_bits;
630 /* digital I/O subdevice */
631 s->type=COMEDI_SUBD_DIO;
632 s->subdev_flags=SDF_WRITABLE|SDF_READABLE;
636 s->private=&dio_private_C;
637 s->range_table=&range_digital;
638 s->insn_config=s626_dio_insn_config;
639 s->insn_bits = s626_dio_insn_bits;
642 /* encoder (counter) subdevice */
643 s->type = COMEDI_SUBD_COUNTER;
644 s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
645 s->n_chan = thisboard->enc_chans;
646 s->private=enc_private_data;
647 s->insn_config = s626_enc_insn_config;
648 s->insn_read = s626_enc_insn_read;
649 s->insn_write = s626_enc_insn_write;
650 s->maxdata = 0xffffff;
651 s->range_table = &range_unknown;
654 devpriv->ai_cmd_running=0;
656 if (devpriv->base_addr && (devpriv->allocatedBuf==2)){
660 // enab DEBI and audio pins, enable I2C interface.
661 MC_ENABLE( P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C );
662 // Configure DEBI operating mode.
663 WR7146( P_DEBICFG, DEBI_CFG_SLAVE16 // Local bus is 16
665 | ( DEBI_TOUT << DEBI_CFG_TOUT_BIT )// Declare DEBI
668 | DEBI_SWAP // Set up byte lane
670 | DEBI_CFG_INTEL ); // Intel-compatible
673 DEBUG("s626_attach: %d debi init -- %d\n", DEBI_CFG_SLAVE16| ( DEBI_TOUT << DEBI_CFG_TOUT_BIT )| DEBI_SWAP| DEBI_CFG_INTEL, DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ| DEBI_CFG_16Q);
675 //DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ
676 //| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end
678 // Paging is disabled.
679 WR7146( P_DEBIPAGE, DEBI_PAGE_DISABLE ); // Disable MMU paging.
681 // Init GPIO so that ADC Start* is negated.
682 WR7146( P_GPIO, GPIO_BASE | GPIO1_HI );
684 //IsBoardRevA is a boolean that indicates whether the board is
687 // VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
688 // EEPROM ADDRESS SELECTION. Initialize the I2C interface, which
689 // is used to access the onboard serial EEPROM. The EEPROM's I2C
690 // DeviceAddress is hardwired to a value that is dependent on the
691 // 626 board revision. On all board revisions, the EEPROM stores
692 // TrimDAC calibration constants for analog I/O. On RevB and
693 // higher boards, the DeviceAddress is hardwired to 0 to enable
694 // the EEPROM to also store the PCI SubVendorID and SubDeviceID;
695 // this is the address at which the SAA7146 expects a
696 // configuration EEPROM to reside. On RevA boards, the EEPROM
697 // device address, which is hardwired to 4, prevents the SAA7146
698 // from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
699 // default values, instead.
701 // devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM
703 // and DeviceAddress<<1.
705 devpriv->I2CAdrs=0xA0; // I2C device address for onboard
708 // Issue an I2C ABORT command to halt any I2C operation in
709 //progress and reset BUSY flag.
710 WR7146( P_I2CSTAT, I2C_CLKSEL | I2C_ABORT );// Write I2C control:
713 MC_ENABLE( P_MC2, MC2_UPLD_IIC ); // Invoke command
715 while ( ( RR7146(P_MC2) & MC2_UPLD_IIC ) == 0 );// and wait for
719 // Per SAA7146 data sheet, write to STATUS reg twice to reset all
721 for ( i = 0; i < 2; i++ )
723 WR7146( P_I2CSTAT, I2C_CLKSEL ); // Write I2C control: reset
725 MC_ENABLE( P_MC2, MC2_UPLD_IIC ); // Invoke command upload
726 while ( !MC_TEST( P_MC2, MC2_UPLD_IIC ) ); // and wait for
731 // Init audio interface functional attributes: set DAC/ADC serial
732 // clock rates, invert DAC serial clock so that DAC data setup
733 // times are satisfied, enable DAC serial clock out.
734 WR7146( P_ACON2, ACON2_INIT );
736 // Set up TSL1 slot list, which is used to control the
737 // accumulation of ADC data: RSD1 = shift data in on SD1. SIB_A1
738 // = store data uint8_t at next available location in FB BUFFER1
740 WR7146( P_TSL1 , RSD1 | SIB_A1 ); // Fetch ADC high data
742 WR7146( P_TSL1 + 4, RSD1 | SIB_A1 | EOS ); // Fetch ADC low data
746 // enab TSL1 slot list so that it executes all the time.
747 WR7146( P_ACON1, ACON1_ADCSTART );
749 // Initialize RPS registers used for ADC.
751 //Physical start of RPS program.
752 WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
754 WR7146( P_RPSPAGE1, 0 ); // RPS program performs no
755 // explicit mem writes.
756 WR7146( P_RPS1_TOUT, 0 ); // Disable RPS timeouts.
758 // SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface to a
759 // known state by invoking ADCs until FB BUFFER 1 register shows
760 // that it is correctly receiving ADC data. This is necessary
761 // because the SAA7146 ADC interface does not start up in a
762 // defined state after a PCI reset.
764 /* PollList = EOPL; // Create a simple polling */
765 /* // list for analog input */
767 /* ResetADC( dev, &PollList ); */
769 /* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
770 /* //Get initial ADC */
773 /* StartVal = data[0]; */
775 /* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
776 /* // Invoke ADCs until the new ADC value differs from the initial */
777 /* // value or a timeout occurs. The timeout protects against the */
778 /* // possibility that the driver is restarting and the ADC data is a */
779 /* // fixed value resulting from the applied ADC analog input being */
780 /* // unusually quiet or at the rail. */
782 /* for ( index = 0; index < 500; index++ ) */
784 /* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
785 /* AdcData = data[0]; //ReadADC( &AdcData ); */
786 /* if ( AdcData != StartVal ) */
792 // init the DAC interface
794 // Init Audio2's output DMAC attributes: burst length = 1 DWORD,
795 // threshold = 1 DWORD.
796 WR7146( P_PCI_BT_A, 0 );
798 // Init Audio2's output DMA physical addresses. The protection
799 // address is set to 1 DWORD past the base address so that a
800 // single DWORD will be transferred each time a DMA transfer is
803 pPhysBuf = (uint32_t *)devpriv->ANABuf.PhysicalBase + DAC_WDMABUF_OS;
805 WR7146( P_BASEA2_OUT, (uint32_t) pPhysBuf ); // Buffer base adrs.
806 WR7146( P_PROTA2_OUT, (uint32_t) (pPhysBuf + 1) ); // Protection address.
808 // Cache Audio2's output DMA buffer logical address. This is
809 // where DAC data is buffered for A2 output DMA transfers.
810 devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS;
812 // Audio2's output channels does not use paging. The protection
813 // violation handling bit is set so that the DMAC will
814 // automatically halt and its PCI address pointer will be reset
815 // when the protection address is reached.
816 WR7146( P_PAGEA2_OUT, 8 );
818 // Initialize time slot list 2 (TSL2), which is used to control
819 // the clock generation for and serialization of data to be sent
820 // to the DAC devices. Slot 0 is a NOP that is used to trap TSL
821 // execution; this permits other slots to be safely modified
822 // without first turning off the TSL sequencer (which is
823 // apparently impossible to do). Also, SD3 (which is driven by a
824 // pull-up resistor) is shifted in and stored to the MSB of
825 // FB_BUFFER2 to be used as evidence that the slot sequence has
826 // not yet finished executing.
827 SETVECT( 0, XSD2 | RSD3 | SIB_A2 | EOS ); // Slot 0: Trap TSL
828 // execution, shift 0xFF
831 // Initialize slot 1, which is constant. Slot 1 causes a DWORD to
832 // be transferred from audio channel 2's output FIFO to the FIFO's
833 // output buffer so that it can be serialized and sent to the DAC
834 // during subsequent slots. All remaining slots are dynamically
835 // populated as required by the target DAC device.
836 SETVECT( 1, LF_A2 ); // Slot 1: Fetch DWORD from Audio2's
839 // Start DAC's audio interface (TSL2) running.
840 WR7146( P_ACON1, ACON1_DACSTART );
842 ////////////////////////////////////////////////////////
844 // end init DAC interface
846 // Init Trim DACs to calibrated values. Do it twice because the
847 // SAA7146 audio channel does not always reset properly and
848 // sometimes causes the first few TrimDAC writes to malfunction.
851 LoadTrimDACs( dev); // Insurance.
853 //////////////////////////////////////////////////////////////////
854 // Manually init all gate array hardware in case this is a soft
855 // reset (we have no way of determining whether this is a warm or
856 // cold start). This is necessary because the gate array will
857 // reset only in response to a PCI hard reset; there is no soft
860 // Init all DAC outputs to 0V and init all DAC setpoint and
862 for ( chan = 0; chan < S626_DAC_CHANNELS; chan++)
863 SetDAC(dev,chan, 0 );
865 // Init image of WRMISC2 Battery Charger Enabled control bit.
866 // This image is used when the state of the charger control bit,
867 // which has no direct hardware readback mechanism, is queried.
868 devpriv->ChargeEnabled = 0;
870 // Init image of watchdog timer interval in WRMISC2. This image
871 // maintains the value of the control bits of MISC2 are
872 // continuously reset to zero as long as the WD timer is disabled.
873 devpriv->WDInterval = 0;
875 // Init Counter Interrupt enab mask for RDMISC2. This mask is
876 // applied against MISC2 when testing to determine which timer
877 // events are requesting interrupt service.
878 devpriv->CounterIntEnabs = 0;
883 // Without modifying the state of the Battery Backup enab, disable
884 // the watchdog timer, set DIO channels 0-5 to operate in the
885 // standard DIO (vs. counter overflow) mode, disable the battery
886 // charger, and reset the watchdog interval selector to zero.
887 WriteMISC2(dev, (uint16_t)( DEBIread( dev,LP_RDMISC2 ) & MISC2_BATT_ENABLE ) );
889 // Initialize the digital I/O subsystem.
892 //enable interrupt test
893 // writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
896 DEBUG("s626_attach: comedi%d s626 attached %04x\n",dev->minor,(uint32_t)devpriv->base_addr);
901 static lsampl_t s626_ai_reg_to_uint(int data){
904 tempdata=(data >> 18);
913 /* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data){ */
917 static irqreturn_t s626_irq_handler(int irq,void *d PT_REGS_ARG)
919 comedi_device *dev=d;
925 uint32_t irqtype,irqstatus,datacount;
926 int kernel_transfer=0;
928 sampl_t *databuf=NULL;
933 DEBUG("s626_irq_handler: interrupt request recieved!!!\n");
935 if(dev->attached == 0) return IRQ_NONE;
936 // lock to avoid race with comedi_poll
937 comedi_spin_lock_irqsave(&dev->spinlock, flags);
939 //save interrupt enable register state
940 irqstatus=readl(devpriv->base_addr+P_IER);
942 //read interrupt type
943 irqtype=readl(devpriv->base_addr+P_ISR);
945 //disable master interrupt
946 writel(0,devpriv->base_addr+P_IER);
949 writel(irqtype,devpriv->base_addr+P_ISR);
952 DEBUG("s626_irq_handler: interrupt type %d\n",irqtype);
955 case IRQ_RPS1: // end_of_scan occurs
957 DEBUG("s626_irq_handler: RPS1 irq detected\n");
959 // manage ai subdevice
961 cmd=&(s->async->cmd);
963 // verify if data buffer exists
964 if(s->async->cmd.data!=NULL){
965 DEBUG("s626_irq_handler: Kernel transfer asserted\n");
967 databuf=s->async->cmd.data;
968 datacount=s->async->cmd.data_len;
971 // Init ptr to DMA buffer that holds new ADC data. We skip the
972 // first uint16_t in the buffer because it contains junk data from
973 // the final ADC of the previous poll list scan.
974 readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1;
976 // get the data and hand it over to comedi
977 for(i=0;i<(s->async->cmd.chanlist_len);i++) {
978 // Convert ADC data to 16-bit integer values and copy to application
980 tempdata=s626_ai_reg_to_uint((int)*readaddr);
984 //send buffer overflow event
985 DEBUG("s626_irq_handler: in kernel transfer...\n");
987 s->async->events|=COMEDI_CB_OVERFLOW;
995 //put data into read buffer
996 // comedi_buf_put(s->async, tempdata);
997 if(cfc_write_to_buffer(s,tempdata)==0) printk("s626_irq_handler: cfc_write_to_buffer error!\n");
999 DEBUG("s626_irq_handler: ai channel %d acquired: %d\n",i,tempdata);
1002 //end of scan occurs
1003 s->async->events|=COMEDI_CB_EOS;
1005 if(!(devpriv->ai_continous)) devpriv->ai_sample_count--;
1006 if(devpriv->ai_sample_count<=0){
1007 devpriv->ai_cmd_running=0;
1009 // Stop RPS program.
1010 MC_DISABLE( P_MC1, MC1_ERPS1 );
1012 //send end of acquisition
1013 s->async->events|=COMEDI_CB_EOA;
1015 //disable master interrupt
1019 if(devpriv->ai_cmd_running && cmd->scan_begin_src==TRIG_EXT){
1020 DEBUG("s626_irq_handler: enable interrupt on dio channel %d\n",cmd->scan_begin_arg);
1022 s626_dio_set_irq(dev,cmd->scan_begin_arg);
1024 DEBUG("s626_irq_handler: External trigger is set!!!\n");
1027 // tell comedi that data is there
1028 DEBUG("s626_irq_handler: events %d\n",s->async->events);
1029 comedi_event(dev, s, s->async->events);
1031 case IRQ_GPIO3: //check dio and conter interrupt
1033 DEBUG("s626_irq_handler: GPIO3 irq detected\n");
1035 // manage ai subdevice
1037 cmd=&(s->async->cmd);
1039 //s626_dio_clear_irq(dev);
1041 for(group=0;group<S626_DIO_BANKS;group++){
1043 //read interrupt type
1044 irqbit=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDCapFlg);
1046 //check if interrupt is generated from dio channels
1048 s626_dio_reset_irq(dev,group,irqbit);
1049 DEBUG("s626_irq_handler: check interrupt on dio group %d %d\n",group,i);
1050 if(devpriv->ai_cmd_running){
1051 //check if interrupt is an ai acquisition start trigger
1052 if((irqbit>>(cmd->start_arg-(16*group)))==1 && cmd->start_src==TRIG_EXT){
1053 DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->start_arg);
1055 // Start executing the RPS program.
1056 MC_ENABLE( P_MC1, MC1_ERPS1 );
1058 DEBUG("s626_irq_handler: aquisition start triggered!!!\n");
1060 if(cmd->scan_begin_src==TRIG_EXT){
1061 DEBUG("s626_ai_cmd: enable interrupt on dio channel %d\n",cmd->scan_begin_arg);
1063 s626_dio_set_irq(dev,cmd->scan_begin_arg);
1065 DEBUG("s626_irq_handler: External scan trigger is set!!!\n");
1068 if((irqbit>>(cmd->scan_begin_arg-(16*group)))==1 && cmd->scan_begin_src==TRIG_EXT){
1069 DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->scan_begin_arg);
1071 // Trigger ADC scan loop start by setting RPS Signal 0.
1072 MC_ENABLE( P_MC2, MC2_ADC_RPS );
1074 DEBUG("s626_irq_handler: scan triggered!!! %d\n",devpriv->ai_sample_count);
1075 if(cmd->convert_src==TRIG_EXT){
1077 DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
1079 devpriv->ai_convert_count=cmd->chanlist_len;
1081 s626_dio_set_irq(dev,cmd->convert_arg);
1083 DEBUG("s626_irq_handler: External convert trigger is set!!!\n");
1086 if(cmd->convert_src==TRIG_TIMER){
1088 devpriv->ai_convert_count=cmd->chanlist_len;
1089 k->SetEnable(dev,k,CLKENAB_ALWAYS);
1092 if((irqbit>>(cmd->convert_arg-(16*group)))==1 && cmd->convert_src==TRIG_EXT){
1093 DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->convert_arg);
1095 // Trigger ADC scan loop start by setting RPS Signal 0.
1096 MC_ENABLE( P_MC2, MC2_ADC_RPS );
1098 DEBUG("s626_irq_handler: adc convert triggered!!!\n");
1100 devpriv->ai_convert_count--;
1102 if(devpriv->ai_convert_count>0){
1104 DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
1106 s626_dio_set_irq(dev,cmd->convert_arg);
1108 DEBUG("s626_irq_handler: External trigger is set!!!\n");
1116 //read interrupt type
1117 irqbit=DEBIread(dev,LP_RDMISC2);
1119 //check interrupt on counters
1120 DEBUG("s626_irq_handler: check counters interrupt %d\n",irqbit);
1122 if(irqbit&IRQ_COINT1A){
1123 DEBUG("s626_irq_handler: interrupt on counter 1A overflow\n");
1126 //clear interrupt capture flag
1127 k->ResetCapFlags(dev,k);
1129 if(irqbit&IRQ_COINT2A){
1130 DEBUG("s626_irq_handler: interrupt on counter 2A overflow\n");
1133 //clear interrupt capture flag
1134 k->ResetCapFlags(dev,k);
1136 if(irqbit&IRQ_COINT3A){
1137 DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n");
1140 //clear interrupt capture flag
1141 k->ResetCapFlags(dev,k);
1143 if(irqbit&IRQ_COINT1B){
1144 DEBUG("s626_irq_handler: interrupt on counter 1B overflow\n");
1147 //clear interrupt capture flag
1148 k->ResetCapFlags(dev,k);
1150 if(irqbit&IRQ_COINT2B){
1151 DEBUG("s626_irq_handler: interrupt on counter 2B overflow\n");
1154 //clear interrupt capture flag
1155 k->ResetCapFlags(dev,k);
1157 if(devpriv->ai_convert_count>0){
1158 devpriv->ai_convert_count--;
1159 if(devpriv->ai_convert_count==0) k->SetEnable(dev,k,CLKENAB_INDEX);
1161 if(cmd->convert_src==TRIG_TIMER){
1162 DEBUG("s626_irq_handler: conver timer trigger!!! %d\n",devpriv->ai_convert_count);
1164 // Trigger ADC scan loop start by setting RPS Signal 0.
1165 MC_ENABLE( P_MC2, MC2_ADC_RPS );
1169 if(irqbit&IRQ_COINT3B){
1170 DEBUG("s626_irq_handler: interrupt on counter 3B overflow\n");
1173 //clear interrupt capture flag
1174 k->ResetCapFlags(dev,k);
1176 if(cmd->scan_begin_src==TRIG_TIMER){
1177 DEBUG("s626_irq_handler: scan timer trigger!!!\n");
1179 // Trigger ADC scan loop start by setting RPS Signal 0.
1180 MC_ENABLE( P_MC2, MC2_ADC_RPS );
1183 if(cmd->convert_src==TRIG_TIMER){
1184 DEBUG("s626_irq_handler: convert timer trigger is set\n");
1186 devpriv->ai_convert_count=cmd->chanlist_len;
1187 k->SetEnable(dev,k,CLKENAB_ALWAYS);
1193 writel(irqstatus,devpriv->base_addr+P_IER);
1195 DEBUG("s626_irq_handler: exit interrupt service routine.\n");
1197 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1201 static int s626_detach(comedi_device *dev)
1205 devpriv->ai_cmd_running=0;
1207 if(devpriv->base_addr){
1209 WR7146( P_IER, 0 ); // Disable master interrupt.
1210 WR7146( P_ISR, IRQ_GPIO3 | IRQ_RPS1 ); // Clear board's IRQ status flag.
1212 // Disable the watchdog timer and battery charger.
1215 // Close all interfaces on 7146 device.
1216 WR7146( P_MC1, MC1_SHUTDOWN );
1217 WR7146( P_ACON1, ACON1_BASE );
1219 CloseDMAB(dev,&devpriv->RPSBuf,DMABUF_SIZE);
1220 CloseDMAB(dev,&devpriv->ANABuf,DMABUF_SIZE);
1224 comedi_free_irq(dev->irq,dev);
1227 if(devpriv->base_addr){
1228 iounmap(devpriv->base_addr);
1232 if(devpriv->got_regions)
1234 pci_release_regions(devpriv->pdev);
1235 pci_disable_device(devpriv->pdev);
1237 pci_dev_put(devpriv->pdev);
1241 DEBUG("s626_detach: S626 detached!\n");
1247 * this functions build the RPS program for hardware driven acquistion
1249 void ResetADC(comedi_device *dev,uint8_t *ppl )
1251 register uint32_t *pRPS;
1256 comedi_cmd *cmd=&(dev->subdevices->async->cmd);
1258 // Stop RPS program in case it is currently running.
1259 MC_DISABLE( P_MC1, MC1_ERPS1 );
1261 // Set starting logical address to write RPS commands.
1262 pRPS = (uint32_t *)devpriv->RPSBuf.LogicalBase;
1264 // Initialize RPS instruction pointer.
1265 WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
1267 // Construct RPS program in RPSBuf DMA buffer
1269 if(cmd!=NULL && cmd->scan_begin_src!=TRIG_FOLLOW){
1270 DEBUG("ResetADC: scan_begin pause inserted\n");
1271 // Wait for Start trigger.
1272 *pRPS++= RPS_PAUSE | RPS_SIGADC ;
1273 *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
1276 // SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary
1277 // because the first RPS DEBI Write following a non-RPS DEBI write
1278 // seems to always fail. If we don't do this dummy write, the ADC
1279 // gain might not be set to the value required for the first slot in
1280 // the poll list; the ADC gain would instead remain unchanged from
1281 // the previously programmed value.
1282 *pRPS++=RPS_LDREG | (P_DEBICMD >> 2) ; // Write DEBI Write command
1283 // and address to shadow RAM.
1284 *pRPS++= DEBI_CMD_WRWORD | LP_GSEL ;
1285 *pRPS++= RPS_LDREG | (P_DEBIAD >> 2) ; // Write DEBI immediate data
1287 *pRPS++= GSEL_BIPOLAR5V ; // arbitrary immediate data
1289 *pRPS++= RPS_CLRSIGNAL | RPS_DEBI ; // Reset "shadow RAM
1291 *pRPS++= RPS_UPLOAD | RPS_DEBI ; // Invoke shadow RAM upload.
1292 *pRPS++= RPS_PAUSE | RPS_DEBI ; // Wait for shadow upload to finish.
1294 // Digitize all slots in the poll list. This is implemented as a
1295 // for loop to limit the slot count to 16 in case the application
1296 // forgot to set the EOPL flag in the final slot.
1297 for ( devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++ ) {
1298 // Convert application's poll list item to private board class
1299 // format. Each app poll list item is an uint8_t with form
1300 // (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
1301 // +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
1302 LocalPPL = ( *ppl << 8 ) | ( *ppl & 0x10 ? GSEL_BIPOLAR5V : GSEL_BIPOLAR10V );
1304 // Switch ADC analog gain.
1305 *pRPS++= RPS_LDREG | (P_DEBICMD >> 2) ; // Write DEBI command
1308 *pRPS++= DEBI_CMD_WRWORD | LP_GSEL ;
1309 *pRPS++ =RPS_LDREG | (P_DEBIAD >> 2) ; // Write DEBI
1310 // immediate data to
1313 *pRPS++= RPS_CLRSIGNAL | RPS_DEBI ; // Reset "shadow RAM uploaded"
1315 *pRPS++= RPS_UPLOAD | RPS_DEBI ; // Invoke shadow RAM upload.
1316 *pRPS++= RPS_PAUSE | RPS_DEBI ; // Wait for shadow upload to
1319 // Select ADC analog input channel.
1320 *pRPS++= RPS_LDREG | (P_DEBICMD >> 2) ; // Write DEBI command
1323 *pRPS++= DEBI_CMD_WRWORD | LP_ISEL ;
1324 *pRPS++= RPS_LDREG | (P_DEBIAD >> 2) ; // Write DEBI
1325 // immediate data to
1328 *pRPS++= RPS_CLRSIGNAL | RPS_DEBI ; // Reset "shadow RAM uploaded"
1330 *pRPS++= RPS_UPLOAD | RPS_DEBI ; // Invoke shadow RAM upload.
1331 *pRPS++= RPS_PAUSE | RPS_DEBI ; // Wait for shadow upload to
1334 // Delay at least 10 microseconds for analog input settling.
1335 // Instead of padding with NOPs, we use RPS_JUMP instructions
1336 // here; this allows us to produce a longer delay than is
1337 // possible with NOPs because each RPS_JUMP flushes the RPS'
1338 // instruction prefetch pipeline.
1339 JmpAdrs = (uint32_t)devpriv->RPSBuf.PhysicalBase + (uint32_t)pRPS - (uint32_t)devpriv->RPSBuf.LogicalBase;
1340 for ( i = 0; i < ( 10 * RPSCLK_PER_US / 2); i++ ) {
1341 JmpAdrs += 8; // Repeat to implement time delay:
1342 * pRPS++= RPS_JUMP ; // Jump to next RPS instruction.
1346 if(cmd!=NULL && cmd->convert_src!=TRIG_NOW){
1347 DEBUG("ResetADC: convert pause inserted\n");
1348 // Wait for Start trigger.
1349 *pRPS++= RPS_PAUSE | RPS_SIGADC ;
1350 *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
1353 // Start ADC by pulsing GPIO1.
1354 *pRPS++= RPS_LDREG | (P_GPIO >> 2) ; // Begin ADC Start pulse.
1355 *pRPS++= GPIO_BASE | GPIO1_LO ;
1357 // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
1358 *pRPS++= RPS_LDREG | (P_GPIO >> 2) ; // End ADC Start pulse.
1359 *pRPS++= GPIO_BASE | GPIO1_HI ;
1361 // Wait for ADC to complete (GPIO2 is asserted high when ADC not
1362 // busy) and for data from previous conversion to shift into FB
1363 // BUFFER 1 register.
1364 *pRPS++= RPS_PAUSE | RPS_GPIO2 ; // Wait for ADC done.
1366 // Transfer ADC data from FB BUFFER 1 register to DMA buffer.
1367 *pRPS++=RPS_STREG | ( BUGFIX_STREG( P_FB_BUFFER1 ) >> 2 ) ;
1368 *pRPS++= (uint32_t)devpriv->ANABuf.PhysicalBase + ( devpriv->AdcItems << 2 ) ;
1370 // If this slot's EndOfPollList flag is set, all channels have
1371 // now been processed.
1372 if ( *ppl++ & EOPL ) {
1373 devpriv->AdcItems++; // Adjust poll list item count.
1374 break; // Exit poll list processing loop.
1377 DEBUG("ResetADC: ADC items %d \n",devpriv->AdcItems);
1379 // VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the
1380 // ADC to stabilize for 2 microseconds before starting the final
1381 // (dummy) conversion. This delay is necessary to allow sufficient
1382 // time between last conversion finished and the start of the dummy
1383 // conversion. Without this delay, the last conversion's data value
1384 // is sometimes set to the previous conversion's data value.
1385 for ( n = 0; n < ( 2 * RPSCLK_PER_US ); n++ ) *pRPS++=RPS_NOP ;
1387 // Start a dummy conversion to cause the data from the last
1388 // conversion of interest to be shifted in.
1389 *pRPS++= RPS_LDREG | (P_GPIO >> 2) ; // Begin ADC Start pulse.
1390 *pRPS++=GPIO_BASE | GPIO1_LO ;
1392 // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
1393 *pRPS++=RPS_LDREG | (P_GPIO >> 2) ; // End ADC Start pulse.
1394 *pRPS++=GPIO_BASE | GPIO1_HI ;
1396 // Wait for the data from the last conversion of interest to arrive
1397 // in FB BUFFER 1 register.
1398 *pRPS++= RPS_PAUSE | RPS_GPIO2 ; // Wait for ADC done.
1400 // Transfer final ADC data from FB BUFFER 1 register to DMA buffer.
1401 *pRPS++=RPS_STREG | ( BUGFIX_STREG( P_FB_BUFFER1 ) >> 2 ) ;//
1402 *pRPS++=(uint32_t)devpriv->ANABuf.PhysicalBase + ( devpriv->AdcItems << 2 ) ;
1404 // Indicate ADC scan loop is finished.
1405 // *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done.
1408 if(devpriv->ai_cmd_running==1){
1409 DEBUG("ResetADC: insert irq in ADC RPS task\n");
1413 // Restart RPS program at its beginning.
1414 *pRPS++= RPS_JUMP ; // Branch to start of RPS program.
1415 *pRPS++=(uint32_t)devpriv->RPSBuf.PhysicalBase ;
1417 // End of RPS program build
1418 // ------------------------------------------------------------
1421 /* TO COMPLETE, IF NECESSARY */
1422 static int s626_ai_insn_config(comedi_device*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
1427 /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */
1429 /* register uint8_t i; */
1430 /* register int32_t *readaddr; */
1432 /* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */
1434 /* // Trigger ADC scan loop start by setting RPS Signal 0. */
1435 /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
1437 /* // Wait until ADC scan loop is finished (RPS Signal 0 reset). */
1438 /* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
1440 /* // Init ptr to DMA buffer that holds new ADC data. We skip the */
1441 /* // first uint16_t in the buffer because it contains junk data from */
1442 /* // the final ADC of the previous poll list scan. */
1443 /* readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */
1445 /* // Convert ADC data to 16-bit integer values and copy to application */
1447 /* for ( i = 0; i < devpriv->AdcItems; i++ ) { */
1448 /* *data = s626_ai_reg_to_uint( *readaddr++ ); */
1449 /* DEBUG("s626_ai_rinsn: data %d \n",*data); */
1453 /* DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */
1457 static int s626_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
1459 uint16_t chan = CR_CHAN(insn->chanspec);
1460 uint16_t range = CR_RANGE(insn->chanspec);
1465 /* //interrupt call test */
1466 /* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); //Writing a logical 1 */
1467 /* //into any of the RPS_PSR */
1468 /* //bits causes the */
1469 /* //corresponding interrupt */
1470 /* //to be generated if */
1473 DEBUG("s626_ai_insn_read: entering\n");
1475 // Convert application's ADC specification into form
1476 // appropriate for register programming.
1477 if(range==0) AdcSpec = ( chan << 8 ) | ( GSEL_BIPOLAR5V );
1478 else AdcSpec = ( chan << 8 ) | ( GSEL_BIPOLAR10V );
1480 // Switch ADC analog gain.
1481 DEBIwrite( dev, LP_GSEL, AdcSpec ); // Set gain.
1483 // Select ADC analog input channel.
1484 DEBIwrite( dev, LP_ISEL, AdcSpec ); // Select channel.
1486 for(n=0; n<insn->n; n++){
1488 // Delay 10 microseconds for analog input settling.
1491 // Start ADC by pulsing GPIO1 low.
1492 GpioImage = RR7146( P_GPIO );
1493 // Assert ADC Start command
1494 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1495 // and stretch it out.
1496 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1497 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1498 // Negate ADC Start command.
1499 WR7146( P_GPIO, GpioImage | GPIO1_HI );
1501 // Wait for ADC to complete (GPIO2 is asserted high when
1502 // ADC not busy) and for data from previous conversion to
1503 // shift into FB BUFFER 1 register.
1505 // Wait for ADC done.
1506 while ( !( RR7146( P_PSR ) & PSR_GPIO2 ) );
1509 if(n!=0) data[n-1]=s626_ai_reg_to_uint(RR7146( P_FB_BUFFER1 ));
1511 // Allow the ADC to stabilize for 4 microseconds before
1512 // starting the next (final) conversion. This delay is
1513 // necessary to allow sufficient time between last
1514 // conversion finished and the start of the next
1515 // conversion. Without this delay, the last conversion's
1516 // data value is sometimes set to the previous
1517 // conversion's data value.
1521 // Start a dummy conversion to cause the data from the
1522 // previous conversion to be shifted in.
1523 GpioImage = RR7146( P_GPIO );
1525 //Assert ADC Start command
1526 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1527 // and stretch it out.
1528 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1529 WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
1530 // Negate ADC Start command.
1531 WR7146( P_GPIO, GpioImage | GPIO1_HI );
1533 // Wait for the data to arrive in FB BUFFER 1 register.
1535 // Wait for ADC done.
1536 while ( !( RR7146( P_PSR ) & PSR_GPIO2 ) );
1538 // Fetch ADC data from audio interface's input shift
1542 if(n!=0) data[n-1]=s626_ai_reg_to_uint(RR7146( P_FB_BUFFER1 ));
1544 DEBUG("s626_ai_insn_read: samples %d, data %d\n",n,data[n-1]);
1549 static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd){
1553 for(n=0;n<cmd->chanlist_len;n++){
1554 if(CR_RANGE((cmd->chanlist)[n])==0) ppl[n]= ( CR_CHAN((cmd->chanlist)[n]) ) | ( RANGE_5V );
1555 else ppl[n] = ( CR_CHAN((cmd->chanlist)[n]) ) | ( RANGE_10V );
1562 static int s626_ai_inttrig(comedi_device *dev,comedi_subdevice *s,
1563 unsigned int trignum)
1565 if(trignum!=0) return -EINVAL;
1567 DEBUG("s626_ai_inttrig: trigger adc start...");
1569 // Start executing the RPS program.
1570 MC_ENABLE( P_MC1, MC1_ERPS1 );
1572 s->async->inttrig=NULL;
1580 static int s626_ai_cmd(comedi_device *dev,comedi_subdevice *s){
1583 comedi_cmd *cmd=&s->async->cmd;
1588 DEBUG("s626_ai_cmd: entering command function\n");
1590 if (devpriv->ai_cmd_running) {
1591 printk("s626_ai_cmd: Another ai_cmd is running %d\n", dev->minor);
1596 writel(0,devpriv->base_addr+P_IER);
1598 //clear interrupt request
1599 writel(IRQ_RPS1|IRQ_GPIO3,devpriv->base_addr+P_ISR);
1601 //clear any pending interrupt
1602 s626_dio_clear_irq(dev);
1603 // s626_enc_clear_irq(dev);
1605 //reset ai_cmd_running flag
1606 devpriv->ai_cmd_running=0;
1608 // test if cmd is valid
1610 DEBUG("s626_ai_cmd: NULL command\n");
1613 DEBUG("s626_ai_cmd: command recieved!!!\n");
1617 comedi_error(dev, "s626_ai_cmd: cannot run command without an irq");
1621 s626_ai_load_polllist(ppl,cmd);
1622 devpriv->ai_cmd_running=1;
1623 devpriv->ai_convert_count=0;
1625 switch(cmd->scan_begin_src){
1629 // set a conter to generate adc trigger at scan_begin_arg interval
1631 tick=s626_ns_to_timer((int *)&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);
1633 //load timer value and enable interrupt
1634 s626_timer_load(dev, k, tick);
1635 k->SetEnable(dev,k,CLKENAB_ALWAYS);
1637 DEBUG("s626_ai_cmd: scan trigger timer is set with value %d\n",tick);
1641 // set the digital line and interrupt for scan trigger
1642 if(cmd->start_src!=TRIG_EXT) s626_dio_set_irq(dev,cmd->scan_begin_arg);
1644 DEBUG("s626_ai_cmd: External scan trigger is set!!!\n");
1649 switch(cmd->convert_src){
1653 // set a conter to generate adc trigger at convert_arg interval
1655 tick=s626_ns_to_timer((int *)&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);
1657 //load timer value and enable interrupt
1658 s626_timer_load(dev, k, tick);
1659 k->SetEnable(dev,k,CLKENAB_INDEX);
1661 DEBUG("s626_ai_cmd: convert trigger timer is set with value %d\n",tick);
1664 // set the digital line and interrupt for convert trigger
1665 if(cmd->scan_begin_src!=TRIG_EXT && cmd->start_src==TRIG_EXT)
1666 s626_dio_set_irq(dev, cmd->convert_arg);
1668 DEBUG("s626_ai_cmd: External convert trigger is set!!!\n");
1673 switch(cmd->stop_src){
1675 // data arrives as one packet
1676 devpriv->ai_sample_count=cmd->stop_arg;
1677 devpriv->ai_continous=0;
1680 // continous aquisition
1681 devpriv->ai_continous=1;
1682 devpriv->ai_sample_count=0;
1688 switch(cmd->start_src){
1690 // Trigger ADC scan loop start by setting RPS Signal 0.
1691 // MC_ENABLE( P_MC2, MC2_ADC_RPS );
1693 // Start executing the RPS program.
1694 MC_ENABLE( P_MC1, MC1_ERPS1 );
1696 DEBUG("s626_ai_cmd: ADC triggered\n");
1697 s->async->inttrig=NULL;
1700 //configure DIO channel for acquisition trigger
1701 s626_dio_set_irq(dev, cmd->start_arg);
1703 DEBUG("s626_ai_cmd: External start trigger is set!!!\n");
1705 s->async->inttrig=NULL;
1708 s->async->inttrig=s626_ai_inttrig;
1713 writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
1715 DEBUG("s626_ai_cmd: command function terminated\n");
1720 static int s626_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,
1725 /* cmdtest tests a particular command to see if it is valid. Using
1726 * the cmdtest ioctl, a user can create a valid cmd and then have it
1727 * executes by the cmd ioctl.
1729 * cmdtest returns 1,2,3,4 or 0, depending on which tests the
1730 * command passes. */
1732 /* step 1: make sure trigger sources are trivially valid */
1735 cmd->start_src &= TRIG_NOW|TRIG_INT|TRIG_EXT;
1736 if(!cmd->start_src || tmp!=cmd->start_src)err++;
1738 tmp=cmd->scan_begin_src;
1739 cmd->scan_begin_src &= TRIG_TIMER|TRIG_EXT|TRIG_FOLLOW;
1740 if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;
1742 tmp=cmd->convert_src;
1743 cmd->convert_src &= TRIG_TIMER|TRIG_EXT|TRIG_NOW;
1744 if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
1746 tmp=cmd->scan_end_src;
1747 cmd->scan_end_src &= TRIG_COUNT;
1748 if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;
1751 cmd->stop_src &= TRIG_COUNT|TRIG_NONE;
1752 if(!cmd->stop_src || tmp!=cmd->stop_src)err++;
1756 /* step 2: make sure trigger sources are unique and mutually
1759 /* note that mutual compatiblity is not an issue here */
1760 if(cmd->scan_begin_src!=TRIG_TIMER &&
1761 cmd->scan_begin_src!=TRIG_EXT && cmd->scan_begin_src!=TRIG_FOLLOW)err++;
1762 if(cmd->convert_src!=TRIG_TIMER &&
1763 cmd->convert_src!=TRIG_EXT && cmd->convert_src!=TRIG_NOW)err++;
1764 if(cmd->stop_src!=TRIG_COUNT &&
1765 cmd->stop_src!=TRIG_NONE)err++;
1769 /* step 3: make sure arguments are trivially compatible */
1771 if(cmd->start_src!=TRIG_EXT && cmd->start_arg!=0){
1776 if(cmd->start_src==TRIG_EXT && cmd->start_arg<0){
1781 if(cmd->start_src==TRIG_EXT && cmd->start_arg>39){
1786 if(cmd->scan_begin_src==TRIG_EXT && cmd->scan_begin_arg<0){
1787 cmd->scan_begin_arg=0;
1791 if(cmd->scan_begin_src==TRIG_EXT && cmd->scan_begin_arg>39){
1792 cmd->scan_begin_arg=39;
1796 if(cmd->convert_src==TRIG_EXT && cmd->convert_arg<0){
1801 if(cmd->convert_src==TRIG_EXT && cmd->convert_arg>39){
1802 cmd->convert_arg=39;
1806 #define MAX_SPEED 200000 /* in nanoseconds */
1807 #define MIN_SPEED 2000000000 /* in nanoseconds */
1809 if(cmd->scan_begin_src==TRIG_TIMER){
1810 if(cmd->scan_begin_arg<MAX_SPEED){
1811 cmd->scan_begin_arg=MAX_SPEED;
1814 if(cmd->scan_begin_arg>MIN_SPEED){
1815 cmd->scan_begin_arg=MIN_SPEED;
1819 /* external trigger */
1820 /* should be level/edge, hi/lo specification here */
1821 /* should specify multiple external triggers */
1822 /* if(cmd->scan_begin_arg>9){ */
1823 /* cmd->scan_begin_arg=9; */
1827 if(cmd->convert_src==TRIG_TIMER){
1828 if(cmd->convert_arg<MAX_SPEED){
1829 cmd->convert_arg=MAX_SPEED;
1832 if(cmd->convert_arg>MIN_SPEED){
1833 cmd->convert_arg=MIN_SPEED;
1837 /* external trigger */
1839 /* if(cmd->convert_arg>9){ */
1840 /* cmd->convert_arg=9; */
1845 if(cmd->scan_end_arg!=cmd->chanlist_len){
1846 cmd->scan_end_arg=cmd->chanlist_len;
1849 if(cmd->stop_src==TRIG_COUNT){
1850 if(cmd->stop_arg>0x00ffffff){
1851 cmd->stop_arg=0x00ffffff;
1856 if(cmd->stop_arg!=0){
1864 /* step 4: fix up any arguments */
1866 if(cmd->scan_begin_src==TRIG_TIMER){
1867 tmp=cmd->scan_begin_arg;
1868 s626_ns_to_timer((int *)&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);
1869 if(tmp!=cmd->scan_begin_arg)err++;
1871 if(cmd->convert_src==TRIG_TIMER){
1872 tmp=cmd->convert_arg;
1873 s626_ns_to_timer((int *)&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);
1874 if(tmp!=cmd->convert_arg)err++;
1875 if(cmd->scan_begin_src==TRIG_TIMER &&
1876 cmd->scan_begin_arg<cmd->convert_arg*cmd->scan_end_arg){
1877 cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg;
1887 static int s626_ai_cancel(comedi_device *dev,comedi_subdevice *s)
1889 // Stop RPS program in case it is currently running.
1890 MC_DISABLE( P_MC1, MC1_ERPS1 );
1892 //disable master interrupt
1893 writel(0,devpriv->base_addr+P_IER);
1895 devpriv->ai_cmd_running=0;
1900 /* This function doesn't require a particular form, this is just what
1901 * happens to be used in some of the drivers. It should convert ns
1902 * nanoseconds to a counter value suitable for programming the device.
1903 * Also, it should adjust ns so that it cooresponds to the actual time
1904 * that the device will use. */
1905 static int s626_ns_to_timer(int *nanosec,int round_mode)
1909 base=500; //2MHz internal clock
1912 case TRIG_ROUND_NEAREST:
1914 divider=(*nanosec+base/2)/base;
1916 case TRIG_ROUND_DOWN:
1917 divider=(*nanosec)/base;
1920 divider=(*nanosec+base-1)/base;
1924 *nanosec=base*divider;
1928 static int s626_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
1931 uint16_t chan = CR_CHAN(insn->chanspec);
1934 for(i=0;i<insn->n;i++){
1935 dacdata=(int16_t)data[i];
1936 devpriv->ao_readback[CR_CHAN(insn->chanspec)]=data[i];
1937 dacdata-= ( 0x1fff );
1939 SetDAC(dev,chan,dacdata);
1945 static int s626_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
1949 for(i=0;i<insn->n;i++){
1950 data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
1956 /////////////////////////////////////////////////////////////////////
1957 /////////////// DIGITAL I/O FUNCTIONS /////////////////////////////
1958 /////////////////////////////////////////////////////////////////////
1959 // All DIO functions address a group of DIO channels by means of
1960 // "group" argument. group may be 0, 1 or 2, which correspond to DIO
1961 // ports A, B and C, respectively.
1962 /////////////////////////////////////////////////////////////////////
1964 static void s626_dio_init(comedi_device *dev)
1967 comedi_subdevice *s;
1969 // Prepare to treat writes to WRCapSel as capture disables.
1970 DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP );
1972 // For each group of sixteen channels ...
1973 for ( group = 0; group < S626_DIO_BANKS ; group++ )
1975 s=dev->subdevices+2+group;
1976 DEBIwrite(dev, diopriv->WRIntSel, 0 ); // Disable all interrupts.
1977 DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF ); // Disable all event
1979 DEBIwrite(dev, diopriv->WREdgSel, 0 ); // Init all DIOs to
1982 DEBIwrite(dev, diopriv->WRDOut, 0 ); // Program all outputs
1983 // to inactive state.
1985 DEBUG("s626_dio_init: DIO initialized \n");
1988 /* DIO devices are slightly special. Although it is possible to
1989 * implement the insn_read/insn_write interface, it is much more
1990 * useful to applications if you implement the insn_bits interface.
1991 * This allows packed reading/writing of the DIO channels. The comedi
1992 * core can convert between insn_bits and insn_read/write */
1994 static int s626_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
1996 /* Length of data must be 2 (mask and new data, see below) */
2001 printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor);
2006 * The insn data consists of a mask in data[0] and the new data in
2007 * data[1]. The mask defines which bits we are concerning about.
2008 * The new data must be anded with the mask. Each channel
2009 * corresponds to a bit.
2012 /* Check if requested ports are configured for output */
2013 if((s->io_bits & data[0]) != data[0])
2016 s->state &= ~data[0];
2017 s->state |= data[0] & data[1];
2019 /* Write out the new digital output lines */
2021 DEBIwrite(dev,diopriv->WRDOut,s->state);
2023 data[1]=DEBIread(dev,diopriv->RDDIn);
2028 static int s626_dio_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
2032 case INSN_CONFIG_DIO_QUERY:
2033 data[1] = (s->io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : COMEDI_INPUT;
2037 s->io_bits&= ~(1 << CR_CHAN(insn->chanspec));
2040 s->io_bits|= 1 << CR_CHAN(insn->chanspec);
2046 DEBIwrite(dev,diopriv->WRDOut,s->io_bits);
2051 static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
2054 unsigned int bitmask;
2055 unsigned int status;
2059 bitmask=1<<(chan-(16*group));
2060 DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",chan-(16*group),group);
2062 //set channel to capture positive edge
2063 status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDEdgSel);
2064 DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WREdgSel,bitmask|status);
2066 //enable interrupt on selected channel
2067 status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDIntSel);
2068 DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRIntSel,bitmask|status);
2070 //enable edge capture write command
2071 DEBIwrite(dev,LP_MISC1,MISC1_EDCAP);
2073 //enable edge capture on selected channel
2074 status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDCapSel);
2075 DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,bitmask|status);
2080 static int s626_dio_reset_irq(comedi_device *dev, unsigned int group, unsigned int mask)
2082 DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n",mask,group);
2084 //disable edge capture write command
2085 DEBIwrite(dev,LP_MISC1,MISC1_NOEDCAP);
2087 //enable edge capture on selected channel
2088 DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,mask);
2093 static int s626_dio_clear_irq(comedi_device *dev)
2097 //disable edge capture write command
2098 DEBIwrite(dev,LP_MISC1,MISC1_NOEDCAP);
2100 for(group=0;group<S626_DIO_BANKS;group++){
2101 //clear pending events and interrupt
2102 DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,0xffff);
2108 /* Now this function initializes the value of the counter (data[0])
2109 and set the subdevice. To complete with trigger and interrupt
2111 static int s626_enc_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
2113 uint16_t Setup = ( LOADSRC_INDX << BF_LOADSRC ) | // Preload upon
2115 ( INDXSRC_SOFT << BF_INDXSRC ) | // Disable hardware index.
2116 ( CLKSRC_COUNTER << BF_CLKSRC ) | // Operating mode is Counter.
2117 ( CLKPOL_POS << BF_CLKPOL ) | // Active high clock.
2118 //( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down.
2119 ( CLKMULT_1X << BF_CLKMULT ) | // Clock multiplier is 1x.
2120 ( CLKENAB_INDEX << BF_CLKENAB );
2121 /* uint16_t DisableIntSrc=TRUE; */
2122 // uint32_t Preloadvalue; //Counter initial value
2123 uint16_t valueSrclatch=LATCHSRC_AB_READ ;
2124 uint16_t enab=CLKENAB_ALWAYS;
2125 enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
2127 DEBUG("s626_enc_insn_config: encoder config\n");
2129 // (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]);
2131 k->SetMode(dev,k,Setup,TRUE);
2132 Preload(dev,k,*(insn->data));
2133 k->PulseIndex(dev,k);
2134 SetLatchSource(dev,k,valueSrclatch);
2135 k->SetEnable(dev,k,(uint16_t)(enab != 0));
2140 static int s626_enc_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
2143 enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
2145 DEBUG("s626_enc_insn_read: encoder read channel %d \n",CR_CHAN(insn->chanspec));
2147 for (n=0;n<insn->n;n++) data[n]=ReadLatch(dev,k);
2149 DEBUG("s626_enc_insn_read: encoder sample %d\n",data[n]);
2154 static int s626_enc_insn_write(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
2156 enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
2158 DEBUG("s626_enc_insn_write: encoder write channel %d \n",CR_CHAN(insn->chanspec));
2160 // Set the preload register
2161 Preload(dev,k,data[0]);
2163 // Software index pulse forces the preload register to load
2165 k->SetLoadTrig(dev, k, 0);
2166 k->PulseIndex(dev, k);
2167 k->SetLoadTrig(dev, k, 2);
2169 DEBUG("s626_enc_insn_write: End encoder write\n");
2174 static void s626_timer_load(comedi_device *dev, enc_private *k, int tick)
2176 uint16_t Setup = ( LOADSRC_INDX << BF_LOADSRC ) | // Preload upon
2178 ( INDXSRC_SOFT << BF_INDXSRC ) | // Disable hardware index.
2179 ( CLKSRC_TIMER << BF_CLKSRC ) | // Operating mode is Timer.
2180 ( CLKPOL_POS << BF_CLKPOL ) | // Active high clock.
2181 ( CNTDIR_DOWN << BF_CLKPOL ) | // Count direction is Down.
2182 ( CLKMULT_1X << BF_CLKMULT ) | // Clock multiplier is 1x.
2183 ( CLKENAB_INDEX << BF_CLKENAB );
2184 uint16_t valueSrclatch=LATCHSRC_A_INDXA ;
2185 // uint16_t enab=CLKENAB_ALWAYS;
2187 k->SetMode(dev,k,Setup,FALSE);
2189 // Set the preload register
2190 Preload(dev,k,tick);
2192 // Software index pulse forces the preload register to load
2194 k->SetLoadTrig(dev, k, 0);
2195 k->PulseIndex(dev, k);
2197 //set reload on counter overflow
2198 k->SetLoadTrig(dev, k, 1);
2200 //set interrupt on overflow
2201 k->SetIntSrc(dev,k,INTSRC_OVER);
2203 SetLatchSource(dev,k,valueSrclatch);
2204 // k->SetEnable(dev,k,(uint16_t)(enab != 0));
2207 ///////////////////////////////////////////////////////////////////////
2208 ///////////////////// DAC FUNCTIONS /////////////////////////////////
2209 ///////////////////////////////////////////////////////////////////////
2211 // Slot 0 base settings.
2212 #define VECT0 ( XSD2 | RSD3 | SIB_A2 ) // Slot 0 always shifts in
2213 // 0xFF and store it to
2216 // TrimDac LogicalChan-to-PhysicalChan mapping table.
2217 static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
2219 // TrimDac LogicalChan-to-EepromAdrs mapping table.
2220 static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
2222 static void LoadTrimDACs(comedi_device *dev){
2225 // Copy TrimDac setpoint values from EEPROM to TrimDacs.
2226 for ( i = 0; i < (sizeof(trimchan)/sizeof(trimchan[0])); i++ )
2227 WriteTrimDAC(dev, i, I2Cread(dev,trimadrs[i] ) );
2230 static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan, uint8_t DacData ){
2233 // Save the new setpoint in case the application needs to read it back later.
2234 devpriv->TrimSetpoint[LogicalChan] = (uint8_t)DacData;
2236 // Map logical channel number to physical channel number.
2237 chan = (uint32_t)trimchan[LogicalChan];
2239 // Set up TSL2 records for TrimDac write operation. All slots shift
2240 // 0xFF in from pulled-up SD3 so that the end of the slot sequence
2242 SETVECT( 2, XSD2 | XFIFO_1 | WS3 ); // Slot 2: Send high uint8_t
2243 // to target TrimDac.
2244 SETVECT( 3, XSD2 | XFIFO_0 | WS3 ); // Slot 3: Send low uint8_t to
2246 SETVECT( 4, XSD2 | XFIFO_3 | WS1 ); // Slot 4: Send NOP high
2247 // uint8_t to DAC0 to keep
2249 SETVECT( 5, XSD2 | XFIFO_2 | WS1 | EOS ); // Slot 5: Send NOP low
2252 // Construct and transmit target DAC's serial packet: ( 0000 AAAA
2253 // ),( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the DAC
2254 // channel's address, and D<7:0> is the DAC setpoint. Append a WORD
2255 // value (that writes a channel 0 NOP command to a non-existent main
2256 // DAC channel) that serves to keep the clock running after the
2257 // packet has been sent to the target DAC.
2259 SendDAC(dev, ( (uint32_t)chan << 8 ) // Address the DAC channel
2260 // within the trimdac device.
2261 | (uint32_t)DacData ); // Include DAC setpoint data.
2264 /////////////////////////////////////////////////////////////////////////
2265 //////////////// EEPROM ACCESS FUNCTIONS //////////////////////////////
2266 /////////////////////////////////////////////////////////////////////////
2268 ///////////////////////////////////////////
2269 // Read uint8_t from EEPROM.
2271 static uint8_t I2Cread(comedi_device *dev, uint8_t addr )
2275 // Send EEPROM target address.
2276 if ( I2Chandshake(dev, I2C_B2( I2C_ATTRSTART, I2CW ) // Byte2 = I2C
2281 | I2C_B1( I2C_ATTRSTOP, addr ) // Byte1 = EEPROM
2284 | I2C_B0( I2C_ATTRNOP, 0 ) ) ) // Byte0 = Not
2287 // Abort function and declare error if handshake failed.
2288 DEBUG("I2Cread: error handshake I2Cread a\n");
2292 // Execute EEPROM read.
2293 if ( I2Chandshake(dev,
2294 I2C_B2( I2C_ATTRSTART, I2CR ) // Byte2 = I2C
2298 | I2C_B1( I2C_ATTRSTOP, 0 ) // Byte1 receives
2301 | I2C_B0( I2C_ATTRNOP, 0 ) ) ) // Byte0 = Not
2304 // Abort function and declare error if handshake failed.
2305 DEBUG("I2Cread: error handshake I2Cread b\n");
2309 // Return copy of EEPROM value.
2310 rtnval = (uint8_t)( RR7146(P_I2CCTRL) >> 16 );
2314 static uint32_t I2Chandshake(comedi_device *dev, uint32_t val )
2316 // Write I2C command to I2C Transfer Control shadow register.
2317 WR7146( P_I2CCTRL, val );
2319 // Upload I2C shadow registers into working registers and wait for
2320 // upload confirmation.
2322 MC_ENABLE( P_MC2, MC2_UPLD_IIC );
2323 while ( !MC_TEST( P_MC2, MC2_UPLD_IIC ) );
2325 // Wait until I2C bus transfer is finished or an error occurs.
2326 while ( ( RR7146(P_I2CCTRL) & ( I2C_BUSY | I2C_ERR ) ) == I2C_BUSY );
2328 // Return non-zero if I2C error occured.
2329 return RR7146(P_I2CCTRL) & I2C_ERR;
2333 // Private helper function: Write setpoint to an application DAC channel.
2335 static void SetDAC(comedi_device *dev,uint16_t chan, short dacdata )
2337 register uint16_t signmask;
2338 register uint32_t WSImage;
2340 // Adjust DAC data polarity and set up Polarity Control Register
2342 signmask = 1 << chan;
2346 devpriv->Dacpol |= signmask;
2349 devpriv->Dacpol &= ~signmask;
2351 // Limit DAC setpoint value to valid range.
2352 if ( (uint16_t)dacdata > 0x1FFF )
2355 // Set up TSL2 records (aka "vectors") for DAC update. Vectors V2
2356 // and V3 transmit the setpoint to the target DAC. V4 and V5 send
2357 // data to a non-existent TrimDac channel just to keep the clock
2358 // running after sending data to the target DAC. This is necessary
2359 // to eliminate the clock glitch that would otherwise occur at the
2360 // end of the target DAC's serial data stream. When the sequence
2361 // restarts at V0 (after executing V5), the gate array automatically
2362 // disables gating for the DAC clock and all DAC chip selects.
2363 WSImage = ( chan & 2 ) ? WS1 : WS2; // Choose DAC chip select to
2365 SETVECT( 2, XSD2 | XFIFO_1 | WSImage ); // Slot 2: Transmit high
2366 // data byte to target DAC.
2367 SETVECT( 3, XSD2 | XFIFO_0 | WSImage ); // Slot 3: Transmit low data
2368 // byte to target DAC.
2369 SETVECT( 4, XSD2 | XFIFO_3 | WS3 ); // Slot 4: Transmit to
2370 // non-existent TrimDac
2371 // channel to keep clock
2372 SETVECT( 5, XSD2 | XFIFO_2 | WS3 | EOS ); // Slot 5: running after
2373 // writing target DAC's
2376 // Construct and transmit target DAC's serial packet: ( A10D DDDD
2377 // ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, and D<12:0>
2378 // is the DAC setpoint. Append a WORD value (that writes to a
2379 // non-existent TrimDac channel) that serves to keep the clock
2380 // running after the packet has been sent to the target DAC.
2381 SendDAC( dev, 0x0F000000 //Continue clock after target DAC
2382 //data (write to non-existent
2384 | 0x00004000 // Address the two main dual-DAC
2385 // devices (TSL's chip select enables
2387 | ( (uint32_t)( chan & 1 ) << 15 ) // Address the DAC
2388 // channel within the
2390 | (uint32_t)dacdata ); // Include DAC setpoint data.
2394 ////////////////////////////////////////////////////////
2395 // Private helper function: Transmit serial data to DAC via Audio
2396 // channel 2. Assumes: (1) TSL2 slot records initialized, and (2)
2397 // Dacpol contains valid target image.
2399 static void SendDAC( comedi_device *dev, uint32_t val )
2403 // START THE SERIAL CLOCK RUNNING -------------
2405 // Assert DAC polarity control and enable gating of DAC serial clock
2406 // and audio bit stream signals. At this point in time we must be
2407 // assured of being in time slot 0. If we are not in slot 0, the
2408 // serial clock and audio stream signals will be disabled; this is
2409 // because the following DEBIwrite statement (which enables signals
2410 // to be passed through the gate array) would execute before the
2411 // trailing edge of WS1/WS3 (which turns off the signals), thus
2412 // causing the signals to be inactive during the DAC write.
2413 DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol );
2415 // TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ----------------
2417 // Copy DAC setpoint value to DAC's output DMA buffer.
2419 //WR7146( (uint32_t)devpriv->pDacWBuf, val );
2420 *devpriv->pDacWBuf=val;
2422 // enab the output DMA transfer. This will cause the DMAC to copy
2423 // the DAC's data value to A2's output FIFO. The DMA transfer will
2424 // then immediately terminate because the protection address is
2425 // reached upon transfer of the first DWORD value.
2426 MC_ENABLE( P_MC1, MC1_A2OUT );
2428 // While the DMA transfer is executing ...
2430 // Reset Audio2 output FIFO's underflow flag (along with any other
2431 // FIFO underflow/overflow flags). When set, this flag will
2432 // indicate that we have emerged from slot 0.
2433 WR7146( P_ISR, ISR_AFOU );
2435 // Wait for the DMA transfer to finish so that there will be data
2436 // available in the FIFO when time slot 1 tries to transfer a DWORD
2437 // from the FIFO to the output buffer register. We test for DMA
2438 // Done by polling the DMAC enable flag; this flag is automatically
2439 // cleared when the transfer has finished.
2440 while ( ( RR7146( P_MC1 ) & MC1_A2OUT ) != 0 );
2442 // START THE OUTPUT STREAM TO THE TARGET DAC --------------------
2444 // FIFO data is now available, so we enable execution of time slots
2445 // 1 and higher by clearing the EOS flag in slot 0. Note that SD3
2446 // will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
2448 SETVECT( 0, XSD2 | RSD3 | SIB_A2 );
2450 // Wait for slot 1 to execute to ensure that the Packet will be
2451 // transmitted. This is detected by polling the Audio2 output FIFO
2452 // underflow flag, which will be set when slot 1 execution has
2453 // finished transferring the DAC's data DWORD from the output FIFO
2454 // to the output buffer register.
2455 while ( ( RR7146( P_SSR ) & SSR_AF2_OUT ) == 0 );
2457 // Set up to trap execution at slot 0 when the TSL sequencer cycles
2458 // back to slot 0 after executing the EOS in slot 5. Also,
2459 // simultaneously shift out and in the 0x00 that is ALWAYS the value
2460 // stored in the last byte to be shifted out of the FIFO's DWORD
2462 SETVECT( 0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS );
2464 // WAIT FOR THE TRANSACTION TO FINISH -----------------------
2466 // Wait for the TSL to finish executing all time slots before
2467 // exiting this function. We must do this so that the next DAC
2468 // write doesn't start, thereby enabling clock/chip select signals:
2469 // 1. Before the TSL sequence cycles back to slot 0, which disables
2470 // the clock/cs signal gating and traps slot // list execution. If
2471 // we have not yet finished slot 5 then the clock/cs signals are
2472 // still gated and we have // not finished transmitting the stream.
2473 // 2. While slots 2-5 are executing due to a late slot 0 trap. In
2474 // this case, the slot sequence is currently // repeating, but with
2475 // clock/cs signals disabled. We must wait for slot 0 to trap
2476 // execution before setting // up the next DAC setpoint DMA transfer
2477 // and enabling the clock/cs signals. To detect the end of slot 5,
2478 // we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If
2479 // the TSL has not yet finished executing slot 5 ...
2480 if ( ( RR7146( P_FB_BUFFER2 ) & 0xFF000000 ) != 0 )
2482 // The trap was set on time and we are still executing somewhere
2483 // in slots 2-5, so we now wait for slot 0 to execute and trap
2484 // TSL execution. This is detected when FB_BUFFER2 MSB changes
2485 // from 0xFF to 0x00, which slot 0 causes to happen by shifting
2486 // out/in on SD2 the 0x00 that is always referenced by slot 5.
2487 while ( ( RR7146( P_FB_BUFFER2 ) & 0xFF000000 ) != 0 );
2490 // Either (1) we were too late setting the slot 0 trap; the TSL
2491 // sequencer restarted slot 0 before we could set the EOS trap flag,
2492 // or (2) we were not late and execution is now trapped at slot 0.
2493 // In either case, we must now change slot 0 so that it will store
2494 // value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
2495 // In order to do this, we reprogram slot 0 so that it will shift in
2496 // SD3, which is driven only by a pull-up resistor.
2497 SETVECT( 0, RSD3 | SIB_A2 | EOS );
2499 // Wait for slot 0 to execute, at which time the TSL is setup for
2500 // the next DAC write. This is detected when FB_BUFFER2 MSB changes
2501 // from 0x00 to 0xFF.
2502 while ( ( RR7146( P_FB_BUFFER2 ) & 0xFF000000 ) == 0 );
2505 static void WriteMISC2( comedi_device *dev, uint16_t NewImage )
2507 DEBIwrite( dev, LP_MISC1, MISC1_WENABLE ); // enab writes to
2509 DEBIwrite(dev, LP_WRMISC2, NewImage ); // Write new image to MISC2.
2510 DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE ); // Disable writes to MISC2.
2513 /////////////////////////////////////////////////////////////////////
2514 // Initialize the DEBI interface for all transfers.
2516 static uint16_t DEBIread( comedi_device *dev, uint16_t addr )
2520 // Set up DEBI control register value in shadow RAM.
2521 WR7146( P_DEBICMD, DEBI_CMD_RDWORD | addr );
2523 // Execute the DEBI transfer.
2526 // Fetch target register value.
2527 retval = (uint16_t)RR7146( P_DEBIAD );
2529 // Return register value.
2533 // Execute a DEBI transfer. This must be called from within a
2534 // critical section.
2535 static void DEBItransfer(comedi_device *dev )
2537 // Initiate upload of shadow RAM to DEBI control register.
2538 MC_ENABLE( P_MC2, MC2_UPLD_DEBI );
2540 // Wait for completion of upload from shadow RAM to DEBI control
2542 while ( !MC_TEST( P_MC2, MC2_UPLD_DEBI ) );
2544 // Wait until DEBI transfer is done.
2545 while ( RR7146(P_PSR) & PSR_DEBI_S );
2548 // Write a value to a gate array register.
2549 static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata )
2552 // Set up DEBI control register value in shadow RAM.
2553 WR7146( P_DEBICMD, DEBI_CMD_WRWORD | addr );
2554 WR7146( P_DEBIAD, wdata );
2556 // Execute the DEBI transfer.
2560 /////////////////////////////////////////////////////////////////////////////
2561 // Replace the specified bits in a gate array register. Imports: mask
2562 // specifies bits that are to be preserved, wdata is new value to be
2563 // or'd with the masked original.
2564 static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask, uint16_t wdata )
2567 // Copy target gate array register into P_DEBIAD register.
2568 WR7146( P_DEBICMD, DEBI_CMD_RDWORD | addr ); // Set up DEBI control
2569 // reg value in shadow
2571 DEBItransfer( dev); // Execute the DEBI
2574 // Write back the modified image.
2575 WR7146( P_DEBICMD, DEBI_CMD_WRWORD | addr ); // Set up DEBI control
2576 // reg value in shadow
2579 WR7146( P_DEBIAD, wdata | ( (uint16_t)RR7146( P_DEBIAD ) & mask ) ); // Modify the register image.
2580 DEBItransfer(dev ); // Execute the DEBI Write transfer.
2583 static void CloseDMAB (comedi_device *dev,DMABUF * pdma,size_t bsize )
2585 void *vbptr, *vpptr;
2587 DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n");
2590 //find the matching allocation from the board struct
2592 vbptr=pdma->LogicalBase;
2593 vpptr=pdma->PhysicalBase;
2596 pci_free_consistent (devpriv->pdev, bsize, vbptr,
2598 pdma->LogicalBase = 0;
2599 pdma->PhysicalBase = 0;
2601 DEBUG ("CloseDMAB(): Logical=0x%x, bsize=%d, Physical=0x%x\n", (uint32_t) vbptr, bsize, (uint32_t) vpptr);
2605 ////////////////////////////////////////////////////////////////////////
2606 ///////////////// COUNTER FUNCTIONS //////////////////////////////////
2607 ////////////////////////////////////////////////////////////////////////
2608 // All counter functions address a specific counter by means of the
2609 // "Counter" argument, which is a logical counter number. The Counter
2610 // argument may have any of the following legal values: 0=0A, 1=1A,
2611 // 2=2A, 3=0B, 4=1B, 5=2B.
2612 ////////////////////////////////////////////////////////////////////////
2614 // Forward declarations for functions that are common to both A and B
2617 /////////////////////////////////////////////////////////////////////
2618 //////////////////// PRIVATE COUNTER FUNCTIONS /////////////////////
2619 /////////////////////////////////////////////////////////////////////
2621 /////////////////////////////////////////////////////////////////
2622 // Read a counter's output latch.
2624 static uint32_t ReadLatch(comedi_device *dev, enc_private *k )
2626 register uint32_t value;
2627 //DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n");
2629 // Latch counts and fetch LSW of latched counts value.
2630 value = (uint32_t)DEBIread(dev,k->MyLatchLsw );
2632 // Fetch MSW of latched counts and combine with LSW.
2633 value |= ( (uint32_t) DEBIread(dev,k->MyLatchLsw + 2 ) << 16 );
2635 // DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n");
2637 // Return latched counts.
2641 ///////////////////////////////////////////////////////////////////
2642 // Reset a counter's index and overflow event capture flags.
2644 static void ResetCapFlags_A(comedi_device *dev, enc_private *k )
2646 DEBIreplace(dev, k->MyCRB, (uint16_t)( ~CRBMSK_INTCTRL ), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A );
2649 static void ResetCapFlags_B(comedi_device *dev, enc_private *k )
2651 DEBIreplace(dev, k->MyCRB, (uint16_t)( ~CRBMSK_INTCTRL ), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B );
2654 /////////////////////////////////////////////////////////////////////////
2655 // Return counter setup in a format (COUNTER_SETUP) that is consistent
2656 // for both A and B counters.
2658 static uint16_t GetMode_A(comedi_device *dev, enc_private *k )
2660 register uint16_t cra;
2661 register uint16_t crb;
2662 register uint16_t setup;
2664 // Fetch CRA and CRB register images.
2665 cra = DEBIread(dev,k->MyCRA );
2666 crb = DEBIread(dev,k->MyCRB );
2668 // Populate the standardized counter setup bit fields. Note:
2669 // IndexSrc is restricted to ENC_X or IndxPol.
2670 setup = ( ( cra & STDMSK_LOADSRC ) // LoadSrc = LoadSrcA.
2671 | ( ( crb << ( STDBIT_LATCHSRC - CRBBIT_LATCHSRC ) ) & STDMSK_LATCHSRC ) // LatchSrc = LatchSrcA.
2672 | ( ( cra << ( STDBIT_INTSRC - CRABIT_INTSRC_A ) ) & STDMSK_INTSRC ) // IntSrc = IntSrcA.
2673 | ( ( cra << ( STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1) ) ) & STDMSK_INDXSRC ) // IndxSrc = IndxSrcA<1>.
2674 | ( ( cra >> ( CRABIT_INDXPOL_A - STDBIT_INDXPOL ) ) & STDMSK_INDXPOL ) // IndxPol = IndxPolA.
2675 | ( ( crb >> ( CRBBIT_CLKENAB_A - STDBIT_CLKENAB ) ) & STDMSK_CLKENAB ) ); // ClkEnab = ClkEnabA.
2677 // Adjust mode-dependent parameters.
2678 if ( cra & ( 2 << CRABIT_CLKSRC_A ) ) // If Timer mode (ClkSrcA<1> == 1):
2679 setup |= ( ( CLKSRC_TIMER << STDBIT_CLKSRC ) // Indicate Timer mode.
2680 | ( ( cra << ( STDBIT_CLKPOL - CRABIT_CLKSRC_A ) ) & STDMSK_CLKPOL ) // Set ClkPol to indicate count direction (ClkSrcA<0>).
2681 | ( MULT_X1 << STDBIT_CLKMULT ) ); // ClkMult must be 1x in Timer mode.
2683 else // If Counter mode (ClkSrcA<1> == 0):
2684 setup |= ( ( CLKSRC_COUNTER << STDBIT_CLKSRC ) // Indicate Counter mode.
2685 | ( ( cra >> ( CRABIT_CLKPOL_A - STDBIT_CLKPOL ) ) & STDMSK_CLKPOL ) // Pass through ClkPol.
2686 | ( ( ( cra & CRAMSK_CLKMULT_A ) == ( MULT_X0 << CRABIT_CLKMULT_A ) ) ? // Force ClkMult to 1x if not legal, else pass through.
2687 ( MULT_X1 << STDBIT_CLKMULT ) :
2688 ( ( cra >> ( CRABIT_CLKMULT_A - STDBIT_CLKMULT ) ) & STDMSK_CLKMULT ) ) );
2690 // Return adjusted counter setup.
2694 static uint16_t GetMode_B(comedi_device *dev, enc_private *k )
2696 register uint16_t cra;
2697 register uint16_t crb;
2698 register uint16_t setup;
2700 // Fetch CRA and CRB register images.
2701 cra = DEBIread(dev,k->MyCRA );
2702 crb = DEBIread(dev,k->MyCRB );
2704 // Populate the standardized counter setup bit fields. Note:
2705 // IndexSrc is restricted to ENC_X or IndxPol.
2707 ( ( ( crb << ( STDBIT_INTSRC - CRBBIT_INTSRC_B ) ) & STDMSK_INTSRC ) // IntSrc = IntSrcB.
2708 | ( ( crb << ( STDBIT_LATCHSRC - CRBBIT_LATCHSRC ) ) & STDMSK_LATCHSRC ) // LatchSrc = LatchSrcB.
2709 | ( ( crb << ( STDBIT_LOADSRC - CRBBIT_LOADSRC_B ) ) & STDMSK_LOADSRC ) // LoadSrc = LoadSrcB.
2710 | ( ( crb << ( STDBIT_INDXPOL - CRBBIT_INDXPOL_B ) ) & STDMSK_INDXPOL ) // IndxPol = IndxPolB.
2711 | ( ( crb >> ( CRBBIT_CLKENAB_B - STDBIT_CLKENAB ) ) & STDMSK_CLKENAB ) // ClkEnab = ClkEnabB.
2712 | ( ( cra >> ( (CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC ) ) & STDMSK_INDXSRC ) ); // IndxSrc = IndxSrcB<1>.
2714 // Adjust mode-dependent parameters.
2715 if ( ( crb & CRBMSK_CLKMULT_B ) == ( MULT_X0 << CRBBIT_CLKMULT_B ) ) // If Extender mode (ClkMultB == MULT_X0):
2716 setup |= ( ( CLKSRC_EXTENDER << STDBIT_CLKSRC ) // Indicate Extender mode.
2717 | ( MULT_X1 << STDBIT_CLKMULT ) // Indicate multiplier is 1x.
2718 | ( ( cra >> ( CRABIT_CLKSRC_B - STDBIT_CLKPOL ) ) & STDMSK_CLKPOL ) ); // Set ClkPol equal to Timer count direction (ClkSrcB<0>).
2720 else if ( cra & ( 2 << CRABIT_CLKSRC_B ) ) // If Timer mode (ClkSrcB<1> == 1):
2721 setup |= ( ( CLKSRC_TIMER << STDBIT_CLKSRC ) // Indicate Timer mode.
2722 | ( MULT_X1 << STDBIT_CLKMULT ) // Indicate multiplier is 1x.
2723 | ( ( cra >> ( CRABIT_CLKSRC_B - STDBIT_CLKPOL ) ) & STDMSK_CLKPOL ) ); // Set ClkPol equal to Timer count direction (ClkSrcB<0>).
2725 else // If Counter mode (ClkSrcB<1> == 0):
2726 setup |= ( ( CLKSRC_COUNTER << STDBIT_CLKSRC ) // Indicate Timer mode.
2727 | ( ( crb >> ( CRBBIT_CLKMULT_B - STDBIT_CLKMULT ) ) & STDMSK_CLKMULT ) // Clock multiplier is passed through.
2728 | ( ( crb << ( STDBIT_CLKPOL - CRBBIT_CLKPOL_B ) ) & STDMSK_CLKPOL ) ); // Clock polarity is passed through.
2730 // Return adjusted counter setup.
2734 /////////////////////////////////////////////////////////////////////////////////////////////
2735 // Set the operating mode for the specified counter. The setup
2736 // parameter is treated as a COUNTER_SETUP data type. The following
2737 // parameters are programmable (all other parms are ignored): ClkMult,
2738 // ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
2740 static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc )
2742 register uint16_t cra;
2743 register uint16_t crb;
2744 register uint16_t setup = Setup; // Cache the Standard Setup.
2746 // Initialize CRA and CRB images.
2747 cra = ( ( setup & CRAMSK_LOADSRC_A ) // Preload trigger is passed through.
2748 | ( ( setup & STDMSK_INDXSRC ) >> ( STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1) ) ) ); // IndexSrc is restricted to ENC_X or IndxPol.
2750 crb = ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A // Reset any pending CounterA event captures.
2751 | ( ( setup & STDMSK_CLKENAB ) << ( CRBBIT_CLKENAB_A - STDBIT_CLKENAB ) ) ); // Clock enable is passed through.
2753 // Force IntSrc to Disabled if DisableIntSrc is asserted.
2754 if ( !DisableIntSrc )
2755 cra |= ( ( setup & STDMSK_INTSRC ) >> ( STDBIT_INTSRC - CRABIT_INTSRC_A ) );
2757 // Populate all mode-dependent attributes of CRA & CRB images.
2758 switch ( ( setup & STDMSK_CLKSRC ) >> STDBIT_CLKSRC )
2760 case CLKSRC_EXTENDER: // Extender Mode: Force to Timer mode
2761 // (Extender valid only for B counters).
2763 case CLKSRC_TIMER: // Timer Mode:
2764 cra |= ( ( 2 << CRABIT_CLKSRC_A ) // ClkSrcA<1> selects system clock
2765 | ( ( setup & STDMSK_CLKPOL ) >> ( STDBIT_CLKPOL - CRABIT_CLKSRC_A ) ) // with count direction (ClkSrcA<0>) obtained from ClkPol.
2766 | ( 1 << CRABIT_CLKPOL_A ) // ClkPolA behaves as always-on clock enable.
2767 | ( MULT_X1 << CRABIT_CLKMULT_A ) ); // ClkMult must be 1x.
2770 default: // Counter Mode:
2771 cra |= ( CLKSRC_COUNTER // Select ENC_C and ENC_D as clock/direction inputs.
2772 | ( ( setup & STDMSK_CLKPOL ) << ( CRABIT_CLKPOL_A - STDBIT_CLKPOL ) ) // Clock polarity is passed through.
2773 | ( ( ( setup & STDMSK_CLKMULT ) == ( MULT_X0 << STDBIT_CLKMULT ) ) ? // Force multiplier to x1 if not legal, otherwise pass through.
2774 ( MULT_X1 << CRABIT_CLKMULT_A ) :
2775 ( ( setup & STDMSK_CLKMULT ) << ( CRABIT_CLKMULT_A - STDBIT_CLKMULT ) ) ) );
2778 // Force positive index polarity if IndxSrc is software-driven only,
2779 // otherwise pass it through.
2780 if ( ~setup & STDMSK_INDXSRC )
2781 cra |= ( ( setup & STDMSK_INDXPOL ) << ( CRABIT_INDXPOL_A - STDBIT_INDXPOL ) );
2783 // If IntSrc has been forced to Disabled, update the MISC2 interrupt
2784 // enable mask to indicate the counter interrupt is disabled.
2785 if ( DisableIntSrc )
2786 devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
2788 // While retaining CounterB and LatchSrc configurations, program the
2789 // new counter operating mode.
2790 DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra );
2791 DEBIreplace(dev, k->MyCRB, (uint16_t)( ~( CRBMSK_INTCTRL | CRBMSK_CLKENAB_A ) ), crb );
2794 static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc )
2796 register uint16_t cra;
2797 register uint16_t crb;
2798 register uint16_t setup = Setup; // Cache the Standard Setup.
2800 // Initialize CRA and CRB images.
2801 cra = ( ( setup & STDMSK_INDXSRC ) << ( (CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC ) ); // IndexSrc field is restricted to ENC_X or IndxPol.
2803 crb = ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B // Reset event captures and disable interrupts.
2804 | ( ( setup & STDMSK_CLKENAB ) << ( CRBBIT_CLKENAB_B - STDBIT_CLKENAB ) ) // Clock enable is passed through.
2805 | ( ( setup & STDMSK_LOADSRC ) >> ( STDBIT_LOADSRC - CRBBIT_LOADSRC_B ) ) ); // Preload trigger source is passed through.
2807 // Force IntSrc to Disabled if DisableIntSrc is asserted.
2808 if ( !DisableIntSrc )
2809 crb |= ( ( setup & STDMSK_INTSRC ) >> ( STDBIT_INTSRC - CRBBIT_INTSRC_B ) );
2811 // Populate all mode-dependent attributes of CRA & CRB images.
2812 switch ( ( setup & STDMSK_CLKSRC ) >> STDBIT_CLKSRC )
2814 case CLKSRC_TIMER: // Timer Mode:
2815 cra |= ( ( 2 << CRABIT_CLKSRC_B ) // ClkSrcB<1> selects system clock
2816 | ( ( setup & STDMSK_CLKPOL ) << ( CRABIT_CLKSRC_B - STDBIT_CLKPOL ) ) ); // with direction (ClkSrcB<0>) obtained from ClkPol.
2817 crb |= ( ( 1 << CRBBIT_CLKPOL_B ) // ClkPolB behaves as always-on clock enable.
2818 | ( MULT_X1 << CRBBIT_CLKMULT_B ) ); // ClkMultB must be 1x.
2821 case CLKSRC_EXTENDER: // Extender Mode:
2822 cra |= ( ( 2 << CRABIT_CLKSRC_B ) // ClkSrcB source is OverflowA (same as "timer")
2823 | ( ( setup & STDMSK_CLKPOL ) << ( CRABIT_CLKSRC_B - STDBIT_CLKPOL ) ) ); // with direction obtained from ClkPol.
2824 crb |= ( ( 1 << CRBBIT_CLKPOL_B ) // ClkPolB controls IndexB -- always set to active.
2825 | ( MULT_X0 << CRBBIT_CLKMULT_B ) ); // ClkMultB selects OverflowA as the clock source.
2828 default: // Counter Mode:
2829 cra |= ( CLKSRC_COUNTER << CRABIT_CLKSRC_B ); // Select ENC_C and ENC_D as clock/direction inputs.
2830 crb |= ( ( ( setup & STDMSK_CLKPOL ) >> ( STDBIT_CLKPOL - CRBBIT_CLKPOL_B ) ) // ClkPol is passed through.
2831 | ( ( ( setup & STDMSK_CLKMULT ) == ( MULT_X0 << STDBIT_CLKMULT ) ) ? // Force ClkMult to x1 if not legal, otherwise pass through.
2832 ( MULT_X1 << CRBBIT_CLKMULT_B ) :
2833 ( ( setup & STDMSK_CLKMULT ) << ( CRBBIT_CLKMULT_B - STDBIT_CLKMULT ) ) ) );
2836 // Force positive index polarity if IndxSrc is software-driven only,
2837 // otherwise pass it through.
2838 if ( ~setup & STDMSK_INDXSRC )
2839 crb |= ( ( setup & STDMSK_INDXPOL ) >> ( STDBIT_INDXPOL - CRBBIT_INDXPOL_B ) );
2841 // If IntSrc has been forced to Disabled, update the MISC2 interrupt
2842 // enable mask to indicate the counter interrupt is disabled.
2843 if ( DisableIntSrc )
2844 devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
2846 // While retaining CounterA and LatchSrc configurations, program the
2847 // new counter operating mode.
2848 DEBIreplace( dev, k->MyCRA, (uint16_t)( ~( CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B ) ), cra );
2849 DEBIreplace( dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb );
2852 ////////////////////////////////////////////////////////////////////////
2853 // Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index.
2855 static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab )
2856 { DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
2857 DEBIreplace( dev,k->MyCRB, (uint16_t)( ~( CRBMSK_INTCTRL | CRBMSK_CLKENAB_A ) ), (uint16_t)( enab << CRBBIT_CLKENAB_A ) );
2860 static void SetEnable_B(comedi_device *dev, enc_private *k, uint16_t enab )
2862 DEBIreplace( dev,k->MyCRB, (uint16_t)( ~( CRBMSK_INTCTRL | CRBMSK_CLKENAB_B ) ), (uint16_t)( enab << CRBBIT_CLKENAB_B ) );
2865 static uint16_t GetEnable_A( comedi_device *dev,enc_private *k )
2867 return ( DEBIread( dev, k->MyCRB) >> CRBBIT_CLKENAB_A ) & 1;
2870 static uint16_t GetEnable_B(comedi_device *dev, enc_private *k )
2872 return ( DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B ) & 1;
2875 ////////////////////////////////////////////////////////////////////////
2876 // Return/set a counter pair's latch trigger source. 0: On read
2877 // access, 1: A index latches A, 2: B index latches B, 3: A overflow
2880 static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value )
2881 { DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
2882 DEBIreplace(dev, k->MyCRB, (uint16_t)( ~( CRBMSK_INTCTRL | CRBMSK_LATCHSRC ) ), (uint16_t)( value << CRBBIT_LATCHSRC ) );
2884 DEBUG("SetLatchSource: SetLatchSource exit \n");
2887 /* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ) */
2889 /* return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; */
2892 /////////////////////////////////////////////////////////////////////////
2893 // Return/set the event that will trigger transfer of the preload
2894 // register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow,
2895 // 2=OverflowA (B counters only), 3=disabled.
2897 static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig )
2899 DEBIreplace(dev, k->MyCRA, (uint16_t)( ~CRAMSK_LOADSRC_A ), (uint16_t)( Trig << CRABIT_LOADSRC_A ) );
2902 static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig )
2904 DEBIreplace(dev, k->MyCRB, (uint16_t)( ~( CRBMSK_LOADSRC_B | CRBMSK_INTCTRL ) ), (uint16_t)( Trig << CRBBIT_LOADSRC_B ) );
2907 static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k )
2909 return ( DEBIread( dev,k->MyCRA) >> CRABIT_LOADSRC_A ) & 3;
2912 static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k )
2914 return ( DEBIread(dev,k->MyCRB) >> CRBBIT_LOADSRC_B ) & 3;
2918 ////////////////////
2919 // Return/set counter interrupt source and clear any captured
2920 // index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly,
2921 // 2=IndexOnly, 3=IndexAndOverflow.
2923 static void SetIntSrc_A(comedi_device *dev, enc_private *k, uint16_t IntSource )
2925 // Reset any pending counter overflow or index captures.
2926 DEBIreplace( dev, k->MyCRB, (uint16_t)( ~CRBMSK_INTCTRL ), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A );
2928 // Program counter interrupt source.
2929 DEBIreplace( dev, k->MyCRA, ~CRAMSK_INTSRC_A, (uint16_t)( IntSource << CRABIT_INTSRC_A ) );
2931 // Update MISC2 interrupt enable mask.
2932 devpriv->CounterIntEnabs = ( devpriv->CounterIntEnabs & ~k->MyEventBits[3] ) | k->MyEventBits[IntSource];
2935 static void SetIntSrc_B( comedi_device *dev,enc_private *k, uint16_t IntSource )
2939 // Cache writeable CRB register image.
2940 crb = DEBIread(dev, k->MyCRB ) & ~CRBMSK_INTCTRL;
2942 // Reset any pending counter overflow or index captures.
2943 DEBIwrite(dev, k->MyCRB, (uint16_t)( crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B ) );
2945 // Program counter interrupt source.
2946 DEBIwrite(dev, k->MyCRB, (uint16_t)( ( crb & ~CRBMSK_INTSRC_B ) | ( IntSource << CRBBIT_INTSRC_B ) ) );
2948 // Update MISC2 interrupt enable mask.
2949 devpriv->CounterIntEnabs = ( devpriv->CounterIntEnabs & ~k->MyEventBits[3] ) | k->MyEventBits[IntSource];
2953 static uint16_t GetIntSrc_A( comedi_device *dev,enc_private *k )
2955 return ( DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A ) & 3;
2958 static uint16_t GetIntSrc_B( comedi_device *dev,enc_private *k )
2960 return ( DEBIread( dev, k->MyCRB) >> CRBBIT_INTSRC_B ) & 3;
2964 /////////////////////////////////////////////////////////////////////////
2965 // Return/set the clock multiplier.
2967 /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) */
2969 /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
2972 /* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) */
2974 /* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
2977 /* ////////////////////////////////////////////////////////////////////////// */
2978 /* // Return/set the clock polarity. */
2980 /* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value ) */
2982 /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
2985 /* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) */
2987 /* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
2990 /* /////////////////////////////////////////////////////////////////////// */
2991 /* // Return/set the clock source. */
2993 /* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value ) */
2995 /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
2998 /* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ) */
3000 /* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
3003 /* //////////////////////////////////////////////////////////////////////// */
3004 /* // Return/set the index polarity. */
3006 /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ) */
3008 /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
3011 /* static uint16_t GetIndexPol(comedi_device *dev, enc_private *k ) */
3013 /* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
3016 /* //////////////////////////////////////////////////////////////////////// */
3017 /* // Return/set the index source. */
3019 /* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value ) */
3021 /* DEBUG("SetIndexSrc: set index src enter 3700\n"); */
3022 /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
3025 /* static uint16_t GetIndexSrc(comedi_device *dev, enc_private *k ) */
3027 /* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
3030 ///////////////////////////////////////////////////////////////////
3031 // Generate an index pulse.
3033 static void PulseIndex_A( comedi_device *dev,enc_private *k )
3035 register uint16_t cra;
3038 DEBUG("PulseIndex_A: pulse index enter\n");
3040 cra = DEBIread(dev, k->MyCRA ); // Pulse index.
3041 DEBIwrite( dev, k->MyCRA, (uint16_t)( cra ^ CRAMSK_INDXPOL_A ) );
3042 DEBUG("PulseIndex_A: pulse index step1\n");
3043 DEBIwrite( dev, k->MyCRA, cra );
3046 static void PulseIndex_B( comedi_device *dev,enc_private *k )
3048 register uint16_t crb;
3050 crb = DEBIread(dev, k->MyCRB ) & ~CRBMSK_INTCTRL; // Pulse index.
3051 DEBIwrite(dev, k->MyCRB, (uint16_t)( crb ^ CRBMSK_INDXPOL_B ) );
3052 DEBIwrite(dev, k->MyCRB, crb);
3055 /////////////////////////////////////////////////////////
3056 // Write value into counter preload register.
3058 static void Preload(comedi_device *dev, enc_private *k, uint32_t value )
3060 DEBUG("Preload: preload enter\n");
3061 DEBIwrite(dev, (uint16_t)( k->MyLatchLsw ), (uint16_t) value ); // Write value to preload register.
3062 DEBUG("Preload: preload step 1\n");
3063 DEBIwrite(dev, (uint16_t)( k->MyLatchLsw + 2 ), (uint16_t)( value >> 16 ) );
3066 static void CountersInit(comedi_device *dev)
3070 uint16_t Setup = ( LOADSRC_INDX << BF_LOADSRC ) | // Preload upon
3072 ( INDXSRC_SOFT << BF_INDXSRC ) | // Disable hardware index.
3073 ( CLKSRC_COUNTER << BF_CLKSRC ) | // Operating mode is counter.
3074 ( CLKPOL_POS << BF_CLKPOL ) | // Active high clock.
3075 ( CNTDIR_UP << BF_CLKPOL ) | // Count direction is up.
3076 ( CLKMULT_1X << BF_CLKMULT ) | // Clock multiplier is 1x.
3077 ( CLKENAB_INDEX << BF_CLKENAB ); // Enabled by index
3079 // Disable all counter interrupts and clear any captured counter events.
3080 for ( chan = 0; chan < S626_ENCODER_CHANNELS; chan++ )
3083 k->SetMode(dev,k,Setup,TRUE);
3084 k->SetIntSrc( dev,k, 0 );
3085 k->ResetCapFlags(dev,k);
3086 k->SetEnable(dev,k,CLKENAB_ALWAYS);
3088 DEBUG("CountersInit: counters initialized \n");