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