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/module.h> 112#include <linux/interrupt.h> 113#include <linux/gfp.h> 114#include "../comedidev.h" 115 116#include <linux/delay.h> 117#include <linux/io.h> 118#include <asm/dma.h> 119 120#include "comedi_fc.h" 121#include "8253.h" 122 123/* hardware types of the cards */ 124#define boardPCL812PG 0 /* and ACL-8112PG */ 125#define boardPCL813B 1 126#define boardPCL812 2 127#define boardPCL813 3 128#define boardISO813 5 129#define boardACL8113 6 130#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ 131#define boardACL8216 8 /* and ICP DAS A-826PG */ 132#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ 133 134/* 135 * Register I/O map 136 */ 137#define PCL812_TIMER_BASE 0x00 138#define PCL812_AI_LSB_REG 0x04 139#define PCL812_AI_MSB_REG 0x05 140#define PCL812_AI_MSB_DRDY (1 << 4) 141#define PCL812_AO_LSB_REG(x) (0x04 + ((x) * 2)) 142#define PCL812_AO_MSB_REG(x) (0x05 + ((x) * 2)) 143#define PCL812_DI_LSB_REG 0x06 144#define PCL812_DI_MSB_REG 0x07 145#define PCL812_STATUS_REG 0x08 146#define PCL812_STATUS_DRDY (1 << 5) 147#define PCL812_RANGE_REG 0x09 148#define PCL812_MUX_REG 0x0a 149#define PCL812_MUX_CHAN(x) ((x) << 0) 150#define PCL812_MUX_CS0 (1 << 4) 151#define PCL812_MUX_CS1 (1 << 5) 152#define PCL812_CTRL_REG 0x0b 153#define PCL812_CTRL_DISABLE_TRIG (0 << 0) 154#define PCL812_CTRL_SOFT_TRIG (1 << 0) 155#define PCL812_CTRL_PACER_DMA_TRIG (2 << 0) 156#define PCL812_CTRL_PACER_EOC_TRIG (6 << 0) 157#define PCL812_SOFTTRIG_REG 0x0c 158#define PCL812_DO_LSB_REG 0x0d 159#define PCL812_DO_MSB_REG 0x0e 160 161#define MAX_CHANLIST_LEN 256 /* length of scan list */ 162 163static const struct comedi_lrange range_pcl812pg_ai = { 164 5, { 165 BIP_RANGE(5), 166 BIP_RANGE(2.5), 167 BIP_RANGE(1.25), 168 BIP_RANGE(0.625), 169 BIP_RANGE(0.3125) 170 } 171}; 172 173static const struct comedi_lrange range_pcl812pg2_ai = { 174 5, { 175 BIP_RANGE(10), 176 BIP_RANGE(5), 177 BIP_RANGE(2.5), 178 BIP_RANGE(1.25), 179 BIP_RANGE(0.625) 180 } 181}; 182 183static const struct comedi_lrange range812_bipolar1_25 = { 184 1, { 185 BIP_RANGE(1.25) 186 } 187}; 188 189static const struct comedi_lrange range812_bipolar0_625 = { 190 1, { 191 BIP_RANGE(0.625) 192 } 193}; 194 195static const struct comedi_lrange range812_bipolar0_3125 = { 196 1, { 197 BIP_RANGE(0.3125) 198 } 199}; 200 201static const struct comedi_lrange range_pcl813b_ai = { 202 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 = { 211 4, { 212 UNI_RANGE(10), 213 UNI_RANGE(5), 214 UNI_RANGE(2.5), 215 UNI_RANGE(1.25) 216 } 217}; 218 219static const struct comedi_lrange range_iso813_1_ai = { 220 5, { 221 BIP_RANGE(5), 222 BIP_RANGE(2.5), 223 BIP_RANGE(1.25), 224 BIP_RANGE(0.625), 225 BIP_RANGE(0.3125) 226 } 227}; 228 229static const struct comedi_lrange range_iso813_1_2_ai = { 230 5, { 231 UNI_RANGE(10), 232 UNI_RANGE(5), 233 UNI_RANGE(2.5), 234 UNI_RANGE(1.25), 235 UNI_RANGE(0.625) 236 } 237}; 238 239static const struct comedi_lrange range_iso813_2_ai = { 240 4, { 241 BIP_RANGE(5), 242 BIP_RANGE(2.5), 243 BIP_RANGE(1.25), 244 BIP_RANGE(0.625) 245 } 246}; 247 248static const struct comedi_lrange range_iso813_2_2_ai = { 249 4, { 250 UNI_RANGE(10), 251 UNI_RANGE(5), 252 UNI_RANGE(2.5), 253 UNI_RANGE(1.25) 254 } 255}; 256 257static const struct comedi_lrange range_acl8113_1_ai = { 258 4, { 259 BIP_RANGE(5), 260 BIP_RANGE(2.5), 261 BIP_RANGE(1.25), 262 BIP_RANGE(0.625) 263 } 264}; 265 266static const struct comedi_lrange range_acl8113_1_2_ai = { 267 4, { 268 UNI_RANGE(10), 269 UNI_RANGE(5), 270 UNI_RANGE(2.5), 271 UNI_RANGE(1.25) 272 } 273}; 274 275static const struct comedi_lrange range_acl8113_2_ai = { 276 3, { 277 BIP_RANGE(5), 278 BIP_RANGE(2.5), 279 BIP_RANGE(1.25) 280 } 281}; 282 283static const struct comedi_lrange range_acl8113_2_2_ai = { 284 3, { 285 UNI_RANGE(10), 286 UNI_RANGE(5), 287 UNI_RANGE(2.5) 288 } 289}; 290 291static const struct comedi_lrange range_acl8112dg_ai = { 292 9, { 293 BIP_RANGE(5), 294 BIP_RANGE(2.5), 295 BIP_RANGE(1.25), 296 BIP_RANGE(0.625), 297 UNI_RANGE(10), 298 UNI_RANGE(5), 299 UNI_RANGE(2.5), 300 UNI_RANGE(1.25), 301 BIP_RANGE(10) 302 } 303}; 304 305static const struct comedi_lrange range_acl8112hg_ai = { 306 12, { 307 BIP_RANGE(5), 308 BIP_RANGE(0.5), 309 BIP_RANGE(0.05), 310 BIP_RANGE(0.005), 311 UNI_RANGE(10), 312 UNI_RANGE(1), 313 UNI_RANGE(0.1), 314 UNI_RANGE(0.01), 315 BIP_RANGE(10), 316 BIP_RANGE(1), 317 BIP_RANGE(0.1), 318 BIP_RANGE(0.01) 319 } 320}; 321 322static const struct comedi_lrange range_a821pgh_ai = { 323 4, { 324 BIP_RANGE(5), 325 BIP_RANGE(0.5), 326 BIP_RANGE(0.05), 327 BIP_RANGE(0.005) 328 } 329}; 330 331struct pcl812_board { 332 const char *name; 333 int board_type; 334 int n_aichan; 335 int n_aochan; 336 unsigned int ai_ns_min; 337 const struct comedi_lrange *rangelist_ai; 338 unsigned int IRQbits; 339 unsigned int has_dma:1; 340 unsigned int has_16bit_ai:1; 341 unsigned int has_mpc508_mux:1; 342 unsigned int has_dio:1; 343}; 344 345static const struct pcl812_board boardtypes[] = { 346 { 347 .name = "pcl812", 348 .board_type = boardPCL812, 349 .n_aichan = 16, 350 .n_aochan = 2, 351 .ai_ns_min = 33000, 352 .rangelist_ai = &range_bipolar10, 353 .IRQbits = 0xdcfc, 354 .has_dma = 1, 355 .has_dio = 1, 356 }, { 357 .name = "pcl812pg", 358 .board_type = boardPCL812PG, 359 .n_aichan = 16, 360 .n_aochan = 2, 361 .ai_ns_min = 33000, 362 .rangelist_ai = &range_pcl812pg_ai, 363 .IRQbits = 0xdcfc, 364 .has_dma = 1, 365 .has_dio = 1, 366 }, { 367 .name = "acl8112pg", 368 .board_type = boardPCL812PG, 369 .n_aichan = 16, 370 .n_aochan = 2, 371 .ai_ns_min = 10000, 372 .rangelist_ai = &range_pcl812pg_ai, 373 .IRQbits = 0xdcfc, 374 .has_dma = 1, 375 .has_dio = 1, 376 }, { 377 .name = "acl8112dg", 378 .board_type = boardACL8112, 379 .n_aichan = 16, /* 8 differential */ 380 .n_aochan = 2, 381 .ai_ns_min = 10000, 382 .rangelist_ai = &range_acl8112dg_ai, 383 .IRQbits = 0xdcfc, 384 .has_dma = 1, 385 .has_mpc508_mux = 1, 386 .has_dio = 1, 387 }, { 388 .name = "acl8112hg", 389 .board_type = boardACL8112, 390 .n_aichan = 16, /* 8 differential */ 391 .n_aochan = 2, 392 .ai_ns_min = 10000, 393 .rangelist_ai = &range_acl8112hg_ai, 394 .IRQbits = 0xdcfc, 395 .has_dma = 1, 396 .has_mpc508_mux = 1, 397 .has_dio = 1, 398 }, { 399 .name = "a821pgl", 400 .board_type = boardA821, 401 .n_aichan = 16, /* 8 differential */ 402 .n_aochan = 1, 403 .ai_ns_min = 10000, 404 .rangelist_ai = &range_pcl813b_ai, 405 .IRQbits = 0x000c, 406 .has_dio = 1, 407 }, { 408 .name = "a821pglnda", 409 .board_type = boardA821, 410 .n_aichan = 16, /* 8 differential */ 411 .ai_ns_min = 10000, 412 .rangelist_ai = &range_pcl813b_ai, 413 .IRQbits = 0x000c, 414 }, { 415 .name = "a821pgh", 416 .board_type = boardA821, 417 .n_aichan = 16, /* 8 differential */ 418 .n_aochan = 1, 419 .ai_ns_min = 10000, 420 .rangelist_ai = &range_a821pgh_ai, 421 .IRQbits = 0x000c, 422 .has_dio = 1, 423 }, { 424 .name = "a822pgl", 425 .board_type = boardACL8112, 426 .n_aichan = 16, /* 8 differential */ 427 .n_aochan = 2, 428 .ai_ns_min = 10000, 429 .rangelist_ai = &range_acl8112dg_ai, 430 .IRQbits = 0xdcfc, 431 .has_dma = 1, 432 .has_dio = 1, 433 }, { 434 .name = "a822pgh", 435 .board_type = boardACL8112, 436 .n_aichan = 16, /* 8 differential */ 437 .n_aochan = 2, 438 .ai_ns_min = 10000, 439 .rangelist_ai = &range_acl8112hg_ai, 440 .IRQbits = 0xdcfc, 441 .has_dma = 1, 442 .has_dio = 1, 443 }, { 444 .name = "a823pgl", 445 .board_type = boardACL8112, 446 .n_aichan = 16, /* 8 differential */ 447 .n_aochan = 2, 448 .ai_ns_min = 8000, 449 .rangelist_ai = &range_acl8112dg_ai, 450 .IRQbits = 0xdcfc, 451 .has_dma = 1, 452 .has_dio = 1, 453 }, { 454 .name = "a823pgh", 455 .board_type = boardACL8112, 456 .n_aichan = 16, /* 8 differential */ 457 .n_aochan = 2, 458 .ai_ns_min = 8000, 459 .rangelist_ai = &range_acl8112hg_ai, 460 .IRQbits = 0xdcfc, 461 .has_dma = 1, 462 .has_dio = 1, 463 }, { 464 .name = "pcl813", 465 .board_type = boardPCL813, 466 .n_aichan = 32, 467 .rangelist_ai = &range_pcl813b_ai, 468 }, { 469 .name = "pcl813b", 470 .board_type = boardPCL813B, 471 .n_aichan = 32, 472 .rangelist_ai = &range_pcl813b_ai, 473 }, { 474 .name = "acl8113", 475 .board_type = boardACL8113, 476 .n_aichan = 32, 477 .rangelist_ai = &range_acl8113_1_ai, 478 }, { 479 .name = "iso813", 480 .board_type = boardISO813, 481 .n_aichan = 32, 482 .rangelist_ai = &range_iso813_1_ai, 483 }, { 484 .name = "acl8216", 485 .board_type = boardACL8216, 486 .n_aichan = 16, /* 8 differential */ 487 .n_aochan = 2, 488 .ai_ns_min = 10000, 489 .rangelist_ai = &range_pcl813b2_ai, 490 .IRQbits = 0xdcfc, 491 .has_dma = 1, 492 .has_16bit_ai = 1, 493 .has_mpc508_mux = 1, 494 .has_dio = 1, 495 }, { 496 .name = "a826pg", 497 .board_type = boardACL8216, 498 .n_aichan = 16, /* 8 differential */ 499 .n_aochan = 2, 500 .ai_ns_min = 10000, 501 .rangelist_ai = &range_pcl813b2_ai, 502 .IRQbits = 0xdcfc, 503 .has_dma = 1, 504 .has_16bit_ai = 1, 505 .has_dio = 1, 506 }, 507}; 508 509struct pcl812_private { 510 unsigned char dma; /* >0 use dma ( usedDMA channel) */ 511 unsigned char range_correction; /* =1 we must add 1 to range number */ 512 unsigned int last_ai_chanspec; 513 unsigned char mode_reg_int; /* there is stored INT number for some card */ 514 unsigned int ai_poll_ptr; /* how many sampes transfer poll */ 515 unsigned int ai_act_scan; /* how many scans we finished */ 516 unsigned int dmapages; 517 unsigned int hwdmasize; 518 unsigned long dmabuf[2]; /* PTR to DMA buf */ 519 unsigned int hwdmaptr[2]; /* HW PTR to DMA buf */ 520 unsigned int dmabytestomove[2]; /* how many bytes DMA transfer */ 521 int next_dma_buf; /* which buffer is next to use */ 522 unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ 523 unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ 524 unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ 525 unsigned int divisor1; 526 unsigned int divisor2; 527 unsigned int use_diff:1; 528 unsigned int use_mpc508:1; 529 unsigned int use_ext_trg:1; 530 unsigned int ai_dma:1; 531 unsigned int ai_eos:1; 532}; 533 534static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) 535{ 536 struct pcl812_private *devpriv = dev->private; 537 unsigned long timer_base = dev->iobase + PCL812_TIMER_BASE; 538 539 i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); 540 i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); 541 udelay(1); 542 543 if (load_timers) { 544 i8254_write(timer_base, 0, 2, devpriv->divisor2); 545 i8254_write(timer_base, 0, 1, devpriv->divisor1); 546 } 547} 548 549static void pcl812_ai_setup_dma(struct comedi_device *dev, 550 struct comedi_subdevice *s) 551{ 552 struct pcl812_private *devpriv = dev->private; 553 struct comedi_cmd *cmd = &s->async->cmd; 554 unsigned int dma_flags; 555 unsigned int bytes; 556 557 /* we use EOS, so adapt DMA buffer to one scan */ 558 if (devpriv->ai_eos) { 559 devpriv->dmabytestomove[0] = cfc_bytes_per_scan(s); 560 devpriv->dmabytestomove[1] = cfc_bytes_per_scan(s); 561 devpriv->dma_runs_to_end = 1; 562 } else { 563 devpriv->dmabytestomove[0] = devpriv->hwdmasize; 564 devpriv->dmabytestomove[1] = devpriv->hwdmasize; 565 if (s->async->prealloc_bufsz < devpriv->hwdmasize) { 566 devpriv->dmabytestomove[0] = 567 s->async->prealloc_bufsz; 568 devpriv->dmabytestomove[1] = 569 s->async->prealloc_bufsz; 570 } 571 if (cmd->stop_src == TRIG_NONE) { 572 devpriv->dma_runs_to_end = 1; 573 } else { 574 /* how many samples we must transfer? */ 575 bytes = cmd->stop_arg * cfc_bytes_per_scan(s); 576 577 /* how many DMA pages we must fill */ 578 devpriv->dma_runs_to_end = 579 bytes / devpriv->dmabytestomove[0]; 580 581 /* on last dma transfer must be moved */ 582 devpriv->last_dma_run = 583 bytes % devpriv->dmabytestomove[0]; 584 if (devpriv->dma_runs_to_end == 0) 585 devpriv->dmabytestomove[0] = 586 devpriv->last_dma_run; 587 devpriv->dma_runs_to_end--; 588 } 589 } 590 if (devpriv->dmabytestomove[0] > devpriv->hwdmasize) { 591 devpriv->dmabytestomove[0] = devpriv->hwdmasize; 592 devpriv->ai_eos = 0; 593 } 594 if (devpriv->dmabytestomove[1] > devpriv->hwdmasize) { 595 devpriv->dmabytestomove[1] = devpriv->hwdmasize; 596 devpriv->ai_eos = 0; 597 } 598 devpriv->next_dma_buf = 0; 599 set_dma_mode(devpriv->dma, DMA_MODE_READ); 600 dma_flags = claim_dma_lock(); 601 clear_dma_ff(devpriv->dma); 602 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); 603 set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); 604 release_dma_lock(dma_flags); 605 enable_dma(devpriv->dma); 606} 607 608static void pcl812_ai_setup_next_dma(struct comedi_device *dev, 609 struct comedi_subdevice *s) 610{ 611 struct pcl812_private *devpriv = dev->private; 612 unsigned long dma_flags; 613 614 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; 615 disable_dma(devpriv->dma); 616 set_dma_mode(devpriv->dma, DMA_MODE_READ); 617 dma_flags = claim_dma_lock(); 618 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); 619 if (devpriv->ai_eos) { 620 set_dma_count(devpriv->dma, 621 devpriv->dmabytestomove[devpriv->next_dma_buf]); 622 } else { 623 if (devpriv->dma_runs_to_end) { 624 set_dma_count(devpriv->dma, 625 devpriv->dmabytestomove[devpriv-> 626 next_dma_buf]); 627 } else { 628 set_dma_count(devpriv->dma, devpriv->last_dma_run); 629 } 630 devpriv->dma_runs_to_end--; 631 } 632 release_dma_lock(dma_flags); 633 enable_dma(devpriv->dma); 634} 635 636static void pcl812_ai_set_chan_range(struct comedi_device *dev, 637 unsigned int chanspec, char wait) 638{ 639 struct pcl812_private *devpriv = dev->private; 640 unsigned int chan = CR_CHAN(chanspec); 641 unsigned int range = CR_RANGE(chanspec); 642 unsigned int mux = 0; 643 644 if (chanspec == devpriv->last_ai_chanspec) 645 return; 646 647 devpriv->last_ai_chanspec = chanspec; 648 649 if (devpriv->use_mpc508) { 650 if (devpriv->use_diff) { 651 mux |= PCL812_MUX_CS0 | PCL812_MUX_CS1; 652 } else { 653 if (chan < 8) 654 mux |= PCL812_MUX_CS0; 655 else 656 mux |= PCL812_MUX_CS1; 657 } 658 } 659 660 outb(mux | PCL812_MUX_CHAN(chan), dev->iobase + PCL812_MUX_REG); 661 outb(range + devpriv->range_correction, dev->iobase + PCL812_RANGE_REG); 662 663 if (wait) 664 /* 665 * XXX this depends on selected range and can be very long for 666 * some high gain ranges! 667 */ 668 udelay(devpriv->max_812_ai_mode0_rangewait); 669} 670 671static void pcl812_ai_clear_eoc(struct comedi_device *dev) 672{ 673 /* writing any value clears the interrupt request */ 674 outb(0, dev->iobase + PCL812_STATUS_REG); 675} 676 677static void pcl812_ai_soft_trig(struct comedi_device *dev) 678{ 679 /* writing any value triggers a software conversion */ 680 outb(255, dev->iobase + PCL812_SOFTTRIG_REG); 681} 682 683static unsigned int pcl812_ai_get_sample(struct comedi_device *dev, 684 struct comedi_subdevice *s) 685{ 686 unsigned int val; 687 688 val = inb(dev->iobase + PCL812_AI_MSB_REG) << 8; 689 val |= inb(dev->iobase + PCL812_AI_LSB_REG); 690 691 return val & s->maxdata; 692} 693 694static int pcl812_ai_eoc(struct comedi_device *dev, 695 struct comedi_subdevice *s, 696 struct comedi_insn *insn, 697 unsigned long context) 698{ 699 unsigned int status; 700 701 if (s->maxdata > 0x0fff) { 702 status = inb(dev->iobase + PCL812_STATUS_REG); 703 if ((status & PCL812_STATUS_DRDY) == 0) 704 return 0; 705 } else { 706 status = inb(dev->iobase + PCL812_AI_MSB_REG); 707 if ((status & PCL812_AI_MSB_DRDY) == 0) 708 return 0; 709 } 710 return -EBUSY; 711} 712 713static int pcl812_ai_cmdtest(struct comedi_device *dev, 714 struct comedi_subdevice *s, struct comedi_cmd *cmd) 715{ 716 const struct pcl812_board *board = dev->board_ptr; 717 struct pcl812_private *devpriv = dev->private; 718 int err = 0; 719 unsigned int flags; 720 unsigned int arg; 721 722 /* Step 1 : check if triggers are trivially valid */ 723 724 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); 725 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); 726 727 if (devpriv->use_ext_trg) 728 flags = TRIG_EXT; 729 else 730 flags = TRIG_TIMER; 731 err |= cfc_check_trigger_src(&cmd->convert_src, flags); 732 733 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 734 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 735 736 if (err) 737 return 1; 738 739 /* Step 2a : make sure trigger sources are unique */ 740 741 err |= cfc_check_trigger_is_unique(cmd->stop_src); 742 743 /* Step 2b : and mutually compatible */ 744 745 if (err) 746 return 2; 747 748 /* Step 3: check if arguments are trivially valid */ 749 750 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 751 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 752 753 if (cmd->convert_src == TRIG_TIMER) 754 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 755 board->ai_ns_min); 756 else /* TRIG_EXT */ 757 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 758 759 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); 760 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 761 762 if (cmd->stop_src == TRIG_COUNT) 763 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); 764 else /* TRIG_NONE */ 765 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 766 767 if (err) 768 return 3; 769 770 /* step 4: fix up any arguments */ 771 772 if (cmd->convert_src == TRIG_TIMER) { 773 arg = cmd->convert_arg; 774 i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, 775 &devpriv->divisor1, 776 &devpriv->divisor2, 777 &arg, cmd->flags); 778 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); 779 } 780 781 if (err) 782 return 4; 783 784 return 0; 785} 786 787static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 788{ 789 struct pcl812_private *devpriv = dev->private; 790 struct comedi_cmd *cmd = &s->async->cmd; 791 unsigned int ctrl = 0; 792 unsigned int i; 793 794 pcl812_start_pacer(dev, false); 795 796 pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1); 797 798 if (devpriv->dma) { /* check if we can use DMA transfer */ 799 devpriv->ai_dma = 1; 800 for (i = 1; i < cmd->chanlist_len; i++) 801 if (cmd->chanlist[0] != cmd->chanlist[i]) { 802 /* we cann't use DMA :-( */ 803 devpriv->ai_dma = 0; 804 break; 805 } 806 } else { 807 devpriv->ai_dma = 0; 808 } 809 810 devpriv->ai_act_scan = 0; 811 devpriv->ai_poll_ptr = 0; 812 s->async->cur_chan = 0; 813 814 /* don't we want wake up every scan? */ 815 if (cmd->flags & CMDF_WAKE_EOS) { 816 devpriv->ai_eos = 1; 817 818 /* DMA is useless for this situation */ 819 if (cmd->chanlist_len == 1) 820 devpriv->ai_dma = 0; 821 } 822 823 if (devpriv->ai_dma) 824 pcl812_ai_setup_dma(dev, s); 825 826 switch (cmd->convert_src) { 827 case TRIG_TIMER: 828 pcl812_start_pacer(dev, true); 829 break; 830 } 831 832 if (devpriv->ai_dma) 833 ctrl |= PCL812_CTRL_PACER_DMA_TRIG; 834 else 835 ctrl |= PCL812_CTRL_PACER_EOC_TRIG; 836 outb(devpriv->mode_reg_int | ctrl, dev->iobase + PCL812_CTRL_REG); 837 838 return 0; 839} 840 841static bool pcl812_ai_next_chan(struct comedi_device *dev, 842 struct comedi_subdevice *s) 843{ 844 struct pcl812_private *devpriv = dev->private; 845 struct comedi_cmd *cmd = &s->async->cmd; 846 847 s->async->events |= COMEDI_CB_BLOCK; 848 849 s->async->cur_chan++; 850 if (s->async->cur_chan >= cmd->chanlist_len) { 851 s->async->cur_chan = 0; 852 devpriv->ai_act_scan++; 853 s->async->events |= COMEDI_CB_EOS; 854 } 855 856 if (cmd->stop_src == TRIG_COUNT && 857 devpriv->ai_act_scan >= cmd->stop_arg) { 858 /* all data sampled */ 859 s->async->events |= COMEDI_CB_EOA; 860 return false; 861 } 862 863 return true; 864} 865 866static void pcl812_handle_eoc(struct comedi_device *dev, 867 struct comedi_subdevice *s) 868{ 869 struct comedi_cmd *cmd = &s->async->cmd; 870 unsigned int next_chan; 871 872 if (pcl812_ai_eoc(dev, s, NULL, 0)) { 873 dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n"); 874 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 875 return; 876 } 877 878 comedi_buf_put(s, pcl812_ai_get_sample(dev, s)); 879 880 /* Set up next channel. Added by abbotti 2010-01-20, but untested. */ 881 next_chan = s->async->cur_chan + 1; 882 if (next_chan >= cmd->chanlist_len) 883 next_chan = 0; 884 if (cmd->chanlist[s->async->cur_chan] != cmd->chanlist[next_chan]) 885 pcl812_ai_set_chan_range(dev, cmd->chanlist[next_chan], 0); 886 887 pcl812_ai_next_chan(dev, s); 888} 889 890static void transfer_from_dma_buf(struct comedi_device *dev, 891 struct comedi_subdevice *s, 892 unsigned short *ptr, 893 unsigned int bufptr, unsigned int len) 894{ 895 unsigned int i; 896 897 for (i = len; i; i--) { 898 comedi_buf_put(s, ptr[bufptr++]); 899 900 if (!pcl812_ai_next_chan(dev, s)) 901 break; 902 } 903} 904 905static void pcl812_handle_dma(struct comedi_device *dev, 906 struct comedi_subdevice *s) 907{ 908 struct pcl812_private *devpriv = dev->private; 909 int len, bufptr; 910 unsigned short *ptr; 911 912 ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; 913 len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - 914 devpriv->ai_poll_ptr; 915 916 pcl812_ai_setup_next_dma(dev, s); 917 918 bufptr = devpriv->ai_poll_ptr; 919 devpriv->ai_poll_ptr = 0; 920 921 transfer_from_dma_buf(dev, s, ptr, bufptr, len); 922} 923 924static irqreturn_t pcl812_interrupt(int irq, void *d) 925{ 926 struct comedi_device *dev = d; 927 struct comedi_subdevice *s = dev->read_subdev; 928 struct pcl812_private *devpriv = dev->private; 929 930 if (!dev->attached) { 931 pcl812_ai_clear_eoc(dev); 932 return IRQ_HANDLED; 933 } 934 935 if (devpriv->ai_dma) 936 pcl812_handle_dma(dev, s); 937 else 938 pcl812_handle_eoc(dev, s); 939 940 pcl812_ai_clear_eoc(dev); 941 942 cfc_handle_events(dev, s); 943 return IRQ_HANDLED; 944} 945 946static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) 947{ 948 struct pcl812_private *devpriv = dev->private; 949 unsigned long flags; 950 unsigned int top1, top2, i; 951 952 if (!devpriv->ai_dma) 953 return 0; /* poll is valid only for DMA transfer */ 954 955 spin_lock_irqsave(&dev->spinlock, flags); 956 957 for (i = 0; i < 10; i++) { 958 /* where is now DMA */ 959 top1 = get_dma_residue(devpriv->ai_dma); 960 top2 = get_dma_residue(devpriv->ai_dma); 961 if (top1 == top2) 962 break; 963 } 964 965 if (top1 != top2) { 966 spin_unlock_irqrestore(&dev->spinlock, flags); 967 return 0; 968 } 969 /* where is now DMA in buffer */ 970 top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; 971 top1 >>= 1; /* sample position */ 972 top2 = top1 - devpriv->ai_poll_ptr; 973 if (top2 < 1) { /* no new samples */ 974 spin_unlock_irqrestore(&dev->spinlock, flags); 975 return 0; 976 } 977 978 transfer_from_dma_buf(dev, s, 979 (void *)devpriv->dmabuf[1 - 980 devpriv->next_dma_buf], 981 devpriv->ai_poll_ptr, top2); 982 983 devpriv->ai_poll_ptr = top1; /* new buffer position */ 984 985 spin_unlock_irqrestore(&dev->spinlock, flags); 986 987 return comedi_buf_n_bytes_ready(s); 988} 989 990static int pcl812_ai_cancel(struct comedi_device *dev, 991 struct comedi_subdevice *s) 992{ 993 struct pcl812_private *devpriv = dev->private; 994 995 if (devpriv->ai_dma) 996 disable_dma(devpriv->dma); 997 998 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 999 dev->iobase + PCL812_CTRL_REG); 1000 pcl812_start_pacer(dev, false); 1001 pcl812_ai_clear_eoc(dev); 1002 return 0; 1003} 1004 1005static int pcl812_ai_insn_read(struct comedi_device *dev, 1006 struct comedi_subdevice *s, 1007 struct comedi_insn *insn, 1008 unsigned int *data) 1009{ 1010 struct pcl812_private *devpriv = dev->private; 1011 int ret = 0; 1012 int i; 1013 1014 outb(devpriv->mode_reg_int | PCL812_CTRL_SOFT_TRIG, 1015 dev->iobase + PCL812_CTRL_REG); 1016 1017 pcl812_ai_set_chan_range(dev, insn->chanspec, 1); 1018 1019 for (i = 0; i < insn->n; i++) { 1020 pcl812_ai_clear_eoc(dev); 1021 pcl812_ai_soft_trig(dev); 1022 1023 ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0); 1024 if (ret) 1025 break; 1026 1027 data[i] = pcl812_ai_get_sample(dev, s); 1028 } 1029 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 1030 dev->iobase + PCL812_CTRL_REG); 1031 pcl812_ai_clear_eoc(dev); 1032 1033 return ret ? ret : insn->n; 1034} 1035 1036static int pcl812_ao_insn_write(struct comedi_device *dev, 1037 struct comedi_subdevice *s, 1038 struct comedi_insn *insn, 1039 unsigned int *data) 1040{ 1041 unsigned int chan = CR_CHAN(insn->chanspec); 1042 unsigned int val = s->readback[chan]; 1043 int i; 1044 1045 for (i = 0; i < insn->n; i++) { 1046 val = data[i]; 1047 outb(val & 0xff, dev->iobase + PCL812_AO_LSB_REG(chan)); 1048 outb((val >> 8) & 0x0f, dev->iobase + PCL812_AO_MSB_REG(chan)); 1049 } 1050 s->readback[chan] = val; 1051 1052 return insn->n; 1053} 1054 1055static int pcl812_di_insn_bits(struct comedi_device *dev, 1056 struct comedi_subdevice *s, 1057 struct comedi_insn *insn, 1058 unsigned int *data) 1059{ 1060 data[1] = inb(dev->iobase + PCL812_DI_LSB_REG) | 1061 (inb(dev->iobase + PCL812_DI_MSB_REG) << 8); 1062 1063 return insn->n; 1064} 1065 1066static int pcl812_do_insn_bits(struct comedi_device *dev, 1067 struct comedi_subdevice *s, 1068 struct comedi_insn *insn, 1069 unsigned int *data) 1070{ 1071 if (comedi_dio_update_state(s, data)) { 1072 outb(s->state & 0xff, dev->iobase + PCL812_DO_LSB_REG); 1073 outb((s->state >> 8), dev->iobase + PCL812_DO_MSB_REG); 1074 } 1075 1076 data[1] = s->state; 1077 1078 return insn->n; 1079} 1080 1081static void pcl812_reset(struct comedi_device *dev) 1082{ 1083 const struct pcl812_board *board = dev->board_ptr; 1084 struct pcl812_private *devpriv = dev->private; 1085 unsigned int chan; 1086 1087 /* disable analog input trigger */ 1088 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 1089 dev->iobase + PCL812_CTRL_REG); 1090 pcl812_ai_clear_eoc(dev); 1091 1092 /* stop pacer */ 1093 if (board->IRQbits) 1094 pcl812_start_pacer(dev, false); 1095 1096 /* 1097 * Invalidate last_ai_chanspec then set analog input to 1098 * known channel/range. 1099 */ 1100 devpriv->last_ai_chanspec = CR_PACK(16, 0, 0); 1101 pcl812_ai_set_chan_range(dev, CR_PACK(0, 0, 0), 0); 1102 1103 /* set analog output channels to 0V */ 1104 for (chan = 0; chan < board->n_aochan; chan++) { 1105 outb(0, dev->iobase + PCL812_AO_LSB_REG(chan)); 1106 outb(0, dev->iobase + PCL812_AO_MSB_REG(chan)); 1107 } 1108 1109 /* set all digital outputs low */ 1110 if (board->has_dio) { 1111 outb(0, dev->iobase + PCL812_DO_MSB_REG); 1112 outb(0, dev->iobase + PCL812_DO_LSB_REG); 1113 } 1114} 1115 1116static void pcl812_set_ai_range_table(struct comedi_device *dev, 1117 struct comedi_subdevice *s, 1118 struct comedi_devconfig *it) 1119{ 1120 const struct pcl812_board *board = dev->board_ptr; 1121 struct pcl812_private *devpriv = dev->private; 1122 1123 /* default to the range table from the boardinfo */ 1124 s->range_table = board->rangelist_ai; 1125 1126 /* now check the user config option based on the boardtype */ 1127 switch (board->board_type) { 1128 case boardPCL812PG: 1129 if (it->options[4] == 1) 1130 s->range_table = &range_pcl812pg2_ai; 1131 break; 1132 case boardPCL812: 1133 switch (it->options[4]) { 1134 case 0: 1135 s->range_table = &range_bipolar10; 1136 break; 1137 case 1: 1138 s->range_table = &range_bipolar5; 1139 break; 1140 case 2: 1141 s->range_table = &range_bipolar2_5; 1142 break; 1143 case 3: 1144 s->range_table = &range812_bipolar1_25; 1145 break; 1146 case 4: 1147 s->range_table = &range812_bipolar0_625; 1148 break; 1149 case 5: 1150 s->range_table = &range812_bipolar0_3125; 1151 break; 1152 default: 1153 s->range_table = &range_bipolar10; 1154 break; 1155 } 1156 break; 1157 case boardPCL813B: 1158 if (it->options[1] == 1) 1159 s->range_table = &range_pcl813b2_ai; 1160 break; 1161 case boardISO813: 1162 switch (it->options[1]) { 1163 case 0: 1164 s->range_table = &range_iso813_1_ai; 1165 break; 1166 case 1: 1167 s->range_table = &range_iso813_1_2_ai; 1168 break; 1169 case 2: 1170 s->range_table = &range_iso813_2_ai; 1171 devpriv->range_correction = 1; 1172 break; 1173 case 3: 1174 s->range_table = &range_iso813_2_2_ai; 1175 devpriv->range_correction = 1; 1176 break; 1177 default: 1178 s->range_table = &range_iso813_1_ai; 1179 break; 1180 } 1181 break; 1182 case boardACL8113: 1183 switch (it->options[1]) { 1184 case 0: 1185 s->range_table = &range_acl8113_1_ai; 1186 break; 1187 case 1: 1188 s->range_table = &range_acl8113_1_2_ai; 1189 break; 1190 case 2: 1191 s->range_table = &range_acl8113_2_ai; 1192 devpriv->range_correction = 1; 1193 break; 1194 case 3: 1195 s->range_table = &range_acl8113_2_2_ai; 1196 devpriv->range_correction = 1; 1197 break; 1198 default: 1199 s->range_table = &range_acl8113_1_ai; 1200 break; 1201 } 1202 break; 1203 } 1204} 1205 1206static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1207{ 1208 const struct pcl812_board *board = dev->board_ptr; 1209 struct pcl812_private *devpriv; 1210 struct comedi_subdevice *s; 1211 int n_subdevices; 1212 int subdev; 1213 int ret; 1214 int i; 1215 1216 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 1217 if (!devpriv) 1218 return -ENOMEM; 1219 1220 ret = comedi_request_region(dev, it->options[0], 0x10); 1221 if (ret) 1222 return ret; 1223 1224 if ((1 << it->options[1]) & board->IRQbits) { 1225 ret = request_irq(it->options[1], pcl812_interrupt, 0, 1226 dev->board_name, dev); 1227 if (ret == 0) 1228 dev->irq = it->options[1]; 1229 } 1230 1231 /* we need an IRQ to do DMA on channel 3 or 1 */ 1232 if (dev->irq && board->has_dma && 1233 (it->options[2] == 3 || it->options[2] == 1)) { 1234 ret = request_dma(it->options[2], dev->board_name); 1235 if (ret) { 1236 dev_err(dev->class_dev, 1237 "unable to request DMA channel %d\n", 1238 it->options[2]); 1239 return -EBUSY; 1240 } 1241 devpriv->dma = it->options[2]; 1242 1243 devpriv->dmapages = 1; /* we want 8KB */ 1244 devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; 1245 1246 for (i = 0; i < 2; i++) { 1247 unsigned long dmabuf; 1248 1249 dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); 1250 if (!dmabuf) 1251 return -ENOMEM; 1252 1253 devpriv->dmabuf[i] = dmabuf; 1254 devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); 1255 } 1256 } 1257 1258 /* differential analog inputs? */ 1259 switch (board->board_type) { 1260 case boardA821: 1261 if (it->options[2] == 1) 1262 devpriv->use_diff = 1; 1263 break; 1264 case boardACL8112: 1265 case boardACL8216: 1266 if (it->options[4] == 1) 1267 devpriv->use_diff = 1; 1268 break; 1269 } 1270 1271 n_subdevices = 1; /* all boardtypes have analog inputs */ 1272 if (board->n_aochan > 0) 1273 n_subdevices++; 1274 if (board->has_dio) 1275 n_subdevices += 2; 1276 1277 ret = comedi_alloc_subdevices(dev, n_subdevices); 1278 if (ret) 1279 return ret; 1280 1281 subdev = 0; 1282 1283 /* Analog Input subdevice */ 1284 s = &dev->subdevices[subdev]; 1285 s->type = COMEDI_SUBD_AI; 1286 s->subdev_flags = SDF_READABLE; 1287 if (devpriv->use_diff) { 1288 s->subdev_flags |= SDF_DIFF; 1289 s->n_chan = board->n_aichan / 2; 1290 } else { 1291 s->subdev_flags |= SDF_GROUND; 1292 s->n_chan = board->n_aichan; 1293 } 1294 s->maxdata = board->has_16bit_ai ? 0xffff : 0x0fff; 1295 1296 pcl812_set_ai_range_table(dev, s, it); 1297 1298 s->insn_read = pcl812_ai_insn_read; 1299 1300 if (dev->irq) { 1301 dev->read_subdev = s; 1302 s->subdev_flags |= SDF_CMD_READ; 1303 s->len_chanlist = MAX_CHANLIST_LEN; 1304 s->do_cmdtest = pcl812_ai_cmdtest; 1305 s->do_cmd = pcl812_ai_cmd; 1306 s->poll = pcl812_ai_poll; 1307 s->cancel = pcl812_ai_cancel; 1308 } 1309 1310 devpriv->use_mpc508 = board->has_mpc508_mux; 1311 1312 subdev++; 1313 1314 /* analog output */ 1315 if (board->n_aochan > 0) { 1316 s = &dev->subdevices[subdev]; 1317 s->type = COMEDI_SUBD_AO; 1318 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 1319 s->n_chan = board->n_aochan; 1320 s->maxdata = 0xfff; 1321 s->range_table = &range_unipolar5; 1322 switch (board->board_type) { 1323 case boardA821: 1324 if (it->options[3] == 1) 1325 s->range_table = &range_unipolar10; 1326 break; 1327 case boardPCL812: 1328 case boardACL8112: 1329 case boardPCL812PG: 1330 case boardACL8216: 1331 if (it->options[5] == 1) 1332 s->range_table = &range_unipolar10; 1333 if (it->options[5] == 2) 1334 s->range_table = &range_unknown; 1335 break; 1336 } 1337 s->insn_write = pcl812_ao_insn_write; 1338 s->insn_read = comedi_readback_insn_read; 1339 1340 ret = comedi_alloc_subdev_readback(s); 1341 if (ret) 1342 return ret; 1343 1344 subdev++; 1345 } 1346 1347 if (board->has_dio) { 1348 /* Digital Input subdevice */ 1349 s = &dev->subdevices[subdev]; 1350 s->type = COMEDI_SUBD_DI; 1351 s->subdev_flags = SDF_READABLE; 1352 s->n_chan = 16; 1353 s->maxdata = 1; 1354 s->range_table = &range_digital; 1355 s->insn_bits = pcl812_di_insn_bits; 1356 subdev++; 1357 1358 /* Digital Output subdevice */ 1359 s = &dev->subdevices[subdev]; 1360 s->type = COMEDI_SUBD_DO; 1361 s->subdev_flags = SDF_WRITABLE; 1362 s->n_chan = 16; 1363 s->maxdata = 1; 1364 s->range_table = &range_digital; 1365 s->insn_bits = pcl812_do_insn_bits; 1366 subdev++; 1367 } 1368 1369 switch (board->board_type) { 1370 case boardACL8216: 1371 case boardPCL812PG: 1372 case boardPCL812: 1373 case boardACL8112: 1374 devpriv->max_812_ai_mode0_rangewait = 1; 1375 if (it->options[3] > 0) 1376 /* we use external trigger */ 1377 devpriv->use_ext_trg = 1; 1378 break; 1379 case boardA821: 1380 devpriv->max_812_ai_mode0_rangewait = 1; 1381 devpriv->mode_reg_int = (dev->irq << 4) & 0xf0; 1382 break; 1383 case boardPCL813B: 1384 case boardPCL813: 1385 case boardISO813: 1386 case boardACL8113: 1387 /* maybe there must by greatest timeout */ 1388 devpriv->max_812_ai_mode0_rangewait = 5; 1389 break; 1390 } 1391 1392 pcl812_reset(dev); 1393 1394 return 0; 1395} 1396 1397static void pcl812_detach(struct comedi_device *dev) 1398{ 1399 struct pcl812_private *devpriv = dev->private; 1400 1401 if (devpriv) { 1402 if (devpriv->dmabuf[0]) 1403 free_pages(devpriv->dmabuf[0], devpriv->dmapages); 1404 if (devpriv->dmabuf[1]) 1405 free_pages(devpriv->dmabuf[1], devpriv->dmapages); 1406 if (devpriv->dma) 1407 free_dma(devpriv->dma); 1408 } 1409 comedi_legacy_detach(dev); 1410} 1411 1412static struct comedi_driver pcl812_driver = { 1413 .driver_name = "pcl812", 1414 .module = THIS_MODULE, 1415 .attach = pcl812_attach, 1416 .detach = pcl812_detach, 1417 .board_name = &boardtypes[0].name, 1418 .num_names = ARRAY_SIZE(boardtypes), 1419 .offset = sizeof(struct pcl812_board), 1420}; 1421module_comedi_driver(pcl812_driver); 1422 1423MODULE_AUTHOR("Comedi http://www.comedi.org"); 1424MODULE_DESCRIPTION("Comedi low-level driver"); 1425MODULE_LICENSE("GPL"); 1426