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