pcl818.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
1/* 2 comedi/drivers/pcl818.c 3 4 Author: Michal Dobes <dobes@tesnet.cz> 5 6 hardware driver for Advantech cards: 7 card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718 8 driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718 9*/ 10/* 11Driver: pcl818 12Description: Advantech PCL-818 cards, PCL-718 13Author: Michal Dobes <dobes@tesnet.cz> 14Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), 15 PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), 16 PCL-718 (pcl718) 17Status: works 18 19All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. 20Differences are only at maximal sample speed, range list and FIFO 21support. 22The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support 23only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. 24PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO 25but this code is untested. 26A word or two about DMA. Driver support DMA operations at two ways: 271) DMA uses two buffers and after one is filled then is generated 28 INT and DMA restart with second buffer. With this mode I'm unable run 29 more that 80Ksamples/secs without data dropouts on K6/233. 302) DMA uses one buffer and run in autoinit mode and the data are 31 from DMA buffer moved on the fly with 2kHz interrupts from RTC. 32 This mode is used if the interrupt 8 is available for allocation. 33 If not, then first DMA mode is used. With this I can run at 34 full speed one card (100ksamples/secs) or two cards with 35 60ksamples/secs each (more is problem on account of ISA limitations). 36 To use this mode you must have compiled kernel with disabled 37 "Enhanced Real Time Clock Support". 38 Maybe you can have problems if you use xntpd or similar. 39 If you've data dropouts with DMA mode 2 then: 40 a) disable IDE DMA 41 b) switch text mode console to fb. 42 43 Options for PCL-818L: 44 [0] - IO Base 45 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 46 [2] - DMA (0=disable, 1, 3) 47 [3] - 0, 10=10MHz clock for 8254 48 1= 1MHz clock for 8254 49 [4] - 0, 5=A/D input -5V.. +5V 50 1, 10=A/D input -10V..+10V 51 [5] - 0, 5=D/A output 0-5V (internal reference -5V) 52 1, 10=D/A output 0-10V (internal reference -10V) 53 2 =D/A output unknow (external reference) 54 55 Options for PCL-818, PCL-818H: 56 [0] - IO Base 57 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 58 [2] - DMA (0=disable, 1, 3) 59 [3] - 0, 10=10MHz clock for 8254 60 1= 1MHz clock for 8254 61 [4] - 0, 5=D/A output 0-5V (internal reference -5V) 62 1, 10=D/A output 0-10V (internal reference -10V) 63 2 =D/A output unknow (external reference) 64 65 Options for PCL-818HD, PCL-818HG: 66 [0] - IO Base 67 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 68 [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, 69 1=use DMA ch 1, 3=use DMA ch 3) 70 [3] - 0, 10=10MHz clock for 8254 71 1= 1MHz clock for 8254 72 [4] - 0, 5=D/A output 0-5V (internal reference -5V) 73 1, 10=D/A output 0-10V (internal reference -10V) 74 2 =D/A output unknow (external reference) 75 76 Options for PCL-718: 77 [0] - IO Base 78 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 79 [2] - DMA (0=disable, 1, 3) 80 [3] - 0, 10=10MHz clock for 8254 81 1= 1MHz clock for 8254 82 [4] - 0=A/D Range is +/-10V 83 1= +/-5V 84 2= +/-2.5V 85 3= +/-1V 86 4= +/-0.5V 87 5= user defined bipolar 88 6= 0-10V 89 7= 0-5V 90 8= 0-2V 91 9= 0-1V 92 10= user defined unipolar 93 [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) 94 1, 10=D/A outputs 0-10V (internal reference -10V) 95 2=D/A outputs unknow (external reference) 96 [6] - 0, 60=max 60kHz A/D sampling 97 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) 98 99*/ 100 101#include "../comedidev.h" 102 103#include <linux/ioport.h> 104#include <linux/mc146818rtc.h> 105#include <linux/delay.h> 106#include <asm/dma.h> 107 108#include "8253.h" 109 110/* #define PCL818_MODE13_AO 1 */ 111 112/* boards constants */ 113 114#define boardPCL818L 0 115#define boardPCL818H 1 116#define boardPCL818HD 2 117#define boardPCL818HG 3 118#define boardPCL818 4 119#define boardPCL718 5 120 121/* IO space len */ 122#define PCLx1x_RANGE 16 123/* IO space len if we use FIFO */ 124#define PCLx1xFIFO_RANGE 32 125 126/* W: clear INT request */ 127#define PCL818_CLRINT 8 128/* R: return status byte */ 129#define PCL818_STATUS 8 130/* R: A/D high byte W: A/D range control */ 131#define PCL818_RANGE 1 132/* R: next mux scan channel W: mux scan channel & range control pointer */ 133#define PCL818_MUX 2 134/* R/W: operation control register */ 135#define PCL818_CONTROL 9 136/* W: counter enable */ 137#define PCL818_CNTENABLE 10 138 139/* R: low byte of A/D W: soft A/D trigger */ 140#define PCL818_AD_LO 0 141/* R: high byte of A/D W: A/D range control */ 142#define PCL818_AD_HI 1 143/* W: D/A low&high byte */ 144#define PCL818_DA_LO 4 145#define PCL818_DA_HI 5 146/* R: low&high byte of DI */ 147#define PCL818_DI_LO 3 148#define PCL818_DI_HI 11 149/* W: low&high byte of DO */ 150#define PCL818_DO_LO 3 151#define PCL818_DO_HI 11 152/* W: PCL718 second D/A */ 153#define PCL718_DA2_LO 6 154#define PCL718_DA2_HI 7 155/* counters */ 156#define PCL818_CTR0 12 157#define PCL818_CTR1 13 158#define PCL818_CTR2 14 159/* W: counter control */ 160#define PCL818_CTRCTL 15 161 162/* W: fifo enable/disable */ 163#define PCL818_FI_ENABLE 6 164/* W: fifo interrupt clear */ 165#define PCL818_FI_INTCLR 20 166/* W: fifo interrupt clear */ 167#define PCL818_FI_FLUSH 25 168/* R: fifo status */ 169#define PCL818_FI_STATUS 25 170/* R: one record from FIFO */ 171#define PCL818_FI_DATALO 23 172#define PCL818_FI_DATAHI 23 173 174/* type of interrupt handler */ 175#define INT_TYPE_AI1_INT 1 176#define INT_TYPE_AI1_DMA 2 177#define INT_TYPE_AI1_FIFO 3 178#define INT_TYPE_AI3_INT 4 179#define INT_TYPE_AI3_DMA 5 180#define INT_TYPE_AI3_FIFO 6 181#ifdef PCL818_MODE13_AO 182#define INT_TYPE_AO1_INT 7 183#define INT_TYPE_AO3_INT 8 184#endif 185 186#ifdef unused 187/* RTC stuff... */ 188#define INT_TYPE_AI1_DMA_RTC 9 189#define INT_TYPE_AI3_DMA_RTC 10 190 191#define RTC_IRQ 8 192#define RTC_IO_EXTENT 0x10 193#endif 194 195#define MAGIC_DMA_WORD 0x5a5a 196 197static const struct comedi_lrange range_pcl818h_ai = { 9, { 198 BIP_RANGE(5), 199 BIP_RANGE(2.5), 200 BIP_RANGE(1.25), 201 BIP_RANGE(0.625), 202 UNI_RANGE(10), 203 UNI_RANGE(5), 204 UNI_RANGE(2.5), 205 UNI_RANGE(1.25), 206 BIP_RANGE(10), 207 } 208}; 209 210static const struct comedi_lrange range_pcl818hg_ai = { 10, { 211 BIP_RANGE(5), 212 BIP_RANGE(0.5), 213 BIP_RANGE(0.05), 214 BIP_RANGE(0.005), 215 UNI_RANGE(10), 216 UNI_RANGE(1), 217 UNI_RANGE(0.1), 218 UNI_RANGE(0.01), 219 BIP_RANGE(10), 220 BIP_RANGE(1), 221 BIP_RANGE(0.1), 222 BIP_RANGE(0.01), 223 } 224}; 225 226static const struct comedi_lrange range_pcl818l_l_ai = { 4, { 227 BIP_RANGE(5), 228 BIP_RANGE(2.5), 229 BIP_RANGE(1.25), 230 BIP_RANGE(0.625), 231 } 232}; 233 234static const struct comedi_lrange range_pcl818l_h_ai = { 4, { 235 BIP_RANGE(10), 236 BIP_RANGE(5), 237 BIP_RANGE(2.5), 238 BIP_RANGE(1.25), 239 } 240}; 241 242static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} }; 243static const struct comedi_lrange range718_bipolar0_5 = 244 { 1, {BIP_RANGE(0.5),} }; 245static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} }; 246static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} }; 247 248static int pcl818_attach(struct comedi_device *dev, 249 struct comedi_devconfig *it); 250static int pcl818_detach(struct comedi_device *dev); 251 252#ifdef unused 253static int RTC_lock = 0; /* RTC lock */ 254static int RTC_timer_lock = 0; /* RTC int lock */ 255#endif 256 257struct pcl818_board { 258 259 const char *name; /* driver name */ 260 int n_ranges; /* len of range list */ 261 int n_aichan_se; /* num of A/D chans in single ended mode */ 262 int n_aichan_diff; /* num of A/D chans in diferencial mode */ 263 unsigned int ns_min; /* minimal alllowed delay between samples (in ns) */ 264 int n_aochan; /* num of D/A chans */ 265 int n_dichan; /* num of DI chans */ 266 int n_dochan; /* num of DO chans */ 267 const struct comedi_lrange *ai_range_type; /* default A/D rangelist */ 268 const struct comedi_lrange *ao_range_type; /* default D/A rangelist */ 269 unsigned int io_range; /* len of IO space */ 270 unsigned int IRQbits; /* allowed interrupts */ 271 unsigned int DMAbits; /* allowed DMA chans */ 272 int ai_maxdata; /* maxdata for A/D */ 273 int ao_maxdata; /* maxdata for D/A */ 274 unsigned char fifo; /* 1=board has FIFO */ 275 int is_818; 276}; 277 278static const struct pcl818_board boardtypes[] = { 279 {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai, 280 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 281 0x0a, 0xfff, 0xfff, 0, 1}, 282 {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai, 283 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 284 0x0a, 0xfff, 0xfff, 0, 1}, 285 {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai, 286 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 287 0x0a, 0xfff, 0xfff, 1, 1}, 288 {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai, 289 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 290 0x0a, 0xfff, 0xfff, 1, 1}, 291 {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai, 292 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 293 0x0a, 0xfff, 0xfff, 0, 1}, 294 {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5, 295 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 296 0x0a, 0xfff, 0xfff, 0, 0}, 297 /* pcm3718 */ 298 {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai, 299 &range_unipolar5, PCLx1x_RANGE, 0x00fc, 300 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ }, 301}; 302 303#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board)) 304 305static struct comedi_driver driver_pcl818 = { 306 .driver_name = "pcl818", 307 .module = THIS_MODULE, 308 .attach = pcl818_attach, 309 .detach = pcl818_detach, 310 .board_name = &boardtypes[0].name, 311 .num_names = n_boardtypes, 312 .offset = sizeof(struct pcl818_board), 313}; 314 315COMEDI_INITCLEANUP(driver_pcl818); 316 317struct pcl818_private { 318 319 unsigned int dma; /* used DMA, 0=don't use DMA */ 320 int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */ 321 unsigned int io_range; 322#ifdef unused 323 unsigned long rtc_iobase; /* RTC port region */ 324 unsigned int rtc_iosize; 325 unsigned int rtc_irq; 326 struct timer_list rtc_irq_timer; /* timer for RTC sanity check */ 327 unsigned long rtc_freq; /* RTC int freq */ 328 int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */ 329#endif 330 unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ 331 unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */ 332 unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ 333 unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */ 334 unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */ 335 unsigned int last_top_dma; /* DMA pointer in last RTC int */ 336 int next_dma_buf; /* which DMA buffer will be used next round */ 337 long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ 338 unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ 339 unsigned char neverending_ai; /* if=1, then we do neverending record (you must use cancel()) */ 340 unsigned int ns_min; /* manimal alllowed delay between samples (in us) for actual card */ 341 int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ 342 int irq_free; /* 1=have allocated IRQ */ 343 int irq_blocked; /* 1=IRQ now uses any subdev */ 344 int irq_was_now_closed; /* when IRQ finish, there's stored int818_mode for last interrupt */ 345 int ai_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */ 346 struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */ 347 int ai_act_scan; /* how many scans we finished */ 348 int ai_act_chan; /* actual position in actual scan */ 349 unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */ 350 unsigned int act_chanlist_len; /* how long is actual MUX list */ 351 unsigned int act_chanlist_pos; /* actual position in MUX list */ 352 unsigned int ai_scans; /* len of scanlist */ 353 unsigned int ai_n_chan; /* how many channels is measured */ 354 unsigned int *ai_chanlist; /* actaul chanlist */ 355 unsigned int ai_flags; /* flaglist */ 356 unsigned int ai_data_len; /* len of data buffer */ 357 short *ai_data; /* data buffer */ 358 unsigned int ai_timer1; /* timers */ 359 unsigned int ai_timer2; 360 struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */ 361 unsigned char usefifo; /* 1=use fifo */ 362 unsigned int ao_readback[2]; 363}; 364 365static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, /* used for gain list programming */ 366 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff 367}; 368 369#define devpriv ((struct pcl818_private *)dev->private) 370#define this_board ((const struct pcl818_board *)dev->board_ptr) 371 372/* 373============================================================================== 374*/ 375static void setup_channel_list(struct comedi_device *dev, 376 struct comedi_subdevice *s, 377 unsigned int *chanlist, unsigned int n_chan, 378 unsigned int seglen); 379static int check_channel_list(struct comedi_device *dev, 380 struct comedi_subdevice *s, 381 unsigned int *chanlist, unsigned int n_chan); 382 383static int pcl818_ai_cancel(struct comedi_device *dev, 384 struct comedi_subdevice *s); 385static void start_pacer(struct comedi_device *dev, int mode, 386 unsigned int divisor1, unsigned int divisor2); 387 388#ifdef unused 389static int set_rtc_irq_bit(unsigned char bit); 390static void rtc_dropped_irq(unsigned long data); 391static int rtc_setfreq_irq(int freq); 392#endif 393 394/* 395============================================================================== 396 ANALOG INPUT MODE0, 818 cards, slow version 397*/ 398static int pcl818_ai_insn_read(struct comedi_device *dev, 399 struct comedi_subdevice *s, 400 struct comedi_insn *insn, unsigned int *data) 401{ 402 int n; 403 int timeout; 404 405 /* software trigger, DMA and INT off */ 406 outb(0, dev->iobase + PCL818_CONTROL); 407 408 /* select channel */ 409 outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX); 410 411 /* select gain */ 412 outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE); 413 414 for (n = 0; n < insn->n; n++) { 415 416 /* clear INT (conversion end) flag */ 417 outb(0, dev->iobase + PCL818_CLRINT); 418 419 /* start conversion */ 420 outb(0, dev->iobase + PCL818_AD_LO); 421 422 timeout = 100; 423 while (timeout--) { 424 if (inb(dev->iobase + PCL818_STATUS) & 0x10) 425 goto conv_finish; 426 udelay(1); 427 } 428 comedi_error(dev, "A/D insn timeout"); 429 /* clear INT (conversion end) flag */ 430 outb(0, dev->iobase + PCL818_CLRINT); 431 return -EIO; 432 433conv_finish: 434 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) | 435 (inb(dev->iobase + PCL818_AD_LO) >> 4)); 436 } 437 438 return n; 439} 440 441/* 442============================================================================== 443 ANALOG OUTPUT MODE0, 818 cards 444 only one sample per call is supported 445*/ 446static int pcl818_ao_insn_read(struct comedi_device *dev, 447 struct comedi_subdevice *s, 448 struct comedi_insn *insn, unsigned int *data) 449{ 450 int n; 451 int chan = CR_CHAN(insn->chanspec); 452 453 for (n = 0; n < insn->n; n++) { 454 data[n] = devpriv->ao_readback[chan]; 455 } 456 457 return n; 458} 459 460static int pcl818_ao_insn_write(struct comedi_device *dev, 461 struct comedi_subdevice *s, 462 struct comedi_insn *insn, unsigned int *data) 463{ 464 int n; 465 int chan = CR_CHAN(insn->chanspec); 466 467 for (n = 0; n < insn->n; n++) { 468 devpriv->ao_readback[chan] = data[n]; 469 outb((data[n] & 0x000f) << 4, dev->iobase + 470 (chan ? PCL718_DA2_LO : PCL818_DA_LO)); 471 outb((data[n] & 0x0ff0) >> 4, dev->iobase + 472 (chan ? PCL718_DA2_HI : PCL818_DA_HI)); 473 } 474 475 return n; 476} 477 478/* 479============================================================================== 480 DIGITAL INPUT MODE0, 818 cards 481 482 only one sample per call is supported 483*/ 484static int pcl818_di_insn_bits(struct comedi_device *dev, 485 struct comedi_subdevice *s, 486 struct comedi_insn *insn, unsigned int *data) 487{ 488 if (insn->n != 2) 489 return -EINVAL; 490 491 data[1] = inb(dev->iobase + PCL818_DI_LO) | 492 (inb(dev->iobase + PCL818_DI_HI) << 8); 493 494 return 2; 495} 496 497/* 498============================================================================== 499 DIGITAL OUTPUT MODE0, 818 cards 500 501 only one sample per call is supported 502*/ 503static int pcl818_do_insn_bits(struct comedi_device *dev, 504 struct comedi_subdevice *s, 505 struct comedi_insn *insn, unsigned int *data) 506{ 507 if (insn->n != 2) 508 return -EINVAL; 509 510 s->state &= ~data[0]; 511 s->state |= (data[0] & data[1]); 512 513 outb(s->state & 0xff, dev->iobase + PCL818_DO_LO); 514 outb((s->state >> 8), dev->iobase + PCL818_DO_HI); 515 516 data[1] = s->state; 517 518 return 2; 519} 520 521/* 522============================================================================== 523 analog input interrupt mode 1 & 3, 818 cards 524 one sample per interrupt version 525*/ 526static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) 527{ 528 struct comedi_device *dev = d; 529 struct comedi_subdevice *s = dev->subdevices + 0; 530 int low; 531 int timeout = 50; /* wait max 50us */ 532 533 while (timeout--) { 534 if (inb(dev->iobase + PCL818_STATUS) & 0x10) 535 goto conv_finish; 536 udelay(1); 537 } 538 outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */ 539 comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); 540 pcl818_ai_cancel(dev, s); 541 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 542 comedi_event(dev, s); 543 return IRQ_HANDLED; 544 545conv_finish: 546 low = inb(dev->iobase + PCL818_AD_LO); 547 comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); /* get one sample */ 548 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 549 550 if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ 551 printk 552 ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n", 553 (low & 0xf), 554 devpriv->act_chanlist[devpriv->act_chanlist_pos]); 555 pcl818_ai_cancel(dev, s); 556 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 557 comedi_event(dev, s); 558 return IRQ_HANDLED; 559 } 560 if (s->async->cur_chan == 0) { 561 /* printk("E"); */ 562 devpriv->ai_act_scan--; 563 } 564 565 if (!devpriv->neverending_ai) { 566 if (devpriv->ai_act_scan == 0) { /* all data sampled */ 567 pcl818_ai_cancel(dev, s); 568 s->async->events |= COMEDI_CB_EOA; 569 } 570 } 571 comedi_event(dev, s); 572 return IRQ_HANDLED; 573} 574 575/* 576============================================================================== 577 analog input dma mode 1 & 3, 818 cards 578*/ 579static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) 580{ 581 struct comedi_device *dev = d; 582 struct comedi_subdevice *s = dev->subdevices + 0; 583 int i, len, bufptr; 584 unsigned long flags; 585 short *ptr; 586 587 disable_dma(devpriv->dma); 588 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; 589 if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { /* switch dma bufs */ 590 set_dma_mode(devpriv->dma, DMA_MODE_READ); 591 flags = claim_dma_lock(); 592 set_dma_addr(devpriv->dma, 593 devpriv->hwdmaptr[devpriv->next_dma_buf]); 594 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) { 595 set_dma_count(devpriv->dma, 596 devpriv->hwdmasize[devpriv-> 597 next_dma_buf]); 598 } else { 599 set_dma_count(devpriv->dma, devpriv->last_dma_run); 600 } 601 release_dma_lock(flags); 602 enable_dma(devpriv->dma); 603 } 604 printk("comedi: A/D mode1/3 IRQ \n"); 605 606 devpriv->dma_runs_to_end--; 607 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 608 ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; 609 610 len = devpriv->hwdmasize[0] >> 1; 611 bufptr = 0; 612 613 for (i = 0; i < len; i++) { 614 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ 615 printk 616 ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n", 617 (ptr[bufptr] & 0xf), 618 devpriv->act_chanlist[devpriv->act_chanlist_pos], 619 devpriv->act_chanlist_pos); 620 pcl818_ai_cancel(dev, s); 621 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 622 comedi_event(dev, s); 623 return IRQ_HANDLED; 624 } 625 626 comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */ 627 628 devpriv->act_chanlist_pos++; 629 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) { 630 devpriv->ai_act_scan--; 631 devpriv->act_chanlist_pos = 0; 632 } 633 634 if (!devpriv->neverending_ai) 635 if (devpriv->ai_act_scan == 0) { /* all data sampled */ 636 pcl818_ai_cancel(dev, s); 637 s->async->events |= COMEDI_CB_EOA; 638 comedi_event(dev, s); 639 /* printk("done int ai13 dma\n"); */ 640 return IRQ_HANDLED; 641 } 642 } 643 644 if (len > 0) 645 comedi_event(dev, s); 646 return IRQ_HANDLED; 647} 648 649#ifdef unused 650/* 651============================================================================== 652 analog input dma mode 1 & 3 over RTC, 818 cards 653*/ 654static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d) 655{ 656 struct comedi_device *dev = d; 657 struct comedi_subdevice *s = dev->subdevices + 0; 658 unsigned long tmp; 659 unsigned int top1, top2, i, bufptr; 660 long ofs_dats; 661 short *dmabuf = (short *)devpriv->dmabuf[0]; 662 663 /* outb(2,0x378); */ 664 switch (devpriv->ai_mode) { 665 case INT_TYPE_AI1_DMA_RTC: 666 case INT_TYPE_AI3_DMA_RTC: 667 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); 668 mod_timer(&devpriv->rtc_irq_timer, 669 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); 670 671 for (i = 0; i < 10; i++) { 672 top1 = get_dma_residue(devpriv->dma); 673 top2 = get_dma_residue(devpriv->dma); 674 if (top1 == top2) 675 break; 676 } 677 678 if (top1 != top2) 679 return IRQ_HANDLED; 680 top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */ 681 top1 >>= 1; 682 ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */ 683 if (ofs_dats < 0) 684 ofs_dats = (devpriv->dmasamplsize) + ofs_dats; 685 if (!ofs_dats) 686 return IRQ_HANDLED; /* exit=no new samples from last call */ 687 /* obsluz data */ 688 i = devpriv->last_top_dma - 1; 689 i &= (devpriv->dmasamplsize - 1); 690 691 if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */ 692 comedi_error(dev, "A/D mode1/3 DMA buffer overflow!"); 693 /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */ 694 pcl818_ai_cancel(dev, s); 695 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 696 comedi_event(dev, s); 697 return IRQ_HANDLED; 698 } 699 /* printk("r %ld ",ofs_dats); */ 700 701 bufptr = devpriv->last_top_dma; 702 703 for (i = 0; i < ofs_dats; i++) { 704 if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ 705 printk 706 ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n", 707 (dmabuf[bufptr] & 0xf), 708 devpriv-> 709 act_chanlist[devpriv->act_chanlist_pos]); 710 pcl818_ai_cancel(dev, s); 711 s->async->events |= 712 COMEDI_CB_EOA | COMEDI_CB_ERROR; 713 comedi_event(dev, s); 714 return IRQ_HANDLED; 715 } 716 717 comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */ 718 bufptr &= (devpriv->dmasamplsize - 1); 719 720 if (s->async->cur_chan == 0) { 721 devpriv->ai_act_scan--; 722 } 723 724 if (!devpriv->neverending_ai) 725 if (devpriv->ai_act_scan == 0) { /* all data sampled */ 726 pcl818_ai_cancel(dev, s); 727 s->async->events |= COMEDI_CB_EOA; 728 comedi_event(dev, s); 729 /* printk("done int ai13 dma\n"); */ 730 return IRQ_HANDLED; 731 } 732 } 733 734 devpriv->last_top_dma = bufptr; 735 bufptr--; 736 bufptr &= (devpriv->dmasamplsize - 1); 737 dmabuf[bufptr] = MAGIC_DMA_WORD; 738 comedi_event(dev, s); 739 /* outb(0,0x378); */ 740 return IRQ_HANDLED; 741 } 742 743 /* outb(0,0x378); */ 744 return IRQ_HANDLED; 745} 746#endif 747 748/* 749============================================================================== 750 analog input interrupt mode 1 & 3, 818HD/HG cards 751*/ 752static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) 753{ 754 struct comedi_device *dev = d; 755 struct comedi_subdevice *s = dev->subdevices + 0; 756 int i, len, lo; 757 758 outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */ 759 760 lo = inb(dev->iobase + PCL818_FI_STATUS); 761 762 if (lo & 4) { 763 comedi_error(dev, "A/D mode1/3 FIFO overflow!"); 764 pcl818_ai_cancel(dev, s); 765 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 766 comedi_event(dev, s); 767 return IRQ_HANDLED; 768 } 769 770 if (lo & 1) { 771 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!"); 772 pcl818_ai_cancel(dev, s); 773 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 774 comedi_event(dev, s); 775 return IRQ_HANDLED; 776 } 777 778 if (lo & 2) { 779 len = 512; 780 } else { 781 len = 0; 782 } 783 784 for (i = 0; i < len; i++) { 785 lo = inb(dev->iobase + PCL818_FI_DATALO); 786 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ 787 printk 788 ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n", 789 (lo & 0xf), 790 devpriv->act_chanlist[devpriv->act_chanlist_pos]); 791 pcl818_ai_cancel(dev, s); 792 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 793 comedi_event(dev, s); 794 return IRQ_HANDLED; 795 } 796 797 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */ 798 799 if (s->async->cur_chan == 0) { 800 devpriv->ai_act_scan--; 801 } 802 803 if (!devpriv->neverending_ai) 804 if (devpriv->ai_act_scan == 0) { /* all data sampled */ 805 pcl818_ai_cancel(dev, s); 806 s->async->events |= COMEDI_CB_EOA; 807 comedi_event(dev, s); 808 return IRQ_HANDLED; 809 } 810 } 811 812 if (len > 0) 813 comedi_event(dev, s); 814 return IRQ_HANDLED; 815} 816 817/* 818============================================================================== 819 INT procedure 820*/ 821static irqreturn_t interrupt_pcl818(int irq, void *d) 822{ 823 struct comedi_device *dev = d; 824 825 if (!dev->attached) { 826 comedi_error(dev, "premature interrupt"); 827 return IRQ_HANDLED; 828 } 829 /* printk("I\n"); */ 830 831 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) { 832 if ((devpriv->neverending_ai || (!devpriv->neverending_ai && 833 devpriv->ai_act_scan > 0)) && 834 (devpriv->ai_mode == INT_TYPE_AI1_DMA || 835 devpriv->ai_mode == INT_TYPE_AI3_DMA)) { 836 /* The cleanup from ai_cancel() has been delayed 837 until now because the card doesn't seem to like 838 being reprogrammed while a DMA transfer is in 839 progress. 840 */ 841 struct comedi_subdevice *s = dev->subdevices + 0; 842 devpriv->ai_act_scan = 0; 843 devpriv->neverending_ai = 0; 844 pcl818_ai_cancel(dev, s); 845 } 846 847 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 848 849 return IRQ_HANDLED; 850 } 851 852 switch (devpriv->ai_mode) { 853 case INT_TYPE_AI1_DMA: 854 case INT_TYPE_AI3_DMA: 855 return interrupt_pcl818_ai_mode13_dma(irq, d); 856 case INT_TYPE_AI1_INT: 857 case INT_TYPE_AI3_INT: 858 return interrupt_pcl818_ai_mode13_int(irq, d); 859 case INT_TYPE_AI1_FIFO: 860 case INT_TYPE_AI3_FIFO: 861 return interrupt_pcl818_ai_mode13_fifo(irq, d); 862#ifdef PCL818_MODE13_AO 863 case INT_TYPE_AO1_INT: 864 case INT_TYPE_AO3_INT: 865 return interrupt_pcl818_ao_mode13_int(irq, d); 866#endif 867 default: 868 break; 869 } 870 871 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 872 873 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked) 874 || (!devpriv->ai_mode)) { 875 comedi_error(dev, "bad IRQ!"); 876 return IRQ_NONE; 877 } 878 879 comedi_error(dev, "IRQ from unknow source!"); 880 return IRQ_NONE; 881} 882 883/* 884============================================================================== 885 ANALOG INPUT MODE 1 or 3 DMA , 818 cards 886*/ 887static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev, 888 struct comedi_subdevice *s) 889{ 890 unsigned int flags; 891 unsigned int bytes; 892 893 printk("mode13dma_int, mode: %d\n", mode); 894 disable_dma(devpriv->dma); /* disable dma */ 895 bytes = devpriv->hwdmasize[0]; 896 if (!devpriv->neverending_ai) { 897 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */ 898 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */ 899 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */ 900 devpriv->dma_runs_to_end--; 901 if (devpriv->dma_runs_to_end >= 0) 902 bytes = devpriv->hwdmasize[0]; 903 } 904 905 devpriv->next_dma_buf = 0; 906 set_dma_mode(devpriv->dma, DMA_MODE_READ); 907 flags = claim_dma_lock(); 908 clear_dma_ff(devpriv->dma); 909 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 910 set_dma_count(devpriv->dma, bytes); 911 release_dma_lock(flags); 912 enable_dma(devpriv->dma); 913 914 if (mode == 1) { 915 devpriv->ai_mode = INT_TYPE_AI1_DMA; 916 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */ 917 } else { 918 devpriv->ai_mode = INT_TYPE_AI3_DMA; 919 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */ 920 }; 921} 922 923#ifdef unused 924/* 925============================================================================== 926 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards 927*/ 928static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev, 929 struct comedi_subdevice *s) 930{ 931 unsigned int flags; 932 short *pole; 933 934 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT); 935 flags = claim_dma_lock(); 936 clear_dma_ff(devpriv->dma); 937 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 938 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]); 939 release_dma_lock(flags); 940 enable_dma(devpriv->dma); 941 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */ 942 pole = (short *)devpriv->dmabuf[0]; 943 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2; 944 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD; 945#ifdef unused 946 devpriv->rtc_freq = rtc_setfreq_irq(2048); 947 devpriv->rtc_irq_timer.expires = 948 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100; 949 devpriv->rtc_irq_timer.data = (unsigned long)dev; 950 devpriv->rtc_irq_timer.function = rtc_dropped_irq; 951 952 add_timer(&devpriv->rtc_irq_timer); 953#endif 954 955 if (mode == 1) { 956 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC; 957 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */ 958 } else { 959 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC; 960 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */ 961 }; 962} 963#endif 964 965/* 966============================================================================== 967 ANALOG INPUT MODE 1 or 3, 818 cards 968*/ 969static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, 970 struct comedi_subdevice *s) 971{ 972 struct comedi_cmd *cmd = &s->async->cmd; 973 int divisor1, divisor2; 974 unsigned int seglen; 975 976 printk("pcl818_ai_cmd_mode()\n"); 977 if ((!dev->irq) && (!devpriv->dma_rtc)) { 978 comedi_error(dev, "IRQ not defined!"); 979 return -EINVAL; 980 } 981 982 if (devpriv->irq_blocked) 983 return -EBUSY; 984 985 start_pacer(dev, -1, 0, 0); /* stop pacer */ 986 987 seglen = check_channel_list(dev, s, devpriv->ai_chanlist, 988 devpriv->ai_n_chan); 989 if (seglen < 1) 990 return -EINVAL; 991 setup_channel_list(dev, s, devpriv->ai_chanlist, 992 devpriv->ai_n_chan, seglen); 993 994 udelay(1); 995 996 devpriv->ai_act_scan = devpriv->ai_scans; 997 devpriv->ai_act_chan = 0; 998 devpriv->irq_blocked = 1; 999 devpriv->irq_was_now_closed = 0; 1000 devpriv->neverending_ai = 0; 1001 devpriv->act_chanlist_pos = 0; 1002 devpriv->dma_runs_to_end = 0; 1003 1004 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) 1005 devpriv->neverending_ai = 1; /* well, user want neverending */ 1006 1007 if (mode == 1) { 1008 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1009 &divisor2, &cmd->convert_arg, 1010 TRIG_ROUND_NEAREST); 1011 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */ 1012 divisor1 = 2; 1013 divisor2 /= 2; 1014 } 1015 if (divisor2 == 1) { 1016 divisor2 = 2; 1017 divisor1 /= 2; 1018 } 1019 } 1020 1021 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ 1022 1023 switch (devpriv->dma) { 1024 case 1: /* DMA */ 1025 case 3: 1026 if (devpriv->dma_rtc == 0) { 1027 pcl818_ai_mode13dma_int(mode, dev, s); 1028 } 1029#ifdef unused 1030 else { 1031 pcl818_ai_mode13dma_rtc(mode, dev, s); 1032 } 1033#else 1034 else { 1035 return -EINVAL; 1036 } 1037#endif 1038 break; 1039 case 0: 1040 if (!devpriv->usefifo) { 1041 /* IRQ */ 1042 /* printk("IRQ\n"); */ 1043 if (mode == 1) { 1044 devpriv->ai_mode = INT_TYPE_AI1_INT; 1045 /* Pacer+IRQ */ 1046 outb(0x83 | (dev->irq << 4), 1047 dev->iobase + PCL818_CONTROL); 1048 } else { 1049 devpriv->ai_mode = INT_TYPE_AI3_INT; 1050 /* Ext trig+IRQ */ 1051 outb(0x82 | (dev->irq << 4), 1052 dev->iobase + PCL818_CONTROL); 1053 } 1054 } else { 1055 /* FIFO */ 1056 /* enable FIFO */ 1057 outb(1, dev->iobase + PCL818_FI_ENABLE); 1058 if (mode == 1) { 1059 devpriv->ai_mode = INT_TYPE_AI1_FIFO; 1060 /* Pacer */ 1061 outb(0x03, dev->iobase + PCL818_CONTROL); 1062 } else { 1063 devpriv->ai_mode = INT_TYPE_AI3_FIFO; 1064 outb(0x02, dev->iobase + PCL818_CONTROL); 1065 } 1066 } 1067 } 1068 1069 start_pacer(dev, mode, divisor1, divisor2); 1070 1071#ifdef unused 1072 switch (devpriv->ai_mode) { 1073 case INT_TYPE_AI1_DMA_RTC: 1074 case INT_TYPE_AI3_DMA_RTC: 1075 set_rtc_irq_bit(1); /* start RTC */ 1076 break; 1077 } 1078#endif 1079 printk("pcl818_ai_cmd_mode() end\n"); 1080 return 0; 1081} 1082 1083#ifdef unused 1084/* 1085============================================================================== 1086 ANALOG OUTPUT MODE 1 or 3, 818 cards 1087*/ 1088#ifdef PCL818_MODE13_AO 1089static int pcl818_ao_mode13(int mode, struct comedi_device *dev, 1090 struct comedi_subdevice *s, comedi_trig * it) 1091{ 1092 int divisor1, divisor2; 1093 1094 if (!dev->irq) { 1095 comedi_error(dev, "IRQ not defined!"); 1096 return -EINVAL; 1097 } 1098 1099 if (devpriv->irq_blocked) 1100 return -EBUSY; 1101 1102 start_pacer(dev, -1, 0, 0); /* stop pacer */ 1103 1104 devpriv->int13_act_scan = it->n; 1105 devpriv->int13_act_chan = 0; 1106 devpriv->irq_blocked = 1; 1107 devpriv->irq_was_now_closed = 0; 1108 devpriv->neverending_ai = 0; 1109 devpriv->act_chanlist_pos = 0; 1110 1111 if (mode == 1) { 1112 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1113 &divisor2, &it->trigvar, 1114 TRIG_ROUND_NEAREST); 1115 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */ 1116 divisor1 = 2; 1117 divisor2 /= 2; 1118 } 1119 if (divisor2 == 1) { 1120 divisor2 = 2; 1121 divisor1 /= 2; 1122 } 1123 } 1124 1125 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ 1126 if (mode == 1) { 1127 devpriv->int818_mode = INT_TYPE_AO1_INT; 1128 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */ 1129 } else { 1130 devpriv->int818_mode = INT_TYPE_AO3_INT; 1131 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */ 1132 }; 1133 1134 start_pacer(dev, mode, divisor1, divisor2); 1135 1136 return 0; 1137} 1138 1139/* 1140============================================================================== 1141 ANALOG OUTPUT MODE 1, 818 cards 1142*/ 1143static int pcl818_ao_mode1(struct comedi_device *dev, 1144 struct comedi_subdevice *s, comedi_trig * it) 1145{ 1146 return pcl818_ao_mode13(1, dev, s, it); 1147} 1148 1149/* 1150============================================================================== 1151 ANALOG OUTPUT MODE 3, 818 cards 1152*/ 1153static int pcl818_ao_mode3(struct comedi_device *dev, 1154 struct comedi_subdevice *s, comedi_trig * it) 1155{ 1156 return pcl818_ao_mode13(3, dev, s, it); 1157} 1158#endif 1159#endif 1160 1161/* 1162============================================================================== 1163 Start/stop pacer onboard pacer 1164*/ 1165static void start_pacer(struct comedi_device *dev, int mode, 1166 unsigned int divisor1, unsigned int divisor2) 1167{ 1168 outb(0xb4, dev->iobase + PCL818_CTRCTL); 1169 outb(0x74, dev->iobase + PCL818_CTRCTL); 1170 udelay(1); 1171 1172 if (mode == 1) { 1173 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2); 1174 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2); 1175 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1); 1176 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1); 1177 } 1178} 1179 1180/* 1181============================================================================== 1182 Check if channel list from user is builded correctly 1183 If it's ok, then program scan/gain logic 1184*/ 1185static int check_channel_list(struct comedi_device *dev, 1186 struct comedi_subdevice *s, 1187 unsigned int *chanlist, unsigned int n_chan) 1188{ 1189 unsigned int chansegment[16]; 1190 unsigned int i, nowmustbechan, seglen, segpos; 1191 1192 /* correct channel and range number check itself comedi/range.c */ 1193 if (n_chan < 1) { 1194 comedi_error(dev, "range/channel list is empty!"); 1195 return 0; 1196 } 1197 1198 if (n_chan > 1) { 1199 /* first channel is everytime ok */ 1200 chansegment[0] = chanlist[0]; 1201 /* build part of chanlist */ 1202 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { 1203 1204 /* printk("%d. %d * %d\n",i, 1205 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/ 1206 1207 /* we detect loop, this must by finish */ 1208 1209 if (chanlist[0] == chanlist[i]) 1210 break; 1211 nowmustbechan = 1212 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; 1213 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ 1214 printk 1215 ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", 1216 dev->minor, i, CR_CHAN(chanlist[i]), 1217 nowmustbechan, CR_CHAN(chanlist[0])); 1218 return 0; 1219 } 1220 /* well, this is next correct channel in list */ 1221 chansegment[i] = chanlist[i]; 1222 } 1223 1224 /* check whole chanlist */ 1225 for (i = 0, segpos = 0; i < n_chan; i++) { 1226 /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */ 1227 if (chanlist[i] != chansegment[i % seglen]) { 1228 printk 1229 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", 1230 dev->minor, i, CR_CHAN(chansegment[i]), 1231 CR_RANGE(chansegment[i]), 1232 CR_AREF(chansegment[i]), 1233 CR_CHAN(chanlist[i % seglen]), 1234 CR_RANGE(chanlist[i % seglen]), 1235 CR_AREF(chansegment[i % seglen])); 1236 return 0; /* chan/gain list is strange */ 1237 } 1238 } 1239 } else { 1240 seglen = 1; 1241 } 1242 printk("check_channel_list: seglen %d\n", seglen); 1243 return seglen; 1244} 1245 1246static void setup_channel_list(struct comedi_device *dev, 1247 struct comedi_subdevice *s, 1248 unsigned int *chanlist, unsigned int n_chan, 1249 unsigned int seglen) 1250{ 1251 int i; 1252 1253 devpriv->act_chanlist_len = seglen; 1254 devpriv->act_chanlist_pos = 0; 1255 1256 for (i = 0; i < seglen; i++) { /* store range list to card */ 1257 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); 1258 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */ 1259 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */ 1260 } 1261 1262 udelay(1); 1263 1264 /* select channel interval to scan */ 1265 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen - 1266 1] << 4), 1267 dev->iobase + PCL818_MUX); 1268} 1269 1270/* 1271============================================================================== 1272 Check if board is switched to SE (1) or DIFF(0) mode 1273*/ 1274static int check_single_ended(unsigned int port) 1275{ 1276 if (inb(port + PCL818_STATUS) & 0x20) { 1277 return 1; 1278 } else { 1279 return 0; 1280 } 1281} 1282 1283/* 1284============================================================================== 1285*/ 1286static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 1287 struct comedi_cmd *cmd) 1288{ 1289 int err = 0; 1290 int tmp, divisor1, divisor2; 1291 1292 /* step 1: make sure trigger sources are trivially valid */ 1293 1294 tmp = cmd->start_src; 1295 cmd->start_src &= TRIG_NOW; 1296 if (!cmd->start_src || tmp != cmd->start_src) 1297 err++; 1298 1299 tmp = cmd->scan_begin_src; 1300 cmd->scan_begin_src &= TRIG_FOLLOW; 1301 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 1302 err++; 1303 1304 tmp = cmd->convert_src; 1305 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 1306 if (!cmd->convert_src || tmp != cmd->convert_src) 1307 err++; 1308 1309 tmp = cmd->scan_end_src; 1310 cmd->scan_end_src &= TRIG_COUNT; 1311 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 1312 err++; 1313 1314 tmp = cmd->stop_src; 1315 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 1316 if (!cmd->stop_src || tmp != cmd->stop_src) 1317 err++; 1318 1319 if (err) { 1320 return 1; 1321 } 1322 1323 /* step 2: make sure trigger sources are unique and mutually compatible */ 1324 1325 if (cmd->start_src != TRIG_NOW) { 1326 cmd->start_src = TRIG_NOW; 1327 err++; 1328 } 1329 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1330 cmd->scan_begin_src = TRIG_FOLLOW; 1331 err++; 1332 } 1333 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 1334 err++; 1335 1336 if (cmd->scan_end_src != TRIG_COUNT) { 1337 cmd->scan_end_src = TRIG_COUNT; 1338 err++; 1339 } 1340 1341 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) 1342 err++; 1343 1344 if (err) { 1345 return 2; 1346 } 1347 1348 /* step 3: make sure arguments are trivially compatible */ 1349 1350 if (cmd->start_arg != 0) { 1351 cmd->start_arg = 0; 1352 err++; 1353 } 1354 1355 if (cmd->scan_begin_arg != 0) { 1356 cmd->scan_begin_arg = 0; 1357 err++; 1358 } 1359 1360 if (cmd->convert_src == TRIG_TIMER) { 1361 if (cmd->convert_arg < this_board->ns_min) { 1362 cmd->convert_arg = this_board->ns_min; 1363 err++; 1364 } 1365 } else { /* TRIG_EXT */ 1366 if (cmd->convert_arg != 0) { 1367 cmd->convert_arg = 0; 1368 err++; 1369 } 1370 } 1371 1372 if (!cmd->chanlist_len) { 1373 cmd->chanlist_len = 1; 1374 err++; 1375 } 1376 if (cmd->chanlist_len > s->n_chan) { 1377 cmd->chanlist_len = s->n_chan; 1378 err++; 1379 } 1380 if (cmd->scan_end_arg != cmd->chanlist_len) { 1381 cmd->scan_end_arg = cmd->chanlist_len; 1382 err++; 1383 } 1384 if (cmd->stop_src == TRIG_COUNT) { 1385 if (!cmd->stop_arg) { 1386 cmd->stop_arg = 1; 1387 err++; 1388 } 1389 } else { /* TRIG_NONE */ 1390 if (cmd->stop_arg != 0) { 1391 cmd->stop_arg = 0; 1392 err++; 1393 } 1394 } 1395 1396 if (err) { 1397 return 3; 1398 } 1399 1400 /* step 4: fix up any arguments */ 1401 1402 if (cmd->convert_src == TRIG_TIMER) { 1403 tmp = cmd->convert_arg; 1404 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1405 &divisor2, &cmd->convert_arg, 1406 cmd->flags & TRIG_ROUND_MASK); 1407 if (cmd->convert_arg < this_board->ns_min) 1408 cmd->convert_arg = this_board->ns_min; 1409 if (tmp != cmd->convert_arg) 1410 err++; 1411 } 1412 1413 if (err) { 1414 return 4; 1415 } 1416 1417 /* step 5: complain about special chanlist considerations */ 1418 1419 if (cmd->chanlist) { 1420 if (!check_channel_list(dev, s, cmd->chanlist, 1421 cmd->chanlist_len)) 1422 return 5; /* incorrect channels list */ 1423 } 1424 1425 return 0; 1426} 1427 1428/* 1429============================================================================== 1430*/ 1431static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1432{ 1433 struct comedi_cmd *cmd = &s->async->cmd; 1434 int retval; 1435 1436 printk("pcl818_ai_cmd()\n"); 1437 devpriv->ai_n_chan = cmd->chanlist_len; 1438 devpriv->ai_chanlist = cmd->chanlist; 1439 devpriv->ai_flags = cmd->flags; 1440 devpriv->ai_data_len = s->async->prealloc_bufsz; 1441 devpriv->ai_data = s->async->prealloc_buf; 1442 devpriv->ai_timer1 = 0; 1443 devpriv->ai_timer2 = 0; 1444 1445 if (cmd->stop_src == TRIG_COUNT) { 1446 devpriv->ai_scans = cmd->stop_arg; 1447 } else { 1448 devpriv->ai_scans = 0; 1449 } 1450 1451 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */ 1452 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */ 1453 devpriv->ai_timer1 = cmd->convert_arg; 1454 retval = pcl818_ai_cmd_mode(1, dev, s); 1455 printk("pcl818_ai_cmd() end\n"); 1456 return retval; 1457 } 1458 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ 1459 return pcl818_ai_cmd_mode(3, dev, s); 1460 } 1461 } 1462 1463 return -1; 1464} 1465 1466/* 1467============================================================================== 1468 cancel any mode 1-4 AI 1469*/ 1470static int pcl818_ai_cancel(struct comedi_device *dev, 1471 struct comedi_subdevice *s) 1472{ 1473 if (devpriv->irq_blocked > 0) { 1474 printk("pcl818_ai_cancel()\n"); 1475 devpriv->irq_was_now_closed = 1; 1476 1477 switch (devpriv->ai_mode) { 1478#ifdef unused 1479 case INT_TYPE_AI1_DMA_RTC: 1480 case INT_TYPE_AI3_DMA_RTC: 1481 set_rtc_irq_bit(0); /* stop RTC */ 1482 del_timer(&devpriv->rtc_irq_timer); 1483#endif 1484 case INT_TYPE_AI1_DMA: 1485 case INT_TYPE_AI3_DMA: 1486 if (devpriv->neverending_ai || 1487 (!devpriv->neverending_ai && 1488 devpriv->ai_act_scan > 0)) { 1489 /* wait for running dma transfer to end, do cleanup in interrupt */ 1490 goto end; 1491 } 1492 disable_dma(devpriv->dma); 1493 case INT_TYPE_AI1_INT: 1494 case INT_TYPE_AI3_INT: 1495 case INT_TYPE_AI1_FIFO: 1496 case INT_TYPE_AI3_FIFO: 1497#ifdef PCL818_MODE13_AO 1498 case INT_TYPE_AO1_INT: 1499 case INT_TYPE_AO3_INT: 1500#endif 1501 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */ 1502 udelay(1); 1503 start_pacer(dev, -1, 0, 0); 1504 outb(0, dev->iobase + PCL818_AD_LO); 1505 inb(dev->iobase + PCL818_AD_LO); 1506 inb(dev->iobase + PCL818_AD_HI); 1507 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 1508 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */ 1509 if (devpriv->usefifo) { /* FIFO shutdown */ 1510 outb(0, dev->iobase + PCL818_FI_INTCLR); 1511 outb(0, dev->iobase + PCL818_FI_FLUSH); 1512 outb(0, dev->iobase + PCL818_FI_ENABLE); 1513 } 1514 devpriv->irq_blocked = 0; 1515 devpriv->last_int_sub = s; 1516 devpriv->neverending_ai = 0; 1517 devpriv->ai_mode = 0; 1518 devpriv->irq_was_now_closed = 0; 1519 break; 1520 } 1521 } 1522 1523end: 1524 printk("pcl818_ai_cancel() end\n"); 1525 return 0; 1526} 1527 1528/* 1529============================================================================== 1530 chech for PCL818 1531*/ 1532static int pcl818_check(unsigned long iobase) 1533{ 1534 outb(0x00, iobase + PCL818_MUX); 1535 udelay(1); 1536 if (inb(iobase + PCL818_MUX) != 0x00) 1537 return 1; /* there isn't card */ 1538 outb(0x55, iobase + PCL818_MUX); 1539 udelay(1); 1540 if (inb(iobase + PCL818_MUX) != 0x55) 1541 return 1; /* there isn't card */ 1542 outb(0x00, iobase + PCL818_MUX); 1543 udelay(1); 1544 outb(0x18, iobase + PCL818_CONTROL); 1545 udelay(1); 1546 if (inb(iobase + PCL818_CONTROL) != 0x18) 1547 return 1; /* there isn't card */ 1548 return 0; /* ok, card exist */ 1549} 1550 1551/* 1552============================================================================== 1553 reset whole PCL-818 cards 1554*/ 1555static void pcl818_reset(struct comedi_device *dev) 1556{ 1557 if (devpriv->usefifo) { /* FIFO shutdown */ 1558 outb(0, dev->iobase + PCL818_FI_INTCLR); 1559 outb(0, dev->iobase + PCL818_FI_FLUSH); 1560 outb(0, dev->iobase + PCL818_FI_ENABLE); 1561 } 1562 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */ 1563 outb(0, dev->iobase + PCL818_DA_HI); 1564 udelay(1); 1565 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */ 1566 outb(0, dev->iobase + PCL818_DO_LO); 1567 udelay(1); 1568 outb(0, dev->iobase + PCL818_CONTROL); 1569 outb(0, dev->iobase + PCL818_CNTENABLE); 1570 outb(0, dev->iobase + PCL818_MUX); 1571 outb(0, dev->iobase + PCL818_CLRINT); 1572 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */ 1573 outb(0x70, dev->iobase + PCL818_CTRCTL); 1574 outb(0x30, dev->iobase + PCL818_CTRCTL); 1575 if (this_board->is_818) { 1576 outb(0, dev->iobase + PCL818_RANGE); 1577 } else { 1578 outb(0, dev->iobase + PCL718_DA2_LO); 1579 outb(0, dev->iobase + PCL718_DA2_HI); 1580 } 1581} 1582 1583#ifdef unused 1584/* 1585============================================================================== 1586 Enable(1)/disable(0) periodic interrupts from RTC 1587*/ 1588static int set_rtc_irq_bit(unsigned char bit) 1589{ 1590 unsigned char val; 1591 unsigned long flags; 1592 1593 if (bit == 1) { 1594 RTC_timer_lock++; 1595 if (RTC_timer_lock > 1) 1596 return 0; 1597 } else { 1598 RTC_timer_lock--; 1599 if (RTC_timer_lock < 0) 1600 RTC_timer_lock = 0; 1601 if (RTC_timer_lock > 0) 1602 return 0; 1603 } 1604 1605 save_flags(flags); 1606 cli(); 1607 val = CMOS_READ(RTC_CONTROL); 1608 if (bit) { 1609 val |= RTC_PIE; 1610 } else { 1611 val &= ~RTC_PIE; 1612 } 1613 CMOS_WRITE(val, RTC_CONTROL); 1614 CMOS_READ(RTC_INTR_FLAGS); 1615 restore_flags(flags); 1616 return 0; 1617} 1618 1619/* 1620============================================================================== 1621 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers) 1622*/ 1623static void rtc_dropped_irq(unsigned long data) 1624{ 1625 struct comedi_device *dev = (void *)data; 1626 unsigned long flags, tmp; 1627 1628 switch (devpriv->int818_mode) { 1629 case INT_TYPE_AI1_DMA_RTC: 1630 case INT_TYPE_AI3_DMA_RTC: 1631 mod_timer(&devpriv->rtc_irq_timer, 1632 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); 1633 save_flags(flags); 1634 cli(); 1635 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ 1636 restore_flags(flags); 1637 break; 1638 }; 1639} 1640 1641/* 1642============================================================================== 1643 Set frequency of interrupts from RTC 1644*/ 1645static int rtc_setfreq_irq(int freq) 1646{ 1647 int tmp = 0; 1648 int rtc_freq; 1649 unsigned char val; 1650 unsigned long flags; 1651 1652 if (freq < 2) 1653 freq = 2; 1654 if (freq > 8192) 1655 freq = 8192; 1656 1657 while (freq > (1 << tmp)) 1658 tmp++; 1659 1660 rtc_freq = 1 << tmp; 1661 1662 save_flags(flags); 1663 cli(); 1664 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0; 1665 val |= (16 - tmp); 1666 CMOS_WRITE(val, RTC_FREQ_SELECT); 1667 restore_flags(flags); 1668 return rtc_freq; 1669} 1670#endif 1671 1672/* 1673============================================================================== 1674 Free any resources that we have claimed 1675*/ 1676static void free_resources(struct comedi_device *dev) 1677{ 1678 /* printk("free_resource()\n"); */ 1679 if (dev->private) { 1680 pcl818_ai_cancel(dev, devpriv->sub_ai); 1681 pcl818_reset(dev); 1682 if (devpriv->dma) 1683 free_dma(devpriv->dma); 1684 if (devpriv->dmabuf[0]) 1685 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); 1686 if (devpriv->dmabuf[1]) 1687 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); 1688#ifdef unused 1689 if (devpriv->rtc_irq) 1690 free_irq(devpriv->rtc_irq, dev); 1691 if ((devpriv->dma_rtc) && (RTC_lock == 1)) { 1692 if (devpriv->rtc_iobase) 1693 release_region(devpriv->rtc_iobase, 1694 devpriv->rtc_iosize); 1695 } 1696 if (devpriv->dma_rtc) 1697 RTC_lock--; 1698#endif 1699 } 1700 1701 if (dev->irq) 1702 free_irq(dev->irq, dev); 1703 if (dev->iobase) 1704 release_region(dev->iobase, devpriv->io_range); 1705 /* printk("free_resource() end\n"); */ 1706} 1707 1708/* 1709============================================================================== 1710 1711 Initialization 1712 1713*/ 1714static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1715{ 1716 int ret; 1717 unsigned long iobase; 1718 unsigned int irq; 1719 int dma; 1720 unsigned long pages; 1721 struct comedi_subdevice *s; 1722 1723 ret = alloc_private(dev, sizeof(struct pcl818_private)); 1724 if (ret < 0) 1725 return ret; /* Can't alloc mem */ 1726 1727 /* claim our I/O space */ 1728 iobase = it->options[0]; 1729 printk("comedi%d: pcl818: board=%s, ioport=0x%03lx", 1730 dev->minor, this_board->name, iobase); 1731 devpriv->io_range = this_board->io_range; 1732 if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */ 1733 devpriv->io_range = PCLx1xFIFO_RANGE; 1734 devpriv->usefifo = 1; 1735 } 1736 if (!request_region(iobase, devpriv->io_range, "pcl818")) { 1737 printk("I/O port conflict\n"); 1738 return -EIO; 1739 } 1740 1741 dev->iobase = iobase; 1742 1743 if (pcl818_check(iobase)) { 1744 printk(", I can't detect board. FAIL!\n"); 1745 return -EIO; 1746 } 1747 1748 /* set up some name stuff */ 1749 dev->board_name = this_board->name; 1750 /* grab our IRQ */ 1751 irq = 0; 1752 if (this_board->IRQbits != 0) { /* board support IRQ */ 1753 irq = it->options[1]; 1754 if (irq) { /* we want to use IRQ */ 1755 if (((1 << irq) & this_board->IRQbits) == 0) { 1756 printk 1757 (", IRQ %u is out of allowed range, DISABLING IT", 1758 irq); 1759 irq = 0; /* Bad IRQ */ 1760 } else { 1761 if (request_irq 1762 (irq, interrupt_pcl818, 0, "pcl818", dev)) { 1763 printk 1764 (", unable to allocate IRQ %u, DISABLING IT", 1765 irq); 1766 irq = 0; /* Can't use IRQ */ 1767 } else { 1768 printk(", irq=%u", irq); 1769 } 1770 } 1771 } 1772 } 1773 1774 dev->irq = irq; 1775 if (irq) { 1776 devpriv->irq_free = 1; 1777 } /* 1=we have allocated irq */ 1778 else { 1779 devpriv->irq_free = 0; 1780 } 1781 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ 1782 devpriv->ai_mode = 0; /* mode of irq */ 1783 1784#ifdef unused 1785 /* grab RTC for DMA operations */ 1786 devpriv->dma_rtc = 0; 1787 if (it->options[2] > 0) { /* we want to use DMA */ 1788 if (RTC_lock == 0) { 1789 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, 1790 "pcl818 (RTC)")) 1791 goto no_rtc; 1792 } 1793 devpriv->rtc_iobase = RTC_PORT(0); 1794 devpriv->rtc_iosize = RTC_IO_EXTENT; 1795 RTC_lock++; 1796 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0, 1797 "pcl818 DMA (RTC)", dev)) { 1798 devpriv->dma_rtc = 1; 1799 devpriv->rtc_irq = RTC_IRQ; 1800 printk(", dma_irq=%u", devpriv->rtc_irq); 1801 } else { 1802 RTC_lock--; 1803 if (RTC_lock == 0) { 1804 if (devpriv->rtc_iobase) 1805 release_region(devpriv->rtc_iobase, 1806 devpriv->rtc_iosize); 1807 } 1808 devpriv->rtc_iobase = 0; 1809 devpriv->rtc_iosize = 0; 1810 } 1811 } 1812 1813no_rtc: 1814#endif 1815 /* grab our DMA */ 1816 dma = 0; 1817 devpriv->dma = dma; 1818 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) 1819 goto no_dma; /* if we haven't IRQ, we can't use DMA */ 1820 if (this_board->DMAbits != 0) { /* board support DMA */ 1821 dma = it->options[2]; 1822 if (dma < 1) 1823 goto no_dma; /* DMA disabled */ 1824 if (((1 << dma) & this_board->DMAbits) == 0) { 1825 printk(", DMA is out of allowed range, FAIL!\n"); 1826 return -EINVAL; /* Bad DMA */ 1827 } 1828 ret = request_dma(dma, "pcl818"); 1829 if (ret) { 1830 printk(", unable to allocate DMA %u, FAIL!\n", dma); 1831 return -EBUSY; /* DMA isn't free */ 1832 } 1833 devpriv->dma = dma; 1834 printk(", dma=%u", dma); 1835 pages = 2; /* we need 16KB */ 1836 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); 1837 if (!devpriv->dmabuf[0]) { 1838 printk(", unable to allocate DMA buffer, FAIL!\n"); 1839 /* maybe experiment with try_to_free_pages() will help .... */ 1840 return -EBUSY; /* no buffer :-( */ 1841 } 1842 devpriv->dmapages[0] = pages; 1843 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); 1844 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; 1845 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ 1846 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */ 1847 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); 1848 if (!devpriv->dmabuf[1]) { 1849 printk 1850 (", unable to allocate DMA buffer, FAIL!\n"); 1851 return -EBUSY; 1852 } 1853 devpriv->dmapages[1] = pages; 1854 devpriv->hwdmaptr[1] = 1855 virt_to_bus((void *)devpriv->dmabuf[1]); 1856 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; 1857 } 1858 } 1859 1860no_dma: 1861 1862 ret = alloc_subdevices(dev, 4); 1863 if (ret < 0) 1864 return ret; 1865 1866 s = dev->subdevices + 0; 1867 if (!this_board->n_aichan_se) { 1868 s->type = COMEDI_SUBD_UNUSED; 1869 } else { 1870 s->type = COMEDI_SUBD_AI; 1871 devpriv->sub_ai = s; 1872 s->subdev_flags = SDF_READABLE; 1873 if (check_single_ended(dev->iobase)) { 1874 s->n_chan = this_board->n_aichan_se; 1875 s->subdev_flags |= SDF_COMMON | SDF_GROUND; 1876 printk(", %dchans S.E. DAC", s->n_chan); 1877 } else { 1878 s->n_chan = this_board->n_aichan_diff; 1879 s->subdev_flags |= SDF_DIFF; 1880 printk(", %dchans DIFF DAC", s->n_chan); 1881 } 1882 s->maxdata = this_board->ai_maxdata; 1883 s->len_chanlist = s->n_chan; 1884 s->range_table = this_board->ai_range_type; 1885 s->cancel = pcl818_ai_cancel; 1886 s->insn_read = pcl818_ai_insn_read; 1887 if ((irq) || (devpriv->dma_rtc)) { 1888 dev->read_subdev = s; 1889 s->subdev_flags |= SDF_CMD_READ; 1890 s->do_cmdtest = ai_cmdtest; 1891 s->do_cmd = ai_cmd; 1892 } 1893 if (this_board->is_818) { 1894 if ((it->options[4] == 1) || (it->options[4] == 10)) 1895 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */ 1896 } else { 1897 switch (it->options[4]) { 1898 case 0: 1899 s->range_table = &range_bipolar10; 1900 break; 1901 case 1: 1902 s->range_table = &range_bipolar5; 1903 break; 1904 case 2: 1905 s->range_table = &range_bipolar2_5; 1906 break; 1907 case 3: 1908 s->range_table = &range718_bipolar1; 1909 break; 1910 case 4: 1911 s->range_table = &range718_bipolar0_5; 1912 break; 1913 case 6: 1914 s->range_table = &range_unipolar10; 1915 break; 1916 case 7: 1917 s->range_table = &range_unipolar5; 1918 break; 1919 case 8: 1920 s->range_table = &range718_unipolar2; 1921 break; 1922 case 9: 1923 s->range_table = &range718_unipolar1; 1924 break; 1925 default: 1926 s->range_table = &range_unknown; 1927 break; 1928 } 1929 } 1930 } 1931 1932 s = dev->subdevices + 1; 1933 if (!this_board->n_aochan) { 1934 s->type = COMEDI_SUBD_UNUSED; 1935 } else { 1936 s->type = COMEDI_SUBD_AO; 1937 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 1938 s->n_chan = this_board->n_aochan; 1939 s->maxdata = this_board->ao_maxdata; 1940 s->len_chanlist = this_board->n_aochan; 1941 s->range_table = this_board->ao_range_type; 1942 s->insn_read = pcl818_ao_insn_read; 1943 s->insn_write = pcl818_ao_insn_write; 1944#ifdef unused 1945#ifdef PCL818_MODE13_AO 1946 if (irq) { 1947 s->trig[1] = pcl818_ao_mode1; 1948 s->trig[3] = pcl818_ao_mode3; 1949 } 1950#endif 1951#endif 1952 if (this_board->is_818) { 1953 if ((it->options[4] == 1) || (it->options[4] == 10)) 1954 s->range_table = &range_unipolar10; 1955 if (it->options[4] == 2) 1956 s->range_table = &range_unknown; 1957 } else { 1958 if ((it->options[5] == 1) || (it->options[5] == 10)) 1959 s->range_table = &range_unipolar10; 1960 if (it->options[5] == 2) 1961 s->range_table = &range_unknown; 1962 } 1963 } 1964 1965 s = dev->subdevices + 2; 1966 if (!this_board->n_dichan) { 1967 s->type = COMEDI_SUBD_UNUSED; 1968 } else { 1969 s->type = COMEDI_SUBD_DI; 1970 s->subdev_flags = SDF_READABLE; 1971 s->n_chan = this_board->n_dichan; 1972 s->maxdata = 1; 1973 s->len_chanlist = this_board->n_dichan; 1974 s->range_table = &range_digital; 1975 s->insn_bits = pcl818_di_insn_bits; 1976 } 1977 1978 s = dev->subdevices + 3; 1979 if (!this_board->n_dochan) { 1980 s->type = COMEDI_SUBD_UNUSED; 1981 } else { 1982 s->type = COMEDI_SUBD_DO; 1983 s->subdev_flags = SDF_WRITABLE; 1984 s->n_chan = this_board->n_dochan; 1985 s->maxdata = 1; 1986 s->len_chanlist = this_board->n_dochan; 1987 s->range_table = &range_digital; 1988 s->insn_bits = pcl818_do_insn_bits; 1989 } 1990 1991 /* select 1/10MHz oscilator */ 1992 if ((it->options[3] == 0) || (it->options[3] == 10)) { 1993 devpriv->i8253_osc_base = 100; 1994 } else { 1995 devpriv->i8253_osc_base = 1000; 1996 } 1997 1998 /* max sampling speed */ 1999 devpriv->ns_min = this_board->ns_min; 2000 2001 if (!this_board->is_818) { 2002 if ((it->options[6] == 1) || (it->options[6] == 100)) 2003 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ 2004 } 2005 2006 pcl818_reset(dev); 2007 2008 printk("\n"); 2009 2010 return 0; 2011} 2012 2013/* 2014============================================================================== 2015 Removes device 2016 */ 2017static int pcl818_detach(struct comedi_device *dev) 2018{ 2019 /* printk("comedi%d: pcl818: remove\n", dev->minor); */ 2020 free_resources(dev); 2021 return 0; 2022} 2023