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