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