s626.c 106 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
  comedi/drivers/s626.c
  Sensoray s626 Comedi driver

  COMEDI - Linux Control and Measurement Device Interface
  Copyright (C) 2000 David A. Schleef <ds@schleef.org>

  Based on Sensoray Model 626 Linux driver Version 0.2
  Copyright (C) 2002-2004 Sensoray Co., Inc.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

/*
Driver: s626
Description: Sensoray 626 driver
Devices: [Sensoray] 626 (s626)
Authors: Gianluca Palli <gpalli@deis.unibo.it>,
Updated: Fri, 15 Feb 2008 10:28:42 +0000
Status: experimental

Configuration options:
  [0] - PCI bus of device (optional)
  [1] - PCI slot of device (optional)
  If bus/slot is not specified, the first supported
  PCI device found will be used.

INSN_CONFIG instructions:
  analog input:
   none

  analog output:
   none

  digital channel:
   s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
   supported configuration options:
   INSN_CONFIG_DIO_QUERY
   COMEDI_INPUT
   COMEDI_OUTPUT

  encoder:
   Every channel must be configured before reading.

   Example code

   insn.insn=INSN_CONFIG;   //configuration instruction
   insn.n=1;                //number of operation (must be 1)
   insn.data=&initialvalue; //initial value loaded into encoder
63
				//during configuration
64
65
   insn.subdev=5;           //encoder subdevice
   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
66
							//to configure
67
68
69
70

   comedi_do_insn(cf,&insn); //executing configuration
*/

71
#include <linux/interrupt.h>
72
73
74
75
76
77
78
79
#include <linux/kernel.h>
#include <linux/types.h>

#include "../comedidev.h"

#include "comedi_fc.h"
#include "s626.h"

80
81
82
83
84
#define PCI_VENDOR_ID_S626 0x1131
#define PCI_DEVICE_ID_S626 0x7146
#define PCI_SUBVENDOR_ID_S626 0x6000
#define PCI_SUBDEVICE_ID_S626 0x0272

85
struct s626_board {
86
	const char *name;
87
88
89
90
	int vendor_id;
	int device_id;
	int subvendor_id;
	int subdevice_id;
91
92
93
94
95
96
97
	int ai_chans;
	int ai_bits;
	int ao_chans;
	int ao_bits;
	int dio_chans;
	int dio_banks;
	int enc_chans;
98
};
99

100
static const struct s626_board s626_boards[] = {
101
	{
102
	 .name = "s626",
103
104
105
106
	 .vendor_id = PCI_VENDOR_ID_S626,
	 .device_id = PCI_DEVICE_ID_S626,
	 .subvendor_id = PCI_SUBVENDOR_ID_S626,
	 .subdevice_id = PCI_SUBDEVICE_ID_S626,
107
108
109
110
111
112
113
114
	 .ai_chans = S626_ADC_CHANNELS,
	 .ai_bits = 14,
	 .ao_chans = S626_DAC_CHANNELS,
	 .ao_bits = 13,
	 .dio_chans = S626_DIO_CHANNELS,
	 .dio_banks = S626_DIO_BANKS,
	 .enc_chans = S626_ENCODER_CHANNELS,
	 }
115
116
};

117
#define thisboard ((const struct s626_board *)dev->board_ptr)
118

119
struct s626_private {
120
	struct pci_dev *pdev;
121
	void __iomem *base_addr;
122
123
	int got_regions;
	short allocatedBuf;
124
	uint8_t ai_cmd_running;	/*  ai_cmd is running */
Lucas De Marchi's avatar
Lucas De Marchi committed
125
	uint8_t ai_continous;	/*  continous acquisition */
126
	int ai_sample_count;	/*  number of samples to acquire */
127
128
129
130
131
132
133
134
	unsigned int ai_sample_timer;
	/*  time between samples in  units of the timer */
	int ai_convert_count;	/*  conversion counter */
	unsigned int ai_convert_timer;
	/*  time between conversion in  units of the timer */
	uint16_t CounterIntEnabs;
	/* Counter interrupt enable  mask for MISC2 register. */
	uint8_t AdcItems;	/* Number of items in ADC poll  list. */
135
	struct bufferDMA RPSBuf;	/* DMA buffer used to hold ADC (RPS1) program. */
136
	struct bufferDMA ANABuf;
137
138
139
140
141
142
143
144
145
146
147
	/* DMA buffer used to receive ADC data and hold DAC data. */
	uint32_t *pDacWBuf;
	/* Pointer to logical adrs of DMA buffer used to hold DAC  data. */
	uint16_t Dacpol;	/* Image of DAC polarity register. */
	uint8_t TrimSetpoint[12];	/* Images of TrimDAC setpoints */
	uint16_t ChargeEnabled;	/* Image of MISC2 Battery */
	/* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */
	uint16_t WDInterval;	/* Image of MISC2 watchdog interval control bits. */
	uint32_t I2CAdrs;
	/* I2C device address for onboard EEPROM (board rev dependent). */
	/*   short         I2Cards; */
148
	unsigned int ao_readback[S626_DAC_CHANNELS];
149
};
150

