amplc_pci230.c (78095B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * comedi/drivers/amplc_pci230.c 4 * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. 5 * 6 * Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au> 7 * 8 * COMEDI - Linux Control and Measurement Device Interface 9 * Copyright (C) 2000 David A. Schleef <ds@schleef.org> 10 */ 11 12/* 13 * Driver: amplc_pci230 14 * Description: Amplicon PCI230, PCI260 Multifunction I/O boards 15 * Author: Allan Willcox <allanwillcox@ozemail.com.au>, 16 * Steve D Sharples <steve.sharples@nottingham.ac.uk>, 17 * Ian Abbott <abbotti@mev.co.uk> 18 * Updated: Mon, 01 Sep 2014 10:09:16 +0000 19 * Devices: [Amplicon] PCI230 (amplc_pci230), PCI230+, PCI260, PCI260+ 20 * Status: works 21 * 22 * Configuration options: 23 * none 24 * 25 * Manual configuration of PCI cards is not supported; they are configured 26 * automatically. 27 * 28 * The PCI230+ and PCI260+ have the same PCI device IDs as the PCI230 and 29 * PCI260, but can be distinguished by the size of the PCI regions. A 30 * card will be configured as a "+" model if detected as such. 31 * 32 * Subdevices: 33 * 34 * PCI230(+) PCI260(+) 35 * --------- --------- 36 * Subdevices 3 1 37 * 0 AI AI 38 * 1 AO 39 * 2 DIO 40 * 41 * AI Subdevice: 42 * 43 * The AI subdevice has 16 single-ended channels or 8 differential 44 * channels. 45 * 46 * The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and 47 * PCI260+ cards have 16-bit resolution. 48 * 49 * For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use 50 * inputs 14 and 15 for channel 7). If the card is physically a PCI230 51 * or PCI260 then it actually uses a "pseudo-differential" mode where the 52 * inputs are sampled a few microseconds apart. The PCI230+ and PCI260+ 53 * use true differential sampling. Another difference is that if the 54 * card is physically a PCI230 or PCI260, the inverting input is 2N, 55 * whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a 56 * PCI230 is physically replaced by a PCI230+ (or a PCI260 with a 57 * PCI260+) and differential mode is used, the differential inputs need 58 * to be physically swapped on the connector. 59 * 60 * The following input ranges are supported: 61 * 62 * 0 => [-10, +10] V 63 * 1 => [-5, +5] V 64 * 2 => [-2.5, +2.5] V 65 * 3 => [-1.25, +1.25] V 66 * 4 => [0, 10] V 67 * 5 => [0, 5] V 68 * 6 => [0, 2.5] V 69 * 70 * AI Commands: 71 * 72 * +=========+==============+===========+============+==========+ 73 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | 74 * +=========+==============+===========+============+==========+ 75 * |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE | 76 * |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT| 77 * | | |TRIG_INT | | | 78 * | |--------------|-----------| | | 79 * | | TRIG_TIMER(1)|TRIG_TIMER | | | 80 * | | TRIG_EXT(2) | | | | 81 * | | TRIG_INT | | | | 82 * +---------+--------------+-----------+------------+----------+ 83 * 84 * Note 1: If AI command and AO command are used simultaneously, only 85 * one may have scan_begin_src == TRIG_TIMER. 86 * 87 * Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses 88 * DIO channel 16 (pin 49) which will need to be configured as 89 * a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input 90 * (pin 17) is used instead. For PCI230, scan_begin_src == 91 * TRIG_EXT is not supported. The trigger is a rising edge 92 * on the input. 93 * 94 * Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input 95 * (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The 96 * convert_arg value is interpreted as follows: 97 * 98 * convert_arg == (CR_EDGE | 0) => rising edge 99 * convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge 100 * convert_arg == 0 => falling edge (backwards compatibility) 101 * convert_arg == 1 => rising edge (backwards compatibility) 102 * 103 * All entries in the channel list must use the same analogue reference. 104 * If the analogue reference is not AREF_DIFF (not differential) each 105 * pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same 106 * input range. The input ranges used in the sequence must be all 107 * bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel 108 * sequence must consist of 1 or more identical subsequences. Within the 109 * subsequence, channels must be in ascending order with no repeated 110 * channels. For example, the following sequences are valid: 0 1 2 3 111 * (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid 112 * subsequence), 1 1 1 1 (repeated valid subsequence). The following 113 * sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3 114 * (incompletely repeated subsequence). Some versions of the PCI230+ and 115 * PCI260+ have a bug that requires a subsequence longer than one entry 116 * long to include channel 0. 117 * 118 * AO Subdevice: 119 * 120 * The AO subdevice has 2 channels with 12-bit resolution. 121 * The following output ranges are supported: 122 * 0 => [0, 10] V 123 * 1 => [-10, +10] V 124 * 125 * AO Commands: 126 * 127 * +=========+==============+===========+============+==========+ 128 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | 129 * +=========+==============+===========+============+==========+ 130 * |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE | 131 * | | TRIG_EXT(2) | | |TRIG_COUNT| 132 * | | TRIG_INT | | | | 133 * +---------+--------------+-----------+------------+----------+ 134 * 135 * Note 1: If AI command and AO command are used simultaneously, only 136 * one may have scan_begin_src == TRIG_TIMER. 137 * 138 * Note 2: scan_begin_src == TRIG_EXT is only supported if the card is 139 * configured as a PCI230+ and is only supported on later 140 * versions of the card. As a card configured as a PCI230+ is 141 * not guaranteed to support external triggering, please consider 142 * this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK 143 * input (PCI230+ pin 25). Triggering will be on the rising edge 144 * unless the CR_INVERT flag is set in scan_begin_arg. 145 * 146 * The channels in the channel sequence must be in ascending order with 147 * no repeats. All entries in the channel sequence must use the same 148 * output range. 149 * 150 * DIO Subdevice: 151 * 152 * The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO 153 * channels are configurable as inputs or outputs in four groups: 154 * 155 * Port A - channels 0 to 7 156 * Port B - channels 8 to 15 157 * Port CL - channels 16 to 19 158 * Port CH - channels 20 to 23 159 * 160 * Only mode 0 of the 8255 chip is supported. 161 * 162 * Bit 0 of port C (DIO channel 16) is also used as an external scan 163 * trigger input for AI commands on PCI230 and PCI230+, so would need to 164 * be configured as an input to use it for that purpose. 165 */ 166 167/* 168 * Extra triggered scan functionality, interrupt bug-fix added by Steve 169 * Sharples. Support for PCI230+/260+, more triggered scan functionality, 170 * and workarounds for (or detection of) various hardware problems added 171 * by Ian Abbott. 172 */ 173 174#include <linux/module.h> 175#include <linux/delay.h> 176#include <linux/interrupt.h> 177#include <linux/comedi/comedi_pci.h> 178#include <linux/comedi/comedi_8255.h> 179#include <linux/comedi/comedi_8254.h> 180 181/* 182 * PCI230 PCI configuration register information 183 */ 184#define PCI_DEVICE_ID_PCI230 0x0000 185#define PCI_DEVICE_ID_PCI260 0x0006 186 187/* 188 * PCI230 i/o space 1 registers. 189 */ 190#define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */ 191#define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */ 192#define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */ 193#define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */ 194#define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */ 195#define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */ 196#define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */ 197#define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */ 198#define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */ 199#define PCI230_INT_STAT 0x1E /* Interrupt status (r) */ 200 201/* 202 * PCI230 i/o space 2 registers. 203 */ 204#define PCI230_DACCON 0x00 /* DAC control */ 205#define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */ 206#define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */ 207#define PCI230_ADCDATA 0x08 /* ADC data (r) */ 208#define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */ 209#define PCI230_ADCCON 0x0A /* ADC control */ 210#define PCI230_ADCEN 0x0C /* ADC channel enable bits */ 211#define PCI230_ADCG 0x0E /* ADC gain control bits */ 212/* PCI230+ i/o space 2 additional registers. */ 213#define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */ 214#define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */ 215#define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */ 216#define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */ 217#define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */ 218#define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */ 219#define PCI230P_EXTFUNC 0x1C /* Extended functions */ 220#define PCI230P_HWVER 0x1E /* Hardware version (r) */ 221/* PCI230+ hardware version 2 onwards. */ 222#define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */ 223#define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */ 224#define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */ 225 226/* 227 * DACCON read-write values. 228 */ 229#define PCI230_DAC_OR(x) (((x) & 0x1) << 0) 230#define PCI230_DAC_OR_UNI PCI230_DAC_OR(0) /* Output unipolar */ 231#define PCI230_DAC_OR_BIP PCI230_DAC_OR(1) /* Output bipolar */ 232#define PCI230_DAC_OR_MASK PCI230_DAC_OR(1) 233/* 234 * The following applies only if DAC FIFO support is enabled in the EXTFUNC 235 * register (and only for PCI230+ hardware version 2 onwards). 236 */ 237#define PCI230P2_DAC_FIFO_EN BIT(8) /* FIFO enable */ 238/* 239 * The following apply only if the DAC FIFO is enabled (and only for PCI230+ 240 * hardware version 2 onwards). 241 */ 242#define PCI230P2_DAC_TRIG(x) (((x) & 0x7) << 2) 243#define PCI230P2_DAC_TRIG_NONE PCI230P2_DAC_TRIG(0) /* none */ 244#define PCI230P2_DAC_TRIG_SW PCI230P2_DAC_TRIG(1) /* soft trig */ 245#define PCI230P2_DAC_TRIG_EXTP PCI230P2_DAC_TRIG(2) /* ext + edge */ 246#define PCI230P2_DAC_TRIG_EXTN PCI230P2_DAC_TRIG(3) /* ext - edge */ 247#define PCI230P2_DAC_TRIG_Z2CT0 PCI230P2_DAC_TRIG(4) /* Z2 CT0 out */ 248#define PCI230P2_DAC_TRIG_Z2CT1 PCI230P2_DAC_TRIG(5) /* Z2 CT1 out */ 249#define PCI230P2_DAC_TRIG_Z2CT2 PCI230P2_DAC_TRIG(6) /* Z2 CT2 out */ 250#define PCI230P2_DAC_TRIG_MASK PCI230P2_DAC_TRIG(7) 251#define PCI230P2_DAC_FIFO_WRAP BIT(7) /* FIFO wraparound mode */ 252#define PCI230P2_DAC_INT_FIFO(x) (((x) & 7) << 9) 253#define PCI230P2_DAC_INT_FIFO_EMPTY PCI230P2_DAC_INT_FIFO(0) /* empty */ 254#define PCI230P2_DAC_INT_FIFO_NEMPTY PCI230P2_DAC_INT_FIFO(1) /* !empty */ 255#define PCI230P2_DAC_INT_FIFO_NHALF PCI230P2_DAC_INT_FIFO(2) /* !half */ 256#define PCI230P2_DAC_INT_FIFO_HALF PCI230P2_DAC_INT_FIFO(3) /* half */ 257#define PCI230P2_DAC_INT_FIFO_NFULL PCI230P2_DAC_INT_FIFO(4) /* !full */ 258#define PCI230P2_DAC_INT_FIFO_FULL PCI230P2_DAC_INT_FIFO(5) /* full */ 259#define PCI230P2_DAC_INT_FIFO_MASK PCI230P2_DAC_INT_FIFO(7) 260 261/* 262 * DACCON read-only values. 263 */ 264#define PCI230_DAC_BUSY BIT(1) /* DAC busy. */ 265/* 266 * The following apply only if the DAC FIFO is enabled (and only for PCI230+ 267 * hardware version 2 onwards). 268 */ 269#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED BIT(5) /* Underrun error */ 270#define PCI230P2_DAC_FIFO_EMPTY BIT(13) /* FIFO empty */ 271#define PCI230P2_DAC_FIFO_FULL BIT(14) /* FIFO full */ 272#define PCI230P2_DAC_FIFO_HALF BIT(15) /* FIFO half full */ 273 274/* 275 * DACCON write-only, transient values. 276 */ 277/* 278 * The following apply only if the DAC FIFO is enabled (and only for PCI230+ 279 * hardware version 2 onwards). 280 */ 281#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR BIT(5) /* Clear underrun */ 282#define PCI230P2_DAC_FIFO_RESET BIT(12) /* FIFO reset */ 283 284/* 285 * PCI230+ hardware version 2 DAC FIFO levels. 286 */ 287#define PCI230P2_DAC_FIFOLEVEL_HALF 512 288#define PCI230P2_DAC_FIFOLEVEL_FULL 1024 289/* Free space in DAC FIFO. */ 290#define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL 291#define PCI230P2_DAC_FIFOROOM_ONETOHALF \ 292 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF) 293#define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1 294#define PCI230P2_DAC_FIFOROOM_FULL 0 295 296/* 297 * ADCCON read/write values. 298 */ 299#define PCI230_ADC_TRIG(x) (((x) & 0x7) << 0) 300#define PCI230_ADC_TRIG_NONE PCI230_ADC_TRIG(0) /* none */ 301#define PCI230_ADC_TRIG_SW PCI230_ADC_TRIG(1) /* soft trig */ 302#define PCI230_ADC_TRIG_EXTP PCI230_ADC_TRIG(2) /* ext + edge */ 303#define PCI230_ADC_TRIG_EXTN PCI230_ADC_TRIG(3) /* ext - edge */ 304#define PCI230_ADC_TRIG_Z2CT0 PCI230_ADC_TRIG(4) /* Z2 CT0 out*/ 305#define PCI230_ADC_TRIG_Z2CT1 PCI230_ADC_TRIG(5) /* Z2 CT1 out */ 306#define PCI230_ADC_TRIG_Z2CT2 PCI230_ADC_TRIG(6) /* Z2 CT2 out */ 307#define PCI230_ADC_TRIG_MASK PCI230_ADC_TRIG(7) 308#define PCI230_ADC_IR(x) (((x) & 0x1) << 3) 309#define PCI230_ADC_IR_UNI PCI230_ADC_IR(0) /* Input unipolar */ 310#define PCI230_ADC_IR_BIP PCI230_ADC_IR(1) /* Input bipolar */ 311#define PCI230_ADC_IR_MASK PCI230_ADC_IR(1) 312#define PCI230_ADC_IM(x) (((x) & 0x1) << 4) 313#define PCI230_ADC_IM_SE PCI230_ADC_IM(0) /* single ended */ 314#define PCI230_ADC_IM_DIF PCI230_ADC_IM(1) /* differential */ 315#define PCI230_ADC_IM_MASK PCI230_ADC_IM(1) 316#define PCI230_ADC_FIFO_EN BIT(8) /* FIFO enable */ 317#define PCI230_ADC_INT_FIFO(x) (((x) & 0x7) << 9) 318#define PCI230_ADC_INT_FIFO_EMPTY PCI230_ADC_INT_FIFO(0) /* empty */ 319#define PCI230_ADC_INT_FIFO_NEMPTY PCI230_ADC_INT_FIFO(1) /* !empty */ 320#define PCI230_ADC_INT_FIFO_NHALF PCI230_ADC_INT_FIFO(2) /* !half */ 321#define PCI230_ADC_INT_FIFO_HALF PCI230_ADC_INT_FIFO(3) /* half */ 322#define PCI230_ADC_INT_FIFO_NFULL PCI230_ADC_INT_FIFO(4) /* !full */ 323#define PCI230_ADC_INT_FIFO_FULL PCI230_ADC_INT_FIFO(5) /* full */ 324#define PCI230P_ADC_INT_FIFO_THRESH PCI230_ADC_INT_FIFO(7) /* threshold */ 325#define PCI230_ADC_INT_FIFO_MASK PCI230_ADC_INT_FIFO(7) 326 327/* 328 * ADCCON write-only, transient values. 329 */ 330#define PCI230_ADC_FIFO_RESET BIT(12) /* FIFO reset */ 331#define PCI230_ADC_GLOB_RESET BIT(13) /* Global reset */ 332 333/* 334 * ADCCON read-only values. 335 */ 336#define PCI230_ADC_BUSY BIT(15) /* ADC busy */ 337#define PCI230_ADC_FIFO_EMPTY BIT(12) /* FIFO empty */ 338#define PCI230_ADC_FIFO_FULL BIT(13) /* FIFO full */ 339#define PCI230_ADC_FIFO_HALF BIT(14) /* FIFO half full */ 340#define PCI230_ADC_FIFO_FULL_LATCHED BIT(5) /* FIFO overrun occurred */ 341 342/* 343 * PCI230 ADC FIFO levels. 344 */ 345#define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */ 346#define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */ 347 348/* 349 * PCI230+ EXTFUNC values. 350 */ 351/* Route EXTTRIG pin to external gate inputs. */ 352#define PCI230P_EXTFUNC_GAT_EXTTRIG BIT(0) 353/* PCI230+ hardware version 2 values. */ 354/* Allow DAC FIFO to be enabled. */ 355#define PCI230P2_EXTFUNC_DACFIFO BIT(1) 356 357/* 358 * Counter/timer clock input configuration sources. 359 */ 360#define CLK_CLK 0 /* reserved (channel-specific clock) */ 361#define CLK_10MHZ 1 /* internal 10 MHz clock */ 362#define CLK_1MHZ 2 /* internal 1 MHz clock */ 363#define CLK_100KHZ 3 /* internal 100 kHz clock */ 364#define CLK_10KHZ 4 /* internal 10 kHz clock */ 365#define CLK_1KHZ 5 /* internal 1 kHz clock */ 366#define CLK_OUTNM1 6 /* output of channel-1 modulo total */ 367#define CLK_EXT 7 /* external clock */ 368 369static unsigned int pci230_clk_config(unsigned int chan, unsigned int src) 370{ 371 return ((chan & 3) << 3) | (src & 7); 372} 373 374/* 375 * Counter/timer gate input configuration sources. 376 */ 377#define GAT_VCC 0 /* VCC (i.e. enabled) */ 378#define GAT_GND 1 /* GND (i.e. disabled) */ 379#define GAT_EXT 2 /* external gate input (PPCn on PCI230) */ 380#define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */ 381 382static unsigned int pci230_gat_config(unsigned int chan, unsigned int src) 383{ 384 return ((chan & 3) << 3) | (src & 7); 385} 386 387/* 388 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260: 389 * 390 * Channel's Channel's 391 * clock input gate input 392 * Channel CLK_OUTNM1 GAT_NOUTNM2 393 * ------- ---------- ----------- 394 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT 395 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT 396 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT 397 */ 398 399/* 400 * Interrupt enables/status register values. 401 */ 402#define PCI230_INT_DISABLE 0 403#define PCI230_INT_PPI_C0 BIT(0) 404#define PCI230_INT_PPI_C3 BIT(1) 405#define PCI230_INT_ADC BIT(2) 406#define PCI230_INT_ZCLK_CT1 BIT(5) 407/* For PCI230+ hardware version 2 when DAC FIFO enabled. */ 408#define PCI230P2_INT_DAC BIT(4) 409 410/* 411 * (Potentially) shared resources and their owners 412 */ 413enum { 414 RES_Z2CT0 = BIT(0), /* Z2-CT0 */ 415 RES_Z2CT1 = BIT(1), /* Z2-CT1 */ 416 RES_Z2CT2 = BIT(2) /* Z2-CT2 */ 417}; 418 419enum { 420 OWNER_AICMD, /* Owned by AI command */ 421 OWNER_AOCMD, /* Owned by AO command */ 422 NUM_OWNERS /* Number of owners */ 423}; 424 425/* 426 * Handy macros. 427 */ 428 429/* Combine old and new bits. */ 430#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask))) 431 432/* Current CPU. XXX should this be hard_smp_processor_id()? */ 433#define THISCPU smp_processor_id() 434 435/* 436 * Board descriptions for the two boards supported. 437 */ 438 439struct pci230_board { 440 const char *name; 441 unsigned short id; 442 unsigned char ai_bits; 443 unsigned char ao_bits; 444 unsigned char min_hwver; /* Minimum hardware version supported. */ 445 unsigned int have_dio:1; 446}; 447 448static const struct pci230_board pci230_boards[] = { 449 { 450 .name = "pci230+", 451 .id = PCI_DEVICE_ID_PCI230, 452 .ai_bits = 16, 453 .ao_bits = 12, 454 .have_dio = true, 455 .min_hwver = 1, 456 }, 457 { 458 .name = "pci260+", 459 .id = PCI_DEVICE_ID_PCI260, 460 .ai_bits = 16, 461 .min_hwver = 1, 462 }, 463 { 464 .name = "pci230", 465 .id = PCI_DEVICE_ID_PCI230, 466 .ai_bits = 12, 467 .ao_bits = 12, 468 .have_dio = true, 469 }, 470 { 471 .name = "pci260", 472 .id = PCI_DEVICE_ID_PCI260, 473 .ai_bits = 12, 474 }, 475}; 476 477struct pci230_private { 478 spinlock_t isr_spinlock; /* Interrupt spin lock */ 479 spinlock_t res_spinlock; /* Shared resources spin lock */ 480 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */ 481 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */ 482 unsigned long daqio; /* PCI230's DAQ I/O space */ 483 int intr_cpuid; /* ID of CPU running ISR */ 484 unsigned short hwver; /* Hardware version (for '+' models) */ 485 unsigned short adccon; /* ADCCON register value */ 486 unsigned short daccon; /* DACCON register value */ 487 unsigned short adcfifothresh; /* ADC FIFO threshold (PCI230+/260+) */ 488 unsigned short adcg; /* ADCG register value */ 489 unsigned char ier; /* Interrupt enable bits */ 490 unsigned char res_owned[NUM_OWNERS]; /* Owned resources */ 491 unsigned int intr_running:1; /* Flag set in interrupt routine */ 492 unsigned int ai_bipolar:1; /* Flag AI range is bipolar */ 493 unsigned int ao_bipolar:1; /* Flag AO range is bipolar */ 494 unsigned int ai_cmd_started:1; /* Flag AI command started */ 495 unsigned int ao_cmd_started:1; /* Flag AO command started */ 496}; 497 498/* PCI230 clock source periods in ns */ 499static const unsigned int pci230_timebase[8] = { 500 [CLK_10MHZ] = I8254_OSC_BASE_10MHZ, 501 [CLK_1MHZ] = I8254_OSC_BASE_1MHZ, 502 [CLK_100KHZ] = I8254_OSC_BASE_100KHZ, 503 [CLK_10KHZ] = I8254_OSC_BASE_10KHZ, 504 [CLK_1KHZ] = I8254_OSC_BASE_1KHZ, 505}; 506 507/* PCI230 analogue input range table */ 508static const struct comedi_lrange pci230_ai_range = { 509 7, { 510 BIP_RANGE(10), 511 BIP_RANGE(5), 512 BIP_RANGE(2.5), 513 BIP_RANGE(1.25), 514 UNI_RANGE(10), 515 UNI_RANGE(5), 516 UNI_RANGE(2.5) 517 } 518}; 519 520/* PCI230 analogue gain bits for each input range. */ 521static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 }; 522 523/* PCI230 analogue output range table */ 524static const struct comedi_lrange pci230_ao_range = { 525 2, { 526 UNI_RANGE(10), 527 BIP_RANGE(10) 528 } 529}; 530 531static unsigned short pci230_ai_read(struct comedi_device *dev) 532{ 533 const struct pci230_board *board = dev->board_ptr; 534 struct pci230_private *devpriv = dev->private; 535 unsigned short data; 536 537 /* Read sample. */ 538 data = inw(devpriv->daqio + PCI230_ADCDATA); 539 /* 540 * PCI230 is 12 bit - stored in upper bits of 16 bit register 541 * (lower four bits reserved for expansion). PCI230+ is 16 bit AI. 542 * 543 * If a bipolar range was specified, mangle it 544 * (twos complement->straight binary). 545 */ 546 if (devpriv->ai_bipolar) 547 data ^= 0x8000; 548 data >>= (16 - board->ai_bits); 549 return data; 550} 551 552static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, 553 unsigned short datum) 554{ 555 const struct pci230_board *board = dev->board_ptr; 556 struct pci230_private *devpriv = dev->private; 557 558 /* 559 * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower 560 * four bits reserved for expansion). PCI230+ is also 12 bit AO. 561 */ 562 datum <<= (16 - board->ao_bits); 563 /* 564 * If a bipolar range was specified, mangle it 565 * (straight binary->twos complement). 566 */ 567 if (devpriv->ao_bipolar) 568 datum ^= 0x8000; 569 return datum; 570} 571 572static void pci230_ao_write_nofifo(struct comedi_device *dev, 573 unsigned short datum, unsigned int chan) 574{ 575 struct pci230_private *devpriv = dev->private; 576 577 /* Write mangled datum to appropriate DACOUT register. */ 578 outw(pci230_ao_mangle_datum(dev, datum), 579 devpriv->daqio + ((chan == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2)); 580} 581 582static void pci230_ao_write_fifo(struct comedi_device *dev, 583 unsigned short datum, unsigned int chan) 584{ 585 struct pci230_private *devpriv = dev->private; 586 587 /* Write mangled datum to appropriate DACDATA register. */ 588 outw(pci230_ao_mangle_datum(dev, datum), 589 devpriv->daqio + PCI230P2_DACDATA); 590} 591 592static bool pci230_claim_shared(struct comedi_device *dev, 593 unsigned char res_mask, unsigned int owner) 594{ 595 struct pci230_private *devpriv = dev->private; 596 unsigned int o; 597 unsigned long irqflags; 598 599 spin_lock_irqsave(&devpriv->res_spinlock, irqflags); 600 for (o = 0; o < NUM_OWNERS; o++) { 601 if (o == owner) 602 continue; 603 if (devpriv->res_owned[o] & res_mask) { 604 spin_unlock_irqrestore(&devpriv->res_spinlock, 605 irqflags); 606 return false; 607 } 608 } 609 devpriv->res_owned[owner] |= res_mask; 610 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags); 611 return true; 612} 613 614static void pci230_release_shared(struct comedi_device *dev, 615 unsigned char res_mask, unsigned int owner) 616{ 617 struct pci230_private *devpriv = dev->private; 618 unsigned long irqflags; 619 620 spin_lock_irqsave(&devpriv->res_spinlock, irqflags); 621 devpriv->res_owned[owner] &= ~res_mask; 622 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags); 623} 624 625static void pci230_release_all_resources(struct comedi_device *dev, 626 unsigned int owner) 627{ 628 pci230_release_shared(dev, (unsigned char)~0, owner); 629} 630 631static unsigned int pci230_divide_ns(u64 ns, unsigned int timebase, 632 unsigned int flags) 633{ 634 u64 div; 635 unsigned int rem; 636 637 div = ns; 638 rem = do_div(div, timebase); 639 switch (flags & CMDF_ROUND_MASK) { 640 default: 641 case CMDF_ROUND_NEAREST: 642 div += DIV_ROUND_CLOSEST(rem, timebase); 643 break; 644 case CMDF_ROUND_DOWN: 645 break; 646 case CMDF_ROUND_UP: 647 div += DIV_ROUND_UP(rem, timebase); 648 break; 649 } 650 return div > UINT_MAX ? UINT_MAX : (unsigned int)div; 651} 652 653/* 654 * Given desired period in ns, returns the required internal clock source 655 * and gets the initial count. 656 */ 657static unsigned int pci230_choose_clk_count(u64 ns, unsigned int *count, 658 unsigned int flags) 659{ 660 unsigned int clk_src, cnt; 661 662 for (clk_src = CLK_10MHZ;; clk_src++) { 663 cnt = pci230_divide_ns(ns, pci230_timebase[clk_src], flags); 664 if (cnt <= 65536 || clk_src == CLK_1KHZ) 665 break; 666 } 667 *count = cnt; 668 return clk_src; 669} 670 671static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags) 672{ 673 unsigned int count; 674 unsigned int clk_src; 675 676 clk_src = pci230_choose_clk_count(*ns, &count, flags); 677 *ns = count * pci230_timebase[clk_src]; 678} 679 680static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, 681 unsigned int mode, u64 ns, 682 unsigned int flags) 683{ 684 unsigned int clk_src; 685 unsigned int count; 686 687 /* Set mode. */ 688 comedi_8254_set_mode(dev->pacer, ct, mode); 689 /* Determine clock source and count. */ 690 clk_src = pci230_choose_clk_count(ns, &count, flags); 691 /* Program clock source. */ 692 outb(pci230_clk_config(ct, clk_src), dev->iobase + PCI230_ZCLK_SCE); 693 /* Set initial count. */ 694 if (count >= 65536) 695 count = 0; 696 697 comedi_8254_write(dev->pacer, ct, count); 698} 699 700static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct) 701{ 702 /* Counter ct, 8254 mode 1, initial count not written. */ 703 comedi_8254_set_mode(dev->pacer, ct, I8254_MODE1); 704} 705 706static int pci230_ai_eoc(struct comedi_device *dev, 707 struct comedi_subdevice *s, 708 struct comedi_insn *insn, 709 unsigned long context) 710{ 711 struct pci230_private *devpriv = dev->private; 712 unsigned int status; 713 714 status = inw(devpriv->daqio + PCI230_ADCCON); 715 if ((status & PCI230_ADC_FIFO_EMPTY) == 0) 716 return 0; 717 return -EBUSY; 718} 719 720static int pci230_ai_insn_read(struct comedi_device *dev, 721 struct comedi_subdevice *s, 722 struct comedi_insn *insn, unsigned int *data) 723{ 724 struct pci230_private *devpriv = dev->private; 725 unsigned int n; 726 unsigned int chan, range, aref; 727 unsigned int gainshift; 728 unsigned short adccon, adcen; 729 int ret; 730 731 /* Unpack channel and range. */ 732 chan = CR_CHAN(insn->chanspec); 733 range = CR_RANGE(insn->chanspec); 734 aref = CR_AREF(insn->chanspec); 735 if (aref == AREF_DIFF) { 736 /* Differential. */ 737 if (chan >= s->n_chan / 2) { 738 dev_dbg(dev->class_dev, 739 "%s: differential channel number out of range 0 to %u\n", 740 __func__, (s->n_chan / 2) - 1); 741 return -EINVAL; 742 } 743 } 744 745 /* 746 * Use Z2-CT2 as a conversion trigger instead of the built-in 747 * software trigger, as otherwise triggering of differential channels 748 * doesn't work properly for some versions of PCI230/260. Also set 749 * FIFO mode because the ADC busy bit only works for software triggers. 750 */ 751 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN; 752 /* Set Z2-CT2 output low to avoid any false triggers. */ 753 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0); 754 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range); 755 if (aref == AREF_DIFF) { 756 /* Differential. */ 757 gainshift = chan * 2; 758 if (devpriv->hwver == 0) { 759 /* 760 * Original PCI230/260 expects both inputs of the 761 * differential channel to be enabled. 762 */ 763 adcen = 3 << gainshift; 764 } else { 765 /* 766 * PCI230+/260+ expects only one input of the 767 * differential channel to be enabled. 768 */ 769 adcen = 1 << gainshift; 770 } 771 adccon |= PCI230_ADC_IM_DIF; 772 } else { 773 /* Single ended. */ 774 adcen = 1 << chan; 775 gainshift = chan & ~1; 776 adccon |= PCI230_ADC_IM_SE; 777 } 778 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) | 779 (pci230_ai_gain[range] << gainshift); 780 if (devpriv->ai_bipolar) 781 adccon |= PCI230_ADC_IR_BIP; 782 else 783 adccon |= PCI230_ADC_IR_UNI; 784 785 /* 786 * Enable only this channel in the scan list - otherwise by default 787 * we'll get one sample from each channel. 788 */ 789 outw(adcen, devpriv->daqio + PCI230_ADCEN); 790 791 /* Set gain for channel. */ 792 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG); 793 794 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */ 795 devpriv->adccon = adccon; 796 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON); 797 798 /* Convert n samples */ 799 for (n = 0; n < insn->n; n++) { 800 /* 801 * Trigger conversion by toggling Z2-CT2 output 802 * (finish with output high). 803 */ 804 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0); 805 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1); 806 807 /* wait for conversion to end */ 808 ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0); 809 if (ret) 810 return ret; 811 812 /* read data */ 813 data[n] = pci230_ai_read(dev); 814 } 815 816 /* return the number of samples read/written */ 817 return n; 818} 819 820static int pci230_ao_insn_write(struct comedi_device *dev, 821 struct comedi_subdevice *s, 822 struct comedi_insn *insn, 823 unsigned int *data) 824{ 825 struct pci230_private *devpriv = dev->private; 826 unsigned int chan = CR_CHAN(insn->chanspec); 827 unsigned int range = CR_RANGE(insn->chanspec); 828 unsigned int val = s->readback[chan]; 829 int i; 830 831 /* 832 * Set range - see analogue output range table; 0 => unipolar 10V, 833 * 1 => bipolar +/-10V range scale 834 */ 835 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range); 836 outw(range, devpriv->daqio + PCI230_DACCON); 837 838 for (i = 0; i < insn->n; i++) { 839 val = data[i]; 840 pci230_ao_write_nofifo(dev, val, chan); 841 } 842 s->readback[chan] = val; 843 844 return insn->n; 845} 846 847static int pci230_ao_check_chanlist(struct comedi_device *dev, 848 struct comedi_subdevice *s, 849 struct comedi_cmd *cmd) 850{ 851 unsigned int prev_chan = CR_CHAN(cmd->chanlist[0]); 852 unsigned int range0 = CR_RANGE(cmd->chanlist[0]); 853 int i; 854 855 for (i = 1; i < cmd->chanlist_len; i++) { 856 unsigned int chan = CR_CHAN(cmd->chanlist[i]); 857 unsigned int range = CR_RANGE(cmd->chanlist[i]); 858 859 if (chan < prev_chan) { 860 dev_dbg(dev->class_dev, 861 "%s: channel numbers must increase\n", 862 __func__); 863 return -EINVAL; 864 } 865 866 if (range != range0) { 867 dev_dbg(dev->class_dev, 868 "%s: channels must have the same range\n", 869 __func__); 870 return -EINVAL; 871 } 872 873 prev_chan = chan; 874 } 875 876 return 0; 877} 878 879static int pci230_ao_cmdtest(struct comedi_device *dev, 880 struct comedi_subdevice *s, struct comedi_cmd *cmd) 881{ 882 const struct pci230_board *board = dev->board_ptr; 883 struct pci230_private *devpriv = dev->private; 884 int err = 0; 885 unsigned int tmp; 886 887 /* Step 1 : check if triggers are trivially valid */ 888 889 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); 890 891 tmp = TRIG_TIMER | TRIG_INT; 892 if (board->min_hwver > 0 && devpriv->hwver >= 2) { 893 /* 894 * For PCI230+ hardware version 2 onwards, allow external 895 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). 896 * 897 * FIXME: The permitted scan_begin_src values shouldn't depend 898 * on devpriv->hwver (the detected card's actual hardware 899 * version). They should only depend on board->min_hwver 900 * (the static capabilities of the configured card). To fix 901 * it, a new card model, e.g. "pci230+2" would have to be 902 * defined with min_hwver set to 2. It doesn't seem worth it 903 * for this alone. At the moment, please consider 904 * scan_begin_src==TRIG_EXT support to be a bonus rather than a 905 * guarantee! 906 */ 907 tmp |= TRIG_EXT; 908 } 909 err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp); 910 911 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); 912 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 913 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 914 915 if (err) 916 return 1; 917 918 /* Step 2a : make sure trigger sources are unique */ 919 920 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); 921 err |= comedi_check_trigger_is_unique(cmd->stop_src); 922 923 /* Step 2b : and mutually compatible */ 924 925 if (err) 926 return 2; 927 928 /* Step 3: check if arguments are trivially valid */ 929 930 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); 931 932#define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */ 933/* 934 * Comedi limit due to unsigned int cmd. Driver limit = 935 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s 936 */ 937#define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */ 938 939 switch (cmd->scan_begin_src) { 940 case TRIG_TIMER: 941 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 942 MAX_SPEED_AO); 943 err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 944 MIN_SPEED_AO); 945 break; 946 case TRIG_EXT: 947 /* 948 * External trigger - for PCI230+ hardware version 2 onwards. 949 */ 950 /* Trigger number must be 0. */ 951 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) { 952 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, 953 ~CR_FLAGS_MASK); 954 err |= -EINVAL; 955 } 956 /* 957 * The only flags allowed are CR_EDGE and CR_INVERT. 958 * The CR_EDGE flag is ignored. 959 */ 960 if (cmd->scan_begin_arg & CR_FLAGS_MASK & 961 ~(CR_EDGE | CR_INVERT)) { 962 cmd->scan_begin_arg = 963 COMBINE(cmd->scan_begin_arg, 0, 964 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT)); 965 err |= -EINVAL; 966 } 967 break; 968 default: 969 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 970 break; 971 } 972 973 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, 974 cmd->chanlist_len); 975 976 if (cmd->stop_src == TRIG_COUNT) 977 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); 978 else /* TRIG_NONE */ 979 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); 980 981 if (err) 982 return 3; 983 984 /* Step 4: fix up any arguments */ 985 986 if (cmd->scan_begin_src == TRIG_TIMER) { 987 tmp = cmd->scan_begin_arg; 988 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags); 989 if (tmp != cmd->scan_begin_arg) 990 err++; 991 } 992 993 if (err) 994 return 4; 995 996 /* Step 5: check channel list if it exists */ 997 if (cmd->chanlist && cmd->chanlist_len > 0) 998 err |= pci230_ao_check_chanlist(dev, s, cmd); 999 1000 if (err) 1001 return 5; 1002 1003 return 0; 1004} 1005 1006static void pci230_ao_stop(struct comedi_device *dev, 1007 struct comedi_subdevice *s) 1008{ 1009 struct pci230_private *devpriv = dev->private; 1010 unsigned long irqflags; 1011 unsigned char intsrc; 1012 bool started; 1013 struct comedi_cmd *cmd; 1014 1015 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); 1016 started = devpriv->ao_cmd_started; 1017 devpriv->ao_cmd_started = false; 1018 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); 1019 if (!started) 1020 return; 1021 cmd = &s->async->cmd; 1022 if (cmd->scan_begin_src == TRIG_TIMER) { 1023 /* Stop scan rate generator. */ 1024 pci230_cancel_ct(dev, 1); 1025 } 1026 /* Determine interrupt source. */ 1027 if (devpriv->hwver < 2) { 1028 /* Not using DAC FIFO. Using CT1 interrupt. */ 1029 intsrc = PCI230_INT_ZCLK_CT1; 1030 } else { 1031 /* Using DAC FIFO interrupt. */ 1032 intsrc = PCI230P2_INT_DAC; 1033 } 1034 /* 1035 * Disable interrupt and wait for interrupt routine to finish running 1036 * unless we are called from the interrupt routine. 1037 */ 1038 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1039 devpriv->ier &= ~intsrc; 1040 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { 1041 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1042 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1043 } 1044 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 1045 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1046 if (devpriv->hwver >= 2) { 1047 /* 1048 * Using DAC FIFO. Reset FIFO, clear underrun error, 1049 * disable FIFO. 1050 */ 1051 devpriv->daccon &= PCI230_DAC_OR_MASK; 1052 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET | 1053 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, 1054 devpriv->daqio + PCI230_DACCON); 1055 } 1056 /* Release resources. */ 1057 pci230_release_all_resources(dev, OWNER_AOCMD); 1058} 1059 1060static void pci230_handle_ao_nofifo(struct comedi_device *dev, 1061 struct comedi_subdevice *s) 1062{ 1063 struct comedi_async *async = s->async; 1064 struct comedi_cmd *cmd = &async->cmd; 1065 unsigned short data; 1066 int i; 1067 1068 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) 1069 return; 1070 1071 for (i = 0; i < cmd->chanlist_len; i++) { 1072 unsigned int chan = CR_CHAN(cmd->chanlist[i]); 1073 1074 if (!comedi_buf_read_samples(s, &data, 1)) { 1075 async->events |= COMEDI_CB_OVERFLOW; 1076 return; 1077 } 1078 pci230_ao_write_nofifo(dev, data, chan); 1079 s->readback[chan] = data; 1080 } 1081 1082 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) 1083 async->events |= COMEDI_CB_EOA; 1084} 1085 1086/* 1087 * Loads DAC FIFO (if using it) from buffer. 1088 * Returns false if AO finished due to completion or error, true if still going. 1089 */ 1090static bool pci230_handle_ao_fifo(struct comedi_device *dev, 1091 struct comedi_subdevice *s) 1092{ 1093 struct pci230_private *devpriv = dev->private; 1094 struct comedi_async *async = s->async; 1095 struct comedi_cmd *cmd = &async->cmd; 1096 unsigned int num_scans = comedi_nscans_left(s, 0); 1097 unsigned int room; 1098 unsigned short dacstat; 1099 unsigned int i, n; 1100 unsigned int events = 0; 1101 1102 /* Get DAC FIFO status. */ 1103 dacstat = inw(devpriv->daqio + PCI230_DACCON); 1104 1105 if (cmd->stop_src == TRIG_COUNT && num_scans == 0) 1106 events |= COMEDI_CB_EOA; 1107 1108 if (events == 0) { 1109 /* Check for FIFO underrun. */ 1110 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) { 1111 dev_err(dev->class_dev, "AO FIFO underrun\n"); 1112 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; 1113 } 1114 /* 1115 * Check for buffer underrun if FIFO less than half full 1116 * (otherwise there will be loads of "DAC FIFO not half full" 1117 * interrupts). 1118 */ 1119 if (num_scans == 0 && 1120 (dacstat & PCI230P2_DAC_FIFO_HALF) == 0) { 1121 dev_err(dev->class_dev, "AO buffer underrun\n"); 1122 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; 1123 } 1124 } 1125 if (events == 0) { 1126 /* Determine how much room is in the FIFO (in samples). */ 1127 if (dacstat & PCI230P2_DAC_FIFO_FULL) 1128 room = PCI230P2_DAC_FIFOROOM_FULL; 1129 else if (dacstat & PCI230P2_DAC_FIFO_HALF) 1130 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL; 1131 else if (dacstat & PCI230P2_DAC_FIFO_EMPTY) 1132 room = PCI230P2_DAC_FIFOROOM_EMPTY; 1133 else 1134 room = PCI230P2_DAC_FIFOROOM_ONETOHALF; 1135 /* Convert room to number of scans that can be added. */ 1136 room /= cmd->chanlist_len; 1137 /* Determine number of scans to process. */ 1138 if (num_scans > room) 1139 num_scans = room; 1140 /* Process scans. */ 1141 for (n = 0; n < num_scans; n++) { 1142 for (i = 0; i < cmd->chanlist_len; i++) { 1143 unsigned int chan = CR_CHAN(cmd->chanlist[i]); 1144 unsigned short datum; 1145 1146 comedi_buf_read_samples(s, &datum, 1); 1147 pci230_ao_write_fifo(dev, datum, chan); 1148 s->readback[chan] = datum; 1149 } 1150 } 1151 1152 if (cmd->stop_src == TRIG_COUNT && 1153 async->scans_done >= cmd->stop_arg) { 1154 /* 1155 * All data for the command has been written 1156 * to FIFO. Set FIFO interrupt trigger level 1157 * to 'empty'. 1158 */ 1159 devpriv->daccon &= ~PCI230P2_DAC_INT_FIFO_MASK; 1160 devpriv->daccon |= PCI230P2_DAC_INT_FIFO_EMPTY; 1161 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON); 1162 } 1163 /* Check if FIFO underrun occurred while writing to FIFO. */ 1164 dacstat = inw(devpriv->daqio + PCI230_DACCON); 1165 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) { 1166 dev_err(dev->class_dev, "AO FIFO underrun\n"); 1167 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; 1168 } 1169 } 1170 async->events |= events; 1171 return !(async->events & COMEDI_CB_CANCEL_MASK); 1172} 1173 1174static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, 1175 struct comedi_subdevice *s, 1176 unsigned int trig_num) 1177{ 1178 struct pci230_private *devpriv = dev->private; 1179 unsigned long irqflags; 1180 1181 if (trig_num) 1182 return -EINVAL; 1183 1184 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); 1185 if (!devpriv->ao_cmd_started) { 1186 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); 1187 return 1; 1188 } 1189 /* Perform scan. */ 1190 if (devpriv->hwver < 2) { 1191 /* Not using DAC FIFO. */ 1192 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); 1193 pci230_handle_ao_nofifo(dev, s); 1194 comedi_handle_events(dev, s); 1195 } else { 1196 /* Using DAC FIFO. */ 1197 /* Read DACSWTRIG register to trigger conversion. */ 1198 inw(devpriv->daqio + PCI230P2_DACSWTRIG); 1199 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); 1200 } 1201 /* Delay. Should driver be responsible for this? */ 1202 /* XXX TODO: See if DAC busy bit can be used. */ 1203 udelay(8); 1204 return 1; 1205} 1206 1207static void pci230_ao_start(struct comedi_device *dev, 1208 struct comedi_subdevice *s) 1209{ 1210 struct pci230_private *devpriv = dev->private; 1211 struct comedi_async *async = s->async; 1212 struct comedi_cmd *cmd = &async->cmd; 1213 unsigned long irqflags; 1214 1215 devpriv->ao_cmd_started = true; 1216 1217 if (devpriv->hwver >= 2) { 1218 /* Using DAC FIFO. */ 1219 unsigned short scantrig; 1220 bool run; 1221 1222 /* Preload FIFO data. */ 1223 run = pci230_handle_ao_fifo(dev, s); 1224 comedi_handle_events(dev, s); 1225 if (!run) { 1226 /* Stopped. */ 1227 return; 1228 } 1229 /* Set scan trigger source. */ 1230 switch (cmd->scan_begin_src) { 1231 case TRIG_TIMER: 1232 scantrig = PCI230P2_DAC_TRIG_Z2CT1; 1233 break; 1234 case TRIG_EXT: 1235 /* Trigger on EXTTRIG/EXTCONVCLK pin. */ 1236 if ((cmd->scan_begin_arg & CR_INVERT) == 0) { 1237 /* +ve edge */ 1238 scantrig = PCI230P2_DAC_TRIG_EXTP; 1239 } else { 1240 /* -ve edge */ 1241 scantrig = PCI230P2_DAC_TRIG_EXTN; 1242 } 1243 break; 1244 case TRIG_INT: 1245 scantrig = PCI230P2_DAC_TRIG_SW; 1246 break; 1247 default: 1248 /* Shouldn't get here. */ 1249 scantrig = PCI230P2_DAC_TRIG_NONE; 1250 break; 1251 } 1252 devpriv->daccon = 1253 (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) | scantrig; 1254 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON); 1255 } 1256 switch (cmd->scan_begin_src) { 1257 case TRIG_TIMER: 1258 if (devpriv->hwver < 2) { 1259 /* Not using DAC FIFO. */ 1260 /* Enable CT1 timer interrupt. */ 1261 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1262 devpriv->ier |= PCI230_INT_ZCLK_CT1; 1263 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 1264 spin_unlock_irqrestore(&devpriv->isr_spinlock, 1265 irqflags); 1266 } 1267 /* Set CT1 gate high to start counting. */ 1268 outb(pci230_gat_config(1, GAT_VCC), 1269 dev->iobase + PCI230_ZGAT_SCE); 1270 break; 1271 case TRIG_INT: 1272 async->inttrig = pci230_ao_inttrig_scan_begin; 1273 break; 1274 } 1275 if (devpriv->hwver >= 2) { 1276 /* Using DAC FIFO. Enable DAC FIFO interrupt. */ 1277 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1278 devpriv->ier |= PCI230P2_INT_DAC; 1279 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 1280 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1281 } 1282} 1283 1284static int pci230_ao_inttrig_start(struct comedi_device *dev, 1285 struct comedi_subdevice *s, 1286 unsigned int trig_num) 1287{ 1288 struct comedi_cmd *cmd = &s->async->cmd; 1289 1290 if (trig_num != cmd->start_src) 1291 return -EINVAL; 1292 1293 s->async->inttrig = NULL; 1294 pci230_ao_start(dev, s); 1295 1296 return 1; 1297} 1298 1299static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1300{ 1301 struct pci230_private *devpriv = dev->private; 1302 unsigned short daccon; 1303 unsigned int range; 1304 1305 /* Get the command. */ 1306 struct comedi_cmd *cmd = &s->async->cmd; 1307 1308 if (cmd->scan_begin_src == TRIG_TIMER) { 1309 /* Claim Z2-CT1. */ 1310 if (!pci230_claim_shared(dev, RES_Z2CT1, OWNER_AOCMD)) 1311 return -EBUSY; 1312 } 1313 1314 /* 1315 * Set range - see analogue output range table; 0 => unipolar 10V, 1316 * 1 => bipolar +/-10V range scale 1317 */ 1318 range = CR_RANGE(cmd->chanlist[0]); 1319 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range); 1320 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI; 1321 /* Use DAC FIFO for hardware version 2 onwards. */ 1322 if (devpriv->hwver >= 2) { 1323 unsigned short dacen; 1324 unsigned int i; 1325 1326 dacen = 0; 1327 for (i = 0; i < cmd->chanlist_len; i++) 1328 dacen |= 1 << CR_CHAN(cmd->chanlist[i]); 1329 1330 /* Set channel scan list. */ 1331 outw(dacen, devpriv->daqio + PCI230P2_DACEN); 1332 /* 1333 * Enable DAC FIFO. 1334 * Set DAC scan source to 'none'. 1335 * Set DAC FIFO interrupt trigger level to 'not half full'. 1336 * Reset DAC FIFO and clear underrun. 1337 * 1338 * N.B. DAC FIFO interrupts are currently disabled. 1339 */ 1340 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET | 1341 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR | 1342 PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF; 1343 } 1344 1345 /* Set DACCON. */ 1346 outw(daccon, devpriv->daqio + PCI230_DACCON); 1347 /* Preserve most of DACCON apart from write-only, transient bits. */ 1348 devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET | 1349 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR); 1350 1351 if (cmd->scan_begin_src == TRIG_TIMER) { 1352 /* 1353 * Set the counter timer 1 to the specified scan frequency. 1354 * cmd->scan_begin_arg is sampling period in ns. 1355 * Gate it off for now. 1356 */ 1357 outb(pci230_gat_config(1, GAT_GND), 1358 dev->iobase + PCI230_ZGAT_SCE); 1359 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, 1360 cmd->scan_begin_arg, 1361 cmd->flags); 1362 } 1363 1364 /* N.B. cmd->start_src == TRIG_INT */ 1365 s->async->inttrig = pci230_ao_inttrig_start; 1366 1367 return 0; 1368} 1369 1370static int pci230_ao_cancel(struct comedi_device *dev, 1371 struct comedi_subdevice *s) 1372{ 1373 pci230_ao_stop(dev, s); 1374 return 0; 1375} 1376 1377static int pci230_ai_check_scan_period(struct comedi_cmd *cmd) 1378{ 1379 unsigned int min_scan_period, chanlist_len; 1380 int err = 0; 1381 1382 chanlist_len = cmd->chanlist_len; 1383 if (cmd->chanlist_len == 0) 1384 chanlist_len = 1; 1385 1386 min_scan_period = chanlist_len * cmd->convert_arg; 1387 if (min_scan_period < chanlist_len || 1388 min_scan_period < cmd->convert_arg) { 1389 /* Arithmetic overflow. */ 1390 min_scan_period = UINT_MAX; 1391 err++; 1392 } 1393 if (cmd->scan_begin_arg < min_scan_period) { 1394 cmd->scan_begin_arg = min_scan_period; 1395 err++; 1396 } 1397 1398 return !err; 1399} 1400 1401static int pci230_ai_check_chanlist(struct comedi_device *dev, 1402 struct comedi_subdevice *s, 1403 struct comedi_cmd *cmd) 1404{ 1405 struct pci230_private *devpriv = dev->private; 1406 unsigned int max_diff_chan = (s->n_chan / 2) - 1; 1407 unsigned int prev_chan = 0; 1408 unsigned int prev_range = 0; 1409 unsigned int prev_aref = 0; 1410 bool prev_bipolar = false; 1411 unsigned int subseq_len = 0; 1412 int i; 1413 1414 for (i = 0; i < cmd->chanlist_len; i++) { 1415 unsigned int chanspec = cmd->chanlist[i]; 1416 unsigned int chan = CR_CHAN(chanspec); 1417 unsigned int range = CR_RANGE(chanspec); 1418 unsigned int aref = CR_AREF(chanspec); 1419 bool bipolar = comedi_range_is_bipolar(s, range); 1420 1421 if (aref == AREF_DIFF && chan >= max_diff_chan) { 1422 dev_dbg(dev->class_dev, 1423 "%s: differential channel number out of range 0 to %u\n", 1424 __func__, max_diff_chan); 1425 return -EINVAL; 1426 } 1427 1428 if (i > 0) { 1429 /* 1430 * Channel numbers must strictly increase or 1431 * subsequence must repeat exactly. 1432 */ 1433 if (chan <= prev_chan && subseq_len == 0) 1434 subseq_len = i; 1435 1436 if (subseq_len > 0 && 1437 cmd->chanlist[i % subseq_len] != chanspec) { 1438 dev_dbg(dev->class_dev, 1439 "%s: channel numbers must increase or sequence must repeat exactly\n", 1440 __func__); 1441 return -EINVAL; 1442 } 1443 1444 if (aref != prev_aref) { 1445 dev_dbg(dev->class_dev, 1446 "%s: channel sequence analogue references must be all the same (single-ended or differential)\n", 1447 __func__); 1448 return -EINVAL; 1449 } 1450 1451 if (bipolar != prev_bipolar) { 1452 dev_dbg(dev->class_dev, 1453 "%s: channel sequence ranges must be all bipolar or all unipolar\n", 1454 __func__); 1455 return -EINVAL; 1456 } 1457 1458 if (aref != AREF_DIFF && range != prev_range && 1459 ((chan ^ prev_chan) & ~1) == 0) { 1460 dev_dbg(dev->class_dev, 1461 "%s: single-ended channel pairs must have the same range\n", 1462 __func__); 1463 return -EINVAL; 1464 } 1465 } 1466 prev_chan = chan; 1467 prev_range = range; 1468 prev_aref = aref; 1469 prev_bipolar = bipolar; 1470 } 1471 1472 if (subseq_len == 0) 1473 subseq_len = cmd->chanlist_len; 1474 1475 if (cmd->chanlist_len % subseq_len) { 1476 dev_dbg(dev->class_dev, 1477 "%s: sequence must repeat exactly\n", __func__); 1478 return -EINVAL; 1479 } 1480 1481 /* 1482 * Buggy PCI230+ or PCI260+ requires channel 0 to be (first) in the 1483 * sequence if the sequence contains more than one channel. Hardware 1484 * versions 1 and 2 have the bug. There is no hardware version 3. 1485 * 1486 * Actually, there are two firmwares that report themselves as 1487 * hardware version 1 (the boards have different ADC chips with 1488 * slightly different timing requirements, which was supposed to 1489 * be invisible to software). The first one doesn't seem to have 1490 * the bug, but the second one does, and we can't tell them apart! 1491 */ 1492 if (devpriv->hwver > 0 && devpriv->hwver < 4) { 1493 if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0])) { 1494 dev_info(dev->class_dev, 1495 "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n", 1496 devpriv->hwver); 1497 return -EINVAL; 1498 } 1499 } 1500 1501 return 0; 1502} 1503 1504static int pci230_ai_cmdtest(struct comedi_device *dev, 1505 struct comedi_subdevice *s, struct comedi_cmd *cmd) 1506{ 1507 const struct pci230_board *board = dev->board_ptr; 1508 struct pci230_private *devpriv = dev->private; 1509 int err = 0; 1510 unsigned int tmp; 1511 1512 /* Step 1 : check if triggers are trivially valid */ 1513 1514 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); 1515 1516 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; 1517 if (board->have_dio || board->min_hwver > 0) { 1518 /* 1519 * Unfortunately, we cannot trigger a scan off an external 1520 * source on the PCI260 board, since it uses the PPIC0 (DIO) 1521 * input, which isn't present on the PCI260. For PCI260+ 1522 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead. 1523 */ 1524 tmp |= TRIG_EXT; 1525 } 1526 err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp); 1527 err |= comedi_check_trigger_src(&cmd->convert_src, 1528 TRIG_TIMER | TRIG_INT | TRIG_EXT); 1529 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 1530 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 1531 1532 if (err) 1533 return 1; 1534 1535 /* Step 2a : make sure trigger sources are unique */ 1536 1537 err |= comedi_check_trigger_is_unique(cmd->start_src); 1538 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); 1539 err |= comedi_check_trigger_is_unique(cmd->convert_src); 1540 err |= comedi_check_trigger_is_unique(cmd->stop_src); 1541 1542 /* Step 2b : and mutually compatible */ 1543 1544 /* 1545 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be 1546 * set up to generate a fixed number of timed conversion pulses. 1547 */ 1548 if (cmd->scan_begin_src != TRIG_FOLLOW && 1549 cmd->convert_src != TRIG_TIMER) 1550 err |= -EINVAL; 1551 1552 if (err) 1553 return 2; 1554 1555 /* Step 3: check if arguments are trivially valid */ 1556 1557 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); 1558 1559#define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */ 1560#define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */ 1561#define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */ 1562/* 1563 * Comedi limit due to unsigned int cmd. Driver limit = 1564 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s 1565 */ 1566#define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */ 1567 1568 if (cmd->convert_src == TRIG_TIMER) { 1569 unsigned int max_speed_ai; 1570 1571 if (devpriv->hwver == 0) { 1572 /* 1573 * PCI230 or PCI260. Max speed depends whether 1574 * single-ended or pseudo-differential. 1575 */ 1576 if (cmd->chanlist && cmd->chanlist_len > 0) { 1577 /* Peek analogue reference of first channel. */ 1578 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) 1579 max_speed_ai = MAX_SPEED_AI_DIFF; 1580 else 1581 max_speed_ai = MAX_SPEED_AI_SE; 1582 1583 } else { 1584 /* No channel list. Assume single-ended. */ 1585 max_speed_ai = MAX_SPEED_AI_SE; 1586 } 1587 } else { 1588 /* PCI230+ or PCI260+. */ 1589 max_speed_ai = MAX_SPEED_AI_PLUS; 1590 } 1591 1592 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 1593 max_speed_ai); 1594 err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 1595 MIN_SPEED_AI); 1596 } else if (cmd->convert_src == TRIG_EXT) { 1597 /* 1598 * external trigger 1599 * 1600 * convert_arg == (CR_EDGE | 0) 1601 * => trigger on +ve edge. 1602 * convert_arg == (CR_EDGE | CR_INVERT | 0) 1603 * => trigger on -ve edge. 1604 */ 1605 if (cmd->convert_arg & CR_FLAGS_MASK) { 1606 /* Trigger number must be 0. */ 1607 if (cmd->convert_arg & ~CR_FLAGS_MASK) { 1608 cmd->convert_arg = COMBINE(cmd->convert_arg, 0, 1609 ~CR_FLAGS_MASK); 1610 err |= -EINVAL; 1611 } 1612 /* 1613 * The only flags allowed are CR_INVERT and CR_EDGE. 1614 * CR_EDGE is required. 1615 */ 1616 if ((cmd->convert_arg & CR_FLAGS_MASK & ~CR_INVERT) != 1617 CR_EDGE) { 1618 /* Set CR_EDGE, preserve CR_INVERT. */ 1619 cmd->convert_arg = 1620 COMBINE(cmd->start_arg, CR_EDGE | 0, 1621 CR_FLAGS_MASK & ~CR_INVERT); 1622 err |= -EINVAL; 1623 } 1624 } else { 1625 /* 1626 * Backwards compatibility with previous versions: 1627 * convert_arg == 0 => trigger on -ve edge. 1628 * convert_arg == 1 => trigger on +ve edge. 1629 */ 1630 err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 1631 1); 1632 } 1633 } else { 1634 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); 1635 } 1636 1637 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, 1638 cmd->chanlist_len); 1639 1640 if (cmd->stop_src == TRIG_COUNT) 1641 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); 1642 else /* TRIG_NONE */ 1643 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); 1644 1645 if (cmd->scan_begin_src == TRIG_EXT) { 1646 /* 1647 * external "trigger" to begin each scan: 1648 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate 1649 * of CT2 (sample convert trigger is CT2) 1650 */ 1651 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) { 1652 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, 1653 ~CR_FLAGS_MASK); 1654 err |= -EINVAL; 1655 } 1656 /* The only flag allowed is CR_EDGE, which is ignored. */ 1657 if (cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) { 1658 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, 1659 CR_FLAGS_MASK & ~CR_EDGE); 1660 err |= -EINVAL; 1661 } 1662 } else if (cmd->scan_begin_src == TRIG_TIMER) { 1663 /* N.B. cmd->convert_arg is also TRIG_TIMER */ 1664 if (!pci230_ai_check_scan_period(cmd)) 1665 err |= -EINVAL; 1666 1667 } else { 1668 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 1669 } 1670 1671 if (err) 1672 return 3; 1673 1674 /* Step 4: fix up any arguments */ 1675 1676 if (cmd->convert_src == TRIG_TIMER) { 1677 tmp = cmd->convert_arg; 1678 pci230_ns_to_single_timer(&cmd->convert_arg, cmd->flags); 1679 if (tmp != cmd->convert_arg) 1680 err++; 1681 } 1682 1683 if (cmd->scan_begin_src == TRIG_TIMER) { 1684 /* N.B. cmd->convert_arg is also TRIG_TIMER */ 1685 tmp = cmd->scan_begin_arg; 1686 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags); 1687 if (!pci230_ai_check_scan_period(cmd)) { 1688 /* Was below minimum required. Round up. */ 1689 pci230_ns_to_single_timer(&cmd->scan_begin_arg, 1690 CMDF_ROUND_UP); 1691 pci230_ai_check_scan_period(cmd); 1692 } 1693 if (tmp != cmd->scan_begin_arg) 1694 err++; 1695 } 1696 1697 if (err) 1698 return 4; 1699 1700 /* Step 5: check channel list if it exists */ 1701 if (cmd->chanlist && cmd->chanlist_len > 0) 1702 err |= pci230_ai_check_chanlist(dev, s, cmd); 1703 1704 if (err) 1705 return 5; 1706 1707 return 0; 1708} 1709 1710static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev, 1711 struct comedi_subdevice *s) 1712{ 1713 struct pci230_private *devpriv = dev->private; 1714 struct comedi_cmd *cmd = &s->async->cmd; 1715 unsigned int wake; 1716 unsigned short triglev; 1717 unsigned short adccon; 1718 1719 if (cmd->flags & CMDF_WAKE_EOS) 1720 wake = cmd->scan_end_arg - s->async->cur_chan; 1721 else 1722 wake = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); 1723 1724 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) { 1725 triglev = PCI230_ADC_INT_FIFO_HALF; 1726 } else if (wake > 1 && devpriv->hwver > 0) { 1727 /* PCI230+/260+ programmable FIFO interrupt level. */ 1728 if (devpriv->adcfifothresh != wake) { 1729 devpriv->adcfifothresh = wake; 1730 outw(wake, devpriv->daqio + PCI230P_ADCFFTH); 1731 } 1732 triglev = PCI230P_ADC_INT_FIFO_THRESH; 1733 } else { 1734 triglev = PCI230_ADC_INT_FIFO_NEMPTY; 1735 } 1736 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev; 1737 if (adccon != devpriv->adccon) { 1738 devpriv->adccon = adccon; 1739 outw(adccon, devpriv->daqio + PCI230_ADCCON); 1740 } 1741} 1742 1743static int pci230_ai_inttrig_convert(struct comedi_device *dev, 1744 struct comedi_subdevice *s, 1745 unsigned int trig_num) 1746{ 1747 struct pci230_private *devpriv = dev->private; 1748 unsigned long irqflags; 1749 unsigned int delayus; 1750 1751 if (trig_num) 1752 return -EINVAL; 1753 1754 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); 1755 if (!devpriv->ai_cmd_started) { 1756 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); 1757 return 1; 1758 } 1759 /* 1760 * Trigger conversion by toggling Z2-CT2 output. 1761 * Finish with output high. 1762 */ 1763 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0); 1764 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1); 1765 /* 1766 * Delay. Should driver be responsible for this? An 1767 * alternative would be to wait until conversion is complete, 1768 * but we can't tell when it's complete because the ADC busy 1769 * bit has a different meaning when FIFO enabled (and when 1770 * FIFO not enabled, it only works for software triggers). 1771 */ 1772 if ((devpriv->adccon & PCI230_ADC_IM_MASK) == PCI230_ADC_IM_DIF && 1773 devpriv->hwver == 0) { 1774 /* PCI230/260 in differential mode */ 1775 delayus = 8; 1776 } else { 1777 /* single-ended or PCI230+/260+ */ 1778 delayus = 4; 1779 } 1780 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); 1781 udelay(delayus); 1782 return 1; 1783} 1784 1785static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, 1786 struct comedi_subdevice *s, 1787 unsigned int trig_num) 1788{ 1789 struct pci230_private *devpriv = dev->private; 1790 unsigned long irqflags; 1791 unsigned char zgat; 1792 1793 if (trig_num) 1794 return -EINVAL; 1795 1796 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); 1797 if (devpriv->ai_cmd_started) { 1798 /* Trigger scan by waggling CT0 gate source. */ 1799 zgat = pci230_gat_config(0, GAT_GND); 1800 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 1801 zgat = pci230_gat_config(0, GAT_VCC); 1802 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 1803 } 1804 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); 1805 1806 return 1; 1807} 1808 1809static void pci230_ai_stop(struct comedi_device *dev, 1810 struct comedi_subdevice *s) 1811{ 1812 struct pci230_private *devpriv = dev->private; 1813 unsigned long irqflags; 1814 struct comedi_cmd *cmd; 1815 bool started; 1816 1817 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); 1818 started = devpriv->ai_cmd_started; 1819 devpriv->ai_cmd_started = false; 1820 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); 1821 if (!started) 1822 return; 1823 cmd = &s->async->cmd; 1824 if (cmd->convert_src == TRIG_TIMER) { 1825 /* Stop conversion rate generator. */ 1826 pci230_cancel_ct(dev, 2); 1827 } 1828 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1829 /* Stop scan period monostable. */ 1830 pci230_cancel_ct(dev, 0); 1831 } 1832 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1833 /* 1834 * Disable ADC interrupt and wait for interrupt routine to finish 1835 * running unless we are called from the interrupt routine. 1836 */ 1837 devpriv->ier &= ~PCI230_INT_ADC; 1838 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { 1839 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1840 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1841 } 1842 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 1843 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1844 /* 1845 * Reset FIFO, disable FIFO and set start conversion source to none. 1846 * Keep se/diff and bip/uni settings. 1847 */ 1848 devpriv->adccon = 1849 (devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) | 1850 PCI230_ADC_TRIG_NONE; 1851 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, 1852 devpriv->daqio + PCI230_ADCCON); 1853 /* Release resources. */ 1854 pci230_release_all_resources(dev, OWNER_AICMD); 1855} 1856 1857static void pci230_ai_start(struct comedi_device *dev, 1858 struct comedi_subdevice *s) 1859{ 1860 struct pci230_private *devpriv = dev->private; 1861 unsigned long irqflags; 1862 unsigned short conv; 1863 struct comedi_async *async = s->async; 1864 struct comedi_cmd *cmd = &async->cmd; 1865 1866 devpriv->ai_cmd_started = true; 1867 1868 /* Enable ADC FIFO trigger level interrupt. */ 1869 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 1870 devpriv->ier |= PCI230_INT_ADC; 1871 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 1872 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 1873 1874 /* 1875 * Update conversion trigger source which is currently set 1876 * to CT2 output, which is currently stuck high. 1877 */ 1878 switch (cmd->convert_src) { 1879 default: 1880 conv = PCI230_ADC_TRIG_NONE; 1881 break; 1882 case TRIG_TIMER: 1883 /* Using CT2 output. */ 1884 conv = PCI230_ADC_TRIG_Z2CT2; 1885 break; 1886 case TRIG_EXT: 1887 if (cmd->convert_arg & CR_EDGE) { 1888 if ((cmd->convert_arg & CR_INVERT) == 0) { 1889 /* Trigger on +ve edge. */ 1890 conv = PCI230_ADC_TRIG_EXTP; 1891 } else { 1892 /* Trigger on -ve edge. */ 1893 conv = PCI230_ADC_TRIG_EXTN; 1894 } 1895 } else { 1896 /* Backwards compatibility. */ 1897 if (cmd->convert_arg) { 1898 /* Trigger on +ve edge. */ 1899 conv = PCI230_ADC_TRIG_EXTP; 1900 } else { 1901 /* Trigger on -ve edge. */ 1902 conv = PCI230_ADC_TRIG_EXTN; 1903 } 1904 } 1905 break; 1906 case TRIG_INT: 1907 /* 1908 * Use CT2 output for software trigger due to problems 1909 * in differential mode on PCI230/260. 1910 */ 1911 conv = PCI230_ADC_TRIG_Z2CT2; 1912 break; 1913 } 1914 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv; 1915 outw(devpriv->adccon, devpriv->daqio + PCI230_ADCCON); 1916 if (cmd->convert_src == TRIG_INT) 1917 async->inttrig = pci230_ai_inttrig_convert; 1918 1919 /* 1920 * Update FIFO interrupt trigger level, which is currently 1921 * set to "full". 1922 */ 1923 pci230_ai_update_fifo_trigger_level(dev, s); 1924 if (cmd->convert_src == TRIG_TIMER) { 1925 /* Update timer gates. */ 1926 unsigned char zgat; 1927 1928 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1929 /* 1930 * Conversion timer CT2 needs to be gated by 1931 * inverted output of monostable CT2. 1932 */ 1933 zgat = pci230_gat_config(2, GAT_NOUTNM2); 1934 } else { 1935 /* 1936 * Conversion timer CT2 needs to be gated on 1937 * continuously. 1938 */ 1939 zgat = pci230_gat_config(2, GAT_VCC); 1940 } 1941 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 1942 if (cmd->scan_begin_src != TRIG_FOLLOW) { 1943 /* Set monostable CT0 trigger source. */ 1944 switch (cmd->scan_begin_src) { 1945 default: 1946 zgat = pci230_gat_config(0, GAT_VCC); 1947 break; 1948 case TRIG_EXT: 1949 /* 1950 * For CT0 on PCI230, the external trigger 1951 * (gate) signal comes from PPC0, which is 1952 * channel 16 of the DIO subdevice. The 1953 * application needs to configure this as an 1954 * input in order to use it as an external scan 1955 * trigger. 1956 */ 1957 zgat = pci230_gat_config(0, GAT_EXT); 1958 break; 1959 case TRIG_TIMER: 1960 /* 1961 * Monostable CT0 triggered by rising edge on 1962 * inverted output of CT1 (falling edge on CT1). 1963 */ 1964 zgat = pci230_gat_config(0, GAT_NOUTNM2); 1965 break; 1966 case TRIG_INT: 1967 /* 1968 * Monostable CT0 is triggered by inttrig 1969 * function waggling the CT0 gate source. 1970 */ 1971 zgat = pci230_gat_config(0, GAT_VCC); 1972 break; 1973 } 1974 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 1975 switch (cmd->scan_begin_src) { 1976 case TRIG_TIMER: 1977 /* 1978 * Scan period timer CT1 needs to be 1979 * gated on to start counting. 1980 */ 1981 zgat = pci230_gat_config(1, GAT_VCC); 1982 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 1983 break; 1984 case TRIG_INT: 1985 async->inttrig = pci230_ai_inttrig_scan_begin; 1986 break; 1987 } 1988 } 1989 } else if (cmd->convert_src != TRIG_INT) { 1990 /* No longer need Z2-CT2. */ 1991 pci230_release_shared(dev, RES_Z2CT2, OWNER_AICMD); 1992 } 1993} 1994 1995static int pci230_ai_inttrig_start(struct comedi_device *dev, 1996 struct comedi_subdevice *s, 1997 unsigned int trig_num) 1998{ 1999 struct comedi_cmd *cmd = &s->async->cmd; 2000 2001 if (trig_num != cmd->start_arg) 2002 return -EINVAL; 2003 2004 s->async->inttrig = NULL; 2005 pci230_ai_start(dev, s); 2006 2007 return 1; 2008} 2009 2010static void pci230_handle_ai(struct comedi_device *dev, 2011 struct comedi_subdevice *s) 2012{ 2013 struct pci230_private *devpriv = dev->private; 2014 struct comedi_async *async = s->async; 2015 struct comedi_cmd *cmd = &async->cmd; 2016 unsigned int status_fifo; 2017 unsigned int i; 2018 unsigned int nsamples; 2019 unsigned int fifoamount; 2020 unsigned short val; 2021 2022 /* Determine number of samples to read. */ 2023 nsamples = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); 2024 if (nsamples == 0) 2025 return; 2026 2027 fifoamount = 0; 2028 for (i = 0; i < nsamples; i++) { 2029 if (fifoamount == 0) { 2030 /* Read FIFO state. */ 2031 status_fifo = inw(devpriv->daqio + PCI230_ADCCON); 2032 if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) { 2033 /* 2034 * Report error otherwise FIFO overruns will go 2035 * unnoticed by the caller. 2036 */ 2037 dev_err(dev->class_dev, "AI FIFO overrun\n"); 2038 async->events |= COMEDI_CB_ERROR; 2039 break; 2040 } else if (status_fifo & PCI230_ADC_FIFO_EMPTY) { 2041 /* FIFO empty. */ 2042 break; 2043 } else if (status_fifo & PCI230_ADC_FIFO_HALF) { 2044 /* FIFO half full. */ 2045 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL; 2046 } else if (devpriv->hwver > 0) { 2047 /* Read PCI230+/260+ ADC FIFO level. */ 2048 fifoamount = inw(devpriv->daqio + 2049 PCI230P_ADCFFLEV); 2050 if (fifoamount == 0) 2051 break; /* Shouldn't happen. */ 2052 } else { 2053 /* FIFO not empty. */ 2054 fifoamount = 1; 2055 } 2056 } 2057 2058 val = pci230_ai_read(dev); 2059 if (!comedi_buf_write_samples(s, &val, 1)) 2060 break; 2061 2062 fifoamount--; 2063 2064 if (cmd->stop_src == TRIG_COUNT && 2065 async->scans_done >= cmd->stop_arg) { 2066 async->events |= COMEDI_CB_EOA; 2067 break; 2068 } 2069 } 2070 2071 /* update FIFO interrupt trigger level if still running */ 2072 if (!(async->events & COMEDI_CB_CANCEL_MASK)) 2073 pci230_ai_update_fifo_trigger_level(dev, s); 2074} 2075 2076static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 2077{ 2078 struct pci230_private *devpriv = dev->private; 2079 unsigned int i, chan, range, diff; 2080 unsigned int res_mask; 2081 unsigned short adccon, adcen; 2082 unsigned char zgat; 2083 2084 /* Get the command. */ 2085 struct comedi_async *async = s->async; 2086 struct comedi_cmd *cmd = &async->cmd; 2087 2088 /* 2089 * Determine which shared resources are needed. 2090 */ 2091 res_mask = 0; 2092 /* 2093 * Need Z2-CT2 to supply a conversion trigger source at a high 2094 * logic level, even if not doing timed conversions. 2095 */ 2096 res_mask |= RES_Z2CT2; 2097 if (cmd->scan_begin_src != TRIG_FOLLOW) { 2098 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */ 2099 res_mask |= RES_Z2CT0; 2100 if (cmd->scan_begin_src == TRIG_TIMER) { 2101 /* Using Z2-CT1 for scan frequency */ 2102 res_mask |= RES_Z2CT1; 2103 } 2104 } 2105 /* Claim resources. */ 2106 if (!pci230_claim_shared(dev, res_mask, OWNER_AICMD)) 2107 return -EBUSY; 2108 2109 /* 2110 * Steps: 2111 * - Set channel scan list. 2112 * - Set channel gains. 2113 * - Enable and reset FIFO, specify uni/bip, se/diff, and set 2114 * start conversion source to point to something at a high logic 2115 * level (we use the output of counter/timer 2 for this purpose. 2116 * - PAUSE to allow things to settle down. 2117 * - Reset the FIFO again because it needs resetting twice and there 2118 * may have been a false conversion trigger on some versions of 2119 * PCI230/260 due to the start conversion source being set to a 2120 * high logic level. 2121 * - Enable ADC FIFO level interrupt. 2122 * - Set actual conversion trigger source and FIFO interrupt trigger 2123 * level. 2124 * - If convert_src is TRIG_TIMER, set up the timers. 2125 */ 2126 2127 adccon = PCI230_ADC_FIFO_EN; 2128 adcen = 0; 2129 2130 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) { 2131 /* Differential - all channels must be differential. */ 2132 diff = 1; 2133 adccon |= PCI230_ADC_IM_DIF; 2134 } else { 2135 /* Single ended - all channels must be single-ended. */ 2136 diff = 0; 2137 adccon |= PCI230_ADC_IM_SE; 2138 } 2139 2140 range = CR_RANGE(cmd->chanlist[0]); 2141 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range); 2142 if (devpriv->ai_bipolar) 2143 adccon |= PCI230_ADC_IR_BIP; 2144 else 2145 adccon |= PCI230_ADC_IR_UNI; 2146 2147 for (i = 0; i < cmd->chanlist_len; i++) { 2148 unsigned int gainshift; 2149 2150 chan = CR_CHAN(cmd->chanlist[i]); 2151 range = CR_RANGE(cmd->chanlist[i]); 2152 if (diff) { 2153 gainshift = 2 * chan; 2154 if (devpriv->hwver == 0) { 2155 /* 2156 * Original PCI230/260 expects both inputs of 2157 * the differential channel to be enabled. 2158 */ 2159 adcen |= 3 << gainshift; 2160 } else { 2161 /* 2162 * PCI230+/260+ expects only one input of the 2163 * differential channel to be enabled. 2164 */ 2165 adcen |= 1 << gainshift; 2166 } 2167 } else { 2168 gainshift = chan & ~1; 2169 adcen |= 1 << chan; 2170 } 2171 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) | 2172 (pci230_ai_gain[range] << gainshift); 2173 } 2174 2175 /* Set channel scan list. */ 2176 outw(adcen, devpriv->daqio + PCI230_ADCEN); 2177 2178 /* Set channel gains. */ 2179 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG); 2180 2181 /* 2182 * Set counter/timer 2 output high for use as the initial start 2183 * conversion source. 2184 */ 2185 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1); 2186 2187 /* 2188 * Temporarily use CT2 output as conversion trigger source and 2189 * temporarily set FIFO interrupt trigger level to 'full'. 2190 */ 2191 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2; 2192 2193 /* 2194 * Enable and reset FIFO, specify FIFO trigger level full, specify 2195 * uni/bip, se/diff, and temporarily set the start conversion source 2196 * to CT2 output. Note that CT2 output is currently high, and this 2197 * will produce a false conversion trigger on some versions of the 2198 * PCI230/260, but that will be dealt with later. 2199 */ 2200 devpriv->adccon = adccon; 2201 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON); 2202 2203 /* 2204 * Delay - 2205 * Failure to include this will result in the first few channels'-worth 2206 * of data being corrupt, normally manifesting itself by large negative 2207 * voltages. It seems the board needs time to settle between the first 2208 * FIFO reset (above) and the second FIFO reset (below). Setting the 2209 * channel gains and scan list _before_ the first FIFO reset also 2210 * helps, though only slightly. 2211 */ 2212 usleep_range(25, 100); 2213 2214 /* Reset FIFO again. */ 2215 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON); 2216 2217 if (cmd->convert_src == TRIG_TIMER) { 2218 /* 2219 * Set up CT2 as conversion timer, but gate it off for now. 2220 * Note, counter/timer output 2 can be monitored on the 2221 * connector: PCI230 pin 21, PCI260 pin 18. 2222 */ 2223 zgat = pci230_gat_config(2, GAT_GND); 2224 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 2225 /* Set counter/timer 2 to the specified conversion period. */ 2226 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg, 2227 cmd->flags); 2228 if (cmd->scan_begin_src != TRIG_FOLLOW) { 2229 /* 2230 * Set up monostable on CT0 output for scan timing. A 2231 * rising edge on the trigger (gate) input of CT0 will 2232 * trigger the monostable, causing its output to go low 2233 * for the configured period. The period depends on 2234 * the conversion period and the number of conversions 2235 * in the scan. 2236 * 2237 * Set the trigger high before setting up the 2238 * monostable to stop it triggering. The trigger 2239 * source will be changed later. 2240 */ 2241 zgat = pci230_gat_config(0, GAT_VCC); 2242 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 2243 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1, 2244 ((u64)cmd->convert_arg * 2245 cmd->scan_end_arg), 2246 CMDF_ROUND_UP); 2247 if (cmd->scan_begin_src == TRIG_TIMER) { 2248 /* 2249 * Monostable on CT0 will be triggered by 2250 * output of CT1 at configured scan frequency. 2251 * 2252 * Set up CT1 but gate it off for now. 2253 */ 2254 zgat = pci230_gat_config(1, GAT_GND); 2255 outb(zgat, dev->iobase + PCI230_ZGAT_SCE); 2256 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, 2257 cmd->scan_begin_arg, 2258 cmd->flags); 2259 } 2260 } 2261 } 2262 2263 if (cmd->start_src == TRIG_INT) 2264 s->async->inttrig = pci230_ai_inttrig_start; 2265 else /* TRIG_NOW */ 2266 pci230_ai_start(dev, s); 2267 2268 return 0; 2269} 2270 2271static int pci230_ai_cancel(struct comedi_device *dev, 2272 struct comedi_subdevice *s) 2273{ 2274 pci230_ai_stop(dev, s); 2275 return 0; 2276} 2277 2278/* Interrupt handler */ 2279static irqreturn_t pci230_interrupt(int irq, void *d) 2280{ 2281 unsigned char status_int, valid_status_int, temp_ier; 2282 struct comedi_device *dev = d; 2283 struct pci230_private *devpriv = dev->private; 2284 struct comedi_subdevice *s_ao = dev->write_subdev; 2285 struct comedi_subdevice *s_ai = dev->read_subdev; 2286 unsigned long irqflags; 2287 2288 /* Read interrupt status/enable register. */ 2289 status_int = inb(dev->iobase + PCI230_INT_STAT); 2290 2291 if (status_int == PCI230_INT_DISABLE) 2292 return IRQ_NONE; 2293 2294 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 2295 valid_status_int = devpriv->ier & status_int; 2296 /* 2297 * Disable triggered interrupts. 2298 * (Only those interrupts that need re-enabling, are, later in the 2299 * handler). 2300 */ 2301 temp_ier = devpriv->ier & ~status_int; 2302 outb(temp_ier, dev->iobase + PCI230_INT_SCE); 2303 devpriv->intr_running = true; 2304 devpriv->intr_cpuid = THISCPU; 2305 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 2306 2307 /* 2308 * Check the source of interrupt and handle it. 2309 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3 2310 * interrupts. However, at present (Comedi-0.7.60) does not allow 2311 * concurrent execution of commands, instructions or a mixture of the 2312 * two. 2313 */ 2314 2315 if (valid_status_int & PCI230_INT_ZCLK_CT1) 2316 pci230_handle_ao_nofifo(dev, s_ao); 2317 2318 if (valid_status_int & PCI230P2_INT_DAC) 2319 pci230_handle_ao_fifo(dev, s_ao); 2320 2321 if (valid_status_int & PCI230_INT_ADC) 2322 pci230_handle_ai(dev, s_ai); 2323 2324 /* Reenable interrupts. */ 2325 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); 2326 if (devpriv->ier != temp_ier) 2327 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE); 2328 devpriv->intr_running = false; 2329 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); 2330 2331 if (s_ao) 2332 comedi_handle_events(dev, s_ao); 2333 comedi_handle_events(dev, s_ai); 2334 2335 return IRQ_HANDLED; 2336} 2337 2338/* Check if PCI device matches a specific board. */ 2339static bool pci230_match_pci_board(const struct pci230_board *board, 2340 struct pci_dev *pci_dev) 2341{ 2342 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */ 2343 if (board->id != pci_dev->device) 2344 return false; 2345 if (board->min_hwver == 0) 2346 return true; 2347 /* Looking for a '+' model. First check length of registers. */ 2348 if (pci_resource_len(pci_dev, 3) < 32) 2349 return false; /* Not a '+' model. */ 2350 /* 2351 * TODO: temporarily enable PCI device and read the hardware version 2352 * register. For now, assume it's okay. 2353 */ 2354 return true; 2355} 2356 2357/* Look for board matching PCI device. */ 2358static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev) 2359{ 2360 unsigned int i; 2361 2362 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++) 2363 if (pci230_match_pci_board(&pci230_boards[i], pci_dev)) 2364 return &pci230_boards[i]; 2365 return NULL; 2366} 2367 2368static int pci230_auto_attach(struct comedi_device *dev, 2369 unsigned long context_unused) 2370{ 2371 struct pci_dev *pci_dev = comedi_to_pci_dev(dev); 2372 const struct pci230_board *board; 2373 struct pci230_private *devpriv; 2374 struct comedi_subdevice *s; 2375 int rc; 2376 2377 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n", 2378 pci_name(pci_dev)); 2379 2380 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 2381 if (!devpriv) 2382 return -ENOMEM; 2383 2384 spin_lock_init(&devpriv->isr_spinlock); 2385 spin_lock_init(&devpriv->res_spinlock); 2386 spin_lock_init(&devpriv->ai_stop_spinlock); 2387 spin_lock_init(&devpriv->ao_stop_spinlock); 2388 2389 board = pci230_find_pci_board(pci_dev); 2390 if (!board) { 2391 dev_err(dev->class_dev, 2392 "amplc_pci230: BUG! cannot determine board type!\n"); 2393 return -EINVAL; 2394 } 2395 dev->board_ptr = board; 2396 dev->board_name = board->name; 2397 2398 rc = comedi_pci_enable(dev); 2399 if (rc) 2400 return rc; 2401 2402 /* 2403 * Read base addresses of the PCI230's two I/O regions from PCI 2404 * configuration register. 2405 */ 2406 dev->iobase = pci_resource_start(pci_dev, 2); 2407 devpriv->daqio = pci_resource_start(pci_dev, 3); 2408 dev_dbg(dev->class_dev, 2409 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", 2410 dev->board_name, dev->iobase, devpriv->daqio); 2411 /* Read bits of DACCON register - only the output range. */ 2412 devpriv->daccon = inw(devpriv->daqio + PCI230_DACCON) & 2413 PCI230_DAC_OR_MASK; 2414 /* 2415 * Read hardware version register and set extended function register 2416 * if they exist. 2417 */ 2418 if (pci_resource_len(pci_dev, 3) >= 32) { 2419 unsigned short extfunc = 0; 2420 2421 devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER); 2422 if (devpriv->hwver < board->min_hwver) { 2423 dev_err(dev->class_dev, 2424 "%s - bad hardware version - got %u, need %u\n", 2425 dev->board_name, devpriv->hwver, 2426 board->min_hwver); 2427 return -EIO; 2428 } 2429 if (devpriv->hwver > 0) { 2430 if (!board->have_dio) { 2431 /* 2432 * No DIO ports. Route counters' external gates 2433 * to the EXTTRIG signal (PCI260+ pin 17). 2434 * (Otherwise, they would be routed to DIO 2435 * inputs PC0, PC1 and PC2 which don't exist 2436 * on PCI260[+].) 2437 */ 2438 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; 2439 } 2440 if (board->ao_bits && devpriv->hwver >= 2) { 2441 /* Enable DAC FIFO functionality. */ 2442 extfunc |= PCI230P2_EXTFUNC_DACFIFO; 2443 } 2444 } 2445 outw(extfunc, devpriv->daqio + PCI230P_EXTFUNC); 2446 if (extfunc & PCI230P2_EXTFUNC_DACFIFO) { 2447 /* 2448 * Temporarily enable DAC FIFO, reset it and disable 2449 * FIFO wraparound. 2450 */ 2451 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN | 2452 PCI230P2_DAC_FIFO_RESET, 2453 devpriv->daqio + PCI230_DACCON); 2454 /* Clear DAC FIFO channel enable register. */ 2455 outw(0, devpriv->daqio + PCI230P2_DACEN); 2456 /* Disable DAC FIFO. */ 2457 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON); 2458 } 2459 } 2460 /* Disable board's interrupts. */ 2461 outb(0, dev->iobase + PCI230_INT_SCE); 2462 /* Set ADC to a reasonable state. */ 2463 devpriv->adcg = 0; 2464 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE | 2465 PCI230_ADC_IR_BIP; 2466 outw(BIT(0), devpriv->daqio + PCI230_ADCEN); 2467 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG); 2468 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, 2469 devpriv->daqio + PCI230_ADCCON); 2470 2471 if (pci_dev->irq) { 2472 rc = request_irq(pci_dev->irq, pci230_interrupt, IRQF_SHARED, 2473 dev->board_name, dev); 2474 if (rc == 0) 2475 dev->irq = pci_dev->irq; 2476 } 2477 2478 dev->pacer = comedi_8254_init(dev->iobase + PCI230_Z2_CT_BASE, 2479 0, I8254_IO8, 0); 2480 if (!dev->pacer) 2481 return -ENOMEM; 2482 2483 rc = comedi_alloc_subdevices(dev, 3); 2484 if (rc) 2485 return rc; 2486 2487 s = &dev->subdevices[0]; 2488 /* analog input subdevice */ 2489 s->type = COMEDI_SUBD_AI; 2490 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; 2491 s->n_chan = 16; 2492 s->maxdata = (1 << board->ai_bits) - 1; 2493 s->range_table = &pci230_ai_range; 2494 s->insn_read = pci230_ai_insn_read; 2495 s->len_chanlist = 256; /* but there are restrictions. */ 2496 if (dev->irq) { 2497 dev->read_subdev = s; 2498 s->subdev_flags |= SDF_CMD_READ; 2499 s->do_cmd = pci230_ai_cmd; 2500 s->do_cmdtest = pci230_ai_cmdtest; 2501 s->cancel = pci230_ai_cancel; 2502 } 2503 2504 s = &dev->subdevices[1]; 2505 /* analog output subdevice */ 2506 if (board->ao_bits) { 2507 s->type = COMEDI_SUBD_AO; 2508 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 2509 s->n_chan = 2; 2510 s->maxdata = (1 << board->ao_bits) - 1; 2511 s->range_table = &pci230_ao_range; 2512 s->insn_write = pci230_ao_insn_write; 2513 s->len_chanlist = 2; 2514 if (dev->irq) { 2515 dev->write_subdev = s; 2516 s->subdev_flags |= SDF_CMD_WRITE; 2517 s->do_cmd = pci230_ao_cmd; 2518 s->do_cmdtest = pci230_ao_cmdtest; 2519 s->cancel = pci230_ao_cancel; 2520 } 2521 2522 rc = comedi_alloc_subdev_readback(s); 2523 if (rc) 2524 return rc; 2525 } else { 2526 s->type = COMEDI_SUBD_UNUSED; 2527 } 2528 2529 s = &dev->subdevices[2]; 2530 /* digital i/o subdevice */ 2531 if (board->have_dio) { 2532 rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE); 2533 if (rc) 2534 return rc; 2535 } else { 2536 s->type = COMEDI_SUBD_UNUSED; 2537 } 2538 2539 return 0; 2540} 2541 2542static struct comedi_driver amplc_pci230_driver = { 2543 .driver_name = "amplc_pci230", 2544 .module = THIS_MODULE, 2545 .auto_attach = pci230_auto_attach, 2546 .detach = comedi_pci_detach, 2547}; 2548 2549static int amplc_pci230_pci_probe(struct pci_dev *dev, 2550 const struct pci_device_id *id) 2551{ 2552 return comedi_pci_auto_config(dev, &lc_pci230_driver, 2553 id->driver_data); 2554} 2555 2556static const struct pci_device_id amplc_pci230_pci_table[] = { 2557 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) }, 2558 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) }, 2559 { 0 } 2560}; 2561MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table); 2562 2563static struct pci_driver amplc_pci230_pci_driver = { 2564 .name = "amplc_pci230", 2565 .id_table = amplc_pci230_pci_table, 2566 .probe = amplc_pci230_pci_probe, 2567 .remove = comedi_pci_auto_unconfig, 2568}; 2569module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver); 2570 2571MODULE_AUTHOR("Comedi https://www.comedi.org"); 2572MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)"); 2573MODULE_LICENSE("GPL");