pcl818.c revision c3744138715045adb316284ee7a1e608f0278f6c
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) 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 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) { 824 if ((devpriv->neverending_ai || (!devpriv->neverending_ai && 825 devpriv->ai_act_scan > 0)) && 826 (devpriv->ai_mode == INT_TYPE_AI1_DMA || 827 devpriv->ai_mode == INT_TYPE_AI3_DMA)) { 828 /* The cleanup from ai_cancel() has been delayed 829 until now because the card doesn't seem to like 830 being reprogrammed while a DMA transfer is in 831 progress. 832 */ 833 struct comedi_subdevice *s = dev->subdevices + 0; 834 devpriv->ai_act_scan = 0; 835 devpriv->neverending_ai = 0; 836 pcl818_ai_cancel(dev, s); 837 } 838 839 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 840 841 return IRQ_HANDLED; 842 } 843 844 switch (devpriv->ai_mode) { 845 case INT_TYPE_AI1_DMA: 846 case INT_TYPE_AI3_DMA: 847 return interrupt_pcl818_ai_mode13_dma(irq, d); 848 case INT_TYPE_AI1_INT: 849 case INT_TYPE_AI3_INT: 850 return interrupt_pcl818_ai_mode13_int(irq, d); 851 case INT_TYPE_AI1_FIFO: 852 case INT_TYPE_AI3_FIFO: 853 return interrupt_pcl818_ai_mode13_fifo(irq, d); 854#ifdef PCL818_MODE13_AO 855 case INT_TYPE_AO1_INT: 856 case INT_TYPE_AO3_INT: 857 return interrupt_pcl818_ao_mode13_int(irq, d); 858#endif 859 default: 860 break; 861 } 862 863 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 864 865 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked) 866 || (!devpriv->ai_mode)) { 867 comedi_error(dev, "bad IRQ!"); 868 return IRQ_NONE; 869 } 870 871 comedi_error(dev, "IRQ from unknow source!"); 872 return IRQ_NONE; 873} 874 875/* 876============================================================================== 877 ANALOG INPUT MODE 1 or 3 DMA , 818 cards 878*/ 879static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev, 880 struct comedi_subdevice *s) 881{ 882 unsigned int flags; 883 unsigned int bytes; 884 885 rt_printk("mode13dma_int, mode: %d\n", mode); 886 disable_dma(devpriv->dma); /* disable dma */ 887 bytes = devpriv->hwdmasize[0]; 888 if (!devpriv->neverending_ai) { 889 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */ 890 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */ 891 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */ 892 devpriv->dma_runs_to_end--; 893 if (devpriv->dma_runs_to_end >= 0) 894 bytes = devpriv->hwdmasize[0]; 895 } 896 897 devpriv->next_dma_buf = 0; 898 set_dma_mode(devpriv->dma, DMA_MODE_READ); 899 flags = claim_dma_lock(); 900 clear_dma_ff(devpriv->dma); 901 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 902 set_dma_count(devpriv->dma, bytes); 903 release_dma_lock(flags); 904 enable_dma(devpriv->dma); 905 906 if (mode == 1) { 907 devpriv->ai_mode = INT_TYPE_AI1_DMA; 908 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */ 909 } else { 910 devpriv->ai_mode = INT_TYPE_AI3_DMA; 911 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */ 912 }; 913} 914 915#ifdef unused 916/* 917============================================================================== 918 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards 919*/ 920static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev, 921 struct comedi_subdevice *s) 922{ 923 unsigned int flags; 924 short *pole; 925 926 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT); 927 flags = claim_dma_lock(); 928 clear_dma_ff(devpriv->dma); 929 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 930 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]); 931 release_dma_lock(flags); 932 enable_dma(devpriv->dma); 933 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */ 934 pole = (short *) devpriv->dmabuf[0]; 935 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2; 936 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD; 937#ifdef unused 938 devpriv->rtc_freq = rtc_setfreq_irq(2048); 939 devpriv->rtc_irq_timer.expires = 940 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100; 941 devpriv->rtc_irq_timer.data = (unsigned long)dev; 942 devpriv->rtc_irq_timer.function = rtc_dropped_irq; 943 944 add_timer(&devpriv->rtc_irq_timer); 945#endif 946 947 if (mode == 1) { 948 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC; 949 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */ 950 } else { 951 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC; 952 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */ 953 }; 954} 955#endif 956 957/* 958============================================================================== 959 ANALOG INPUT MODE 1 or 3, 818 cards 960*/ 961static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, 962 struct comedi_subdevice *s) 963{ 964 struct comedi_cmd *cmd = &s->async->cmd; 965 int divisor1, divisor2; 966 unsigned int seglen; 967 968 rt_printk("pcl818_ai_cmd_mode()\n"); 969 if ((!dev->irq) && (!devpriv->dma_rtc)) { 970 comedi_error(dev, "IRQ not defined!"); 971 return -EINVAL; 972 } 973 974 if (devpriv->irq_blocked) 975 return -EBUSY; 976 977 start_pacer(dev, -1, 0, 0); /* stop pacer */ 978 979 seglen = check_channel_list(dev, s, devpriv->ai_chanlist, 980 devpriv->ai_n_chan); 981 if (seglen < 1) 982 return -EINVAL; 983 setup_channel_list(dev, s, devpriv->ai_chanlist, 984 devpriv->ai_n_chan, seglen); 985 986 comedi_udelay(1); 987 988 devpriv->ai_act_scan = devpriv->ai_scans; 989 devpriv->ai_act_chan = 0; 990 devpriv->irq_blocked = 1; 991 devpriv->irq_was_now_closed = 0; 992 devpriv->neverending_ai = 0; 993 devpriv->act_chanlist_pos = 0; 994 devpriv->dma_runs_to_end = 0; 995 996 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) 997 devpriv->neverending_ai = 1; /* well, user want neverending */ 998 999 if (mode == 1) { 1000 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1001 &divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST); 1002 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */ 1003 divisor1 = 2; 1004 divisor2 /= 2; 1005 } 1006 if (divisor2 == 1) { 1007 divisor2 = 2; 1008 divisor1 /= 2; 1009 } 1010 } 1011 1012 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ 1013 1014 switch (devpriv->dma) { 1015 case 1: /* DMA */ 1016 case 3: 1017 if (devpriv->dma_rtc == 0) { 1018 pcl818_ai_mode13dma_int(mode, dev, s); 1019 } 1020#ifdef unused 1021 else { 1022 pcl818_ai_mode13dma_rtc(mode, dev, s); 1023 } 1024#else 1025 else { 1026 return -EINVAL; 1027 } 1028#endif 1029 break; 1030 case 0: 1031 if (!devpriv->usefifo) { 1032 /* IRQ */ 1033 /* rt_printk("IRQ\n"); */ 1034 if (mode == 1) { 1035 devpriv->ai_mode = INT_TYPE_AI1_INT; 1036 /* Pacer+IRQ */ 1037 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); 1038 } else { 1039 devpriv->ai_mode = INT_TYPE_AI3_INT; 1040 /* Ext trig+IRQ */ 1041 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); 1042 } 1043 } else { 1044 /* FIFO */ 1045 /* enable FIFO */ 1046 outb(1, dev->iobase + PCL818_FI_ENABLE); 1047 if (mode == 1) { 1048 devpriv->ai_mode = INT_TYPE_AI1_FIFO; 1049 /* Pacer */ 1050 outb(0x03, dev->iobase + PCL818_CONTROL); 1051 } else { 1052 devpriv->ai_mode = INT_TYPE_AI3_FIFO; 1053 outb(0x02, dev->iobase + PCL818_CONTROL); 1054 } 1055 } 1056 } 1057 1058 start_pacer(dev, mode, divisor1, divisor2); 1059 1060#ifdef unused 1061 switch (devpriv->ai_mode) { 1062 case INT_TYPE_AI1_DMA_RTC: 1063 case INT_TYPE_AI3_DMA_RTC: 1064 set_rtc_irq_bit(1); /* start RTC */ 1065 break; 1066 } 1067#endif 1068 rt_printk("pcl818_ai_cmd_mode() end\n"); 1069 return 0; 1070} 1071 1072#ifdef unused 1073/* 1074============================================================================== 1075 ANALOG OUTPUT MODE 1 or 3, 818 cards 1076*/ 1077#ifdef PCL818_MODE13_AO 1078static int pcl818_ao_mode13(int mode, struct comedi_device *dev, struct comedi_subdevice *s, 1079 comedi_trig *it) 1080{ 1081 int divisor1, divisor2; 1082 1083 if (!dev->irq) { 1084 comedi_error(dev, "IRQ not defined!"); 1085 return -EINVAL; 1086 } 1087 1088 if (devpriv->irq_blocked) 1089 return -EBUSY; 1090 1091 start_pacer(dev, -1, 0, 0); /* stop pacer */ 1092 1093 devpriv->int13_act_scan = it->n; 1094 devpriv->int13_act_chan = 0; 1095 devpriv->irq_blocked = 1; 1096 devpriv->irq_was_now_closed = 0; 1097 devpriv->neverending_ai = 0; 1098 devpriv->act_chanlist_pos = 0; 1099 1100 if (mode == 1) { 1101 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1102 &divisor2, &it->trigvar, TRIG_ROUND_NEAREST); 1103 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */ 1104 divisor1 = 2; 1105 divisor2 /= 2; 1106 } 1107 if (divisor2 == 1) { 1108 divisor2 = 2; 1109 divisor1 /= 2; 1110 } 1111 } 1112 1113 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ 1114 if (mode == 1) { 1115 devpriv->int818_mode = INT_TYPE_AO1_INT; 1116 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */ 1117 } else { 1118 devpriv->int818_mode = INT_TYPE_AO3_INT; 1119 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */ 1120 }; 1121 1122 start_pacer(dev, mode, divisor1, divisor2); 1123 1124 return 0; 1125} 1126 1127/* 1128============================================================================== 1129 ANALOG OUTPUT MODE 1, 818 cards 1130*/ 1131static int pcl818_ao_mode1(struct comedi_device *dev, struct comedi_subdevice *s, 1132 comedi_trig *it) 1133{ 1134 return pcl818_ao_mode13(1, dev, s, it); 1135} 1136 1137/* 1138============================================================================== 1139 ANALOG OUTPUT MODE 3, 818 cards 1140*/ 1141static int pcl818_ao_mode3(struct comedi_device *dev, struct comedi_subdevice *s, 1142 comedi_trig *it) 1143{ 1144 return pcl818_ao_mode13(3, dev, s, it); 1145} 1146#endif 1147#endif 1148 1149/* 1150============================================================================== 1151 Start/stop pacer onboard pacer 1152*/ 1153static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, 1154 unsigned int divisor2) 1155{ 1156 outb(0xb4, dev->iobase + PCL818_CTRCTL); 1157 outb(0x74, dev->iobase + PCL818_CTRCTL); 1158 comedi_udelay(1); 1159 1160 if (mode == 1) { 1161 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2); 1162 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2); 1163 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1); 1164 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1); 1165 } 1166} 1167 1168/* 1169============================================================================== 1170 Check if channel list from user is builded correctly 1171 If it's ok, then program scan/gain logic 1172*/ 1173static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, 1174 unsigned int *chanlist, unsigned int n_chan) 1175{ 1176 unsigned int chansegment[16]; 1177 unsigned int i, nowmustbechan, seglen, segpos; 1178 1179 /* correct channel and range number check itself comedi/range.c */ 1180 if (n_chan < 1) { 1181 comedi_error(dev, "range/channel list is empty!"); 1182 return 0; 1183 } 1184 1185 if (n_chan > 1) { 1186 /* first channel is everytime ok */ 1187 chansegment[0] = chanlist[0]; 1188 /* build part of chanlist */ 1189 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { 1190 1191 /* rt_printk("%d. %d * %d\n",i, 1192 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/ 1193 1194 /* we detect loop, this must by finish */ 1195 1196 if (chanlist[0] == chanlist[i]) 1197 break; 1198 nowmustbechan = 1199 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; 1200 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ 1201 rt_printk 1202 ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", 1203 dev->minor, i, CR_CHAN(chanlist[i]), 1204 nowmustbechan, CR_CHAN(chanlist[0])); 1205 return 0; 1206 } 1207 /* well, this is next correct channel in list */ 1208 chansegment[i] = chanlist[i]; 1209 } 1210 1211 /* check whole chanlist */ 1212 for (i = 0, segpos = 0; i < n_chan; i++) { 1213 /* 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])); */ 1214 if (chanlist[i] != chansegment[i % seglen]) { 1215 rt_printk 1216 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", 1217 dev->minor, i, CR_CHAN(chansegment[i]), 1218 CR_RANGE(chansegment[i]), 1219 CR_AREF(chansegment[i]), 1220 CR_CHAN(chanlist[i % seglen]), 1221 CR_RANGE(chanlist[i % seglen]), 1222 CR_AREF(chansegment[i % seglen])); 1223 return 0; /* chan/gain list is strange */ 1224 } 1225 } 1226 } else { 1227 seglen = 1; 1228 } 1229 rt_printk("check_channel_list: seglen %d\n", seglen); 1230 return seglen; 1231} 1232 1233static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, 1234 unsigned int *chanlist, unsigned int n_chan, unsigned int seglen) 1235{ 1236 int i; 1237 1238 devpriv->act_chanlist_len = seglen; 1239 devpriv->act_chanlist_pos = 0; 1240 1241 for (i = 0; i < seglen; i++) { /* store range list to card */ 1242 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); 1243 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */ 1244 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */ 1245 } 1246 1247 comedi_udelay(1); 1248 1249 /* select channel interval to scan */ 1250 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen - 1251 1] << 4), dev->iobase + PCL818_MUX); 1252} 1253 1254/* 1255============================================================================== 1256 Check if board is switched to SE (1) or DIFF(0) mode 1257*/ 1258static int check_single_ended(unsigned int port) 1259{ 1260 if (inb(port + PCL818_STATUS) & 0x20) { 1261 return 1; 1262 } else { 1263 return 0; 1264 } 1265} 1266 1267/* 1268============================================================================== 1269*/ 1270static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 1271 struct comedi_cmd *cmd) 1272{ 1273 int err = 0; 1274 int tmp, divisor1, divisor2; 1275 1276 /* step 1: make sure trigger sources are trivially valid */ 1277 1278 tmp = cmd->start_src; 1279 cmd->start_src &= TRIG_NOW; 1280 if (!cmd->start_src || tmp != cmd->start_src) 1281 err++; 1282 1283 tmp = cmd->scan_begin_src; 1284 cmd->scan_begin_src &= TRIG_FOLLOW; 1285 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 1286 err++; 1287 1288 tmp = cmd->convert_src; 1289 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 1290 if (!cmd->convert_src || tmp != cmd->convert_src) 1291 err++; 1292 1293 tmp = cmd->scan_end_src; 1294 cmd->scan_end_src &= TRIG_COUNT; 1295 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 1296 err++; 1297 1298 tmp = cmd->stop_src; 1299 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 1300 if (!cmd->stop_src || tmp != cmd->stop_src) 1301 err++; 1302 1303 if (err) { 1304 return 1; 1305 } 1306 1307 /* step 2: make sure trigger sources are unique and mutually compatible */ 1308 1309 if (cmd->start_src != TRIG_NOW) { 1310 cmd->start_src = TRIG_NOW; 1311 err++; 1312 } 1313 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1314 cmd->scan_begin_src = TRIG_FOLLOW; 1315 err++; 1316 } 1317 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 1318 err++; 1319 1320 if (cmd->scan_end_src != TRIG_COUNT) { 1321 cmd->scan_end_src = TRIG_COUNT; 1322 err++; 1323 } 1324 1325 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) 1326 err++; 1327 1328 if (err) { 1329 return 2; 1330 } 1331 1332 /* step 3: make sure arguments are trivially compatible */ 1333 1334 if (cmd->start_arg != 0) { 1335 cmd->start_arg = 0; 1336 err++; 1337 } 1338 1339 if (cmd->scan_begin_arg != 0) { 1340 cmd->scan_begin_arg = 0; 1341 err++; 1342 } 1343 1344 if (cmd->convert_src == TRIG_TIMER) { 1345 if (cmd->convert_arg < this_board->ns_min) { 1346 cmd->convert_arg = this_board->ns_min; 1347 err++; 1348 } 1349 } else { /* TRIG_EXT */ 1350 if (cmd->convert_arg != 0) { 1351 cmd->convert_arg = 0; 1352 err++; 1353 } 1354 } 1355 1356 if (!cmd->chanlist_len) { 1357 cmd->chanlist_len = 1; 1358 err++; 1359 } 1360 if (cmd->chanlist_len > s->n_chan) { 1361 cmd->chanlist_len = s->n_chan; 1362 err++; 1363 } 1364 if (cmd->scan_end_arg != cmd->chanlist_len) { 1365 cmd->scan_end_arg = cmd->chanlist_len; 1366 err++; 1367 } 1368 if (cmd->stop_src == TRIG_COUNT) { 1369 if (!cmd->stop_arg) { 1370 cmd->stop_arg = 1; 1371 err++; 1372 } 1373 } else { /* TRIG_NONE */ 1374 if (cmd->stop_arg != 0) { 1375 cmd->stop_arg = 0; 1376 err++; 1377 } 1378 } 1379 1380 if (err) { 1381 return 3; 1382 } 1383 1384 /* step 4: fix up any arguments */ 1385 1386 if (cmd->convert_src == TRIG_TIMER) { 1387 tmp = cmd->convert_arg; 1388 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, 1389 &divisor2, &cmd->convert_arg, 1390 cmd->flags & TRIG_ROUND_MASK); 1391 if (cmd->convert_arg < this_board->ns_min) 1392 cmd->convert_arg = this_board->ns_min; 1393 if (tmp != cmd->convert_arg) 1394 err++; 1395 } 1396 1397 if (err) { 1398 return 4; 1399 } 1400 1401 /* step 5: complain about special chanlist considerations */ 1402 1403 if (cmd->chanlist) { 1404 if (!check_channel_list(dev, s, cmd->chanlist, 1405 cmd->chanlist_len)) 1406 return 5; /* incorrect channels list */ 1407 } 1408 1409 return 0; 1410} 1411 1412/* 1413============================================================================== 1414*/ 1415static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1416{ 1417 struct comedi_cmd *cmd = &s->async->cmd; 1418 int retval; 1419 1420 rt_printk("pcl818_ai_cmd()\n"); 1421 devpriv->ai_n_chan = cmd->chanlist_len; 1422 devpriv->ai_chanlist = cmd->chanlist; 1423 devpriv->ai_flags = cmd->flags; 1424 devpriv->ai_data_len = s->async->prealloc_bufsz; 1425 devpriv->ai_data = s->async->prealloc_buf; 1426 devpriv->ai_timer1 = 0; 1427 devpriv->ai_timer2 = 0; 1428 1429 if (cmd->stop_src == TRIG_COUNT) { 1430 devpriv->ai_scans = cmd->stop_arg; 1431 } else { 1432 devpriv->ai_scans = 0; 1433 } 1434 1435 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */ 1436 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */ 1437 devpriv->ai_timer1 = cmd->convert_arg; 1438 retval = pcl818_ai_cmd_mode(1, dev, s); 1439 rt_printk("pcl818_ai_cmd() end\n"); 1440 return retval; 1441 } 1442 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ 1443 return pcl818_ai_cmd_mode(3, dev, s); 1444 } 1445 } 1446 1447 return -1; 1448} 1449 1450/* 1451============================================================================== 1452 cancel any mode 1-4 AI 1453*/ 1454static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 1455{ 1456 if (devpriv->irq_blocked > 0) { 1457 rt_printk("pcl818_ai_cancel()\n"); 1458 devpriv->irq_was_now_closed = 1; 1459 1460 switch (devpriv->ai_mode) { 1461#ifdef unused 1462 case INT_TYPE_AI1_DMA_RTC: 1463 case INT_TYPE_AI3_DMA_RTC: 1464 set_rtc_irq_bit(0); /* stop RTC */ 1465 del_timer(&devpriv->rtc_irq_timer); 1466#endif 1467 case INT_TYPE_AI1_DMA: 1468 case INT_TYPE_AI3_DMA: 1469 if (devpriv->neverending_ai || 1470 (!devpriv->neverending_ai && 1471 devpriv->ai_act_scan > 0)) { 1472 /* wait for running dma transfer to end, do cleanup in interrupt */ 1473 goto end; 1474 } 1475 disable_dma(devpriv->dma); 1476 case INT_TYPE_AI1_INT: 1477 case INT_TYPE_AI3_INT: 1478 case INT_TYPE_AI1_FIFO: 1479 case INT_TYPE_AI3_FIFO: 1480#ifdef PCL818_MODE13_AO 1481 case INT_TYPE_AO1_INT: 1482 case INT_TYPE_AO3_INT: 1483#endif 1484 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */ 1485 comedi_udelay(1); 1486 start_pacer(dev, -1, 0, 0); 1487 outb(0, dev->iobase + PCL818_AD_LO); 1488 inb(dev->iobase + PCL818_AD_LO); 1489 inb(dev->iobase + PCL818_AD_HI); 1490 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ 1491 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */ 1492 if (devpriv->usefifo) { /* FIFO shutdown */ 1493 outb(0, dev->iobase + PCL818_FI_INTCLR); 1494 outb(0, dev->iobase + PCL818_FI_FLUSH); 1495 outb(0, dev->iobase + PCL818_FI_ENABLE); 1496 } 1497 devpriv->irq_blocked = 0; 1498 devpriv->last_int_sub = s; 1499 devpriv->neverending_ai = 0; 1500 devpriv->ai_mode = 0; 1501 devpriv->irq_was_now_closed = 0; 1502 break; 1503 } 1504 } 1505 1506 end: 1507 rt_printk("pcl818_ai_cancel() end\n"); 1508 return 0; 1509} 1510 1511/* 1512============================================================================== 1513 chech for PCL818 1514*/ 1515static int pcl818_check(unsigned long iobase) 1516{ 1517 outb(0x00, iobase + PCL818_MUX); 1518 comedi_udelay(1); 1519 if (inb(iobase + PCL818_MUX) != 0x00) 1520 return 1; /* there isn't card */ 1521 outb(0x55, iobase + PCL818_MUX); 1522 comedi_udelay(1); 1523 if (inb(iobase + PCL818_MUX) != 0x55) 1524 return 1; /* there isn't card */ 1525 outb(0x00, iobase + PCL818_MUX); 1526 comedi_udelay(1); 1527 outb(0x18, iobase + PCL818_CONTROL); 1528 comedi_udelay(1); 1529 if (inb(iobase + PCL818_CONTROL) != 0x18) 1530 return 1; /* there isn't card */ 1531 return 0; /* ok, card exist */ 1532} 1533 1534/* 1535============================================================================== 1536 reset whole PCL-818 cards 1537*/ 1538static void pcl818_reset(struct comedi_device *dev) 1539{ 1540 if (devpriv->usefifo) { /* FIFO shutdown */ 1541 outb(0, dev->iobase + PCL818_FI_INTCLR); 1542 outb(0, dev->iobase + PCL818_FI_FLUSH); 1543 outb(0, dev->iobase + PCL818_FI_ENABLE); 1544 } 1545 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */ 1546 outb(0, dev->iobase + PCL818_DA_HI); 1547 comedi_udelay(1); 1548 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */ 1549 outb(0, dev->iobase + PCL818_DO_LO); 1550 comedi_udelay(1); 1551 outb(0, dev->iobase + PCL818_CONTROL); 1552 outb(0, dev->iobase + PCL818_CNTENABLE); 1553 outb(0, dev->iobase + PCL818_MUX); 1554 outb(0, dev->iobase + PCL818_CLRINT); 1555 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */ 1556 outb(0x70, dev->iobase + PCL818_CTRCTL); 1557 outb(0x30, dev->iobase + PCL818_CTRCTL); 1558 if (this_board->is_818) { 1559 outb(0, dev->iobase + PCL818_RANGE); 1560 } else { 1561 outb(0, dev->iobase + PCL718_DA2_LO); 1562 outb(0, dev->iobase + PCL718_DA2_HI); 1563 } 1564} 1565 1566#ifdef unused 1567/* 1568============================================================================== 1569 Enable(1)/disable(0) periodic interrupts from RTC 1570*/ 1571static int set_rtc_irq_bit(unsigned char bit) 1572{ 1573 unsigned char val; 1574 unsigned long flags; 1575 1576 if (bit == 1) { 1577 RTC_timer_lock++; 1578 if (RTC_timer_lock > 1) 1579 return 0; 1580 } else { 1581 RTC_timer_lock--; 1582 if (RTC_timer_lock < 0) 1583 RTC_timer_lock = 0; 1584 if (RTC_timer_lock > 0) 1585 return 0; 1586 } 1587 1588 save_flags(flags); 1589 cli(); 1590 val = CMOS_READ(RTC_CONTROL); 1591 if (bit) { 1592 val |= RTC_PIE; 1593 } else { 1594 val &= ~RTC_PIE; 1595 } 1596 CMOS_WRITE(val, RTC_CONTROL); 1597 CMOS_READ(RTC_INTR_FLAGS); 1598 restore_flags(flags); 1599 return 0; 1600} 1601 1602/* 1603============================================================================== 1604 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers) 1605*/ 1606static void rtc_dropped_irq(unsigned long data) 1607{ 1608 struct comedi_device *dev = (void *)data; 1609 unsigned long flags, tmp; 1610 1611 switch (devpriv->int818_mode) { 1612 case INT_TYPE_AI1_DMA_RTC: 1613 case INT_TYPE_AI3_DMA_RTC: 1614 mod_timer(&devpriv->rtc_irq_timer, 1615 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); 1616 save_flags(flags); 1617 cli(); 1618 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ 1619 restore_flags(flags); 1620 break; 1621 }; 1622} 1623 1624/* 1625============================================================================== 1626 Set frequency of interrupts from RTC 1627*/ 1628static int rtc_setfreq_irq(int freq) 1629{ 1630 int tmp = 0; 1631 int rtc_freq; 1632 unsigned char val; 1633 unsigned long flags; 1634 1635 if (freq < 2) 1636 freq = 2; 1637 if (freq > 8192) 1638 freq = 8192; 1639 1640 while (freq > (1 << tmp)) 1641 tmp++; 1642 1643 rtc_freq = 1 << tmp; 1644 1645 save_flags(flags); 1646 cli(); 1647 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0; 1648 val |= (16 - tmp); 1649 CMOS_WRITE(val, RTC_FREQ_SELECT); 1650 restore_flags(flags); 1651 return rtc_freq; 1652} 1653#endif 1654 1655/* 1656============================================================================== 1657 Free any resources that we have claimed 1658*/ 1659static void free_resources(struct comedi_device *dev) 1660{ 1661 /* rt_printk("free_resource()\n"); */ 1662 if (dev->private) { 1663 pcl818_ai_cancel(dev, devpriv->sub_ai); 1664 pcl818_reset(dev); 1665 if (devpriv->dma) 1666 free_dma(devpriv->dma); 1667 if (devpriv->dmabuf[0]) 1668 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); 1669 if (devpriv->dmabuf[1]) 1670 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); 1671#ifdef unused 1672 if (devpriv->rtc_irq) 1673 comedi_free_irq(devpriv->rtc_irq, dev); 1674 if ((devpriv->dma_rtc) && (RTC_lock == 1)) { 1675 if (devpriv->rtc_iobase) 1676 release_region(devpriv->rtc_iobase, 1677 devpriv->rtc_iosize); 1678 } 1679 if (devpriv->dma_rtc) 1680 RTC_lock--; 1681#endif 1682 } 1683 1684 if (dev->irq) 1685 free_irq(dev->irq, dev); 1686 if (dev->iobase) 1687 release_region(dev->iobase, devpriv->io_range); 1688 /* rt_printk("free_resource() end\n"); */ 1689} 1690 1691/* 1692============================================================================== 1693 1694 Initialization 1695 1696*/ 1697static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1698{ 1699 int ret; 1700 unsigned long iobase; 1701 unsigned int irq; 1702 int dma; 1703 unsigned long pages; 1704 struct comedi_subdevice *s; 1705 1706 ret = alloc_private(dev, sizeof(struct pcl818_private)); 1707 if (ret < 0) 1708 return ret; /* Can't alloc mem */ 1709 1710 /* claim our I/O space */ 1711 iobase = it->options[0]; 1712 printk("comedi%d: pcl818: board=%s, ioport=0x%03lx", 1713 dev->minor, this_board->name, iobase); 1714 devpriv->io_range = this_board->io_range; 1715 if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */ 1716 devpriv->io_range = PCLx1xFIFO_RANGE; 1717 devpriv->usefifo = 1; 1718 } 1719 if (!request_region(iobase, devpriv->io_range, "pcl818")) { 1720 rt_printk("I/O port conflict\n"); 1721 return -EIO; 1722 } 1723 1724 dev->iobase = iobase; 1725 1726 if (pcl818_check(iobase)) { 1727 rt_printk(", I can't detect board. FAIL!\n"); 1728 return -EIO; 1729 } 1730 1731 /* set up some name stuff */ 1732 dev->board_name = this_board->name; 1733 /* grab our IRQ */ 1734 irq = 0; 1735 if (this_board->IRQbits != 0) { /* board support IRQ */ 1736 irq = it->options[1]; 1737 if (irq) { /* we want to use IRQ */ 1738 if (((1 << irq) & this_board->IRQbits) == 0) { 1739 rt_printk 1740 (", IRQ %u is out of allowed range, DISABLING IT", 1741 irq); 1742 irq = 0; /* Bad IRQ */ 1743 } else { 1744 if (comedi_request_irq(irq, interrupt_pcl818, 0, 1745 "pcl818", dev)) { 1746 rt_printk 1747 (", unable to allocate IRQ %u, DISABLING IT", 1748 irq); 1749 irq = 0; /* Can't use IRQ */ 1750 } else { 1751 rt_printk(", irq=%u", irq); 1752 } 1753 } 1754 } 1755 } 1756 1757 dev->irq = irq; 1758 if (irq) { 1759 devpriv->irq_free = 1; 1760 } /* 1=we have allocated irq */ 1761 else { 1762 devpriv->irq_free = 0; 1763 } 1764 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ 1765 devpriv->ai_mode = 0; /* mode of irq */ 1766 1767#ifdef unused 1768 /* grab RTC for DMA operations */ 1769 devpriv->dma_rtc = 0; 1770 if (it->options[2] > 0) { /* we want to use DMA */ 1771 if (RTC_lock == 0) { 1772 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, 1773 "pcl818 (RTC)")) 1774 goto no_rtc; 1775 } 1776 devpriv->rtc_iobase = RTC_PORT(0); 1777 devpriv->rtc_iosize = RTC_IO_EXTENT; 1778 RTC_lock++; 1779 if (!comedi_request_irq(RTC_IRQ, 1780 interrupt_pcl818_ai_mode13_dma_rtc, 0, 1781 "pcl818 DMA (RTC)", dev)) { 1782 devpriv->dma_rtc = 1; 1783 devpriv->rtc_irq = RTC_IRQ; 1784 rt_printk(", dma_irq=%u", devpriv->rtc_irq); 1785 } else { 1786 RTC_lock--; 1787 if (RTC_lock == 0) { 1788 if (devpriv->rtc_iobase) 1789 release_region(devpriv->rtc_iobase, 1790 devpriv->rtc_iosize); 1791 } 1792 devpriv->rtc_iobase = 0; 1793 devpriv->rtc_iosize = 0; 1794 } 1795 } 1796 1797 no_rtc: 1798#endif 1799 /* grab our DMA */ 1800 dma = 0; 1801 devpriv->dma = dma; 1802 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) 1803 goto no_dma; /* if we haven't IRQ, we can't use DMA */ 1804 if (this_board->DMAbits != 0) { /* board support DMA */ 1805 dma = it->options[2]; 1806 if (dma < 1) 1807 goto no_dma; /* DMA disabled */ 1808 if (((1 << dma) & this_board->DMAbits) == 0) { 1809 rt_printk(", DMA is out of allowed range, FAIL!\n"); 1810 return -EINVAL; /* Bad DMA */ 1811 } 1812 ret = request_dma(dma, "pcl818"); 1813 if (ret) { 1814 rt_printk(", unable to allocate DMA %u, FAIL!\n", dma); 1815 return -EBUSY; /* DMA isn't free */ 1816 } 1817 devpriv->dma = dma; 1818 rt_printk(", dma=%u", dma); 1819 pages = 2; /* we need 16KB */ 1820 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); 1821 if (!devpriv->dmabuf[0]) { 1822 rt_printk(", unable to allocate DMA buffer, FAIL!\n"); 1823 /* maybe experiment with try_to_free_pages() will help .... */ 1824 return -EBUSY; /* no buffer :-( */ 1825 } 1826 devpriv->dmapages[0] = pages; 1827 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); 1828 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; 1829 /* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ 1830 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */ 1831 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); 1832 if (!devpriv->dmabuf[1]) { 1833 rt_printk 1834 (", unable to allocate DMA buffer, FAIL!\n"); 1835 return -EBUSY; 1836 } 1837 devpriv->dmapages[1] = pages; 1838 devpriv->hwdmaptr[1] = 1839 virt_to_bus((void *)devpriv->dmabuf[1]); 1840 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; 1841 } 1842 } 1843 1844 no_dma: 1845 1846 ret = alloc_subdevices(dev, 4); 1847 if (ret < 0) 1848 return ret; 1849 1850 s = dev->subdevices + 0; 1851 if (!this_board->n_aichan_se) { 1852 s->type = COMEDI_SUBD_UNUSED; 1853 } else { 1854 s->type = COMEDI_SUBD_AI; 1855 devpriv->sub_ai = s; 1856 s->subdev_flags = SDF_READABLE; 1857 if (check_single_ended(dev->iobase)) { 1858 s->n_chan = this_board->n_aichan_se; 1859 s->subdev_flags |= SDF_COMMON | SDF_GROUND; 1860 printk(", %dchans S.E. DAC", s->n_chan); 1861 } else { 1862 s->n_chan = this_board->n_aichan_diff; 1863 s->subdev_flags |= SDF_DIFF; 1864 printk(", %dchans DIFF DAC", s->n_chan); 1865 } 1866 s->maxdata = this_board->ai_maxdata; 1867 s->len_chanlist = s->n_chan; 1868 s->range_table = this_board->ai_range_type; 1869 s->cancel = pcl818_ai_cancel; 1870 s->insn_read = pcl818_ai_insn_read; 1871 if ((irq) || (devpriv->dma_rtc)) { 1872 dev->read_subdev = s; 1873 s->subdev_flags |= SDF_CMD_READ; 1874 s->do_cmdtest = ai_cmdtest; 1875 s->do_cmd = ai_cmd; 1876 } 1877 if (this_board->is_818) { 1878 if ((it->options[4] == 1) || (it->options[4] == 10)) 1879 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */ 1880 } else { 1881 switch (it->options[4]) { 1882 case 0: 1883 s->range_table = &range_bipolar10; 1884 break; 1885 case 1: 1886 s->range_table = &range_bipolar5; 1887 break; 1888 case 2: 1889 s->range_table = &range_bipolar2_5; 1890 break; 1891 case 3: 1892 s->range_table = &range718_bipolar1; 1893 break; 1894 case 4: 1895 s->range_table = &range718_bipolar0_5; 1896 break; 1897 case 6: 1898 s->range_table = &range_unipolar10; 1899 break; 1900 case 7: 1901 s->range_table = &range_unipolar5; 1902 break; 1903 case 8: 1904 s->range_table = &range718_unipolar2; 1905 break; 1906 case 9: 1907 s->range_table = &range718_unipolar1; 1908 break; 1909 default: 1910 s->range_table = &range_unknown; 1911 break; 1912 } 1913 } 1914 } 1915 1916 s = dev->subdevices + 1; 1917 if (!this_board->n_aochan) { 1918 s->type = COMEDI_SUBD_UNUSED; 1919 } else { 1920 s->type = COMEDI_SUBD_AO; 1921 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 1922 s->n_chan = this_board->n_aochan; 1923 s->maxdata = this_board->ao_maxdata; 1924 s->len_chanlist = this_board->n_aochan; 1925 s->range_table = this_board->ao_range_type; 1926 s->insn_read = pcl818_ao_insn_read; 1927 s->insn_write = pcl818_ao_insn_write; 1928#ifdef unused 1929#ifdef PCL818_MODE13_AO 1930 if (irq) { 1931 s->trig[1] = pcl818_ao_mode1; 1932 s->trig[3] = pcl818_ao_mode3; 1933 } 1934#endif 1935#endif 1936 if (this_board->is_818) { 1937 if ((it->options[4] == 1) || (it->options[4] == 10)) 1938 s->range_table = &range_unipolar10; 1939 if (it->options[4] == 2) 1940 s->range_table = &range_unknown; 1941 } else { 1942 if ((it->options[5] == 1) || (it->options[5] == 10)) 1943 s->range_table = &range_unipolar10; 1944 if (it->options[5] == 2) 1945 s->range_table = &range_unknown; 1946 } 1947 } 1948 1949 s = dev->subdevices + 2; 1950 if (!this_board->n_dichan) { 1951 s->type = COMEDI_SUBD_UNUSED; 1952 } else { 1953 s->type = COMEDI_SUBD_DI; 1954 s->subdev_flags = SDF_READABLE; 1955 s->n_chan = this_board->n_dichan; 1956 s->maxdata = 1; 1957 s->len_chanlist = this_board->n_dichan; 1958 s->range_table = &range_digital; 1959 s->insn_bits = pcl818_di_insn_bits; 1960 } 1961 1962 s = dev->subdevices + 3; 1963 if (!this_board->n_dochan) { 1964 s->type = COMEDI_SUBD_UNUSED; 1965 } else { 1966 s->type = COMEDI_SUBD_DO; 1967 s->subdev_flags = SDF_WRITABLE; 1968 s->n_chan = this_board->n_dochan; 1969 s->maxdata = 1; 1970 s->len_chanlist = this_board->n_dochan; 1971 s->range_table = &range_digital; 1972 s->insn_bits = pcl818_do_insn_bits; 1973 } 1974 1975 /* select 1/10MHz oscilator */ 1976 if ((it->options[3] == 0) || (it->options[3] == 10)) { 1977 devpriv->i8253_osc_base = 100; 1978 } else { 1979 devpriv->i8253_osc_base = 1000; 1980 } 1981 1982 /* max sampling speed */ 1983 devpriv->ns_min = this_board->ns_min; 1984 1985 if (!this_board->is_818) { 1986 if ((it->options[6] == 1) || (it->options[6] == 100)) 1987 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ 1988 } 1989 1990 pcl818_reset(dev); 1991 1992 rt_printk("\n"); 1993 1994 return 0; 1995} 1996 1997/* 1998============================================================================== 1999 Removes device 2000 */ 2001static int pcl818_detach(struct comedi_device *dev) 2002{ 2003 /* rt_printk("comedi%d: pcl818: remove\n", dev->minor); */ 2004 free_resources(dev); 2005 return 0; 2006} 2007