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