pcl812.c revision 25985edcedea6396277003854657b5f3cb31a628
1/* 2 * comedi/drivers/pcl812.c 3 * 4 * Author: Michal Dobes <dobes@tesnet.cz> 5 * 6 * hardware driver for Advantech cards 7 * card: PCL-812, PCL-812PG, PCL-813, PCL-813B 8 * driver: pcl812, pcl812pg, pcl813, pcl813b 9 * and for ADlink cards 10 * card: ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216 11 * driver: acl8112dg, acl8112hg, acl8112pg, acl8113, acl8216 12 * and for ICP DAS cards 13 * card: ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL, 14 * driver: iso813, a821pgh, a-821pgl, a-821pglnda, a822pgh, a822pgl, 15 * card: A-823PGH, A-823PGL, A-826PG 16 * driver: a823pgh, a823pgl, a826pg 17 */ 18 19/* 20 * Driver: pcl812 21 * Description: Advantech PCL-812/PG, PCL-813/B, 22 * ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, 23 * ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG, 24 * ICP DAS ISO-813 25 * Author: Michal Dobes <dobes@tesnet.cz> 26 * Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg), 27 * PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg), 28 * ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216), 29 * [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl), 30 * A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl), 31 * A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg) 32 * Updated: Mon, 06 Aug 2007 12:03:15 +0100 33 * Status: works (I hope. My board fire up under my hands 34 * and I cann't test all features.) 35 * 36 * This driver supports insn and cmd interfaces. Some boards support only insn 37 * because their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). 38 * Data transfer over DMA is supported only when you measure only one 39 * channel, this is too hardware limitation of these boards. 40 * 41 * Options for PCL-812: 42 * [0] - IO Base 43 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 44 * [2] - DMA (0=disable, 1, 3) 45 * [3] - 0=trigger source is internal 8253 with 2MHz clock 46 * 1=trigger source is external 47 * [4] - 0=A/D input range is +/-10V 48 * 1=A/D input range is +/-5V 49 * 2=A/D input range is +/-2.5V 50 * 3=A/D input range is +/-1.25V 51 * 4=A/D input range is +/-0.625V 52 * 5=A/D input range is +/-0.3125V 53 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 54 * 1=D/A outputs 0-10V (internal reference -10V) 55 * 2=D/A outputs unknown (external reference) 56 * 57 * Options for PCL-812PG, ACL-8112PG: 58 * [0] - IO Base 59 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 60 * [2] - DMA (0=disable, 1, 3) 61 * [3] - 0=trigger source is internal 8253 with 2MHz clock 62 * 1=trigger source is external 63 * [4] - 0=A/D have max +/-5V input 64 * 1=A/D have max +/-10V input 65 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 66 * 1=D/A outputs 0-10V (internal reference -10V) 67 * 2=D/A outputs unknown (external reference) 68 * 69 * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: 70 * [0] - IO Base 71 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 72 * [2] - DMA (0=disable, 1, 3) 73 * [3] - 0=trigger source is internal 8253 with 2MHz clock 74 * 1=trigger source is external 75 * [4] - 0=A/D channels are S.E. 76 * 1=A/D channels are DIFF 77 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 78 * 1=D/A outputs 0-10V (internal reference -10V) 79 * 2=D/A outputs unknown (external reference) 80 * 81 * Options for A-821PGL/PGH: 82 * [0] - IO Base 83 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 84 * [2] - 0=A/D channels are S.E. 85 * 1=A/D channels are DIFF 86 * [3] - 0=D/A output 0-5V (internal reference -5V) 87 * 1=D/A output 0-10V (internal reference -10V) 88 * 89 * Options for A-821PGL-NDA: 90 * [0] - IO Base 91 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 92 * [2] - 0=A/D channels are S.E. 93 * 1=A/D channels are DIFF 94 * 95 * Options for PCL-813: 96 * [0] - IO Base 97 * 98 * Options for PCL-813B: 99 * [0] - IO Base 100 * [1] - 0= bipolar inputs 101 * 1= unipolar inputs 102 * 103 * Options for ACL-8113, ISO-813: 104 * [0] - IO Base 105 * [1] - 0= 10V bipolar inputs 106 * 1= 10V unipolar inputs 107 * 2= 20V bipolar inputs 108 * 3= 20V unipolar inputs 109 */ 110 111#include <linux/interrupt.h> 112#include <linux/gfp.h> 113#include "../comedidev.h" 114 115#include <linux/delay.h> 116#include <linux/ioport.h> 117#include <asm/dma.h> 118 119#include "8253.h" 120 121/* if this is defined then a lot of messages is printed */ 122#undef PCL812_EXTDEBUG 123 124/* hardware types of the cards */ 125#define boardPCL812PG 0 /* and ACL-8112PG */ 126#define boardPCL813B 1 127#define boardPCL812 2 128#define boardPCL813 3 129#define boardISO813 5 130#define boardACL8113 6 131#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ 132#define boardACL8216 8 /* and ICP DAS A-826PG */ 133#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ 134 135#define PCLx1x_IORANGE 16 136 137#define PCL812_CTR0 0 138#define PCL812_CTR1 1 139#define PCL812_CTR2 2 140#define PCL812_CTRCTL 3 141#define PCL812_AD_LO 4 142#define PCL812_DA1_LO 4 143#define PCL812_AD_HI 5 144#define PCL812_DA1_HI 5 145#define PCL812_DA2_LO 6 146#define PCL812_DI_LO 6 147#define PCL812_DA2_HI 7 148#define PCL812_DI_HI 7 149#define PCL812_CLRINT 8 150#define PCL812_GAIN 9 151#define PCL812_MUX 10 152#define PCL812_MODE 11 153#define PCL812_CNTENABLE 10 154#define PCL812_SOFTTRIG 12 155#define PCL812_DO_LO 13 156#define PCL812_DO_HI 14 157 158#define PCL812_DRDY 0x10 /* =0 data ready */ 159 160#define ACL8216_STATUS 8 /* 5. bit signalize data ready */ 161 162#define ACL8216_DRDY 0x20 /* =0 data ready */ 163 164#define MAX_CHANLIST_LEN 256 /* length of scan list */ 165 166static const struct comedi_lrange range_pcl812pg_ai = { 5, { 167 BIP_RANGE(5), 168 BIP_RANGE(2.5), 169 BIP_RANGE(1.25), 170 BIP_RANGE(0.625), 171 BIP_RANGE(0.3125), 172 } 173}; 174 175static const struct comedi_lrange range_pcl812pg2_ai = { 5, { 176 BIP_RANGE(10), 177 BIP_RANGE(5), 178 BIP_RANGE(2.5), 179 BIP_RANGE(1.25), 180 BIP_RANGE(0.625), 181 } 182}; 183 184static const struct comedi_lrange range812_bipolar1_25 = { 1, { 185 BIP_RANGE(1.25), 186 } 187}; 188 189static const struct comedi_lrange range812_bipolar0_625 = { 1, { 190 BIP_RANGE 191 (0.625), 192 } 193}; 194 195static const struct comedi_lrange range812_bipolar0_3125 = { 1, { 196 BIP_RANGE 197 (0.3125), 198 } 199}; 200 201static const struct comedi_lrange range_pcl813b_ai = { 4, { 202 BIP_RANGE(5), 203 BIP_RANGE(2.5), 204 BIP_RANGE(1.25), 205 BIP_RANGE(0.625), 206 } 207}; 208 209static const struct comedi_lrange range_pcl813b2_ai = { 4, { 210 UNI_RANGE(10), 211 UNI_RANGE(5), 212 UNI_RANGE(2.5), 213 UNI_RANGE(1.25), 214 } 215}; 216 217static const struct comedi_lrange range_iso813_1_ai = { 5, { 218 BIP_RANGE(5), 219 BIP_RANGE(2.5), 220 BIP_RANGE(1.25), 221 BIP_RANGE(0.625), 222 BIP_RANGE(0.3125), 223 } 224}; 225 226static const struct comedi_lrange range_iso813_1_2_ai = { 5, { 227 UNI_RANGE(10), 228 UNI_RANGE(5), 229 UNI_RANGE(2.5), 230 UNI_RANGE(1.25), 231 UNI_RANGE(0.625), 232 } 233}; 234 235static const struct comedi_lrange range_iso813_2_ai = { 4, { 236 BIP_RANGE(5), 237 BIP_RANGE(2.5), 238 BIP_RANGE(1.25), 239 BIP_RANGE(0.625), 240 } 241}; 242 243static const struct comedi_lrange range_iso813_2_2_ai = { 4, { 244 UNI_RANGE(10), 245 UNI_RANGE(5), 246 UNI_RANGE(2.5), 247 UNI_RANGE(1.25), 248 } 249}; 250 251static const struct comedi_lrange range_acl8113_1_ai = { 4, { 252 BIP_RANGE(5), 253 BIP_RANGE(2.5), 254 BIP_RANGE(1.25), 255 BIP_RANGE(0.625), 256 } 257}; 258 259static const struct comedi_lrange range_acl8113_1_2_ai = { 4, { 260 UNI_RANGE(10), 261 UNI_RANGE(5), 262 UNI_RANGE(2.5), 263 UNI_RANGE(1.25), 264 } 265}; 266 267static const struct comedi_lrange range_acl8113_2_ai = { 3, { 268 BIP_RANGE(5), 269 BIP_RANGE(2.5), 270 BIP_RANGE(1.25), 271 } 272}; 273 274static const struct comedi_lrange range_acl8113_2_2_ai = { 3, { 275 UNI_RANGE(10), 276 UNI_RANGE(5), 277 UNI_RANGE(2.5), 278 } 279}; 280 281static const struct comedi_lrange range_acl8112dg_ai = { 9, { 282 BIP_RANGE(5), 283 BIP_RANGE(2.5), 284 BIP_RANGE(1.25), 285 BIP_RANGE(0.625), 286 UNI_RANGE(10), 287 UNI_RANGE(5), 288 UNI_RANGE(2.5), 289 UNI_RANGE(1.25), 290 BIP_RANGE(10), 291 } 292}; 293 294static const struct comedi_lrange range_acl8112hg_ai = { 12, { 295 BIP_RANGE(5), 296 BIP_RANGE(0.5), 297 BIP_RANGE(0.05), 298 BIP_RANGE(0.005), 299 UNI_RANGE(10), 300 UNI_RANGE(1), 301 UNI_RANGE(0.1), 302 UNI_RANGE(0.01), 303 BIP_RANGE(10), 304 BIP_RANGE(1), 305 BIP_RANGE(0.1), 306 BIP_RANGE(0.01), 307 } 308}; 309 310static const struct comedi_lrange range_a821pgh_ai = { 4, { 311 BIP_RANGE(5), 312 BIP_RANGE(0.5), 313 BIP_RANGE(0.05), 314 BIP_RANGE(0.005), 315 } 316}; 317 318static int pcl812_attach(struct comedi_device *dev, 319 struct comedi_devconfig *it); 320static int pcl812_detach(struct comedi_device *dev); 321 322struct pcl812_board { 323 324 const char *name; /* board name */ 325 int board_type; /* type of this board */ 326 int n_aichan; /* num of AI chans in S.E. */ 327 int n_aichan_diff; /* DIFF num of chans */ 328 int n_aochan; /* num of DA chans */ 329 int n_dichan; /* DI and DO chans */ 330 int n_dochan; 331 int ai_maxdata; /* AI resolution */ 332 unsigned int ai_ns_min; /* max sample speed of card v ns */ 333 unsigned int i8254_osc_base; /* clock base */ 334 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ 335 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ 336 unsigned int IRQbits; /* allowed IRQ */ 337 unsigned char DMAbits; /* allowed DMA chans */ 338 unsigned char io_range; /* iorange for this board */ 339 unsigned char haveMPC508; /* 1=board use MPC508A multiplexor */ 340}; 341 342static const struct pcl812_board boardtypes[] = { 343 {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff, 344 33000, 500, &range_bipolar10, &range_unipolar5, 345 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 346 {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, 347 33000, 500, &range_pcl812pg_ai, &range_unipolar5, 348 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 349 {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, 350 10000, 500, &range_pcl812pg_ai, &range_unipolar5, 351 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 352 {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 353 10000, 500, &range_acl8112dg_ai, &range_unipolar5, 354 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, 355 {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 356 10000, 500, &range_acl8112hg_ai, &range_unipolar5, 357 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, 358 {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff, 359 10000, 500, &range_pcl813b_ai, &range_unipolar5, 360 0x000c, 0x00, PCLx1x_IORANGE, 0}, 361 {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff, 362 10000, 500, &range_pcl813b_ai, NULL, 363 0x000c, 0x00, PCLx1x_IORANGE, 0}, 364 {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff, 365 10000, 500, &range_a821pgh_ai, &range_unipolar5, 366 0x000c, 0x00, PCLx1x_IORANGE, 0}, 367 {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 368 10000, 500, &range_acl8112dg_ai, &range_unipolar5, 369 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 370 {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 371 10000, 500, &range_acl8112hg_ai, &range_unipolar5, 372 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 373 {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 374 8000, 500, &range_acl8112dg_ai, &range_unipolar5, 375 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 376 {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, 377 8000, 500, &range_acl8112hg_ai, &range_unipolar5, 378 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 379 {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff, 380 0, 0, &range_pcl813b_ai, NULL, 381 0x0000, 0x00, PCLx1x_IORANGE, 0}, 382 {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff, 383 0, 0, &range_pcl813b_ai, NULL, 384 0x0000, 0x00, PCLx1x_IORANGE, 0}, 385 {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff, 386 0, 0, &range_acl8113_1_ai, NULL, 387 0x0000, 0x00, PCLx1x_IORANGE, 0}, 388 {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff, 389 0, 0, &range_iso813_1_ai, NULL, 390 0x0000, 0x00, PCLx1x_IORANGE, 0}, 391 {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff, 392 10000, 500, &range_pcl813b2_ai, &range_unipolar5, 393 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, 394 {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff, 395 10000, 500, &range_pcl813b2_ai, &range_unipolar5, 396 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, 397}; 398 399#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl812_board)) 400#define this_board ((const struct pcl812_board *)dev->board_ptr) 401 402static struct comedi_driver driver_pcl812 = { 403 .driver_name = "pcl812", 404 .module = THIS_MODULE, 405 .attach = pcl812_attach, 406 .detach = pcl812_detach, 407 .board_name = &boardtypes[0].name, 408 .num_names = n_boardtypes, 409 .offset = sizeof(struct pcl812_board), 410}; 411 412static int __init driver_pcl812_init_module(void) 413{ 414 return comedi_driver_register(&driver_pcl812); 415} 416 417static void __exit driver_pcl812_cleanup_module(void) 418{ 419 comedi_driver_unregister(&driver_pcl812); 420} 421 422module_init(driver_pcl812_init_module); 423module_exit(driver_pcl812_cleanup_module); 424 425struct pcl812_private { 426 427 unsigned char valid; /* =1 device is OK */ 428 unsigned char dma; /* >0 use dma ( usedDMA channel) */ 429 unsigned char use_diff; /* =1 diff inputs */ 430 unsigned char use_MPC; /* 1=board uses MPC508A multiplexor */ 431 unsigned char use_ext_trg; /* 1=board uses external trigger */ 432 unsigned char range_correction; /* =1 we must add 1 to range number */ 433 unsigned char old_chan_reg; /* lastly used chan/gain pair */ 434 unsigned char old_gain_reg; 435 unsigned char mode_reg_int; /* there is stored INT number for some card */ 436 unsigned char ai_neverending; /* =1 we do unlimited AI */ 437 unsigned char ai_eos; /* 1=EOS wake up */ 438 unsigned char ai_dma; /* =1 we use DMA */ 439 unsigned int ai_poll_ptr; /* how many sampes transfer poll */ 440 unsigned int ai_scans; /* len of scanlist */ 441 unsigned int ai_act_scan; /* how many scans we finished */ 442 unsigned int ai_chanlist[MAX_CHANLIST_LEN]; /* our copy of channel/range list */ 443 unsigned int ai_n_chan; /* how many channels is measured */ 444 unsigned int ai_flags; /* flaglist */ 445 unsigned int ai_data_len; /* len of data buffer */ 446 short *ai_data; /* data buffer */ 447 unsigned int ai_is16b; /* =1 we have 16 bit card */ 448 unsigned long dmabuf[2]; /* PTR to DMA buf */ 449 unsigned int dmapages[2]; /* how many pages we have allocated */ 450 unsigned int hwdmaptr[2]; /* HW PTR to DMA buf */ 451 unsigned int hwdmasize[2]; /* DMA buf size in bytes */ 452 unsigned int dmabytestomove[2]; /* how many bytes DMA transfer */ 453 int next_dma_buf; /* which buffer is next to use */ 454 unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ 455 unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ 456 unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ 457 unsigned int ao_readback[2]; /* data for AO readback */ 458}; 459 460#define devpriv ((struct pcl812_private *)dev->private) 461 462/* 463============================================================================== 464*/ 465static void start_pacer(struct comedi_device *dev, int mode, 466 unsigned int divisor1, unsigned int divisor2); 467static void setup_range_channel(struct comedi_device *dev, 468 struct comedi_subdevice *s, 469 unsigned int rangechan, char wait); 470static int pcl812_ai_cancel(struct comedi_device *dev, 471 struct comedi_subdevice *s); 472/* 473============================================================================== 474*/ 475static int pcl812_ai_insn_read(struct comedi_device *dev, 476 struct comedi_subdevice *s, 477 struct comedi_insn *insn, unsigned int *data) 478{ 479 int n; 480 int timeout, hi; 481 482 /* select software trigger */ 483 outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE); 484 /* select channel and renge */ 485 setup_range_channel(dev, s, insn->chanspec, 1); 486 for (n = 0; n < insn->n; n++) { 487 /* start conversion */ 488 outb(255, dev->iobase + PCL812_SOFTTRIG); 489 udelay(5); 490 timeout = 50; /* wait max 50us, it must finish under 33us */ 491 while (timeout--) { 492 hi = inb(dev->iobase + PCL812_AD_HI); 493 if (!(hi & PCL812_DRDY)) 494 goto conv_finish; 495 udelay(1); 496 } 497 printk 498 ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", 499 dev->minor, dev->board_name, dev->iobase); 500 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); 501 return -ETIME; 502 503conv_finish: 504 data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO); 505 } 506 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); 507 return n; 508} 509 510/* 511============================================================================== 512*/ 513static int acl8216_ai_insn_read(struct comedi_device *dev, 514 struct comedi_subdevice *s, 515 struct comedi_insn *insn, unsigned int *data) 516{ 517 int n; 518 int timeout; 519 520 /* select software trigger */ 521 outb(1, dev->iobase + PCL812_MODE); 522 /* select channel and renge */ 523 setup_range_channel(dev, s, insn->chanspec, 1); 524 for (n = 0; n < insn->n; n++) { 525 /* start conversion */ 526 outb(255, dev->iobase + PCL812_SOFTTRIG); 527 udelay(5); 528 timeout = 50; /* wait max 50us, it must finish under 33us */ 529 while (timeout--) { 530 if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) 531 goto conv_finish; 532 udelay(1); 533 } 534 printk 535 ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", 536 dev->minor, dev->board_name, dev->iobase); 537 outb(0, dev->iobase + PCL812_MODE); 538 return -ETIME; 539 540conv_finish: 541 data[n] = 542 (inb(dev->iobase + 543 PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO); 544 } 545 outb(0, dev->iobase + PCL812_MODE); 546 return n; 547} 548 549/* 550============================================================================== 551*/ 552static int pcl812_ao_insn_write(struct comedi_device *dev, 553 struct comedi_subdevice *s, 554 struct comedi_insn *insn, unsigned int *data) 555{ 556 int chan = CR_CHAN(insn->chanspec); 557 int i; 558 559 for (i = 0; i < insn->n; i++) { 560 outb((data[i] & 0xff), 561 dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO)); 562 outb((data[i] >> 8) & 0x0f, 563 dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI)); 564 devpriv->ao_readback[chan] = data[i]; 565 } 566 567 return i; 568} 569 570/* 571============================================================================== 572*/ 573static int pcl812_ao_insn_read(struct comedi_device *dev, 574 struct comedi_subdevice *s, 575 struct comedi_insn *insn, unsigned int *data) 576{ 577 int chan = CR_CHAN(insn->chanspec); 578 int i; 579 580 for (i = 0; i < insn->n; i++) 581 data[i] = devpriv->ao_readback[chan]; 582 583 return i; 584} 585 586/* 587============================================================================== 588*/ 589static int pcl812_di_insn_bits(struct comedi_device *dev, 590 struct comedi_subdevice *s, 591 struct comedi_insn *insn, unsigned int *data) 592{ 593 if (insn->n != 2) 594 return -EINVAL; 595 596 data[1] = inb(dev->iobase + PCL812_DI_LO); 597 data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8; 598 599 return 2; 600} 601 602/* 603============================================================================== 604*/ 605static int pcl812_do_insn_bits(struct comedi_device *dev, 606 struct comedi_subdevice *s, 607 struct comedi_insn *insn, unsigned int *data) 608{ 609 if (insn->n != 2) 610 return -EINVAL; 611 612 if (data[0]) { 613 s->state &= ~data[0]; 614 s->state |= data[0] & data[1]; 615 outb(s->state & 0xff, dev->iobase + PCL812_DO_LO); 616 outb((s->state >> 8), dev->iobase + PCL812_DO_HI); 617 } 618 data[1] = s->state; 619 620 return 2; 621} 622 623#ifdef PCL812_EXTDEBUG 624/* 625============================================================================== 626*/ 627static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd) 628{ 629 printk(KERN_INFO "pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, 630 cmd->start_src, cmd->scan_begin_src, cmd->convert_src); 631 printk(KERN_INFO "pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e, 632 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); 633 printk(KERN_INFO "pcl812 e=%d stopsrc=%x scanend=%x\n", e, 634 cmd->stop_src, cmd->scan_end_src); 635 printk(KERN_INFO "pcl812 e=%d stoparg=%d scanendarg=%d " 636 "chanlistlen=%d\n", e, cmd->stop_arg, cmd->scan_end_arg, 637 cmd->chanlist_len); 638} 639#endif 640 641/* 642============================================================================== 643*/ 644static int pcl812_ai_cmdtest(struct comedi_device *dev, 645 struct comedi_subdevice *s, struct comedi_cmd *cmd) 646{ 647 int err = 0; 648 int tmp, divisor1, divisor2; 649 650#ifdef PCL812_EXTDEBUG 651 printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n"); 652 pcl812_cmdtest_out(-1, cmd); 653#endif 654 /* step 1: make sure trigger sources are trivially valid */ 655 656 tmp = cmd->start_src; 657 cmd->start_src &= TRIG_NOW; 658 if (!cmd->start_src || tmp != cmd->start_src) 659 err++; 660 661 tmp = cmd->scan_begin_src; 662 cmd->scan_begin_src &= TRIG_FOLLOW; 663 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 664 err++; 665 666 tmp = cmd->convert_src; 667 if (devpriv->use_ext_trg) 668 cmd->convert_src &= TRIG_EXT; 669 else 670 cmd->convert_src &= TRIG_TIMER; 671 672 if (!cmd->convert_src || tmp != cmd->convert_src) 673 err++; 674 675 tmp = cmd->scan_end_src; 676 cmd->scan_end_src &= TRIG_COUNT; 677 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 678 err++; 679 680 tmp = cmd->stop_src; 681 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 682 if (!cmd->stop_src || tmp != cmd->stop_src) 683 err++; 684 685 if (err) { 686#ifdef PCL812_EXTDEBUG 687 pcl812_cmdtest_out(1, cmd); 688 printk 689 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n", 690 err); 691#endif 692 return 1; 693 } 694 695 /* 696 * step 2: make sure trigger sources are 697 * unique and mutually compatible 698 */ 699 700 if (cmd->start_src != TRIG_NOW) { 701 cmd->start_src = TRIG_NOW; 702 err++; 703 } 704 705 if (cmd->scan_begin_src != TRIG_FOLLOW) { 706 cmd->scan_begin_src = TRIG_FOLLOW; 707 err++; 708 } 709 710 if (devpriv->use_ext_trg) { 711 if (cmd->convert_src != TRIG_EXT) { 712 cmd->convert_src = TRIG_EXT; 713 err++; 714 } 715 } else { 716 if (cmd->convert_src != TRIG_TIMER) { 717 cmd->convert_src = TRIG_TIMER; 718 err++; 719 } 720 } 721 722 if (cmd->scan_end_src != TRIG_COUNT) { 723 cmd->scan_end_src = TRIG_COUNT; 724 err++; 725 } 726 727 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) 728 err++; 729 730 if (err) { 731#ifdef PCL812_EXTDEBUG 732 pcl812_cmdtest_out(2, cmd); 733 printk 734 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n", 735 err); 736#endif 737 return 2; 738 } 739 740 /* step 3: make sure arguments are trivially compatible */ 741 742 if (cmd->start_arg != 0) { 743 cmd->start_arg = 0; 744 err++; 745 } 746 747 if (cmd->scan_begin_arg != 0) { 748 cmd->scan_begin_arg = 0; 749 err++; 750 } 751 752 if (cmd->convert_src == TRIG_TIMER) { 753 if (cmd->convert_arg < this_board->ai_ns_min) { 754 cmd->convert_arg = this_board->ai_ns_min; 755 err++; 756 } 757 } else { /* TRIG_EXT */ 758 if (cmd->convert_arg != 0) { 759 cmd->convert_arg = 0; 760 err++; 761 } 762 } 763 764 if (!cmd->chanlist_len) { 765 cmd->chanlist_len = 1; 766 err++; 767 } 768 if (cmd->chanlist_len > MAX_CHANLIST_LEN) { 769 cmd->chanlist_len = this_board->n_aichan; 770 err++; 771 } 772 if (cmd->scan_end_arg != cmd->chanlist_len) { 773 cmd->scan_end_arg = cmd->chanlist_len; 774 err++; 775 } 776 if (cmd->stop_src == TRIG_COUNT) { 777 if (!cmd->stop_arg) { 778 cmd->stop_arg = 1; 779 err++; 780 } 781 } else { /* TRIG_NONE */ 782 if (cmd->stop_arg != 0) { 783 cmd->stop_arg = 0; 784 err++; 785 } 786 } 787 788 if (err) { 789#ifdef PCL812_EXTDEBUG 790 pcl812_cmdtest_out(3, cmd); 791 printk 792 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n", 793 err); 794#endif 795 return 3; 796 } 797 798 /* step 4: fix up any arguments */ 799 800 if (cmd->convert_src == TRIG_TIMER) { 801 tmp = cmd->convert_arg; 802 i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, 803 &divisor2, &cmd->convert_arg, 804 cmd->flags & TRIG_ROUND_MASK); 805 if (cmd->convert_arg < this_board->ai_ns_min) 806 cmd->convert_arg = this_board->ai_ns_min; 807 if (tmp != cmd->convert_arg) 808 err++; 809 } 810 811 if (err) { 812#ifdef PCL812_EXTDEBUG 813 printk 814 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n", 815 err); 816#endif 817 return 4; 818 } 819 820 return 0; 821} 822 823/* 824============================================================================== 825*/ 826static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 827{ 828 unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes; 829 struct comedi_cmd *cmd = &s->async->cmd; 830 831#ifdef PCL812_EXTDEBUG 832 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n"); 833#endif 834 835 if (cmd->start_src != TRIG_NOW) 836 return -EINVAL; 837 if (cmd->scan_begin_src != TRIG_FOLLOW) 838 return -EINVAL; 839 if (devpriv->use_ext_trg) { 840 if (cmd->convert_src != TRIG_EXT) 841 return -EINVAL; 842 } else { 843 if (cmd->convert_src != TRIG_TIMER) 844 return -EINVAL; 845 } 846 if (cmd->scan_end_src != TRIG_COUNT) 847 return -EINVAL; 848 if (cmd->scan_end_arg != cmd->chanlist_len) 849 return -EINVAL; 850 if (cmd->chanlist_len > MAX_CHANLIST_LEN) 851 return -EINVAL; 852 853 if (cmd->convert_src == TRIG_TIMER) { 854 if (cmd->convert_arg < this_board->ai_ns_min) 855 cmd->convert_arg = this_board->ai_ns_min; 856 i8253_cascade_ns_to_timer(this_board->i8254_osc_base, 857 &divisor1, &divisor2, 858 &cmd->convert_arg, 859 cmd->flags & TRIG_ROUND_MASK); 860 } 861 862 start_pacer(dev, -1, 0, 0); /* stop pacer */ 863 864 devpriv->ai_n_chan = cmd->chanlist_len; 865 memcpy(devpriv->ai_chanlist, cmd->chanlist, 866 sizeof(unsigned int) * cmd->scan_end_arg); 867 /* select first channel and range */ 868 setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1); 869 870 if (devpriv->dma) { /* check if we can use DMA transfer */ 871 devpriv->ai_dma = 1; 872 for (i = 1; i < devpriv->ai_n_chan; i++) 873 if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) { 874 /* we cann't use DMA :-( */ 875 devpriv->ai_dma = 0; 876 break; 877 } 878 } else 879 devpriv->ai_dma = 0; 880 881 devpriv->ai_flags = cmd->flags; 882 devpriv->ai_data_len = s->async->prealloc_bufsz; 883 devpriv->ai_data = s->async->prealloc_buf; 884 if (cmd->stop_src == TRIG_COUNT) { 885 devpriv->ai_scans = cmd->stop_arg; 886 devpriv->ai_neverending = 0; 887 } else { 888 devpriv->ai_scans = 0; 889 devpriv->ai_neverending = 1; 890 } 891 892 devpriv->ai_act_scan = 0; 893 devpriv->ai_poll_ptr = 0; 894 s->async->cur_chan = 0; 895 896 /* don't we want wake up every scan? */ 897 if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { 898 devpriv->ai_eos = 1; 899 900 /* DMA is useless for this situation */ 901 if (devpriv->ai_n_chan == 1) 902 devpriv->ai_dma = 0; 903 } 904 905 if (devpriv->ai_dma) { 906 /* we use EOS, so adapt DMA buffer to one scan */ 907 if (devpriv->ai_eos) { 908 devpriv->dmabytestomove[0] = 909 devpriv->ai_n_chan * sizeof(short); 910 devpriv->dmabytestomove[1] = 911 devpriv->ai_n_chan * sizeof(short); 912 devpriv->dma_runs_to_end = 1; 913 } else { 914 devpriv->dmabytestomove[0] = devpriv->hwdmasize[0]; 915 devpriv->dmabytestomove[1] = devpriv->hwdmasize[1]; 916 if (devpriv->ai_data_len < devpriv->hwdmasize[0]) 917 devpriv->dmabytestomove[0] = 918 devpriv->ai_data_len; 919 if (devpriv->ai_data_len < devpriv->hwdmasize[1]) 920 devpriv->dmabytestomove[1] = 921 devpriv->ai_data_len; 922 if (devpriv->ai_neverending) { 923 devpriv->dma_runs_to_end = 1; 924 } else { 925 /* how many samples we must transfer? */ 926 bytes = devpriv->ai_n_chan * 927 devpriv->ai_scans * sizeof(short); 928 929 /* how many DMA pages we must fill */ 930 devpriv->dma_runs_to_end = 931 bytes / devpriv->dmabytestomove[0]; 932 933 /* on last dma transfer must be moved */ 934 devpriv->last_dma_run = 935 bytes % devpriv->dmabytestomove[0]; 936 if (devpriv->dma_runs_to_end == 0) 937 devpriv->dmabytestomove[0] = 938 devpriv->last_dma_run; 939 devpriv->dma_runs_to_end--; 940 } 941 } 942 if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) { 943 devpriv->dmabytestomove[0] = devpriv->hwdmasize[0]; 944 devpriv->ai_eos = 0; 945 } 946 if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) { 947 devpriv->dmabytestomove[1] = devpriv->hwdmasize[1]; 948 devpriv->ai_eos = 0; 949 } 950 devpriv->next_dma_buf = 0; 951 set_dma_mode(devpriv->dma, DMA_MODE_READ); 952 dma_flags = claim_dma_lock(); 953 clear_dma_ff(devpriv->dma); 954 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 955 set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); 956 release_dma_lock(dma_flags); 957 enable_dma(devpriv->dma); 958#ifdef PCL812_EXTDEBUG 959 printk 960 ("pcl812 EDBG: DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n", 961 devpriv->dma, devpriv->hwdmaptr[0], 962 devpriv->hwdmaptr[1], devpriv->dmabytestomove[0], 963 devpriv->dmabytestomove[1], devpriv->ai_eos); 964#endif 965 } 966 967 switch (cmd->convert_src) { 968 case TRIG_TIMER: 969 start_pacer(dev, 1, divisor1, divisor2); 970 break; 971 } 972 973 if (devpriv->ai_dma) /* let's go! */ 974 outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE); 975 else /* let's go! */ 976 outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE); 977 978#ifdef PCL812_EXTDEBUG 979 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cmd(...)\n"); 980#endif 981 982 return 0; 983} 984 985/* 986============================================================================== 987*/ 988static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) 989{ 990 char err = 1; 991 unsigned int mask, timeout; 992 struct comedi_device *dev = d; 993 struct comedi_subdevice *s = dev->subdevices + 0; 994 unsigned int next_chan; 995 996 s->async->events = 0; 997 998 timeout = 50; /* wait max 50us, it must finish under 33us */ 999 if (devpriv->ai_is16b) { 1000 mask = 0xffff; 1001 while (timeout--) { 1002 if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) { 1003 err = 0; 1004 break; 1005 } 1006 udelay(1); 1007 } 1008 } else { 1009 mask = 0x0fff; 1010 while (timeout--) { 1011 if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) { 1012 err = 0; 1013 break; 1014 } 1015 udelay(1); 1016 } 1017 } 1018 1019 if (err) { 1020 printk 1021 ("comedi%d: pcl812: (%s at 0x%lx) " 1022 "A/D cmd IRQ without DRDY!\n", 1023 dev->minor, dev->board_name, dev->iobase); 1024 pcl812_ai_cancel(dev, s); 1025 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 1026 comedi_event(dev, s); 1027 return IRQ_HANDLED; 1028 } 1029 1030 comedi_buf_put(s->async, 1031 ((inb(dev->iobase + PCL812_AD_HI) << 8) | 1032 inb(dev->iobase + PCL812_AD_LO)) & mask); 1033 1034 /* Set up next channel. Added by abbotti 2010-01-20, but untested. */ 1035 next_chan = s->async->cur_chan + 1; 1036 if (next_chan >= devpriv->ai_n_chan) 1037 next_chan = 0; 1038 if (devpriv->ai_chanlist[s->async->cur_chan] != 1039 devpriv->ai_chanlist[next_chan]) 1040 setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0); 1041 1042 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ 1043 1044 s->async->cur_chan = next_chan; 1045 if (next_chan == 0) { /* one scan done */ 1046 devpriv->ai_act_scan++; 1047 if (!(devpriv->ai_neverending)) 1048 /* all data sampled */ 1049 if (devpriv->ai_act_scan >= devpriv->ai_scans) { 1050 pcl812_ai_cancel(dev, s); 1051 s->async->events |= COMEDI_CB_EOA; 1052 } 1053 } 1054 1055 comedi_event(dev, s); 1056 return IRQ_HANDLED; 1057} 1058 1059/* 1060============================================================================== 1061*/ 1062static void transfer_from_dma_buf(struct comedi_device *dev, 1063 struct comedi_subdevice *s, short *ptr, 1064 unsigned int bufptr, unsigned int len) 1065{ 1066 unsigned int i; 1067 1068 s->async->events = 0; 1069 for (i = len; i; i--) { 1070 /* get one sample */ 1071 comedi_buf_put(s->async, ptr[bufptr++]); 1072 1073 s->async->cur_chan++; 1074 if (s->async->cur_chan >= devpriv->ai_n_chan) { 1075 s->async->cur_chan = 0; 1076 devpriv->ai_act_scan++; 1077 if (!devpriv->ai_neverending) 1078 /* all data sampled */ 1079 if (devpriv->ai_act_scan >= devpriv->ai_scans) { 1080 pcl812_ai_cancel(dev, s); 1081 s->async->events |= COMEDI_CB_EOA; 1082 break; 1083 } 1084 } 1085 } 1086 1087 comedi_event(dev, s); 1088} 1089 1090/* 1091============================================================================== 1092*/ 1093static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) 1094{ 1095 struct comedi_device *dev = d; 1096 struct comedi_subdevice *s = dev->subdevices + 0; 1097 unsigned long dma_flags; 1098 int len, bufptr; 1099 short *ptr; 1100 1101#ifdef PCL812_EXTDEBUG 1102 printk(KERN_DEBUG "pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n"); 1103#endif 1104 ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf]; 1105 len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - 1106 devpriv->ai_poll_ptr; 1107 1108 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; 1109 disable_dma(devpriv->dma); 1110 set_dma_mode(devpriv->dma, DMA_MODE_READ); 1111 dma_flags = claim_dma_lock(); 1112 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); 1113 if (devpriv->ai_eos) { 1114 set_dma_count(devpriv->dma, 1115 devpriv->dmabytestomove[devpriv->next_dma_buf]); 1116 } else { 1117 if (devpriv->dma_runs_to_end) { 1118 set_dma_count(devpriv->dma, 1119 devpriv->dmabytestomove[devpriv-> 1120 next_dma_buf]); 1121 } else { 1122 set_dma_count(devpriv->dma, devpriv->last_dma_run); 1123 } 1124 devpriv->dma_runs_to_end--; 1125 } 1126 release_dma_lock(dma_flags); 1127 enable_dma(devpriv->dma); 1128 1129 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ 1130 1131 bufptr = devpriv->ai_poll_ptr; 1132 devpriv->ai_poll_ptr = 0; 1133 1134 transfer_from_dma_buf(dev, s, ptr, bufptr, len); 1135 1136#ifdef PCL812_EXTDEBUG 1137 printk(KERN_DEBUG "pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n"); 1138#endif 1139 return IRQ_HANDLED; 1140} 1141 1142/* 1143============================================================================== 1144*/ 1145static irqreturn_t interrupt_pcl812(int irq, void *d) 1146{ 1147 struct comedi_device *dev = d; 1148 1149 if (!dev->attached) { 1150 comedi_error(dev, "spurious interrupt"); 1151 return IRQ_HANDLED; 1152 } 1153 if (devpriv->ai_dma) 1154 return interrupt_pcl812_ai_dma(irq, d); 1155 else 1156 return interrupt_pcl812_ai_int(irq, d); 1157} 1158 1159/* 1160============================================================================== 1161*/ 1162static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) 1163{ 1164 unsigned long flags; 1165 unsigned int top1, top2, i; 1166 1167 if (!devpriv->ai_dma) 1168 return 0; /* poll is valid only for DMA transfer */ 1169 1170 spin_lock_irqsave(&dev->spinlock, flags); 1171 1172 for (i = 0; i < 10; i++) { 1173 /* where is now DMA */ 1174 top1 = get_dma_residue(devpriv->ai_dma); 1175 top2 = get_dma_residue(devpriv->ai_dma); 1176 if (top1 == top2) 1177 break; 1178 } 1179 1180 if (top1 != top2) { 1181 spin_unlock_irqrestore(&dev->spinlock, flags); 1182 return 0; 1183 } 1184 /* where is now DMA in buffer */ 1185 top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; 1186 top1 >>= 1; /* sample position */ 1187 top2 = top1 - devpriv->ai_poll_ptr; 1188 if (top2 < 1) { /* no new samples */ 1189 spin_unlock_irqrestore(&dev->spinlock, flags); 1190 return 0; 1191 } 1192 1193 transfer_from_dma_buf(dev, s, 1194 (void *)devpriv->dmabuf[1 - 1195 devpriv->next_dma_buf], 1196 devpriv->ai_poll_ptr, top2); 1197 1198 devpriv->ai_poll_ptr = top1; /* new buffer position */ 1199 1200 spin_unlock_irqrestore(&dev->spinlock, flags); 1201 1202 return s->async->buf_write_count - s->async->buf_read_count; 1203} 1204 1205/* 1206============================================================================== 1207*/ 1208static void setup_range_channel(struct comedi_device *dev, 1209 struct comedi_subdevice *s, 1210 unsigned int rangechan, char wait) 1211{ 1212 unsigned char chan_reg = CR_CHAN(rangechan); /* normal board */ 1213 /* gain index */ 1214 unsigned char gain_reg = CR_RANGE(rangechan) + 1215 devpriv->range_correction; 1216 1217 if ((chan_reg == devpriv->old_chan_reg) 1218 && (gain_reg == devpriv->old_gain_reg)) 1219 return; /* we can return, no change */ 1220 1221 devpriv->old_chan_reg = chan_reg; 1222 devpriv->old_gain_reg = gain_reg; 1223 1224 if (devpriv->use_MPC) { 1225 if (devpriv->use_diff) { 1226 chan_reg = chan_reg | 0x30; /* DIFF inputs */ 1227 } else { 1228 if (chan_reg & 0x80) 1229 /* SE inputs 8-15 */ 1230 chan_reg = chan_reg | 0x20; 1231 else 1232 /* SE inputs 0-7 */ 1233 chan_reg = chan_reg | 0x10; 1234 } 1235 } 1236 1237 outb(chan_reg, dev->iobase + PCL812_MUX); /* select channel */ 1238 outb(gain_reg, dev->iobase + PCL812_GAIN); /* select gain */ 1239 1240 1241 if (wait) 1242 /* 1243 * XXX this depends on selected range and can be very long for 1244 * some high gain ranges! 1245 */ 1246 udelay(devpriv->max_812_ai_mode0_rangewait); 1247} 1248 1249/* 1250============================================================================== 1251*/ 1252static void start_pacer(struct comedi_device *dev, int mode, 1253 unsigned int divisor1, unsigned int divisor2) 1254{ 1255#ifdef PCL812_EXTDEBUG 1256 printk(KERN_DEBUG "pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, 1257 divisor1, divisor2); 1258#endif 1259 outb(0xb4, dev->iobase + PCL812_CTRCTL); 1260 outb(0x74, dev->iobase + PCL812_CTRCTL); 1261 udelay(1); 1262 1263 if (mode == 1) { 1264 outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2); 1265 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2); 1266 outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1); 1267 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1); 1268 } 1269#ifdef PCL812_EXTDEBUG 1270 printk(KERN_DEBUG "pcl812 EDBG: END: start_pacer(...)\n"); 1271#endif 1272} 1273 1274/* 1275============================================================================== 1276*/ 1277static void free_resources(struct comedi_device *dev) 1278{ 1279 1280 if (dev->private) { 1281 if (devpriv->dmabuf[0]) 1282 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); 1283 if (devpriv->dmabuf[1]) 1284 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); 1285 if (devpriv->dma) 1286 free_dma(devpriv->dma); 1287 } 1288 if (dev->irq) 1289 free_irq(dev->irq, dev); 1290 if (dev->iobase) 1291 release_region(dev->iobase, this_board->io_range); 1292} 1293 1294/* 1295============================================================================== 1296*/ 1297static int pcl812_ai_cancel(struct comedi_device *dev, 1298 struct comedi_subdevice *s) 1299{ 1300#ifdef PCL812_EXTDEBUG 1301 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n"); 1302#endif 1303 if (devpriv->ai_dma) 1304 disable_dma(devpriv->dma); 1305 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ 1306 /* Stop A/D */ 1307 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); 1308 start_pacer(dev, -1, 0, 0); /* stop 8254 */ 1309 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ 1310#ifdef PCL812_EXTDEBUG 1311 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cancel(...)\n"); 1312#endif 1313 return 0; 1314} 1315 1316/* 1317============================================================================== 1318*/ 1319static void pcl812_reset(struct comedi_device *dev) 1320{ 1321#ifdef PCL812_EXTDEBUG 1322 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_reset(...)\n"); 1323#endif 1324 outb(0, dev->iobase + PCL812_MUX); 1325 outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN); 1326 devpriv->old_chan_reg = -1; /* invalidate chain/gain memory */ 1327 devpriv->old_gain_reg = -1; 1328 1329 switch (this_board->board_type) { 1330 case boardPCL812PG: 1331 case boardPCL812: 1332 case boardACL8112: 1333 case boardACL8216: 1334 outb(0, dev->iobase + PCL812_DA2_LO); 1335 outb(0, dev->iobase + PCL812_DA2_HI); 1336 case boardA821: 1337 outb(0, dev->iobase + PCL812_DA1_LO); 1338 outb(0, dev->iobase + PCL812_DA1_HI); 1339 start_pacer(dev, -1, 0, 0); /* stop 8254 */ 1340 outb(0, dev->iobase + PCL812_DO_HI); 1341 outb(0, dev->iobase + PCL812_DO_LO); 1342 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); 1343 outb(0, dev->iobase + PCL812_CLRINT); 1344 break; 1345 case boardPCL813B: 1346 case boardPCL813: 1347 case boardISO813: 1348 case boardACL8113: 1349 udelay(5); 1350 break; 1351 } 1352 udelay(5); 1353#ifdef PCL812_EXTDEBUG 1354 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_reset(...)\n"); 1355#endif 1356} 1357 1358/* 1359============================================================================== 1360*/ 1361static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1362{ 1363 int ret, subdev; 1364 unsigned long iobase; 1365 unsigned int irq; 1366 unsigned int dma; 1367 unsigned long pages; 1368 struct comedi_subdevice *s; 1369 int n_subdevices; 1370 1371 iobase = it->options[0]; 1372 printk(KERN_INFO "comedi%d: pcl812: board=%s, ioport=0x%03lx", 1373 dev->minor, this_board->name, iobase); 1374 1375 if (!request_region(iobase, this_board->io_range, "pcl812")) { 1376 printk("I/O port conflict\n"); 1377 return -EIO; 1378 } 1379 dev->iobase = iobase; 1380 1381 ret = alloc_private(dev, sizeof(struct pcl812_private)); 1382 if (ret < 0) { 1383 free_resources(dev); 1384 return ret; /* Can't alloc mem */ 1385 } 1386 1387 dev->board_name = this_board->name; 1388 1389 irq = 0; 1390 if (this_board->IRQbits != 0) { /* board support IRQ */ 1391 irq = it->options[1]; 1392 if (irq) { /* we want to use IRQ */ 1393 if (((1 << irq) & this_board->IRQbits) == 0) { 1394 printk 1395 (", IRQ %u is out of allowed range, " 1396 "DISABLING IT", irq); 1397 irq = 0; /* Bad IRQ */ 1398 } else { 1399 if (request_irq 1400 (irq, interrupt_pcl812, 0, "pcl812", dev)) { 1401 printk 1402 (", unable to allocate IRQ %u, " 1403 "DISABLING IT", irq); 1404 irq = 0; /* Can't use IRQ */ 1405 } else { 1406 printk(KERN_INFO ", irq=%u", irq); 1407 } 1408 } 1409 } 1410 } 1411 1412 dev->irq = irq; 1413 1414 dma = 0; 1415 devpriv->dma = dma; 1416 if (!dev->irq) 1417 goto no_dma; /* if we haven't IRQ, we can't use DMA */ 1418 if (this_board->DMAbits != 0) { /* board support DMA */ 1419 dma = it->options[2]; 1420 if (((1 << dma) & this_board->DMAbits) == 0) { 1421 printk(", DMA is out of allowed range, FAIL!\n"); 1422 return -EINVAL; /* Bad DMA */ 1423 } 1424 ret = request_dma(dma, "pcl812"); 1425 if (ret) { 1426 printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n", 1427 dma); 1428 return -EBUSY; /* DMA isn't free */ 1429 } 1430 devpriv->dma = dma; 1431 printk(KERN_INFO ", dma=%u", dma); 1432 pages = 1; /* we want 8KB */ 1433 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); 1434 if (!devpriv->dmabuf[0]) { 1435 printk(", unable to allocate DMA buffer, FAIL!\n"); 1436 /* 1437 * maybe experiment with try_to_free_pages() 1438 * will help .... 1439 */ 1440 free_resources(dev); 1441 return -EBUSY; /* no buffer :-( */ 1442 } 1443 devpriv->dmapages[0] = pages; 1444 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); 1445 devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages); 1446 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); 1447 if (!devpriv->dmabuf[1]) { 1448 printk(KERN_ERR ", unable to allocate DMA buffer, FAIL!\n"); 1449 free_resources(dev); 1450 return -EBUSY; 1451 } 1452 devpriv->dmapages[1] = pages; 1453 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]); 1454 devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages); 1455 } 1456no_dma: 1457 1458 n_subdevices = 0; 1459 if (this_board->n_aichan > 0) 1460 n_subdevices++; 1461 if (this_board->n_aochan > 0) 1462 n_subdevices++; 1463 if (this_board->n_dichan > 0) 1464 n_subdevices++; 1465 if (this_board->n_dochan > 0) 1466 n_subdevices++; 1467 1468 ret = alloc_subdevices(dev, n_subdevices); 1469 if (ret < 0) { 1470 free_resources(dev); 1471 return ret; 1472 } 1473 1474 subdev = 0; 1475 1476 /* analog input */ 1477 if (this_board->n_aichan > 0) { 1478 s = dev->subdevices + subdev; 1479 s->type = COMEDI_SUBD_AI; 1480 s->subdev_flags = SDF_READABLE; 1481 switch (this_board->board_type) { 1482 case boardA821: 1483 if (it->options[2] == 1) { 1484 s->n_chan = this_board->n_aichan_diff; 1485 s->subdev_flags |= SDF_DIFF; 1486 devpriv->use_diff = 1; 1487 } else { 1488 s->n_chan = this_board->n_aichan; 1489 s->subdev_flags |= SDF_GROUND; 1490 } 1491 break; 1492 case boardACL8112: 1493 case boardACL8216: 1494 if (it->options[4] == 1) { 1495 s->n_chan = this_board->n_aichan_diff; 1496 s->subdev_flags |= SDF_DIFF; 1497 devpriv->use_diff = 1; 1498 } else { 1499 s->n_chan = this_board->n_aichan; 1500 s->subdev_flags |= SDF_GROUND; 1501 } 1502 break; 1503 default: 1504 s->n_chan = this_board->n_aichan; 1505 s->subdev_flags |= SDF_GROUND; 1506 break; 1507 } 1508 s->maxdata = this_board->ai_maxdata; 1509 s->len_chanlist = MAX_CHANLIST_LEN; 1510 s->range_table = this_board->rangelist_ai; 1511 if (this_board->board_type == boardACL8216) 1512 s->insn_read = acl8216_ai_insn_read; 1513 else 1514 s->insn_read = pcl812_ai_insn_read; 1515 1516 devpriv->use_MPC = this_board->haveMPC508; 1517 s->cancel = pcl812_ai_cancel; 1518 if (dev->irq) { 1519 dev->read_subdev = s; 1520 s->subdev_flags |= SDF_CMD_READ; 1521 s->do_cmdtest = pcl812_ai_cmdtest; 1522 s->do_cmd = pcl812_ai_cmd; 1523 s->poll = pcl812_ai_poll; 1524 } 1525 switch (this_board->board_type) { 1526 case boardPCL812PG: 1527 if (it->options[4] == 1) 1528 s->range_table = &range_pcl812pg2_ai; 1529 break; 1530 case boardPCL812: 1531 switch (it->options[4]) { 1532 case 0: 1533 s->range_table = &range_bipolar10; 1534 break; 1535 case 1: 1536 s->range_table = &range_bipolar5; 1537 break; 1538 case 2: 1539 s->range_table = &range_bipolar2_5; 1540 break; 1541 case 3: 1542 s->range_table = &range812_bipolar1_25; 1543 break; 1544 case 4: 1545 s->range_table = &range812_bipolar0_625; 1546 break; 1547 case 5: 1548 s->range_table = &range812_bipolar0_3125; 1549 break; 1550 default: 1551 s->range_table = &range_bipolar10; 1552 break; 1553 printk 1554 (", incorrect range number %d, changing " 1555 "to 0 (+/-10V)", it->options[4]); 1556 break; 1557 } 1558 break; 1559 break; 1560 case boardPCL813B: 1561 if (it->options[1] == 1) 1562 s->range_table = &range_pcl813b2_ai; 1563 break; 1564 case boardISO813: 1565 switch (it->options[1]) { 1566 case 0: 1567 s->range_table = &range_iso813_1_ai; 1568 break; 1569 case 1: 1570 s->range_table = &range_iso813_1_2_ai; 1571 break; 1572 case 2: 1573 s->range_table = &range_iso813_2_ai; 1574 devpriv->range_correction = 1; 1575 break; 1576 case 3: 1577 s->range_table = &range_iso813_2_2_ai; 1578 devpriv->range_correction = 1; 1579 break; 1580 default: 1581 s->range_table = &range_iso813_1_ai; 1582 break; 1583 printk 1584 (", incorrect range number %d, " 1585 "changing to 0 ", it->options[1]); 1586 break; 1587 } 1588 break; 1589 case boardACL8113: 1590 switch (it->options[1]) { 1591 case 0: 1592 s->range_table = &range_acl8113_1_ai; 1593 break; 1594 case 1: 1595 s->range_table = &range_acl8113_1_2_ai; 1596 break; 1597 case 2: 1598 s->range_table = &range_acl8113_2_ai; 1599 devpriv->range_correction = 1; 1600 break; 1601 case 3: 1602 s->range_table = &range_acl8113_2_2_ai; 1603 devpriv->range_correction = 1; 1604 break; 1605 default: 1606 s->range_table = &range_acl8113_1_ai; 1607 break; 1608 printk 1609 (", incorrect range number %d, " 1610 "changing to 0 ", it->options[1]); 1611 break; 1612 } 1613 break; 1614 } 1615 subdev++; 1616 } 1617 1618 /* analog output */ 1619 if (this_board->n_aochan > 0) { 1620 s = dev->subdevices + subdev; 1621 s->type = COMEDI_SUBD_AO; 1622 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 1623 s->n_chan = this_board->n_aochan; 1624 s->maxdata = 0xfff; 1625 s->len_chanlist = 1; 1626 s->range_table = this_board->rangelist_ao; 1627 s->insn_read = pcl812_ao_insn_read; 1628 s->insn_write = pcl812_ao_insn_write; 1629 switch (this_board->board_type) { 1630 case boardA821: 1631 if (it->options[3] == 1) 1632 s->range_table = &range_unipolar10; 1633 break; 1634 case boardPCL812: 1635 case boardACL8112: 1636 case boardPCL812PG: 1637 case boardACL8216: 1638 if (it->options[5] == 1) 1639 s->range_table = &range_unipolar10; 1640 if (it->options[5] == 2) 1641 s->range_table = &range_unknown; 1642 break; 1643 } 1644 subdev++; 1645 } 1646 1647 /* digital input */ 1648 if (this_board->n_dichan > 0) { 1649 s = dev->subdevices + subdev; 1650 s->type = COMEDI_SUBD_DI; 1651 s->subdev_flags = SDF_READABLE; 1652 s->n_chan = this_board->n_dichan; 1653 s->maxdata = 1; 1654 s->len_chanlist = this_board->n_dichan; 1655 s->range_table = &range_digital; 1656 s->insn_bits = pcl812_di_insn_bits; 1657 subdev++; 1658 } 1659 1660 /* digital output */ 1661 if (this_board->n_dochan > 0) { 1662 s = dev->subdevices + subdev; 1663 s->type = COMEDI_SUBD_DO; 1664 s->subdev_flags = SDF_WRITABLE; 1665 s->n_chan = this_board->n_dochan; 1666 s->maxdata = 1; 1667 s->len_chanlist = this_board->n_dochan; 1668 s->range_table = &range_digital; 1669 s->insn_bits = pcl812_do_insn_bits; 1670 subdev++; 1671 } 1672 1673 switch (this_board->board_type) { 1674 case boardACL8216: 1675 devpriv->ai_is16b = 1; 1676 case boardPCL812PG: 1677 case boardPCL812: 1678 case boardACL8112: 1679 devpriv->max_812_ai_mode0_rangewait = 1; 1680 if (it->options[3] > 0) 1681 /* we use external trigger */ 1682 devpriv->use_ext_trg = 1; 1683 case boardA821: 1684 devpriv->max_812_ai_mode0_rangewait = 1; 1685 devpriv->mode_reg_int = (irq << 4) & 0xf0; 1686 break; 1687 case boardPCL813B: 1688 case boardPCL813: 1689 case boardISO813: 1690 case boardACL8113: 1691 /* maybe there must by greatest timeout */ 1692 devpriv->max_812_ai_mode0_rangewait = 5; 1693 break; 1694 } 1695 1696 printk(KERN_INFO "\n"); 1697 devpriv->valid = 1; 1698 1699 pcl812_reset(dev); 1700 1701 return 0; 1702} 1703 1704/* 1705============================================================================== 1706 */ 1707static int pcl812_detach(struct comedi_device *dev) 1708{ 1709 1710#ifdef PCL812_EXTDEBUG 1711 printk(KERN_DEBUG "comedi%d: pcl812: remove\n", dev->minor); 1712#endif 1713 free_resources(dev); 1714 return 0; 1715} 1716 1717MODULE_AUTHOR("Comedi http://www.comedi.org"); 1718MODULE_DESCRIPTION("Comedi low-level driver"); 1719MODULE_LICENSE("GPL"); 1720