1124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* 2124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi/drivers/ni_labpc.c 3124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess Driver for National Instruments Lab-PC series boards and compatibles 4124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net> 5124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 6124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess This program is free software; you can redistribute it and/or modify 7124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess it under the terms of the GNU General Public License as published by 8124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess the Free Software Foundation; either version 2 of the License, or 9124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess (at your option) any later version. 10124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 11124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess This program is distributed in the hope that it will be useful, 12124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess but WITHOUT ANY WARRANTY; without even the implied warranty of 13124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess GNU General Public License for more details. 15124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 16124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess You should have received a copy of the GNU General Public License 17124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess along with this program; if not, write to the Free Software 18124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 20124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess************************************************************************ 21124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess*/ 22124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* 23124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessDriver: ni_labpc 24124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessDescription: National Instruments Lab-PC (& compatibles) 25124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessAuthor: Frank Mori Hess <fmhess@users.sourceforge.net> 26124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessDevices: [National Instruments] Lab-PC-1200 (labpc-1200), 27124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (ni_labpc) 28124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessStatus: works 29124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 30124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessTested with lab-pc-1200. For the older Lab-PC+, not all input ranges 31124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessand analog references will work, the available ranges/arefs will 32124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessdepend on how you have configured the jumpers on your board 33124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess(see your owner's manual). 34124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 35124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessKernel-level ISA plug-and-play support for the lab-pc-1200 36124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessboards has not 37124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessyet been added to the driver, mainly due to the fact that 38124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessI don't know the device id numbers. If you have one 39124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessof these boards, 40631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattockplease file a bug report at http://comedi.org/ 41124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessso I can get the necessary information from you. 42124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 43124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessThe 1200 series boards have onboard calibration dacs for correcting 44124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessanalog input/output offsets and gains. The proper settings for these 45124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hesscaldacs are stored on the board's eeprom. To read the caldac values 46124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessfrom the eeprom and store them into a file that can be then be used by 47124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hesscomedilib, use the comedi_calibrate program. 48124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 49124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessConfiguration options - ISA boards: 50124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess [0] - I/O port base address 51124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess [1] - IRQ (optional, required for timed or externally triggered conversions) 52124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess [2] - DMA channel (optional) 53124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 54124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessConfiguration options - PCI boards: 55124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess [0] - bus (optional) 56124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess [1] - slot (optional) 57124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 58124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessThe Lab-pc+ has quirky chanlist requirements 59124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hesswhen scanning multiple channels. Multiple channel scan 60124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hesssequence must start at highest channel, then decrement down to 61124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hesschannel 0. The rest of the cards can scan down like lab-pc+ or scan 62124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessup from channel zero. Chanlists consisting of all one channel 63124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessare also legal, and allow you to pace conversions in bursts. 64124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 65124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess*/ 66124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 67124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* 68124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 69124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessNI manuals: 70124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess341309a (labpc-1200 register manual) 71124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess340914a (pci-1200) 72124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess320502b (lab-pc+) 73124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 74124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess*/ 75124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 76124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#undef LABPC_DEBUG 77f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* #define LABPC_DEBUG enable debugging messages */ 78124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 7925436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 805a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 81845d131e2b363717d8ac8db2c6b4417de8cf10b5Greg Kroah-Hartman#include <linux/io.h> 82124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "../comedidev.h" 83124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 84124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include <linux/delay.h> 85124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include <asm/dma.h> 86124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 87124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "8253.h" 88124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "8255.h" 89124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "mite.h" 90124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "comedi_fc.h" 91124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#include "ni_labpc.h" 92124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 93124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DRV_NAME "ni_labpc" 94124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 95e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* size of io region used by board */ 96e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define LABPC_SIZE 32 97e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* 2 MHz master clock */ 98e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define LABPC_TIMER_BASE 500 99124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 100124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* Registers for the lab-pc+ */ 101124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 102f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* write-only registers */ 103124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COMMAND1_REG 0x0 104124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define ADC_GAIN_MASK (0x7 << 4) 105124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define ADC_CHAN_BITS(x) ((x) & 0x7) 106e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enables multi channel scans */ 107e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_SCAN_EN_BIT 0x80 108124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COMMAND2_REG 0x1 109e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable pretriggering (used in conjunction with SWTRIG) */ 110e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define PRETRIG_BIT 0x1 111e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable paced conversions on external trigger */ 112e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define HWTRIG_BIT 0x2 113e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable paced conversions */ 114e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define SWTRIG_BIT 0x4 115e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* use two cascaded counters for pacing */ 116e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define CASCADE_BIT 0x8 117124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DAC_PACED_BIT(channel) (0x40 << ((channel) & 0x1)) 118124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COMMAND3_REG 0x2 119e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable dma transfers */ 120e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DMA_EN_BIT 0x1 121e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable interrupts for 8255 */ 122e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DIO_INTR_EN_BIT 0x2 123e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable dma terminal count interrupt */ 124e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DMATC_INTR_EN_BIT 0x4 125e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable timer interrupt */ 126e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define TIMER_INTR_EN_BIT 0x8 127e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable error interrupt */ 128e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ERR_INTR_EN_BIT 0x10 129e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable fifo not empty interrupt */ 130e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_FNE_INTR_EN_BIT 0x20 131124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define ADC_CONVERT_REG 0x3 132124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DAC_LSB_REG(channel) (0x4 + 2 * ((channel) & 0x1)) 133124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DAC_MSB_REG(channel) (0x5 + 2 * ((channel) & 0x1)) 134124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define ADC_CLEAR_REG 0x8 135124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DMATC_CLEAR_REG 0xa 136124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define TIMER_CLEAR_REG 0xc 137e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* 1200 boards only */ 138e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define COMMAND6_REG 0xe 139e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* select ground or common-mode reference */ 140e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_COMMON_BIT 0x1 141e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* adc unipolar */ 142e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_UNIP_BIT 0x2 143e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* dac unipolar */ 144e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DAC_UNIP_BIT(channel) (0x4 << ((channel) & 0x1)) 145e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable fifo half full interrupt */ 146e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_FHF_INTR_EN_BIT 0x20 147e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable interrupt on end of hardware count */ 148e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define A1_INTR_EN_BIT 0x40 149e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* scan up from channel zero instead of down to zero */ 150e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_SCAN_UP_BIT 0x80 151124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COMMAND4_REG 0xf 152e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enables 'interval' scanning */ 153e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define INTERVAL_SCAN_EN_BIT 0x1 154e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enables external signal on counter b1 output to trigger scan */ 155e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EXT_SCAN_EN_BIT 0x2 156e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* chooses direction (output or input) for EXTCONV* line */ 157e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EXT_CONVERT_OUT_BIT 0x4 158e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* chooses differential inputs for adc (in conjunction with board jumper) */ 159e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define ADC_DIFF_BIT 0x8 160124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define EXT_CONVERT_DISABLE_BIT 0x10 161e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* 1200 boards only, calibration stuff */ 162e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define COMMAND5_REG 0x1c 163e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable eeprom for write */ 164e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EEPROM_WRITE_UNPROTECT_BIT 0x4 165e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable dithering */ 166e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DITHER_EN_BIT 0x8 167e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* load calibration dac */ 168e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define CALDAC_LOAD_BIT 0x10 169e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* serial clock - rising edge writes, falling edge reads */ 170e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define SCLOCK_BIT 0x20 171e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* serial data bit for writing to eeprom or calibration dacs */ 172e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define SDATA_BIT 0x40 173e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* enable eeprom for read/write */ 174e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EEPROM_EN_BIT 0x80 175124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define INTERVAL_COUNT_REG 0x1e 176124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define INTERVAL_LOAD_REG 0x1f 177124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define INTERVAL_LOAD_BITS 0x1 178124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 179f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* read-only registers */ 180124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define STATUS1_REG 0x0 181e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* data is available in fifo */ 182e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DATA_AVAIL_BIT 0x1 183e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* overrun has occurred */ 184e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define OVERRUN_BIT 0x2 185e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* fifo overflow */ 186e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define OVERFLOW_BIT 0x4 18725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* timer interrupt has occurred */ 188e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define TIMER_BIT 0x8 18925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* dma terminal count has occurred */ 190e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define DMATC_BIT 0x10 19125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* external trigger has occurred */ 192e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EXT_TRIG_BIT 0x40 193e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* 1200 boards only */ 194e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define STATUS2_REG 0x1d 195e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* programmable eeprom serial output */ 196e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define EEPROM_OUT_BIT 0x1 197e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* counter A1 terminal count */ 198e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define A1_TC_BIT 0x2 199e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* fifo not half full */ 200e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define FNHF_BIT 0x4 201124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define ADC_FIFO_REG 0xa 202124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 203124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define DIO_BASE_REG 0x10 204124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COUNTER_A_BASE_REG 0x14 205124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COUNTER_A_CONTROL_REG (COUNTER_A_BASE_REG + 0x3) 206e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* check modes put conversion pacer output in harmless state (a0 mode 2) */ 207e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define INIT_A0_BITS 0x14 208e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* put hardware conversion counter output in harmless state (a1 mode 0) */ 209e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson#define INIT_A1_BITS 0x70 210124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define COUNTER_B_BASE_REG 0x18 211124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 212814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it); 213814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s); 21470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t labpc_interrupt(int irq, void *d); 215814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_drain_fifo(struct comedi_device *dev); 2163297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 217814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void labpc_drain_dma(struct comedi_device *dev); 218814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void handle_isa_dma(struct comedi_device *dev); 2193297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 220814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void labpc_drain_dregs(struct comedi_device *dev); 2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_ai_cmdtest(struct comedi_device *dev, 2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd); 223814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); 224814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 2250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 226814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 2270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 228814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 2290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_calib_read_insn(struct comedi_device *dev, 2310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_calib_write_insn(struct comedi_device *dev, 2340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_eeprom_read_insn(struct comedi_device *dev, 2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_eeprom_write_insn(struct comedi_device *dev, 2400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data); 243814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd); 244d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_ISA_DMA_API 2453297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlapstatic unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd); 246d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#endif 247d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 24871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int labpc_find_device(struct comedi_device *dev, int bus, int slot); 249124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 250124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic int labpc_dio_mem_callback(int dir, int port, int data, 2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned long arg); 252814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void labpc_serial_out(struct comedi_device *dev, unsigned int value, 2530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int num_bits); 254814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic unsigned int labpc_serial_in(struct comedi_device *dev); 255814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic unsigned int labpc_eeprom_read(struct comedi_device *dev, 2560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int address); 257814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic unsigned int labpc_eeprom_read_status(struct comedi_device *dev); 258d6269644e1f8fc7931c4d6b86d58de7af63a5fc9Julia Lawallstatic int labpc_eeprom_write(struct comedi_device *dev, 2590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int address, 2600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int value); 261814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void write_caldac(struct comedi_device *dev, unsigned int channel, 2620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int value); 263124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 264124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessenum scan_mode { 265124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess MODE_SINGLE_CHAN, 266124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess MODE_SINGLE_CHAN_INTERVAL, 267124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess MODE_MULT_CHAN_UP, 268124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess MODE_MULT_CHAN_DOWN, 269124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 270124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 271f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* analog input ranges */ 272124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define NUM_LABPC_PLUS_AI_RANGES 16 273f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* indicates unipolar ranges */ 274124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = { 275124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 276124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 277124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 278124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 279124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 280124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 281124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 282124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 283124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 284124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 285124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 286124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 287124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 288124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 289124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 290124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 291124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 292124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 293f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* map range index to gain bits */ 294124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = { 295124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x00, 296124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x10, 297124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x20, 298124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x30, 299124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x40, 300124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x50, 301124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x60, 302124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x70, 303124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x00, 304124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x10, 305124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x20, 306124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x30, 307124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x40, 308124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x50, 309124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x60, 310124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x70, 311124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 3120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 3139ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_labpc_plus_ai = { 314124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess NUM_LABPC_PLUS_AI_RANGES, 315124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(4), 3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1), 3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.5), 3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.25), 3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.1), 3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.05), 3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(8), 3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(5), 3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(2), 3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(1), 3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.5), 3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.2), 3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.1), 3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 333124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 334124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 335124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define NUM_LABPC_1200_AI_RANGES 14 336f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* indicates unipolar ranges */ 337124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessconst int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = { 338124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 339124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 340124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 341124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 342124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 343124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 344124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0, 345124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 346124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 347124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 348124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 349124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 350124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 351124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1, 352124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 3530656bb352080982f960bfff2b78602a5071c909fMaurice DawsonEXPORT_SYMBOL_GPL(labpc_1200_is_unipolar); 354124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 355f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* map range index to gain bits */ 356124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessconst int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = { 357124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x00, 358124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x20, 359124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x30, 360124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x40, 361124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x50, 362124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x60, 363124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x70, 364124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x00, 365124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x20, 366124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x30, 367124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x40, 368124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x50, 369124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x60, 370124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 0x70, 371124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 3720656bb352080982f960bfff2b78602a5071c909fMaurice DawsonEXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits); 3730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 3749ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonconst struct comedi_lrange range_labpc_1200_ai = { 375124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess NUM_LABPC_1200_AI_RANGES, 376124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 3770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 3780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 3790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1), 3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.5), 3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.25), 3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.1), 3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(0.05), 3840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 3850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(5), 3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(2), 3870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(1), 3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.5), 3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.2), 3900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(0.1), 3910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 392124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 3930656bb352080982f960bfff2b78602a5071c909fMaurice DawsonEXPORT_SYMBOL_GPL(range_labpc_1200_ai); 394124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 395f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* analog output ranges */ 396124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#define AO_RANGE_IS_UNIPOLAR 0x1 3979ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_labpc_ao = { 398124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2, 399124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 4010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 4020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 403124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 404124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 405124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* functions that do inb/outb and readb/writeb so we can use 406124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * function pointers to decide which to use */ 407124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic inline unsigned int labpc_inb(unsigned long address) 408124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 409124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return inb(address); 410124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 4110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 412124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic inline void labpc_outb(unsigned int byte, unsigned long address) 413124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 414124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess outb(byte, address); 415124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 4160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 417124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic inline unsigned int labpc_readb(unsigned long address) 418124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 419124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return readb((void *)address); 420124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 4210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 422124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic inline void labpc_writeb(unsigned int byte, unsigned long address) 423124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 424124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess writeb(byte, (void *)address); 425124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 426124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 4279ad007403fa4326586060e443ee344697daa60ecBill Pembertonstatic const struct labpc_board_struct labpc_boards[] = { 428124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "lab-pc-1200", 4300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_speed = 10000, 4310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .bustype = isa_bustype, 4320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .register_layout = labpc_1200_layout, 4330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .has_ao = 1, 4340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_table = &range_labpc_1200_ai, 4350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_code = labpc_1200_ai_gain_bits, 4360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_is_unipolar = labpc_1200_is_unipolar, 4370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_scan_up = 1, 4380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .memory_mapped_io = 0, 4390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 440124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "lab-pc-1200ai", 4420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_speed = 10000, 4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .bustype = isa_bustype, 4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .register_layout = labpc_1200_layout, 4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .has_ao = 0, 4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_table = &range_labpc_1200_ai, 4470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_code = labpc_1200_ai_gain_bits, 4480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_is_unipolar = labpc_1200_is_unipolar, 4490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_scan_up = 1, 4500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .memory_mapped_io = 0, 4510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 452124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "lab-pc+", 4540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_speed = 12000, 4550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .bustype = isa_bustype, 4560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .register_layout = labpc_plus_layout, 4570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .has_ao = 1, 4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_table = &range_labpc_plus_ai, 4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_code = labpc_plus_ai_gain_bits, 4600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_is_unipolar = labpc_plus_is_unipolar, 4610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_scan_up = 0, 4620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .memory_mapped_io = 0, 4630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 464d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 465124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "pci-1200", 4670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = 0x161, 4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_speed = 10000, 4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .bustype = pci_bustype, 4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .register_layout = labpc_1200_layout, 4710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .has_ao = 1, 4720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_table = &range_labpc_1200_ai, 4730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_code = labpc_1200_ai_gain_bits, 4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_range_is_unipolar = labpc_1200_is_unipolar, 4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_scan_up = 1, 4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .memory_mapped_io = 1, 4770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 478e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* dummy entry so pci board works when comedi_config is passed driver name */ 479124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess { 4800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = DRV_NAME, 4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .bustype = pci_bustype, 4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 483124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 484124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 485124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 486124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* 487124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * Useful for shorthand access to the particular board structure 488124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess */ 4899ad007403fa4326586060e443ee344697daa60ecBill Pemberton#define thisboard ((struct labpc_board_struct *)dev->board_ptr) 490124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 491e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* size in bytes of dma buffer */ 492e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertsonstatic const int dma_buffer_size = 0xff00; 493e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* 2 bytes per sample */ 494e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertsonstatic const int sample_size = 2; 495124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 4960a4eb4b6c7c12730254be53d93a67ed2955d5c66Bill Pemberton#define devpriv ((struct labpc_private *)dev->private) 497124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 498139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_labpc = { 499124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess .driver_name = DRV_NAME, 500124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess .module = THIS_MODULE, 501124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess .attach = labpc_attach, 502124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess .detach = labpc_common_detach, 5038629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton .num_names = ARRAY_SIZE(labpc_boards), 504124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess .board_name = &labpc_boards[0].name, 5059ad007403fa4326586060e443ee344697daa60ecBill Pemberton .offset = sizeof(struct labpc_board_struct), 506124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 507124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 508d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 509124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { 5104e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)}, 5114e40cee9c8a46d4231d28ae7ae6d9938cf0526d5Greg Kroah-Hartman {0} 512124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 513124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 514124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori HessMODULE_DEVICE_TABLE(pci, labpc_pci_table); 515d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#endif /* CONFIG_COMEDI_PCI_DRIVERS */ 516124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 517da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic inline int labpc_counter_load(struct comedi_device *dev, 5180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned long base_address, 5190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int counter_number, 5200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int count, unsigned int mode) 521124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 522124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->memory_mapped_io) 523124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return i8254_mm_load((void *)base_address, 0, counter_number, 5240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral count, mode); 525124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 526124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return i8254_load(base_address, 0, counter_number, count, mode); 527124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 528124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 529da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonint labpc_common_attach(struct comedi_device *dev, unsigned long iobase, 5300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int irq, unsigned int dma_chan) 531124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 53234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 533124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 5343297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap unsigned long isr_flags; 5353297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 5363297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap unsigned long dma_flags; 5373297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 538124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess short lsb, msb; 539124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 54088d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, 54188d8ed4b643d2064a663b2f07426963289def676Maurice Dawson thisboard->name, 5420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral iobase); 543412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (irq) 544124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess printk(", irq %u", irq); 545412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (dma_chan) 546124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess printk(", dma %u", dma_chan); 547124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess printk("\n"); 548124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 549124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (iobase == 0) { 550177d42821e2d662fda5bb57d31d33d215fb74fd0Aseem Sethi printk(KERN_ERR "io base address is zero!\n"); 551124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 552124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 553f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* request io regions for isa boards */ 554124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->bustype == isa_bustype) { 555124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* check if io addresses are available */ 556124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!request_region(iobase, LABPC_SIZE, 5570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral driver_labpc.driver_name)) { 55888d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "I/O port conflict\n"); 559124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EIO; 560124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 561124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 562124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dev->iobase = iobase; 563124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 564124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->memory_mapped_io) { 565124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->read_byte = labpc_readb; 566124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte = labpc_writeb; 567124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else { 568124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->read_byte = labpc_inb; 569124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte = labpc_outb; 570124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 571e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* initialize board's command registers */ 572124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); 573124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 574124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); 575124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); 576124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 577124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, 5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND5_REG); 579124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command6_bits, 5800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND6_REG); 581124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 582124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 583124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* grab our IRQ */ 584124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (irq) { 585124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess isr_flags = 0; 586d1ce318496f5943d2cc5e20171fc383a59a1421fIan Abbott if (thisboard->bustype == pci_bustype 587d1ce318496f5943d2cc5e20171fc383a59a1421fIan Abbott || thisboard->bustype == pcmcia_bustype) 588124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess isr_flags |= IRQF_SHARED; 5895f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman if (request_irq(irq, labpc_interrupt, isr_flags, 590124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess driver_labpc.driver_name, dev)) { 59188d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "unable to allocate irq %u\n", irq); 592124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 593124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 594124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 595124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dev->irq = irq; 596124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 5973297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 598e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* grab dma channel */ 599124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (dma_chan > 3) { 60088d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR " invalid dma channel %u\n", dma_chan); 601124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 602124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else if (dma_chan) { 603e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* allocate dma buffer */ 604124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->dma_buffer = 6050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); 606124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->dma_buffer == NULL) { 60788d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR " failed to allocate dma buffer\n"); 608124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -ENOMEM; 609124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 610124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (request_dma(dma_chan, driver_labpc.driver_name)) { 61188d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR " failed to allocate dma channel %u\n", 6120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dma_chan); 613124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 614124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 615124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->dma_chan = dma_chan; 616124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dma_flags = claim_dma_lock(); 617124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess disable_dma(devpriv->dma_chan); 618124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); 619124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess release_dma_lock(dma_flags); 620124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 6213297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 622124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 623124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dev->board_name = thisboard->name; 624124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 625124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (alloc_subdevices(dev, 5) < 0) 626124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -ENOMEM; 627124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 628124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* analog input subdevice */ 629124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s = dev->subdevices + 0; 630124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dev->read_subdev = s; 631124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_AI; 632124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->subdev_flags = 6330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ; 634124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->n_chan = 8; 635124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->len_chanlist = 8; 636e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson s->maxdata = (1 << 12) - 1; /* 12 bit resolution */ 637124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->range_table = thisboard->ai_range_table; 638124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->do_cmd = labpc_ai_cmd; 639124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->do_cmdtest = labpc_ai_cmdtest; 640124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_read = labpc_ai_rinsn; 641124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->cancel = labpc_cancel; 642124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 643124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* analog output */ 644124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s = dev->subdevices + 1; 645124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->has_ao) { 646639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson /* 647639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson * Could provide command support, except it only has a 648412bd046b0a1726f8b168d5056d21213932f9d84tony burrows * one sample hardware buffer for analog output and no 649639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson * underrun flag. 650639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson */ 651124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_AO; 652124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; 653124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->n_chan = NUM_AO_CHAN; 654f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton s->maxdata = (1 << 12) - 1; /* 12 bit resolution */ 655124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->range_table = &range_labpc_ao; 656124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_read = labpc_ao_rinsn; 657124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_write = labpc_ao_winsn; 658124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* initialize analog outputs to a known value */ 659124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < s->n_chan; i++) { 660124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->ao_value[i] = s->maxdata / 2; 661124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess lsb = devpriv->ao_value[i] & 0xff; 662124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess msb = (devpriv->ao_value[i] >> 8) & 0xff; 663124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i)); 664124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i)); 665124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 666124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else { 667124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_UNUSED; 668124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 669124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 670124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* 8255 dio */ 671124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s = dev->subdevices + 2; 672412bd046b0a1726f8b168d5056d21213932f9d84tony burrows /* if board uses io memory we have to give a custom callback 673412bd046b0a1726f8b168d5056d21213932f9d84tony burrows * function to the 8255 driver */ 674124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->memory_mapped_io) 675124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess subdev_8255_init(dev, s, labpc_dio_mem_callback, 6760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (unsigned long)(dev->iobase + DIO_BASE_REG)); 677124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 678124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG); 679124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 680f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* calibration subdevices for boards that have one */ 681124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s = dev->subdevices + 3; 682124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 683124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_CALIB; 684124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; 685124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->n_chan = 16; 686124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->maxdata = 0xff; 687124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_read = labpc_calib_read_insn; 688124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_write = labpc_calib_write_insn; 689124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 690124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < s->n_chan; i++) 691124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess write_caldac(dev, i, s->maxdata / 2); 692124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 693124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_UNUSED; 694124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 695124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* EEPROM */ 696124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s = dev->subdevices + 4; 697124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 698124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_MEMORY; 699124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; 700124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->n_chan = EEPROM_SIZE; 701124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->maxdata = 0xff; 702124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_read = labpc_eeprom_read_insn; 703124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->insn_write = labpc_eeprom_write_insn; 704124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 705412bd046b0a1726f8b168d5056d21213932f9d84tony burrows for (i = 0; i < EEPROM_SIZE; i++) 706124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); 707124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#ifdef LABPC_DEBUG 70888d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR " eeprom:"); 709412bd046b0a1726f8b168d5056d21213932f9d84tony burrows for (i = 0; i < EEPROM_SIZE; i++) 710124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess printk(" %i:0x%x ", i, devpriv->eeprom_data[i]); 711124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess printk("\n"); 712124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 713124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 714124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess s->type = COMEDI_SUBD_UNUSED; 715124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 716124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 717124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 7180656bb352080982f960bfff2b78602a5071c909fMaurice DawsonEXPORT_SYMBOL_GPL(labpc_common_attach); 719124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 720da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) 721124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 722124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long iobase = 0; 723124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int irq = 0; 724124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int dma_chan = 0; 725d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 726124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int retval; 727124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 728124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 729124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* allocate and initialize dev->private */ 7300a4eb4b6c7c12730254be53d93a67ed2955d5c66Bill Pemberton if (alloc_private(dev, sizeof(struct labpc_private)) < 0) 731124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -ENOMEM; 732124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 733e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* get base address, irq etc. based on bustype */ 734124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (thisboard->bustype) { 735124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case isa_bustype: 7363297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 737124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess iobase = it->options[0]; 738124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess irq = it->options[1]; 739124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dma_chan = it->options[2]; 7403297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#else 7413297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap printk(KERN_ERR " this driver has not been built with ISA DMA " 7423297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap "support.\n"); 7433297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap return -EINVAL; 7443297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 745124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 746124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case pci_bustype: 747d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 748124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess retval = labpc_find_device(dev, it->options[0], it->options[1]); 749412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (retval < 0) 750124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return retval; 751124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess retval = mite_setup(devpriv->mite); 752124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (retval < 0) 753124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return retval; 754124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess iobase = (unsigned long)devpriv->mite->daq_io_addr; 755124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess irq = mite_irq(devpriv->mite); 756124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#else 75788d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR " this driver has not been built with PCI " 75888d8ed4b643d2064a663b2f07426963289def676Maurice Dawson "support.\n"); 759124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 760124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 761124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 762124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case pcmcia_bustype: 7630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 7640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (" this driver does not support pcmcia cards, use ni_labpc_cs.o\n"); 765124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 766124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 767124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 76888d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "bug! couldn't determine board type\n"); 769124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 770124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 771124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 772124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 773124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return labpc_common_attach(dev, iobase, irq, dma_chan); 774124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 775124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 776f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* adapted from ni_pcimio for finding mite based boards (pc-1200) */ 777d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 77871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int labpc_find_device(struct comedi_device *dev, int bus, int slot) 779124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 780124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess struct mite_struct *mite; 781124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 782124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (mite = mite_devices; mite; mite = mite->next) { 783124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (mite->used) 784124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess continue; 785e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* if bus/slot are specified then make sure we have the right bus/slot */ 786124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (bus || slot) { 787124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (bus != mite->pcidev->bus->number 7880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral || slot != PCI_SLOT(mite->pcidev->devfn)) 789124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess continue; 790124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 791124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < driver_labpc.num_names; i++) { 792124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_boards[i].bustype != pci_bustype) 793124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess continue; 794124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (mite_device_id(mite) == labpc_boards[i].device_id) { 795124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->mite = mite; 796e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson/* fixup board pointer, in case we were using the dummy "ni_labpc" entry */ 797124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess dev->board_ptr = &labpc_boards[i]; 798124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 799124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 800124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 801124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 80288d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "no device found\n"); 803124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess mite_list_devices(); 804124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EIO; 805124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 806124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 807124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 808da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonint labpc_common_detach(struct comedi_device *dev) 809124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 81088d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "comedi%d: ni_labpc: detach\n", dev->minor); 811124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 812124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (dev->subdevices) 813124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess subdev_8255_cleanup(dev, dev->subdevices + 2); 814124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 8153297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 816124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* only free stuff if it has been allocated by _attach */ 817e4e1f289be88a75dc8b63d50ade1f9a2e6168021Ilia Mirkin kfree(devpriv->dma_buffer); 818124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->dma_chan) 819124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess free_dma(devpriv->dma_chan); 8203297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 821124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (dev->irq) 8225f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(dev->irq, dev); 823124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->bustype == isa_bustype && dev->iobase) 824124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess release_region(dev->iobase, LABPC_SIZE); 825d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 826124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->mite) 827124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess mite_unsetup(devpriv->mite); 828124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 829124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 830124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 831124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess}; 8320656bb352080982f960bfff2b78602a5071c909fMaurice DawsonEXPORT_SYMBOL_GPL(labpc_common_detach); 833124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 834da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_clear_adc_fifo(const struct comedi_device *dev) 835124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 836124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); 837124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 838124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 839124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 840124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 841da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 842124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 843124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long flags; 844124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 8455f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&dev->spinlock, flags); 846124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; 847124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 8485f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&dev->spinlock, flags); 849124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 850124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits = 0; 851124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); 852124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 853124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 854124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 855124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 856da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) 857124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 858124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->chanlist_len == 1) 859124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return MODE_SINGLE_CHAN; 860124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 861124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* chanlist may be NULL during cmdtest. */ 862124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->chanlist == NULL) 863124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return MODE_MULT_CHAN_UP; 864124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 865124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[0]) == CR_CHAN(cmd->chanlist[1])) 866124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return MODE_SINGLE_CHAN_INTERVAL; 867124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 868124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[0]) < CR_CHAN(cmd->chanlist[1])) 869124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return MODE_MULT_CHAN_UP; 870124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 871124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1])) 872124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return MODE_MULT_CHAN_DOWN; 873124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 87488d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "ni_labpc: bug! this should never happen\n"); 875124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 876124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 877124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 878124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 879da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_ai_chanlist_invalid(const struct comedi_device *dev, 8800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral const struct comedi_cmd *cmd) 881124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 882124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int mode, channel, range, aref, i; 883124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 884124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->chanlist == NULL) 885124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 886124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 887124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess mode = labpc_ai_scan_mode(cmd); 888124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 889124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (mode == MODE_SINGLE_CHAN) 890124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 891124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 892124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (mode == MODE_SINGLE_CHAN_INTERVAL) { 893124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->chanlist_len > 0xff) { 894124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 8950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "ni_labpc: chanlist too long for single channel interval mode\n"); 896124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 897124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 898124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 899124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 900124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess channel = CR_CHAN(cmd->chanlist[0]); 901124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess range = CR_RANGE(cmd->chanlist[0]); 902124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess aref = CR_AREF(cmd->chanlist[0]); 903124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 904124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < cmd->chanlist_len; i++) { 905124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 906124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (mode) { 907124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case MODE_SINGLE_CHAN_INTERVAL: 908124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[i]) != channel) { 909124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 9100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "channel scanning order specified in chanlist is not supported by hardware.\n"); 911124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 912124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 913124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 914124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case MODE_MULT_CHAN_UP: 915124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[i]) != i) { 916124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 9170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "channel scanning order specified in chanlist is not supported by hardware.\n"); 918124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 919124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 920124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 921124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case MODE_MULT_CHAN_DOWN: 922124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_CHAN(cmd->chanlist[i]) != 9230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->chanlist_len - i - 1) { 924124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "channel scanning order specified in chanlist is not supported by hardware.\n"); 926124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 927124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 928124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 929124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 93088d8ed4b643d2064a663b2f07426963289def676Maurice Dawson printk(KERN_ERR "ni_labpc: bug! in chanlist check\n"); 931124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 932124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 933124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 934124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 935124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_RANGE(cmd->chanlist[i]) != range) { 936124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 9370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "entries in chanlist must all have the same range\n"); 938124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 939124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 940124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 941124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_AREF(cmd->chanlist[i]) != aref) { 942124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, 9430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "entries in chanlist must all have the same reference\n"); 944124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 945124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 946124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 947124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 948124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 949124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 950124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 951da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_use_continuous_mode(const struct comedi_cmd *cmd) 952124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 953124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN) 954124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 955124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 956124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src == TRIG_FOLLOW) 957124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 958124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 959124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 960124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 961124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 962da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd) 963124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 964124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src != TRIG_TIMER) 965124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 966124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 967124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && 9680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src == TRIG_TIMER) 969124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return cmd->scan_begin_arg; 970124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 971124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return cmd->convert_arg; 972124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 973124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 974da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns) 975124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 976124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src != TRIG_TIMER) 977124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return; 978124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 979124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && 9800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src == TRIG_TIMER) { 981124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_begin_arg = ns; 982124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_arg > cmd->scan_begin_arg) 983124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->convert_arg = cmd->scan_begin_arg; 984124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 985124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->convert_arg = ns; 986124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 987124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 988da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd) 989124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 990124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src != TRIG_TIMER) 991124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 992124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 993124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && 9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_src == TRIG_TIMER) 995124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 996124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 997124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return cmd->scan_begin_arg; 998124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 999124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1000da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns) 1001124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1002124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src != TRIG_TIMER) 1003124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return; 1004124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1005124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && 10060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_src == TRIG_TIMER) 1007124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return; 1008124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1009124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_begin_arg = ns; 1010124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1011124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 10120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_ai_cmdtest(struct comedi_device *dev, 10130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 1014124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1015124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int err = 0; 1016124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int tmp, tmp2; 1017124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int stop_mask; 1018124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1019124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* step 1: make sure trigger sources are trivially valid */ 1020124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1021124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->start_src; 1022124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->start_src &= TRIG_NOW | TRIG_EXT; 1023124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->start_src || tmp != cmd->start_src) 1024124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1025124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1026124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->scan_begin_src; 1027124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT; 1028124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 1029124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1030124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1031124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->convert_src; 1032124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 1033124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->convert_src || tmp != cmd->convert_src) 1034124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1035124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1036124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->scan_end_src; 1037124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_end_src &= TRIG_COUNT; 1038124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 1039124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1040124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1041124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->stop_src; 1042124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess stop_mask = TRIG_COUNT | TRIG_NONE; 1043124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) 1044124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess stop_mask |= TRIG_EXT; 1045124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->stop_src &= stop_mask; 1046124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->stop_src || tmp != cmd->stop_src) 1047124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1048124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1049124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (err) 1050124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1051124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1052124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* step 2: make sure trigger sources are unique and mutually compatible */ 1053124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1054124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) 1055124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1056124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src != TRIG_TIMER && 10570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_FOLLOW && 10580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_EXT) 1059124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1060124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 1061124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1062124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src != TRIG_COUNT && 10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) 1064124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1065124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1066e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* can't have external stop and start triggers at once */ 1067124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) 1068124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1069124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1070124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (err) 1071124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 2; 1072124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1073124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* step 3: make sure arguments are trivially compatible */ 1074124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1075124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->start_arg == TRIG_NOW && cmd->start_arg != 0) { 1076124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->start_arg = 0; 1077124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1078124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1079124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1080412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (!cmd->chanlist_len) 1081124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1082412bd046b0a1726f8b168d5056d21213932f9d84tony burrows 1083124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_end_arg != cmd->chanlist_len) { 1084124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_end_arg = cmd->chanlist_len; 1085124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1086124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1087124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1088124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src == TRIG_TIMER) { 1089124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_arg < thisboard->ai_speed) { 1090124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->convert_arg = thisboard->ai_speed; 1091124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1092124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1093124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1094e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* make sure scan timing is not too fast */ 1095124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src == TRIG_TIMER) { 1096124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src == TRIG_TIMER && 10970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_arg < 10980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->chanlist_len) { 1099124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_begin_arg = 11000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->chanlist_len; 1101124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1102124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1103124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_arg < 11040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisboard->ai_speed * cmd->chanlist_len) { 1105124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->scan_begin_arg = 11060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisboard->ai_speed * cmd->chanlist_len; 1107124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1108124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1109124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1110e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* stop source */ 1111124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (cmd->stop_src) { 1112124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_COUNT: 1113124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!cmd->stop_arg) { 1114124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->stop_arg = 1; 1115124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1116124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1117124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1118124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_NONE: 1119124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_arg != 0) { 1120124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd->stop_arg = 0; 1121124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1122124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1123124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 11241309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 11251309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * TRIG_EXT doesn't care since it doesn't 11261309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * trigger off a numbered channel 11271309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1128124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 1129124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1130124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1131124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1132124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (err) 1133124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 3; 1134124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1135124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* step 4: fix up any arguments */ 1136124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1137124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp = cmd->convert_arg; 1138124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess tmp2 = cmd->scan_begin_arg; 1139124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_adc_timing(dev, cmd); 1140124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg) 1141124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess err++; 1142124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1143124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (err) 1144124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 4; 1145124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1146124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_chanlist_invalid(dev, cmd)) 1147124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 5; 1148124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1149124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 1150124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1151124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1152da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1153124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1154124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int channel, range, aref; 11553297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1156124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long irq_flags; 11573297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1158124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int ret; 1159d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 1160ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &async->cmd; 1161124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess enum transfer_type xfer; 1162124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long flags; 1163124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1164124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (!dev->irq) { 1165124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "no irq assigned, cannot perform command"); 1166124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1167124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1168124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1169124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess range = CR_RANGE(cmd->chanlist[0]); 1170124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess aref = CR_AREF(cmd->chanlist[0]); 1171124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 117225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* make sure board is disabled before setting up acquisition */ 11735f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&dev->spinlock, flags); 1174124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; 1175124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 11765f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&dev->spinlock, flags); 1177124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1178124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits = 0; 1179124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); 1180124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1181f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* initialize software conversion count */ 1182412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (cmd->stop_src == TRIG_COUNT) 1183124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->count = cmd->stop_arg * cmd->chanlist_len; 118465d6d26c6bcd802ebe2b22a29d9b6bbebfd8d7f8Maurice Dawson 1185f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* setup hardware conversion counter */ 1186124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src == TRIG_EXT) { 11871309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 11881309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * load counter a1 with count of 3 11891309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * (pc+ manual says this is minimum allowed) using mode 0 11901309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1191124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, 11920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1, 3, 0); 1193124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (ret < 0) { 1194124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "error loading counter a1"); 1195124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1196124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 11971309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson } else /* 11981309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * otherwise, just put a1 in mode 0 11991309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * with no count to set its output low 12001309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1201124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(INIT_A1_BITS, 12020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COUNTER_A_CONTROL_REG); 1203124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 12043297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1205f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* figure out what method we will use to transfer data */ 1206f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton if (devpriv->dma_chan && /* need a dma channel allocated */ 12071309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 12081309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * dma unsafe at RT priority, 12091309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * and too much setup time for TRIG_WAKE_EOS for 12101309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 12110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 && 12120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* only available on the isa boards */ 12130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisboard->bustype == isa_bustype) { 1214124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess xfer = isa_dma_transfer; 12151309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* pc-plus has no fifo-half full interrupt */ 12163297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap } else 12173297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 12183297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap if (thisboard->register_layout == labpc_1200_layout && 12190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* wake-end-of-scan should interrupt on fifo not empty */ 12200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (cmd->flags & TRIG_WAKE_EOS) == 0 && 12210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* make sure we are taking more than just a few points */ 12220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) { 1223124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess xfer = fifo_half_full_transfer; 1224124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 1225124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess xfer = fifo_not_empty_transfer; 1226124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->current_transfer = xfer; 1227124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1228f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* setup command6 register for 1200 boards */ 1229124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 1230f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* reference inputs to ground or common? */ 1231124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (aref != AREF_GROUND) 1232124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_COMMON_BIT; 1233124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1234124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_COMMON_BIT; 1235f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* bipolar or unipolar range? */ 1236124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->ai_range_is_unipolar[range]) 1237124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_UNIP_BIT; 1238124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1239124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_UNIP_BIT; 1240f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* interrupt on fifo half full? */ 1241124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (xfer == fifo_half_full_transfer) 1242124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT; 1243124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1244124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; 1245f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable interrupt on counter a1 terminal count? */ 1246124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src == TRIG_EXT) 1247124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= A1_INTR_EN_BIT; 1248124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1249124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~A1_INTR_EN_BIT; 1250f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* are we scanning up or down through channels? */ 1251124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) 1252124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_SCAN_UP_BIT; 1253124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1254124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_SCAN_UP_BIT; 1255f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write to register */ 1256124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command6_bits, 12570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND6_REG); 1258124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1259124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1260124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* setup channel list, etc (command1 register) */ 1261124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits = 0; 1262124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) 1263124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); 1264124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1265124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess channel = CR_CHAN(cmd->chanlist[0]); 1266e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* munge channel bits for differential / scan disabled mode */ 1267124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) 1268124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess channel *= 2; 1269124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits |= ADC_CHAN_BITS(channel); 1270124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits |= thisboard->ai_range_code[range]; 1271124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); 1272e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* manual says to set scan enable bit on second pass */ 1273124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP || 12740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) { 1275124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits |= ADC_SCAN_EN_BIT; 1276e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* need a brief delay before enabling scan, or scan 1277e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * list will get screwed when you switch 1278124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * between scan up to scan down mode - dunno why */ 12795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1280124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command1_bits, 12810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND1_REG); 1282124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1283f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* setup any external triggering/pacing (command4 register) */ 1284124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits = 0; 1285124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src != TRIG_EXT) 1286124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; 1287124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* XXX should discard first scan when using interval scanning 1288124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * since manual says it is not synced with scan clock */ 1289124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_use_continuous_mode(cmd) == 0) { 1290124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; 1291124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->scan_begin_src == TRIG_EXT) 1292124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= EXT_SCAN_EN_BIT; 1293124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1294f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* single-ended/differential */ 1295124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (aref == AREF_DIFF) 1296124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= ADC_DIFF_BIT; 1297124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); 1298124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1299124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(cmd->chanlist_len, 13000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + INTERVAL_COUNT_REG); 1301f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* load count */ 1302124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(INTERVAL_LOAD_BITS, 13030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + INTERVAL_LOAD_REG); 1304124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1305124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { 1306f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set up pacing */ 1307124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_adc_timing(dev, cmd); 1308f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* load counter b0 in mode 3 */ 1309124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 13100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0, devpriv->divisor_b0, 3); 1311124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (ret < 0) { 1312124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "error loading counter b0"); 1313124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1314124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1315124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1316f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set up conversion pacing */ 1317124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_convert_period(cmd)) { 1318f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* load counter a0 in mode 2 */ 1319124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, 13200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0, devpriv->divisor_a0, 2); 1321124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (ret < 0) { 1322124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "error loading counter a0"); 1323124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1324124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1325124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 1326124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(INIT_A0_BITS, 13270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COUNTER_A_CONTROL_REG); 1328124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1329f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set up scan pacing */ 1330124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_scan_period(cmd)) { 1331f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* load counter b1 in mode 2 */ 1332124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, 13330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1, devpriv->divisor_b1, 2); 1334124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (ret < 0) { 1335124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "error loading counter b1"); 1336124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1337124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1338124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1339124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1340124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_clear_adc_fifo(dev); 1341124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 13423297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1343f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set up dma transfer */ 1344124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (xfer == isa_dma_transfer) { 1345124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess irq_flags = claim_dma_lock(); 1346124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess disable_dma(devpriv->dma_chan); 1347124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* clear flip-flop to make sure 2-byte registers for 1348124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * count and address get set correctly */ 1349124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess clear_dma_ff(devpriv->dma_chan); 1350124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess set_dma_addr(devpriv->dma_chan, 13510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral virt_to_bus(devpriv->dma_buffer)); 1352f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set appropriate size of transfer */ 1353124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd); 1354124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src == TRIG_COUNT && 13550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->count * sample_size < devpriv->dma_transfer_size) { 1356124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->dma_transfer_size = 13570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->count * sample_size; 1358124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1359124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); 1360124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess enable_dma(devpriv->dma_chan); 1361124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess release_dma_lock(irq_flags); 1362f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable board's dma */ 1363124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT; 1364124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 1365124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT; 13663297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1367124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1368f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable error interrupts */ 1369124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits |= ERR_INTR_EN_BIT; 1370f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable fifo not empty interrupt? */ 1371124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (xfer == fifo_not_empty_transfer) 1372124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT; 1373124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1374124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; 1375124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); 1376124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 137725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* startup acquisition */ 1378124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1379f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* command2 reg */ 1380f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* use 2 cascaded counters for pacing */ 13815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&dev->spinlock, flags); 1382124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits |= CASCADE_BIT; 1383124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (cmd->start_src) { 1384124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_EXT: 1385124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits |= HWTRIG_BIT; 1386124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~PRETRIG_BIT & ~SWTRIG_BIT; 1387124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1388124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_NOW: 1389124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits |= SWTRIG_BIT; 1390124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~PRETRIG_BIT & ~HWTRIG_BIT; 1391124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1392124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 1393124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "bug with start_src"); 1394124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1395124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1396124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1397124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (cmd->stop_src) { 1398124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_EXT: 1399124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits |= HWTRIG_BIT | PRETRIG_BIT; 1400124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1401124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_COUNT: 1402124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_NONE: 1403124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1404124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 1405124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "bug with stop_src"); 1406124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1407124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1408124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 14095f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&dev->spinlock, flags); 1410124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1411124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 1412124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1413124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1414124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess/* interrupt service routine */ 141570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t labpc_interrupt(int irq, void *d) 1416124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 141771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = d; 141834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->read_subdev; 1419d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 1420ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd; 1421124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1422124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (dev->attached == 0) { 1423124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "premature interrupt"); 1424124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return IRQ_HANDLED; 1425124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1426124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1427124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async = s->async; 1428124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cmd = &async->cmd; 1429124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events = 0; 1430124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1431e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* read board status */ 1432124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); 1433124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) 1434124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->status2_bits = 14350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->read_byte(dev->iobase + STATUS2_REG); 1436124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1437124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if ((devpriv->status1_bits & (DMATC_BIT | TIMER_BIT | OVERFLOW_BIT | 14380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral OVERRUN_BIT | DATA_AVAIL_BIT)) == 0 14390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && (devpriv->status2_bits & A1_TC_BIT) == 0 14400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && (devpriv->status2_bits & FNHF_BIT)) { 1441124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return IRQ_NONE; 1442124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1443124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1444124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->status1_bits & OVERRUN_BIT) { 1445e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* clear error interrupt */ 1446124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); 1447124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 1448124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_event(dev, s); 1449124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "overrun"); 1450124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return IRQ_HANDLED; 1451124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1452124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 14533297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1454124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->current_transfer == isa_dma_transfer) { 1455639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson /* 1456639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson * if a dma terminal count of external stop trigger 1457639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson * has occurred 1458639b9f1ee5987270be2bca4bf8b7e6110d3b47ecStewart Robertson */ 1459124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->status1_bits & DMATC_BIT || 14600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (thisboard->register_layout == labpc_1200_layout 14610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral && devpriv->status2_bits & A1_TC_BIT)) { 1462124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess handle_isa_dma(dev); 1463124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1464124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else 14653297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1466124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_drain_fifo(dev); 1467124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1468124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->status1_bits & TIMER_BIT) { 1469124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "handled timer interrupt?"); 1470f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear it */ 1471124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG); 1472124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1473124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1474124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->status1_bits & OVERFLOW_BIT) { 1475f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear error interrupt */ 1476124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); 1477124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 1478124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_event(dev, s); 1479124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "overflow"); 1480124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return IRQ_HANDLED; 1481124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1482f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* handle external stop trigger */ 1483124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src == TRIG_EXT) { 1484124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->status2_bits & A1_TC_BIT) { 1485124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_drain_dregs(dev); 1486124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_cancel(dev, s); 1487124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_EOA; 1488124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1489124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1490124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1491124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* TRIG_COUNT end of acquisition */ 1492124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd->stop_src == TRIG_COUNT) { 1493124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->count == 0) { 1494124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_cancel(dev, s); 1495124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_EOA; 1496124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1497124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1498124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1499124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_event(dev, s); 1500124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return IRQ_HANDLED; 1501124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1502124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1503f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* read all available samples from ai fifo */ 1504da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_drain_fifo(struct comedi_device *dev) 1505124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1506124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int lsb, msb; 1507790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short data; 1508d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = dev->read_subdev->async; 1509124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int timeout = 10000; 1510124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int i; 1511124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1512124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); 1513124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1514124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout; 15150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral i++) { 1516f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* quit if we have all the data we want */ 1517124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (async->cmd.stop_src == TRIG_COUNT) { 1518124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->count == 0) 1519124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1520124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->count--; 1521124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1522124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 1523124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 1524124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess data = (msb << 8) | lsb; 1525124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cfc_write_to_buffer(dev->read_subdev, data); 1526124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->status1_bits = 15270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->read_byte(dev->iobase + STATUS1_REG); 1528124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1529124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (i == timeout) { 1530124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "ai timeout, fifo never empties"); 1531124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 1532124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -1; 1533124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1534124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1535124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 1536124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1537124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 15383297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1539da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_drain_dma(struct comedi_device *dev) 1540124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 154134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->read_subdev; 1542d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 1543124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int status; 1544124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long flags; 1545124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int max_points, num_points, residue, leftover; 1546124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 1547124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1548124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess status = devpriv->status1_bits; 1549124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1550124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess flags = claim_dma_lock(); 1551124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess disable_dma(devpriv->dma_chan); 1552124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* clear flip-flop to make sure 2-byte registers for 1553124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * count and address get set correctly */ 1554124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess clear_dma_ff(devpriv->dma_chan); 1555124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1556f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* figure out how many points to read */ 1557124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess max_points = devpriv->dma_transfer_size / sample_size; 1558124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* residue is the number of points left to be done on the dma 1559124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * transfer. It should always be zero at this point unless 1560124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * the stop_src is set to external triggering. 1561124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess */ 1562124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess residue = get_dma_residue(devpriv->dma_chan) / sample_size; 1563124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess num_points = max_points - residue; 1564124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT) 1565124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess num_points = devpriv->count; 1566124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1567f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* figure out how many points will be stored next time */ 1568124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess leftover = 0; 1569124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (async->cmd.stop_src != TRIG_COUNT) { 1570124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess leftover = devpriv->dma_transfer_size / sample_size; 1571124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else if (devpriv->count > num_points) { 1572124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess leftover = devpriv->count - num_points; 1573124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (leftover > max_points) 1574124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess leftover = max_points; 1575124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1576124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1577124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* write data to comedi buffer */ 1578412bd046b0a1726f8b168d5056d21213932f9d84tony burrows for (i = 0; i < num_points; i++) 1579124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess cfc_write_to_buffer(s, devpriv->dma_buffer[i]); 158065d6d26c6bcd802ebe2b22a29d9b6bbebfd8d7f8Maurice Dawson 1581124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (async->cmd.stop_src == TRIG_COUNT) 1582124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->count -= num_points; 1583124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1584f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set address and count for next transfer */ 1585124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer)); 1586124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess set_dma_count(devpriv->dma_chan, leftover * sample_size); 1587124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess release_dma_lock(flags); 1588124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1589124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess async->events |= COMEDI_CB_BLOCK; 1590124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1591124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1592da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void handle_isa_dma(struct comedi_device *dev) 1593124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1594124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_drain_dma(dev); 1595124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1596124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess enable_dma(devpriv->dma_chan); 1597124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1598f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear dma tc interrupt */ 1599124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); 1600124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 16013297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1602124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 160325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* makes sure all data acquired by board is transferred to comedi (used 160425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * when acquisition is terminated by stop_src == TRIG_EXT). */ 1605da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_drain_dregs(struct comedi_device *dev) 1606124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 16073297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1608124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->current_transfer == isa_dma_transfer) 1609124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_drain_dma(dev); 16103297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1611124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1612124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_drain_fifo(dev); 1613124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1614124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1615da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 16160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1617124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1618124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i, n; 1619124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int chan, range; 1620124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int lsb, msb; 1621124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int timeout = 1000; 1622124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long flags; 1623124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1624f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* disable timed conversions */ 16255f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&dev->spinlock, flags); 1626124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; 1627124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 16285f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&dev->spinlock, flags); 1629124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1630f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* disable interrupt generation and dma */ 1631124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command3_bits = 0; 1632124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); 1633124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1634124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* set gain and channel */ 1635124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits = 0; 1636124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess chan = CR_CHAN(insn->chanspec); 1637124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess range = CR_RANGE(insn->chanspec); 1638124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits |= thisboard->ai_range_code[range]; 1639e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* munge channel bits for differential/scan disabled mode */ 1640124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_AREF(insn->chanspec) == AREF_DIFF) 1641124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess chan *= 2; 1642124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command1_bits |= ADC_CHAN_BITS(chan); 1643124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); 1644124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1645e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* setup command6 register for 1200 boards */ 1646124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 1647f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* reference inputs to ground or common? */ 1648124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_AREF(insn->chanspec) != AREF_GROUND) 1649124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_COMMON_BIT; 1650124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1651124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_COMMON_BIT; 1652e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* bipolar or unipolar range? */ 1653124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->ai_range_is_unipolar[range]) 1654124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= ADC_UNIP_BIT; 1655124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1656124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_UNIP_BIT; 1657e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* don't interrupt on fifo half full */ 1658124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; 1659e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* don't enable interrupt on counter a1 terminal count? */ 1660124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~A1_INTR_EN_BIT; 1661e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* write to register */ 1662124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command6_bits, 16630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND6_REG); 1664124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1665e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* setup command4 register */ 1666124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits = 0; 1667124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; 1668e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* single-ended/differential */ 1669124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (CR_AREF(insn->chanspec) == AREF_DIFF) 1670124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command4_bits |= ADC_DIFF_BIT; 1671124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); 1672124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 16731309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 16741309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * initialize pacer counter output to make sure it doesn't 16751309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * cause any problems 16761309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1677124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG); 1678124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1679124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_clear_adc_fifo(dev); 1680124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1681124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (n = 0; n < insn->n; n++) { 1682124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* trigger conversion */ 1683124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(0x1, dev->iobase + ADC_CONVERT_REG); 1684124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1685124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < timeout; i++) { 1686124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->read_byte(dev->iobase + 16870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral STATUS1_REG) & DATA_AVAIL_BIT) 1688124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 16895f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1690124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1691124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (i == timeout) { 1692124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "timeout"); 1693124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -ETIME; 1694124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1695124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 1696124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); 1697124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess data[n] = (msb << 8) | lsb; 1698124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1699124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1700124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return n; 1701124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1702124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1703f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* analog output insn */ 1704da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 17050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1706124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1707124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int channel, range; 1708124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned long flags; 1709124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int lsb, msb; 1710124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1711124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess channel = CR_CHAN(insn->chanspec); 1712124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1713e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* turn off pacing of analog output channel */ 1714124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess /* note: hardware bug in daqcard-1200 means pacing cannot 1715124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess * be independently enabled/disabled for its the two channels */ 17165f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&dev->spinlock, flags); 1717124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command2_bits &= ~DAC_PACED_BIT(channel); 1718124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); 17195f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&dev->spinlock, flags); 1720124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1721e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* set range */ 1722124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (thisboard->register_layout == labpc_1200_layout) { 1723124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess range = CR_RANGE(insn->chanspec); 1724124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (range & AO_RANGE_IS_UNIPOLAR) 1725124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits |= DAC_UNIP_BIT(channel); 1726124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1727124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command6_bits &= ~DAC_UNIP_BIT(channel); 1728f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write to register */ 1729124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command6_bits, 17300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND6_REG); 1731124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1732e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* send data */ 1733124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess lsb = data[0] & 0xff; 1734124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess msb = (data[0] >> 8) & 0xff; 1735124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel)); 1736124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel)); 1737124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1738e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* remember value for readback */ 1739124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->ao_value[channel] = data[0]; 1740124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1741124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1742124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1743124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1744f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* analog output readback insn */ 1745da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 17460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1747124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1748124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; 1749124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1750124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1751124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1752124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 17530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_calib_read_insn(struct comedi_device *dev, 17540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 17550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1756124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1757124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)]; 1758124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1759124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1760124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1761124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 17620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_calib_write_insn(struct comedi_device *dev, 17630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 17640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1765124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1766124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int channel = CR_CHAN(insn->chanspec); 1767124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1768124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess write_caldac(dev, channel, data[0]); 1769124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1770124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1771124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 17720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_eeprom_read_insn(struct comedi_device *dev, 17730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 17740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1775124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1776124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)]; 1777124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1778124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1779124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1780124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 17810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int labpc_eeprom_write_insn(struct comedi_device *dev, 17820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 17830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1784124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1785124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int channel = CR_CHAN(insn->chanspec); 1786124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int ret; 1787124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1788f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* only allow writes to user area of eeprom */ 1789124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (channel < 16 || channel > 127) { 17900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 17910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)"); 1792124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -EINVAL; 1793124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1794124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1795124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess ret = labpc_eeprom_write(dev, channel, data[0]); 1796124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (ret < 0) 1797124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return ret; 1798124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1799124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 1; 1800124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1801124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 18023297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#ifdef CONFIG_ISA_DMA_API 1803f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* utility function that suggests a dma transfer size in bytes */ 1804ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd) 1805124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1806124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int size; 1807124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int freq; 1808124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1809124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (cmd.convert_src == TRIG_TIMER) 1810124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess freq = 1000000000 / cmd.convert_arg; 1811e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* return some default value */ 1812124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1813124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess freq = 0xffffffff; 1814124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1815e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* make buffer fill in no more than 1/3 second */ 1816124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess size = (freq / 3) * sample_size; 1817124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1818e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* set a minimum and maximum size allowed */ 1819124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (size > dma_buffer_size) 1820124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess size = dma_buffer_size - dma_buffer_size % sample_size; 1821124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else if (size < sample_size) 1822124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess size = sample_size; 1823124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1824124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return size; 1825124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 18263297d6c7c84a2a3f62b41b703a2963759e822e96Randy Dunlap#endif 1827124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1828f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* figures out what counter values to use based on command */ 1829da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) 1830124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1831e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* max value for 16 bit counter in mode 2 */ 1832e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson const int max_counter_value = 0x10000; 1833e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* min value for 16 bit counter in mode 2 */ 1834e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson const int min_counter_value = 2; 1835124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int base_period; 1836124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1837e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* 1838e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * if both convert and scan triggers are TRIG_TIMER, then they 1839e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * both rely on counter b0 1840e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson */ 1841124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) { 1842e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* 1843e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * pick the lowest b0 divisor value we can (for maximum input 1844e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * clock speed on convert and scan counters) 1845e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson */ 1846124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) / 18470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (LABPC_TIMER_BASE * max_counter_value) + 1; 1848124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_b0 < min_counter_value) 1849124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b0 = min_counter_value; 1850124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_b0 > max_counter_value) 1851124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b0 = max_counter_value; 1852124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1853124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess base_period = LABPC_TIMER_BASE * devpriv->divisor_b0; 1854124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1855f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set a0 for conversion frequency and b1 for scan frequency */ 1856124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess switch (cmd->flags & TRIG_ROUND_MASK) { 1857124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess default: 1858124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_ROUND_NEAREST: 1859124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_a0 = 18600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (labpc_ai_convert_period(cmd) + 18610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (base_period / 2)) / base_period; 1862124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b1 = 18630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (labpc_ai_scan_period(cmd) + 18640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (base_period / 2)) / base_period; 1865124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1866124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_ROUND_UP: 1867124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_a0 = 18680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (labpc_ai_convert_period(cmd) + (base_period - 18690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1)) / base_period; 1870124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b1 = 18710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (labpc_ai_scan_period(cmd) + (base_period - 18720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1)) / base_period; 1873124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1874124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess case TRIG_ROUND_DOWN: 1875124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_a0 = 18760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral labpc_ai_convert_period(cmd) / base_period; 1877124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b1 = 18780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral labpc_ai_scan_period(cmd) / base_period; 1879124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 1880124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1881f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* make sure a0 and b1 values are acceptable */ 1882124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_a0 < min_counter_value) 1883124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_a0 = min_counter_value; 1884124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_a0 > max_counter_value) 1885124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_a0 = max_counter_value; 1886124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_b1 < min_counter_value) 1887124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b1 = min_counter_value; 1888124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (devpriv->divisor_b1 > max_counter_value) 1889124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->divisor_b1 = max_counter_value; 1890f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write corrected timings to command */ 1891124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_set_ai_convert_period(cmd, 18920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral base_period * devpriv->divisor_a0); 1893124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_set_ai_scan_period(cmd, 18940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral base_period * devpriv->divisor_b1); 1895e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* 1896e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * if only one TRIG_TIMER is used, we can employ the generic 1897e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson * cascaded timing functions 1898e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson */ 1899124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else if (labpc_ai_scan_period(cmd)) { 1900124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int scan_period; 1901124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1902124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess scan_period = labpc_ai_scan_period(cmd); 19031309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 19041309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * calculate cascaded counter values 19051309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * that give desired scan timing 19061309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1907124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, 19080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &(devpriv->divisor_b1), 19090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &(devpriv->divisor_b0), 19100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &scan_period, 19110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 1912124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_set_ai_scan_period(cmd, scan_period); 1913124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else if (labpc_ai_convert_period(cmd)) { 1914124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int convert_period; 1915124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1916124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess convert_period = labpc_ai_convert_period(cmd); 19171309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson /* 19181309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * calculate cascaded counter values 19191309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson * that give desired conversion timing 19201309e617bc56f2f8af9a9c5aab1224a45539002aMaurice Dawson */ 1921124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, 19220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &(devpriv->divisor_a0), 19230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &(devpriv->divisor_b0), 19240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &convert_period, 19250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 1926124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_set_ai_convert_period(cmd, convert_period); 1927124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1928124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1929124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1930124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hessstatic int labpc_dio_mem_callback(int dir, int port, int data, 19310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned long iobase) 1932124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1933124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (dir) { 1934124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess writeb(data, (void *)(iobase + port)); 1935124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 1936124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } else { 1937124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return readb((void *)(iobase + port)); 1938124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1939124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1940124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1941f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* lowlevel write to eeprom/dac */ 1942da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void labpc_serial_out(struct comedi_device *dev, unsigned int value, 19430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int value_width) 1944124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1945124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 1946124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1947124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 1; i <= value_width; i++) { 1948f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear serial clock */ 1949124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~SCLOCK_BIT; 1950f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send bits most significant bit first */ 1951124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (value & (1 << (value_width - i))) 1952124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= SDATA_BIT; 1953124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess else 1954124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~SDATA_BIT; 19555f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1956124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, 19570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND5_REG); 1958f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set clock to load bit */ 1959124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= SCLOCK_BIT; 19605f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1961124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, 19620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND5_REG); 1963124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1964124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1965124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1966f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* lowlevel read from eeprom */ 1967da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int labpc_serial_in(struct comedi_device *dev) 1968124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1969124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int value = 0; 1970124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 1971f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton const int value_width = 8; /* number of bits wide values are */ 1972124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1973124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 1; i <= value_width; i++) { 1974f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set serial clock */ 1975124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= SCLOCK_BIT; 19765f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1977124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, 19780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND5_REG); 1979f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear clock bit */ 1980124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~SCLOCK_BIT; 19815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1982124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, 19830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + COMMAND5_REG); 1984f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* read bits most significant bit first */ 19855f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 1986124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->status2_bits = 19870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral devpriv->read_byte(dev->iobase + STATUS2_REG); 1988412bd046b0a1726f8b168d5056d21213932f9d84tony burrows if (devpriv->status2_bits & EEPROM_OUT_BIT) 1989124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess value |= 1 << (value_width - i); 1990124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 1991124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 1992124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return value; 1993124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 1994124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 19950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic unsigned int labpc_eeprom_read(struct comedi_device *dev, 19960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int address) 1997124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 1998124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int value; 1999e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* bits to tell eeprom to expect a read */ 2000e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson const int read_instruction = 0x3; 2001e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson /* 8 bit write lengths to eeprom */ 2002e41a6f6d9cb7404420d596f27609a3f4f55dcaf5Stewart Robertson const int write_length = 8; 2003124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2004f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable read/write to eeprom */ 2005124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT; 20065f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2007124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2008124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; 20095f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2010124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2011124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2012f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send read instruction */ 2013124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, read_instruction, write_length); 2014f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send 8 bit address to read from */ 2015124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, address, write_length); 2016f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* read result */ 2017124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess value = labpc_serial_in(dev); 2018124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2019f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* disable read/write to eeprom */ 2020124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; 20215f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2022124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2023124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2024124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return value; 2025124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 2026124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2027d6269644e1f8fc7931c4d6b86d58de7af63a5fc9Julia Lawallstatic int labpc_eeprom_write(struct comedi_device *dev, 2028d6269644e1f8fc7931c4d6b86d58de7af63a5fc9Julia Lawall unsigned int address, unsigned int value) 2029124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 2030124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int write_enable_instruction = 0x6; 2031124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int write_instruction = 0x2; 2032f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton const int write_length = 8; /* 8 bit write lengths to eeprom */ 2033124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int write_in_progress_bit = 0x1; 2034124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int timeout = 10000; 2035124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess int i; 2036124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2037f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* make sure there isn't already a write in progress */ 2038124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess for (i = 0; i < timeout; i++) { 2039124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if ((labpc_eeprom_read_status(dev) & write_in_progress_bit) == 20400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0) 2041124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess break; 2042124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 2043124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (i == timeout) { 2044124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess comedi_error(dev, "eeprom write timed out"); 2045124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return -ETIME; 2046124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess } 2047f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* update software copy of eeprom */ 2048124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->eeprom_data[address] = value; 2049124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2050f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable read/write to eeprom */ 2051124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT; 20525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2053124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2054124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; 20555f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2056124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2057124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2058f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send write_enable instruction */ 2059124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, write_enable_instruction, write_length); 2060124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT; 20615f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2062124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2063124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2064f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send write instruction */ 2065124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= EEPROM_EN_BIT; 20665f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2067124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2068124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, write_instruction, write_length); 2069f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send 8 bit address to write to */ 2070124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, address, write_length); 2071f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write value */ 2072124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, value, write_length); 2073124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT; 20745f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2075124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2076124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2077f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* disable read/write to eeprom */ 2078124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; 20795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2080124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2081124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2082124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return 0; 2083124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 2084124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2085da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int labpc_eeprom_read_status(struct comedi_device *dev) 2086124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 2087124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess unsigned int value; 2088124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess const int read_status_instruction = 0x5; 2089f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton const int write_length = 8; /* 8 bit write lengths to eeprom */ 2090124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2091f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* enable read/write to eeprom */ 2092124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT; 20935f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2094124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2095124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; 20965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2097124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2098124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2099f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* send read status instruction */ 2100124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, read_status_instruction, write_length); 2101f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* read result */ 2102124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess value = labpc_serial_in(dev); 2103124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2104f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* disable read/write to eeprom */ 2105124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; 21065f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2107124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2108124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2109124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return value; 2110124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 2111124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2112f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton/* writes to 8 bit calibration dacs */ 2113da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void write_caldac(struct comedi_device *dev, unsigned int channel, 21140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int value) 2115124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess{ 2116124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess if (value == devpriv->caldac[channel]) 2117124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess return; 2118124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->caldac[channel] = value; 2119124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2120f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* clear caldac load bit and make sure we don't write to eeprom */ 2121124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= 21220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ~CALDAC_LOAD_BIT & ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; 21235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2124124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2125124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2126f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write 4 bit channel */ 2127124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, channel, 4); 2128f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* write 8 bit caldac value */ 2129124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess labpc_serial_out(dev, value, 8); 2130124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2131f6b49620a43ca661246d209009b849d7d3030caeBill Pemberton /* set and clear caldac bit to load caldac value */ 2132124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits |= CALDAC_LOAD_BIT; 21335f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2134124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2135124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->command5_bits &= ~CALDAC_LOAD_BIT; 21365f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 2137124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); 2138124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess} 2139124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 2140d6aa8366dde1656f859b6ebf5face1718793a467Randy Dunlap#ifdef CONFIG_COMEDI_PCI_DRIVERS 2141727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_labpc_pci_probe(struct pci_dev *dev, 2142727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas const struct pci_device_id *ent) 2143727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 2144727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return comedi_pci_auto_config(dev, driver_labpc.driver_name); 2145727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 2146727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2147727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_labpc_pci_remove(struct pci_dev *dev) 2148727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 2149727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_pci_auto_unconfig(dev); 2150727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 2151727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2152727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_labpc_pci_driver = { 2153727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .id_table = labpc_pci_table, 2154727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .probe = &driver_labpc_pci_probe, 2155727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .remove = __devexit_p(&driver_labpc_pci_remove) 2156727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}; 2157727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2158727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_labpc_init_module(void) 2159727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 2160727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas int retval; 2161727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2162727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas retval = comedi_driver_register(&driver_labpc); 2163727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas if (retval < 0) 2164727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return retval; 2165727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2166727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas driver_labpc_pci_driver.name = (char *)driver_labpc.driver_name; 2167727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return pci_register_driver(&driver_labpc_pci_driver); 2168727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 2169727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2170727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_labpc_cleanup_module(void) 2171727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 2172727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas pci_unregister_driver(&driver_labpc_pci_driver); 2173727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_driver_unregister(&driver_labpc); 2174727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 2175727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 2176727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_labpc_init_module); 2177727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_labpc_cleanup_module); 2178124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#else 21797114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_labpc_init_module(void) 21807114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 21817114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_labpc); 21827114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 21837114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 21847114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_labpc_cleanup_module(void) 21857114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 21867114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_labpc); 21877114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 21887114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 21897114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_labpc_init_module); 21907114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_labpc_cleanup_module); 2191124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess#endif 2192124b13b26df5dab0236520de95e1cc1dea06e3c3Frank Mori Hess 219390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 219490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 219590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 219690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 2197