151
struct dio_private {
152
153
154
155
156
157
158
159
160
	uint16_t RDDIn;
	uint16_t WRDOut;
	uint16_t RDEdgSel;
	uint16_t WREdgSel;
	uint16_t RDCapSel;
	uint16_t WRCapSel;
	uint16_t RDCapFlg;
	uint16_t RDIntSel;
	uint16_t WRIntSel;
161
};
162

163
static struct dio_private dio_private_A = {
164
165
166
167
168
169
170
171
172
	.RDDIn = LP_RDDINA,
	.WRDOut = LP_WRDOUTA,
	.RDEdgSel = LP_RDEDGSELA,
	.WREdgSel = LP_WREDGSELA,
	.RDCapSel = LP_RDCAPSELA,
	.WRCapSel = LP_WRCAPSELA,
	.RDCapFlg = LP_RDCAPFLGA,
	.RDIntSel = LP_RDINTSELA,
	.WRIntSel = LP_WRINTSELA,
173
174
};

175
static struct dio_private dio_private_B = {
176
177
178
179
180
181
182
183
184
	.RDDIn = LP_RDDINB,
	.WRDOut = LP_WRDOUTB,
	.RDEdgSel = LP_RDEDGSELB,
	.WREdgSel = LP_WREDGSELB,
	.RDCapSel = LP_RDCAPSELB,
	.WRCapSel = LP_WRCAPSELB,
	.RDCapFlg = LP_RDCAPFLGB,
	.RDIntSel = LP_RDINTSELB,
	.WRIntSel = LP_WRINTSELB,
185
186
};

187
static struct dio_private dio_private_C = {
188
189
190
191
192
193
194
195
196
	.RDDIn = LP_RDDINC,
	.WRDOut = LP_WRDOUTC,
	.RDEdgSel = LP_RDEDGSELC,
	.WREdgSel = LP_WREDGSELC,
	.RDCapSel = LP_RDCAPSELC,
	.WRCapSel = LP_WRCAPSELC,
	.RDCapFlg = LP_RDCAPFLGC,
	.RDIntSel = LP_RDINTSELC,
	.WRIntSel = LP_WRINTSELC,
197
198
199
};

/* to group dio devices (48 bits mask and data are not allowed ???)
200
static struct dio_private *dio_private_word[]={
201
202
203
204
205
206
  &dio_private_A,
  &dio_private_B,
  &dio_private_C,
};
*/

207
208
#define devpriv ((struct s626_private *)dev->private)
#define diopriv ((struct dio_private *)s->private)
209

210
/* ioctl routines */
211
212
213
static int s626_ai_insn_config(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn, unsigned int *data);
214
/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
215
216
217
static int s626_ai_insn_read(struct comedi_device *dev,
			     struct comedi_subdevice *s,
			     struct comedi_insn *insn, unsigned int *data);
218
static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
219
220
221
222
static int s626_ai_cmdtest(struct comedi_device *dev,
			   struct comedi_subdevice *s, struct comedi_cmd *cmd);
static int s626_ai_cancel(struct comedi_device *dev,
			  struct comedi_subdevice *s);
223
static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
224
			 struct comedi_insn *insn, unsigned int *data);
225
static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
226
227
228
229
230
231
232
			 struct comedi_insn *insn, unsigned int *data);
static int s626_dio_insn_bits(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn, unsigned int *data);
static int s626_dio_insn_config(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_insn *insn, unsigned int *data);
233
234
static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan);
static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop,
235
			      unsigned int mask);
236
static int s626_dio_clear_irq(struct comedi_device *dev);
237
238
239
240
241
242
243
244
245
static int s626_enc_insn_config(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_insn *insn, unsigned int *data);
static int s626_enc_insn_read(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn, unsigned int *data);
static int s626_enc_insn_write(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn, unsigned int *data);
246
static int s626_ns_to_timer(int *nanosec, int round_mode);
247
static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd);
248
249
static int s626_ai_inttrig(struct comedi_device *dev,
			   struct comedi_subdevice *s, unsigned int trignum);
250
static irqreturn_t s626_irq_handler(int irq, void *d);
251
static unsigned int s626_ai_reg_to_uint(int data);
252
/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data); */
253

254
/* end ioctl routines */
255

256
/* internal routines */
257
static void s626_dio_init(struct comedi_device *dev);
258
static void ResetADC(struct comedi_device *dev, uint8_t * ppl);
259
260
static void LoadTrimDACs(struct comedi_device *dev);
static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
261
			 uint8_t DacData);
