cb_pcidas.c revision d163679ceec20c50f9aee880fa76c0c1185244a8
159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi/drivers/cb_pcidas.c 359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Developed by Ivan Martinez and Frank Mori Hess, with valuable help from 559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez David Schleef and the rest of the Comedi developers comunity. 659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk> 859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net> 959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez COMEDI - Linux Control and Measurement Device Interface 1159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> 1259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez This program is free software; you can redistribute it and/or modify 1459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez it under the terms of the GNU General Public License as published by 1559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez the Free Software Foundation; either version 2 of the License, or 1659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez (at your option) any later version. 1759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez This program is distributed in the hope that it will be useful, 1959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez but WITHOUT ANY WARRANTY; without even the implied warranty of 2059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez GNU General Public License for more details. 2259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 2359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez You should have received a copy of the GNU General Public License 2459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez along with this program; if not, write to the Free Software 2559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 2759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez************************************************************************ 2859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/ 2959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 3059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDriver: cb_pcidas 3159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDescription: MeasurementComputing PCI-DAS series with the AMCC S5933 PCI controller 3259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezAuthor: Ivan Martinez <imr@oersted.dtu.dk>, 3359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez Frank Mori Hess <fmhess@users.sourceforge.net> 3459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezUpdated: 2003-3-11 3559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDevices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas), 3659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr, 3759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez PCI-DAS1000, PCI-DAS1001, PCI_DAS1002 3859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 3959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezStatus: 4059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez There are many reports of the driver being used with most of the 4159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez supported cards. Despite no detailed log is maintained, it can 4259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez be said that the driver is quite tested and stable. 4359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 4459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez The boards may be autocalibrated using the comedi_calibrate 4559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez utility. 4659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 4759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezConfiguration options: 4859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez [0] - PCI bus of device (optional) 4959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez [1] - PCI slot of device (optional) 5059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez If bus/slot is not specified, the first supported 5159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez PCI device found will be used. 5259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 5359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezFor commands, the scanned channels must be consecutive 5459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez(i.e. 4-5-6-7, 2-3-4,...), and must all have the same 5559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezrange and aref. 5659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/ 5759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 5859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 5959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezTODO: 6059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 6159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezanalog triggering on 1602 series 6259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/ 6359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 6459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "../comedidev.h" 6559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include <linux/delay.h> 6659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 6759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8253.h" 6859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8255.h" 6959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "amcc_s5933.h" 7059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_pci.h" 7159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_fc.h" 7259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 7359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#undef CB_PCIDAS_DEBUG // disable debugging code 7459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez//#define CB_PCIDAS_DEBUG // enable debugging code 7559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 7659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// PCI vendor number of ComputerBoards/MeasurementComputing 7759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PCI_VENDOR_ID_CB 0x1307 7859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define TIMER_BASE 100 // 10MHz master clock 7959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AI_BUFFER_SIZE 1024 // maximum fifo size of any supported board 8059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_BUFFER_SIZE 1024 // maximum fifo size of any supported board 8159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8800 8 8259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_7376 1 8359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8402 2 8459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_DAC08 1 8559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 8659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* PCI-DAS base addresses */ 8759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 8859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// indices of base address regions 8959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define S5933_BADRINDEX 0 9059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_BADRINDEX 1 9159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_BADRINDEX 2 9259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_BADRINDEX 3 9359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_BADRINDEX 4 9459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// sizes of io regions 9559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_SIZE 10 9659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_SIZE 4 9759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_SIZE 12 9859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_SIZE 4 9959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 10059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* Control/Status registers */ 10159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT_ADCFIFO 0 // INTERRUPT / ADC FIFO register 10259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT_EOS 0x1 // interrupt end of scan 10359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT_FHF 0x2 // interrupt fifo half full 10459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT_FNE 0x3 // interrupt fifo not empty 10559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT_MASK 0x3 // mask of interrupt select bits 10659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INTE 0x4 // interrupt enable 10759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAHFIE 0x8 // dac half full interrupt enable 10859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define EOAIE 0x10 // end of aquisition interrupt enable 10959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAHFI 0x20 // dac half full read status / write interrupt clear 11059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define EOAI 0x40 // read end of acq. interrupt status / write clear 11159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define INT 0x80 // read interrupt status / write clear 11259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define EOBI 0x200 // read end of burst interrupt status 11359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADHFI 0x400 // read half-full interrupt status 11459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADNEI 0x800 // read fifo not empty interrupt latch status 11559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADNE 0x1000 // read, fifo not empty (realtime, not latched) status 11659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAEMIE 0x1000 // write, dac empty interrupt enable 11759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define LADFUL 0x2000 // read fifo overflow / write clear 11859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAEMI 0x4000 // dac fifo empty interrupt status / write clear 11959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 12059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADCMUX_CONT 2 // ADC CHANNEL MUX AND CONTROL register 12159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define BEGIN_SCAN(x) ((x) & 0xf) 12259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define END_SCAN(x) (((x) & 0xf) << 4) 12359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define GAIN_BITS(x) (((x) & 0x3) << 8) 12459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define UNIP 0x800 // Analog front-end unipolar for range 12559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SE 0x400 // Inputs in single-ended mode 12659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_MASK 0x3000 // pacer source bits 12759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_INT 0x1000 // internal pacer 12859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_EXT_FALL 0x2000 // external falling edge 12959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_EXT_RISE 0x3000 // external rising edge 13059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define EOC 0x4000 // adc not busy 13159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 13259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define TRIG_CONTSTAT 4 // TRIGGER CONTROL/STATUS register 13359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SW_TRIGGER 0x1 // software start trigger 13459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define EXT_TRIGGER 0x2 // external start trigger 13559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ANALOG_TRIGGER 0x3 // external analog trigger 13659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define TRIGGER_MASK 0x3 // mask of bits that determine start trigger 13759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define TGEN 0x10 // enable external start trigger 13859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define BURSTE 0x20 // burst mode enable 13959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define XTRCL 0x80 // clear external trigger 14059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 14159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CALIBRATION_REG 6 // CALIBRATION register 14259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SELECT_8800_BIT 0x100 // select 8800 caldac 14359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SELECT_TRIMPOT_BIT 0x200 // select ad7376 trim pot 14459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SELECT_DAC08_BIT 0x400 // select dac08 caldac 14559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CAL_SRC_BITS(x) (((x) & 0x7) << 11) 14659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CAL_EN_BIT 0x4000 // read calibration source instead of analog input channel 0 14759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define SERIAL_DATA_IN_BIT 0x8000 // serial data stream going to 8800 and 7376 14859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 14959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC_CSR 0x8 // dac control and status register 15059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits { 15159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DACEN = 0x2, // dac enable 15259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_MODE_UPDATE_BOTH = 0x80, // update both dacs when dac0 is written 15359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 15459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range) 15559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 15659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return (range & 0x3) << (8 + 2 * (channel & 0x1)); 15759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 15859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE_MASK(unsigned int channel) 15959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 16059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0x3 << (8 + 2 * (channel & 0x1)); 16159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 16259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 16359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// bits for 1602 series only 16459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits_1602 { 16559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_EMPTY = 0x1, // dac fifo empty, read, write clear 16659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_START = 0x4, // start/arm dac fifo operations 16759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_PACER_MASK = 0x18, // bits that set dac pacer source 16859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_PACER_INT = 0x8, // dac internal pacing 16959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_PACER_EXT_FALL = 0x10, // dac external pacing, falling edge 17059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_PACER_EXT_RISE = 0x18, // dac external pacing, rising edge 17159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 17259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_CHAN_EN(unsigned int channel) 17359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 17459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1 << (5 + (channel & 0x1)); // enable channel 0 or 1 17559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 17659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 17759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog input fifo */ 17859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADCDATA 0 // ADC DATA register 17959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADCFIFOCLR 2 // ADC FIFO CLEAR 18059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 18159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// pacer, counter, dio registers 18259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC8254 0 18359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DIO_8255 4 18459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC8254 8 18559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 18659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog output registers for 100x, 1200 series 18759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_DATA_REG(unsigned int channel) 18859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 18959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 2 * (channel & 0x1); 19059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 19159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 19259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog output registers for 1602 series*/ 19359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DACDATA 0 // DAC DATA register 19459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DACFIFOCLR 2 // DAC FIFO CLEAR 19559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 19659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// bit in hexadecimal representation of range index that indicates unipolar input range 19759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define IS_UNIPOLAR 0x4 19859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog input ranges for most boards 19959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic const comedi_lrange cb_pcidas_ranges = { 20059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 8, 20159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 20259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(10), 20359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(5), 20459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(2.5), 20559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(1.25), 20659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(10), 20759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(5), 20859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(2.5), 20959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(1.25) 21059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 21159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 21259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 21359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// pci-das1001 input ranges 21459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic const comedi_lrange cb_pcidas_alt_ranges = { 21559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 8, 21659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 21759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(10), 21859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(1), 21959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(0.1), 22059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(0.01), 22159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(10), 22259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(1), 22359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(0.1), 22459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(0.01) 22559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 22659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 22759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 22859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog output ranges 22959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic const comedi_lrange cb_pcidas_ao_ranges = { 23059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 4, 23159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 23259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(5), 23359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez BIP_RANGE(10), 23459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(5), 23559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez UNI_RANGE(10), 23659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 23759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 23859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 23959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum trimpot_model { 24059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez AD7376, 24159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez AD8402, 24259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 24359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 24459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martineztypedef struct cb_pcidas_board_struct { 24559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez const char *name; 24659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned short device_id; 24759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ai_se_chans; // Inputs in single-ended mode 24859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ai_diff_chans; // Inputs in differential mode 24959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ai_bits; // analog input resolution 25059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ai_speed; // fastest conversion period in ns 25159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ao_nchan; // number of analog out channels 25259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int has_ao_fifo; // analog output has fifo 25359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ao_scan_speed; // analog output speed for 1602 series (for a scan, not conversion) 25459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int fifo_size; // number of samples fifo can hold 25559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez const comedi_lrange *ranges; 25659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez enum trimpot_model trimpot; 25759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned has_dac08:1; 25859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} cb_pcidas_board; 25959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 26059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic const cb_pcidas_board cb_pcidas_boards[] = { 26159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 26259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1602/16", 26359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x1, 26459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 26559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 26659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 16, 26759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:5000, 26859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:2, 26959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:1, 27059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_scan_speed:10000, 27159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:512, 27259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 27359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD8402, 27459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:1, 27559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 27659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 27759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1200", 27859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0xF, 27959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 28059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 28159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 28259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:3200, 28359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:2, 28459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 28559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 28659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 28759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 28859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 28959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 29059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 29159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1602/12", 29259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x10, 29359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 29459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 29559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 29659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:3200, 29759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:2, 29859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:1, 29959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_scan_speed:4000, 30059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 30159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 30259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 30359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 30459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 30559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 30659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1200/jr", 30759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x19, 30859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 30959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 31059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 31159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:3200, 31259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:0, 31359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 31459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 31559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 31659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 31759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 31859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 31959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 32059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1602/16/jr", 32159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x1C, 32259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 32359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 32459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 16, 32559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:5000, 32659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:0, 32759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 32859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:512, 32959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 33059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD8402, 33159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:1, 33259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 33359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 33459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1000", 33559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x4C, 33659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 33759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 33859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 33959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:4000, 34059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:0, 34159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 34259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 34359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 34459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 34559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 34659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 34759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 34859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1001", 34959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x1a, 35059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 35159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 35259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 35359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:6800, 35459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:2, 35559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 35659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 35759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_alt_ranges, 35859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 35959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 36059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 36159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez { 36259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez name: "pci-das1002", 36359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez device_id:0x1b, 36459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_se_chans:16, 36559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_diff_chans:8, 36659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_bits: 12, 36759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ai_speed:6800, 36859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ao_nchan:2, 36959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_ao_fifo:0, 37059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez fifo_size:1024, 37159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ranges: &cb_pcidas_ranges, 37259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot: AD7376, 37359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez has_dac08:0, 37459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez }, 37559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 37659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 37759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// Number of boards in cb_pcidas_boards 37859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define N_BOARDS (sizeof(cb_pcidas_boards) / sizeof(cb_pcidas_board)) 37959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 38059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = { 38159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 38959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez {0} 39059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 39159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 39259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table); 39359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 39459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 39559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Useful for shorthand access to the particular board structure 39659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 39759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define thisboard ((const cb_pcidas_board *)dev->board_ptr) 39859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 39959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* this structure is for data unique to this hardware driver. If 40059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez several hardware drivers keep similar information in this structure, 40171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton feel free to suggest moving the variable to the struct comedi_device struct. */ 40259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martineztypedef struct { 40359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* would be useful for a PCI device */ 40459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez struct pci_dev *pci_dev; 40559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // base addresses 40659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long s5933_config; 40759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long control_status; 40859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long adc_fifo; 40959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long pacer_counter_dio; 41059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long ao_registers; 41159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // divisors of master clock for analog input pacing 41259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int divisor1; 41359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int divisor2; 41459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez volatile unsigned int count; // number of analog input samples remaining 41559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez volatile unsigned int adc_fifo_bits; // bits to write to interupt/adcfifo register 41659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez volatile unsigned int s5933_intcsr_bits; // bits to write to amcc s5933 interrupt control/status register 41759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez volatile unsigned int ao_control_bits; // bits to write to ao control and status register 418790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short ai_buffer[AI_BUFFER_SIZE]; 419790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short ao_buffer[AO_BUFFER_SIZE]; 42059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // divisors of master clock for analog output pacing 42159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int ao_divisor1; 42259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int ao_divisor2; 42359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez volatile unsigned int ao_count; // number of analog output samples remaining 42459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int ao_value[2]; // remember what the analog outputs are set to, to allow readback 42559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int caldac_value[NUM_CHANNELS_8800]; // for readback of caldac 42659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int trimpot_value[NUM_CHANNELS_8402]; // for readback of trimpot 42759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int dac08_value; 42859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int calibration_source; 42959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} cb_pcidas_private; 43059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 43159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 43259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * most drivers define the following macro to make it easy to 43359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * access the private structure. 43459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 43559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define devpriv ((cb_pcidas_private *)dev->private) 43659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 43759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 43859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * The comedi_driver structure tells the Comedi core module 43959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * which functions to call to configure/deconfigure (attach/detach) 44059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the board, and also about the kernel module that contains 44159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the device code. 44259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 44371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it); 44471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_detach(struct comedi_device * dev); 44559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic comedi_driver driver_cb_pcidas = { 44659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez driver_name:"cb_pcidas", 44759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez module:THIS_MODULE, 44859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez attach:cb_pcidas_attach, 44959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez detach:cb_pcidas_detach, 45059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}; 45159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 452d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s, 453790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 45434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, 455790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 45634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 457790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 45834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 459790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 46034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, 461790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 46234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); 46334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 46459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd * cmd); 46534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s); 466d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev, 467d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_subdevice *subdev, 468d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton unsigned int trig_num); 46934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 47059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd * cmd); 47159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG); 47271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void handle_ao_interrupt(struct comedi_device * dev, unsigned int status); 47334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s); 47434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s); 47571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns, 47659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int round_flags); 47734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 478790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 47934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 480790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 48134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 482790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 48334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 484790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 48571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel, 486790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int value); 48734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 488790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 48934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 490790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 49171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dac08_write(struct comedi_device * dev, unsigned int value); 49234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 493790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data); 49471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int caldac_8800_write(struct comedi_device * dev, unsigned int address, 49559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t value); 49671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_7376_write(struct comedi_device * dev, uint8_t value); 49771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_8402_write(struct comedi_device * dev, unsigned int channel, 49859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t value); 49971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int nvram_read(struct comedi_device * dev, unsigned int address, 50059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t * data); 50159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 50271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic inline unsigned int cal_enable_bits(struct comedi_device * dev) 50359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 50459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); 50559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 50659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 50759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 50859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Attach is called by the Comedi core to configure the driver 50959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * for a particular board. 51059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 51171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it) 51259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 51334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 51459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez struct pci_dev *pcidev; 51559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int index; 51659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int i; 51759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 51859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("comedi%d: cb_pcidas: ", dev->minor); 51959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 52059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 52159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the private structure area. 52259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 52359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (alloc_private(dev, sizeof(cb_pcidas_private)) < 0) 52459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -ENOMEM; 52559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 52659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 52759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Probe the device to determine what device in the series it is. 52859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 52959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("\n"); 53059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 53159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 53259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pcidev != NULL; 53359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { 53459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // is it not a computer boards card? 53559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (pcidev->vendor != PCI_VENDOR_ID_CB) 53659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez continue; 53759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // loop through cards supported by this driver 53859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (index = 0; index < N_BOARDS; index++) { 53959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cb_pcidas_boards[index].device_id != pcidev->device) 54059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez continue; 54159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // was a particular bus/slot requested? 54259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (it->options[0] || it->options[1]) { 54359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // are we on the wrong bus/slot? 54459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (pcidev->bus->number != it->options[0] || 54559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez PCI_SLOT(pcidev->devfn) != 54659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez it->options[1]) { 54759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez continue; 54859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 54959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 55059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->pci_dev = pcidev; 55159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dev->board_ptr = cb_pcidas_boards + index; 55259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez goto found; 55359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 55459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 55559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 55659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("No supported ComputerBoards/MeasurementComputing card found on " 55759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez "requested position\n"); 55859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EIO; 55959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 56059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez found: 56159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 56259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name, 56359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pcidev->bus->number, PCI_SLOT(pcidev->devfn)); 56459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 56559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* 56659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Enable PCI device and reserve I/O ports. 56759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 56859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (comedi_pci_enable(pcidev, "cb_pcidas")) { 56959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk(" Failed to enable PCI device and request regions\n"); 57059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EIO; 57159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 57259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* 57359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Initialize devpriv->control_status and devpriv->adc_fifo to point to 57459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * their base address. 57559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 57659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_config = 57759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); 57859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status = 57959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); 58059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo = 58159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); 58259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->pacer_counter_dio = 58359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); 58459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (thisboard->ao_nchan) { 58559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_registers = 58659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); 58759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 58859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable and clear interrupts on amcc s5933 58959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outl(INTCSR_INBOX_INTR_STATUS, 59059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_config + AMCC_OP_REG_INTCSR); 59159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 59259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // get irq 59359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, 59459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez IRQF_SHARED, "cb_pcidas", dev)) { 59559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq); 59659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EINVAL; 59759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 59859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dev->irq = devpriv->pci_dev->irq; 59959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 60059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez //Initialize dev->board_name 60159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dev->board_name = thisboard->name; 60259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 60359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 60459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the subdevice structures. 60559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 60659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (alloc_subdevices(dev, 7) < 0) 60759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -ENOMEM; 60859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 60959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 0; 61059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* analog input subdevice */ 61159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dev->read_subdev = s; 61259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_AI; 61359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; 61459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* WARNING: Number of inputs in differential mode is ignored */ 61559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = thisboard->ai_se_chans; 61659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->len_chanlist = thisboard->ai_se_chans; 61759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = (1 << thisboard->ai_bits) - 1; 61859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->range_table = thisboard->ranges; 61959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = cb_pcidas_ai_rinsn; 62059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_config = ai_config_insn; 62159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->do_cmd = cb_pcidas_ai_cmd; 62259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->do_cmdtest = cb_pcidas_ai_cmdtest; 62359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->cancel = cb_pcidas_cancel; 62459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 62559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* analog output subdevice */ 62659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 1; 62759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (thisboard->ao_nchan) { 62859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_AO; 62959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; 63059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = thisboard->ao_nchan; 63159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // analog out resolution is the same as analog input resolution, so use ai_bits 63259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = (1 << thisboard->ai_bits) - 1; 63359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->range_table = &cb_pcidas_ao_ranges; 63459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = cb_pcidas_ao_readback_insn; 63559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (thisboard->has_ao_fifo) { 63659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dev->write_subdev = s; 63759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags |= SDF_CMD_WRITE; 63859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_write = cb_pcidas_ao_fifo_winsn; 63959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->do_cmdtest = cb_pcidas_ao_cmdtest; 64059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->do_cmd = cb_pcidas_ao_cmd; 64159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->cancel = cb_pcidas_ao_cancel; 64259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else { 64359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_write = cb_pcidas_ao_nofifo_winsn; 64459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 64559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else { 64659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_UNUSED; 64759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 64859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 64959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* 8255 */ 65059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 2; 65159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); 65259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 65359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // serial EEPROM, 65459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 3; 65559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_MEMORY; 65659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_INTERNAL; 65759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = 256; 65859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = 0xff; 65959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = eeprom_read_insn; 66059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 66159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // 8800 caldac 66259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 4; 66359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_CALIB; 66459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; 66559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = NUM_CHANNELS_8800; 66659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = 0xff; 66759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = caldac_read_insn; 66859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_write = caldac_write_insn; 66959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < s->n_chan; i++) 67059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez caldac_8800_write(dev, i, s->maxdata / 2); 67159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 67259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // trim potentiometer 67359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 5; 67459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_CALIB; 67559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; 67659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (thisboard->trimpot == AD7376) { 67759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = NUM_CHANNELS_7376; 67859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = 0x7f; 67959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else { 68059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = NUM_CHANNELS_8402; 68159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = 0xff; 68259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 68359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = trimpot_read_insn; 68459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_write = trimpot_write_insn; 68559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < s->n_chan; i++) 68659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); 68759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 68859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // dac08 caldac 68959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s = dev->subdevices + 6; 69059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (thisboard->has_dac08) { 69159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_CALIB; 69259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; 69359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->n_chan = NUM_CHANNELS_DAC08; 69459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_read = dac08_read_insn; 69559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->insn_write = dac08_write_insn; 69659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->maxdata = 0xff; 69759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez dac08_write(dev, s->maxdata / 2); 69859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else 69959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s->type = COMEDI_SUBD_UNUSED; 70059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 70159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // make sure mailbox 4 is empty 70259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez inl(devpriv->s5933_config + AMCC_OP_REG_IMB4); 70359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* Set bits to enable incoming mailbox interrupts on amcc s5933. */ 70459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_intcsr_bits = 70559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | 70659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez INTCSR_INBOX_FULL_INT; 70759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear and enable interrupt on amcc s5933 70859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, 70959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_config + AMCC_OP_REG_INTCSR); 71059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 71159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 71259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 71359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 71459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 71559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cb_pcidas_detach is called to deconfigure a device. It should deallocate 71659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * resources. 71759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * This function is also called when _attach() fails, so it should be 71859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * careful not to release resources that were not necessarily 71959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * allocated by _attach(). dev->private and dev->subdevices are 72059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * deallocated automatically by the core. 72159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 72271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_detach(struct comedi_device * dev) 72359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 72459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("comedi%d: cb_pcidas: remove\n", dev->minor); 72559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 72659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv) { 72759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv->s5933_config) { 72859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable and clear interrupts on amcc s5933 72959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outl(INTCSR_INBOX_INTR_STATUS, 73059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_config + AMCC_OP_REG_INTCSR); 73159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 73259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("detaching, incsr is 0x%x\n", 73359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez inl(devpriv->s5933_config + 73459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez AMCC_OP_REG_INTCSR)); 73559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 73659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 73759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 73859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (dev->irq) 73959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_free_irq(dev->irq, dev); 74059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (dev->subdevices) 74159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez subdev_8255_cleanup(dev, dev->subdevices + 2); 74259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv && devpriv->pci_dev) { 74359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv->s5933_config) { 74459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_pci_disable(devpriv->pci_dev); 74559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 74659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez pci_dev_put(devpriv->pci_dev); 74759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 74859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 74959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 75059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 75159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 75259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 75359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * "instructions" read/write data in "one-shot" or "software-triggered" 75459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * mode. 75559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 75634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, 757790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 75859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 75959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int n, i; 76059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bits; 76159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int timeout = 10000; 76259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int channel; 76359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable calibration input if appropriate 76459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (insn->chanspec & CR_ALT_SOURCE) { 76559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev), 76659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + CALIBRATION_REG); 76759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez channel = 0; 76859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else { 76959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->control_status + CALIBRATION_REG); 77059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez channel = CR_CHAN(insn->chanspec); 77159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 77259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set mux limits and gain 77359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits = BEGIN_SCAN(channel) | 77459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec)); 77559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set unipolar/bipolar 77659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR) 77759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= UNIP; 77859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set singleended/differential 77959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_AREF(insn->chanspec) != AREF_DIFF) 78059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= SE; 78159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(bits, devpriv->control_status + ADCMUX_CONT); 78259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 78359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* clear fifo */ 78459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->adc_fifo + ADCFIFOCLR); 78559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 78659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* convert n samples */ 78759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (n = 0; n < insn->n; n++) { 78859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* trigger conversion */ 78959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->adc_fifo + ADCDATA); 79059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 79159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* wait for conversion to end */ 79259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* return -ETIMEDOUT if there is a timeout */ 79359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < timeout; i++) { 79459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (inw(devpriv->control_status + ADCMUX_CONT) & EOC) 79559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 79659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 79759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (i == timeout) 79859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -ETIMEDOUT; 79959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 80059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* read data */ 80159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[n] = inw(devpriv->adc_fifo + ADCDATA); 80259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 80359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 80459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* return the number of samples read/written */ 80559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return n; 80659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 80759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 80871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data) 80959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 81059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int num_calibration_sources = 8; 811790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int source = data[1]; 81259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 81359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (source >= num_calibration_sources) { 81459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez printk("invalid calibration source: %i\n", source); 81559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EINVAL; 81659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 81759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 81859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->calibration_source = source; 81959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 82059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 2; 82159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 82259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 82334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, 824790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 82559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 82659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int id = data[0]; 82759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 82859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez switch (id) { 82959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez case INSN_CONFIG_ALT_SOURCE: 83059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return ai_config_calibration_source(dev, data); 83159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 83259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez default: 83359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EINVAL; 83459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 83559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 83659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EINVAL; 83759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 83859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 83959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog output insn for pcidas-1000 and 1200 series 84034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 841790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 84259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 84359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int channel; 84459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 84559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 84659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set channel and range 84759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez channel = CR_CHAN(insn->chanspec); 84859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 84959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits &= 85059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel); 85159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= 85259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec)); 85359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); 85459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 85559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 85659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // remember value for readback 85759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_value[channel] = data[0]; 85859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // send data 85959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel)); 86059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 86159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 86259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 86359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 86459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog output insn for pcidas-1602 series 86534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 866790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 86759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 86859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int channel; 86959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 87059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 87159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear dac fifo 87259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->ao_registers + DACFIFOCLR); 87359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 87459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set channel and range 87559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez channel = CR_CHAN(insn->chanspec); 87659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 87759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits &= 87859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) & 87959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez ~DAC_PACER_MASK; 88059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= 88159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DACEN | DAC_RANGE(channel, 88259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez CR_RANGE(insn->chanspec)) | DAC_CHAN_EN(channel) | DAC_START; 88359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); 88459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 88559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 88659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // remember value for readback 88759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_value[channel] = data[0]; 88859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // send data 88959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(data[0], devpriv->ao_registers + DACDATA); 89059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 89159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 89259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 89359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 89459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// analog output readback insn 89559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez// XXX loses track of analog output value back after an analog ouput command is executed 89634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, 897790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 89859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 89959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; 90059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 90159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 90259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 90359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 90434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 905790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 90659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 90759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t nvram_data; 90859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int retval; 90959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 91059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data); 91159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (retval < 0) 91259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return retval; 91359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 91459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[0] = nvram_data; 91559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 91659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 91759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 91859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 91934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 920790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 92159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 92259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez const unsigned int channel = CR_CHAN(insn->chanspec); 92359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 92459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return caldac_8800_write(dev, channel, data[0]); 92559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 92659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 92734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 928790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 92959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 93059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)]; 93159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 93259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 93359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 93459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 93559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 1602/16 pregain offset */ 93671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dac08_write(struct comedi_device * dev, unsigned int value) 93759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 93859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv->dac08_value == value) 93959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 94059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 94159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->dac08_value = value; 94259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 94359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev) | (value & 0xff), 94459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + CALIBRATION_REG); 94559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(1); 94659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff), 94759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + CALIBRATION_REG); 94859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(1); 94959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev) | (value & 0xff), 95059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + CALIBRATION_REG); 95159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(1); 95259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 95359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 95459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 95559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 95634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 957790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 95859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 95959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return dac08_write(dev, data[0]); 96059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 96159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 96234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 963790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 96459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 96559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[0] = devpriv->dac08_value; 96659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 96759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 96859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 96959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 97071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device * dev, 971790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int channel, unsigned int value) 97259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 97359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (devpriv->trimpot_value[channel] == value) 97459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 97559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 97659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->trimpot_value[channel] = value; 97759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez switch (thisboard->trimpot) { 97859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez case AD7376: 97959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot_7376_write(dev, value); 98059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 98159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez case AD8402: 98259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez trimpot_8402_write(dev, channel, value); 98359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 98459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez default: 98559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "driver bug?"); 98659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -1; 98759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 98859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 98959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 99059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 99159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 99259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 99334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, 994790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 99559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 99659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int channel = CR_CHAN(insn->chanspec); 99759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 99859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return cb_pcidas_trimpot_write(dev, channel, data[0]); 99959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 100059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 100134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, 1002790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton comedi_insn * insn, unsigned int * data) 100359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 100459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int channel = CR_CHAN(insn->chanspec); 100559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 100659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez data[0] = devpriv->trimpot_value[channel]; 100759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 100859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 100959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 101059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 101134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 101259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd * cmd) 101359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 101459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int err = 0; 101559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int tmp; 101659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int i, gain, start_chan; 101759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 101859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* cmdtest tests a particular command to see if it is valid. 101959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Using the cmdtest ioctl, a user can create a valid cmd 102059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * and then have it executes by the cmd ioctl. 102159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * 102259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cmdtest returns 1,2,3,4 or 0, depending on which tests 102359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the command passes. */ 102459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 102559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 1: make sure trigger sources are trivially valid */ 102659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 102759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->start_src; 102859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->start_src &= TRIG_NOW | TRIG_EXT; 102959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->start_src || tmp != cmd->start_src) 103059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 103159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 103259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_begin_src; 103359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; 103459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 103559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 103659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 103759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->convert_src; 103859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT; 103959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->convert_src || tmp != cmd->convert_src) 104059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 104159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 104259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_end_src; 104359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_end_src &= TRIG_COUNT; 104459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 104559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 104659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 104759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->stop_src; 104859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 104959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->stop_src || tmp != cmd->stop_src) 105059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 105159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 105259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 105359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 105459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 105559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 2: make sure trigger sources are unique and mutually compatible */ 105659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 105759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) 105859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 105959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src != TRIG_FOLLOW && 106059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_src != TRIG_TIMER && 106159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_src != TRIG_EXT) 106259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 106359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src != TRIG_TIMER && 106459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) 106559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 106659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 106759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 106859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 106959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // make sure trigger sources are compatible with each other 107059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) 107159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 107259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) 107359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 107459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->start_src == TRIG_EXT && 107559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez (cmd->convert_src == TRIG_EXT 107659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez || cmd->scan_begin_src == TRIG_EXT)) 107759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 107859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 107959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 108059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 2; 108159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 108259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 3: make sure arguments are trivially compatible */ 108359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 108459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->start_arg != 0) { 108559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->start_arg = 0; 108659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 108759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 108859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 108959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_TIMER) { 109059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_arg < 109159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez thisboard->ai_speed * cmd->chanlist_len) { 109259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_arg = 109359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez thisboard->ai_speed * cmd->chanlist_len; 109459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 109559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 109659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 109759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_TIMER) { 109859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_arg < thisboard->ai_speed) { 109959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->convert_arg = thisboard->ai_speed; 110059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 110159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 110259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 110359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 110459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_end_arg != cmd->chanlist_len) { 110559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_end_arg = cmd->chanlist_len; 110659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 110759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 110859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_NONE) { 110959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* TRIG_NONE */ 111059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_arg != 0) { 111159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->stop_arg = 0; 111259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 111359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 111459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 111559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 111659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 111759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 3; 111859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 111959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 4: fix up any arguments */ 112059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 112159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_TIMER) { 112259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_begin_arg; 112359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8253_cascade_ns_to_timer_2div(TIMER_BASE, 112459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(devpriv->divisor1), &(devpriv->divisor2), 112559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); 112659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (tmp != cmd->scan_begin_arg) 112759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 112859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 112959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_TIMER) { 113059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->convert_arg; 113159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8253_cascade_ns_to_timer_2div(TIMER_BASE, 113259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(devpriv->divisor1), &(devpriv->divisor2), 113359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); 113459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (tmp != cmd->convert_arg) 113559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 113659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 113759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 113859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 113959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 4; 114059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 114159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // check channel/gain list against card's limitations 114259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->chanlist) { 114359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez gain = CR_RANGE(cmd->chanlist[0]); 114459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez start_chan = CR_CHAN(cmd->chanlist[0]); 114559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 1; i < cmd->chanlist_len; i++) { 114659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_CHAN(cmd->chanlist[i]) != 114759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez (start_chan + i) % s->n_chan) { 114859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, 114959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez "entries in chanlist must be consecutive channels, counting upwards\n"); 115059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 115159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 115259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_RANGE(cmd->chanlist[i]) != gain) { 115359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, 115459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez "entries in chanlist must all have the same gain\n"); 115559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 115659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 115759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 115859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 115959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 116059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 116159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 5; 116259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 116359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 116459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 116559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 116634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) 116759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 1168d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 116959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd *cmd = &async->cmd; 117059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bits; 117159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 117259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 117359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // make sure CAL_EN_BIT is disabled 117459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->control_status + CALIBRATION_REG); 117559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // initialize before settings pacer source and count values 117659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->control_status + TRIG_CONTSTAT); 117759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear fifo 117859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->adc_fifo + ADCFIFOCLR); 117959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 118059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set mux limits, gain and pacer source 118159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) | 118259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) | 118359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez GAIN_BITS(CR_RANGE(cmd->chanlist[0])); 118459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set unipolar/bipolar 118559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR) 118659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= UNIP; 118759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set singleended/differential 118859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF) 118959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= SE; 119059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set pacer source 119159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT) 119259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= PACER_EXT_RISE; 119359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else 119459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= PACER_INT; 119559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(bits, devpriv->control_status + ADCMUX_CONT); 119659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 119759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 119859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("comedi: sent 0x%x to adcmux control\n", bits); 119959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 120059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 120159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // load counters 120259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_TIMER) 120359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_load_counters(dev, &cmd->convert_arg, 120459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->flags & TRIG_ROUND_MASK); 120559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else if (cmd->scan_begin_src == TRIG_TIMER) 120659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_load_counters(dev, &cmd->scan_begin_arg, 120759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->flags & TRIG_ROUND_MASK); 120859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 120959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set number of conversions 121059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_COUNT) { 121159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->count = cmd->chanlist_len * cmd->stop_arg; 121259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 121359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable interrupts 121459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 121559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits |= INTE; 121659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits &= ~INT_MASK; 121759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->flags & TRIG_WAKE_EOS) { 121859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) 121959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits |= INT_EOS; // interrupt end of burst 122059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else 122159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits |= INT_FNE; // interrupt fifo not empty 122259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else { 122359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits |= INT_FHF; //interrupt fifo half full 122459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 122559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 122659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); 122759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 122859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable (and clear) interrupts 122959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL, 123059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 123159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 123259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 123359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set start trigger and burst mode 123459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits = 0; 123559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->start_src == TRIG_NOW) 123659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= SW_TRIGGER; 123759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else if (cmd->start_src == TRIG_EXT) 123859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= EXT_TRIGGER | TGEN | XTRCL; 123959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else { 124059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "bug!"); 124159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -1; 124259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 124359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) 124459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bits |= BURSTE; 124559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(bits, devpriv->control_status + TRIG_CONTSTAT); 124659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 124759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("comedi: sent 0x%x to trig control\n", bits); 124859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 124959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 125059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 125159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 125259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 125334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 125459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd * cmd) 125559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 125659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int err = 0; 125759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int tmp; 125859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 125959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* cmdtest tests a particular command to see if it is valid. 126059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Using the cmdtest ioctl, a user can create a valid cmd 126159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * and then have it executes by the cmd ioctl. 126259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * 126359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cmdtest returns 1,2,3,4 or 0, depending on which tests 126459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the command passes. */ 126559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 126659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 1: make sure trigger sources are trivially valid */ 126759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 126859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->start_src; 126959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->start_src &= TRIG_INT; 127059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->start_src || tmp != cmd->start_src) 127159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 127259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 127359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_begin_src; 127459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 127559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 127659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 127759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 127859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->convert_src; 127959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->convert_src &= TRIG_NOW; 128059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->convert_src || tmp != cmd->convert_src) 128159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 128259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 128359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_end_src; 128459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_end_src &= TRIG_COUNT; 128559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 128659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 128759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 128859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->stop_src; 128959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 129059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (!cmd->stop_src || tmp != cmd->stop_src) 129159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 129259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 129359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 129459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 129559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 129659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 2: make sure trigger sources are unique and mutually compatible */ 129759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 129859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src != TRIG_TIMER && 129959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_src != TRIG_EXT) 130059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 130159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 130259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 130359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 130459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 130559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 2; 130659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 130759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 3: make sure arguments are trivially compatible */ 130859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 130959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->start_arg != 0) { 131059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->start_arg = 0; 131159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 131259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 131359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 131459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_TIMER) { 131559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_arg < thisboard->ao_scan_speed) { 131659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_begin_arg = thisboard->ao_scan_speed; 131759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 131859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 131959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 132059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 132159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_end_arg != cmd->chanlist_len) { 132259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->scan_end_arg = cmd->chanlist_len; 132359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 132459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 132559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_NONE) { 132659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* TRIG_NONE */ 132759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_arg != 0) { 132859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cmd->stop_arg = 0; 132959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 133059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 133159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 133259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 133359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 133459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 3; 133559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 133659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* step 4: fix up any arguments */ 133759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 133859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_TIMER) { 133959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez tmp = cmd->scan_begin_arg; 134059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8253_cascade_ns_to_timer_2div(TIMER_BASE, 134159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(devpriv->ao_divisor1), &(devpriv->ao_divisor2), 134259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); 134359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (tmp != cmd->scan_begin_arg) 134459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 134559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 134659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 134759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 134859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 4; 134959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 135059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // check channel/gain list against card's limitations 135159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->chanlist && cmd->chanlist_len > 1) { 135259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (CR_CHAN(cmd->chanlist[0]) != 0 || 135359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez CR_CHAN(cmd->chanlist[1]) != 1) { 135459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, 135559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez "channels must be ordered channel 0, channel 1 in chanlist\n"); 135659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez err++; 135759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 135859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 135959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 136059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (err) 136159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 5; 136259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 136359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 136459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 136559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 136634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) 136759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 1368d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 136959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd *cmd = &async->cmd; 137059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int i; 137159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 137259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 137359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set channel limits, gain 137459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 137559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < cmd->chanlist_len; i++) { 137659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable channel 137759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= 137859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i])); 137959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set range 138059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]), 138159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez CR_RANGE(cmd->chanlist[i])); 138259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 138359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 138459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable analog out before settings pacer source and count values 138559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); 138659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 138759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 138859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear fifo 138959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->ao_registers + DACFIFOCLR); 139059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 139159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // load counters 139259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->scan_begin_src == TRIG_TIMER) { 139359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8253_cascade_ns_to_timer_2div(TIMER_BASE, 139459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(devpriv->ao_divisor1), &(devpriv->ao_divisor2), 139559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(cmd->scan_begin_arg), cmd->flags); 139659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 139759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ 139859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1, 139959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_divisor1, 2); 140059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2, 140159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_divisor2, 2); 140259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 140359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set number of conversions 140459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_COUNT) { 140559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg; 140659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 140759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // set pacer source 140859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 140959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez switch (cmd->scan_begin_src) { 141059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez case TRIG_TIMER: 141159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= DAC_PACER_INT; 141259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 141359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez case TRIG_EXT: 141459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= DAC_PACER_EXT_RISE; 141559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 141659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez default: 141759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 141859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "error setting dac pacer source"); 141959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -1; 142059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 142159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 142259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 142359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 142459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->inttrig = cb_pcidas_ao_inttrig; 142559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 142659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 142759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 142859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1429d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev, 1430d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_subdevice *s, 1431d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton unsigned int trig_num) 143259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 143359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int num_bytes, num_points = thisboard->fifo_size; 1434d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 143559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd *cmd = &s->async->cmd; 143659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 143759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 143859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (trig_num != 0) 143959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -EINVAL; 144059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 144159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // load up fifo 144259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points) 144359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_points = devpriv->ao_count; 144459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 144559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer, 1446790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton num_points * sizeof(short)); 1447790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton num_points = num_bytes / sizeof(short); 144859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 144959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_COUNT) { 145059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_count -= num_points; 145159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 145259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // write data to board's fifo 145359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes); 145459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 145559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable dac half-full and empty interrupts 145659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 145759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; 145859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 145959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); 146059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 146159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // enable and clear interrupts 146259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, 146359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 146459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 146559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // start dac 146659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; 146759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); 146859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 146959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("comedi: sent 0x%x to dac control\n", 147059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits); 147159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 147259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 147359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 147459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->inttrig = NULL; 147559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 147659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 147759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 147859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 147959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG) 148059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 148171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = (struct comedi_device *) d; 148234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->read_subdev; 1483d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 148459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int status, s5933_status; 148559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int half_fifo = thisboard->fifo_size / 2; 148659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int num_samples, i; 148759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int timeout = 10000; 148859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 148959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 149059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (dev->attached == 0) { 149159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return IRQ_NONE; 149259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 149359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 149459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async = s->async; 149559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events = 0; 149659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 149759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); 149859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 149959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("intcsr 0x%x\n", s5933_status); 150059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez rt_printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF)); 150159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 150259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 150359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if ((INTCSR_INTR_ASSERTED & s5933_status) == 0) 150459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return IRQ_NONE; 150559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 150659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // make sure mailbox 4 is empty 150759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4); 150859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear interrupt on amcc s5933 150959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, 151059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->s5933_config + AMCC_OP_REG_INTCSR); 151159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 151259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez status = inw(devpriv->control_status + INT_ADCFIFO); 151359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG 151459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) { 151559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "spurious interrupt"); 151659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 151759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif 151859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 151959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // check for analog output interrupt 152059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (status & (DAHFI | DAEMI)) { 152159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez handle_ao_interrupt(dev, status); 152259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 152359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // check for analog input interrupts 152459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // if fifo half-full 152559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (status & ADHFI) { 152659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // read data 152759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_samples = half_fifo; 152859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (async->cmd.stop_src == TRIG_COUNT && 152959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_samples > devpriv->count) { 153059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_samples = devpriv->count; 153159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 153259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer, 153359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_samples); 153459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cfc_write_array_to_buffer(s, devpriv->ai_buffer, 1535790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton num_samples * sizeof(short)); 153659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->count -= num_samples; 153759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) { 153859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events |= COMEDI_CB_EOA; 153959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_cancel(dev, s); 154059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 154159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear half-full interrupt latch 154259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 154359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | INT, 154459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 154559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 154659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // else if fifo not empty 154759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else if (status & (ADNEI | EOBI)) { 154859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < timeout; i++) { 154959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // break if fifo is empty 155059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if ((ADNE & inw(devpriv->control_status + 155159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez INT_ADCFIFO)) == 0) 155259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 155359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cfc_write_to_buffer(s, inw(devpriv->adc_fifo)); 155459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */ 155559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_cancel(dev, s); 155659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events |= COMEDI_CB_EOA; 155759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez break; 155859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 155959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 156059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear not-empty interrupt latch 156159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 156259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | INT, 156359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 156459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 156559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else if (status & EOAI) { 156659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, 156759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez "bug! encountered end of aquisition interrupt?"); 156859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear EOA interrupt latch 156959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 157059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | EOAI, 157159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 157259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 157359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 157459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez //check for fifo overflow 157559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (status & LADFUL) { 157659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "fifo overflow"); 157759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear overflow interrupt latch 157859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 157959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | LADFUL, 158059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 158159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 158259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_cancel(dev, s); 158359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; 158459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 158559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 158659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_event(dev, s); 158759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 158859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return IRQ_HANDLED; 158959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 159059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 159171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void handle_ao_interrupt(struct comedi_device * dev, unsigned int status) 159259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 159334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = dev->write_subdev; 1594d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 159559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_cmd *cmd = &async->cmd; 159659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int half_fifo = thisboard->fifo_size / 2; 159759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int num_points; 159859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int flags; 159959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 160059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events = 0; 160159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 160259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (status & DAEMI) { 160359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear dac empty interrupt latch 160459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 160559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | DAEMI, 160659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 160759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 160859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { 160959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_NONE || 161059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez (cmd->stop_src == TRIG_COUNT 161159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez && devpriv->ao_count)) { 161259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "dac fifo underflow"); 161359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cb_pcidas_ao_cancel(dev, s); 161459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events |= COMEDI_CB_ERROR; 161559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 161659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez async->events |= COMEDI_CB_EOA; 161759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 161859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } else if (status & DAHFI) { 161959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int num_bytes; 162059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 162159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // figure out how many points we are writing to fifo 162259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_points = half_fifo; 162359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (cmd->stop_src == TRIG_COUNT && 162459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_count < num_points) 162559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_points = devpriv->ao_count; 162659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_bytes = 162759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez cfc_read_array_from_buffer(s, devpriv->ao_buffer, 1628790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton num_points * sizeof(short)); 1629790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton num_points = num_bytes / sizeof(short); 163059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 163159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (async->cmd.stop_src == TRIG_COUNT) { 163259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_count -= num_points; 163359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 163459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // write data to board's fifo 163559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, 163659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez num_points); 163759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // clear half-full interrupt latch 163859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 163959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits | DAHFI, 164059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + INT_ADCFIFO); 164159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 164259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 164359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 164459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_event(dev, s); 164559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 164659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1647d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog input command */ 164834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s) 164959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 165059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 165159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 165259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 165359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable interrupts 165459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits &= ~INTE & ~EOAIE; 165559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); 165659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 165759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 165859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable start trigger source and burst mode 165959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->control_status + TRIG_CONTSTAT); 166059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // software pacer source 166159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(0, devpriv->control_status + ADCMUX_CONT); 166259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 166359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 166459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 166559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 1666d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog output command */ 1667d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device *dev, 1668d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_subdevice *s) 166959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 167059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long flags; 167159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 167259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_lock_irqsave(&dev->spinlock, flags); 167359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable interrupts 167459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE; 167559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); 167659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 167759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez // disable output 167859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK; 167959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); 168059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 168159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 168259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 168359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 168459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 168571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns, 168659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez int rounding_flags) 168759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 168859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), 168959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez &(devpriv->divisor2), ns, rounding_flags & TRIG_ROUND_MASK); 169059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 169159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ 169259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, 169359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->divisor1, 2); 169459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2, 169559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->divisor2, 2); 169659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 169759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 169871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void write_calibration_bitstream(struct comedi_device * dev, 169959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int register_bits, unsigned int bitstream, 170059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bitstream_length) 170159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 170259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int write_delay = 1; 170359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bit; 170459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 170559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { 170659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (bitstream & bit) 170759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez register_bits |= SERIAL_DATA_IN_BIT; 170859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez else 170959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez register_bits &= ~SERIAL_DATA_IN_BIT; 171059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(write_delay); 171159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(register_bits, devpriv->control_status + CALIBRATION_REG); 171259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 171359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 171459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 171571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int caldac_8800_write(struct comedi_device * dev, unsigned int address, 171659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t value) 171759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 171859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int num_caldac_channels = 8; 171959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int bitstream_length = 11; 172059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bitstream = ((address & 0x7) << 8) | value; 172159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int caldac_8800_comedi_udelay = 1; 172259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 172359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (address >= num_caldac_channels) { 172459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_error(dev, "illegal caldac channel"); 172559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -1; 172659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 172759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 172859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (value == devpriv->caldac_value[address]) 172959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 173059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 173159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->caldac_value[address] = value; 173259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 173359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, 173459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bitstream_length); 173559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 173659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(caldac_8800_comedi_udelay); 173759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev) | SELECT_8800_BIT, 173859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez devpriv->control_status + CALIBRATION_REG); 173959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(caldac_8800_comedi_udelay); 174059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); 174159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 174259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 1; 174359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 174459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 174571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_7376_write(struct comedi_device * dev, uint8_t value) 174659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 174759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int bitstream_length = 7; 174859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bitstream = value & 0x7f; 174959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int register_bits; 175059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int ad7376_comedi_udelay = 1; 175159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 175259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; 175359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(ad7376_comedi_udelay); 175459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(register_bits, devpriv->control_status + CALIBRATION_REG); 175559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 175659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez write_calibration_bitstream(dev, register_bits, bitstream, 175759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bitstream_length); 175859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 175959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(ad7376_comedi_udelay); 176059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); 176159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 176259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 176359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 176459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 176559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* For 1602/16 only 176659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 0 : adc gain 176759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 1 : adc postgain offset */ 176871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_8402_write(struct comedi_device * dev, unsigned int channel, 176959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez uint8_t value) 177059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 177159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int bitstream_length = 10; 177259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); 177359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int register_bits; 177459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int ad8402_comedi_udelay = 1; 177559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 177659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; 177759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(ad8402_comedi_udelay); 177859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(register_bits, devpriv->control_status + CALIBRATION_REG); 177959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 178059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez write_calibration_bitstream(dev, register_bits, bitstream, 178159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez bitstream_length); 178259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 178359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(ad8402_comedi_udelay); 178459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); 178559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 178659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 178759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 178859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 178959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic int wait_for_nvram_ready(unsigned long s5933_base_addr) 179059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 179159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez static const int timeout = 1000; 179259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned int i; 179359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 179459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez for (i = 0; i < timeout; i++) { 179559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if ((inb(s5933_base_addr + 179659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY) 179759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez == 0) 179859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 179959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez comedi_udelay(1); 180059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez } 180159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -1; 180259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 180359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 180471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int nvram_read(struct comedi_device * dev, unsigned int address, uint8_t * data) 180559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{ 180659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez unsigned long iobase = devpriv->s5933_config; 180759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 180859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (wait_for_nvram_ready(iobase) < 0) 180959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -ETIMEDOUT; 181059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 181159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, 181259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez iobase + AMCC_OP_REG_MCSR_NVCMD); 181359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); 181459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, 181559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez iobase + AMCC_OP_REG_MCSR_NVCMD); 181659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); 181759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); 181859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 181959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez if (wait_for_nvram_ready(iobase) < 0) 182059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return -ETIMEDOUT; 182159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 182259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); 182359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 182459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez return 0; 182559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez} 182659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez 182759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 182859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * A convenient macro that defines init_module() and cleanup_module(), 182959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * as necessary. 183059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */ 183159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezCOMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table); 1832