staging: comedi: comedi_test: simplify time since last AI scan
[deliverable/linux.git] / drivers / staging / comedi / drivers / adl_pci9118.c
CommitLineData
3063d6de
MD
1/*
2 * comedi/drivers/adl_pci9118.c
3 *
4 * hardware driver for ADLink cards:
5 * card: PCI-9118DG, PCI-9118HG, PCI-9118HR
6 * driver: pci9118dg, pci9118hg, pci9118hr
7 *
8 * Author: Michal Dobes <dobes@tesnet.cz>
9 *
c8ea69c4 10 */
3063d6de 11
c8ea69c4
SA
12/*
13 * Driver: adl_pci9118
14 * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
15 * Author: Michal Dobes <dobes@tesnet.cz>
16 * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
17 * PCI-9118HR (pci9118hr)
18 * Status: works
19 *
20 * This driver supports AI, AO, DI and DO subdevices.
21 * AI subdevice supports cmd and insn interface,
22 * other subdevices support only insn interface.
23 * For AI:
24 * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
25 * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
26 * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
27 * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
28 * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
29 * - If return value of cmdtest is 5 then you've bad channel list
30 * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
31 * ranges).
32 *
33 * There are some hardware limitations:
34 * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
35 * ended inputs.
36 * b) DMA transfers must have the length aligned to two samples (32 bit),
37 * so there is some problems if cmd->chanlist_len is odd. This driver tries
38 * bypass this with adding one sample to the end of the every scan and discard
c25dec57
IA
39 * it on output but this can't be used if cmd->scan_begin_src=TRIG_FOLLOW
40 * and is used flag CMDF_WAKE_EOS, then driver switch to interrupt driven mode
c8ea69c4
SA
41 * with interrupt after every sample.
42 * c) If isn't used DMA then you can use only mode where
43 * cmd->scan_begin_src=TRIG_FOLLOW.
44 *
45 * Configuration options:
46 * [0] - PCI bus of device (optional)
47 * [1] - PCI slot of device (optional)
48 * If bus/slot is not specified, then first available PCI
49 * card will be used.
50 * [2] - 0= standard 8 DIFF/16 SE channels configuration
51 * n = external multiplexer connected, 1 <= n <= 256
cb578327 52 * [3] - ignored
c8ea69c4
SA
53 * [4] - sample&hold signal - card can generate signal for external S&H board
54 * 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
55 * 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
56 * long delay is requested in ns and sign polarity of the hold
57 * (in this case external multiplexor can serve only 128 channels)
9e531485 58 * [5] - ignored
c8ea69c4 59 */
15358a7f
IA
60
61/*
62 * FIXME
63 *
64 * All the supported boards have the same PCI vendor and device IDs, so
65 * auto-attachment of PCI devices will always find the first board type.
66 *
67 * Perhaps the boards have different subdevice IDs that we could use to
68 * distinguish them?
69 *
70 * Need some device attributes so the board type can be corrected after
71 * attachment if necessary, and possibly to set other options supported by
72 * manual attachment.
73 */
3063d6de 74
ce157f80 75#include <linux/module.h>
3063d6de 76#include <linux/delay.h>
5a0e3ad6 77#include <linux/gfp.h>
70265d24 78#include <linux/interrupt.h>
845d131e 79#include <linux/io.h>
3063d6de 80
b2ad146a 81#include "../comedi_pci.h"
33782dd5 82
3063d6de 83#include "amcc_s5933.h"
a9da9d20 84#include "comedi_8254.h"
3063d6de 85
6dc35953
HS
86/*
87 * PCI BAR2 Register map (dev->iobase)
88 */
a9da9d20 89#define PCI9118_TIMER_BASE 0x00
7cc1110d 90#define PCI9118_AI_FIFO_REG 0x10
c6908517 91#define PCI9118_AO_REG(x) (0x10 + ((x) * 4))
602c1729 92#define PCI9118_AI_STATUS_REG 0x18
7db6ed68
HS
93#define PCI9118_AI_STATUS_NFULL BIT(8) /* 0=FIFO full (fatal) */
94#define PCI9118_AI_STATUS_NHFULL BIT(7) /* 0=FIFO half full */
95#define PCI9118_AI_STATUS_NEPTY BIT(6) /* 0=FIFO empty */
96#define PCI9118_AI_STATUS_ACMP BIT(5) /* 1=about trigger complete */
97#define PCI9118_AI_STATUS_DTH BIT(4) /* 1=ext. digital trigger */
98#define PCI9118_AI_STATUS_BOVER BIT(3) /* 1=burst overrun (fatal) */
99#define PCI9118_AI_STATUS_ADOS BIT(2) /* 1=A/D over speed (warn) */
100#define PCI9118_AI_STATUS_ADOR BIT(1) /* 1=A/D overrun (fatal) */
101#define PCI9118_AI_STATUS_ADRDY BIT(0) /* 1=A/D ready */
a2a1fc7a 102#define PCI9118_AI_CTRL_REG 0x18
7db6ed68
HS
103#define PCI9118_AI_CTRL_UNIP BIT(7) /* 1=unipolar */
104#define PCI9118_AI_CTRL_DIFF BIT(6) /* 1=differential inputs */
105#define PCI9118_AI_CTRL_SOFTG BIT(5) /* 1=8254 software gate */
106#define PCI9118_AI_CTRL_EXTG BIT(4) /* 1=8254 TGIN(pin 46) gate */
107#define PCI9118_AI_CTRL_EXTM BIT(3) /* 1=ext. trigger (pin 44) */
108#define PCI9118_AI_CTRL_TMRTR BIT(2) /* 1=8254 is trigger source */
109#define PCI9118_AI_CTRL_INT BIT(1) /* 1=enable interrupt */
110#define PCI9118_AI_CTRL_DMA BIT(0) /* 1=enable DMA */
c7f499bd 111#define PCI9118_DIO_REG 0x1c
1750bed3 112#define PCI9118_SOFTTRG_REG 0x20
7e38f36b 113#define PCI9118_AI_CHANLIST_REG 0x24
5fc6c95c
HS
114#define PCI9118_AI_CHANLIST_RANGE(x) (((x) & 0x3) << 8)
115#define PCI9118_AI_CHANLIST_CHAN(x) ((x) << 0)
16d44e86 116#define PCI9118_AI_BURST_NUM_REG 0x28
89a7dc15 117#define PCI9118_AI_AUTOSCAN_MODE_REG 0x2c
7b460e9e 118#define PCI9118_AI_CFG_REG 0x30
7db6ed68
HS
119#define PCI9118_AI_CFG_PDTRG BIT(7) /* 1=positive trigger */
120#define PCI9118_AI_CFG_PETRG BIT(6) /* 1=positive ext. trigger */
121#define PCI9118_AI_CFG_BSSH BIT(5) /* 1=with sample & hold */
122#define PCI9118_AI_CFG_BM BIT(4) /* 1=burst mode */
123#define PCI9118_AI_CFG_BS BIT(3) /* 1=burst mode start */
124#define PCI9118_AI_CFG_PM BIT(2) /* 1=post trigger */
125#define PCI9118_AI_CFG_AM BIT(1) /* 1=about trigger */
126#define PCI9118_AI_CFG_START BIT(0) /* 1=trigger start */
582e59c0 127#define PCI9118_FIFO_RESET_REG 0x34
74ba15ed 128#define PCI9118_INT_CTRL_REG 0x38
7db6ed68
HS
129#define PCI9118_INT_CTRL_TIMER BIT(3) /* timer interrupt */
130#define PCI9118_INT_CTRL_ABOUT BIT(2) /* about trigger complete */
131#define PCI9118_INT_CTRL_HFULL BIT(1) /* A/D FIFO half full */
132#define PCI9118_INT_CTRL_DTRG BIT(0) /* ext. digital trigger */
3063d6de
MD
133
134#define START_AI_EXT 0x01 /* start measure on external trigger */
135#define STOP_AI_EXT 0x02 /* stop measure on external trigger */
3063d6de
MD
136#define STOP_AI_INT 0x08 /* stop measure on internal trigger */
137
344a15c1 138static const struct comedi_lrange pci9118_ai_range = {
713d5512
HS
139 8, {
140 BIP_RANGE(5),
141 BIP_RANGE(2.5),
142 BIP_RANGE(1.25),
143 BIP_RANGE(0.625),
144 UNI_RANGE(10),
145 UNI_RANGE(5),
146 UNI_RANGE(2.5),
147 UNI_RANGE(1.25)
148 }
3063d6de
MD
149};
150
344a15c1 151static const struct comedi_lrange pci9118hg_ai_range = {
713d5512
HS
152 8, {
153 BIP_RANGE(5),
154 BIP_RANGE(0.5),
155 BIP_RANGE(0.05),
156 BIP_RANGE(0.005),
157 UNI_RANGE(10),
158 UNI_RANGE(1),
159 UNI_RANGE(0.1),
160 UNI_RANGE(0.01)
161 }
3063d6de
MD
162};
163
83defe83
HS
164enum pci9118_boardid {
165 BOARD_PCI9118DG,
166 BOARD_PCI9118HG,
167 BOARD_PCI9118HR,
168};
169
25a8aaf0
HS
170struct pci9118_boardinfo {
171 const char *name;
a0972008 172 unsigned int ai_is_16bit:1;
344a15c1 173 unsigned int is_hg:1;
193a21e4 174};
3063d6de 175
25a8aaf0 176static const struct pci9118_boardinfo pci9118_boards[] = {
83defe83 177 [BOARD_PCI9118DG] = {
15358a7f 178 .name = "pci9118dg",
83defe83
HS
179 },
180 [BOARD_PCI9118HG] = {
15358a7f 181 .name = "pci9118hg",
344a15c1 182 .is_hg = 1,
83defe83
HS
183 },
184 [BOARD_PCI9118HR] = {
15358a7f 185 .name = "pci9118hr",
a0972008 186 .ai_is_16bit = 1,
15358a7f
IA
187 },
188};
189
1f2cbe2c 190struct pci9118_dmabuf {
75fbdbf6
IA
191 unsigned short *virt; /* virtual address of buffer */
192 dma_addr_t hw; /* hardware (bus) address of buffer */
1f2cbe2c
HS
193 unsigned int size; /* size of dma buffer in bytes */
194 unsigned int use_size; /* which size we may now use for transfer */
1f2cbe2c
HS
195};
196
5b5fc21b 197struct pci9118_private {
242467bd 198 unsigned long iobase_a; /* base+size for AMCC chip */
32502f5a
HS
199 unsigned int master:1;
200 unsigned int dma_doublebuf:1;
201 unsigned int ai_neverending:1;
202 unsigned int usedma:1;
203 unsigned int usemux:1;
559cc1ee 204 unsigned char ai_ctrl;
26ec7765 205 unsigned char int_ctrl;
5bdee661 206 unsigned char ai_cfg;
242467bd 207 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
242467bd
MD
208 unsigned int ai_n_realscanlen; /*
209 * what we must transfer for one
210 * outgoing scan include front/back adds
211 */
212 unsigned int ai_act_dmapos; /* position in actual real stream */
213 unsigned int ai_add_front; /*
214 * how many channels we must add
215 * before scan to satisfy S&H?
216 */
217 unsigned int ai_add_back; /*
218 * how many channels we must add
219 * before scan to satisfy DMA?
220 */
3063d6de 221 unsigned int ai_flags;
242467bd
MD
222 char ai12_startstop; /*
223 * measure can start/stop
224 * on external trigger
225 */
242467bd 226 unsigned int dma_actbuf; /* which buffer is used now */
1f2cbe2c 227 struct pci9118_dmabuf dmabuf[2];
242467bd
MD
228 int softsshdelay; /*
229 * >0 use software S&H,
230 * numer is requested delay in ns
231 */
232 unsigned char softsshsample; /*
233 * polarity of S&H signal
234 * in sample state
235 */
236 unsigned char softsshhold; /*
237 * polarity of S&H signal
238 * in hold state
239 */
34607db8 240 unsigned int ai_ns_min;
5b5fc21b 241};
3063d6de 242
959068c3
HS
243static void pci9118_amcc_setup_dma(struct comedi_device *dev, unsigned int buf)
244{
245 struct pci9118_private *devpriv = dev->private;
1f2cbe2c 246 struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[buf];
959068c3
HS
247
248 /* set the master write address and transfer count */
1f2cbe2c
HS
249 outl(dmabuf->hw, devpriv->iobase_a + AMCC_OP_REG_MWAR);
250 outl(dmabuf->use_size, devpriv->iobase_a + AMCC_OP_REG_MWTC);
959068c3
HS
251}
252
97d09d46
HS
253static void pci9118_amcc_dma_ena(struct comedi_device *dev, bool enable)
254{
255 struct pci9118_private *devpriv = dev->private;
256 unsigned int mcsr;
257
258 mcsr = inl(devpriv->iobase_a + AMCC_OP_REG_MCSR);
259 if (enable)
260 mcsr |= RESET_A2P_FLAGS | A2P_HI_PRIORITY | EN_A2P_TRANSFERS;
261 else
262 mcsr &= ~EN_A2P_TRANSFERS;
263 outl(mcsr, devpriv->iobase_a + AMCC_OP_REG_MCSR);
264}
265
312eaf0b
HS
266static void pci9118_amcc_int_ena(struct comedi_device *dev, bool enable)
267{
268 struct pci9118_private *devpriv = dev->private;
269 unsigned int intcsr;
270
271 /* enable/disable interrupt for AMCC Incoming Mailbox 4 (32-bit) */
272 intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
273 if (enable)
274 intcsr |= 0x1f00;
275 else
276 intcsr &= ~0x1f00;
277 outl(intcsr, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
278}
279
582e59c0
HS
280static void pci9118_ai_reset_fifo(struct comedi_device *dev)
281{
282 /* writing any value resets the A/D FIFO */
283 outl(0, dev->iobase + PCI9118_FIFO_RESET_REG);
284}
285
0f3cb85a
HS
286static int pci9118_ai_check_chanlist(struct comedi_device *dev,
287 struct comedi_subdevice *s,
288 struct comedi_cmd *cmd)
5e49e515 289{
5e49e515 290 struct pci9118_private *devpriv = dev->private;
0f3cb85a
HS
291 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
292 unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
293 int i;
5e49e515 294
0f3cb85a
HS
295 /* single channel scans are always ok */
296 if (cmd->chanlist_len == 1)
5e49e515 297 return 0;
5e49e515 298
0f3cb85a
HS
299 for (i = 1; i < cmd->chanlist_len; i++) {
300 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
301 unsigned int range = CR_RANGE(cmd->chanlist[i]);
302 unsigned int aref = CR_AREF(cmd->chanlist[i]);
303
304 if (aref != aref0) {
305 dev_err(dev->class_dev,
306 "Differential and single ended inputs can't be mixed!\n");
307 return -EINVAL;
308 }
309 if (comedi_range_is_bipolar(s, range) !=
310 comedi_range_is_bipolar(s, range0)) {
311 dev_err(dev->class_dev,
312 "Bipolar and unipolar ranges can't be mixed!\n");
313 return -EINVAL;
314 }
315 if (!devpriv->usemux && aref == AREF_DIFF &&
316 (chan >= (s->n_chan / 2))) {
317 dev_err(dev->class_dev,
318 "AREF_DIFF is only available for the first 8 channels!\n");
319 return -EINVAL;
5e49e515 320 }
0f3cb85a 321 }
5e49e515 322
0f3cb85a 323 return 0;
5e49e515
HS
324}
325
7d62b548
HS
326static void pci9118_set_chanlist(struct comedi_device *dev,
327 struct comedi_subdevice *s,
328 int n_chan, unsigned int *chanlist,
329 int frontadd, int backadd)
5e49e515
HS
330{
331 struct pci9118_private *devpriv = dev->private;
5fc6c95c 332 unsigned int chan0 = CR_CHAN(chanlist[0]);
b7a078e9
HS
333 unsigned int range0 = CR_RANGE(chanlist[0]);
334 unsigned int aref0 = CR_AREF(chanlist[0]);
5fc6c95c
HS
335 unsigned int ssh = 0x00;
336 unsigned int val;
26318c1c 337 int i;
5e49e515 338
b7a078e9
HS
339 /*
340 * Configure analog input based on the first chanlist entry.
341 * All entries are either unipolar or bipolar and single-ended
342 * or differential.
343 */
344 devpriv->ai_ctrl = 0;
345 if (comedi_range_is_unipolar(s, range0))
346 devpriv->ai_ctrl |= PCI9118_AI_CTRL_UNIP;
347 if (aref0 == AREF_DIFF)
348 devpriv->ai_ctrl |= PCI9118_AI_CTRL_DIFF;
349 outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
350
89a7dc15
HS
351 /* gods know why this sequence! */
352 outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
353 outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
354 outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
5e49e515 355
5fc6c95c
HS
356 /* insert channels for S&H */
357 if (frontadd) {
358 val = PCI9118_AI_CHANLIST_CHAN(chan0) |
359 PCI9118_AI_CHANLIST_RANGE(range0);
5e49e515
HS
360 ssh = devpriv->softsshsample;
361 for (i = 0; i < frontadd; i++) {
5fc6c95c 362 outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
5e49e515
HS
363 ssh = devpriv->softsshhold;
364 }
365 }
366
5fc6c95c
HS
367 /* store chanlist */
368 for (i = 0; i < n_chan; i++) {
369 unsigned int chan = CR_CHAN(chanlist[i]);
370 unsigned int range = CR_RANGE(chanlist[i]);
371
372 val = PCI9118_AI_CHANLIST_CHAN(chan) |
373 PCI9118_AI_CHANLIST_RANGE(range);
374 outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
5e49e515
HS
375 }
376
5fc6c95c
HS
377 /* insert channels to fit onto 32bit DMA */
378 if (backadd) {
379 val = PCI9118_AI_CHANLIST_CHAN(chan0) |
380 PCI9118_AI_CHANLIST_RANGE(range0);
381 for (i = 0; i < backadd; i++)
382 outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
5e49e515 383 }
89a7dc15
HS
384 /* close scan queue */
385 outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
5e49e515 386 /* udelay(100); important delay, or first sample will be crippled */
5e49e515 387}
3063d6de 388
ad1a9646
HS
389static void pci9118_ai_mode4_switch(struct comedi_device *dev,
390 unsigned int next_buf)
3063d6de 391{
ae34f6aa 392 struct pci9118_private *devpriv = dev->private;
f9d208d3 393 struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[next_buf];
ae34f6aa 394
5bdee661
HS
395 devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG |
396 PCI9118_AI_CFG_AM;
397 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
a9da9d20
HS
398 comedi_8254_load(dev->pacer, 0, dmabuf->hw >> 1,
399 I8254_MODE0 | I8254_BINARY);
5bdee661
HS
400 devpriv->ai_cfg |= PCI9118_AI_CFG_START;
401 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
3063d6de
MD
402}
403
9459ff2b
HS
404static unsigned int pci9118_ai_samples_ready(struct comedi_device *dev,
405 struct comedi_subdevice *s,
406 unsigned int n_raw_samples)
bb4a51a1
IA
407{
408 struct pci9118_private *devpriv = dev->private;
409 struct comedi_cmd *cmd = &s->async->cmd;
410 unsigned int start_pos = devpriv->ai_add_front;
411 unsigned int stop_pos = start_pos + cmd->chanlist_len;
412 unsigned int span_len = stop_pos + devpriv->ai_add_back;
413 unsigned int dma_pos = devpriv->ai_act_dmapos;
414 unsigned int whole_spans, n_samples, x;
415
416 if (span_len == cmd->chanlist_len)
417 return n_raw_samples; /* use all samples */
418
419 /*
420 * Not all samples are to be used. Buffer contents consist of a
421 * possibly non-whole number of spans and a region of each span
422 * is to be used.
423 *
424 * Account for samples in whole number of spans.
425 */
426 whole_spans = n_raw_samples / span_len;
427 n_samples = whole_spans * cmd->chanlist_len;
428 n_raw_samples -= whole_spans * span_len;
429
430 /*
431 * Deal with remaining samples which could overlap up to two spans.
432 */
433 while (n_raw_samples) {
434 if (dma_pos < start_pos) {
435 /* Skip samples before start position. */
436 x = start_pos - dma_pos;
437 if (x > n_raw_samples)
438 x = n_raw_samples;
439 dma_pos += x;
440 n_raw_samples -= x;
441 if (!n_raw_samples)
442 break;
443 }
444 if (dma_pos < stop_pos) {
445 /* Include samples before stop position. */
446 x = stop_pos - dma_pos;
447 if (x > n_raw_samples)
448 x = n_raw_samples;
449 n_samples += x;
450 dma_pos += x;
451 n_raw_samples -= x;
452 }
453 /* Advance to next span. */
454 start_pos += span_len;
455 stop_pos += span_len;
456 }
457 return n_samples;
458}
459
5c912f1f 460static void pci9118_ai_dma_xfer(struct comedi_device *dev,
e87f65b2
IA
461 struct comedi_subdevice *s,
462 unsigned short *dma_buffer,
463 unsigned int n_raw_samples)
3063d6de 464{
ae34f6aa 465 struct pci9118_private *devpriv = dev->private;
0642d080 466 struct comedi_cmd *cmd = &s->async->cmd;
e87f65b2
IA
467 unsigned int start_pos = devpriv->ai_add_front;
468 unsigned int stop_pos = start_pos + cmd->chanlist_len;
469 unsigned int span_len = stop_pos + devpriv->ai_add_back;
470 unsigned int dma_pos = devpriv->ai_act_dmapos;
471 unsigned int x;
472
473 if (span_len == cmd->chanlist_len) {
474 /* All samples are to be copied. */
475 comedi_buf_write_samples(s, dma_buffer, n_raw_samples);
476 dma_pos += n_raw_samples;
477 } else {
478 /*
479 * Not all samples are to be copied. Buffer contents consist
480 * of a possibly non-whole number of spans and a region of
481 * each span is to be copied.
482 */
483 while (n_raw_samples) {
484 if (dma_pos < start_pos) {
485 /* Skip samples before start position. */
486 x = start_pos - dma_pos;
487 if (x > n_raw_samples)
488 x = n_raw_samples;
489 dma_pos += x;
490 n_raw_samples -= x;
491 if (!n_raw_samples)
492 break;
493 }
494 if (dma_pos < stop_pos) {
495 /* Copy samples before stop position. */
496 x = stop_pos - dma_pos;
497 if (x > n_raw_samples)
498 x = n_raw_samples;
499 comedi_buf_write_samples(s, dma_buffer, x);
500 dma_pos += x;
501 n_raw_samples -= x;
502 }
503 /* Advance to next span. */
504 start_pos += span_len;
505 stop_pos += span_len;
3063d6de 506 }
3063d6de 507 }
e87f65b2
IA
508 /* Update position in span for next time. */
509 devpriv->ai_act_dmapos = dma_pos % span_len;
3063d6de
MD
510}
511
11822f02 512static void pci9118_exttrg_enable(struct comedi_device *dev, bool enable)
3063d6de 513{
ae34f6aa
HS
514 struct pci9118_private *devpriv = dev->private;
515
11822f02
HS
516 if (enable)
517 devpriv->int_ctrl |= PCI9118_INT_CTRL_DTRG;
518 else
519 devpriv->int_ctrl &= ~PCI9118_INT_CTRL_DTRG;
26ec7765 520 outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
a41aec1b 521
11822f02
HS
522 if (devpriv->int_ctrl)
523 pci9118_amcc_int_ena(dev, true);
524 else
664e244c 525 pci9118_amcc_int_ena(dev, false);
3063d6de
MD
526}
527
f3d3dad6 528static void pci9118_calc_divisors(struct comedi_device *dev,
5e49e515
HS
529 struct comedi_subdevice *s,
530 unsigned int *tim1, unsigned int *tim2,
531 unsigned int flags, int chans,
532 unsigned int *div1, unsigned int *div2,
f3f15e54 533 unsigned int chnsshfront)
3063d6de 534{
a9da9d20 535 struct comedi_8254 *pacer = dev->pacer;
f3f15e54 536 struct comedi_cmd *cmd = &s->async->cmd;
3063d6de 537
a9da9d20
HS
538 *div1 = *tim2 / pacer->osc_base; /* convert timer (burst) */
539 *div2 = *tim1 / pacer->osc_base; /* scan timer */
f3d3dad6
HS
540 *div2 = *div2 / *div1; /* major timer is c1*c2 */
541 if (*div2 < chans)
542 *div2 = chans;
5e49e515 543
a9da9d20 544 *tim2 = *div1 * pacer->osc_base; /* real convert timer */
f3d3dad6
HS
545
546 if (cmd->convert_src == TRIG_NOW && !chnsshfront) {
547 /* use BSSH signal */
548 if (*div2 < (chans + 2))
549 *div2 = chans + 2;
5e49e515 550 }
f3d3dad6 551
a9da9d20 552 *tim1 = *div1 * *div2 * pacer->osc_base;
5e49e515
HS
553}
554
bd3772ec 555static void pci9118_start_pacer(struct comedi_device *dev, int mode)
5e49e515 556{
a9da9d20
HS
557 if (mode == 1 || mode == 2 || mode == 4)
558 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
5e49e515
HS
559}
560
561static int pci9118_ai_cancel(struct comedi_device *dev,
562 struct comedi_subdevice *s)
563{
564 struct pci9118_private *devpriv = dev->private;
565
566 if (devpriv->usedma)
97d09d46 567 pci9118_amcc_dma_ena(dev, false);
11822f02 568 pci9118_exttrg_enable(dev, false);
a9da9d20 569 comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
4ed1bd5a 570 /* set default config (disable burst and triggers) */
5bdee661
HS
571 devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
572 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
4ed1bd5a 573 /* reset acqusition control */
559cc1ee
HS
574 devpriv->ai_ctrl = 0;
575 outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
16d44e86 576 outl(0, dev->iobase + PCI9118_AI_BURST_NUM_REG);
89a7dc15
HS
577 /* reset scan queue */
578 outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
579 outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
582e59c0 580 pci9118_ai_reset_fifo(dev);
5e49e515 581
312eaf0b
HS
582 devpriv->int_ctrl = 0;
583 outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
584 pci9118_amcc_int_ena(dev, false);
585
5e49e515
HS
586 devpriv->ai_do = 0;
587 devpriv->usedma = 0;
588
5e49e515 589 devpriv->ai_act_dmapos = 0;
5e49e515 590 s->async->inttrig = NULL;
5e49e515
HS
591 devpriv->ai_neverending = 0;
592 devpriv->dma_actbuf = 0;
593
5e49e515
HS
594 return 0;
595}
596
5e49e515
HS
597static void pci9118_ai_munge(struct comedi_device *dev,
598 struct comedi_subdevice *s, void *data,
599 unsigned int num_bytes,
600 unsigned int start_chan_index)
601{
602 struct pci9118_private *devpriv = dev->private;
6cda0d26 603 unsigned short *array = data;
1d3d32a7
HS
604 unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
605 unsigned int i;
5e49e515
HS
606
607 for (i = 0; i < num_samples; i++) {
608 if (devpriv->usedma)
609 array[i] = be16_to_cpu(array[i]);
1fb2082d 610 if (s->maxdata == 0xffff)
5e49e515
HS
611 array[i] ^= 0x8000;
612 else
613 array[i] = (array[i] >> 4) & 0x0fff;
5e49e515
HS
614 }
615}
616
45037a95
HS
617static void pci9118_ai_get_onesample(struct comedi_device *dev,
618 struct comedi_subdevice *s)
5e49e515
HS
619{
620 struct pci9118_private *devpriv = dev->private;
dab18a96 621 struct comedi_cmd *cmd = &s->async->cmd;
6cda0d26 622 unsigned short sampl;
5e49e515 623
7cc1110d 624 sampl = inl(dev->iobase + PCI9118_AI_FIFO_REG);
3063d6de 625
28e8c898 626 comedi_buf_write_samples(s, &sampl, 1);
f8736ca4 627
6250d982
HS
628 if (!devpriv->ai_neverending) {
629 if (s->async->scans_done >= cmd->stop_arg)
630 s->async->events |= COMEDI_CB_EOA;
3063d6de 631 }
3063d6de
MD
632}
633
45037a95
HS
634static void pci9118_ai_get_dma(struct comedi_device *dev,
635 struct comedi_subdevice *s)
3063d6de 636{
ae34f6aa 637 struct pci9118_private *devpriv = dev->private;
80ffd625 638 struct comedi_cmd *cmd = &s->async->cmd;
1f2cbe2c 639 struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[devpriv->dma_actbuf];
bb4a51a1
IA
640 unsigned int n_all = comedi_bytes_to_samples(s, dmabuf->use_size);
641 unsigned int n_valid;
642 bool more_dma;
643
644 /* determine whether more DMA buffers to do after this one */
9459ff2b 645 n_valid = pci9118_ai_samples_ready(dev, s, n_all);
bb4a51a1 646 more_dma = n_valid < comedi_nsamples_left(s, n_valid + 1);
3063d6de 647
ac33c20d 648 /* switch DMA buffers and restart DMA if double buffering */
bb4a51a1 649 if (more_dma && devpriv->dma_doublebuf) {
ac33c20d
IA
650 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
651 pci9118_amcc_setup_dma(dev, devpriv->dma_actbuf);
ad1a9646
HS
652 if (devpriv->ai_do == 4)
653 pci9118_ai_mode4_switch(dev, devpriv->dma_actbuf);
3063d6de
MD
654 }
655
e87f65b2 656 if (n_all)
5c912f1f 657 pci9118_ai_dma_xfer(dev, s, dmabuf->virt, n_all);
3063d6de 658
def69d7f 659 if (!devpriv->ai_neverending) {
6250d982 660 if (s->async->scans_done >= cmd->stop_arg)
3063d6de 661 s->async->events |= COMEDI_CB_EOA;
def69d7f 662 }
3063d6de 663
bb4a51a1
IA
664 if (s->async->events & COMEDI_CB_CANCEL_MASK)
665 more_dma = false;
666
ac33c20d 667 /* restart DMA if not double buffering */
bb4a51a1 668 if (more_dma && !devpriv->dma_doublebuf) {
959068c3 669 pci9118_amcc_setup_dma(dev, 0);
3063d6de 670 if (devpriv->ai_do == 4)
ad1a9646 671 pci9118_ai_mode4_switch(dev, 0);
3063d6de 672 }
3063d6de
MD
673}
674
c089d5af 675static irqreturn_t pci9118_interrupt(int irq, void *d)
3063d6de 676{
71b5f4f1 677 struct comedi_device *dev = d;
901be534 678 struct comedi_subdevice *s = dev->read_subdev;
ae34f6aa 679 struct pci9118_private *devpriv = dev->private;
c089d5af
HS
680 unsigned int intsrc; /* IRQ reasons from card */
681 unsigned int intcsr; /* INT register from AMCC chip */
682 unsigned int adstat; /* STATUS register */
3063d6de
MD
683
684 if (!dev->attached)
c089d5af
HS
685 return IRQ_NONE;
686
74ba15ed 687 intsrc = inl(dev->iobase + PCI9118_INT_CTRL_REG) & 0xf;
c089d5af
HS
688 intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
689
690 if (!intsrc && !(intcsr & ANY_S593X_INT))
691 return IRQ_NONE;
692
693 outl(intcsr | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
694
318141a1
HS
695 if (intcsr & MASTER_ABORT_INT) {
696 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
3e6cb74f 697 s->async->events |= COMEDI_CB_ERROR;
45ada8e8 698 goto interrupt_exit;
318141a1
HS
699 }
700
701 if (intcsr & TARGET_ABORT_INT) {
702 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
3e6cb74f 703 s->async->events |= COMEDI_CB_ERROR;
45ada8e8 704 goto interrupt_exit;
318141a1
HS
705 }
706
f16a7b85
HS
707 adstat = inl(dev->iobase + PCI9118_AI_STATUS_REG);
708 if ((adstat & PCI9118_AI_STATUS_NFULL) == 0) {
709 dev_err(dev->class_dev,
710 "A/D FIFO Full status (Fatal Error!)\n");
711 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
45ada8e8 712 goto interrupt_exit;
f16a7b85
HS
713 }
714 if (adstat & PCI9118_AI_STATUS_BOVER) {
715 dev_err(dev->class_dev,
716 "A/D Burst Mode Overrun Status (Fatal Error!)\n");
717 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
45ada8e8 718 goto interrupt_exit;
f16a7b85
HS
719 }
720 if (adstat & PCI9118_AI_STATUS_ADOS) {
721 dev_err(dev->class_dev, "A/D Over Speed Status (Warning!)\n");
722 s->async->events |= COMEDI_CB_ERROR;
45ada8e8 723 goto interrupt_exit;
f16a7b85
HS
724 }
725 if (adstat & PCI9118_AI_STATUS_ADOR) {
726 dev_err(dev->class_dev, "A/D Overrun Status (Fatal Error!)\n");
727 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
45ada8e8 728 goto interrupt_exit;
f16a7b85 729 }
c089d5af
HS
730
731 if (!devpriv->ai_do)
732 return IRQ_HANDLED;
733
734 if (devpriv->ai12_startstop) {
00bd059f
HS
735 if ((adstat & PCI9118_AI_STATUS_DTH) &&
736 (intsrc & PCI9118_INT_CTRL_DTRG)) {
c089d5af
HS
737 /* start/stop of measure */
738 if (devpriv->ai12_startstop & START_AI_EXT) {
739 /* deactivate EXT trigger */
740 devpriv->ai12_startstop &= ~START_AI_EXT;
741 if (!(devpriv->ai12_startstop & STOP_AI_EXT))
11822f02 742 pci9118_exttrg_enable(dev, false);
c089d5af
HS
743
744 /* start pacer */
bd3772ec 745 pci9118_start_pacer(dev, devpriv->ai_do);
559cc1ee 746 outl(devpriv->ai_ctrl,
a2a1fc7a 747 dev->iobase + PCI9118_AI_CTRL_REG);
c089d5af
HS
748 } else if (devpriv->ai12_startstop & STOP_AI_EXT) {
749 /* deactivate EXT trigger */
750 devpriv->ai12_startstop &= ~STOP_AI_EXT;
11822f02 751 pci9118_exttrg_enable(dev, false);
c089d5af
HS
752
753 /* on next interrupt measure will stop */
754 devpriv->ai_neverending = 0;
3063d6de 755 }
901be534 756 }
c089d5af 757 }
3063d6de 758
c089d5af 759 if (devpriv->usedma)
45037a95 760 pci9118_ai_get_dma(dev, s);
c089d5af 761 else
45037a95 762 pci9118_ai_get_onesample(dev, s);
3063d6de 763
45ada8e8 764interrupt_exit:
f5b5164d 765 comedi_handle_events(dev, s);
3063d6de
MD
766 return IRQ_HANDLED;
767}
768
5e17ae87
HS
769static void pci9118_ai_cmd_start(struct comedi_device *dev)
770{
771 struct pci9118_private *devpriv = dev->private;
772
773 outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
774 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
775 if (devpriv->ai_do != 3) {
776 pci9118_start_pacer(dev, devpriv->ai_do);
777 devpriv->ai_ctrl |= PCI9118_AI_CTRL_SOFTG;
778 }
779 outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
780}
781
0a85b6f0 782static int pci9118_ai_inttrig(struct comedi_device *dev,
01dc2a05
HS
783 struct comedi_subdevice *s,
784 unsigned int trig_num)
3063d6de 785{
01dc2a05 786 struct comedi_cmd *cmd = &s->async->cmd;
ae34f6aa 787
01dc2a05 788 if (trig_num != cmd->start_arg)
3063d6de
MD
789 return -EINVAL;
790
3063d6de 791 s->async->inttrig = NULL;
5e17ae87 792 pci9118_ai_cmd_start(dev);
3063d6de
MD
793
794 return 1;
795}
796
eb12dfc9
HS
797static int pci9118_ai_setup_dma(struct comedi_device *dev,
798 struct comedi_subdevice *s)
3063d6de 799{
ae34f6aa 800 struct pci9118_private *devpriv = dev->private;
80ffd625 801 struct comedi_cmd *cmd = &s->async->cmd;
1f2cbe2c
HS
802 struct pci9118_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
803 struct pci9118_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
eb96c7fc
HS
804 unsigned int dmalen0 = dmabuf0->size;
805 unsigned int dmalen1 = dmabuf1->size;
806 unsigned int scan_bytes = devpriv->ai_n_realscanlen *
807 comedi_bytes_per_sample(s);
3063d6de 808
242467bd 809 /* isn't output buff smaller that our DMA buff? */
cc06e241
HS
810 if (dmalen0 > s->async->prealloc_bufsz) {
811 /* align to 32bit down */
812 dmalen0 = s->async->prealloc_bufsz & ~3L;
3063d6de 813 }
cc06e241
HS
814 if (dmalen1 > s->async->prealloc_bufsz) {
815 /* align to 32bit down */
816 dmalen1 = s->async->prealloc_bufsz & ~3L;
3063d6de 817 }
3063d6de 818
242467bd 819 /* we want wake up every scan? */
c25dec57 820 if (devpriv->ai_flags & CMDF_WAKE_EOS) {
eb96c7fc 821 if (dmalen0 < scan_bytes) {
242467bd 822 /* uff, too short DMA buffer, disable EOS support! */
c25dec57 823 devpriv->ai_flags &= (~CMDF_WAKE_EOS);
f41d2573 824 dev_info(dev->class_dev,
c25dec57 825 "WAR: DMA0 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
eb96c7fc 826 dmalen0, scan_bytes);
3063d6de 827 } else {
242467bd 828 /* short first DMA buffer to one scan */
eb96c7fc 829 dmalen0 = scan_bytes;
3063d6de 830 if (dmalen0 < 4) {
f41d2573
IA
831 dev_info(dev->class_dev,
832 "ERR: DMA0 buf len bug? (%d<4)\n",
833 dmalen0);
3063d6de
MD
834 dmalen0 = 4;
835 }
836 }
837 }
c25dec57 838 if (devpriv->ai_flags & CMDF_WAKE_EOS) {
eb96c7fc 839 if (dmalen1 < scan_bytes) {
242467bd 840 /* uff, too short DMA buffer, disable EOS support! */
c25dec57 841 devpriv->ai_flags &= (~CMDF_WAKE_EOS);
f41d2573 842 dev_info(dev->class_dev,
c25dec57 843 "WAR: DMA1 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
eb96c7fc 844 dmalen1, scan_bytes);
3063d6de 845 } else {
242467bd 846 /* short second DMA buffer to one scan */
eb96c7fc 847 dmalen1 = scan_bytes;
3063d6de 848 if (dmalen1 < 4) {
f41d2573
IA
849 dev_info(dev->class_dev,
850 "ERR: DMA1 buf len bug? (%d<4)\n",
851 dmalen1);
3063d6de
MD
852 dmalen1 = 4;
853 }
854 }
855 }
856
c25dec57
IA
857 /* transfer without CMDF_WAKE_EOS */
858 if (!(devpriv->ai_flags & CMDF_WAKE_EOS)) {
eb96c7fc
HS
859 unsigned int tmp;
860
25985edc 861 /* if it's possible then align DMA buffers to length of scan */
eb96c7fc
HS
862 tmp = dmalen0;
863 dmalen0 = (dmalen0 / scan_bytes) * scan_bytes;
3063d6de
MD
864 dmalen0 &= ~3L;
865 if (!dmalen0)
eb96c7fc
HS
866 dmalen0 = tmp; /* uff. very long scan? */
867 tmp = dmalen1;
868 dmalen1 = (dmalen1 / scan_bytes) * scan_bytes;
3063d6de
MD
869 dmalen1 &= ~3L;
870 if (!dmalen1)
eb96c7fc 871 dmalen1 = tmp; /* uff. very long scan? */
242467bd
MD
872 /*
873 * if measure isn't neverending then test, if it fits whole
874 * into one or two DMA buffers
875 */
3063d6de 876 if (!devpriv->ai_neverending) {
eb96c7fc
HS
877 unsigned long long scanlen;
878
879 scanlen = (unsigned long long)scan_bytes *
880 cmd->stop_arg;
881
242467bd 882 /* fits whole measure into one DMA buffer? */
eb96c7fc
HS
883 if (dmalen0 > scanlen) {
884 dmalen0 = scanlen;
3063d6de 885 dmalen0 &= ~3L;
eb96c7fc
HS
886 } else {
887 /* fits whole measure into two DMA buffer? */
888 if (dmalen1 > (scanlen - dmalen0)) {
889 dmalen1 = scanlen - dmalen0;
890 dmalen1 &= ~3L;
891 }
3063d6de
MD
892 }
893 }
894 }
895
242467bd 896 /* these DMA buffer size will be used */
3063d6de 897 devpriv->dma_actbuf = 0;
1f2cbe2c
HS
898 dmabuf0->use_size = dmalen0;
899 dmabuf1->use_size = dmalen1;
3063d6de 900
97d09d46 901 pci9118_amcc_dma_ena(dev, false);
959068c3 902 pci9118_amcc_setup_dma(dev, 0);
242467bd 903 /* init DMA transfer */
3063d6de 904 outl(0x00000000 | AINT_WRITE_COMPL,
0a85b6f0 905 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
0f04c356 906/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
97d09d46 907 pci9118_amcc_dma_ena(dev, true);
242467bd 908 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
6c7d2c8b 909 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
242467bd 910 /* allow bus mastering */
3063d6de 911
3063d6de
MD
912 return 0;
913}
914
da91b269 915static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
3063d6de 916{
ae34f6aa 917 struct pci9118_private *devpriv = dev->private;
a9da9d20 918 struct comedi_8254 *pacer = dev->pacer;
ea6d0d4c 919 struct comedi_cmd *cmd = &s->async->cmd;
3063d6de 920 unsigned int addchans = 0;
0f3cb85a 921 unsigned int scanlen;
3063d6de 922
3063d6de
MD
923 devpriv->ai12_startstop = 0;
924 devpriv->ai_flags = cmd->flags;
3063d6de
MD
925 devpriv->ai_add_front = 0;
926 devpriv->ai_add_back = 0;
3063d6de 927
242467bd 928 /* prepare for start/stop conditions */
3063d6de
MD
929 if (cmd->start_src == TRIG_EXT)
930 devpriv->ai12_startstop |= START_AI_EXT;
931 if (cmd->stop_src == TRIG_EXT) {
932 devpriv->ai_neverending = 1;
933 devpriv->ai12_startstop |= STOP_AI_EXT;
934 }
3063d6de
MD
935 if (cmd->stop_src == TRIG_NONE)
936 devpriv->ai_neverending = 1;
80ffd625 937 if (cmd->stop_src == TRIG_COUNT)
3063d6de 938 devpriv->ai_neverending = 0;
3063d6de 939
242467bd
MD
940 /*
941 * use additional sample at end of every scan
942 * to satisty DMA 32 bit transfer?
943 */
3063d6de
MD
944 devpriv->ai_add_front = 0;
945 devpriv->ai_add_back = 0;
3063d6de
MD
946 if (devpriv->master) {
947 devpriv->usedma = 1;
c25dec57 948 if ((cmd->flags & CMDF_WAKE_EOS) &&
dab18a96 949 (cmd->scan_end_arg == 1)) {
beb50909 950 if (cmd->convert_src == TRIG_NOW)
3063d6de 951 devpriv->ai_add_back = 1;
3063d6de 952 if (cmd->convert_src == TRIG_TIMER) {
242467bd
MD
953 devpriv->usedma = 0;
954 /*
955 * use INT transfer if scanlist
956 * have only one channel
957 */
3063d6de
MD
958 }
959 }
c25dec57 960 if ((cmd->flags & CMDF_WAKE_EOS) &&
dab18a96
HS
961 (cmd->scan_end_arg & 1) &&
962 (cmd->scan_end_arg > 1)) {
3063d6de 963 if (cmd->scan_begin_src == TRIG_FOLLOW) {
242467bd
MD
964 devpriv->usedma = 0;
965 /*
966 * XXX maybe can be corrected to use 16 bit DMA
967 */
968 } else { /*
969 * well, we must insert one sample
970 * to end of EOS to meet 32 bit transfer
971 */
3063d6de
MD
972 devpriv->ai_add_back = 1;
973 }
974 }
242467bd 975 } else { /* interrupt transfer don't need any correction */
3063d6de
MD
976 devpriv->usedma = 0;
977 }
978
242467bd
MD
979 /*
980 * we need software S&H signal?
981 * It adds two samples before every scan as minimum
982 */
f3f15e54 983 if (cmd->convert_src == TRIG_NOW && devpriv->softsshdelay) {
3063d6de 984 devpriv->ai_add_front = 2;
242467bd
MD
985 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
986 /* move it to front */
3063d6de
MD
987 devpriv->ai_add_front++;
988 devpriv->ai_add_back = 0;
989 }
34607db8
HS
990 if (cmd->convert_arg < devpriv->ai_ns_min)
991 cmd->convert_arg = devpriv->ai_ns_min;
3063d6de
MD
992 addchans = devpriv->softsshdelay / cmd->convert_arg;
993 if (devpriv->softsshdelay % cmd->convert_arg)
994 addchans++;
242467bd
MD
995 if (addchans > (devpriv->ai_add_front - 1)) {
996 /* uff, still short */
3063d6de
MD
997 devpriv->ai_add_front = addchans + 1;
998 if (devpriv->usedma == 1)
999 if ((devpriv->ai_add_front +
0642d080 1000 cmd->chanlist_len +
0a85b6f0 1001 devpriv->ai_add_back) & 1)
242467bd
MD
1002 devpriv->ai_add_front++;
1003 /* round up to 32 bit */
3063d6de 1004 }
0a85b6f0 1005 }
242467bd 1006 /* well, we now know what must be all added */
0f3cb85a
HS
1007 scanlen = devpriv->ai_add_front + cmd->chanlist_len +
1008 devpriv->ai_add_back;
1009 /*
1010 * what we must take from card in real to have cmd->scan_end_arg
1011 * on output?
1012 */
1013 devpriv->ai_n_realscanlen = scanlen *
1014 (cmd->scan_end_arg / cmd->chanlist_len);
1015
1016 if (scanlen > s->len_chanlist) {
1017 dev_err(dev->class_dev,
1018 "range/channel list is too long for actual configuration!\n");
3063d6de 1019 return -EINVAL;
0f3cb85a 1020 }
26318c1c
HS
1021
1022 /*
b7a078e9 1023 * Configure analog input and load the chanlist.
26318c1c
HS
1024 * The acqusition control bits are enabled later.
1025 */
7d62b548
HS
1026 pci9118_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist,
1027 devpriv->ai_add_front, devpriv->ai_add_back);
3063d6de 1028
f3d3dad6 1029 /* Determine acqusition mode and calculate timing */
fa795752 1030 devpriv->ai_do = 0;
f3d3dad6
HS
1031 if (cmd->scan_begin_src != TRIG_TIMER &&
1032 cmd->convert_src == TRIG_TIMER) {
1033 /* cascaded timers 1 and 2 are used for convert timing */
beb50909 1034 if (cmd->scan_begin_src == TRIG_EXT)
3063d6de 1035 devpriv->ai_do = 4;
beb50909 1036 else
3063d6de 1037 devpriv->ai_do = 1;
fa795752 1038
a9da9d20
HS
1039 comedi_8254_cascade_ns_to_timer(pacer, &cmd->convert_arg,
1040 devpriv->ai_flags &
1041 CMDF_ROUND_NEAREST);
1042 comedi_8254_update_divisors(pacer);
fa795752
HS
1043
1044 devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
1045
1046 if (!devpriv->usedma) {
1047 devpriv->ai_ctrl |= PCI9118_AI_CTRL_INT;
1048 devpriv->int_ctrl |= PCI9118_INT_CTRL_TIMER;
1049 }
1050
1051 if (cmd->scan_begin_src == TRIG_EXT) {
1052 struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[0];
1053
1054 devpriv->ai_cfg |= PCI9118_AI_CFG_AM;
1055 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
a9da9d20
HS
1056 comedi_8254_load(pacer, 0, dmabuf->hw >> 1,
1057 I8254_MODE0 | I8254_BINARY);
fa795752
HS
1058 devpriv->ai_cfg |= PCI9118_AI_CFG_START;
1059 }
3063d6de
MD
1060 }
1061
f3d3dad6
HS
1062 if (cmd->scan_begin_src == TRIG_TIMER &&
1063 cmd->convert_src != TRIG_EXT) {
3063d6de 1064 if (!devpriv->usedma) {
027a8ccf
HS
1065 dev_err(dev->class_dev,
1066 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n");
3063d6de
MD
1067 return -EIO;
1068 }
1069
f3d3dad6 1070 /* double timed action */
3063d6de 1071 devpriv->ai_do = 2;
fa795752 1072
f3d3dad6 1073 pci9118_calc_divisors(dev, s,
0a85b6f0
MT
1074 &cmd->scan_begin_arg, &cmd->convert_arg,
1075 devpriv->ai_flags,
1076 devpriv->ai_n_realscanlen,
a9da9d20
HS
1077 &pacer->divisor1,
1078 &pacer->divisor2,
0a85b6f0 1079 devpriv->ai_add_front);
fa795752
HS
1080
1081 devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
1082 devpriv->ai_cfg |= PCI9118_AI_CFG_BM | PCI9118_AI_CFG_BS;
1083 if (cmd->convert_src == TRIG_NOW && !devpriv->softsshdelay)
1084 devpriv->ai_cfg |= PCI9118_AI_CFG_BSSH;
1085 outl(devpriv->ai_n_realscanlen,
1086 dev->iobase + PCI9118_AI_BURST_NUM_REG);
3063d6de
MD
1087 }
1088
f3d3dad6
HS
1089 if (cmd->scan_begin_src == TRIG_FOLLOW &&
1090 cmd->convert_src == TRIG_EXT) {
1091 /* external trigger conversion */
3063d6de 1092 devpriv->ai_do = 3;
fa795752
HS
1093
1094 devpriv->ai_ctrl |= PCI9118_AI_CTRL_EXTM;
1095 }
1096
1097 if (devpriv->ai_do == 0) {
1098 dev_err(dev->class_dev,
1099 "Unable to determine acqusition mode! BUG in (*do_cmdtest)?\n");
1100 return -EINVAL;
3063d6de
MD
1101 }
1102
d900197e
HS
1103 if (devpriv->usedma)
1104 devpriv->ai_ctrl |= PCI9118_AI_CTRL_DMA;
1105
4ed1bd5a 1106 /* set default config (disable burst and triggers) */
5bdee661 1107 devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
5bdee661 1108 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
5f74ea14 1109 udelay(1);
582e59c0 1110 pci9118_ai_reset_fifo(dev);
602c1729
HS
1111
1112 /* clear A/D and INT status registers */
1113 inl(dev->iobase + PCI9118_AI_STATUS_REG);
74ba15ed 1114 inl(dev->iobase + PCI9118_INT_CTRL_REG);
3063d6de 1115
3063d6de 1116 devpriv->ai_act_dmapos = 0;
3063d6de 1117
fa795752 1118 if (devpriv->usedma) {
eb12dfc9 1119 pci9118_ai_setup_dma(dev, s);
fa795752
HS
1120
1121 outl(0x02000000 | AINT_WRITE_COMPL,
1122 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1123 } else {
1124 pci9118_amcc_int_ena(dev, true);
1125 }
3063d6de 1126
e7d2191b
HS
1127 /* start async command now or wait for internal trigger */
1128 if (cmd->start_src == TRIG_NOW)
1129 pci9118_ai_cmd_start(dev);
1130 else if (cmd->start_src == TRIG_INT)
1131 s->async->inttrig = pci9118_ai_inttrig;
1132
1133 /* enable external trigger for command start/stop */
1134 if (cmd->start_src == TRIG_EXT || cmd->stop_src == TRIG_EXT)
1135 pci9118_exttrg_enable(dev, true);
1136
1137 return 0;
3063d6de
MD
1138}
1139
8c469410
HS
1140static int pci9118_ai_cmdtest(struct comedi_device *dev,
1141 struct comedi_subdevice *s,
1142 struct comedi_cmd *cmd)
1143{
1144 struct pci9118_private *devpriv = dev->private;
1145 int err = 0;
1146 unsigned int flags;
1147 unsigned int arg;
8c469410
HS
1148
1149 /* Step 1 : check if triggers are trivially valid */
1150
94fff03d 1151 err |= comedi_check_trigger_src(&cmd->start_src,
8c469410
HS
1152 TRIG_NOW | TRIG_EXT | TRIG_INT);
1153
1154 flags = TRIG_FOLLOW;
1155 if (devpriv->master)
1156 flags |= TRIG_TIMER | TRIG_EXT;
94fff03d 1157 err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
8c469410
HS
1158
1159 flags = TRIG_TIMER | TRIG_EXT;
1160 if (devpriv->master)
1161 flags |= TRIG_NOW;
94fff03d 1162 err |= comedi_check_trigger_src(&cmd->convert_src, flags);
8c469410 1163
94fff03d
IA
1164 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1165 err |= comedi_check_trigger_src(&cmd->stop_src,
8c469410
HS
1166 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1167
1168 if (err)
1169 return 1;
1170
1171 /* Step 2a : make sure trigger sources are unique */
1172
94fff03d
IA
1173 err |= comedi_check_trigger_is_unique(cmd->start_src);
1174 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
1175 err |= comedi_check_trigger_is_unique(cmd->convert_src);
1176 err |= comedi_check_trigger_is_unique(cmd->stop_src);
8c469410
HS
1177
1178 /* Step 2b : and mutually compatible */
1179
1180 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1181 err |= -EINVAL;
1182
8c469410
HS
1183 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1184 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1185 err |= -EINVAL;
1186
1187 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1188 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1189 err |= -EINVAL;
1190
1191 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1192 err |= -EINVAL;
1193
1194 if (err)
1195 return 2;
1196
1197 /* Step 3: check if arguments are trivially valid */
1198
1199 switch (cmd->start_src) {
1200 case TRIG_NOW:
1201 case TRIG_EXT:
94fff03d 1202 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
8c469410
HS
1203 break;
1204 case TRIG_INT:
1205 /* start_arg is the internal trigger (any value) */
1206 break;
1207 }
1208
1209 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
94fff03d 1210 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
8c469410
HS
1211
1212 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1213 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1214 cmd->scan_begin_src = TRIG_FOLLOW;
1215 cmd->convert_arg = cmd->scan_begin_arg;
1216 cmd->scan_begin_arg = 0;
1217 }
1218
94fff03d
IA
1219 if (cmd->scan_begin_src == TRIG_TIMER) {
1220 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
1221 devpriv->ai_ns_min);
1222 }
8c469410 1223
94fff03d 1224 if (cmd->scan_begin_src == TRIG_EXT) {
8c469410
HS
1225 if (cmd->scan_begin_arg) {
1226 cmd->scan_begin_arg = 0;
1227 err |= -EINVAL;
94fff03d
IA
1228 err |= comedi_check_trigger_arg_max(&cmd->scan_end_arg,
1229 65535);
8c469410 1230 }
94fff03d 1231 }
8c469410 1232
94fff03d
IA
1233 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1234 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
1235 devpriv->ai_ns_min);
1236 }
8c469410
HS
1237
1238 if (cmd->convert_src == TRIG_EXT)
94fff03d 1239 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
8c469410
HS
1240
1241 if (cmd->stop_src == TRIG_COUNT)
94fff03d 1242 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
8c469410 1243 else /* TRIG_NONE */
94fff03d 1244 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
8c469410 1245
94fff03d 1246 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
8c469410 1247
94fff03d
IA
1248 err |= comedi_check_trigger_arg_min(&cmd->scan_end_arg,
1249 cmd->chanlist_len);
8c469410
HS
1250
1251 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1252 cmd->scan_end_arg =
1253 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1254 err |= -EINVAL;
1255 }
1256
1257 if (err)
1258 return 3;
1259
1260 /* step 4: fix up any arguments */
1261
1262 if (cmd->scan_begin_src == TRIG_TIMER) {
1263 arg = cmd->scan_begin_arg;
a9da9d20 1264 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
94fff03d 1265 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
8c469410
HS
1266 }
1267
1268 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1269 arg = cmd->convert_arg;
a9da9d20 1270 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
94fff03d 1271 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
8c469410
HS
1272
1273 if (cmd->scan_begin_src == TRIG_TIMER &&
1274 cmd->convert_src == TRIG_NOW) {
1275 if (cmd->convert_arg == 0) {
1276 arg = devpriv->ai_ns_min *
1277 (cmd->scan_end_arg + 2);
1278 } else {
1279 arg = cmd->convert_arg * cmd->chanlist_len;
1280 }
94fff03d
IA
1281 err |= comedi_check_trigger_arg_min(&cmd->
1282 scan_begin_arg,
1283 arg);
8c469410
HS
1284 }
1285 }
1286
1287 if (err)
1288 return 4;
1289
0f3cb85a
HS
1290 /* Step 5: check channel list if it exists */
1291
8c469410 1292 if (cmd->chanlist)
0f3cb85a
HS
1293 err |= pci9118_ai_check_chanlist(dev, s, cmd);
1294
1295 if (err)
1296 return 5;
8c469410
HS
1297
1298 return 0;
1299}
1300
649a7d15
HS
1301static int pci9118_ai_eoc(struct comedi_device *dev,
1302 struct comedi_subdevice *s,
1303 struct comedi_insn *insn,
1304 unsigned long context)
1305{
1306 unsigned int status;
1307
1308 status = inl(dev->iobase + PCI9118_AI_STATUS_REG);
1309 if (status & PCI9118_AI_STATUS_ADRDY)
1310 return 0;
1311 return -EBUSY;
1312}
1313
1314static void pci9118_ai_start_conv(struct comedi_device *dev)
1315{
1316 /* writing any value triggers an A/D conversion */
1317 outl(0, dev->iobase + PCI9118_SOFTTRG_REG);
1318}
1319
1320static int pci9118_ai_insn_read(struct comedi_device *dev,
1321 struct comedi_subdevice *s,
1322 struct comedi_insn *insn,
1323 unsigned int *data)
1324{
1325 struct pci9118_private *devpriv = dev->private;
1326 unsigned int val;
1327 int ret;
1328 int i;
1329
1330 /*
1331 * Configure analog input based on the chanspec.
1332 * Acqusition is software controlled without interrupts.
1333 */
b7a078e9 1334 pci9118_set_chanlist(dev, s, 1, &insn->chanspec, 0, 0);
649a7d15
HS
1335
1336 /* set default config (disable burst and triggers) */
1337 devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
1338 outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
1339
649a7d15
HS
1340 pci9118_ai_reset_fifo(dev);
1341
1342 for (i = 0; i < insn->n; i++) {
1343 pci9118_ai_start_conv(dev);
1344
1345 ret = comedi_timeout(dev, s, insn, pci9118_ai_eoc, 0);
1346 if (ret)
1347 return ret;
1348
1349 val = inl(dev->iobase + PCI9118_AI_FIFO_REG);
1350 if (s->maxdata == 0xffff)
1351 data[i] = (val & 0xffff) ^ 0x8000;
1352 else
1353 data[i] = (val >> 4) & 0xfff;
1354 }
1355
1356 return insn->n;
1357}
1358
3cb3fc0a
HS
1359static int pci9118_ao_insn_write(struct comedi_device *dev,
1360 struct comedi_subdevice *s,
1361 struct comedi_insn *insn,
1362 unsigned int *data)
1363{
1364 unsigned int chan = CR_CHAN(insn->chanspec);
1365 unsigned int val = s->readback[chan];
1366 int i;
1367
1368 for (i = 0; i < insn->n; i++) {
1369 val = data[i];
1370 outl(val, dev->iobase + PCI9118_AO_REG(chan));
1371 }
1372 s->readback[chan] = val;
1373
1374 return insn->n;
1375}
1376
f300fab2
HS
1377static int pci9118_di_insn_bits(struct comedi_device *dev,
1378 struct comedi_subdevice *s,
1379 struct comedi_insn *insn,
1380 unsigned int *data)
1381{
1382 /*
1383 * The digital inputs and outputs share the read register.
1384 * bits [7:4] are the digital outputs
1385 * bits [3:0] are the digital inputs
1386 */
1387 data[1] = inl(dev->iobase + PCI9118_DIO_REG) & 0xf;
1388
1389 return insn->n;
1390}
1391
8df6166b
HS
1392static int pci9118_do_insn_bits(struct comedi_device *dev,
1393 struct comedi_subdevice *s,
1394 struct comedi_insn *insn,
1395 unsigned int *data)
1396{
1397 /*
1398 * The digital outputs are set with the same register that
1399 * the digital inputs and outputs are read from. But the
1400 * outputs are set with bits [3:0] so we can simply write
1401 * the s->state to set them.
1402 */
1403 if (comedi_dio_update_state(s, data))
1404 outl(s->state, dev->iobase + PCI9118_DIO_REG);
1405
1406 data[1] = s->state;
1407
1408 return insn->n;
1409}
1410
5358e899 1411static void pci9118_reset(struct comedi_device *dev)
3063d6de 1412{
5358e899
HS
1413 /* reset analog input subsystem */
1414 outl(0, dev->iobase + PCI9118_INT_CTRL_REG);
1415 outl(0, dev->iobase + PCI9118_AI_CTRL_REG);
1416 outl(0, dev->iobase + PCI9118_AI_CFG_REG);
1417 pci9118_ai_reset_fifo(dev);
ae34f6aa 1418
5358e899 1419 /* clear any pending interrupts and status */
74ba15ed 1420 inl(dev->iobase + PCI9118_INT_CTRL_REG);
5358e899
HS
1421 inl(dev->iobase + PCI9118_AI_STATUS_REG);
1422
5358e899 1423 /* reset DMA and scan queue */
16d44e86 1424 outl(0, dev->iobase + PCI9118_AI_BURST_NUM_REG);
89a7dc15
HS
1425 outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
1426 outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
3063d6de 1427
c6908517 1428 /* reset analog outputs to 0V */
458a76f4
HS
1429 outl(2047, dev->iobase + PCI9118_AO_REG(0));
1430 outl(2047, dev->iobase + PCI9118_AO_REG(1));
3063d6de
MD
1431}
1432
93b6e479
HS
1433static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1434 struct comedi_devconfig *it)
1435{
1436 struct pci_dev *pcidev = NULL;
1437 int bus = it->options[0];
1438 int slot = it->options[1];
1439
1440 for_each_pci_dev(pcidev) {
1441 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1442 continue;
8bd1e1df 1443 if (pcidev->device != 0x80d9)
93b6e479
HS
1444 continue;
1445 if (bus || slot) {
1446 /* requested particular bus/slot */
1447 if (pcidev->bus->number != bus ||
1448 PCI_SLOT(pcidev->devfn) != slot)
1449 continue;
1450 }
93b6e479
HS
1451 return pcidev;
1452 }
f41d2573
IA
1453 dev_err(dev->class_dev,
1454 "no supported board found! (req. bus/slot : %d/%d)\n",
1455 bus, slot);
93b6e479
HS
1456 return NULL;
1457}
1458
b9ca5508
HS
1459static void pci9118_alloc_dma(struct comedi_device *dev)
1460{
1461 struct pci9118_private *devpriv = dev->private;
1f2cbe2c 1462 struct pci9118_dmabuf *dmabuf;
f39f87e9 1463 int order;
b9ca5508
HS
1464 int i;
1465
1466 for (i = 0; i < 2; i++) {
1f2cbe2c 1467 dmabuf = &devpriv->dmabuf[i];
f39f87e9 1468 for (order = 2; order >= 0; order--) {
75fbdbf6
IA
1469 dmabuf->virt =
1470 dma_alloc_coherent(dev->hw_dev, PAGE_SIZE << order,
1471 &dmabuf->hw, GFP_KERNEL);
1f2cbe2c 1472 if (dmabuf->virt)
b9ca5508
HS
1473 break;
1474 }
d5733baf
IA
1475 if (!dmabuf->virt)
1476 break;
f39f87e9 1477 dmabuf->size = PAGE_SIZE << order;
d5733baf
IA
1478
1479 if (i == 0)
1480 devpriv->master = 1;
1481 if (i == 1)
1482 devpriv->dma_doublebuf = 1;
b9ca5508 1483 }
b9ca5508
HS
1484}
1485
1486static void pci9118_free_dma(struct comedi_device *dev)
1487{
1488 struct pci9118_private *devpriv = dev->private;
1f2cbe2c
HS
1489 struct pci9118_dmabuf *dmabuf;
1490 int i;
b9ca5508
HS
1491
1492 if (!devpriv)
1493 return;
1494
1f2cbe2c
HS
1495 for (i = 0; i < 2; i++) {
1496 dmabuf = &devpriv->dmabuf[i];
75fbdbf6
IA
1497 if (dmabuf->virt) {
1498 dma_free_coherent(dev->hw_dev, dmabuf->size,
1499 dmabuf->virt, dmabuf->hw);
1500 }
1f2cbe2c 1501 }
b9ca5508
HS
1502}
1503
cb578327 1504static int pci9118_common_attach(struct comedi_device *dev,
9e531485 1505 int ext_mux, int softsshdelay)
3063d6de 1506{
0220d472 1507 const struct pci9118_boardinfo *board = dev->board_ptr;
f3b81d54 1508 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
f6009ae5 1509 struct pci9118_private *devpriv;
34c43922 1510 struct comedi_subdevice *s;
b9ca5508
HS
1511 int ret;
1512 int i;
3063d6de
MD
1513 u16 u16w;
1514
f6009ae5
HS
1515 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1516 if (!devpriv)
1517 return -ENOMEM;
1518
818f569f
HS
1519 ret = comedi_pci_enable(dev);
1520 if (ret)
f3b81d54 1521 return ret;
cb578327 1522 pci_set_master(pcidev);
a41aec1b 1523
c945a1d1
HS
1524 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1525 dev->iobase = pci_resource_start(pcidev, 2);
3063d6de 1526
a9da9d20
HS
1527 dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
1528 I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
1529 if (!dev->pacer)
1530 return -ENOMEM;
1531
3063d6de
MD
1532 pci9118_reset(dev);
1533
cb578327 1534 if (pcidev->irq) {
6cf6b367
HS
1535 ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
1536 dev->board_name, dev);
1537 if (ret == 0) {
1538 dev->irq = pcidev->irq;
1539
cb578327 1540 pci9118_alloc_dma(dev);
6cf6b367
HS
1541 }
1542 }
f3b81d54
IA
1543
1544 if (ext_mux > 0) {
1545 if (ext_mux > 256)
1546 ext_mux = 256; /* max 256 channels! */
1547 if (softsshdelay > 0)
1548 if (ext_mux > 128)
1549 ext_mux = 128;
32502f5a 1550 devpriv->usemux = 1;
f3b81d54
IA
1551 } else {
1552 devpriv->usemux = 0;
3063d6de
MD
1553 }
1554
f3b81d54
IA
1555 if (softsshdelay < 0) {
1556 /* select sample&hold signal polarity */
1557 devpriv->softsshdelay = -softsshdelay;
3063d6de
MD
1558 devpriv->softsshsample = 0x80;
1559 devpriv->softsshhold = 0x00;
1560 } else {
f3b81d54 1561 devpriv->softsshdelay = softsshdelay;
3063d6de
MD
1562 devpriv->softsshsample = 0x00;
1563 devpriv->softsshhold = 0x80;
1564 }
1565
c945a1d1
HS
1566 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
1567 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
242467bd 1568 /* Enable parity check for parity error */
3063d6de 1569
2f0b9d08 1570 ret = comedi_alloc_subdevices(dev, 4);
8b6c5694 1571 if (ret)
3063d6de
MD
1572 return ret;
1573
76c1b7bc 1574 /* Analog Input subdevice */
17c7ac91 1575 s = &dev->subdevices[0];
76c1b7bc
HS
1576 s->type = COMEDI_SUBD_AI;
1577 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
32502f5a 1578 s->n_chan = (devpriv->usemux) ? ext_mux : 16;
76c1b7bc
HS
1579 s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff;
1580 s->range_table = board->is_hg ? &pci9118hg_ai_range
1581 : &pci9118_ai_range;
649a7d15 1582 s->insn_read = pci9118_ai_insn_read;
19cf54dd
HS
1583 if (dev->irq) {
1584 dev->read_subdev = s;
76c1b7bc 1585 s->subdev_flags |= SDF_CMD_READ;
dd2907c3 1586 s->len_chanlist = 255;
76c1b7bc
HS
1587 s->do_cmdtest = pci9118_ai_cmdtest;
1588 s->do_cmd = pci9118_ai_cmd;
1589 s->cancel = pci9118_ai_cancel;
1590 s->munge = pci9118_ai_munge;
19cf54dd 1591 }
3063d6de 1592
34607db8
HS
1593 if (s->maxdata == 0xffff) {
1594 /*
1595 * 16-bit samples are from an ADS7805 A/D converter.
1596 * Minimum sampling rate is 10us.
1597 */
1598 devpriv->ai_ns_min = 10000;
1599 } else {
1600 /*
1601 * 12-bit samples are from an ADS7800 A/D converter.
1602 * Minimum sampling rate is 3us.
1603 */
1604 devpriv->ai_ns_min = 3000;
1605 }
1606
949dcfce 1607 /* Analog Output subdevice */
17c7ac91 1608 s = &dev->subdevices[1];
949dcfce
HS
1609 s->type = COMEDI_SUBD_AO;
1610 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1611 s->n_chan = 2;
1612 s->maxdata = 0x0fff;
1613 s->range_table = &range_bipolar10;
3cb3fc0a 1614 s->insn_write = pci9118_ao_insn_write;
458a76f4
HS
1615
1616 ret = comedi_alloc_subdev_readback(s);
1617 if (ret)
1618 return ret;
1619
1620 /* the analog outputs were reset to 0V, make the readback match */
1621 for (i = 0; i < s->n_chan; i++)
1622 s->readback[i] = 2047;
3063d6de 1623
32034aaf 1624 /* Digital Input subdevice */
17c7ac91 1625 s = &dev->subdevices[2];
32034aaf
HS
1626 s->type = COMEDI_SUBD_DI;
1627 s->subdev_flags = SDF_READABLE;
1628 s->n_chan = 4;
1629 s->maxdata = 1;
1630 s->range_table = &range_digital;
f300fab2 1631 s->insn_bits = pci9118_di_insn_bits;
3063d6de 1632
1e9879f7 1633 /* Digital Output subdevice */
17c7ac91 1634 s = &dev->subdevices[3];
1e9879f7
HS
1635 s->type = COMEDI_SUBD_DO;
1636 s->subdev_flags = SDF_WRITABLE;
1637 s->n_chan = 4;
1638 s->maxdata = 1;
1639 s->range_table = &range_digital;
8df6166b 1640 s->insn_bits = pci9118_do_insn_bits;
3063d6de 1641
304e2be1
HS
1642 /* get the current state of the digital outputs */
1643 s->state = inl(dev->iobase + PCI9118_DIO_REG) >> 4;
1644
3063d6de
MD
1645 return 0;
1646}
1647
f3b81d54
IA
1648static int pci9118_attach(struct comedi_device *dev,
1649 struct comedi_devconfig *it)
1650{
f3b81d54 1651 struct pci_dev *pcidev;
9e531485 1652 int ext_mux, softsshdelay;
f3b81d54
IA
1653
1654 ext_mux = it->options[2];
f3b81d54 1655 softsshdelay = it->options[4];
f3b81d54 1656
f3b81d54
IA
1657 pcidev = pci9118_find_pci(dev, it);
1658 if (!pcidev)
1659 return -EIO;
1660 comedi_set_hw_dev(dev, &pcidev->dev);
1661
9e531485 1662 return pci9118_common_attach(dev, ext_mux, softsshdelay);
f3b81d54
IA
1663}
1664
a690b7e5 1665static int pci9118_auto_attach(struct comedi_device *dev,
83defe83 1666 unsigned long context)
15358a7f
IA
1667{
1668 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
25a8aaf0 1669 const struct pci9118_boardinfo *board = NULL;
15358a7f 1670
25a8aaf0
HS
1671 if (context < ARRAY_SIZE(pci9118_boards))
1672 board = &pci9118_boards[context];
83defe83
HS
1673 if (!board)
1674 return -ENODEV;
1675 dev->board_ptr = board;
1676 dev->board_name = board->name;
1677
15358a7f
IA
1678 /*
1679 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
1680 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
1681 */
1682 pci_dev_get(pcidev);
9e531485
HS
1683 /* no external mux, no sample-hold delay */
1684 return pci9118_common_attach(dev, 0, 0);
15358a7f
IA
1685}
1686
484ecc95 1687static void pci9118_detach(struct comedi_device *dev)
3063d6de 1688{
c945a1d1
HS
1689 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1690
aac307f9
HS
1691 if (dev->iobase)
1692 pci9118_reset(dev);
1693 comedi_pci_detach(dev);
b9ca5508 1694 pci9118_free_dma(dev);
7f072f54 1695 if (pcidev)
c945a1d1 1696 pci_dev_put(pcidev);
3063d6de
MD
1697}
1698
618fc38f
HS
1699static struct comedi_driver adl_pci9118_driver = {
1700 .driver_name = "adl_pci9118",
1701 .module = THIS_MODULE,
1702 .attach = pci9118_attach,
15358a7f 1703 .auto_attach = pci9118_auto_attach,
618fc38f 1704 .detach = pci9118_detach,
25a8aaf0
HS
1705 .num_names = ARRAY_SIZE(pci9118_boards),
1706 .board_name = &pci9118_boards[0].name,
1707 .offset = sizeof(struct pci9118_boardinfo),
618fc38f
HS
1708};
1709
a690b7e5 1710static int adl_pci9118_pci_probe(struct pci_dev *dev,
b8f4ac23 1711 const struct pci_device_id *id)
618fc38f 1712{
b8f4ac23
HS
1713 return comedi_pci_auto_config(dev, &adl_pci9118_driver,
1714 id->driver_data);
618fc38f
HS
1715}
1716
83defe83 1717/* FIXME: All the supported board types have the same device ID! */
41e043fc 1718static const struct pci_device_id adl_pci9118_pci_table[] = {
83defe83
HS
1719 { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118DG },
1720/* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HG }, */
1721/* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HR }, */
618fc38f
HS
1722 { 0 }
1723};
1724MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
1725
1726static struct pci_driver adl_pci9118_pci_driver = {
1727 .name = "adl_pci9118",
1728 .id_table = adl_pci9118_pci_table,
1729 .probe = adl_pci9118_pci_probe,
9901a4d7 1730 .remove = comedi_pci_auto_unconfig,
618fc38f
HS
1731};
1732module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
90f703d3
AT
1733
1734MODULE_AUTHOR("Comedi http://www.comedi.org");
1735MODULE_DESCRIPTION("Comedi low-level driver");
1736MODULE_LICENSE("GPL");
This page took 1.01031 seconds and 5 git commands to generate.