262
263
264
265
266
267
268
269
270
static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr);
static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val);
static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata);
static void SendDAC(struct comedi_device *dev, uint32_t val);
static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage);
static void DEBItransfer(struct comedi_device *dev);
static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr);
static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata);
static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
271
272
273
			uint16_t wdata);
static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
		      size_t bsize);
274

275
/*  COUNTER OBJECT ------------------------------------------------ */
276
struct enc_private {
277
	/*  Pointers to functions that differ for A and B counters: */
278
279
280
281
282
283
284
285
286
287
	uint16_t(*GetEnable) (struct comedi_device *dev, struct enc_private *);	/* Return clock enable. */
	uint16_t(*GetIntSrc) (struct comedi_device *dev, struct enc_private *);	/* Return interrupt source. */
	uint16_t(*GetLoadTrig) (struct comedi_device *dev, struct enc_private *);	/* Return preload trigger source. */
	uint16_t(*GetMode) (struct comedi_device *dev, struct enc_private *);	/* Return standardized operating mode. */
	void (*PulseIndex) (struct comedi_device *dev, struct enc_private *);	/* Generate soft index strobe. */
	void (*SetEnable) (struct comedi_device *dev, struct enc_private *, uint16_t enab);	/* Program clock enable. */
	void (*SetIntSrc) (struct comedi_device *dev, struct enc_private *, uint16_t IntSource);	/* Program interrupt source. */
	void (*SetLoadTrig) (struct comedi_device *dev, struct enc_private *, uint16_t Trig);	/* Program preload trigger source. */
	void (*SetMode) (struct comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
	void (*ResetCapFlags) (struct comedi_device *dev, struct enc_private *);	/* Reset event capture flags. */
288
289
290
291
292
293

	uint16_t MyCRA;		/*    Address of CRA register. */
	uint16_t MyCRB;		/*    Address of CRB register. */
	uint16_t MyLatchLsw;	/*    Address of Latch least-significant-word */
	/*    register. */
	uint16_t MyEventBits[4];	/*    Bit translations for IntSrc -->RDMISC2. */
294
};
295

296
#define encpriv ((struct enc_private *)(dev->subdevices+5)->private)
297

298
/* counters routines */
299
300
static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
			    int tick);
301
302
303
304
305
static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k);
static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k);
static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k);
static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k);
static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k);
306
307
308
309
310
311
312
313
static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
		      uint16_t Setup, uint16_t DisableIntSrc);
static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
		      uint16_t Setup, uint16_t DisableIntSrc);
static void SetEnable_A(struct comedi_device *dev, struct enc_private *k,
			uint16_t enab);
static void SetEnable_B(struct comedi_device *dev, struct enc_private *k,
			uint16_t enab);
314
315
316
static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k);
static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k);
static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
317
			   uint16_t value);
318
/* static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ); */
319
320
321
322
static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k,
			  uint16_t Trig);
static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k,
			  uint16_t Trig);
323
324
325
static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k);
static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k);
static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
326
			uint16_t IntSource);
327
static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
328
			uint16_t IntSource);
329
330
331
332
333
334
335
336
337
338
339
340
static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k);
static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k);
/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) ; */
/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) ; */
/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ); */
/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) ; */
/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k );  */
/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
/* static uint16_t GetIndexSrc( struct comedi_device *dev,struct enc_private *k );  */
static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k);
static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k);
341
342
static void Preload(struct comedi_device *dev, struct enc_private *k,
		    uint32_t value);
343
static void CountersInit(struct comedi_device *dev);
344
/* end internal routines */
345

346
/*  Counter objects constructor. */
347

348
/*  Counter overflow/index event flag masks for RDMISC2. */
349
350
#define INDXMASK(C)		(1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
#define OVERMASK(C)		(1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
351
352
#define EVBITS(C)		{ 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }

