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