adv_pci1710.c revision 97feeef5c55fe783e6f01d4dec3fd0926e60b0d8
1/* 2 * comedi/drivers/adv_pci1710.c 3 * 4 * Author: Michal Dobes <dobes@tesnet.cz> 5 * 6 * Thanks to ZhenGang Shang <ZhenGang.Shang@Advantech.com.cn> 7 * for testing and informations. 8 * 9 * hardware driver for Advantech cards: 10 * card: PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, PCI-1720, PCI-1731 11 * driver: pci1710, pci1710hg, pci1711, pci1713, pci1720, pci1731 12 * 13 * Options: 14 * [0] - PCI bus number - if bus number and slot number are 0, 15 * then driver search for first unused card 16 * [1] - PCI slot number 17 * 18*/ 19/* 20Driver: adv_pci1710 21Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, 22 Advantech PCI-1720, PCI-1731 23Author: Michal Dobes <dobes@tesnet.cz> 24Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG (pci1710hg), 25 PCI-1711 (adv_pci1710), PCI-1713, PCI-1720, 26 PCI-1731 27Status: works 28 29This driver supports AI, AO, DI and DO subdevices. 30AI subdevice supports cmd and insn interface, 31other subdevices support only insn interface. 32 33The PCI-1710 and PCI-1710HG have the same PCI device ID, so the 34driver cannot distinguish between them, as would be normal for a 35PCI driver. 36 37Configuration options: 38 [0] - PCI bus of device (optional) 39 [1] - PCI slot of device (optional) 40 If bus/slot is not specified, the first available PCI 41 device will be used. 42*/ 43 44#include <linux/interrupt.h> 45 46#include "../comedidev.h" 47 48#include "comedi_pci.h" 49 50#include "8253.h" 51#include "amcc_s5933.h" 52 53#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control 54 * correct channel number on every 12 bit 55 * sample */ 56 57#undef PCI171X_EXTDEBUG 58 59#define DRV_NAME "adv_pci1710" 60 61#undef DPRINTK 62#ifdef PCI171X_EXTDEBUG 63#define DPRINTK(fmt, args...) printk(fmt, ## args) 64#else 65#define DPRINTK(fmt, args...) 66#endif 67 68#define PCI_VENDOR_ID_ADVANTECH 0x13fe 69 70/* hardware types of the cards */ 71#define TYPE_PCI171X 0 72#define TYPE_PCI1713 2 73#define TYPE_PCI1720 3 74 75#define IORANGE_171x 32 76#define IORANGE_1720 16 77 78#define PCI171x_AD_DATA 0 /* R: A/D data */ 79#define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ 80#define PCI171x_RANGE 2 /* W: A/D gain/range register */ 81#define PCI171x_MUX 4 /* W: A/D multiplexor control */ 82#define PCI171x_STATUS 6 /* R: status register */ 83#define PCI171x_CONTROL 6 /* W: control register */ 84#define PCI171x_CLRINT 8 /* W: clear interrupts request */ 85#define PCI171x_CLRFIFO 9 /* W: clear FIFO */ 86#define PCI171x_DA1 10 /* W: D/A register */ 87#define PCI171x_DA2 12 /* W: D/A register */ 88#define PCI171x_DAREF 14 /* W: D/A reference control */ 89#define PCI171x_DI 16 /* R: digi inputs */ 90#define PCI171x_DO 16 /* R: digi inputs */ 91#define PCI171x_CNT0 24 /* R/W: 8254 counter 0 */ 92#define PCI171x_CNT1 26 /* R/W: 8254 counter 1 */ 93#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */ 94#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */ 95 96/* upper bits from status register (PCI171x_STATUS) (lower is same with control 97 * reg) */ 98#define Status_FE 0x0100 /* 1=FIFO is empty */ 99#define Status_FH 0x0200 /* 1=FIFO is half full */ 100#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */ 101#define Status_IRQ 0x0800 /* 1=IRQ occured */ 102/* bits from control register (PCI171x_CONTROL) */ 103#define Control_CNT0 0x0040 /* 1=CNT0 have external source, 104 * 0=have internal 100kHz source */ 105#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */ 106#define Control_IRQEN 0x0010 /* 1=enable IRQ */ 107#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */ 108#define Control_EXT 0x0004 /* 1=external trigger source */ 109#define Control_PACER 0x0002 /* 1=enable internal 8254 trigger source */ 110#define Control_SW 0x0001 /* 1=enable software trigger source */ 111/* bits from counter control register (PCI171x_CNTCTRL) */ 112#define Counter_BCD 0x0001 /* 0 = binary counter, 1 = BCD counter */ 113#define Counter_M0 0x0002 /* M0-M2 select modes 0-5 */ 114#define Counter_M1 0x0004 /* 000 = mode 0, 010 = mode 2 ... */ 115#define Counter_M2 0x0008 116#define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */ 117#define Counter_RW1 0x0020 118#define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */ 119#define Counter_SC1 0x0080 /* be used, 00 for CNT0, 120 * 11 for read-back command */ 121 122#define PCI1720_DA0 0 /* W: D/A register 0 */ 123#define PCI1720_DA1 2 /* W: D/A register 1 */ 124#define PCI1720_DA2 4 /* W: D/A register 2 */ 125#define PCI1720_DA3 6 /* W: D/A register 3 */ 126#define PCI1720_RANGE 8 /* R/W: D/A range register */ 127#define PCI1720_SYNCOUT 9 /* W: D/A synchronized output register */ 128#define PCI1720_SYNCONT 15 /* R/W: D/A synchronized control */ 129 130/* D/A synchronized control (PCI1720_SYNCONT) */ 131#define Syncont_SC0 1 /* set synchronous output mode */ 132 133static const struct comedi_lrange range_pci1710_3 = { 9, { 134 BIP_RANGE(5), 135 BIP_RANGE(2.5), 136 BIP_RANGE(1.25), 137 BIP_RANGE(0.625), 138 BIP_RANGE(10), 139 UNI_RANGE(10), 140 UNI_RANGE(5), 141 UNI_RANGE(2.5), 142 UNI_RANGE(1.25) 143 } 144}; 145 146static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 147 0x10, 0x11, 0x12, 0x13 }; 148 149static const struct comedi_lrange range_pci1710hg = { 12, { 150 BIP_RANGE(5), 151 BIP_RANGE(0.5), 152 BIP_RANGE(0.05), 153 BIP_RANGE(0.005), 154 BIP_RANGE(10), 155 BIP_RANGE(1), 156 BIP_RANGE(0.1), 157 BIP_RANGE(0.01), 158 UNI_RANGE(10), 159 UNI_RANGE(1), 160 UNI_RANGE(0.1), 161 UNI_RANGE(0.01) 162 } 163}; 164 165static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 166 0x05, 0x06, 0x07, 0x10, 0x11, 167 0x12, 0x13 }; 168 169static const struct comedi_lrange range_pci17x1 = { 5, { 170 BIP_RANGE(10), 171 BIP_RANGE(5), 172 BIP_RANGE(2.5), 173 BIP_RANGE(1.25), 174 BIP_RANGE(0.625) 175 } 176}; 177 178static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; 179 180static const struct comedi_lrange range_pci1720 = { 4, { 181 UNI_RANGE(5), 182 UNI_RANGE(10), 183 BIP_RANGE(5), 184 BIP_RANGE(10) 185 } 186}; 187 188static const struct comedi_lrange range_pci171x_da = { 2, { 189 UNI_RANGE(5), 190 UNI_RANGE(10), 191 } 192}; 193 194static int pci1710_attach(struct comedi_device *dev, 195 struct comedi_devconfig *it); 196static int pci1710_detach(struct comedi_device *dev); 197 198struct boardtype { 199 const char *name; /* board name */ 200 int device_id; 201 int iorange; /* I/O range len */ 202 char have_irq; /* 1=card support IRQ */ 203 char cardtype; /* 0=1710& co. 2=1713, ... */ 204 int n_aichan; /* num of A/D chans */ 205 int n_aichand; /* num of A/D chans in diff mode */ 206 int n_aochan; /* num of D/A chans */ 207 int n_dichan; /* num of DI chans */ 208 int n_dochan; /* num of DO chans */ 209 int n_counter; /* num of counters */ 210 int ai_maxdata; /* resolution of A/D */ 211 int ao_maxdata; /* resolution of D/A */ 212 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ 213 const char *rangecode_ai; /* range codes for programming */ 214 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ 215 unsigned int ai_ns_min; /* max sample speed of card v ns */ 216 unsigned int fifo_half_size; /* size of FIFO/2 */ 217}; 218 219static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = { 220 { 221 PCI_VENDOR_ID_ADVANTECH, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 222 PCI_VENDOR_ID_ADVANTECH, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 223 PCI_VENDOR_ID_ADVANTECH, 0x1713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 224 PCI_VENDOR_ID_ADVANTECH, 0x1720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 225 PCI_VENDOR_ID_ADVANTECH, 0x1731, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 226 0} 227}; 228 229MODULE_DEVICE_TABLE(pci, pci1710_pci_table); 230 231static const struct boardtype boardtypes[] = { 232 {"pci1710", 0x1710, 233 IORANGE_171x, 1, TYPE_PCI171X, 234 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, 235 &range_pci1710_3, range_codes_pci1710_3, 236 &range_pci171x_da, 237 10000, 2048}, 238 {"pci1710hg", 0x1710, 239 IORANGE_171x, 1, TYPE_PCI171X, 240 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, 241 &range_pci1710hg, range_codes_pci1710hg, 242 &range_pci171x_da, 243 10000, 2048}, 244 {"pci1711", 0x1711, 245 IORANGE_171x, 1, TYPE_PCI171X, 246 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff, 247 &range_pci17x1, range_codes_pci17x1, &range_pci171x_da, 248 10000, 512}, 249 {"pci1713", 0x1713, 250 IORANGE_171x, 1, TYPE_PCI1713, 251 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000, 252 &range_pci1710_3, range_codes_pci1710_3, NULL, 253 10000, 2048}, 254 {"pci1720", 0x1720, 255 IORANGE_1720, 0, TYPE_PCI1720, 256 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff, 257 NULL, NULL, &range_pci1720, 258 0, 0}, 259 {"pci1731", 0x1731, 260 IORANGE_171x, 1, TYPE_PCI171X, 261 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000, 262 &range_pci17x1, range_codes_pci17x1, NULL, 263 10000, 512}, 264 /* dummy entry corresponding to driver name */ 265 {.name = DRV_NAME}, 266}; 267 268#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) 269 270static struct comedi_driver driver_pci1710 = { 271 .driver_name = DRV_NAME, 272 .module = THIS_MODULE, 273 .attach = pci1710_attach, 274 .detach = pci1710_detach, 275 .num_names = n_boardtypes, 276 .board_name = &boardtypes[0].name, 277 .offset = sizeof(struct boardtype), 278}; 279 280struct pci1710_private { 281 struct pci_dev *pcidev; /* ptr to PCI device */ 282 char valid; /* card is usable */ 283 char neverending_ai; /* we do unlimited AI */ 284 unsigned int CntrlReg; /* Control register */ 285 unsigned int i8254_osc_base; /* frequence of onboard oscilator */ 286 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */ 287 unsigned int ai_act_scan; /* how many scans we finished */ 288 unsigned int ai_act_chan; /* actual position in actual scan */ 289 unsigned int ai_buf_ptr; /* data buffer ptr in samples */ 290 unsigned char ai_eos; /* 1=EOS wake up */ 291 unsigned char ai_et; 292 unsigned int ai_et_CntrlReg; 293 unsigned int ai_et_MuxVal; 294 unsigned int ai_et_div1, ai_et_div2; 295 unsigned int act_chanlist[32]; /* list of scaned channel */ 296 unsigned char act_chanlist_len; /* len of scanlist */ 297 unsigned char act_chanlist_pos; /* actual position in MUX list */ 298 unsigned char da_ranges; /* copy of D/A outpit range register */ 299 unsigned int ai_scans; /* len of scanlist */ 300 unsigned int ai_n_chan; /* how many channels is measured */ 301 unsigned int *ai_chanlist; /* actaul chanlist */ 302 unsigned int ai_flags; /* flaglist */ 303 unsigned int ai_data_len; /* len of data buffer */ 304 short *ai_data; /* data buffer */ 305 unsigned int ai_timer1; /* timers */ 306 unsigned int ai_timer2; 307 short ao_data[4]; /* data output buffer */ 308 unsigned int cnt0_write_wait; /* after a write, wait for update of the 309 * internal state */ 310}; 311 312#define devpriv ((struct pci1710_private *)dev->private) 313#define this_board ((const struct boardtype *)dev->board_ptr) 314 315/* 316============================================================================== 317*/ 318 319static int check_channel_list(struct comedi_device *dev, 320 struct comedi_subdevice *s, 321 unsigned int *chanlist, unsigned int n_chan); 322static void setup_channel_list(struct comedi_device *dev, 323 struct comedi_subdevice *s, 324 unsigned int *chanlist, unsigned int n_chan, 325 unsigned int seglen); 326static void start_pacer(struct comedi_device *dev, int mode, 327 unsigned int divisor1, unsigned int divisor2); 328static int pci1710_reset(struct comedi_device *dev); 329static int pci171x_ai_cancel(struct comedi_device *dev, 330 struct comedi_subdevice *s); 331 332/* used for gain list programming */ 333static const unsigned int muxonechan[] = { 334 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, 335 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 336 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, 337 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f 338}; 339 340/* 341============================================================================== 342*/ 343static int pci171x_insn_read_ai(struct comedi_device *dev, 344 struct comedi_subdevice *s, 345 struct comedi_insn *insn, unsigned int *data) 346{ 347 int n, timeout; 348#ifdef PCI171x_PARANOIDCHECK 349 unsigned int idata; 350#endif 351 352 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n"); 353 devpriv->CntrlReg &= Control_CNT0; 354 devpriv->CntrlReg |= Control_SW; /* set software trigger */ 355 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 356 outb(0, dev->iobase + PCI171x_CLRFIFO); 357 outb(0, dev->iobase + PCI171x_CLRINT); 358 359 setup_channel_list(dev, s, &insn->chanspec, 1, 1); 360 361 DPRINTK("adv_pci1710 A ST=%4x IO=%x\n", 362 inw(dev->iobase + PCI171x_STATUS), 363 dev->iobase + PCI171x_STATUS); 364 for (n = 0; n < insn->n; n++) { 365 outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ 366 DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n, 367 inw(dev->iobase + PCI171x_STATUS)); 368 /* udelay(1); */ 369 DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n, 370 inw(dev->iobase + PCI171x_STATUS)); 371 timeout = 100; 372 while (timeout--) { 373 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE)) 374 goto conv_finish; 375 if (!(timeout % 10)) 376 DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n, 377 timeout, 378 inw(dev->iobase + PCI171x_STATUS)); 379 } 380 comedi_error(dev, "A/D insn timeout"); 381 outb(0, dev->iobase + PCI171x_CLRFIFO); 382 outb(0, dev->iobase + PCI171x_CLRINT); 383 data[n] = 0; 384 DPRINTK 385 ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", 386 n); 387 return -ETIME; 388 389conv_finish: 390#ifdef PCI171x_PARANOIDCHECK 391 idata = inw(dev->iobase + PCI171x_AD_DATA); 392 if (this_board->cardtype != TYPE_PCI1713) 393 if ((idata & 0xf000) != devpriv->act_chanlist[0]) { 394 comedi_error(dev, "A/D insn data droput!"); 395 return -ETIME; 396 } 397 data[n] = idata & 0x0fff; 398#else 399 data[n] = inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff; 400#endif 401 402 } 403 404 outb(0, dev->iobase + PCI171x_CLRFIFO); 405 outb(0, dev->iobase + PCI171x_CLRINT); 406 407 DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n); 408 return n; 409} 410 411/* 412============================================================================== 413*/ 414static int pci171x_insn_write_ao(struct comedi_device *dev, 415 struct comedi_subdevice *s, 416 struct comedi_insn *insn, unsigned int *data) 417{ 418 int n, chan, range, ofs; 419 420 chan = CR_CHAN(insn->chanspec); 421 range = CR_RANGE(insn->chanspec); 422 if (chan) { 423 devpriv->da_ranges &= 0xfb; 424 devpriv->da_ranges |= (range << 2); 425 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); 426 ofs = PCI171x_DA2; 427 } else { 428 devpriv->da_ranges &= 0xfe; 429 devpriv->da_ranges |= range; 430 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); 431 ofs = PCI171x_DA1; 432 } 433 434 for (n = 0; n < insn->n; n++) 435 outw(data[n], dev->iobase + ofs); 436 437 devpriv->ao_data[chan] = data[n]; 438 439 return n; 440 441} 442 443/* 444============================================================================== 445*/ 446static int pci171x_insn_read_ao(struct comedi_device *dev, 447 struct comedi_subdevice *s, 448 struct comedi_insn *insn, unsigned int *data) 449{ 450 int n, chan; 451 452 chan = CR_CHAN(insn->chanspec); 453 for (n = 0; n < insn->n; n++) 454 data[n] = devpriv->ao_data[chan]; 455 456 return n; 457} 458 459/* 460============================================================================== 461*/ 462static int pci171x_insn_bits_di(struct comedi_device *dev, 463 struct comedi_subdevice *s, 464 struct comedi_insn *insn, unsigned int *data) 465{ 466 data[1] = inw(dev->iobase + PCI171x_DI); 467 468 return 2; 469} 470 471/* 472============================================================================== 473*/ 474static int pci171x_insn_bits_do(struct comedi_device *dev, 475 struct comedi_subdevice *s, 476 struct comedi_insn *insn, unsigned int *data) 477{ 478 if (data[0]) { 479 s->state &= ~data[0]; 480 s->state |= (data[0] & data[1]); 481 outw(s->state, dev->iobase + PCI171x_DO); 482 } 483 data[1] = s->state; 484 485 return 2; 486} 487 488/* 489============================================================================== 490*/ 491static int pci171x_insn_counter_read(struct comedi_device *dev, 492 struct comedi_subdevice *s, 493 struct comedi_insn *insn, 494 unsigned int *data) 495{ 496 unsigned int msb, lsb, ccntrl; 497 int i; 498 499 ccntrl = 0xD2; /* count only */ 500 for (i = 0; i < insn->n; i++) { 501 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); 502 503 lsb = inw(dev->iobase + PCI171x_CNT0) & 0xFF; 504 msb = inw(dev->iobase + PCI171x_CNT0) & 0xFF; 505 506 data[0] = lsb | (msb << 8); 507 } 508 509 return insn->n; 510} 511 512/* 513============================================================================== 514*/ 515static int pci171x_insn_counter_write(struct comedi_device *dev, 516 struct comedi_subdevice *s, 517 struct comedi_insn *insn, 518 unsigned int *data) 519{ 520 uint msb, lsb, ccntrl, status; 521 522 lsb = data[0] & 0x00FF; 523 msb = (data[0] & 0xFF00) >> 8; 524 525 /* write lsb, then msb */ 526 outw(lsb, dev->iobase + PCI171x_CNT0); 527 outw(msb, dev->iobase + PCI171x_CNT0); 528 529 if (devpriv->cnt0_write_wait) { 530 /* wait for the new count to be loaded */ 531 ccntrl = 0xE2; 532 do { 533 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); 534 status = inw(dev->iobase + PCI171x_CNT0) & 0xFF; 535 } while (status & 0x40); 536 } 537 538 return insn->n; 539} 540 541/* 542============================================================================== 543*/ 544static int pci171x_insn_counter_config(struct comedi_device *dev, 545 struct comedi_subdevice *s, 546 struct comedi_insn *insn, 547 unsigned int *data) 548{ 549#ifdef unused 550 /* This doesn't work like a normal Comedi counter config */ 551 uint ccntrl = 0; 552 553 devpriv->cnt0_write_wait = data[0] & 0x20; 554 555 /* internal or external clock? */ 556 if (!(data[0] & 0x10)) { /* internal */ 557 devpriv->CntrlReg &= ~Control_CNT0; 558 } else { 559 devpriv->CntrlReg |= Control_CNT0; 560 } 561 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 562 563 if (data[0] & 0x01) 564 ccntrl |= Counter_M0; 565 if (data[0] & 0x02) 566 ccntrl |= Counter_M1; 567 if (data[0] & 0x04) 568 ccntrl |= Counter_M2; 569 if (data[0] & 0x08) 570 ccntrl |= Counter_BCD; 571 ccntrl |= Counter_RW0; /* set read/write mode */ 572 ccntrl |= Counter_RW1; 573 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); 574#endif 575 576 return 1; 577} 578 579/* 580============================================================================== 581*/ 582static int pci1720_insn_write_ao(struct comedi_device *dev, 583 struct comedi_subdevice *s, 584 struct comedi_insn *insn, unsigned int *data) 585{ 586 int n, rangereg, chan; 587 588 chan = CR_CHAN(insn->chanspec); 589 rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1))); 590 rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1)); 591 if (rangereg != devpriv->da_ranges) { 592 outb(rangereg, dev->iobase + PCI1720_RANGE); 593 devpriv->da_ranges = rangereg; 594 } 595 596 for (n = 0; n < insn->n; n++) { 597 outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1)); 598 outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ 599 } 600 601 devpriv->ao_data[chan] = data[n]; 602 603 return n; 604} 605 606/* 607============================================================================== 608*/ 609static void interrupt_pci1710_every_sample(void *d) 610{ 611 struct comedi_device *dev = d; 612 struct comedi_subdevice *s = dev->subdevices + 0; 613 int m; 614#ifdef PCI171x_PARANOIDCHECK 615 short sampl; 616#endif 617 618 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n"); 619 m = inw(dev->iobase + PCI171x_STATUS); 620 if (m & Status_FE) { 621 printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); 622 pci171x_ai_cancel(dev, s); 623 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 624 comedi_event(dev, s); 625 return; 626 } 627 if (m & Status_FF) { 628 printk 629 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", 630 dev->minor, m); 631 pci171x_ai_cancel(dev, s); 632 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 633 comedi_event(dev, s); 634 return; 635 } 636 637 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ 638 639 DPRINTK("FOR "); 640 for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { 641#ifdef PCI171x_PARANOIDCHECK 642 sampl = inw(dev->iobase + PCI171x_AD_DATA); 643 DPRINTK("%04x:", sampl); 644 if (this_board->cardtype != TYPE_PCI1713) 645 if ((sampl & 0xf000) != 646 devpriv->act_chanlist[s->async->cur_chan]) { 647 printk 648 ("comedi: A/D data dropout: received data from channel %d, expected %d!\n", 649 (sampl & 0xf000) >> 12, 650 (devpriv-> 651 act_chanlist[s-> 652 async->cur_chan] & 0xf000) >> 653 12); 654 pci171x_ai_cancel(dev, s); 655 s->async->events |= 656 COMEDI_CB_EOA | COMEDI_CB_ERROR; 657 comedi_event(dev, s); 658 return; 659 } 660 DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr, 661 s->async->cur_chan, s->async->buf_int_count); 662 comedi_buf_put(s->async, sampl & 0x0fff); 663#else 664 comedi_buf_put(s->async, 665 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); 666#endif 667 ++s->async->cur_chan; 668 669 if (s->async->cur_chan >= devpriv->ai_n_chan) 670 s->async->cur_chan = 0; 671 672 673 if (s->async->cur_chan == 0) { /* one scan done */ 674 devpriv->ai_act_scan++; 675 DPRINTK 676 ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n", 677 s->async->buf_int_count, s->async->buf_int_ptr, 678 s->async->buf_user_count, s->async->buf_user_ptr); 679 DPRINTK("adv_pci1710 EDBG: EOS2\n"); 680 if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { /* all data sampled */ 681 pci171x_ai_cancel(dev, s); 682 s->async->events |= COMEDI_CB_EOA; 683 comedi_event(dev, s); 684 return; 685 } 686 } 687 } 688 689 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ 690 DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n"); 691 692 comedi_event(dev, s); 693} 694 695/* 696============================================================================== 697*/ 698static int move_block_from_fifo(struct comedi_device *dev, 699 struct comedi_subdevice *s, int n, int turn) 700{ 701 int i, j; 702#ifdef PCI171x_PARANOIDCHECK 703 int sampl; 704#endif 705 DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n, 706 turn); 707 j = s->async->cur_chan; 708 for (i = 0; i < n; i++) { 709#ifdef PCI171x_PARANOIDCHECK 710 sampl = inw(dev->iobase + PCI171x_AD_DATA); 711 if (this_board->cardtype != TYPE_PCI1713) 712 if ((sampl & 0xf000) != devpriv->act_chanlist[j]) { 713 printk 714 ("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", 715 dev->minor, (sampl & 0xf000) >> 12, 716 (devpriv->act_chanlist[j] & 0xf000) >> 12, 717 i, j, devpriv->ai_act_scan, n, turn, 718 sampl); 719 pci171x_ai_cancel(dev, s); 720 s->async->events |= 721 COMEDI_CB_EOA | COMEDI_CB_ERROR; 722 comedi_event(dev, s); 723 return 1; 724 } 725 comedi_buf_put(s->async, sampl & 0x0fff); 726#else 727 comedi_buf_put(s->async, 728 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); 729#endif 730 j++; 731 if (j >= devpriv->ai_n_chan) { 732 j = 0; 733 devpriv->ai_act_scan++; 734 } 735 } 736 s->async->cur_chan = j; 737 DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n"); 738 return 0; 739} 740 741/* 742============================================================================== 743*/ 744static void interrupt_pci1710_half_fifo(void *d) 745{ 746 struct comedi_device *dev = d; 747 struct comedi_subdevice *s = dev->subdevices + 0; 748 int m, samplesinbuf; 749 750 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n"); 751 m = inw(dev->iobase + PCI171x_STATUS); 752 if (!(m & Status_FH)) { 753 printk("comedi%d: A/D FIFO not half full! (%4x)\n", 754 dev->minor, m); 755 pci171x_ai_cancel(dev, s); 756 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 757 comedi_event(dev, s); 758 return; 759 } 760 if (m & Status_FF) { 761 printk 762 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", 763 dev->minor, m); 764 pci171x_ai_cancel(dev, s); 765 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 766 comedi_event(dev, s); 767 return; 768 } 769 770 samplesinbuf = this_board->fifo_half_size; 771 if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) { 772 m = devpriv->ai_data_len / sizeof(short); 773 if (move_block_from_fifo(dev, s, m, 0)) 774 return; 775 samplesinbuf -= m; 776 } 777 778 if (samplesinbuf) { 779 if (move_block_from_fifo(dev, s, samplesinbuf, 1)) 780 return; 781 } 782 783 if (!devpriv->neverending_ai) 784 if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data 785 sampled */ 786 pci171x_ai_cancel(dev, s); 787 s->async->events |= COMEDI_CB_EOA; 788 comedi_event(dev, s); 789 return; 790 } 791 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ 792 DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n"); 793 794 comedi_event(dev, s); 795} 796 797/* 798============================================================================== 799*/ 800static irqreturn_t interrupt_service_pci1710(int irq, void *d) 801{ 802 struct comedi_device *dev = d; 803 804 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n", 805 irq); 806 if (!dev->attached) /* is device attached? */ 807 return IRQ_NONE; /* no, exit */ 808 809 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) /* is this interrupt from our board? */ 810 return IRQ_NONE; /* no, exit */ 811 812 DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n", 813 inw(dev->iobase + PCI171x_STATUS)); 814 815 if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */ 816 devpriv->ai_et = 0; 817 devpriv->CntrlReg &= Control_CNT0; 818 devpriv->CntrlReg |= Control_SW; /* set software trigger */ 819 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 820 devpriv->CntrlReg = devpriv->ai_et_CntrlReg; 821 outb(0, dev->iobase + PCI171x_CLRFIFO); 822 outb(0, dev->iobase + PCI171x_CLRINT); 823 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); 824 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 825 /* start pacer */ 826 start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2); 827 return IRQ_HANDLED; 828 } 829 if (devpriv->ai_eos) { /* We use FIFO half full INT or not? */ 830 interrupt_pci1710_every_sample(d); 831 } else { 832 interrupt_pci1710_half_fifo(d); 833 } 834 DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n"); 835 return IRQ_HANDLED; 836} 837 838/* 839============================================================================== 840*/ 841static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, 842 struct comedi_subdevice *s) 843{ 844 unsigned int divisor1 = 0, divisor2 = 0; 845 unsigned int seglen; 846 847 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n", 848 mode); 849 start_pacer(dev, -1, 0, 0); /* stop pacer */ 850 851 seglen = check_channel_list(dev, s, devpriv->ai_chanlist, 852 devpriv->ai_n_chan); 853 if (seglen < 1) 854 return -EINVAL; 855 setup_channel_list(dev, s, devpriv->ai_chanlist, 856 devpriv->ai_n_chan, seglen); 857 858 outb(0, dev->iobase + PCI171x_CLRFIFO); 859 outb(0, dev->iobase + PCI171x_CLRINT); 860 861 devpriv->ai_do = mode; 862 863 devpriv->ai_act_scan = 0; 864 s->async->cur_chan = 0; 865 devpriv->ai_buf_ptr = 0; 866 devpriv->neverending_ai = 0; 867 868 devpriv->CntrlReg &= Control_CNT0; 869 if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { /* don't we want wake up every scan? devpriv->ai_eos=1; */ 870 devpriv->ai_eos = 1; 871 } else { 872 devpriv->CntrlReg |= Control_ONEFH; 873 devpriv->ai_eos = 0; 874 } 875 876 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) 877 devpriv->neverending_ai = 1; 878 /* well, user want neverending */ 879 else 880 devpriv->neverending_ai = 0; 881 882 switch (mode) { 883 case 1: 884 case 2: 885 if (devpriv->ai_timer1 < this_board->ai_ns_min) 886 devpriv->ai_timer1 = this_board->ai_ns_min; 887 devpriv->CntrlReg |= Control_PACER | Control_IRQEN; 888 if (mode == 2) { 889 devpriv->ai_et_CntrlReg = devpriv->CntrlReg; 890 devpriv->CntrlReg &= 891 ~(Control_PACER | Control_ONEFH | Control_GATE); 892 devpriv->CntrlReg |= Control_EXT; 893 devpriv->ai_et = 1; 894 } else { 895 devpriv->ai_et = 0; 896 } 897 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, 898 &divisor2, &devpriv->ai_timer1, 899 devpriv->ai_flags & TRIG_ROUND_MASK); 900 DPRINTK 901 ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n", 902 devpriv->i8254_osc_base, divisor1, divisor2, 903 devpriv->ai_timer1); 904 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 905 if (mode != 2) { 906 /* start pacer */ 907 start_pacer(dev, mode, divisor1, divisor2); 908 } else { 909 devpriv->ai_et_div1 = divisor1; 910 devpriv->ai_et_div2 = divisor2; 911 } 912 break; 913 case 3: 914 devpriv->CntrlReg |= Control_EXT | Control_IRQEN; 915 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); 916 break; 917 } 918 919 DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n"); 920 return 0; 921} 922 923#ifdef PCI171X_EXTDEBUG 924/* 925============================================================================== 926*/ 927static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd) 928{ 929 printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, 930 cmd->start_src, cmd->scan_begin_src, cmd->convert_src); 931 printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e, 932 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); 933 printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, 934 cmd->scan_end_src); 935 printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", 936 e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); 937} 938#endif 939 940/* 941============================================================================== 942*/ 943static int pci171x_ai_cmdtest(struct comedi_device *dev, 944 struct comedi_subdevice *s, 945 struct comedi_cmd *cmd) 946{ 947 int err = 0; 948 int tmp; 949 unsigned int divisor1 = 0, divisor2 = 0; 950 951 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n"); 952#ifdef PCI171X_EXTDEBUG 953 pci171x_cmdtest_out(-1, cmd); 954#endif 955 /* step 1: make sure trigger sources are trivially valid */ 956 957 tmp = cmd->start_src; 958 cmd->start_src &= TRIG_NOW | TRIG_EXT; 959 if (!cmd->start_src || tmp != cmd->start_src) 960 err++; 961 962 tmp = cmd->scan_begin_src; 963 cmd->scan_begin_src &= TRIG_FOLLOW; 964 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 965 err++; 966 967 tmp = cmd->convert_src; 968 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 969 if (!cmd->convert_src || tmp != cmd->convert_src) 970 err++; 971 972 tmp = cmd->scan_end_src; 973 cmd->scan_end_src &= TRIG_COUNT; 974 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 975 err++; 976 977 tmp = cmd->stop_src; 978 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 979 if (!cmd->stop_src || tmp != cmd->stop_src) 980 err++; 981 982 if (err) { 983#ifdef PCI171X_EXTDEBUG 984 pci171x_cmdtest_out(1, cmd); 985#endif 986 DPRINTK 987 ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n", 988 err); 989 return 1; 990 } 991 992 /* step 2: make sure trigger sources are unique and mutually compatible */ 993 994 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { 995 cmd->start_src = TRIG_NOW; 996 err++; 997 } 998 999 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1000 cmd->scan_begin_src = TRIG_FOLLOW; 1001 err++; 1002 } 1003 1004 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 1005 err++; 1006 1007 if (cmd->scan_end_src != TRIG_COUNT) { 1008 cmd->scan_end_src = TRIG_COUNT; 1009 err++; 1010 } 1011 1012 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) 1013 err++; 1014 1015 if (err) { 1016#ifdef PCI171X_EXTDEBUG 1017 pci171x_cmdtest_out(2, cmd); 1018#endif 1019 DPRINTK 1020 ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n", 1021 err); 1022 return 2; 1023 } 1024 1025 /* step 3: make sure arguments are trivially compatible */ 1026 1027 if (cmd->start_arg != 0) { 1028 cmd->start_arg = 0; 1029 err++; 1030 } 1031 1032 if (cmd->scan_begin_arg != 0) { 1033 cmd->scan_begin_arg = 0; 1034 err++; 1035 } 1036 1037 if (cmd->convert_src == TRIG_TIMER) { 1038 if (cmd->convert_arg < this_board->ai_ns_min) { 1039 cmd->convert_arg = this_board->ai_ns_min; 1040 err++; 1041 } 1042 } else { /* TRIG_FOLLOW */ 1043 if (cmd->convert_arg != 0) { 1044 cmd->convert_arg = 0; 1045 err++; 1046 } 1047 } 1048 1049 if (cmd->scan_end_arg != cmd->chanlist_len) { 1050 cmd->scan_end_arg = cmd->chanlist_len; 1051 err++; 1052 } 1053 if (cmd->stop_src == TRIG_COUNT) { 1054 if (!cmd->stop_arg) { 1055 cmd->stop_arg = 1; 1056 err++; 1057 } 1058 } else { /* TRIG_NONE */ 1059 if (cmd->stop_arg != 0) { 1060 cmd->stop_arg = 0; 1061 err++; 1062 } 1063 } 1064 1065 if (err) { 1066#ifdef PCI171X_EXTDEBUG 1067 pci171x_cmdtest_out(3, cmd); 1068#endif 1069 DPRINTK 1070 ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n", 1071 err); 1072 return 3; 1073 } 1074 1075 /* step 4: fix up any arguments */ 1076 1077 if (cmd->convert_src == TRIG_TIMER) { 1078 tmp = cmd->convert_arg; 1079 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, 1080 &divisor2, &cmd->convert_arg, 1081 cmd->flags & TRIG_ROUND_MASK); 1082 if (cmd->convert_arg < this_board->ai_ns_min) 1083 cmd->convert_arg = this_board->ai_ns_min; 1084 if (tmp != cmd->convert_arg) 1085 err++; 1086 } 1087 1088 if (err) { 1089 DPRINTK 1090 ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n", 1091 err); 1092 return 4; 1093 } 1094 1095 /* step 5: complain about special chanlist considerations */ 1096 1097 if (cmd->chanlist) { 1098 if (!check_channel_list(dev, s, cmd->chanlist, 1099 cmd->chanlist_len)) 1100 return 5; /* incorrect channels list */ 1101 } 1102 1103 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n"); 1104 return 0; 1105} 1106 1107/* 1108============================================================================== 1109*/ 1110static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1111{ 1112 struct comedi_cmd *cmd = &s->async->cmd; 1113 1114 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n"); 1115 devpriv->ai_n_chan = cmd->chanlist_len; 1116 devpriv->ai_chanlist = cmd->chanlist; 1117 devpriv->ai_flags = cmd->flags; 1118 devpriv->ai_data_len = s->async->prealloc_bufsz; 1119 devpriv->ai_data = s->async->prealloc_buf; 1120 devpriv->ai_timer1 = 0; 1121 devpriv->ai_timer2 = 0; 1122 1123 if (cmd->stop_src == TRIG_COUNT) 1124 devpriv->ai_scans = cmd->stop_arg; 1125 else 1126 devpriv->ai_scans = 0; 1127 1128 1129 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 2, 3 */ 1130 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 and 2 */ 1131 devpriv->ai_timer1 = cmd->convert_arg; 1132 return pci171x_ai_docmd_and_mode(cmd->start_src == 1133 TRIG_EXT ? 2 : 1, dev, 1134 s); 1135 } 1136 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ 1137 return pci171x_ai_docmd_and_mode(3, dev, s); 1138 } 1139 } 1140 1141 return -1; 1142} 1143 1144/* 1145============================================================================== 1146 Check if channel list from user is builded correctly 1147 If it's ok, then program scan/gain logic. 1148 This works for all cards. 1149*/ 1150static int check_channel_list(struct comedi_device *dev, 1151 struct comedi_subdevice *s, 1152 unsigned int *chanlist, unsigned int n_chan) 1153{ 1154 unsigned int chansegment[32]; 1155 unsigned int i, nowmustbechan, seglen, segpos; 1156 1157 DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan); 1158 /* correct channel and range number check itself comedi/range.c */ 1159 if (n_chan < 1) { 1160 comedi_error(dev, "range/channel list is empty!"); 1161 return 0; 1162 } 1163 1164 if (n_chan > 1) { 1165 chansegment[0] = chanlist[0]; /* first channel is everytime ok */ 1166 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { /* build part of chanlist */ 1167 /* printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */ 1168 if (chanlist[0] == chanlist[i]) 1169 break; /* we detect loop, this must by finish */ 1170 if (CR_CHAN(chanlist[i]) & 1) /* odd channel cann't by differencial */ 1171 if (CR_AREF(chanlist[i]) == AREF_DIFF) { 1172 comedi_error(dev, 1173 "Odd channel can't be differential input!\n"); 1174 return 0; 1175 } 1176 nowmustbechan = 1177 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; 1178 if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) 1179 nowmustbechan = (nowmustbechan + 1) % s->n_chan; 1180 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */ 1181 printk 1182 ("channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", 1183 i, CR_CHAN(chanlist[i]), nowmustbechan, 1184 CR_CHAN(chanlist[0])); 1185 return 0; 1186 } 1187 chansegment[i] = chanlist[i]; /* well, this is next correct channel in list */ 1188 } 1189 1190 for (i = 0, segpos = 0; i < n_chan; i++) { /* check whole chanlist */ 1191 /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */ 1192 if (chanlist[i] != chansegment[i % seglen]) { 1193 printk 1194 ("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", 1195 i, CR_CHAN(chansegment[i]), 1196 CR_RANGE(chansegment[i]), 1197 CR_AREF(chansegment[i]), 1198 CR_CHAN(chanlist[i % seglen]), 1199 CR_RANGE(chanlist[i % seglen]), 1200 CR_AREF(chansegment[i % seglen])); 1201 return 0; /* chan/gain list is strange */ 1202 } 1203 } 1204 } else { 1205 seglen = 1; 1206 } 1207 return seglen; 1208} 1209 1210static void setup_channel_list(struct comedi_device *dev, 1211 struct comedi_subdevice *s, 1212 unsigned int *chanlist, unsigned int n_chan, 1213 unsigned int seglen) 1214{ 1215 unsigned int i, range, chanprog; 1216 1217 DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan, 1218 seglen); 1219 devpriv->act_chanlist_len = seglen; 1220 devpriv->act_chanlist_pos = 0; 1221 1222 DPRINTK("SegLen: %d\n", seglen); 1223 for (i = 0; i < seglen; i++) { /* store range list to card */ 1224 chanprog = muxonechan[CR_CHAN(chanlist[i])]; 1225 outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ 1226 range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; 1227 if (CR_AREF(chanlist[i]) == AREF_DIFF) 1228 range |= 0x0020; 1229 outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ 1230#ifdef PCI171x_PARANOIDCHECK 1231 devpriv->act_chanlist[i] = 1232 (CR_CHAN(chanlist[i]) << 12) & 0xf000; 1233#endif 1234 DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, 1235 devpriv->act_chanlist[i]); 1236 } 1237#ifdef PCI171x_PARANOIDCHECK 1238 for ( ; i < n_chan; i++) { /* store remainder of channel list */ 1239 devpriv->act_chanlist[i] = 1240 (CR_CHAN(chanlist[i]) << 12) & 0xf000; 1241 } 1242#endif 1243 1244 devpriv->ai_et_MuxVal = 1245 CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); 1246 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); /* select channel interval to scan */ 1247 DPRINTK("MUX: %4x L%4x.H%4x\n", 1248 CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8), 1249 CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1])); 1250} 1251 1252/* 1253============================================================================== 1254*/ 1255static void start_pacer(struct comedi_device *dev, int mode, 1256 unsigned int divisor1, unsigned int divisor2) 1257{ 1258 DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, 1259 divisor1, divisor2); 1260 outw(0xb4, dev->iobase + PCI171x_CNTCTRL); 1261 outw(0x74, dev->iobase + PCI171x_CNTCTRL); 1262 1263 if (mode == 1) { 1264 outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); 1265 outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); 1266 outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); 1267 outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); 1268 } 1269 DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n"); 1270} 1271 1272/* 1273============================================================================== 1274*/ 1275static int pci171x_ai_cancel(struct comedi_device *dev, 1276 struct comedi_subdevice *s) 1277{ 1278 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n"); 1279 1280 switch (this_board->cardtype) { 1281 default: 1282 devpriv->CntrlReg &= Control_CNT0; 1283 devpriv->CntrlReg |= Control_SW; 1284 1285 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ 1286 start_pacer(dev, -1, 0, 0); 1287 outb(0, dev->iobase + PCI171x_CLRFIFO); 1288 outb(0, dev->iobase + PCI171x_CLRINT); 1289 break; 1290 } 1291 1292 devpriv->ai_do = 0; 1293 devpriv->ai_act_scan = 0; 1294 s->async->cur_chan = 0; 1295 devpriv->ai_buf_ptr = 0; 1296 devpriv->neverending_ai = 0; 1297 1298 DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n"); 1299 return 0; 1300} 1301 1302/* 1303============================================================================== 1304*/ 1305static int pci171x_reset(struct comedi_device *dev) 1306{ 1307 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n"); 1308 outw(0x30, dev->iobase + PCI171x_CNTCTRL); 1309 devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */ 1310 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ 1311 outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ 1312 outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ 1313 start_pacer(dev, -1, 0, 0); /* stop 8254 */ 1314 devpriv->da_ranges = 0; 1315 if (this_board->n_aochan) { 1316 outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); /* set DACs to 0..5V */ 1317 outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ 1318 devpriv->ao_data[0] = 0x0000; 1319 if (this_board->n_aochan > 1) { 1320 outw(0, dev->iobase + PCI171x_DA2); 1321 devpriv->ao_data[1] = 0x0000; 1322 } 1323 } 1324 outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */ 1325 outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ 1326 outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ 1327 1328 DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n"); 1329 return 0; 1330} 1331 1332/* 1333============================================================================== 1334*/ 1335static int pci1720_reset(struct comedi_device *dev) 1336{ 1337 DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n"); 1338 outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */ 1339 devpriv->da_ranges = 0xAA; 1340 outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */ 1341 outw(0x0800, dev->iobase + PCI1720_DA0); /* set outputs to 0V */ 1342 outw(0x0800, dev->iobase + PCI1720_DA1); 1343 outw(0x0800, dev->iobase + PCI1720_DA2); 1344 outw(0x0800, dev->iobase + PCI1720_DA3); 1345 outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ 1346 devpriv->ao_data[0] = 0x0800; 1347 devpriv->ao_data[1] = 0x0800; 1348 devpriv->ao_data[2] = 0x0800; 1349 devpriv->ao_data[3] = 0x0800; 1350 DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n"); 1351 return 0; 1352} 1353 1354/* 1355============================================================================== 1356*/ 1357static int pci1710_reset(struct comedi_device *dev) 1358{ 1359 DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n"); 1360 switch (this_board->cardtype) { 1361 case TYPE_PCI1720: 1362 return pci1720_reset(dev); 1363 default: 1364 return pci171x_reset(dev); 1365 } 1366 DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n"); 1367} 1368 1369/* 1370============================================================================== 1371*/ 1372static int pci1710_attach(struct comedi_device *dev, 1373 struct comedi_devconfig *it) 1374{ 1375 struct comedi_subdevice *s; 1376 int ret, subdev, n_subdevices; 1377 unsigned int irq; 1378 unsigned long iobase; 1379 struct pci_dev *pcidev; 1380 int opt_bus, opt_slot; 1381 const char *errstr; 1382 unsigned char pci_bus, pci_slot, pci_func; 1383 int i; 1384 int board_index; 1385 1386 printk("comedi%d: adv_pci1710: ", dev->minor); 1387 1388 opt_bus = it->options[0]; 1389 opt_slot = it->options[1]; 1390 1391 ret = alloc_private(dev, sizeof(struct pci1710_private)); 1392 if (ret < 0) { 1393 printk(" - Allocation failed!\n"); 1394 return -ENOMEM; 1395 } 1396 1397 /* Look for matching PCI device */ 1398 errstr = "not found!"; 1399 pcidev = NULL; 1400 board_index = this_board - boardtypes; 1401 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH, 1402 PCI_ANY_ID, pcidev))) { 1403 if (strcmp(this_board->name, DRV_NAME) == 0) { 1404 for (i = 0; i < n_boardtypes; ++i) { 1405 if (pcidev->device == boardtypes[i].device_id) { 1406 board_index = i; 1407 break; 1408 } 1409 } 1410 if (i == n_boardtypes) 1411 continue; 1412 } else { 1413 if (pcidev->device != boardtypes[board_index].device_id) 1414 continue; 1415 } 1416 1417 /* Found matching vendor/device. */ 1418 if (opt_bus || opt_slot) { 1419 /* Check bus/slot. */ 1420 if (opt_bus != pcidev->bus->number 1421 || opt_slot != PCI_SLOT(pcidev->devfn)) 1422 continue; /* no match */ 1423 } 1424 /* 1425 * Look for device that isn't in use. 1426 * Enable PCI device and request regions. 1427 */ 1428 if (comedi_pci_enable(pcidev, DRV_NAME)) { 1429 errstr = 1430 "failed to enable PCI device and request regions!"; 1431 continue; 1432 } 1433 /* fixup board_ptr in case we were using the dummy entry with the driver name */ 1434 dev->board_ptr = &boardtypes[board_index]; 1435 break; 1436 } 1437 1438 if (!pcidev) { 1439 if (opt_bus || opt_slot) { 1440 printk(" - Card at b:s %d:%d %s\n", 1441 opt_bus, opt_slot, errstr); 1442 } else { 1443 printk(" - Card %s\n", errstr); 1444 } 1445 return -EIO; 1446 } 1447 1448 pci_bus = pcidev->bus->number; 1449 pci_slot = PCI_SLOT(pcidev->devfn); 1450 pci_func = PCI_FUNC(pcidev->devfn); 1451 irq = pcidev->irq; 1452 iobase = pci_resource_start(pcidev, 2); 1453 1454 printk(", b:s:f=%d:%d:%d, io=0x%4lx", pci_bus, pci_slot, pci_func, 1455 iobase); 1456 1457 dev->iobase = iobase; 1458 1459 dev->board_name = this_board->name; 1460 devpriv->pcidev = pcidev; 1461 1462 n_subdevices = 0; 1463 if (this_board->n_aichan) 1464 n_subdevices++; 1465 if (this_board->n_aochan) 1466 n_subdevices++; 1467 if (this_board->n_dichan) 1468 n_subdevices++; 1469 if (this_board->n_dochan) 1470 n_subdevices++; 1471 if (this_board->n_counter) 1472 n_subdevices++; 1473 1474 ret = alloc_subdevices(dev, n_subdevices); 1475 if (ret < 0) { 1476 printk(" - Allocation failed!\n"); 1477 return ret; 1478 } 1479 1480 pci1710_reset(dev); 1481 1482 if (this_board->have_irq) { 1483 if (irq) { 1484 if (request_irq(irq, interrupt_service_pci1710, 1485 IRQF_SHARED, "Advantech PCI-1710", 1486 dev)) { 1487 printk 1488 (", unable to allocate IRQ %d, DISABLING IT", 1489 irq); 1490 irq = 0; /* Can't use IRQ */ 1491 } else { 1492 printk(", irq=%u", irq); 1493 } 1494 } else { 1495 printk(", IRQ disabled"); 1496 } 1497 } else { 1498 irq = 0; 1499 } 1500 1501 dev->irq = irq; 1502 1503 printk(".\n"); 1504 1505 subdev = 0; 1506 1507 if (this_board->n_aichan) { 1508 s = dev->subdevices + subdev; 1509 dev->read_subdev = s; 1510 s->type = COMEDI_SUBD_AI; 1511 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; 1512 if (this_board->n_aichand) 1513 s->subdev_flags |= SDF_DIFF; 1514 s->n_chan = this_board->n_aichan; 1515 s->maxdata = this_board->ai_maxdata; 1516 s->len_chanlist = this_board->n_aichan; 1517 s->range_table = this_board->rangelist_ai; 1518 s->cancel = pci171x_ai_cancel; 1519 s->insn_read = pci171x_insn_read_ai; 1520 if (irq) { 1521 s->subdev_flags |= SDF_CMD_READ; 1522 s->do_cmdtest = pci171x_ai_cmdtest; 1523 s->do_cmd = pci171x_ai_cmd; 1524 } 1525 devpriv->i8254_osc_base = 100; /* 100ns=10MHz */ 1526 subdev++; 1527 } 1528 1529 if (this_board->n_aochan) { 1530 s = dev->subdevices + subdev; 1531 s->type = COMEDI_SUBD_AO; 1532 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; 1533 s->n_chan = this_board->n_aochan; 1534 s->maxdata = this_board->ao_maxdata; 1535 s->len_chanlist = this_board->n_aochan; 1536 s->range_table = this_board->rangelist_ao; 1537 switch (this_board->cardtype) { 1538 case TYPE_PCI1720: 1539 s->insn_write = pci1720_insn_write_ao; 1540 break; 1541 default: 1542 s->insn_write = pci171x_insn_write_ao; 1543 break; 1544 } 1545 s->insn_read = pci171x_insn_read_ao; 1546 subdev++; 1547 } 1548 1549 if (this_board->n_dichan) { 1550 s = dev->subdevices + subdev; 1551 s->type = COMEDI_SUBD_DI; 1552 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; 1553 s->n_chan = this_board->n_dichan; 1554 s->maxdata = 1; 1555 s->len_chanlist = this_board->n_dichan; 1556 s->range_table = &range_digital; 1557 s->io_bits = 0; /* all bits input */ 1558 s->insn_bits = pci171x_insn_bits_di; 1559 subdev++; 1560 } 1561 1562 if (this_board->n_dochan) { 1563 s = dev->subdevices + subdev; 1564 s->type = COMEDI_SUBD_DO; 1565 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; 1566 s->n_chan = this_board->n_dochan; 1567 s->maxdata = 1; 1568 s->len_chanlist = this_board->n_dochan; 1569 s->range_table = &range_digital; 1570 /* all bits output */ 1571 s->io_bits = (1 << this_board->n_dochan) - 1; 1572 s->state = 0; 1573 s->insn_bits = pci171x_insn_bits_do; 1574 subdev++; 1575 } 1576 1577 if (this_board->n_counter) { 1578 s = dev->subdevices + subdev; 1579 s->type = COMEDI_SUBD_COUNTER; 1580 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 1581 s->n_chan = this_board->n_counter; 1582 s->len_chanlist = this_board->n_counter; 1583 s->maxdata = 0xffff; 1584 s->range_table = &range_unknown; 1585 s->insn_read = pci171x_insn_counter_read; 1586 s->insn_write = pci171x_insn_counter_write; 1587 s->insn_config = pci171x_insn_counter_config; 1588 subdev++; 1589 } 1590 1591 devpriv->valid = 1; 1592 1593 return 0; 1594} 1595 1596/* 1597============================================================================== 1598*/ 1599static int pci1710_detach(struct comedi_device *dev) 1600{ 1601 1602 if (dev->private) { 1603 if (devpriv->valid) 1604 pci1710_reset(dev); 1605 if (dev->irq) 1606 free_irq(dev->irq, dev); 1607 if (devpriv->pcidev) { 1608 if (dev->iobase) 1609 comedi_pci_disable(devpriv->pcidev); 1610 1611 pci_dev_put(devpriv->pcidev); 1612 } 1613 } 1614 1615 return 0; 1616} 1617 1618/* 1619============================================================================== 1620*/ 1621static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev, 1622 const struct pci_device_id *ent) 1623{ 1624 return comedi_pci_auto_config(dev, driver_pci1710.driver_name); 1625} 1626 1627static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev) 1628{ 1629 comedi_pci_auto_unconfig(dev); 1630} 1631 1632static struct pci_driver driver_pci1710_pci_driver = { 1633 .id_table = pci1710_pci_table, 1634 .probe = &driver_pci1710_pci_probe, 1635 .remove = __devexit_p(&driver_pci1710_pci_remove) 1636}; 1637 1638static int __init driver_pci1710_init_module(void) 1639{ 1640 int retval; 1641 1642 retval = comedi_driver_register(&driver_pci1710); 1643 if (retval < 0) 1644 return retval; 1645 1646 driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name; 1647 return pci_register_driver(&driver_pci1710_pci_driver); 1648} 1649 1650static void __exit driver_pci1710_cleanup_module(void) 1651{ 1652 pci_unregister_driver(&driver_pci1710_pci_driver); 1653 comedi_driver_unregister(&driver_pci1710); 1654} 1655 1656module_init(driver_pci1710_init_module); 1657module_exit(driver_pci1710_cleanup_module); 1658/* 1659============================================================================== 1660*/ 1661 1662MODULE_AUTHOR("Comedi http://www.comedi.org"); 1663MODULE_DESCRIPTION("Comedi low-level driver"); 1664MODULE_LICENSE("GPL"); 1665