353
354
/*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
355

356
357
/* struct enc_private; */
static struct enc_private enc_private_data[] = {
358
	{
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
	 .GetEnable = GetEnable_A,
	 .GetIntSrc = GetIntSrc_A,
	 .GetLoadTrig = GetLoadTrig_A,
	 .GetMode = GetMode_A,
	 .PulseIndex = PulseIndex_A,
	 .SetEnable = SetEnable_A,
	 .SetIntSrc = SetIntSrc_A,
	 .SetLoadTrig = SetLoadTrig_A,
	 .SetMode = SetMode_A,
	 .ResetCapFlags = ResetCapFlags_A,
	 .MyCRA = LP_CR0A,
	 .MyCRB = LP_CR0B,
	 .MyLatchLsw = LP_CNTR0ALSW,
	 .MyEventBits = EVBITS(0),
	 },
374
	{
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
	 .GetEnable = GetEnable_A,
	 .GetIntSrc = GetIntSrc_A,
	 .GetLoadTrig = GetLoadTrig_A,
	 .GetMode = GetMode_A,
	 .PulseIndex = PulseIndex_A,
	 .SetEnable = SetEnable_A,
	 .SetIntSrc = SetIntSrc_A,
	 .SetLoadTrig = SetLoadTrig_A,
	 .SetMode = SetMode_A,
	 .ResetCapFlags = ResetCapFlags_A,
	 .MyCRA = LP_CR1A,
	 .MyCRB = LP_CR1B,
	 .MyLatchLsw = LP_CNTR1ALSW,
	 .MyEventBits = EVBITS(1),
	 },
390
	{
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
	 .GetEnable = GetEnable_A,
	 .GetIntSrc = GetIntSrc_A,
	 .GetLoadTrig = GetLoadTrig_A,
	 .GetMode = GetMode_A,
	 .PulseIndex = PulseIndex_A,
	 .SetEnable = SetEnable_A,
	 .SetIntSrc = SetIntSrc_A,
	 .SetLoadTrig = SetLoadTrig_A,
	 .SetMode = SetMode_A,
	 .ResetCapFlags = ResetCapFlags_A,
	 .MyCRA = LP_CR2A,
	 .MyCRB = LP_CR2B,
	 .MyLatchLsw = LP_CNTR2ALSW,
	 .MyEventBits = EVBITS(2),
	 },
406
	{
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
	 .GetEnable = GetEnable_B,
	 .GetIntSrc = GetIntSrc_B,
	 .GetLoadTrig = GetLoadTrig_B,
	 .GetMode = GetMode_B,
	 .PulseIndex = PulseIndex_B,
	 .SetEnable = SetEnable_B,
	 .SetIntSrc = SetIntSrc_B,
	 .SetLoadTrig = SetLoadTrig_B,
	 .SetMode = SetMode_B,
	 .ResetCapFlags = ResetCapFlags_B,
	 .MyCRA = LP_CR0A,
	 .MyCRB = LP_CR0B,
	 .MyLatchLsw = LP_CNTR0BLSW,
	 .MyEventBits = EVBITS(3),
	 },
422
	{
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
	 .GetEnable = GetEnable_B,
	 .GetIntSrc = GetIntSrc_B,
	 .GetLoadTrig = GetLoadTrig_B,
	 .GetMode = GetMode_B,
	 .PulseIndex = PulseIndex_B,
	 .SetEnable = SetEnable_B,
	 .SetIntSrc = SetIntSrc_B,
	 .SetLoadTrig = SetLoadTrig_B,
	 .SetMode = SetMode_B,
	 .ResetCapFlags = ResetCapFlags_B,
	 .MyCRA = LP_CR1A,
	 .MyCRB = LP_CR1B,
	 .MyLatchLsw = LP_CNTR1BLSW,
	 .MyEventBits = EVBITS(4),
	 },
438
	{
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
	 .GetEnable = GetEnable_B,
	 .GetIntSrc = GetIntSrc_B,
	 .GetLoadTrig = GetLoadTrig_B,
	 .GetMode = GetMode_B,
	 .PulseIndex = PulseIndex_B,
	 .SetEnable = SetEnable_B,
	 .SetIntSrc = SetIntSrc_B,
	 .SetLoadTrig = SetLoadTrig_B,
	 .SetMode = SetMode_B,
	 .ResetCapFlags = ResetCapFlags_B,
	 .MyCRA = LP_CR2A,
	 .MyCRB = LP_CR2B,
	 .MyLatchLsw = LP_CNTR2BLSW,
	 .MyEventBits = EVBITS(5),
	 },
454
455
};

456
457
/*  enab/disable a function or test status bit(s) that are accessed */
/*  through Main Control Registers 1 or 2. */
458
#define MC_ENABLE(REGADRS, CTRLWORD)	writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS))
459

460
#define MC_DISABLE(REGADRS, CTRLWORD)	writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS))
461

462
#define MC_TEST(REGADRS, CTRLWORD)	((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0)
463
464
465

/* #define WR7146(REGARDS,CTRLWORD)
    writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
466
#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS))
467
468
469
470
471

/* #define RR7146(REGARDS)
    readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
#define RR7146(REGARDS)		readl(devpriv->base_addr+(REGARDS))

472
#define BUGFIX_STREG(REGADRS)   (REGADRS - 4)
473

474
/*  Write a time slot control record to TSL2. */
475
476
#define VECTPORT(VECTNUM)		(P_TSL2 + ((VECTNUM) << 2))
#define SETVECT(VECTNUM, VECTVAL)	WR7146(VECTPORT(VECTNUM), (VECTVAL))
477

478
/*  Code macros used for constructing I2C command bytes. */
479
480
481
#define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
#define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
#define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
482

483
static const struct comedi_lrange s626_range_table = { 2, {
484
485
486
							   RANGE(-5, 5),
							   RANGE(-10, 10),
							   }
487
488
};

