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