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