489
static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
490
491
492
493
494
495
496
497
498
499
500
{
/*   uint8_t	PollList; */
/*   uint16_t	AdcData; */
/*   uint16_t	StartVal; */
/*   uint16_t	index; */
/*   unsigned int data[16]; */
	int result;
	int i;
	int ret;
	resource_size_t resourceStart;
	dma_addr_t appdma;
501
	struct comedi_subdevice *s;
502
	struct pci_dev *pdev = NULL;
503

504
	if (alloc_private(dev, sizeof(struct s626_private)) < 0)
505
506
		return -ENOMEM;

507
	for (i = 0; i < ARRAY_SIZE(s626_boards) && !pdev; i++) {
508
		do {
509
510
511
512
			pdev = pci_get_subsys(s626_boards[i].vendor_id,
					      s626_boards[i].device_id,
					      s626_boards[i].subvendor_id,
					      s626_boards[i].subdevice_id,
513
					      pdev);
514
515

			if ((it->options[0] || it->options[1]) && pdev) {
516
				/* matches requested bus/slot */
517
518
519
520
				if (pdev->bus->number == it->options[0] &&
				    PCI_SLOT(pdev->devfn) == it->options[1])
					break;
			} else
521
				break;
522
		} while (1);
523
524
525
526
	}
	devpriv->pdev = pdev;

	if (pdev == NULL) {
527
		printk(KERN_ERR "s626_attach: Board not present!!!\n");
528
529
530
		return -ENODEV;
	}

531
532
	result = comedi_pci_enable(pdev, "s626");
	if (result < 0) {
533
		printk(KERN_ERR "s626_attach: comedi_pci_enable fails\n");
534
535
536
537
538
539
540
541
		return -ENODEV;
	}
	devpriv->got_regions = 1;

	resourceStart = pci_resource_start(devpriv->pdev, 0);

	devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
	if (devpriv->base_addr == NULL) {
542
		printk(KERN_ERR "s626_attach: IOREMAP failed\n");
543
544
545
546
		return -ENODEV;
	}

	if (devpriv->base_addr) {
547
		/* disable master interrupt */
548
549
		writel(0, devpriv->base_addr + P_IER);

550
		/* soft reset */
551
552
		writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);

553
		/* DMA FIXME DMA// */
554
555
		DEBUG("s626_attach: DMA ALLOCATION\n");

556
		/* adc buffer allocation */
557
558
		devpriv->allocatedBuf = 0;

559
		devpriv->ANABuf.LogicalBase =
560
		    pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
561
562

		if (devpriv->ANABuf.LogicalBase == NULL) {
563
			printk(KERN_ERR "s626_attach: DMA Memory mapping error\n");
564
565
566
567
568
			return -ENOMEM;
		}

		devpriv->ANABuf.PhysicalBase = appdma;

569
570
571
572
		DEBUG
		    ("s626_attach: AllocDMAB ADC Logical=%p, bsize=%d, Physical=0x%x\n",
		     devpriv->ANABuf.LogicalBase, DMABUF_SIZE,
		     (uint32_t) devpriv->ANABuf.PhysicalBase);
573
574
575

		devpriv->allocatedBuf++;

576
		devpriv->RPSBuf.LogicalBase =
577
		    pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
578
579

		if (devpriv->RPSBuf.LogicalBase == NULL) {
580
			printk(KERN_ERR "s626_attach: DMA Memory mapping error\n");
581
582
583
584
585
			return -ENOMEM;
		}

		devpriv->RPSBuf.PhysicalBase = appdma;

586
587
588
589
		DEBUG
		    ("s626_attach: AllocDMAB RPS Logical=%p, bsize=%d, Physical=0x%x\n",
		     devpriv->RPSBuf.LogicalBase, DMABUF_SIZE,
		     (uint32_t) devpriv->RPSBuf.PhysicalBase);
590
591
592
593
594
595
596
597

		devpriv->allocatedBuf++;

	}

	dev->board_ptr = s626_boards;
	dev->board_name = thisboard->name;

598
599
600
	ret = comedi_alloc_subdevices(dev, 6);
	if (ret)
		return ret;
601
602
603
604

	dev->iobase = (unsigned long)devpriv->base_addr;
	dev->irq = devpriv->pdev->irq;

605
	/* set up interrupt handler */
606
	if (dev->irq == 0) {
607
		printk(KERN_ERR " unknown irq (bad)\n");
608
	} else {
609
610
		ret = request_irq(dev->irq, s626_irq_handler, IRQF_SHARED,
				  "s626", dev);
611
612

		if (ret < 0) {
613
			printk(KERN_ERR " irq not available\n");
614
615
616
617
			dev->irq = 0;
		}
	}

