]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/adl_pci9118.c
staging: comedi: comedi_pci: change the comedi_pci_auto_config() 'context'
[mirror_ubuntu-hirsute-kernel.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 *
10*/
11/*
12Driver: adl_pci9118
13Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
14Author: Michal Dobes <dobes@tesnet.cz>
15Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
16 PCI-9118HR (pci9118hr)
17Status: works
18
19This driver supports AI, AO, DI and DO subdevices.
20AI subdevice supports cmd and insn interface,
21other subdevices support only insn interface.
22For AI:
23- If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
24- If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
25- If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
25985edc 26- It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
3063d6de
MD
27 cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
28- If return value of cmdtest is 5 then you've bad channel list
29 (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
30 ranges).
31
32There are some hardware limitations:
33a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
34 ended inputs.
35b) DMA transfers must have the length aligned to two samples (32 bit),
36 so there is some problems if cmd->chanlist_len is odd. This driver tries
37 bypass this with adding one sample to the end of the every scan and discard
38 it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
39 and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
40 with interrupt after every sample.
41c) If isn't used DMA then you can use only mode where
42 cmd->scan_begin_src=TRIG_FOLLOW.
43
44Configuration options:
45 [0] - PCI bus of device (optional)
46 [1] - PCI slot of device (optional)
d607c781
MD
47 If bus/slot is not specified, then first available PCI
48 card will be used.
3063d6de 49 [2] - 0= standard 8 DIFF/16 SE channels configuration
d607c781 50 n = external multiplexer connected, 1 <= n <= 256
3063d6de 51 [3] - 0=autoselect DMA or EOC interrupts operation
d607c781
MD
52 1 = disable DMA mode
53 3 = disable DMA and INT, only insn interface will work
3063d6de 54 [4] - sample&hold signal - card can generate signal for external S&H board
d607c781
MD
55 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
56 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
57 long delay is requested in ns and sign polarity of the hold
58 (in this case external multiplexor can serve only 128 channels)
3063d6de 59 [5] - 0=stop measure on all hardware errors
d607c781 60 2 | = ignore ADOR - A/D Overrun status
3063d6de
MD
61 8|=ignore Bover - A/D Burst Mode Overrun status
62 256|=ignore nFull - A/D FIFO Full status
63
64*/
15358a7f
IA
65
66/*
67 * FIXME
68 *
69 * All the supported boards have the same PCI vendor and device IDs, so
70 * auto-attachment of PCI devices will always find the first board type.
71 *
72 * Perhaps the boards have different subdevice IDs that we could use to
73 * distinguish them?
74 *
75 * Need some device attributes so the board type can be corrected after
76 * attachment if necessary, and possibly to set other options supported by
77 * manual attachment.
78 */
3063d6de 79
33782dd5 80#include <linux/pci.h>
3063d6de 81#include <linux/delay.h>
5a0e3ad6 82#include <linux/gfp.h>
70265d24 83#include <linux/interrupt.h>
845d131e 84#include <linux/io.h>
3063d6de 85
33782dd5
HS
86#include "../comedidev.h"
87
3063d6de
MD
88#include "amcc_s5933.h"
89#include "8253.h"
3063d6de
MD
90#include "comedi_fc.h"
91
92/* paranoid checks are broken */
242467bd
MD
93#undef PCI9118_PARANOIDCHECK /*
94 * if defined, then is used code which control
95 * correct channel number on every 12 bit sample
96 */
3063d6de 97
3063d6de 98#define IORANGE_9118 64 /* I hope */
242467bd
MD
99#define PCI9118_CHANLEN 255 /*
100 * len of chanlist, some source say 256,
101 * but reality looks like 255 :-(
102 */
3063d6de 103
d5a2ffd8
UKK
104#define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
105#define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
106#define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
3063d6de
MD
107#define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
108#define PCI9118_AD_DATA 0x10 /* R: A/D data */
109#define PCI9118_DA1 0x10 /* W: D/A registers */
110#define PCI9118_DA2 0x14
111#define PCI9118_ADSTAT 0x18 /* R: A/D status register */
112#define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
113#define PCI9118_DI 0x1c /* R: digi input register */
114#define PCI9118_DO 0x1c /* W: digi output register */
115#define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
116#define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
117#define PCI9118_BURST 0x28 /* W: A/D burst number register */
118#define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
119#define PCI9118_ADFUNC 0x30 /* W: A/D function register */
120#define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
121#define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
122#define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
123
0f04c356 124/* bits from A/D control register (PCI9118_ADCNTRL) */
3063d6de
MD
125#define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
126#define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
127#define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
242467bd
MD
128#define AdControl_ExtG 0x10 /*
129 * 1=8254 countrol controlled by TGIN(pin 46),
130 * 0=controlled by SoftG
131 */
132#define AdControl_ExtM 0x08 /*
133 * 1=external hardware trigger (pin 44),
134 * 0=internal trigger
135 */
136#define AdControl_TmrTr 0x04 /*
137 * 1=8254 is iternal trigger source,
138 * 0=software trigger is source
139 * (register PCI9118_SOFTTRG)
140 */
3063d6de
MD
141#define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
142#define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
143
0f04c356 144/* bits from A/D function register (PCI9118_ADFUNC) */
242467bd
MD
145#define AdFunction_PDTrg 0x80 /*
146 * 1=positive,
147 * 0=negative digital trigger
148 * (only positive is correct)
149 */
150#define AdFunction_PETrg 0x40 /*
151 * 1=positive,
152 * 0=negative external trigger
153 * (only positive is correct)
154 */
3063d6de
MD
155#define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
156#define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
242467bd
MD
157#define AdFunction_BS 0x08 /*
158 * 1=burst mode start,
159 * 0=burst mode stop
160 */
161#define AdFunction_PM 0x04 /*
162 * 1=post trigger mode,
163 * 0=not post trigger
164 */
165#define AdFunction_AM 0x02 /*
166 * 1=about trigger mode,
167 * 0=not about trigger
168 */
3063d6de
MD
169#define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
170
0f04c356 171/* bits from A/D status register (PCI9118_ADSTAT) */
3063d6de
MD
172#define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
173#define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
174#define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
175#define AdStatus_Acmp 0x020 /* */
176#define AdStatus_DTH 0x010 /* 1=external digital trigger */
177#define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
178#define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
179#define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
180#define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
181
0f04c356
BP
182/* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
183/* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
3063d6de
MD
184#define Int_Timer 0x08 /* timer interrupt */
185#define Int_About 0x04 /* about trigger complete */
186#define Int_Hfull 0x02 /* A/D FIFO hlaf full */
187#define Int_DTrg 0x01 /* external digital trigger */
188
189#define START_AI_EXT 0x01 /* start measure on external trigger */
190#define STOP_AI_EXT 0x02 /* stop measure on external trigger */
191#define START_AI_INT 0x04 /* start measure on internal trigger */
192#define STOP_AI_INT 0x08 /* stop measure on internal trigger */
193
194#define EXTTRG_AI 0 /* ext trg is used by AI */
195
9ced1de6 196static const struct comedi_lrange range_pci9118dg_hr = { 8, {
0a85b6f0
MT
197 BIP_RANGE(5),
198 BIP_RANGE(2.5),
199 BIP_RANGE(1.25),
200 BIP_RANGE(0.625),
201 UNI_RANGE(10),
202 UNI_RANGE(5),
203 UNI_RANGE(2.5),
204 UNI_RANGE(1.25)
205 }
3063d6de
MD
206};
207
9ced1de6 208static const struct comedi_lrange range_pci9118hg = { 8, {
0a85b6f0
MT
209 BIP_RANGE(5),
210 BIP_RANGE(0.5),
211 BIP_RANGE(0.05),
212 BIP_RANGE(0.005),
213 UNI_RANGE(10),
214 UNI_RANGE(1),
215 UNI_RANGE(0.1),
216 UNI_RANGE(0.01)
217 }
3063d6de
MD
218};
219
242467bd
MD
220#define PCI9118_BIPOLAR_RANGES 4 /*
221 * used for test on mixture
222 * of BIP/UNI ranges
223 */
3063d6de 224
193a21e4 225struct boardtype {
242467bd 226 const char *name; /* board name */
00d93194 227 int device_id; /* PCI device ID of card */
242467bd
MD
228 int iorange_amcc; /* iorange for own S5933 region */
229 int iorange_9118; /* pass thru card region size */
230 int n_aichan; /* num of A/D chans */
231 int n_aichand; /* num of A/D chans in diff mode */
232 int mux_aichan; /*
233 * num of A/D chans with
234 * external multiplexor
235 */
236 int n_aichanlist; /* len of chanlist */
237 int n_aochan; /* num of D/A chans */
238 int ai_maxdata; /* resolution of A/D */
239 int ao_maxdata; /* resolution of D/A */
240 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
241 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
242 unsigned int ai_ns_min; /* max sample speed of card v ns */
243 unsigned int ai_pacer_min; /*
244 * minimal pacer value
245 * (c1*c2 or c1 in burst)
246 */
247 int half_fifo_size; /* size of FIFO/2 */
3063d6de 248
193a21e4 249};
3063d6de 250
15358a7f
IA
251static const struct boardtype boardtypes[] = {
252 {
253 .name = "pci9118dg",
254 .device_id = 0x80d9,
255 .iorange_amcc = AMCC_OP_REG_SIZE,
256 .iorange_9118 = IORANGE_9118,
257 .n_aichan = 16,
258 .n_aichand = 8,
259 .mux_aichan = 256,
260 .n_aichanlist = PCI9118_CHANLEN,
261 .n_aochan = 2,
262 .ai_maxdata = 0x0fff,
263 .ao_maxdata = 0x0fff,
264 .rangelist_ai = &range_pci9118dg_hr,
265 .rangelist_ao = &range_bipolar10,
266 .ai_ns_min = 3000,
267 .ai_pacer_min = 12,
268 .half_fifo_size = 512,
269 }, {
270 .name = "pci9118hg",
271 .device_id = 0x80d9,
272 .iorange_amcc = AMCC_OP_REG_SIZE,
273 .iorange_9118 = IORANGE_9118,
274 .n_aichan = 16,
275 .n_aichand = 8,
276 .mux_aichan = 256,
277 .n_aichanlist = PCI9118_CHANLEN,
278 .n_aochan = 2,
279 .ai_maxdata = 0x0fff,
280 .ao_maxdata = 0x0fff,
281 .rangelist_ai = &range_pci9118hg,
282 .rangelist_ao = &range_bipolar10,
283 .ai_ns_min = 3000,
284 .ai_pacer_min = 12,
285 .half_fifo_size = 512,
286 }, {
287 .name = "pci9118hr",
288 .device_id = 0x80d9,
289 .iorange_amcc = AMCC_OP_REG_SIZE,
290 .iorange_9118 = IORANGE_9118,
291 .n_aichan = 16,
292 .n_aichand = 8,
293 .mux_aichan = 256,
294 .n_aichanlist = PCI9118_CHANLEN,
295 .n_aochan = 2,
296 .ai_maxdata = 0xffff,
297 .ao_maxdata = 0x0fff,
298 .rangelist_ai = &range_pci9118dg_hr,
299 .rangelist_ao = &range_bipolar10,
300 .ai_ns_min = 10000,
301 .ai_pacer_min = 40,
302 .half_fifo_size = 512,
303 },
304};
305
5b5fc21b 306struct pci9118_private {
242467bd
MD
307 unsigned long iobase_a; /* base+size for AMCC chip */
308 unsigned int master; /* master capable */
242467bd 309 unsigned int usemux; /* we want to use external multiplexor! */
3063d6de 310#ifdef PCI9118_PARANOIDCHECK
242467bd
MD
311 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
312 * list of
313 * scanned channel
314 */
315 unsigned char chanlistlen; /* number of scanlist */
3063d6de 316#endif
242467bd
MD
317 unsigned char AdControlReg; /* A/D control register */
318 unsigned char IntControlReg; /* Interrupt control register */
319 unsigned char AdFunctionReg; /* A/D function register */
320 char valid; /* driver is ok */
321 char ai_neverending; /* we do unlimited AI */
322 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
323 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
324 unsigned int ai_act_scan; /* how many scans we finished */
325 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
326 unsigned int ai_n_chan; /* how many channels is measured */
327 unsigned int ai_n_scanlen; /* len of actual scanlist */
328 unsigned int ai_n_realscanlen; /*
329 * what we must transfer for one
330 * outgoing scan include front/back adds
331 */
332 unsigned int ai_act_dmapos; /* position in actual real stream */
333 unsigned int ai_add_front; /*
334 * how many channels we must add
335 * before scan to satisfy S&H?
336 */
337 unsigned int ai_add_back; /*
338 * how many channels we must add
339 * before scan to satisfy DMA?
340 */
341 unsigned int *ai_chanlist; /* actual chanlist */
3063d6de
MD
342 unsigned int ai_timer1;
343 unsigned int ai_timer2;
344 unsigned int ai_flags;
242467bd
MD
345 char ai12_startstop; /*
346 * measure can start/stop
347 * on external trigger
348 */
349 unsigned int ai_divisor1, ai_divisor2; /*
350 * divisors for start of measure
351 * on external start
352 */
3063d6de 353 unsigned int ai_data_len;
790c5541 354 short *ai_data;
242467bd
MD
355 short ao_data[2]; /* data output buffer */
356 unsigned int ai_scans; /* number of scans to do */
bc04bec0 357 char dma_doublebuf; /* we can use double buffering */
242467bd
MD
358 unsigned int dma_actbuf; /* which buffer is used now */
359 short *dmabuf_virt[2]; /*
360 * pointers to begin of
361 * DMA buffer
362 */
363 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
364 unsigned int dmabuf_size[2]; /*
365 * size of dma buffer in bytes
366 */
367 unsigned int dmabuf_use_size[2]; /*
368 * which size we may now use
369 * for transfer
370 */
371 unsigned int dmabuf_used_size[2]; /* which size was truly used */
3063d6de 372 unsigned int dmabuf_panic_size[2];
242467bd
MD
373 unsigned int dmabuf_samples[2]; /* size in samples */
374 int dmabuf_pages[2]; /* number of pages in buffer */
375 unsigned char cnt0_users; /*
376 * bit field of 8254 CNT0 users
377 * (0-unused, 1-AO, 2-DI, 3-DO)
378 */
379 unsigned char exttrg_users; /*
380 * bit field of external trigger
381 * users(0-AI, 1-AO, 2-DI, 3-DO)
382 */
383 unsigned int cnt0_divisor; /* actual CNT0 divisor */
384 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
385 unsigned short,
386 unsigned int,
387 unsigned short); /*
388 * ptr to actual interrupt
389 * AI function
390 */
391 unsigned char ai16bits; /* =1 16 bit card */
392 unsigned char usedma; /* =1 use DMA transfer and not INT */
393 unsigned char useeoshandle; /*
394 * =1 change WAKE_EOS DMA transfer
395 * to fit on every second
396 */
397 unsigned char usessh; /* =1 turn on S&H support */
398 int softsshdelay; /*
399 * >0 use software S&H,
400 * numer is requested delay in ns
401 */
402 unsigned char softsshsample; /*
403 * polarity of S&H signal
404 * in sample state
405 */
406 unsigned char softsshhold; /*
407 * polarity of S&H signal
408 * in hold state
409 */
410 unsigned int ai_maskerr; /* which warning was printed */
411 unsigned int ai_maskharderr; /* on which error bits stops */
412 unsigned int ai_inttrig_start; /* TRIG_INT for start */
5b5fc21b 413};
3063d6de 414
0a85b6f0
MT
415static int check_channel_list(struct comedi_device *dev,
416 struct comedi_subdevice *s, int n_chan,
5e49e515
HS
417 unsigned int *chanlist, int frontadd, int backadd)
418{
419 const struct boardtype *this_board = comedi_board(dev);
420 struct pci9118_private *devpriv = dev->private;
421 unsigned int i, differencial = 0, bipolar = 0;
422
423 /* correct channel and range number check itself comedi/range.c */
424 if (n_chan < 1) {
425 comedi_error(dev, "range/channel list is empty!");
426 return 0;
427 }
428 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
f41d2573
IA
429 comedi_error(dev,
430 "range/channel list is too long for actual configuration!\n");
5e49e515
HS
431 return 0;
432 }
433
434 if (CR_AREF(chanlist[0]) == AREF_DIFF)
435 differencial = 1; /* all input must be diff */
436 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
437 bipolar = 1; /* all input must be bipolar */
438 if (n_chan > 1)
439 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
440 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
441 (differencial)) {
442 comedi_error(dev,
443 "Differencial and single ended "
444 "inputs can't be mixtured!");
445 return 0;
446 }
447 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
448 (bipolar)) {
449 comedi_error(dev,
450 "Bipolar and unipolar ranges "
451 "can't be mixtured!");
452 return 0;
453 }
454 if (!devpriv->usemux && differencial &&
455 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
456 comedi_error(dev,
457 "If AREF_DIFF is used then is "
458 "available only first 8 channels!");
459 return 0;
460 }
461 }
462
463 return 1;
464}
465
0a85b6f0
MT
466static int setup_channel_list(struct comedi_device *dev,
467 struct comedi_subdevice *s, int n_chan,
468 unsigned int *chanlist, int rot, int frontadd,
5e49e515
HS
469 int backadd, int usedma, char useeos)
470{
471 struct pci9118_private *devpriv = dev->private;
472 unsigned int i, differencial = 0, bipolar = 0;
473 unsigned int scanquad, gain, ssh = 0x00;
474
475 if (usedma == 1) {
476 rot = 8;
477 usedma = 0;
478 }
479
480 if (CR_AREF(chanlist[0]) == AREF_DIFF)
481 differencial = 1; /* all input must be diff */
482 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
483 bipolar = 1; /* all input must be bipolar */
484
485 /* All is ok, so we can setup channel/range list */
486
487 if (!bipolar) {
488 devpriv->AdControlReg |= AdControl_UniP;
489 /* set unibipolar */
490 } else {
491 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
492 /* enable bipolar */
493 }
494
495 if (differencial) {
496 devpriv->AdControlReg |= AdControl_Diff;
497 /* enable diff inputs */
498 } else {
499 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
500 /* set single ended inputs */
501 }
502
503 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
504 /* setup mode */
505
506 outl(2, dev->iobase + PCI9118_SCANMOD);
507 /* gods know why this sequence! */
508 outl(0, dev->iobase + PCI9118_SCANMOD);
509 outl(1, dev->iobase + PCI9118_SCANMOD);
510
511#ifdef PCI9118_PARANOIDCHECK
512 devpriv->chanlistlen = n_chan;
513 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
514 devpriv->chanlist[i] = 0x55aa;
515#endif
516
517 if (frontadd) { /* insert channels for S&H */
518 ssh = devpriv->softsshsample;
519 for (i = 0; i < frontadd; i++) {
520 /* store range list to card */
521 scanquad = CR_CHAN(chanlist[0]);
522 /* get channel number; */
523 gain = CR_RANGE(chanlist[0]);
524 /* get gain number */
525 scanquad |= ((gain & 0x03) << 8);
526 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
527 ssh = devpriv->softsshhold;
528 }
529 }
530
531 for (i = 0; i < n_chan; i++) { /* store range list to card */
532 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
533#ifdef PCI9118_PARANOIDCHECK
534 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
535#endif
536 gain = CR_RANGE(chanlist[i]); /* get gain number */
537 scanquad |= ((gain & 0x03) << 8);
538 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
539 }
540
541 if (backadd) { /* insert channels for fit onto 32bit DMA */
542 for (i = 0; i < backadd; i++) { /* store range list to card */
543 scanquad = CR_CHAN(chanlist[0]);
544 /* get channel number */
545 gain = CR_RANGE(chanlist[0]); /* get gain number */
546 scanquad |= ((gain & 0x03) << 8);
547 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
548 }
549 }
550#ifdef PCI9118_PARANOIDCHECK
551 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
552 /* for 32bit operations */
553 if (useeos) {
554 for (i = 1; i < n_chan; i++) { /* store range list to card */
555 devpriv->chanlist[(n_chan + i) ^ usedma] =
556 (CR_CHAN(chanlist[i]) & 0xf) << rot;
557 }
558 devpriv->chanlist[(2 * n_chan) ^ usedma] =
559 devpriv->chanlist[0 ^ usedma];
560 /* for 32bit operations */
561 useeos = 2;
562 } else {
563 useeos = 1;
564 }
565#endif
566 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
567 /* udelay(100); important delay, or first sample will be crippled */
568
569 return 1; /* we can serve this with scan logic */
570}
3063d6de 571
0a85b6f0
MT
572static int pci9118_insn_read_ai(struct comedi_device *dev,
573 struct comedi_subdevice *s,
574 struct comedi_insn *insn, unsigned int *data)
3063d6de 575{
ae34f6aa 576 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
577 int n, timeout;
578
579 devpriv->AdControlReg = AdControl_Int & 0xff;
580 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
242467bd
MD
581 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
582 /*
583 * positive triggers, no S&H,
584 * no burst, burst stop,
585 * no post trigger,
586 * no about trigger,
587 * trigger stop
588 */
3063d6de
MD
589
590 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
591 return -EINVAL;
592
242467bd 593 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
594
595 for (n = 0; n < insn->n; n++) {
596 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
5f74ea14 597 udelay(2);
3063d6de
MD
598 timeout = 100;
599 while (timeout--) {
600 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
601 goto conv_finish;
5f74ea14 602 udelay(1);
3063d6de
MD
603 }
604
605 comedi_error(dev, "A/D insn timeout");
606 data[n] = 0;
242467bd 607 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
608 return -ETIME;
609
0a85b6f0 610conv_finish:
3063d6de
MD
611 if (devpriv->ai16bits) {
612 data[n] =
0a85b6f0
MT
613 (inl(dev->iobase +
614 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
3063d6de
MD
615 } else {
616 data[n] =
0a85b6f0 617 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
3063d6de
MD
618 }
619 }
620
242467bd 621 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
622 return n;
623
624}
625
0a85b6f0
MT
626static int pci9118_insn_write_ao(struct comedi_device *dev,
627 struct comedi_subdevice *s,
628 struct comedi_insn *insn, unsigned int *data)
3063d6de 629{
ae34f6aa 630 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
631 int n, chanreg, ch;
632
633 ch = CR_CHAN(insn->chanspec);
a41aec1b 634 if (ch)
3063d6de 635 chanreg = PCI9118_DA2;
a41aec1b 636 else
3063d6de 637 chanreg = PCI9118_DA1;
a41aec1b 638
3063d6de
MD
639
640 for (n = 0; n < insn->n; n++) {
641 outl(data[n], dev->iobase + chanreg);
642 devpriv->ao_data[ch] = data[n];
643 }
644
645 return n;
646}
647
0a85b6f0
MT
648static int pci9118_insn_read_ao(struct comedi_device *dev,
649 struct comedi_subdevice *s,
650 struct comedi_insn *insn, unsigned int *data)
3063d6de 651{
ae34f6aa 652 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
653 int n, chan;
654
655 chan = CR_CHAN(insn->chanspec);
656 for (n = 0; n < insn->n; n++)
657 data[n] = devpriv->ao_data[chan];
658
659 return n;
660}
661
0a85b6f0
MT
662static int pci9118_insn_bits_di(struct comedi_device *dev,
663 struct comedi_subdevice *s,
664 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
665{
666 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
667
a2714e3e 668 return insn->n;
3063d6de
MD
669}
670
0a85b6f0
MT
671static int pci9118_insn_bits_do(struct comedi_device *dev,
672 struct comedi_subdevice *s,
673 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
674{
675 if (data[0]) {
676 s->state &= ~data[0];
677 s->state |= (data[0] & data[1]);
678 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
679 }
680 data[1] = s->state;
681
a2714e3e 682 return insn->n;
3063d6de
MD
683}
684
da91b269 685static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
3063d6de 686{
ae34f6aa
HS
687 struct pci9118_private *devpriv = dev->private;
688
3063d6de 689 devpriv->AdFunctionReg =
0a85b6f0 690 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
3063d6de
MD
691 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
692 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
693 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
0a85b6f0 694 dev->iobase + PCI9118_CNT0);
3063d6de 695 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
0a85b6f0 696 dev->iobase + PCI9118_CNT0);
3063d6de
MD
697 devpriv->AdFunctionReg |= AdFunction_Start;
698 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
699}
700
da91b269 701static unsigned int defragment_dma_buffer(struct comedi_device *dev,
0a85b6f0
MT
702 struct comedi_subdevice *s,
703 short *dma_buffer,
704 unsigned int num_samples)
3063d6de 705{
ae34f6aa 706 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
707 unsigned int i = 0, j = 0;
708 unsigned int start_pos = devpriv->ai_add_front,
0a85b6f0 709 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
3063d6de 710 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
0a85b6f0 711 devpriv->ai_add_back;
3063d6de
MD
712
713 for (i = 0; i < num_samples; i++) {
714 if (devpriv->ai_act_dmapos >= start_pos &&
0a85b6f0 715 devpriv->ai_act_dmapos < stop_pos) {
3063d6de
MD
716 dma_buffer[j++] = dma_buffer[i];
717 }
718 devpriv->ai_act_dmapos++;
719 devpriv->ai_act_dmapos %= raw_scanlen;
720 }
721
722 return j;
723}
724
d6269644 725static int move_block_from_dma(struct comedi_device *dev,
0a85b6f0
MT
726 struct comedi_subdevice *s,
727 short *dma_buffer,
728 unsigned int num_samples)
3063d6de 729{
ae34f6aa 730 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
731 unsigned int num_bytes;
732
733 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
734 devpriv->ai_act_scan +=
0a85b6f0 735 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
3063d6de
MD
736 s->async->cur_chan += num_samples;
737 s->async->cur_chan %= devpriv->ai_n_scanlen;
738 num_bytes =
0a85b6f0
MT
739 cfc_write_array_to_buffer(s, dma_buffer,
740 num_samples * sizeof(short));
790c5541 741 if (num_bytes < num_samples * sizeof(short))
3063d6de
MD
742 return -1;
743 return 0;
744}
745
5e49e515 746static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
3063d6de 747{
ae34f6aa
HS
748 struct pci9118_private *devpriv = dev->private;
749
5e49e515
HS
750 if (source > 3)
751 return -1; /* incorrect source */
752 devpriv->exttrg_users |= (1 << source);
753 devpriv->IntControlReg |= Int_DTrg;
754 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
755 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
756 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
757 /* allow INT in AMCC */
3063d6de
MD
758 return 0;
759}
760
5e49e515 761static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
3063d6de 762{
ae34f6aa 763 struct pci9118_private *devpriv = dev->private;
a41aec1b 764
5e49e515
HS
765 if (source > 3)
766 return -1; /* incorrect source */
767 devpriv->exttrg_users &= ~(1 << source);
768 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
769 devpriv->IntControlReg &= ~Int_DTrg;
770 if (!devpriv->IntControlReg) /* all IRQ disabled */
771 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
772 (~0x00001f00),
773 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
774 /* disable int in AMCC */
775 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
3063d6de 776 }
5e49e515 777 return 0;
3063d6de
MD
778}
779
5e49e515
HS
780static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
781 struct comedi_subdevice *s,
782 unsigned int *tim1, unsigned int *tim2,
783 unsigned int flags, int chans,
784 unsigned int *div1, unsigned int *div2,
785 char usessh, unsigned int chnsshfront)
3063d6de 786{
5e49e515 787 const struct boardtype *this_board = comedi_board(dev);
ae34f6aa 788 struct pci9118_private *devpriv = dev->private;
3063d6de 789
5e49e515
HS
790 switch (mode) {
791 case 1:
792 case 4:
793 if (*tim2 < this_board->ai_ns_min)
794 *tim2 = this_board->ai_ns_min;
795 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
796 tim2, flags & TRIG_ROUND_NEAREST);
797 break;
798 case 2:
799 if (*tim2 < this_board->ai_ns_min)
800 *tim2 = this_board->ai_ns_min;
801 *div1 = *tim2 / devpriv->i8254_osc_base;
802 /* convert timer (burst) */
803 if (*div1 < this_board->ai_pacer_min)
804 *div1 = this_board->ai_pacer_min;
805 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
806 *div2 = *div2 / *div1; /* major timer is c1*c2 */
807 if (*div2 < chans)
808 *div2 = chans;
809
810 *tim2 = *div1 * devpriv->i8254_osc_base;
811 /* real convert timer */
812
8289ad05 813 if (usessh && (chnsshfront == 0)) /* use BSSH signal */
5e49e515
HS
814 if (*div2 < (chans + 2))
815 *div2 = chans + 2;
816
817 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
818 break;
819 }
820}
821
822static void start_pacer(struct comedi_device *dev, int mode,
823 unsigned int divisor1, unsigned int divisor2)
824{
825 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
826 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
827/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
828 udelay(1);
829
830 if ((mode == 1) || (mode == 2) || (mode == 4)) {
831 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
832 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
833 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
834 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
835 }
836}
837
838static int pci9118_ai_cancel(struct comedi_device *dev,
839 struct comedi_subdevice *s)
840{
841 struct pci9118_private *devpriv = dev->private;
842
843 if (devpriv->usedma)
844 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
845 (~EN_A2P_TRANSFERS),
846 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
847 pci9118_exttrg_del(dev, EXTTRG_AI);
848 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
849 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
850 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
851 /*
852 * positive triggers, no S&H, no burst,
853 * burst stop, no post trigger,
854 * no about trigger, trigger stop
855 */
856 devpriv->AdControlReg = 0x00;
857 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
858 /*
859 * bipolar, S.E., use 8254, stop 8354,
860 * internal trigger, soft trigger,
861 * disable INT and DMA
862 */
863 outl(0, dev->iobase + PCI9118_BURST);
864 outl(1, dev->iobase + PCI9118_SCANMOD);
865 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
866 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
867
868 devpriv->ai_do = 0;
869 devpriv->usedma = 0;
870
871 devpriv->ai_act_scan = 0;
872 devpriv->ai_act_dmapos = 0;
873 s->async->cur_chan = 0;
874 s->async->inttrig = NULL;
875 devpriv->ai_buf_ptr = 0;
876 devpriv->ai_neverending = 0;
877 devpriv->dma_actbuf = 0;
878
879 if (!devpriv->IntControlReg)
880 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
881 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
882 /* allow INT in AMCC */
883
884 return 0;
885}
886
887static char pci9118_decode_error_status(struct comedi_device *dev,
888 struct comedi_subdevice *s,
889 unsigned char m)
890{
891 struct pci9118_private *devpriv = dev->private;
892
893 if (m & 0x100) {
894 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
895 devpriv->ai_maskerr &= ~0x100L;
896 }
897 if (m & 0x008) {
898 comedi_error(dev,
899 "A/D Burst Mode Overrun Status (Fatal Error!)");
900 devpriv->ai_maskerr &= ~0x008L;
901 }
902 if (m & 0x004) {
903 comedi_error(dev, "A/D Over Speed Status (Warning!)");
904 devpriv->ai_maskerr &= ~0x004L;
905 }
906 if (m & 0x002) {
907 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
908 devpriv->ai_maskerr &= ~0x002L;
909 }
910 if (m & devpriv->ai_maskharderr) {
911 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
912 pci9118_ai_cancel(dev, s);
913 comedi_event(dev, s);
914 return 1;
915 }
916
917 return 0;
918}
919
920static void pci9118_ai_munge(struct comedi_device *dev,
921 struct comedi_subdevice *s, void *data,
922 unsigned int num_bytes,
923 unsigned int start_chan_index)
924{
925 struct pci9118_private *devpriv = dev->private;
926 unsigned int i, num_samples = num_bytes / sizeof(short);
927 short *array = data;
928
929 for (i = 0; i < num_samples; i++) {
930 if (devpriv->usedma)
931 array[i] = be16_to_cpu(array[i]);
932 if (devpriv->ai16bits)
933 array[i] ^= 0x8000;
934 else
935 array[i] = (array[i] >> 4) & 0x0fff;
936
937 }
938}
939
940static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
941 struct comedi_subdevice *s,
942 unsigned short int_adstat,
943 unsigned int int_amcc,
944 unsigned short int_daq)
945{
946 struct pci9118_private *devpriv = dev->private;
947 register short sampl;
948
949 s->async->events = 0;
3063d6de
MD
950
951 if (int_adstat & devpriv->ai_maskerr)
952 if (pci9118_decode_error_status(dev, s, int_adstat))
953 return;
954
955 sampl = inw(dev->iobase + PCI9118_AD_DATA);
956
957#ifdef PCI9118_PARANOIDCHECK
958 if (devpriv->ai16bits == 0) {
242467bd
MD
959 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
960 /* data dropout! */
f41d2573
IA
961 dev_info(dev->class_dev,
962 "A/D SAMPL - data dropout: received channel %d, expected %d!\n",
963 sampl & 0x000f,
964 devpriv->chanlist[s->async->cur_chan]);
3063d6de
MD
965 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
966 pci9118_ai_cancel(dev, s);
967 comedi_event(dev, s);
968 return;
969 }
970 }
971#endif
972 cfc_write_to_buffer(s, sampl);
973 s->async->cur_chan++;
242467bd
MD
974 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
975 /* one scan done */
3063d6de
MD
976 s->async->cur_chan %= devpriv->ai_n_scanlen;
977 devpriv->ai_act_scan++;
978 if (!(devpriv->ai_neverending))
242467bd
MD
979 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
980 /* all data sampled */
3063d6de
MD
981 pci9118_ai_cancel(dev, s);
982 s->async->events |= COMEDI_CB_EOA;
983 }
984 }
985
986 if (s->async->events)
987 comedi_event(dev, s);
988}
989
0a85b6f0
MT
990static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
991 struct comedi_subdevice *s,
992 unsigned short int_adstat,
993 unsigned int int_amcc,
994 unsigned short int_daq)
3063d6de 995{
ae34f6aa 996 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
997 unsigned int next_dma_buf, samplesinbuf, sampls, m;
998
999 if (int_amcc & MASTER_ABORT_INT) {
1000 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
1001 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1002 pci9118_ai_cancel(dev, s);
1003 comedi_event(dev, s);
1004 return;
1005 }
1006
1007 if (int_amcc & TARGET_ABORT_INT) {
1008 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
1009 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1010 pci9118_ai_cancel(dev, s);
1011 comedi_event(dev, s);
1012 return;
1013 }
3063d6de 1014 if (int_adstat & devpriv->ai_maskerr)
cf8d3af5 1015 /* if (int_adstat & 0x106) */
3063d6de
MD
1016 if (pci9118_decode_error_status(dev, s, int_adstat))
1017 return;
1018
242467bd
MD
1019 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
1020 /* number of received real samples */
3063d6de 1021
242467bd
MD
1022 if (devpriv->dma_doublebuf) { /*
1023 * switch DMA buffers if is used
1024 * double buffering
1025 */
3063d6de
MD
1026 next_dma_buf = 1 - devpriv->dma_actbuf;
1027 outl(devpriv->dmabuf_hw[next_dma_buf],
0a85b6f0 1028 devpriv->iobase_a + AMCC_OP_REG_MWAR);
3063d6de 1029 outl(devpriv->dmabuf_use_size[next_dma_buf],
0a85b6f0 1030 devpriv->iobase_a + AMCC_OP_REG_MWTC);
3063d6de 1031 devpriv->dmabuf_used_size[next_dma_buf] =
0a85b6f0 1032 devpriv->dmabuf_use_size[next_dma_buf];
3063d6de
MD
1033 if (devpriv->ai_do == 4)
1034 interrupt_pci9118_ai_mode4_switch(dev);
1035 }
1036
1037 if (samplesinbuf) {
242467bd
MD
1038 m = devpriv->ai_data_len >> 1; /*
1039 * how many samples is to
1040 * end of buffer
1041 */
3063d6de
MD
1042 sampls = m;
1043 move_block_from_dma(dev, s,
0a85b6f0
MT
1044 devpriv->dmabuf_virt[devpriv->dma_actbuf],
1045 samplesinbuf);
25985edc 1046 m = m - sampls; /* m= how many samples was transferred */
3063d6de 1047 }
3063d6de
MD
1048
1049 if (!devpriv->ai_neverending)
242467bd
MD
1050 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
1051 /* all data sampled */
3063d6de
MD
1052 pci9118_ai_cancel(dev, s);
1053 s->async->events |= COMEDI_CB_EOA;
1054 }
1055
242467bd 1056 if (devpriv->dma_doublebuf) { /* switch dma buffers */
3063d6de 1057 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
242467bd 1058 } else { /* restart DMA if is not used double buffering */
3063d6de 1059 outl(devpriv->dmabuf_hw[0],
0a85b6f0 1060 devpriv->iobase_a + AMCC_OP_REG_MWAR);
3063d6de 1061 outl(devpriv->dmabuf_use_size[0],
0a85b6f0 1062 devpriv->iobase_a + AMCC_OP_REG_MWTC);
3063d6de
MD
1063 if (devpriv->ai_do == 4)
1064 interrupt_pci9118_ai_mode4_switch(dev);
1065 }
1066
1067 comedi_event(dev, s);
1068}
1069
70265d24 1070static irqreturn_t interrupt_pci9118(int irq, void *d)
3063d6de 1071{
71b5f4f1 1072 struct comedi_device *dev = d;
ae34f6aa 1073 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
1074 unsigned int int_daq = 0, int_amcc, int_adstat;
1075
1076 if (!dev->attached)
242467bd 1077 return IRQ_NONE; /* not fully initialized */
3063d6de 1078
242467bd
MD
1079 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
1080 /* get IRQ reasons from card */
1081 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1082 /* get INT register from AMCC chip */
3063d6de 1083
3063d6de 1084 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
242467bd 1085 return IRQ_NONE; /* interrupt from other source */
3063d6de 1086
242467bd
MD
1087 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1088 /* shutdown IRQ reasons in AMCC */
3063d6de 1089
242467bd
MD
1090 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
1091 /* get STATUS register */
3063d6de
MD
1092
1093 if (devpriv->ai_do) {
1094 if (devpriv->ai12_startstop)
242467bd
MD
1095 if ((int_adstat & AdStatus_DTH) &&
1096 (int_daq & Int_DTrg)) {
1097 /* start stop of measure */
3063d6de
MD
1098 if (devpriv->ai12_startstop & START_AI_EXT) {
1099 devpriv->ai12_startstop &=
0a85b6f0 1100 ~START_AI_EXT;
3063d6de 1101 if (!(devpriv->ai12_startstop &
242467bd
MD
1102 STOP_AI_EXT))
1103 pci9118_exttrg_del
1104 (dev, EXTTRG_AI);
1105 /* deactivate EXT trigger */
1106 start_pacer(dev, devpriv->ai_do,
1107 devpriv->ai_divisor1,
1108 devpriv->ai_divisor2);
1109 /* start pacer */
3063d6de 1110 outl(devpriv->AdControlReg,
242467bd 1111 dev->iobase + PCI9118_ADCNTRL);
3063d6de 1112 } else {
0a85b6f0 1113 if (devpriv->ai12_startstop &
242467bd 1114 STOP_AI_EXT) {
3063d6de 1115 devpriv->ai12_startstop &=
242467bd
MD
1116 ~STOP_AI_EXT;
1117 pci9118_exttrg_del
1118 (dev, EXTTRG_AI);
1119 /* deactivate EXT trigger */
1120 devpriv->ai_neverending = 0;
1121 /*
1122 * well, on next interrupt from
1123 * DMA/EOC measure will stop
1124 */
3063d6de
MD
1125 }
1126 }
1127 }
1128
17c7ac91 1129 (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat,
0a85b6f0 1130 int_amcc, int_daq);
3063d6de
MD
1131
1132 }
1133 return IRQ_HANDLED;
1134}
1135
0a85b6f0
MT
1136static int pci9118_ai_inttrig(struct comedi_device *dev,
1137 struct comedi_subdevice *s, unsigned int trignum)
3063d6de 1138{
ae34f6aa
HS
1139 struct pci9118_private *devpriv = dev->private;
1140
3063d6de
MD
1141 if (trignum != devpriv->ai_inttrig_start)
1142 return -EINVAL;
1143
1144 devpriv->ai12_startstop &= ~START_AI_INT;
1145 s->async->inttrig = NULL;
1146
1147 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1148 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1149 if (devpriv->ai_do != 3) {
1150 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 1151 devpriv->ai_divisor2);
3063d6de
MD
1152 devpriv->AdControlReg |= AdControl_SoftG;
1153 }
1154 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1155
1156 return 1;
1157}
1158
0a85b6f0
MT
1159static int pci9118_ai_cmdtest(struct comedi_device *dev,
1160 struct comedi_subdevice *s,
1161 struct comedi_cmd *cmd)
3063d6de 1162{
ae34f6aa
HS
1163 const struct boardtype *this_board = comedi_board(dev);
1164 struct pci9118_private *devpriv = dev->private;
3063d6de 1165 int err = 0;
22d4b56f 1166 unsigned int flags;
5f35f3f1
GKH
1167 int tmp;
1168 unsigned int divisor1 = 0, divisor2 = 0;
3063d6de 1169
27020ffe 1170 /* Step 1 : check if triggers are trivially valid */
3063d6de 1171
22d4b56f
HS
1172 err |= cfc_check_trigger_src(&cmd->start_src,
1173 TRIG_NOW | TRIG_EXT | TRIG_INT);
3063d6de 1174
22d4b56f 1175 flags = TRIG_FOLLOW;
a41aec1b 1176 if (devpriv->master)
22d4b56f
HS
1177 flags |= TRIG_TIMER | TRIG_EXT;
1178 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
3063d6de 1179
22d4b56f 1180 flags = TRIG_TIMER | TRIG_EXT;
a41aec1b 1181 if (devpriv->master)
22d4b56f
HS
1182 flags |= TRIG_NOW;
1183 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
3063d6de 1184
22d4b56f
HS
1185 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1186 err |= cfc_check_trigger_src(&cmd->stop_src,
1187 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
3063d6de
MD
1188
1189 if (err)
1190 return 1;
1191
27020ffe 1192 /* Step 2a : make sure trigger sources are unique */
3063d6de 1193
27020ffe
HS
1194 err |= cfc_check_trigger_is_unique(cmd->start_src);
1195 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1196 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1197 err |= cfc_check_trigger_is_unique(cmd->stop_src);
3063d6de 1198
27020ffe 1199 /* Step 2b : and mutually compatible */
3063d6de 1200
27020ffe
HS
1201 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1202 err |= -EINVAL;
3063d6de 1203
27020ffe
HS
1204 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
1205 err |= -EINVAL;
3063d6de
MD
1206
1207 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
27020ffe
HS
1208 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1209 err |= -EINVAL;
3063d6de
MD
1210
1211 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
27020ffe
HS
1212 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1213 err |= -EINVAL;
3063d6de 1214
27020ffe
HS
1215 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1216 err |= -EINVAL;
3063d6de
MD
1217
1218 if (err)
1219 return 2;
1220
1b443313 1221 /* Step 3: check if arguments are trivially valid */
3063d6de
MD
1222
1223 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1b443313 1224 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
3063d6de
MD
1225
1226 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1b443313 1227 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
3063d6de
MD
1228
1229 if ((cmd->scan_begin_src == TRIG_TIMER) &&
0a85b6f0 1230 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
3063d6de
MD
1231 cmd->scan_begin_src = TRIG_FOLLOW;
1232 cmd->convert_arg = cmd->scan_begin_arg;
1233 cmd->scan_begin_arg = 0;
1234 }
1235
1236 if (cmd->scan_begin_src == TRIG_TIMER)
1b443313
HS
1237 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1238 this_board->ai_ns_min);
3063d6de
MD
1239
1240 if (cmd->scan_begin_src == TRIG_EXT)
1241 if (cmd->scan_begin_arg) {
1242 cmd->scan_begin_arg = 0;
1b443313
HS
1243 err |= -EINVAL;
1244 err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg,
1245 65535);
3063d6de
MD
1246 }
1247
1248 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1b443313
HS
1249 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1250 this_board->ai_ns_min);
3063d6de
MD
1251
1252 if (cmd->convert_src == TRIG_EXT)
1b443313 1253 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
3063d6de 1254
1b443313
HS
1255 if (cmd->stop_src == TRIG_COUNT)
1256 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1257 else /* TRIG_NONE */
1258 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
3063d6de 1259
1b443313
HS
1260 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
1261 err |= cfc_check_trigger_arg_max(&cmd->chanlist_len,
1262 this_board->n_aichanlist);
3063d6de 1263
1b443313
HS
1264 err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg,
1265 cmd->chanlist_len);
3063d6de
MD
1266
1267 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1268 cmd->scan_end_arg =
0a85b6f0 1269 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1b443313 1270 err |= -EINVAL;
3063d6de
MD
1271 }
1272
1273 if (err)
1274 return 3;
1275
1276 /* step 4: fix up any arguments */
1277
1278 if (cmd->scan_begin_src == TRIG_TIMER) {
1279 tmp = cmd->scan_begin_arg;
3063d6de 1280 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
0a85b6f0
MT
1281 &divisor2, &cmd->scan_begin_arg,
1282 cmd->flags & TRIG_ROUND_MASK);
3063d6de
MD
1283 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1284 cmd->scan_begin_arg = this_board->ai_ns_min;
1285 if (tmp != cmd->scan_begin_arg)
1286 err++;
1287 }
1288
1289 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1290 tmp = cmd->convert_arg;
1291 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
0a85b6f0
MT
1292 &divisor2, &cmd->convert_arg,
1293 cmd->flags & TRIG_ROUND_MASK);
3063d6de
MD
1294 if (cmd->convert_arg < this_board->ai_ns_min)
1295 cmd->convert_arg = this_board->ai_ns_min;
1296 if (tmp != cmd->convert_arg)
1297 err++;
1298 if (cmd->scan_begin_src == TRIG_TIMER
0a85b6f0 1299 && cmd->convert_src == TRIG_NOW) {
3063d6de
MD
1300 if (cmd->convert_arg == 0) {
1301 if (cmd->scan_begin_arg <
0a85b6f0
MT
1302 this_board->ai_ns_min *
1303 (cmd->scan_end_arg + 2)) {
3063d6de 1304 cmd->scan_begin_arg =
0a85b6f0
MT
1305 this_board->ai_ns_min *
1306 (cmd->scan_end_arg + 2);
3063d6de
MD
1307 err++;
1308 }
1309 } else {
1310 if (cmd->scan_begin_arg <
0a85b6f0 1311 cmd->convert_arg * cmd->chanlist_len) {
3063d6de 1312 cmd->scan_begin_arg =
0a85b6f0
MT
1313 cmd->convert_arg *
1314 cmd->chanlist_len;
3063d6de
MD
1315 err++;
1316 }
1317 }
1318 }
1319 }
1320
1321 if (err)
1322 return 4;
1323
1324 if (cmd->chanlist)
1325 if (!check_channel_list(dev, s, cmd->chanlist_len,
0a85b6f0 1326 cmd->chanlist, 0, 0))
242467bd 1327 return 5; /* incorrect channels list */
3063d6de
MD
1328
1329 return 0;
1330}
1331
da91b269 1332static int Compute_and_setup_dma(struct comedi_device *dev)
3063d6de 1333{
ae34f6aa 1334 struct pci9118_private *devpriv = dev->private;
3063d6de
MD
1335 unsigned int dmalen0, dmalen1, i;
1336
3063d6de
MD
1337 dmalen0 = devpriv->dmabuf_size[0];
1338 dmalen1 = devpriv->dmabuf_size[1];
242467bd 1339 /* isn't output buff smaller that our DMA buff? */
3063d6de 1340 if (dmalen0 > (devpriv->ai_data_len)) {
242467bd
MD
1341 dmalen0 = devpriv->ai_data_len & ~3L; /*
1342 * align to 32bit down
1343 */
3063d6de
MD
1344 }
1345 if (dmalen1 > (devpriv->ai_data_len)) {
242467bd
MD
1346 dmalen1 = devpriv->ai_data_len & ~3L; /*
1347 * align to 32bit down
1348 */
3063d6de 1349 }
3063d6de 1350
242467bd 1351 /* we want wake up every scan? */
3063d6de
MD
1352 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1353 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
242467bd 1354 /* uff, too short DMA buffer, disable EOS support! */
3063d6de 1355 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
f41d2573
IA
1356 dev_info(dev->class_dev,
1357 "WAR: DMA0 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1358 dmalen0, devpriv->ai_n_realscanlen << 1);
3063d6de 1359 } else {
242467bd 1360 /* short first DMA buffer to one scan */
3063d6de 1361 dmalen0 = devpriv->ai_n_realscanlen << 1;
3063d6de
MD
1362 if (devpriv->useeoshandle)
1363 dmalen0 += 2;
1364 if (dmalen0 < 4) {
f41d2573
IA
1365 dev_info(dev->class_dev,
1366 "ERR: DMA0 buf len bug? (%d<4)\n",
1367 dmalen0);
3063d6de
MD
1368 dmalen0 = 4;
1369 }
1370 }
1371 }
1372 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1373 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
242467bd 1374 /* uff, too short DMA buffer, disable EOS support! */
3063d6de 1375 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
f41d2573
IA
1376 dev_info(dev->class_dev,
1377 "WAR: DMA1 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1378 dmalen1, devpriv->ai_n_realscanlen << 1);
3063d6de 1379 } else {
242467bd 1380 /* short second DMA buffer to one scan */
3063d6de 1381 dmalen1 = devpriv->ai_n_realscanlen << 1;
3063d6de
MD
1382 if (devpriv->useeoshandle)
1383 dmalen1 -= 2;
1384 if (dmalen1 < 4) {
f41d2573
IA
1385 dev_info(dev->class_dev,
1386 "ERR: DMA1 buf len bug? (%d<4)\n",
1387 dmalen1);
3063d6de
MD
1388 dmalen1 = 4;
1389 }
1390 }
1391 }
1392
242467bd 1393 /* transfer without TRIG_WAKE_EOS */
3063d6de 1394 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
25985edc 1395 /* if it's possible then align DMA buffers to length of scan */
3063d6de
MD
1396 i = dmalen0;
1397 dmalen0 =
0a85b6f0
MT
1398 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1399 (devpriv->ai_n_realscanlen << 1);
3063d6de
MD
1400 dmalen0 &= ~3L;
1401 if (!dmalen0)
242467bd 1402 dmalen0 = i; /* uff. very long scan? */
3063d6de
MD
1403 i = dmalen1;
1404 dmalen1 =
0a85b6f0
MT
1405 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1406 (devpriv->ai_n_realscanlen << 1);
3063d6de
MD
1407 dmalen1 &= ~3L;
1408 if (!dmalen1)
242467bd
MD
1409 dmalen1 = i; /* uff. very long scan? */
1410 /*
1411 * if measure isn't neverending then test, if it fits whole
1412 * into one or two DMA buffers
1413 */
3063d6de 1414 if (!devpriv->ai_neverending) {
242467bd 1415 /* fits whole measure into one DMA buffer? */
3063d6de 1416 if (dmalen0 >
0a85b6f0
MT
1417 ((devpriv->ai_n_realscanlen << 1) *
1418 devpriv->ai_scans)) {
3063d6de 1419 dmalen0 =
0a85b6f0
MT
1420 (devpriv->ai_n_realscanlen << 1) *
1421 devpriv->ai_scans;
3063d6de 1422 dmalen0 &= ~3L;
242467bd
MD
1423 } else { /*
1424 * fits whole measure into
1425 * two DMA buffer?
1426 */
3063d6de 1427 if (dmalen1 >
0a85b6f0
MT
1428 ((devpriv->ai_n_realscanlen << 1) *
1429 devpriv->ai_scans - dmalen0))
3063d6de 1430 dmalen1 =
0a85b6f0
MT
1431 (devpriv->ai_n_realscanlen << 1) *
1432 devpriv->ai_scans - dmalen0;
3063d6de
MD
1433 dmalen1 &= ~3L;
1434 }
1435 }
1436 }
1437
242467bd 1438 /* these DMA buffer size will be used */
3063d6de
MD
1439 devpriv->dma_actbuf = 0;
1440 devpriv->dmabuf_use_size[0] = dmalen0;
1441 devpriv->dmabuf_use_size[1] = dmalen1;
1442
3063d6de
MD
1443#if 0
1444 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1445 devpriv->dmabuf_panic_size[0] =
0a85b6f0
MT
1446 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1447 1) * devpriv->ai_n_scanlen * sizeof(short);
3063d6de 1448 devpriv->dmabuf_panic_size[1] =
0a85b6f0
MT
1449 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1450 1) * devpriv->ai_n_scanlen * sizeof(short);
3063d6de
MD
1451 } else {
1452 devpriv->dmabuf_panic_size[0] =
0a85b6f0 1453 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
3063d6de 1454 devpriv->dmabuf_panic_size[1] =
0a85b6f0 1455 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
3063d6de
MD
1456 }
1457#endif
1458
242467bd
MD
1459 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1460 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
3063d6de
MD
1461 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1462 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
242467bd 1463 /* init DMA transfer */
3063d6de 1464 outl(0x00000000 | AINT_WRITE_COMPL,
0a85b6f0 1465 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
0f04c356 1466/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
3063d6de
MD
1467
1468 outl(inl(devpriv->iobase_a +
0a85b6f0
MT
1469 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1470 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
242467bd
MD
1471 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1472 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1473 /* allow bus mastering */
3063d6de 1474
3063d6de
MD
1475 return 0;
1476}
1477
0a85b6f0
MT
1478static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1479 struct comedi_subdevice *s)
3063d6de 1480{
ae34f6aa
HS
1481 struct pci9118_private *devpriv = dev->private;
1482
3063d6de
MD
1483 switch (devpriv->ai_do) {
1484 case 1:
1485 devpriv->AdControlReg |= AdControl_TmrTr;
1486 break;
1487 case 2:
1488 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1489 return -EIO;
1490 case 3:
1491 devpriv->AdControlReg |= AdControl_ExtM;
1492 break;
1493 case 4:
1494 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1495 return -EIO;
1496 default:
1497 comedi_error(dev,
0a85b6f0 1498 "pci9118_ai_docmd_sampl() mode number bug!\n");
3063d6de 1499 return -EIO;
95cd17c9 1500 }
3063d6de 1501
242467bd
MD
1502 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1503 /* transfer function */
3063d6de
MD
1504
1505 if (devpriv->ai12_startstop)
242467bd
MD
1506 pci9118_exttrg_add(dev, EXTTRG_AI);
1507 /* activate EXT trigger */
3063d6de
MD
1508
1509 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1510 devpriv->IntControlReg |= Int_Timer;
1511
1512 devpriv->AdControlReg |= AdControl_Int;
1513
242467bd
MD
1514 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1515 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1516 /* allow INT in AMCC */
3063d6de
MD
1517
1518 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1519 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1520 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1521 if (devpriv->ai_do != 3) {
1522 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 1523 devpriv->ai_divisor2);
3063d6de
MD
1524 devpriv->AdControlReg |= AdControl_SoftG;
1525 }
1526 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1527 }
1528
3063d6de
MD
1529 return 0;
1530}
1531
0a85b6f0
MT
1532static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1533 struct comedi_subdevice *s)
3063d6de 1534{
ae34f6aa
HS
1535 struct pci9118_private *devpriv = dev->private;
1536
3063d6de
MD
1537 Compute_and_setup_dma(dev);
1538
1539 switch (devpriv->ai_do) {
1540 case 1:
1541 devpriv->AdControlReg |=
0a85b6f0 1542 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de
MD
1543 break;
1544 case 2:
1545 devpriv->AdControlReg |=
0a85b6f0 1546 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de 1547 devpriv->AdFunctionReg =
0a85b6f0
MT
1548 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1549 AdFunction_BS;
3063d6de
MD
1550 if (devpriv->usessh && (!devpriv->softsshdelay))
1551 devpriv->AdFunctionReg |= AdFunction_BSSH;
1552 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1553 break;
1554 case 3:
1555 devpriv->AdControlReg |=
0a85b6f0 1556 ((AdControl_ExtM | AdControl_Dma) & 0xff);
3063d6de
MD
1557 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1558 break;
1559 case 4:
1560 devpriv->AdControlReg |=
0a85b6f0 1561 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de 1562 devpriv->AdFunctionReg =
0a85b6f0 1563 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
3063d6de
MD
1564 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1565 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1566 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
0a85b6f0 1567 dev->iobase + PCI9118_CNT0);
3063d6de 1568 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
0a85b6f0 1569 dev->iobase + PCI9118_CNT0);
3063d6de
MD
1570 devpriv->AdFunctionReg |= AdFunction_Start;
1571 break;
1572 default:
1573 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1574 return -EIO;
95cd17c9 1575 }
3063d6de
MD
1576
1577 if (devpriv->ai12_startstop) {
242467bd
MD
1578 pci9118_exttrg_add(dev, EXTTRG_AI);
1579 /* activate EXT trigger */
3063d6de
MD
1580 }
1581
242467bd
MD
1582 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1583 /* transfer function */
3063d6de
MD
1584
1585 outl(0x02000000 | AINT_WRITE_COMPL,
0a85b6f0 1586 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
3063d6de
MD
1587
1588 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1589 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1590 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1591 if (devpriv->ai_do != 3) {
1592 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 1593 devpriv->ai_divisor2);
3063d6de
MD
1594 devpriv->AdControlReg |= AdControl_SoftG;
1595 }
1596 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1597 }
1598
3063d6de
MD
1599 return 0;
1600}
1601
da91b269 1602static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
3063d6de 1603{
ae34f6aa
HS
1604 const struct boardtype *this_board = comedi_board(dev);
1605 struct pci9118_private *devpriv = dev->private;
ea6d0d4c 1606 struct comedi_cmd *cmd = &s->async->cmd;
3063d6de
MD
1607 unsigned int addchans = 0;
1608 int ret = 0;
1609
3063d6de
MD
1610 devpriv->ai12_startstop = 0;
1611 devpriv->ai_flags = cmd->flags;
1612 devpriv->ai_n_chan = cmd->chanlist_len;
1613 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1614 devpriv->ai_chanlist = cmd->chanlist;
1615 devpriv->ai_data = s->async->prealloc_buf;
1616 devpriv->ai_data_len = s->async->prealloc_bufsz;
1617 devpriv->ai_timer1 = 0;
1618 devpriv->ai_timer2 = 0;
1619 devpriv->ai_add_front = 0;
1620 devpriv->ai_add_back = 0;
1621 devpriv->ai_maskerr = 0x10e;
1622
242467bd 1623 /* prepare for start/stop conditions */
3063d6de
MD
1624 if (cmd->start_src == TRIG_EXT)
1625 devpriv->ai12_startstop |= START_AI_EXT;
1626 if (cmd->stop_src == TRIG_EXT) {
1627 devpriv->ai_neverending = 1;
1628 devpriv->ai12_startstop |= STOP_AI_EXT;
1629 }
1630 if (cmd->start_src == TRIG_INT) {
1631 devpriv->ai12_startstop |= START_AI_INT;
1632 devpriv->ai_inttrig_start = cmd->start_arg;
1633 s->async->inttrig = pci9118_ai_inttrig;
1634 }
1635#if 0
1636 if (cmd->stop_src == TRIG_INT) {
1637 devpriv->ai_neverending = 1;
1638 devpriv->ai12_startstop |= STOP_AI_INT;
1639 }
1640#endif
1641 if (cmd->stop_src == TRIG_NONE)
1642 devpriv->ai_neverending = 1;
1643 if (cmd->stop_src == TRIG_COUNT) {
1644 devpriv->ai_scans = cmd->stop_arg;
1645 devpriv->ai_neverending = 0;
1646 } else {
1647 devpriv->ai_scans = 0;
1648 }
1649
242467bd 1650 /* use sample&hold signal? */
beb50909 1651 if (cmd->convert_src == TRIG_NOW)
3063d6de 1652 devpriv->usessh = 1;
beb50909
MD
1653 /* yes */
1654 else
3063d6de 1655 devpriv->usessh = 0;
beb50909 1656 /* no */
3063d6de 1657
242467bd
MD
1658 /*
1659 * use additional sample at end of every scan
1660 * to satisty DMA 32 bit transfer?
1661 */
3063d6de
MD
1662 devpriv->ai_add_front = 0;
1663 devpriv->ai_add_back = 0;
1664 devpriv->useeoshandle = 0;
1665 if (devpriv->master) {
1666 devpriv->usedma = 1;
1667 if ((cmd->flags & TRIG_WAKE_EOS) &&
0a85b6f0 1668 (devpriv->ai_n_scanlen == 1)) {
beb50909 1669 if (cmd->convert_src == TRIG_NOW)
3063d6de 1670 devpriv->ai_add_back = 1;
3063d6de 1671 if (cmd->convert_src == TRIG_TIMER) {
242467bd
MD
1672 devpriv->usedma = 0;
1673 /*
1674 * use INT transfer if scanlist
1675 * have only one channel
1676 */
3063d6de
MD
1677 }
1678 }
1679 if ((cmd->flags & TRIG_WAKE_EOS) &&
0a85b6f0
MT
1680 (devpriv->ai_n_scanlen & 1) &&
1681 (devpriv->ai_n_scanlen > 1)) {
3063d6de 1682 if (cmd->scan_begin_src == TRIG_FOLLOW) {
242467bd
MD
1683 /*
1684 * vpriv->useeoshandle=1; // change DMA transfer
1685 * block to fit EOS on every second call
1686 */
1687 devpriv->usedma = 0;
1688 /*
1689 * XXX maybe can be corrected to use 16 bit DMA
1690 */
1691 } else { /*
1692 * well, we must insert one sample
1693 * to end of EOS to meet 32 bit transfer
1694 */
3063d6de
MD
1695 devpriv->ai_add_back = 1;
1696 }
1697 }
242467bd 1698 } else { /* interrupt transfer don't need any correction */
3063d6de
MD
1699 devpriv->usedma = 0;
1700 }
1701
242467bd
MD
1702 /*
1703 * we need software S&H signal?
1704 * It adds two samples before every scan as minimum
1705 */
3063d6de
MD
1706 if (devpriv->usessh && devpriv->softsshdelay) {
1707 devpriv->ai_add_front = 2;
242467bd
MD
1708 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1709 /* move it to front */
3063d6de
MD
1710 devpriv->ai_add_front++;
1711 devpriv->ai_add_back = 0;
1712 }
1713 if (cmd->convert_arg < this_board->ai_ns_min)
1714 cmd->convert_arg = this_board->ai_ns_min;
1715 addchans = devpriv->softsshdelay / cmd->convert_arg;
1716 if (devpriv->softsshdelay % cmd->convert_arg)
1717 addchans++;
242467bd
MD
1718 if (addchans > (devpriv->ai_add_front - 1)) {
1719 /* uff, still short */
3063d6de
MD
1720 devpriv->ai_add_front = addchans + 1;
1721 if (devpriv->usedma == 1)
1722 if ((devpriv->ai_add_front +
0a85b6f0
MT
1723 devpriv->ai_n_chan +
1724 devpriv->ai_add_back) & 1)
242467bd
MD
1725 devpriv->ai_add_front++;
1726 /* round up to 32 bit */
3063d6de 1727 }
0a85b6f0 1728 }
242467bd
MD
1729 /* well, we now know what must be all added */
1730 devpriv->ai_n_realscanlen = /*
1731 * what we must take from card in real
1732 * to have ai_n_scanlen on output?
1733 */
0a85b6f0
MT
1734 (devpriv->ai_add_front + devpriv->ai_n_chan +
1735 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1736 devpriv->ai_n_chan);
3063d6de 1737
242467bd 1738 /* check and setup channel list */
3063d6de 1739 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
0a85b6f0
MT
1740 devpriv->ai_chanlist, devpriv->ai_add_front,
1741 devpriv->ai_add_back))
3063d6de
MD
1742 return -EINVAL;
1743 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
0a85b6f0
MT
1744 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1745 devpriv->ai_add_back, devpriv->usedma,
1746 devpriv->useeoshandle))
3063d6de
MD
1747 return -EINVAL;
1748
242467bd
MD
1749 /* compute timers settings */
1750 /*
1751 * simplest way, fr=4Mhz/(tim1*tim2),
1752 * channel manipulation without timers effect
1753 */
1754 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1755 (cmd->scan_begin_src == TRIG_EXT) ||
1756 (cmd->scan_begin_src == TRIG_INT)) &&
1757 (cmd->convert_src == TRIG_TIMER)) {
1758 /* both timer is used for one time */
beb50909 1759 if (cmd->scan_begin_src == TRIG_EXT)
3063d6de 1760 devpriv->ai_do = 4;
beb50909 1761 else
3063d6de 1762 devpriv->ai_do = 1;
3063d6de 1763 pci9118_calc_divisors(devpriv->ai_do, dev, s,
0a85b6f0
MT
1764 &cmd->scan_begin_arg, &cmd->convert_arg,
1765 devpriv->ai_flags,
1766 devpriv->ai_n_realscanlen,
1767 &devpriv->ai_divisor1,
1768 &devpriv->ai_divisor2, devpriv->usessh,
1769 devpriv->ai_add_front);
3063d6de
MD
1770 devpriv->ai_timer2 = cmd->convert_arg;
1771 }
1772
242467bd
MD
1773 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1774 ((cmd->convert_src == TRIG_TIMER) ||
1775 (cmd->convert_src == TRIG_NOW))) {
1776 /* double timed action */
3063d6de
MD
1777 if (!devpriv->usedma) {
1778 comedi_error(dev,
242467bd
MD
1779 "cmd->scan_begin_src=TRIG_TIMER works "
1780 "only with bus mastering!");
3063d6de
MD
1781 return -EIO;
1782 }
1783
1784 devpriv->ai_do = 2;
1785 pci9118_calc_divisors(devpriv->ai_do, dev, s,
0a85b6f0
MT
1786 &cmd->scan_begin_arg, &cmd->convert_arg,
1787 devpriv->ai_flags,
1788 devpriv->ai_n_realscanlen,
1789 &devpriv->ai_divisor1,
1790 &devpriv->ai_divisor2, devpriv->usessh,
1791 devpriv->ai_add_front);
3063d6de
MD
1792 devpriv->ai_timer1 = cmd->scan_begin_arg;
1793 devpriv->ai_timer2 = cmd->convert_arg;
1794 }
1795
1796 if ((cmd->scan_begin_src == TRIG_FOLLOW)
0a85b6f0 1797 && (cmd->convert_src == TRIG_EXT)) {
3063d6de
MD
1798 devpriv->ai_do = 3;
1799 }
1800
242467bd 1801 start_pacer(dev, -1, 0, 0); /* stop pacer */
3063d6de 1802
242467bd
MD
1803 devpriv->AdControlReg = 0; /*
1804 * bipolar, S.E., use 8254, stop 8354,
1805 * internal trigger, soft trigger,
1806 * disable DMA
1807 */
3063d6de 1808 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
242467bd
MD
1809 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1810 /*
1811 * positive triggers, no S&H, no burst,
1812 * burst stop, no post trigger,
1813 * no about trigger, trigger stop
1814 */
3063d6de 1815 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
5f74ea14 1816 udelay(1);
242467bd
MD
1817 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1818 inl(dev->iobase + PCI9118_ADSTAT); /*
1819 * flush A/D and INT
1820 * status register
1821 */
3063d6de
MD
1822 inl(dev->iobase + PCI9118_INTSRC);
1823
1824 devpriv->ai_act_scan = 0;
1825 devpriv->ai_act_dmapos = 0;
1826 s->async->cur_chan = 0;
1827 devpriv->ai_buf_ptr = 0;
1828
c3744138 1829 if (devpriv->usedma)
3063d6de 1830 ret = pci9118_ai_docmd_dma(dev, s);
c3744138 1831 else
3063d6de 1832 ret = pci9118_ai_docmd_sampl(dev, s);
3063d6de 1833
3063d6de
MD
1834 return ret;
1835}
1836
da91b269 1837static int pci9118_reset(struct comedi_device *dev)
3063d6de 1838{
ae34f6aa
HS
1839 struct pci9118_private *devpriv = dev->private;
1840
3063d6de
MD
1841 devpriv->IntControlReg = 0;
1842 devpriv->exttrg_users = 0;
1843 inl(dev->iobase + PCI9118_INTCTRL);
242467bd
MD
1844 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1845 /* disable interrupts source */
3063d6de 1846 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
0f04c356 1847/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
242467bd 1848 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
3063d6de 1849 devpriv->AdControlReg = 0;
242467bd
MD
1850 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1851 /*
1852 * bipolar, S.E., use 8254,
1853 * stop 8354, internal trigger,
1854 * soft trigger,
1855 * disable INT and DMA
1856 */
3063d6de
MD
1857 outl(0, dev->iobase + PCI9118_BURST);
1858 outl(1, dev->iobase + PCI9118_SCANMOD);
242467bd 1859 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
3063d6de 1860 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
242467bd
MD
1861 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1862 /*
1863 * positive triggers, no S&H,
1864 * no burst, burst stop,
1865 * no post trigger,
1866 * no about trigger,
1867 * trigger stop
1868 */
3063d6de
MD
1869
1870 devpriv->ao_data[0] = 2047;
1871 devpriv->ao_data[1] = 2047;
242467bd
MD
1872 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
1873 /* reset A/D outs to 0V */
3063d6de 1874 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
242467bd 1875 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
5f74ea14 1876 udelay(10);
3063d6de 1877 inl(dev->iobase + PCI9118_AD_DATA);
242467bd
MD
1878 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1879 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1880 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1881 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
3063d6de 1882 devpriv->AdControlReg = 0;
242467bd
MD
1883 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1884 /*
1885 * bipolar, S.E., use 8254,
1886 * stop 8354, internal trigger,
1887 * soft trigger,
1888 * disable INT and DMA
1889 */
3063d6de
MD
1890
1891 devpriv->cnt0_users = 0;
1892 devpriv->exttrg_users = 0;
1893
1894 return 0;
1895}
1896
15358a7f
IA
1897/*
1898 * FIXME - this is pretty ineffective because all the supported board types
1899 * have the same device ID!
1900 */
1901static const struct boardtype *pci9118_find_boardinfo(struct pci_dev *pcidev)
1902{
1903 unsigned int i;
1904
1905 for (i = 0; i < ARRAY_SIZE(boardtypes); i++)
1906 if (pcidev->device == boardtypes[i].device_id)
1907 return &boardtypes[i];
1908 return NULL;
1909}
1910
93b6e479
HS
1911static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1912 struct comedi_devconfig *it)
1913{
ae34f6aa 1914 const struct boardtype *this_board = comedi_board(dev);
93b6e479
HS
1915 struct pci_dev *pcidev = NULL;
1916 int bus = it->options[0];
1917 int slot = it->options[1];
1918
1919 for_each_pci_dev(pcidev) {
1920 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1921 continue;
1922 if (pcidev->device != this_board->device_id)
1923 continue;
1924 if (bus || slot) {
1925 /* requested particular bus/slot */
1926 if (pcidev->bus->number != bus ||
1927 PCI_SLOT(pcidev->devfn) != slot)
1928 continue;
1929 }
93b6e479
HS
1930 return pcidev;
1931 }
f41d2573
IA
1932 dev_err(dev->class_dev,
1933 "no supported board found! (req. bus/slot : %d/%d)\n",
1934 bus, slot);
93b6e479
HS
1935 return NULL;
1936}
1937
f41d2573
IA
1938static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
1939{
1940 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1941 struct pci9118_private *devpriv = dev->private;
1942 char irqbuf[30];
1943 char muxbuf[30];
1944
1945 if (irq)
1946 snprintf(irqbuf, sizeof(irqbuf), "irq %u%s", irq,
1947 (dev->irq ? "" : " UNAVAILABLE"));
1948 else
1949 snprintf(irqbuf, sizeof(irqbuf), "irq DISABLED");
1950 if (devpriv->usemux)
1951 snprintf(muxbuf, sizeof(muxbuf), "ext mux %u chans",
1952 devpriv->usemux);
1953 else
1954 snprintf(muxbuf, sizeof(muxbuf), "no ext mux");
1955 dev_info(dev->class_dev, "%s (pci %s, %s, %sbus master, %s) attached\n",
1956 dev->board_name, pci_name(pcidev), irqbuf,
1957 (devpriv->master ? "" : "no "), muxbuf);
1958}
1959
f3b81d54
IA
1960static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
1961 int master, int ext_mux, int softsshdelay,
1962 int hw_err_mask)
3063d6de 1963{
ae34f6aa 1964 const struct boardtype *this_board = comedi_board(dev);
f3b81d54
IA
1965 struct pci9118_private *devpriv = dev->private;
1966 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
34c43922 1967 struct comedi_subdevice *s;
3063d6de 1968 int ret, pages, i;
3063d6de 1969 unsigned int irq;
3063d6de
MD
1970 u16 u16w;
1971
f3b81d54
IA
1972 dev->board_name = this_board->name;
1973 ret = comedi_pci_enable(pcidev, dev->board_name);
1974 if (ret) {
1975 dev_err(dev->class_dev,
1976 "cannot enable PCI device %s\n", pci_name(pcidev));
1977 return ret;
1978 }
a41aec1b 1979 if (master)
c945a1d1 1980 pci_set_master(pcidev);
a41aec1b 1981
c945a1d1
HS
1982 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1983 dev->iobase = pci_resource_start(pcidev, 2);
3063d6de 1984
3063d6de
MD
1985 pci9118_reset(dev);
1986
242467bd 1987 if (master) { /* alloc DMA buffers */
3063d6de
MD
1988 devpriv->dma_doublebuf = 0;
1989 for (i = 0; i < 2; i++) {
c3744138
BP
1990 for (pages = 4; pages >= 0; pages--) {
1991 devpriv->dmabuf_virt[i] =
0a85b6f0
MT
1992 (short *)__get_free_pages(GFP_KERNEL,
1993 pages);
c3744138 1994 if (devpriv->dmabuf_virt[i])
3063d6de 1995 break;
c3744138 1996 }
3063d6de
MD
1997 if (devpriv->dmabuf_virt[i]) {
1998 devpriv->dmabuf_pages[i] = pages;
1999 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2000 devpriv->dmabuf_samples[i] =
0a85b6f0 2001 devpriv->dmabuf_size[i] >> 1;
3063d6de 2002 devpriv->dmabuf_hw[i] =
0a85b6f0
MT
2003 virt_to_bus((void *)
2004 devpriv->dmabuf_virt[i]);
3063d6de
MD
2005 }
2006 }
2007 if (!devpriv->dmabuf_virt[0]) {
f41d2573
IA
2008 dev_warn(dev->class_dev,
2009 "Can't allocate DMA buffer, DMA disabled!\n");
3063d6de
MD
2010 master = 0;
2011 }
3063d6de
MD
2012 if (devpriv->dmabuf_virt[1])
2013 devpriv->dma_doublebuf = 1;
3063d6de 2014 }
c3744138 2015 devpriv->master = master;
f3b81d54
IA
2016
2017 if (ext_mux > 0) {
2018 if (ext_mux > 256)
2019 ext_mux = 256; /* max 256 channels! */
2020 if (softsshdelay > 0)
2021 if (ext_mux > 128)
2022 ext_mux = 128;
2023 devpriv->usemux = ext_mux;
2024 } else {
2025 devpriv->usemux = 0;
3063d6de
MD
2026 }
2027
f3b81d54
IA
2028 if (softsshdelay < 0) {
2029 /* select sample&hold signal polarity */
2030 devpriv->softsshdelay = -softsshdelay;
3063d6de
MD
2031 devpriv->softsshsample = 0x80;
2032 devpriv->softsshhold = 0x00;
2033 } else {
f3b81d54 2034 devpriv->softsshdelay = softsshdelay;
3063d6de
MD
2035 devpriv->softsshsample = 0x00;
2036 devpriv->softsshhold = 0x80;
2037 }
2038
c945a1d1
HS
2039 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
2040 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
242467bd 2041 /* Enable parity check for parity error */
3063d6de 2042
2f0b9d08 2043 ret = comedi_alloc_subdevices(dev, 4);
8b6c5694 2044 if (ret)
3063d6de
MD
2045 return ret;
2046
17c7ac91 2047 s = &dev->subdevices[0];
3063d6de
MD
2048 dev->read_subdev = s;
2049 s->type = COMEDI_SUBD_AI;
2050 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
a41aec1b 2051 if (devpriv->usemux)
3063d6de 2052 s->n_chan = devpriv->usemux;
a41aec1b 2053 else
3063d6de 2054 s->n_chan = this_board->n_aichan;
a41aec1b 2055
3063d6de
MD
2056 s->maxdata = this_board->ai_maxdata;
2057 s->len_chanlist = this_board->n_aichanlist;
2058 s->range_table = this_board->rangelist_ai;
2059 s->cancel = pci9118_ai_cancel;
2060 s->insn_read = pci9118_insn_read_ai;
f3b81d54 2061 s->munge = pci9118_ai_munge;
3063d6de 2062
17c7ac91 2063 s = &dev->subdevices[1];
3063d6de
MD
2064 s->type = COMEDI_SUBD_AO;
2065 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2066 s->n_chan = this_board->n_aochan;
2067 s->maxdata = this_board->ao_maxdata;
2068 s->len_chanlist = this_board->n_aochan;
2069 s->range_table = this_board->rangelist_ao;
2070 s->insn_write = pci9118_insn_write_ao;
2071 s->insn_read = pci9118_insn_read_ao;
2072
17c7ac91 2073 s = &dev->subdevices[2];
3063d6de
MD
2074 s->type = COMEDI_SUBD_DI;
2075 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2076 s->n_chan = 4;
2077 s->maxdata = 1;
2078 s->len_chanlist = 4;
2079 s->range_table = &range_digital;
2080 s->io_bits = 0; /* all bits input */
2081 s->insn_bits = pci9118_insn_bits_di;
2082
17c7ac91 2083 s = &dev->subdevices[3];
3063d6de
MD
2084 s->type = COMEDI_SUBD_DO;
2085 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2086 s->n_chan = 4;
2087 s->maxdata = 1;
2088 s->len_chanlist = 4;
2089 s->range_table = &range_digital;
2090 s->io_bits = 0xf; /* all bits output */
2091 s->insn_bits = pci9118_insn_bits_do;
2092
2093 devpriv->valid = 1;
242467bd
MD
2094 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2095 devpriv->ai_maskharderr = 0x10a;
2096 /* default measure crash condition */
f3b81d54
IA
2097 if (hw_err_mask) /* disable some requested */
2098 devpriv->ai_maskharderr &= ~hw_err_mask;
3063d6de
MD
2099
2100 switch (this_board->ai_maxdata) {
2101 case 0xffff:
2102 devpriv->ai16bits = 1;
2103 break;
2104 default:
2105 devpriv->ai16bits = 0;
2106 break;
2107 }
f3b81d54
IA
2108
2109 if (disable_irq)
2110 irq = 0;
2111 else
2112 irq = pcidev->irq;
2113 if (irq > 0) {
2114 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
2115 dev->board_name, dev)) {
2116 dev_warn(dev->class_dev,
2117 "unable to allocate IRQ %u, DISABLING IT\n",
2118 irq);
2119 } else {
2120 dev->irq = irq;
2121 /* Enable AI commands */
2122 s = &dev->subdevices[0];
2123 s->subdev_flags |= SDF_CMD_READ;
2124 s->do_cmdtest = pci9118_ai_cmdtest;
2125 s->do_cmd = pci9118_ai_cmd;
2126 }
2127 }
2128
f41d2573 2129 pci9118_report_attach(dev, irq);
3063d6de
MD
2130 return 0;
2131}
2132
f3b81d54
IA
2133static int pci9118_attach(struct comedi_device *dev,
2134 struct comedi_devconfig *it)
2135{
2136 struct pci9118_private *devpriv;
2137 struct pci_dev *pcidev;
2138 int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;
2139
2140 ext_mux = it->options[2];
2141 master = ((it->options[3] & 1) == 0);
2142 disable_irq = ((it->options[3] & 2) != 0);
2143 softsshdelay = it->options[4];
2144 hw_err_mask = it->options[5];
2145
2146 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
2147 if (!devpriv)
2148 return -ENOMEM;
2149 dev->private = devpriv;
2150
2151 pcidev = pci9118_find_pci(dev, it);
2152 if (!pcidev)
2153 return -EIO;
2154 comedi_set_hw_dev(dev, &pcidev->dev);
2155
2156 return pci9118_common_attach(dev, disable_irq, master, ext_mux,
2157 softsshdelay, hw_err_mask);
2158}
2159
a690b7e5 2160static int pci9118_auto_attach(struct comedi_device *dev,
15358a7f
IA
2161 unsigned long context_unused)
2162{
2163 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2164 struct pci9118_private *devpriv;
2165
2166 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
2167 if (!devpriv)
2168 return -ENOMEM;
2169 dev->private = devpriv;
2170
2171 dev->board_ptr = pci9118_find_boardinfo(pcidev);
2172 if (dev->board_ptr == NULL) {
2173 dev_err(dev->class_dev,
2174 "adl_pci9118: cannot determine board type for pci %s\n",
2175 pci_name(pcidev));
2176 return -EINVAL;
2177 }
2178 /*
2179 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
2180 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
2181 */
2182 pci_dev_get(pcidev);
2183 /* Don't disable irq, use bus master, no external mux,
2184 * no sample-hold delay, no error mask. */
2185 return pci9118_common_attach(dev, 0, 1, 0, 0, 0);
2186}
2187
484ecc95 2188static void pci9118_detach(struct comedi_device *dev)
3063d6de 2189{
c945a1d1 2190 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
ae34f6aa 2191 struct pci9118_private *devpriv = dev->private;
c945a1d1 2192
ae34f6aa 2193 if (devpriv) {
3063d6de
MD
2194 if (devpriv->valid)
2195 pci9118_reset(dev);
2196 if (dev->irq)
5f74ea14 2197 free_irq(dev->irq, dev);
3063d6de
MD
2198 if (devpriv->dmabuf_virt[0])
2199 free_pages((unsigned long)devpriv->dmabuf_virt[0],
0a85b6f0 2200 devpriv->dmabuf_pages[0]);
3063d6de
MD
2201 if (devpriv->dmabuf_virt[1])
2202 free_pages((unsigned long)devpriv->dmabuf_virt[1],
0a85b6f0 2203 devpriv->dmabuf_pages[1]);
3063d6de 2204 }
c945a1d1
HS
2205 if (pcidev) {
2206 if (dev->iobase)
2207 comedi_pci_disable(pcidev);
2208
2209 pci_dev_put(pcidev);
2210 }
3063d6de
MD
2211}
2212
618fc38f
HS
2213static struct comedi_driver adl_pci9118_driver = {
2214 .driver_name = "adl_pci9118",
2215 .module = THIS_MODULE,
2216 .attach = pci9118_attach,
15358a7f 2217 .auto_attach = pci9118_auto_attach,
618fc38f
HS
2218 .detach = pci9118_detach,
2219 .num_names = ARRAY_SIZE(boardtypes),
2220 .board_name = &boardtypes[0].name,
2221 .offset = sizeof(struct boardtype),
2222};
2223
a690b7e5 2224static int adl_pci9118_pci_probe(struct pci_dev *dev,
b8f4ac23 2225 const struct pci_device_id *id)
618fc38f 2226{
b8f4ac23
HS
2227 return comedi_pci_auto_config(dev, &adl_pci9118_driver,
2228 id->driver_data);
618fc38f
HS
2229}
2230
618fc38f
HS
2231static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
2232 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2233 { 0 }
2234};
2235MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2236
2237static struct pci_driver adl_pci9118_pci_driver = {
2238 .name = "adl_pci9118",
2239 .id_table = adl_pci9118_pci_table,
2240 .probe = adl_pci9118_pci_probe,
9901a4d7 2241 .remove = comedi_pci_auto_unconfig,
618fc38f
HS
2242};
2243module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
90f703d3
AT
2244
2245MODULE_AUTHOR("Comedi http://www.comedi.org");
2246MODULE_DESCRIPTION("Comedi low-level driver");
2247MODULE_LICENSE("GPL");