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