618
	DEBUG("s626_attach: -- it opts  %d,%d --\n",
619
	      it->options[0], it->options[1]);
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

	s = dev->subdevices + 0;
	/* analog input subdevice */
	dev->read_subdev = s;
	/* we support single-ended (ground) and differential */
	s->type = COMEDI_SUBD_AI;
	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
	s->n_chan = thisboard->ai_chans;
	s->maxdata = (0xffff >> 2);
	s->range_table = &s626_range_table;
	s->len_chanlist = thisboard->ai_chans;	/* This is the maximum chanlist
						   length that the board can
						   handle */
	s->insn_config = s626_ai_insn_config;
	s->insn_read = s626_ai_insn_read;
	s->do_cmd = s626_ai_cmd;
	s->do_cmdtest = s626_ai_cmdtest;
	s->cancel = s626_ai_cancel;

	s = dev->subdevices + 1;
	/* analog output subdevice */
	s->type = COMEDI_SUBD_AO;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
	s->n_chan = thisboard->ao_chans;
	s->maxdata = (0x3fff);
	s->range_table = &range_bipolar10;
	s->insn_write = s626_ao_winsn;
	s->insn_read = s626_ao_rinsn;

	s = dev->subdevices + 2;
	/* digital I/O subdevice */
	s->type = COMEDI_SUBD_DIO;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
	s->n_chan = S626_DIO_CHANNELS;
	s->maxdata = 1;
	s->io_bits = 0xffff;
	s->private = &dio_private_A;
	s->range_table = &range_digital;
	s->insn_config = s626_dio_insn_config;
	s->insn_bits = s626_dio_insn_bits;

	s = dev->subdevices + 3;
	/* digital I/O subdevice */
	s->type = COMEDI_SUBD_DIO;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
	s->n_chan = 16;
	s->maxdata = 1;
	s->io_bits = 0xffff;
	s->private = &dio_private_B;
	s->range_table = &range_digital;
	s->insn_config = s626_dio_insn_config;
	s->insn_bits = s626_dio_insn_bits;

	s = dev->subdevices + 4;
	/* digital I/O subdevice */
	s->type = COMEDI_SUBD_DIO;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
	s->n_chan = 16;
	s->maxdata = 1;
	s->io_bits = 0xffff;
	s->private = &dio_private_C;
	s->range_table = &range_digital;
	s->insn_config = s626_dio_insn_config;
	s->insn_bits = s626_dio_insn_bits;

	s = dev->subdevices + 5;
	/* encoder (counter) subdevice */
	s->type = COMEDI_SUBD_COUNTER;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
	s->n_chan = thisboard->enc_chans;
	s->private = enc_private_data;
	s->insn_config = s626_enc_insn_config;
	s->insn_read = s626_enc_insn_read;
	s->insn_write = s626_enc_insn_write;
	s->maxdata = 0xffffff;
	s->range_table = &range_unknown;

697
	/* stop ai_command */
698
699
700
701
702
703
	devpriv->ai_cmd_running = 0;

	if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) {
		dma_addr_t pPhysBuf;
		uint16_t chan;

704
		/*  enab DEBI and audio pins, enable I2C interface. */
705
		MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
706
707
		/*  Configure DEBI operating mode. */
		WR7146(P_DEBICFG, DEBI_CFG_SLAVE16	/*  Local bus is 16 */
708
709
710
711
712
713
714
715
716
		       /*  bits wide. */
		       | (DEBI_TOUT << DEBI_CFG_TOUT_BIT)

		       /*  Declare DEBI */
		       /*  transfer timeout */
		       /*  interval. */
		       |DEBI_SWAP	/*  Set up byte lane */
		       /*  steering. */
		       | DEBI_CFG_INTEL);	/*  Intel-compatible */
717
718
		/*  local bus (DEBI */
		/*  never times out). */
719
		DEBUG("s626_attach: %d debi init -- %d\n",
720
721
722
723
		      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);
724

725
726
		/* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */
		/* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */
727

728
729
		/*  Paging is disabled. */
		WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);	/*  Disable MMU paging. */
730

731
		/*  Init GPIO so that ADC Start* is negated. */
732
733
		WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);

734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
		/* IsBoardRevA is a boolean that indicates whether the board is RevA.
		 *
		 * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
		 * EEPROM ADDRESS SELECTION.  Initialize the I2C interface, which
		 * is used to access the onboard serial EEPROM.  The EEPROM's I2C
		 * DeviceAddress is hardwired to a value that is dependent on the
		 * 626 board revision.  On all board revisions, the EEPROM stores
		 * TrimDAC calibration constants for analog I/O.  On RevB and
		 * higher boards, the DeviceAddress is hardwired to 0 to enable
		 * the EEPROM to also store the PCI SubVendorID and SubDeviceID;
		 * this is the address at which the SAA7146 expects a
		 * configuration EEPROM to reside.  On RevA boards, the EEPROM
		 * device address, which is hardwired to 4, prevents the SAA7146
		 * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
		 * default values, instead.
		 */
