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