adl_pci9118.c revision 48b1aff5b93521c5ad90842bef52b218ac50a4ab
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> 69#include <linux/interrupt.h> 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 83#define DPRINTK(fmt, args...) printk(fmt, ## args) 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 111/* bits from A/D control register (PCI9118_ADCNTRL) */ 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 121/* bits from A/D function register (PCI9118_ADFUNC) */ 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 131/* bits from A/D status register (PCI9118_ADSTAT) */ 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 142/* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */ 143/* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */ 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 156static const struct comedi_lrange range_pci9118dg_hr = { 8, { 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 } 166}; 167 168static const struct comedi_lrange range_pci9118hg = { 8, { 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 } 178}; 179 180#define PCI9118_BIPOLAR_RANGES 4 /* used for test on mixture of BIP/UNI ranges */ 181 182static int pci9118_attach(struct comedi_device *dev, 183 struct comedi_devconfig *it); 184static int pci9118_detach(struct comedi_device *dev); 185 186struct boardtype { 187 const char *name; /* board name */ 188 int vendor_id; /* PCI vendor a device ID of card */ 189 int device_id; 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 */ 204 205}; 206 207static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = { 208 { 209 PCI_VENDOR_ID_AMCC, 0x80d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 210 0} 211}; 212 213MODULE_DEVICE_TABLE(pci, pci9118_pci_table); 214 215static const struct boardtype boardtypes[] = { 216 {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9, 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}, 221 {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9, 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}, 226 {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9, 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}, 231}; 232 233#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) 234 235static struct comedi_driver driver_pci9118 = { 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), 243}; 244 245COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table); 246 247struct pci9118_private { 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! */ 252#ifdef PCI9118_PARANOIDCHECK 253 unsigned short chanlist[PCI9118_CHANLEN + 1]; /* list of scaned channel */ 254 unsigned char chanlistlen; /* number of scanlist */ 255#endif 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 */ 272 unsigned int ai_timer1; 273 unsigned int ai_timer2; 274 unsigned int ai_flags; 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 */ 277 unsigned int ai_data_len; 278 short *ai_data; 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 */ 288 unsigned int dmabuf_panic_size[2]; 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 */ 305}; 306 307#define devpriv ((struct pci9118_private *)dev->private) 308#define this_board ((struct boardtype *)dev->board_ptr) 309 310/* 311============================================================================== 312*/ 313 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); 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); 327static int pci9118_ai_cancel(struct comedi_device *dev, 328 struct comedi_subdevice *s); 329static void pci9118_calc_divisors(char mode, struct comedi_device *dev, 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); 335 336/* 337============================================================================== 338*/ 339static int pci9118_insn_read_ai(struct comedi_device *dev, 340 struct comedi_subdevice *s, 341 struct comedi_insn *insn, unsigned int *data) 342{ 343 344 int n, timeout; 345 346 devpriv->AdControlReg = AdControl_Int & 0xff; 347 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; 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 */ 349 350 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0)) 351 return -EINVAL; 352 353 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ 354 355 for (n = 0; n < insn->n; n++) { 356 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */ 357 udelay(2); 358 timeout = 100; 359 while (timeout--) { 360 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy) 361 goto conv_finish; 362 udelay(1); 363 } 364 365 comedi_error(dev, "A/D insn timeout"); 366 data[n] = 0; 367 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ 368 return -ETIME; 369 370conv_finish: 371 if (devpriv->ai16bits) { 372 data[n] = 373 (inl(dev->iobase + 374 PCI9118_AD_DATA) & 0xffff) ^ 0x8000; 375 } else { 376 data[n] = 377 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff; 378 } 379 } 380 381 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ 382 return n; 383 384} 385 386/* 387============================================================================== 388*/ 389static int pci9118_insn_write_ao(struct comedi_device *dev, 390 struct comedi_subdevice *s, 391 struct comedi_insn *insn, unsigned int *data) 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*/ 413static int pci9118_insn_read_ao(struct comedi_device *dev, 414 struct comedi_subdevice *s, 415 struct comedi_insn *insn, unsigned int *data) 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*/ 429static int pci9118_insn_bits_di(struct comedi_device *dev, 430 struct comedi_subdevice *s, 431 struct comedi_insn *insn, unsigned int *data) 432{ 433 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf; 434 435 return 2; 436} 437 438/* 439============================================================================== 440*/ 441static int pci9118_insn_bits_do(struct comedi_device *dev, 442 struct comedi_subdevice *s, 443 struct comedi_insn *insn, unsigned int *data) 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*/ 458static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev) 459{ 460 devpriv->AdFunctionReg = 461 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM; 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, 465 dev->iobase + PCI9118_CNT0); 466 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff, 467 dev->iobase + PCI9118_CNT0); 468 devpriv->AdFunctionReg |= AdFunction_Start; 469 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); 470} 471 472static unsigned int defragment_dma_buffer(struct comedi_device *dev, 473 struct comedi_subdevice *s, 474 short *dma_buffer, 475 unsigned int num_samples) 476{ 477 unsigned int i = 0, j = 0; 478 unsigned int start_pos = devpriv->ai_add_front, 479 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan; 480 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan + 481 devpriv->ai_add_back; 482 483 for (i = 0; i < num_samples; i++) { 484 if (devpriv->ai_act_dmapos >= start_pos && 485 devpriv->ai_act_dmapos < stop_pos) { 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*/ 498static unsigned int move_block_from_dma(struct comedi_device *dev, 499 struct comedi_subdevice *s, 500 short *dma_buffer, 501 unsigned int num_samples) 502{ 503 unsigned int num_bytes; 504 505 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples); 506 devpriv->ai_act_scan += 507 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen; 508 s->async->cur_chan += num_samples; 509 s->async->cur_chan %= devpriv->ai_n_scanlen; 510 num_bytes = 511 cfc_write_array_to_buffer(s, dma_buffer, 512 num_samples * sizeof(short)); 513 if (num_bytes < num_samples * sizeof(short)) 514 return -1; 515 return 0; 516} 517 518/* 519============================================================================== 520*/ 521static char pci9118_decode_error_status(struct comedi_device *dev, 522 struct comedi_subdevice *s, 523 unsigned char m) 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, 531 "A/D Burst Mode Overrun Status (Fatal Error!)"); 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 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) 556{ 557 unsigned int i, num_samples = num_bytes / sizeof(short); 558 short *array = data; 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*/ 574static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, 575 struct comedi_subdevice *s, 576 unsigned short int_adstat, 577 unsigned int int_amcc, 578 unsigned short int_daq) 579{ 580 register short sampl; 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) { 592 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) { /* data dropout! */ 593 printk 594 ("comedi: A/D SAMPL - data dropout: received channel %d, expected %d!\n", 595 sampl & 0x000f, 596 devpriv->chanlist[s->async->cur_chan]); 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*/ 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) 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) 648/* if (int_adstat & 0x106) */ 649 if (pci9118_decode_error_status(dev, s, int_adstat)) 650 return; 651 652 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1; /* number of received real samples */ 653/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */ 654 655 if (devpriv->dma_doublebuf) { /* switch DMA buffers if is used double buffering */ 656 next_dma_buf = 1 - devpriv->dma_actbuf; 657 outl(devpriv->dmabuf_hw[next_dma_buf], 658 devpriv->iobase_a + AMCC_OP_REG_MWAR); 659 outl(devpriv->dmabuf_use_size[next_dma_buf], 660 devpriv->iobase_a + AMCC_OP_REG_MWTC); 661 devpriv->dmabuf_used_size[next_dma_buf] = 662 devpriv->dmabuf_use_size[next_dma_buf]; 663 if (devpriv->ai_do == 4) 664 interrupt_pci9118_ai_mode4_switch(dev); 665 } 666 667 if (samplesinbuf) { 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); */ 670 sampls = m; 671 move_block_from_dma(dev, s, 672 devpriv->dmabuf_virt[devpriv->dma_actbuf], 673 samplesinbuf); 674 m = m - sampls; /* m= how many samples was transfered */ 675 } 676/* DPRINTK("YYY\n"); */ 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 684 if (devpriv->dma_doublebuf) { /* switch dma buffers */ 685 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf; 686 } else { /* restart DMA if is not used double buffering */ 687 outl(devpriv->dmabuf_hw[0], 688 devpriv->iobase_a + AMCC_OP_REG_MWAR); 689 outl(devpriv->dmabuf_use_size[0], 690 devpriv->iobase_a + AMCC_OP_REG_MWTC); 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*/ 701static irqreturn_t interrupt_pci9118(int irq, void *d) 702{ 703 struct comedi_device *dev = d; 704 unsigned int int_daq = 0, int_amcc, int_adstat; 705 706 if (!dev->attached) 707 return IRQ_NONE; /* not fully initialized */ 708 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 */ 711 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); */ 713 714 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) 715 return IRQ_NONE; /* interrupt from other source */ 716 717 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* shutdown IRQ reasons in AMCC */ 718 719 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; /* get STATUS register */ 720 721 if (devpriv->ai_do) { 722 if (devpriv->ai12_startstop) 723 if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) { /* start stop of measure */ 724 if (devpriv->ai12_startstop & START_AI_EXT) { 725 devpriv->ai12_startstop &= 726 ~START_AI_EXT; 727 if (!(devpriv->ai12_startstop & 728 STOP_AI_EXT)) 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 */ 731 outl(devpriv->AdControlReg, 732 dev->iobase + PCI9118_ADCNTRL); 733 } else { 734 if (devpriv->ai12_startstop & 735 STOP_AI_EXT) { 736 devpriv->ai12_startstop &= 737 ~STOP_AI_EXT; 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 */ 740 } 741 } 742 } 743 744 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat, 745 int_amcc, int_daq); 746 747 } 748 return IRQ_HANDLED; 749} 750 751/* 752============================================================================== 753*/ 754static int pci9118_ai_inttrig(struct comedi_device *dev, 755 struct comedi_subdevice *s, unsigned int trignum) 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, 767 devpriv->ai_divisor2); 768 devpriv->AdControlReg |= AdControl_SoftG; 769 } 770 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); 771 772 return 1; 773} 774 775/* 776============================================================================== 777*/ 778static int pci9118_ai_cmdtest(struct comedi_device *dev, 779 struct comedi_subdevice *s, 780 struct comedi_cmd *cmd) 781{ 782 int err = 0; 783 int tmp, divisor1 = 0, divisor2 = 0; 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 && 826 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) { 827 cmd->start_src = TRIG_NOW; 828 err++; 829 } 830 831 if (cmd->scan_begin_src != TRIG_TIMER && 832 cmd->scan_begin_src != TRIG_EXT && 833 cmd->scan_begin_src != TRIG_INT && 834 cmd->scan_begin_src != TRIG_FOLLOW) { 835 cmd->scan_begin_src = TRIG_FOLLOW; 836 err++; 837 } 838 839 if (cmd->convert_src != TRIG_TIMER && 840 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) { 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 && 851 cmd->stop_src != TRIG_COUNT && 852 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) { 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)) && 868 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) { 869 cmd->convert_src = TRIG_TIMER; 870 err++; 871 } 872 873 if ((cmd->scan_begin_src == TRIG_FOLLOW) && 874 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) { 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) && 902 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) { 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 = 965 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len); 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; 976/* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ 977 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, 978 &divisor2, &cmd->scan_begin_arg, 979 cmd->flags & TRIG_ROUND_MASK); 980/* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ 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, 990 &divisor2, &cmd->convert_arg, 991 cmd->flags & TRIG_ROUND_MASK); 992/* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ 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 998 && cmd->convert_src == TRIG_NOW) { 999 if (cmd->convert_arg == 0) { 1000 if (cmd->scan_begin_arg < 1001 this_board->ai_ns_min * 1002 (cmd->scan_end_arg + 2)) { 1003 cmd->scan_begin_arg = 1004 this_board->ai_ns_min * 1005 (cmd->scan_end_arg + 2); 1006/* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ 1007 err++; 1008 } 1009 } else { 1010 if (cmd->scan_begin_arg < 1011 cmd->convert_arg * cmd->chanlist_len) { 1012 cmd->scan_begin_arg = 1013 cmd->convert_arg * 1014 cmd->chanlist_len; 1015/* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */ 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, 1027 cmd->chanlist, 0, 0)) 1028 return 5; /* incorrect channels list */ 1029 1030 return 0; 1031} 1032 1033/* 1034============================================================================== 1035*/ 1036static int Compute_and_setup_dma(struct comedi_device *dev) 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); 1045 /* isn't output buff smaller that our DMA buff? */ 1046 if (dmalen0 > (devpriv->ai_data_len)) { 1047 dmalen0 = devpriv->ai_data_len & ~3L; /* allign to 32bit down */ 1048 } 1049 if (dmalen1 > (devpriv->ai_data_len)) { 1050 dmalen1 = devpriv->ai_data_len & ~3L; /* allign to 32bit down */ 1051 } 1052 DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); 1053 1054 /* we want wake up every scan? */ 1055 if (devpriv->ai_flags & TRIG_WAKE_EOS) { 1056 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) { 1057 /* uff, too short DMA buffer, disable EOS support! */ 1058 devpriv->ai_flags &= (~TRIG_WAKE_EOS); 1059 printk 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); 1063 } else { 1064 /* short first DMA buffer to one scan */ 1065 dmalen0 = devpriv->ai_n_realscanlen << 1; 1066 DPRINTK 1067 ("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n", 1068 dmalen0, devpriv->ai_n_realscanlen, 1069 devpriv->useeoshandle); 1070 if (devpriv->useeoshandle) 1071 dmalen0 += 2; 1072 if (dmalen0 < 4) { 1073 printk 1074 ("comedi%d: ERR: DMA0 buf len bug? (%d<4)\n", 1075 dev->minor, dmalen0); 1076 dmalen0 = 4; 1077 } 1078 } 1079 } 1080 if (devpriv->ai_flags & TRIG_WAKE_EOS) { 1081 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) { 1082 /* uff, too short DMA buffer, disable EOS support! */ 1083 devpriv->ai_flags &= (~TRIG_WAKE_EOS); 1084 printk 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); 1088 } else { 1089 /* short second DMA buffer to one scan */ 1090 dmalen1 = devpriv->ai_n_realscanlen << 1; 1091 DPRINTK 1092 ("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n", 1093 dmalen1, devpriv->ai_n_realscanlen, 1094 devpriv->useeoshandle); 1095 if (devpriv->useeoshandle) 1096 dmalen1 -= 2; 1097 if (dmalen1 < 4) { 1098 printk 1099 ("comedi%d: ERR: DMA1 buf len bug? (%d<4)\n", 1100 dev->minor, dmalen1); 1101 dmalen1 = 4; 1102 } 1103 } 1104 } 1105 1106 DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); 1107 /* transfer without TRIG_WAKE_EOS */ 1108 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) { 1109 /* if it's possible then allign DMA buffers to length of scan */ 1110 i = dmalen0; 1111 dmalen0 = 1112 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) * 1113 (devpriv->ai_n_realscanlen << 1); 1114 dmalen0 &= ~3L; 1115 if (!dmalen0) 1116 dmalen0 = i; /* uff. very long scan? */ 1117 i = dmalen1; 1118 dmalen1 = 1119 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) * 1120 (devpriv->ai_n_realscanlen << 1); 1121 dmalen1 &= ~3L; 1122 if (!dmalen1) 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 */ 1125 if (!devpriv->ai_neverending) { 1126 /* fits whole measure into one DMA buffer? */ 1127 if (dmalen0 > 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); 1134 dmalen0 = 1135 (devpriv->ai_n_realscanlen << 1) * 1136 devpriv->ai_scans; 1137 DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0, 1138 dmalen1); 1139 dmalen0 &= ~3L; 1140 } else { /* fits whole measure into two DMA buffer? */ 1141 if (dmalen1 > 1142 ((devpriv->ai_n_realscanlen << 1) * 1143 devpriv->ai_scans - dmalen0)) 1144 dmalen1 = 1145 (devpriv->ai_n_realscanlen << 1) * 1146 devpriv->ai_scans - dmalen0; 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 1156 /* these DMA buffer size we'll be used */ 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] = 1165 (this_board->half_fifo_size / devpriv->ai_n_scanlen + 1166 1) * devpriv->ai_n_scanlen * sizeof(short); 1167 devpriv->dmabuf_panic_size[1] = 1168 (this_board->half_fifo_size / devpriv->ai_n_scanlen + 1169 1) * devpriv->ai_n_scanlen * sizeof(short); 1170 } else { 1171 devpriv->dmabuf_panic_size[0] = 1172 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0]; 1173 devpriv->dmabuf_panic_size[1] = 1174 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1]; 1175 } 1176#endif 1177 1178 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */ 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); 1181 /* init DMA transfer */ 1182 outl(0x00000000 | AINT_WRITE_COMPL, 1183 devpriv->iobase_a + AMCC_OP_REG_INTCSR); 1184/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */ 1185 1186 outl(inl(devpriv->iobase_a + 1187 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY | 1188 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR); 1189 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow bus mastering */ 1190 1191 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n"); 1192 return 0; 1193} 1194 1195/* 1196============================================================================== 1197*/ 1198static int pci9118_ai_docmd_sampl(struct comedi_device *dev, 1199 struct comedi_subdevice *s) 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, 1218 "pci9118_ai_docmd_sampl() mode number bug!\n"); 1219 return -EIO; 1220 }; 1221 1222 devpriv->int_ai_func = interrupt_pci9118_ai_onesample; /* transfer function */ 1223 1224 if (devpriv->ai12_startstop) 1225 pci9118_exttrg_add(dev, EXTTRG_AI); /* activate EXT trigger */ 1226 1227 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2)) 1228 devpriv->IntControlReg |= Int_Timer; 1229 1230 devpriv->AdControlReg |= AdControl_Int; 1231 1232 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */ 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, 1239 devpriv->ai_divisor2); 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*/ 1252static int pci9118_ai_docmd_dma(struct comedi_device *dev, 1253 struct comedi_subdevice *s) 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 |= 1262 ((AdControl_TmrTr | AdControl_Dma) & 0xff); 1263 break; 1264 case 2: 1265 devpriv->AdControlReg |= 1266 ((AdControl_TmrTr | AdControl_Dma) & 0xff); 1267 devpriv->AdFunctionReg = 1268 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM | 1269 AdFunction_BS; 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 |= 1276 ((AdControl_ExtM | AdControl_Dma) & 0xff); 1277 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; 1278 break; 1279 case 4: 1280 devpriv->AdControlReg |= 1281 ((AdControl_TmrTr | AdControl_Dma) & 0xff); 1282 devpriv->AdFunctionReg = 1283 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM; 1284 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); 1285 outl(0x30, dev->iobase + PCI9118_CNTCTRL); 1286 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff, 1287 dev->iobase + PCI9118_CNT0); 1288 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff, 1289 dev->iobase + PCI9118_CNT0); 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) { 1298 pci9118_exttrg_add(dev, EXTTRG_AI); /* activate EXT trigger */ 1299 } 1300 1301 devpriv->int_ai_func = interrupt_pci9118_ai_dma; /* transfer function */ 1302 1303 outl(0x02000000 | AINT_WRITE_COMPL, 1304 devpriv->iobase_a + AMCC_OP_REG_INTCSR); 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, 1311 devpriv->ai_divisor2); 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*/ 1324static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1325{ 1326 struct comedi_cmd *cmd = &s->async->cmd; 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 1344 /* prepare for start/stop conditions */ 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 1371 /* use sample&hold signal? */ 1372 if (cmd->convert_src == TRIG_NOW) { 1373 devpriv->usessh = 1; 1374 } /* yes */ 1375 else { 1376 devpriv->usessh = 0; 1377 } /* no */ 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 1383 /* use additional sample at end of every scan to satisty DMA 32 bit transfer? */ 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) && 1390 (devpriv->ai_n_scanlen == 1)) { 1391 if (cmd->convert_src == TRIG_NOW) { 1392 devpriv->ai_add_back = 1; 1393 } 1394 if (cmd->convert_src == TRIG_TIMER) { 1395 devpriv->usedma = 0; /* use INT transfer if scanlist have only one channel */ 1396 } 1397 } 1398 if ((cmd->flags & TRIG_WAKE_EOS) && 1399 (devpriv->ai_n_scanlen & 1) && 1400 (devpriv->ai_n_scanlen > 1)) { 1401 if (cmd->scan_begin_src == TRIG_FOLLOW) { 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 */ 1405 devpriv->ai_add_back = 1; 1406 } 1407 } 1408 } else { /* interrupt transfer don't need any correction */ 1409 devpriv->usedma = 0; 1410 } 1411 1412 /* we need software S&H signal? It add two samples before every scan as minimum */ 1413 if (devpriv->usessh && devpriv->softsshdelay) { 1414 devpriv->ai_add_front = 2; 1415 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) { /* move it to front */ 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++; 1424 if (addchans > (devpriv->ai_add_front - 1)) { /* uff, still short :-( */ 1425 devpriv->ai_add_front = addchans + 1; 1426 if (devpriv->usedma == 1) 1427 if ((devpriv->ai_add_front + 1428 devpriv->ai_n_chan + 1429 devpriv->ai_add_back) & 1) 1430 devpriv->ai_add_front++; /* round up to 32 bit */ 1431 } 1432 } 1433 /* well, we now know what must be all added */ 1434 devpriv->ai_n_realscanlen = /* what we must take from card in real to have ai_n_scanlen on output? */ 1435 (devpriv->ai_add_front + devpriv->ai_n_chan + 1436 devpriv->ai_add_back) * (devpriv->ai_n_scanlen / 1437 devpriv->ai_n_chan); 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 1445 /* check and setup channel list */ 1446 if (!check_channel_list(dev, s, devpriv->ai_n_chan, 1447 devpriv->ai_chanlist, devpriv->ai_add_front, 1448 devpriv->ai_add_back)) 1449 return -EINVAL; 1450 if (!setup_channel_list(dev, s, devpriv->ai_n_chan, 1451 devpriv->ai_chanlist, 0, devpriv->ai_add_front, 1452 devpriv->ai_add_back, devpriv->usedma, 1453 devpriv->useeoshandle)) 1454 return -EINVAL; 1455 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 */ 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, 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); 1471 devpriv->ai_timer2 = cmd->convert_arg; 1472 } 1473 1474 if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) { /* double timed action */ 1475 if (!devpriv->usedma) { 1476 comedi_error(dev, 1477 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!"); 1478 return -EIO; 1479 } 1480 1481 devpriv->ai_do = 2; 1482 pci9118_calc_divisors(devpriv->ai_do, dev, s, 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); 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) 1494 && (cmd->convert_src == TRIG_EXT)) { 1495 devpriv->ai_do = 3; 1496 } 1497 1498 start_pacer(dev, -1, 0, 0); /* stop pacer */ 1499 1500 devpriv->AdControlReg = 0; /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA */ 1501 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); 1502 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; /* positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */ 1503 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); 1504 udelay(1); 1505 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ 1506 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D and INT status register */ 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 1514 if (devpriv->usedma) 1515 ret = pci9118_ai_docmd_dma(dev, s); 1516 else 1517 ret = pci9118_ai_docmd_sampl(dev, s); 1518 1519 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n"); 1520 return ret; 1521} 1522 1523/* 1524============================================================================== 1525*/ 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) 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) { 1538 printk 1539 ("comedi%d: range/channel list is too long for actual configuration (%d>%d)!", 1540 dev->minor, n_chan, s->len_chanlist - frontadd - backadd); 1541 return 0; 1542 } 1543 1544 if (CR_AREF(chanlist[0]) == AREF_DIFF) 1545 differencial = 1; /* all input must be diff */ 1546 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) 1547 bipolar = 1; /* all input must be bipolar */ 1548 if (n_chan > 1) 1549 for (i = 1; i < n_chan; i++) { /* check S.E/diff */ 1550 if ((CR_AREF(chanlist[i]) == AREF_DIFF) != 1551 (differencial)) { 1552 comedi_error(dev, 1553 "Differencial and single ended inputs cann't be mixtured!"); 1554 return 0; 1555 } 1556 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) != 1557 (bipolar)) { 1558 comedi_error(dev, 1559 "Bipolar and unipolar ranges cann't be mixtured!"); 1560 return 0; 1561 } 1562 if ((!devpriv->usemux) & (differencial) & 1563 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) { 1564 comedi_error(dev, 1565 "If AREF_DIFF is used then is available only first 8 channels!"); 1566 return 0; 1567 } 1568 } 1569 1570 return 1; 1571} 1572 1573/* 1574============================================================================== 1575*/ 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) 1580{ 1581 unsigned int i, differencial = 0, bipolar = 0; 1582 unsigned int scanquad, gain, ssh = 0x00; 1583 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); 1587 1588 if (usedma == 1) { 1589 rot = 8; 1590 usedma = 0; 1591 } 1592 1593 if (CR_AREF(chanlist[0]) == AREF_DIFF) 1594 differencial = 1; /* all input must be diff */ 1595 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) 1596 bipolar = 1; /* all input must be bipolar */ 1597 1598 /* All is ok, so we can setup channel/range list */ 1599 1600 if (!bipolar) { 1601 devpriv->AdControlReg |= AdControl_UniP; /* set unibipolar */ 1602 } else { 1603 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff); /* enable bipolar */ 1604 } 1605 1606 if (differencial) { 1607 devpriv->AdControlReg |= AdControl_Diff; /* enable diff inputs */ 1608 } else { 1609 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff); /* set single ended inputs */ 1610 } 1611 1612 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* setup mode */ 1613 1614 outl(2, dev->iobase + PCI9118_SCANMOD); /* gods know why this sequence! */ 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 1624 if (frontadd) { /* insert channels for S&H */ 1625 ssh = devpriv->softsshsample; 1626 DPRINTK("FA: %04x: ", ssh); 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 */ 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); 1639 for (i = 0; i < n_chan; i++) { /* store range list to card */ 1640 scanquad = CR_CHAN(chanlist[i]); /* get channel number; */ 1641#ifdef PCI9118_PARANOIDCHECK 1642 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot; 1643#endif 1644 gain = CR_RANGE(chanlist[i]); /* get gain number */ 1645 scanquad |= ((gain & 0x03) << 8); 1646 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); 1647 DPRINTK("%02x ", scanquad | ssh); 1648 } 1649 DPRINTK("\n "); 1650 1651 if (backadd) { /* insert channels for fit onto 32bit DMA */ 1652 DPRINTK("BA: %04x: ", ssh); 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 */ 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 1663 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; /* for 32bit oerations */ 1664 if (useeos) { 1665 for (i = 1; i < n_chan; i++) { /* store range list to card */ 1666 devpriv->chanlist[(n_chan + i) ^ usedma] = 1667 (CR_CHAN(chanlist[i]) & 0xf) << rot; 1668 } 1669 devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma]; /* for 32bit oerations */ 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 1682 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */ 1683/* udelay(100); important delay, or first sample will be cripled */ 1684 1685 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n"); 1686 return 1; /* we can serve this with scan logic */ 1687} 1688 1689/* 1690============================================================================== 1691 calculate 8254 divisors if they are used for dual timing 1692*/ 1693static void pci9118_calc_divisors(char mode, struct comedi_device *dev, 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) 1699{ 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); 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, 1709 tim2, flags & TRIG_ROUND_NEAREST); 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); 1718 *div1 = *tim2 / devpriv->i8254_osc_base; /* convert timer (burst) */ 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); 1725 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */ 1726 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, 1727 *tim1, *tim2); 1728 *div2 = *div2 / *div1; /* major timer is c1*c2 */ 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 1736 *tim2 = *div1 * devpriv->i8254_osc_base; /* real convert timer */ 1737 1738 if (usessh & (chnsshfront == 0)) /* use BSSH signal */ 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*/ 1756static void start_pacer(struct comedi_device *dev, int mode, 1757 unsigned int divisor1, unsigned int divisor2) 1758{ 1759 outl(0x74, dev->iobase + PCI9118_CNTCTRL); 1760 outl(0xb4, dev->iobase + PCI9118_CNTCTRL); 1761/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */ 1762 udelay(1); 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*/ 1775static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source) 1776{ 1777 if (source > 3) 1778 return -1; /* incorrect source */ 1779 devpriv->exttrg_users |= (1 << source); 1780 devpriv->IntControlReg |= Int_DTrg; 1781 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); 1782 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */ 1783 return 0; 1784} 1785 1786/* 1787============================================================================== 1788*/ 1789static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source) 1790{ 1791 if (source > 3) 1792 return -1; /* incorrect source */ 1793 devpriv->exttrg_users &= ~(1 << source); 1794 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */ 1795 devpriv->IntControlReg &= ~Int_DTrg; 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 */ 1798 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); 1799 } 1800 return 0; 1801} 1802 1803/* 1804============================================================================== 1805*/ 1806static int pci9118_ai_cancel(struct comedi_device *dev, 1807 struct comedi_subdevice *s) 1808{ 1809 if (devpriv->usedma) 1810 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */ 1811 pci9118_exttrg_del(dev, EXTTRG_AI); 1812 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ 1813 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; 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 */ 1815 devpriv->AdControlReg = 0x00; 1816 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */ 1817 outl(0, dev->iobase + PCI9118_BURST); 1818 outl(1, dev->iobase + PCI9118_SCANMOD); 1819 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */ 1820 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ 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) 1834 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */ 1835 1836 return 0; 1837} 1838 1839/* 1840============================================================================== 1841*/ 1842static int pci9118_reset(struct comedi_device *dev) 1843{ 1844 devpriv->IntControlReg = 0; 1845 devpriv->exttrg_users = 0; 1846 inl(dev->iobase + PCI9118_INTCTRL); 1847 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); /* disable interrupts source */ 1848 outl(0x30, dev->iobase + PCI9118_CNTCTRL); 1849/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */ 1850 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ 1851 devpriv->AdControlReg = 0; 1852 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */ 1853 outl(0, dev->iobase + PCI9118_BURST); 1854 outl(1, dev->iobase + PCI9118_SCANMOD); 1855 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */ 1856 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; 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 */ 1858 1859 devpriv->ao_data[0] = 2047; 1860 devpriv->ao_data[1] = 2047; 1861 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1); /* reset A/D outs to 0V */ 1862 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2); 1863 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */ 1864 udelay(10); 1865 inl(dev->iobase + PCI9118_AD_DATA); 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 */ 1870 devpriv->AdControlReg = 0; 1871 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */ 1872 1873 devpriv->cnt0_users = 0; 1874 devpriv->exttrg_users = 0; 1875 1876 return 0; 1877} 1878 1879/* 1880============================================================================== 1881*/ 1882static int pci9118_attach(struct comedi_device *dev, 1883 struct comedi_devconfig *it) 1884{ 1885 struct comedi_subdevice *s; 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 1896 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name); 1897 1898 opt_bus = it->options[0]; 1899 opt_slot = it->options[1]; 1900 if (it->options[3] & 1) { 1901 master = 0; /* user don't want use bus master */ 1902 } else { 1903 master = 1; 1904 } 1905 1906 ret = alloc_private(dev, sizeof(struct pci9118_private)); 1907 if (ret < 0) { 1908 printk(" - Allocation failed!\n"); 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, 1916 this_board->device_id, 1917 pcidev))) { 1918 /* Found matching vendor/device. */ 1919 if (opt_bus || opt_slot) { 1920 /* Check bus/slot. */ 1921 if (opt_bus != pcidev->bus->number 1922 || opt_slot != PCI_SLOT(pcidev->devfn)) 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")) { 1930 errstr = 1931 "failed to enable PCI device and request regions!"; 1932 continue; 1933 } 1934 break; 1935 } 1936 1937 if (!pcidev) { 1938 if (opt_bus || opt_slot) { 1939 printk(" - Card at b:s %d:%d %s\n", 1940 opt_bus, opt_slot, errstr); 1941 } else { 1942 printk(" - Card %s\n", errstr); 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 1958 printk(", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus, pci_slot, 1959 pci_func, iobase_9, iobase_a); 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) 1970 irq = 0; /* user don't want use IRQ */ 1971 if (irq > 0) { 1972 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED, 1973 "ADLink PCI-9118", dev)) { 1974 printk(", unable to allocate IRQ %d, DISABLING IT", 1975 irq); 1976 irq = 0; /* Can't use IRQ */ 1977 } else { 1978 printk(", irq=%u", irq); 1979 } 1980 } else { 1981 printk(", IRQ disabled"); 1982 } 1983 1984 dev->irq = irq; 1985 1986 if (master) { /* alloc DMA buffers */ 1987 devpriv->dma_doublebuf = 0; 1988 for (i = 0; i < 2; i++) { 1989 for (pages = 4; pages >= 0; pages--) { 1990 devpriv->dmabuf_virt[i] = 1991 (short *)__get_free_pages(GFP_KERNEL, 1992 pages); 1993 if (devpriv->dmabuf_virt[i]) 1994 break; 1995 } 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] = 2000 devpriv->dmabuf_size[i] >> 1; 2001 devpriv->dmabuf_hw[i] = 2002 virt_to_bus((void *) 2003 devpriv->dmabuf_virt[i]); 2004 } 2005 } 2006 if (!devpriv->dmabuf_virt[0]) { 2007 printk(", Can't allocate DMA buffer, DMA disabled!"); 2008 master = 0; 2009 } 2010 2011 if (devpriv->dmabuf_virt[1]) 2012 devpriv->dma_doublebuf = 1; 2013 2014 } 2015 2016 devpriv->master = master; 2017 if (devpriv->master) 2018 printk(", bus master"); 2019 else 2020 printk(", no bus master"); 2021 2022 devpriv->usemux = 0; 2023 if (it->options[2] > 0) { 2024 devpriv->usemux = it->options[2]; 2025 if (devpriv->usemux > 256) 2026 devpriv->usemux = 256; /* max 256 channels! */ 2027 if (it->options[4] > 0) 2028 if (devpriv->usemux > 128) { 2029 devpriv->usemux = 128; /* max 128 channels with softare S&H! */ 2030 } 2031 printk(", ext. mux %d channels", devpriv->usemux); 2032 } 2033 2034 devpriv->softsshdelay = it->options[4]; 2035 if (devpriv->softsshdelay < 0) { /* select sample&hold signal polarity */ 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 2044 printk(".\n"); 2045 2046 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w); 2047 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64); /* Enable parity check for parity error */ 2048 2049 ret = alloc_subdevices(dev, 4); 2050 if (ret < 0) 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; 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 */ 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*/ 2124static int pci9118_detach(struct comedi_device *dev) 2125{ 2126 if (dev->private) { 2127 if (devpriv->valid) 2128 pci9118_reset(dev); 2129 if (dev->irq) 2130 free_irq(dev->irq, dev); 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], 2139 devpriv->dmabuf_pages[0]); 2140 if (devpriv->dmabuf_virt[1]) 2141 free_pages((unsigned long)devpriv->dmabuf_virt[1], 2142 devpriv->dmabuf_pages[1]); 2143 } 2144 2145 return 0; 2146} 2147 2148/* 2149============================================================================== 2150*/ 2151