750
751
752
753
754
755
756
757
758
759
760
761
762
763

		/*     devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */
		/*  DeviceType (0xA0) */
		/*  and DeviceAddress<<1. */

		devpriv->I2CAdrs = 0xA0;	/*  I2C device address for onboard */
		/*  eeprom(revb) */

		/*  Issue an I2C ABORT command to halt any I2C operation in */
		/* progress and reset BUSY flag. */
		WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
		/*  Write I2C control: abort any I2C activity. */
		MC_ENABLE(P_MC2, MC2_UPLD_IIC);
		/*  Invoke command  upload */
764
		while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0)
765
			;
766
767
768
769
		/*  and wait for upload to complete. */

		/* Per SAA7146 data sheet, write to STATUS reg twice to
		 * reset all  I2C error flags. */
770
		for (i = 0; i < 2; i++) {
771
772
773
			WR7146(P_I2CSTAT, I2C_CLKSEL);
			/*  Write I2C control: reset  error flags. */
			MC_ENABLE(P_MC2, MC2_UPLD_IIC);	/*  Invoke command upload */
774
			while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
775
				;
776
			/* and wait for upload to complete. */
777
778
		}

779
780
781
782
783
784
		/* Init audio interface functional attributes: set DAC/ADC
		 * serial clock rates, invert DAC serial clock so that
		 * DAC data setup times are satisfied, enable DAC serial
		 * clock out.
		 */

785
786
		WR7146(P_ACON2, ACON2_INIT);

787
788
789
790
791
792
793
794
795
796
		/* Set up TSL1 slot list, which is used to control the
		 * accumulation of ADC data: RSD1 = shift data in on SD1.
		 * SIB_A1  = store data uint8_t at next available location in
		 * FB BUFFER1  register. */
		WR7146(P_TSL1, RSD1 | SIB_A1);
		/*  Fetch ADC high data uint8_t. */
		WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
		/*  Fetch ADC low data uint8_t; end of TSL1. */

		/*  enab TSL1 slot list so that it executes all the time. */
797
798
		WR7146(P_ACON1, ACON1_ADCSTART);

799
		/*  Initialize RPS registers used for ADC. */
800

801
		/* Physical start of RPS program. */
802
803
		WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);

804
805
806
		WR7146(P_RPSPAGE1, 0);
		/*  RPS program performs no explicit mem writes. */
		WR7146(P_RPS1_TOUT, 0);	/*  Disable RPS timeouts. */
807

808
809
810
811
812
813
		/* SAA7146 BUG WORKAROUND.  Initialize SAA7146 ADC interface
		 * to a known state by invoking ADCs until FB BUFFER 1
		 * register shows that it is correctly receiving ADC data.
		 * This is necessary because the SAA7146 ADC interface does
		 * not start up in a defined state after a PCI reset.
		 */
814

815
816
817
/*     PollList = EOPL;		// Create a simple polling */
/*				// list for analog input */
/*				// channel 0. */
818
819
820
/*     ResetADC( dev, &PollList ); */

/*     s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
821
822
/*							//Get initial ADC */
/*							//value. */
823
824
825
826
827
828
829
830
831
832
833
834

/*     StartVal = data[0]; */

/*     // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
/*     // Invoke ADCs until the new ADC value differs from the initial */
/*     // value or a timeout occurs.  The timeout protects against the */
/*     // possibility that the driver is restarting and the ADC data is a */
/*     // fixed value resulting from the applied ADC analog input being */
/*     // unusually quiet or at the rail. */

/*     for ( index = 0; index < 500; index++ ) */
/*       { */
835
836
837
838
/*	s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
/*	AdcData = data[0];	//ReadADC(  &AdcData ); */
/*	if ( AdcData != StartVal ) */
/*		break; */
839
840
/*       } */

841
		/*  end initADC */
842

843
		/*  init the DAC interface */
844

845
846
847
		/* Init Audio2's output DMAC attributes: burst length = 1
		 * DWORD,  threshold = 1 DWORD.
		 */
848
849
		WR7146(P_PCI_BT_A, 0);

850
851
852
853
		/* Init Audio2's output DMA physical addresses.  The protection
		 * address is set to 1 DWORD past the base address so that a
		 * single DWORD will be transferred each time a DMA transfer is
		 * enabled. */
854
855

		pPhysBuf =
856
857
		    devpriv->ANABuf.PhysicalBase +
		    (DAC_WDMABUF_OS * sizeof(uint32_t));
858

859
860
		WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);	/*  Buffer base adrs. */
		WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t)));	/*  Protection address. */
861

862
863
		/* Cache Audio2's output DMA buffer logical address.  This is
		 * where DAC data is buffered for A2 output DMA transfers. */
864
		devpriv->pDacWBuf =
865
		    (uint32_t *) devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS;
866

867
868
869
870
871
		/* Audio2's output channels does not use paging.  The protection
		 * violation handling bit is set so that the DMAC will
		 * automatically halt and its PCI address pointer will be reset
		 * when the protection address is reached. */

