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