10e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 20e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 30e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes comedi/drivers/me_daq.c 40e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 50e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes Hardware driver for Meilhaus data acquisition cards: 60e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 70e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes ME-2000i, ME-2600i, ME-3000vm1 80e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 90e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de> 100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 110e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes This program is free software; you can redistribute it and/or modify 120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes it under the terms of the GNU General Public License as published by 130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes the Free Software Foundation; either version 2 of the License, or 140e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes (at your option) any later version. 150e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes This program is distributed in the hope that it will be useful, 170e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes but WITHOUT ANY WARRANTY; without even the implied warranty of 180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes GNU General Public License for more details. 200e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes You should have received a copy of the GNU General Public License 2297feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark along with this program; if not, write to the Free Software 230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes*/ 250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 270e8db97a04b37960828b273d166e35eac9a1888bMichal DobesDriver: me_daq 280e8db97a04b37960828b273d166e35eac9a1888bMichal DobesDescription: Meilhaus PCI data acquisition cards 290e8db97a04b37960828b273d166e35eac9a1888bMichal DobesAuthor: Michael Hillmann <hillmann@syscongroup.de> 300e8db97a04b37960828b273d166e35eac9a1888bMichal DobesDevices: [Meilhaus] ME-2600i (me_daq), ME-2000i 310e8db97a04b37960828b273d166e35eac9a1888bMichal DobesStatus: experimental 320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 330e8db97a04b37960828b273d166e35eac9a1888bMichal DobesSupports: 340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes Analog Output 360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 370e8db97a04b37960828b273d166e35eac9a1888bMichal DobesConfiguration options: 380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes [0] - PCI bus number (optional) 4097feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark [1] - PCI slot number (optional) 4197feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark 420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes If bus/slot is not specified, the first available PCI 430e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes device will be used. 4470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby 4570265d24e3404fe798b6edd55a02016b1edb49d7Jiri SlabyThe 2600 requires a firmware upload, which can be accomplished 460e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesusing the -i or --init-data option of comedi_config. 470e8db97a04b37960828b273d166e35eac9a1888bMichal DobesThe firmware can be 480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesfound in the comedi_nonfree_firmware tarball available 490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesfrom http://www.comedi.org 500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 510e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes*/ 520e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5397feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#include <linux/interrupt.h> 5497feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#include <linux/sched.h> 5597feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#include "../comedidev.h" 560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#include "comedi_pci.h" 580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/*#include "me2600_fw.h" */ 600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 610e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_DRIVER_NAME "me_daq" 620e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 635f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman#define PCI_VENDOR_ID_MEILHAUS 0x1402 640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME2000_DEVICE_ID 0x2000 650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME2600_DEVICE_ID 0x2600 660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define PLX_INTCSR 0x4C /* PLX interrupt status register */ 6859af888d6af8e3d2c91b32e00e43f2ce750589b8Greg Kroah-Hartman#define XILINX_DOWNLOAD_RESET 0x42 /* Xilinx registers */ 6959af888d6af8e3d2c91b32e00e43f2ce750589b8Greg Kroah-Hartman 702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define ME_CONTROL_1 0x0000 /* - | W */ 710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define INTERRUPT_ENABLE (1<<15) 720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define COUNTER_B_IRQ (1<<12) 730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define COUNTER_A_IRQ (1<<11) 740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define CHANLIST_READY_IRQ (1<<10) 7597feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define EXT_IRQ (1<<9) 7697feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ADFIFO_HALFFULL_IRQ (1<<8) 770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define SCAN_COUNT_ENABLE (1<<5) 780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define SIMULTANEOUS_ENABLE (1<<4) 790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define TRIGGER_FALLING_EDGE (1<<3) 800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define CONTINUOUS_MODE (1<<2) 810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DISABLE_ADC (0<<0) 820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define SOFTWARE_TRIGGERED_ADC (1<<0) 830e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define SCAN_TRIGGERED_ADC (2<<0) 840e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define EXT_TRIGGERED_ADC (3<<0) 850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_ADC_START 0x0000 /* R | - */ 860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_CONTROL_2 0x0002 /* - | W */ 870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ENABLE_ADFIFO (1<<10) 880e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ENABLE_CHANLIST (1<<9) 890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ENABLE_PORT_B (1<<7) 900e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ENABLE_PORT_A (1<<6) 91d5a2ffd8e8d602293339f69180aff8914c454d83Uwe Kleine-König#define ENABLE_COUNTER_B (1<<4) 92d5a2ffd8e8d602293339f69180aff8914c454d83Uwe Kleine-König#define ENABLE_COUNTER_A (1<<3) 93d5a2ffd8e8d602293339f69180aff8914c454d83Uwe Kleine-König#define ENABLE_DAC (1<<1) 940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define BUFFERED_DAC (1<<0) 950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_DAC_UPDATE 0x0002 /* R | - */ 9697feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ME_STATUS 0x0004 /* R | - */ 9797feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define COUNTER_B_IRQ_PENDING (1<<12) 980e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define COUNTER_A_IRQ_PENDING (1<<11) 990e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define CHANLIST_READY_IRQ_PENDING (1<<10) 1000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define EXT_IRQ_PENDING (1<<9) 10125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi#define ADFIFO_HALFFULL_IRQ_PENDING (1<<8) 1022696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define ADFIFO_FULL (1<<4) 10397feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ADFIFO_HALFFULL (1<<3) 10497feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ADFIFO_EMPTY (1<<2) 1050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define CHANLIST_FULL (1<<1) 1060e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define FST_ACTIVE (1<<0) 1070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_RESET_INTERRUPT 0x0004 /* - | W */ 1080e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_DIO_PORT_A 0x0006 /* R | W */ 1090e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_DIO_PORT_B 0x0008 /* R | W */ 1100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_TIMER_DATA_0 0x000A /* - | W */ 1112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define ME_TIMER_DATA_1 0x000C /* - | W */ 1120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_TIMER_DATA_2 0x000E /* - | W */ 1130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_CHANNEL_LIST 0x0010 /* - | W */ 1140e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ADC_UNIPOLAR (1<<6) 1150e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ADC_GAIN_0 (0<<4) 1160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ADC_GAIN_1 (1<<4) 1170e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ADC_GAIN_2 (2<<4) 1180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ADC_GAIN_3 (3<<4) 11997feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ME_READ_AD_FIFO 0x0010 /* R | - */ 12097feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ME_DAC_CONTROL 0x0012 /* - | W */ 1210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_UNIPOLAR_D (0<<4) 1220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_BIPOLAR_D (1<<4) 1230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_UNIPOLAR_C (0<<5) 1240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_BIPOLAR_C (1<<5) 1250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_UNIPOLAR_B (0<<6) 1260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_BIPOLAR_B (1<<6) 1270e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_UNIPOLAR_A (0<<7) 1280e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_BIPOLAR_A (1<<7) 1290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_GAIN_0_D (0<<8) 1302696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DAC_GAIN_1_D (1<<8) 1310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_GAIN_0_C (0<<9) 1320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define DAC_GAIN_1_C (1<<9) 1339ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton#define DAC_GAIN_0_B (0<<10) 1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define DAC_GAIN_1_B (1<<10) 1350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define DAC_GAIN_0_A (0<<11) 1360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define DAC_GAIN_1_A (1<<11) 1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_DAC_CONTROL_UPDATE 0x0012 /* R | - */ 1380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_DAC_DATA_A 0x0014 /* - | W */ 1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_DAC_DATA_B 0x0016 /* - | W */ 1400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_DAC_DATA_C 0x0018 /* - | W */ 1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_DAC_DATA_D 0x001A /* - | W */ 1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_COUNTER_ENDDATA_A 0x001C /* - | W */ 1430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral#define ME_COUNTER_ENDDATA_B 0x001E /* - | W */ 1440e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_COUNTER_STARTDATA_A 0x0020 /* - | W */ 1450e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define ME_COUNTER_VALUE_A 0x0020 /* R | - */ 14697feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ME_COUNTER_STARTDATA_B 0x0022 /* - | W */ 14797feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark#define ME_COUNTER_VALUE_B 0x0022 /* R | - */ 1480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 1499ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton/* Function prototypes */ 1500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int me_attach(struct comedi_device *dev, struct comedi_devconfig *it); 1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int me_detach(struct comedi_device *dev); 1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic const struct comedi_lrange me2000_ai_range = { 1540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 8, 1550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral { 1560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(10), 1570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 1580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 1590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1.25), 1600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(5), 1620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(2.5), 1630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes UNI_RANGE(1.25) 1640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 16597feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark}; 16697feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark 16797feeef5c55fe783e6f01d4dec3fd0926e60b0d8Markstatic const struct comedi_lrange me2600_ai_range = { 1680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8, 1699ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton { 1700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(10), 1710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 1720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.5), 1730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(1.25), 1740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(10), 1750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral UNI_RANGE(5), 1760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes UNI_RANGE(2.5), 1770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes UNI_RANGE(1.25) 1780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 1790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes}; 1809ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton 1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic const struct comedi_lrange me2600_ao_range = { 1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 3, 1830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral { 1840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(10), 1850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(5), 1860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes UNI_RANGE(10) 1870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 1889ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton}; 1890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic DEFINE_PCI_DEVICE_TABLE(me_pci_table) = { 1910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) }, 1920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) }, 1930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes {0} 1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral}; 1950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 196da91b2692e0939b307f9047192d2b9fe07793e7aBill PembertonMODULE_DEVICE_TABLE(pci, me_pci_table); 1970e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 1987875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton/* Board specification structure */ 1992696fb57e6af653dd8b4df41b16754579f42fc78Bill Pembertonstruct me_board { 2000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes const char *name; /* driver name */ 2012696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int device_id; 2022696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ao_channel_nbr; /* DA config */ 2032696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ao_resolution; 2042696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ao_resolution_mask; 2052696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton const struct comedi_lrange *ao_range_list; 2062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ai_channel_nbr; /* AD config */ 2072696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ai_resolution; 2082696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ai_resolution_mask; 2092696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton const struct comedi_lrange *ai_range_list; 2102696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int dio_channel_nbr; /* DIO config */ 2112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton}; 2122696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 2132696fb57e6af653dd8b4df41b16754579f42fc78Bill Pembertonstatic const struct me_board me_boards[] = { 2142696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton { 2152696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* -- ME-2600i -- */ 2162696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton .name = ME_DRIVER_NAME, 2177875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton .device_id = ME2600_DEVICE_ID, 2180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Analog Output */ 2190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .ao_channel_nbr = 4, 220d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas .ao_resolution = 12, 221d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas .ao_resolution_mask = 0x0fff, 222d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas .ao_range_list = &me2600_ao_range, 223d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas .ai_channel_nbr = 16, 224d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas /* Analog Input */ 225d991058efbc140957af0f3338ad6f52448c2890eJavier Martinez Canillas .ai_resolution = 12, 2260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .ai_resolution_mask = 0x0fff, 2270e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .ai_range_list = &me2600_ai_range, 2280e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .dio_channel_nbr = 32, 2290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes }, 2307875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton { 2310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* -- ME-2000i -- */ 2320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = ME_DRIVER_NAME, 2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = ME2000_DEVICE_ID, 2340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* Analog Output */ 2350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_channel_nbr = 0, 2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_resolution = 0, 2370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .ao_resolution_mask = 0, 2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_range_list = NULL, 2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_channel_nbr = 16, 2400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* Analog Input */ 2410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_resolution = 12, 2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_resolution_mask = 0x0fff, 2430e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .ai_range_list = &me2000_ai_range, 2440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_channel_nbr = 32, 2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral}; 2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 2480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes#define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board)) 2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 2500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic struct comedi_driver me_driver = { 2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .driver_name = ME_DRIVER_NAME, 2520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .module = THIS_MODULE, 2530e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .attach = me_attach, 2540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .detach = me_detach, 2550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral}; 2560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 2570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int __devinit me_driver_pci_probe(struct pci_dev *dev, 2580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes const struct pci_device_id *ent) 2590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral{ 2600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral return comedi_pci_auto_config(dev, me_driver.driver_name); 2610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral} 2620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 2632696fb57e6af653dd8b4df41b16754579f42fc78Bill Pembertonstatic void __devexit me_driver_pci_remove(struct pci_dev *dev) 2640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 2650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes comedi_pci_auto_unconfig(dev); 2660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 2677875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton 2680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic struct pci_driver me_driver_pci_driver = { 269139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton .id_table = me_pci_table, 2700e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .probe = &me_driver_pci_probe, 2710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes .remove = __devexit_p(&me_driver_pci_remove) 2720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes}; 2730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 2740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int __init me_driver_init_module(void) 2750e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 2767875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton int retval; 2770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 2780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes retval = comedi_driver_register(&me_driver); 2796e8131a86d6c1a9896282f572d17c447a85262adBill Pemberton if (retval < 0) 2802696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton return retval; 2812696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 2822696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton me_driver_pci_driver.name = (char *)me_driver.driver_name; 2832696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton return pci_register_driver(&me_driver_pci_driver); 2842696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton} 2852696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 2862696fb57e6af653dd8b4df41b16754579f42fc78Bill Pembertonstatic void __exit me_driver_cleanup_module(void) 2872696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton{ 2882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton pci_unregister_driver(&me_driver_pci_driver); 2892696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton comedi_driver_unregister(&me_driver); 2900e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 2910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 2920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesmodule_init(me_driver_init_module); 2930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesmodule_exit(me_driver_cleanup_module); 2942696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 2952696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* Private data structure */ 2962696fb57e6af653dd8b4df41b16754579f42fc78Bill Pembertonstruct me_private_data { 2972696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton struct pci_dev *pci_device; 2982696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton void __iomem *plx_regbase; /* PLX configuration base address */ 2992696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton void __iomem *me_regbase; /* Base address of the Meilhaus card */ 3002696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton unsigned long plx_regbase_size; /* Size of PLX configuration space */ 3012696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton unsigned long me_regbase_size; /* Size of Meilhaus space */ 3022696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned short control_1; /* Mirror of CONTROL_1 register */ 3042696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton unsigned short control_2; /* Mirror of CONTROL_2 register */ 3050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned short dac_control; /* Mirror of the DAC_CONTROL register */ 3062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int ao_readback[4]; /* Mirror of analog output data */ 30797feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark}; 30897feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark 3096e8131a86d6c1a9896282f572d17c447a85262adBill Pemberton#define dev_private ((struct me_private_data *)dev->private) 3100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3116e8131a86d6c1a9896282f572d17c447a85262adBill Pemberton/* 3127875a00b702e62ebafe68cd2abf96570e2d747e5Bill Pemberton * ------------------------------------------------------------------ 3130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 3140e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Helpful functions 3150e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 3160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 3170e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic inline void sleep(unsigned sec) 3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral{ 3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral current->state = TASK_INTERRUPTIBLE; 3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral schedule_timeout(sec * HZ); 3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral} 3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral/* 3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * ------------------------------------------------------------------ 3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 327da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton * DIGITAL INPUT/OUTPUT SECTION 3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * ------------------------------------------------------------------ 3300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 33197feeef5c55fe783e6f01d4dec3fd0926e60b0d8Markstatic int me_dio_insn_config(struct comedi_device *dev, 33297feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark struct comedi_subdevice *s, 33397feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark struct comedi_insn *insn, unsigned int *data) 3340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 3350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int bits; 3360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int mask = 1 << CR_CHAN(insn->chanspec); 3370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* calculate port */ 3390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (mask & 0x0000ffff) { /* Port A in use */ 3400e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes bits = 0x0000ffff; 3410e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* Enable Port A */ 3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_private->control_2 |= ENABLE_PORT_A; 3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral writew(dev_private->control_2, 3450e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase + ME_CONTROL_2); 3460e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } else { /* Port B in use */ 3470e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes bits = 0xffff0000; 3490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Enable Port B */ 3510e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 |= ENABLE_PORT_B; 3520e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_2, 3532696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton dev_private->me_regbase + ME_CONTROL_2); 3540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 3550e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (data[0]) { 3570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Config port as output */ 3580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes s->io_bits |= bits; 3590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } else { 3600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Config port as input */ 3610e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes s->io_bits &= ~bits; 3620e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 3630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 1; 3650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 3660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3675f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman/* Digital instant input/outputs */ 3680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_dio_insn_bits(struct comedi_device *dev, 3690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_subdevice *s, 3700e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_insn *insn, unsigned int *data) 3710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 3720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int mask = data[0]; 3730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes s->state &= ~mask; 3740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes s->state |= (mask & data[1]); 3750e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes mask &= s->io_bits; 3770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (mask & 0x0000ffff) { /* Port A */ 3780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew((s->state & 0xffff), 3790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase + ME_DIO_PORT_A); 3800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } else { 3810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[1] &= ~0x0000ffff; 3820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_A); 3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 3840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 3850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (mask & 0xffff0000) { /* Port B */ 3860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(((s->state >> 16) & 0xffff), 3870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase + ME_DIO_PORT_B); 3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } else { 3890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[1] &= ~0xffff0000; 3900e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16; 3910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 3920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 2; 3940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 3950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 3960e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 3970e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 3980e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 3990e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ANALOG INPUT SECTION 4000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 4010e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 4020e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 4030e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4040e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Analog instant input */ 4050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_ai_insn_read(struct comedi_device *dev, 4060e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_subdevice *subdevice, 4070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_insn *insn, unsigned int *data) 4080e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 4090e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned short value; 4100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int chan = CR_CHAN((&insn->chanspec)[0]); 4110e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int rang = CR_RANGE((&insn->chanspec)[0]); 4120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int aref = CR_AREF((&insn->chanspec)[0]); 4130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral int i; 4140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 4150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* stop any running conversion */ 4160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_1 &= 0xFFFC; 4170e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); 4180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* clear chanlist and ad fifo */ 4200e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST); 4210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); 4220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* reset any pending interrupt */ 4240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT); 4250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* enable the chanlist and ADC fifo */ 4270e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST); 4280e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); 4290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* write to channel list fifo */ 4310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* b3:b0 are the channel number */ 4320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value = chan & 0x0f; 4330e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* b5:b4 are the channel gain */ 4340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value |= (rang & 0x03) << 4; 4350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* b6 channel polarity */ 4360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value |= (rang & 0x04) << 4; 4370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* b7 single or differential */ 4380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value |= ((aref & AREF_DIFF) ? 0x80 : 0); 4390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(value & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST); 4400e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4410e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* set ADC mode to software trigger */ 4420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC; 4430e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); 4440e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* start conversion by reading from ADC_START */ 4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral readw(dev_private->me_regbase + ME_ADC_START); 4470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 4480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* wait for ADC fifo not empty flag */ 4490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 100000; i > 0; i--) 4500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004)) 4510e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes break; 4520e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4530e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* get value from ADC fifo */ 4540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (i) { 4550e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[0] = 4560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes (readw(dev_private->me_regbase + 4570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF; 4580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } else { 4590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_ERR "comedi%d: Cannot get single value\n", 4600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->minor); 4610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral return -EIO; 4620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 4630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 4640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* stop any running conversion */ 4650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_1 &= 0xFFFC; 4660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); 4670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 1; 4690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 4700e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 4720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 4730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * HARDWARE TRIGGERED ANALOG INPUT SECTION 4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 4760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 4770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 4780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Cancel analog input autoscan */ 4800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 4810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 4820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* disable interrupts */ 4830e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4840e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* stop any running conversion */ 4850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_1 &= 0xFFFC; 4860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); 4870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4880e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 4890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral/* Test analog input command */ 4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int me_ai_do_cmd_test(struct comedi_device *dev, 4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 4940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 4950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 4960e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 4970e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 4980e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Analog input command */ 4990e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_ai_do_cmd(struct comedi_device *dev, 5000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_subdevice *subdevice) 5010e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 5020e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 5030e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 5040e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 5060e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 5070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 5080e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ANALOG OUTPUT SECTION 5090e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * 5100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 5110e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 5120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Analog instant output */ 5140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int me_ao_insn_write(struct comedi_device *dev, 5150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 5170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral{ 5180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int chan; 5190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int rang; 5200e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int i; 5210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Enable all DAC */ 5230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 |= ENABLE_DAC; 5240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); 5250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* and set DAC to "buffered" mode */ 5270e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 |= BUFFERED_DAC; 5280e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); 5290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Set dac-control register */ 5310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 0; i < insn->n; i++) { 5320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes chan = CR_CHAN((&insn->chanspec)[i]); 5330e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes rang = CR_RANGE((&insn->chanspec)[i]); 5340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* clear bits for this channel */ 5360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->dac_control &= ~(0x0880 >> chan); 5370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (rang == 0) 5380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->dac_control |= 5390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes ((DAC_BIPOLAR_A | DAC_GAIN_1_A) >> chan); 5400e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes else if (rang == 1) 5410e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->dac_control |= 5420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan); 543da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton } 5440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral writew(dev_private->dac_control, 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_private->me_regbase + ME_DAC_CONTROL); 5460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 5470e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Update dac-control register */ 5480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE); 5490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Set data register */ 5510e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 0; i < insn->n; i++) { 5520e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes chan = CR_CHAN((&insn->chanspec)[i]); 5530e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew((data[0] & s->maxdata), 5540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1)); 5550e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->ao_readback[chan] = (data[0] & s->maxdata); 5560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 5570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Update dac with data registers */ 5590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes readw(dev_private->me_regbase + ME_DAC_UPDATE); 5600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5610e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return i; 5620e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 5630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Analog output readback */ 5650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_ao_insn_read(struct comedi_device *dev, 5660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_subdevice *s, struct comedi_insn *insn, 5670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int *data) 5680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 5690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int i; 5700e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 0; i < insn->n; i++) { 5720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes data[i] = 5730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->ao_readback[CR_CHAN((&insn->chanspec)[i])]; 5740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 5750e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 1; 5770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 5780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* 5800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 5810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 5820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * INITIALISATION SECTION 5830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 5840e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * ------------------------------------------------------------------ 5850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 5860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Xilinx firmware download for card: ME-2600i */ 5880e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me2600_xilinx_download(struct comedi_device *dev, 5890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned char *me2600_firmware, 5900e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int length) 5910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 5920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int value; 5930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int file_length; 5940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned int i; 5950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5960e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* disable irq's on PLX */ 5972696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton writel(0x00, dev_private->plx_regbase + PLX_INTCSR); 5980e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 5990e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* First, make a dummy read to reset xilinx */ 6000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET); 6010e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6020e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Wait until reset is over */ 6030e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes sleep(1); 6040e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Write a dummy value to Xilinx */ 6060e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writeb(0x00, dev_private->me_regbase + 0x0); 6070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes sleep(1); 6080e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6090e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* 61071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton * Format of the firmware 61134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton * Build longs from the byte-wise coded header 6120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Byte 1-3: length of the array 6130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Byte 4-7: version 614790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton * Byte 8-11: date 6150e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Byte 12-15: reserved 6160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 6170e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (length < 16) 6180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EINVAL; 6190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) + 6205f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman (((unsigned int)me2600_firmware[1] & 0xff) << 16) + 6210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes (((unsigned int)me2600_firmware[2] & 0xff) << 8) + 6220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes ((unsigned int)me2600_firmware[3] & 0xff); 6230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* 6250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Loop for writing firmware byte by byte to xilinx 6260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Firmware data start at offfset 16 6275f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman */ 6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral for (i = 0; i < file_length; i++) 6290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral writeb((me2600_firmware[16 + i] & 0xff), 6300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase + 0x0); 6310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Write 5 dummy values to xilinx */ 6330e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 0; i < 5; i++) 6340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writeb(0x00, dev_private->me_regbase + 0x0); 6350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6362696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* Test if there was an error during download -> INTB was thrown */ 6370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes value = readl(dev_private->plx_regbase + PLX_INTCSR); 6380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (value & 0x20) { 6390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Disable interrupt */ 6400e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writel(0x00, dev_private->plx_regbase + PLX_INTCSR); 6410e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_ERR "comedi%d: Xilinx download failed\n", 6420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->minor); 6430e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 6440e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 6450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 6465f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman /* Wait until the Xilinx is ready for real work */ 6470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral sleep(1); 6480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 6490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* Enable PLX-Interrupts */ 6500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral writel(0x43, dev_private->plx_regbase + PLX_INTCSR); 6510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 6520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral return 0; 6530e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 6540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral/* Reset device */ 6560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_reset(struct comedi_device *dev) 6570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 6580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Reset board */ 6590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(0x00, dev_private->me_regbase + ME_CONTROL_1); 6600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(0x00, dev_private->me_regbase + ME_CONTROL_2); 6610e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT); 6620e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL); 6630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* Save values in the board context */ 6650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->dac_control = 0; 6660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_1 = 0; 6670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->control_2 = 0; 668ec14016e751106499ef237efc1000a424f53e372Jason Wong 6690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 670ec14016e751106499ef237efc1000a424f53e372Jason Wong} 6710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6722696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* 6730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * Attach 6740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 6750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * - Register PCI device 6760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * - Declare device driver capability 6770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral */ 6780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) 6792696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton{ 6800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct pci_dev *pci_device = NULL; 6810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct comedi_subdevice *subdevice; 6820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes struct me_board *board; 6830e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes resource_size_t plx_regbase_tmp; 6840e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned long plx_regbase_size_tmp; 6850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes resource_size_t me_regbase_tmp; 6860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned long me_regbase_size_tmp; 6870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes resource_size_t swap_regbase_tmp; 6882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton unsigned long swap_regbase_size_tmp; 6890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes resource_size_t regbase_tmp; 6900e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int result, error, i; 6910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Allocate private memory */ 6930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (alloc_private(dev, sizeof(struct me_private_data)) < 0) 6940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -ENOMEM; 6950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 6960e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Probe the device to determine what device in the series it is. */ 6970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral for_each_pci_dev(pci_device) { 6980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) { 6990e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes for (i = 0; i < me_board_nbr; i++) { 7000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (me_boards[i].device_id == 7010e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes pci_device->device) { 7020e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* 7030e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * was a particular bus/slot requested? 7040e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 7050e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if ((it->options[0] != 0) 7060e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes || (it->options[1] != 0)) { 7070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* 7080e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes * are we on the wrong bus/slot? 7090e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes */ 7100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (pci_device->bus->number != 7110e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes it->options[0] 7125f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman || 7130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral PCI_SLOT(pci_device->devfn) 7140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral != it->options[1]) { 7150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral continue; 7160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 7170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 7180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->board_ptr = me_boards + i; 7200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral board = 7210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes (struct me_board *)dev->board_ptr; 7220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->pci_device = pci_device; 7230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes goto found; 7240e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 7280e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_ERR 7300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", 7310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->minor, it->options[0], it->options[1]); 7320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 7330e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesfound: 73561283d227c6b39e30afc6346db099521b0b64fa1Ian Abbott printk(KERN_INFO "comedi%d: found %s at PCI bus %d, slot %d\n", 7360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->minor, me_boards[i].name, 7370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes pci_device->bus->number, PCI_SLOT(pci_device->devfn)); 7380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Enable PCI device and request PCI regions */ 7400e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) { 7410e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_ERR "comedi%d: Failed to enable PCI device and " 7420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes "request regions\n", dev->minor); 7430e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 7440e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 74571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton 74634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton /* Set data in device structure */ 7470e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->board_name = board->name; 7480e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Read PLX register base address [PCI_BASE_ADDRESS #0]. */ 7500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_tmp = pci_resource_start(pci_device, 0); 7510e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_size_tmp = pci_resource_len(pci_device, 0); 7525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman dev_private->plx_regbase = 7530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ioremap(plx_regbase_tmp, plx_regbase_size_tmp); 7540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->plx_regbase_size = plx_regbase_size_tmp; 7550e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (!dev_private->plx_regbase) { 7560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk("comedi%d: Failed to remap I/O memory\n", dev->minor); 7570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -ENOMEM; 7580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7605f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman /* Read Swap base address [PCI_BASE_ADDRESS #5]. */ 7610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 7620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral swap_regbase_tmp = pci_resource_start(pci_device, 5); 7630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes swap_regbase_size_tmp = pci_resource_len(pci_device, 5); 7640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (!swap_regbase_tmp) 7660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor); 7670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7680e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /*---------------------------------------------- Workaround start ---*/ 7690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (plx_regbase_tmp & 0x0080) { 770790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton printk(KERN_ERR "comedi%d: PLX-Bug detected\n", dev->minor); 771790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton 7720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (swap_regbase_tmp) { 7730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes regbase_tmp = plx_regbase_tmp; 7740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_tmp = swap_regbase_tmp; 7750e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes swap_regbase_tmp = regbase_tmp; 7760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 7770e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes result = pci_write_config_dword(pci_device, 7780e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes PCI_BASE_ADDRESS_0, 7790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_tmp); 7800e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (result != PCIBIOS_SUCCESSFUL) 7810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 7820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 78397feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark result = pci_write_config_dword(pci_device, 78497feeef5c55fe783e6f01d4dec3fd0926e60b0d8Mark PCI_BASE_ADDRESS_5, 7850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes swap_regbase_tmp); 7860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (result != PCIBIOS_SUCCESSFUL) 7870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 7880e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } else { 7890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_tmp -= 0x80; 7902696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton result = pci_write_config_dword(pci_device, 7910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes PCI_BASE_ADDRESS_0, 7920e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes plx_regbase_tmp); 7930e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (result != PCIBIOS_SUCCESSFUL) 7940e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EIO; 7950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7960e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 7970e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /*--------------------------------------------- Workaround end -----*/ 7980e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 79970265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby /* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */ 8000e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 80171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton me_regbase_tmp = pci_resource_start(pci_device, 2); 8020e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes me_regbase_size_tmp = pci_resource_len(pci_device, 2); 8030e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase_size = me_regbase_size_tmp; 8040e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp); 8052696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton if (!dev_private->me_regbase) { 8062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton printk(KERN_ERR "comedi%d: Failed to remap I/O memory\n", 8070e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes dev->minor); 8082696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton return -ENOMEM; 8092696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton } 8100e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* Download firmware and reset card */ 8110e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (board->device_id == ME2600_DEVICE_ID) { 8120e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes unsigned char *aux_data; 8130e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes int aux_len; 8142696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 8150e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes aux_data = comedi_aux_data(it->options, 0); 8160e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; 8172696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 8180e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (!aux_data || aux_len < 1) { 8190e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes comedi_error(dev, "You must provide me2600 firmware " 8200e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes "using the --init-data option of " 8210e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes "comedi_config"); 8220e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return -EINVAL; 8230e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 8242696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton me2600_xilinx_download(dev, aux_data, aux_len); 8250e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 8260e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8270e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes me_reset(dev); 8282696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton 8290e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes /* device driver capabilities */ 8300e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes error = alloc_subdevices(dev, 3); 8310e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (error < 0) 8320e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return error; 8330e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8340e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice = dev->subdevices + 0; 8350e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->type = COMEDI_SUBD_AI; 8360e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; 8370e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->n_chan = board->ai_channel_nbr; 8380e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->maxdata = board->ai_resolution_mask; 8390e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->len_chanlist = board->ai_channel_nbr; 840da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton subdevice->range_table = board->ai_range_list; 8410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subdevice->cancel = me_ai_cancel; 8420e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->insn_read = me_ai_insn_read; 84348b1aff5b93521c5ad90842bef52b218ac50a4abIan Abbott subdevice->do_cmdtest = me_ai_do_cmd_test; 8440e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->do_cmd = me_ai_do_cmd; 8450e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8460e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice = dev->subdevices + 1; 8470e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->type = COMEDI_SUBD_AO; 8482696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton subdevice->subdev_flags = SDF_WRITEABLE | SDF_COMMON; 8490e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->n_chan = board->ao_channel_nbr; 8500e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->maxdata = board->ao_resolution_mask; 8510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral subdevice->len_chanlist = board->ao_channel_nbr; 8520e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->range_table = board->ao_range_list; 8530e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->insn_read = me_ao_insn_read; 8540e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->insn_write = me_ao_insn_write; 8550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 8560e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice = dev->subdevices + 2; 8570e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->type = COMEDI_SUBD_DIO; 8580e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->subdev_flags = SDF_READABLE | SDF_WRITEABLE; 8590e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->n_chan = board->dio_channel_nbr; 8600e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->maxdata = 1; 8610e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->len_chanlist = board->dio_channel_nbr; 8620e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->range_table = &range_digital; 8630e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->insn_bits = me_dio_insn_bits; 8640e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->insn_config = me_dio_insn_config; 8650e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes subdevice->io_bits = 0; 8660e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8670e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes printk(KERN_INFO "comedi%d: " ME_DRIVER_NAME " attached.\n", 8682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton dev->minor); 8690e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 8700e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes} 8710e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8720e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes/* Detach */ 8730e8db97a04b37960828b273d166e35eac9a1888bMichal Dobesstatic int me_detach(struct comedi_device *dev) 8740e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes{ 875ec14016e751106499ef237efc1000a424f53e372Jason Wong if (dev_private) { 8760e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (dev_private->me_regbase) { 877ec14016e751106499ef237efc1000a424f53e372Jason Wong me_reset(dev); 878ec14016e751106499ef237efc1000a424f53e372Jason Wong iounmap(dev_private->me_regbase); 8790e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 880ec14016e751106499ef237efc1000a424f53e372Jason Wong if (dev_private->plx_regbase) 8810e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes iounmap(dev_private->plx_regbase); 8820e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (dev_private->pci_device) { 8830e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes if (dev_private->plx_regbase_size) 8840e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes comedi_pci_disable(dev_private->pci_device); 8850e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8860e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes pci_dev_put(dev_private->pci_device); 8870e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 8880e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes } 8890e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes return 0; 8900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral} 8910e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes 8920e8db97a04b37960828b273d166e35eac9a1888bMichal DobesMODULE_AUTHOR("Comedi http://www.comedi.org"); 8930e8db97a04b37960828b273d166e35eac9a1888bMichal DobesMODULE_DESCRIPTION("Comedi low-level driver"); 8940e8db97a04b37960828b273d166e35eac9a1888bMichal DobesMODULE_LICENSE("GPL"); 8950e8db97a04b37960828b273d166e35eac9a1888bMichal Dobes