872
873
		WR7146(P_PAGEA2_OUT, 8);

874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
		/* Initialize time slot list 2 (TSL2), which is used to control
		 * the clock generation for and serialization of data to be sent
		 * to the DAC devices.  Slot 0 is a NOP that is used to trap TSL
		 * execution; this permits other slots to be safely modified
		 * without first turning off the TSL sequencer (which is
		 * apparently impossible to do).  Also, SD3 (which is driven by a
		 * pull-up resistor) is shifted in and stored to the MSB of
		 * FB_BUFFER2 to be used as evidence that the slot sequence has
		 * not yet finished executing.
		 */

		SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
		/*  Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */

		/* Initialize slot 1, which is constant.  Slot 1 causes a
		 * DWORD to be transferred from audio channel 2's output FIFO
		 * to the FIFO's output buffer so that it can be serialized
		 * and sent to the DAC during subsequent slots.  All remaining
		 * slots are dynamically populated as required by the target
		 * DAC device.
		 */
		SETVECT(1, LF_A2);
		/*  Slot 1: Fetch DWORD from Audio2's output FIFO. */

		/*  Start DAC's audio interface (TSL2) running. */
899
900
		WR7146(P_ACON1, ACON1_DACSTART);

901
		/* end init DAC interface */
902

903
904
905
906
		/* Init Trim DACs to calibrated values.  Do it twice because the
		 * SAA7146 audio channel does not always reset properly and
		 * sometimes causes the first few TrimDAC writes to malfunction.
		 */
907
908

		LoadTrimDACs(dev);
909
		LoadTrimDACs(dev);	/*  Insurance. */
910

911
912
913
914
915
		/* Manually init all gate array hardware in case this is a soft
		 * reset (we have no way of determining whether this is a warm
		 * or cold start).  This is necessary because the gate array will
		 * reset only in response to a PCI hard reset; there is no soft
		 * reset function. */
916

917
918
919
		/* Init all DAC outputs to 0V and init all DAC setpoint and
		 * polarity images.
		 */
920
921
922
		for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
			SetDAC(dev, chan, 0);

923
924
925
926
		/* Init image of WRMISC2 Battery Charger Enabled control bit.
		 * This image is used when the state of the charger control bit,
		 * which has no direct hardware readback mechanism, is queried.
		 */
927
928
		devpriv->ChargeEnabled = 0;

929
930
931
932
		/* Init image of watchdog timer interval in WRMISC2.  This image
		 * maintains the value of the control bits of MISC2 are
		 * continuously reset to zero as long as the WD timer is disabled.
		 */
933
934
		devpriv->WDInterval = 0;

935
936
937
938
		/* Init Counter Interrupt enab mask for RDMISC2.  This mask is
		 * applied against MISC2 when testing to determine which timer
		 * events are requesting interrupt service.
		 */
939
940
		devpriv->CounterIntEnabs = 0;

941
		/*  Init counters. */
942
943
		CountersInit(dev);

944
945
946
947
948
		/* Without modifying the state of the Battery Backup enab, disable
		 * the watchdog timer, set DIO channels 0-5 to operate in the
		 * standard DIO (vs. counter overflow) mode, disable the battery
		 * charger, and reset the watchdog interval selector to zero.
		 */
949
		WriteMISC2(dev, (uint16_t) (DEBIread(dev,
950
951
						     LP_RDMISC2) &
					    MISC2_BATT_ENABLE));
952

953
		/*  Initialize the digital I/O subsystem. */
954
955
		s626_dio_init(dev);

956
957
		/* enable interrupt test */
		/*  writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */
958
959
960
	}

	DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor,
961
	      (uint32_t) devpriv->base_addr);
962
963
964
965

	return 1;
}

966
static unsigned int s626_ai_reg_to_uint(int data)
967
{
968
	unsigned int tempdata;
969
970
971
972
973
974
975
976
977
978

	tempdata = (data >> 18);
	if (tempdata & 0x2000)
		tempdata &= 0x1fff;
	else
		tempdata += (1 << 13);

	return tempdata;
}

979
/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */
980
981
982
/*   return 0; */
/* } */

983
static irqreturn_t s626_irq_handler(int irq, void *d)
984
{
985
	struct comedi_device *dev = d;
986
	struct comedi_subdevice *s;
987
	struct comedi_cmd *cmd;
988
	struct enc_private *k;
989
990
991
992
	unsigned long flags;
	int32_t *readaddr;
	uint32_t irqtype, irqstatus;
	int i = 0;
993
	short tempdata;
994
995
996
	uint8_t group;
	uint16_t irqbit;

Lucas De Marchi's avatar
Lucas De Marchi committed
997
	DEBUG("s626_irq_handler: interrupt request received!!!\n");
998
999
1000

	if (dev->attached == 0)
		return IRQ_NONE;
For faster browsing, not all history is shown. View entire blame