1a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef/* 2a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef comedi/drivers/dt2814.c 3a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef Hardware driver for Data Translation DT2814 4a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 5a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef COMEDI - Linux Control and Measurement Device Interface 6a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef Copyright (C) 1998 David A. Schleef <ds@schleef.org> 7a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 8a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef This program is free software; you can redistribute it and/or modify 9a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef it under the terms of the GNU General Public License as published by 10a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef the Free Software Foundation; either version 2 of the License, or 11a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef (at your option) any later version. 12a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 13a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef This program is distributed in the hope that it will be useful, 14a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 15a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef GNU General Public License for more details. 17a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 18a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef You should have received a copy of the GNU General Public License 19a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef along with this program; if not, write to the Free Software 20a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 22a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef*/ 23a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef/* 24a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefDriver: dt2814 25a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefDescription: Data Translation DT2814 26a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefAuthor: ds 27a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefStatus: complete 28a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefDevices: [Data Translation] DT2814 (dt2814) 29a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 30a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefConfiguration options: 31a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef [0] - I/O port base address 32a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef [1] - IRQ 33a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 34a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid SchleefThis card has 16 analog inputs multiplexed onto a 12 bit ADC. There 35a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefis a minimally useful onboard clock. The base frequency for the 36a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefclock is selected by jumpers, and the clock divider can be selected 37a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefvia programmed I/O. Unfortunately, the clock divider can only be 38a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefa power of 10, from 1 to 10^7, of which only 3 or 4 are useful. In 39a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefaddition, the clock does not seem to be very accurate. 40a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef*/ 41a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 4225436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 43a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#include "../comedidev.h" 44a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 45a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#include <linux/ioport.h> 46a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#include <linux/delay.h> 47a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 48a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_SIZE 2 49a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 50a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_CSR 0 51a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_DATA 1 52a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 53a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef/* 54a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef * flags 55a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef */ 56a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 57a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_FINISH 0x80 58a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_ERR 0x40 59a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_BUSY 0x20 60a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_ENB 0x10 61a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_CHANMASK 0x0f 62a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt2814_attach(struct comedi_device *dev, 640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 65da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt2814_detach(struct comedi_device *dev); 66139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_dt2814 = { 6768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "dt2814", 6868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 6968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = dt2814_attach, 7068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = dt2814_detach, 71a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef}; 72a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 737114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_dt2814_init_module(void) 747114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 757114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_dt2814); 767114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 777114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 787114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_dt2814_cleanup_module(void) 797114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 807114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_dt2814); 817114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 827114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 837114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_dt2814_init_module); 847114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_dt2814_cleanup_module); 85a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 8670265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t dt2814_interrupt(int irq, void *dev); 87a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 88ca6f10ca8630d709e0d291fb9601f8c8d81c19a0Bill Pembertonstruct dt2814_private { 89ca6f10ca8630d709e0d291fb9601f8c8d81c19a0Bill Pemberton 90a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int ntrig; 91a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int curadchan; 92ca6f10ca8630d709e0d291fb9601f8c8d81c19a0Bill Pemberton}; 93ca6f10ca8630d709e0d291fb9601f8c8d81c19a0Bill Pemberton 94ca6f10ca8630d709e0d291fb9601f8c8d81c19a0Bill Pemberton#define devpriv ((struct dt2814_private *)dev->private) 95a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 96a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_TIMEOUT 10 97a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#define DT2814_MAX_SPEED 100000 /* Arbitrary 10 khz limit */ 98a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt2814_ai_insn_read(struct comedi_device *dev, 1000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 102a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 103a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int n, i, hi, lo; 104a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int chan; 105a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int status = 0; 106a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 107a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef for (n = 0; n < insn->n; n++) { 108a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef chan = CR_CHAN(insn->chanspec); 109a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 110a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef outb(chan, dev->iobase + DT2814_CSR); 111a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef for (i = 0; i < DT2814_TIMEOUT; i++) { 112a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef status = inb(dev->iobase + DT2814_CSR); 1133f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_INFO "dt2814: status: %02x\n", status); 1145f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(10); 115a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (status & DT2814_FINISH) 116a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef break; 117a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 118a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (i >= DT2814_TIMEOUT) { 1193f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_INFO "dt2814: status: %02x\n", status); 120a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return -ETIMEDOUT; 121a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 122a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 123a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef hi = inb(dev->iobase + DT2814_DATA); 124a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef lo = inb(dev->iobase + DT2814_DATA); 125a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 126a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef data[n] = (hi << 4) | (lo >> 4); 127a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 128a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 129a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return n; 130a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 131a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 132a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleefstatic int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags) 133a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 134a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int i; 135a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef unsigned int f; 136a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 137a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* XXX ignores flags */ 138a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 139a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef f = 10000; /* ns */ 140a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef for (i = 0; i < 8; i++) { 141a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if ((2 * (*ns)) < (f * 11)) 142a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef break; 143a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef f *= 10; 144a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 145a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 146a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef *ns = f; 147a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 148a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return i; 149a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 150a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dt2814_ai_cmdtest(struct comedi_device *dev, 1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 153a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 154a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int err = 0; 155a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int tmp; 156a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 157a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* step 1: make sure trigger sources are trivially valid */ 158a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 159a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->start_src; 160a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->start_src &= TRIG_NOW; 161a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!cmd->start_src || tmp != cmd->start_src) 162a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 163a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 164a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->scan_begin_src; 165a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->scan_begin_src &= TRIG_TIMER; 166a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 167a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 168a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 169a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->convert_src; 170a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->convert_src &= TRIG_NOW; 171a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 172a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 173a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 174a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->scan_end_src; 175a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->scan_end_src &= TRIG_COUNT; 176a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 177a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 178a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 179a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->stop_src; 180a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 181a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 182a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 183a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 184a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (err) 185a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 1; 186a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 1873f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus /* step 2: make sure trigger sources are 1883f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus * unique and mutually compatible */ 189a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 190828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel /* note that mutual compatibility is not an issue here */ 191a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) 192a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 193a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 194a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (err) 195a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 2; 196a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 197a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* step 3: make sure arguments are trivially compatible */ 198a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 199a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->start_arg != 0) { 200a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->start_arg = 0; 201a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 202a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 203a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->scan_begin_arg > 1000000000) { 204a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->scan_begin_arg = 1000000000; 205a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 206a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 207a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->scan_begin_arg < DT2814_MAX_SPEED) { 208a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->scan_begin_arg = DT2814_MAX_SPEED; 209a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 210a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 211a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->scan_end_arg != cmd->chanlist_len) { 212a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->scan_end_arg = cmd->chanlist_len; 213a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 214a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 215a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->stop_src == TRIG_COUNT) { 216a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->stop_arg < 2) { 217a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->stop_arg = 2; 218a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 219a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 220a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } else { 221a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* TRIG_NONE */ 222a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (cmd->stop_arg != 0) { 223a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef cmd->stop_arg = 0; 224a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 225a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 226a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 227a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 228a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (err) 229a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 3; 230a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 231a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* step 4: fix up any arguments */ 232a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 233a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef tmp = cmd->scan_begin_arg; 234a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dt2814_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); 235a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (tmp != cmd->scan_begin_arg) 236a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef err++; 237a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 238a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (err) 239a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 4; 240a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 241a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 0; 242a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 243a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 244da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 245a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 246ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd *cmd = &s->async->cmd; 247a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int chan; 248a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int trigvar; 249a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 250a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef trigvar = 2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dt2814_ns_to_timer(&cmd->scan_begin_arg, 2520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 253a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 254a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef chan = CR_CHAN(cmd->chanlist[0]); 255a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 256a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef devpriv->ntrig = cmd->stop_arg; 257a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef outb(chan | DT2814_ENB | (trigvar << 5), dev->iobase + DT2814_CSR); 258a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 259a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 0; 260a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 261a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 262a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 263da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) 264a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 265a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int i, irq; 266a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int ret; 26734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 268a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef unsigned long iobase; 269a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 270a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef iobase = it->options[0]; 2713f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_INFO "comedi%d: dt2814: 0x%04lx ", dev->minor, iobase); 272a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!request_region(iobase, DT2814_SIZE, "dt2814")) { 2733f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_ERR "I/O port conflict\n"); 274a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return -EIO; 275a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 276a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dev->iobase = iobase; 277a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dev->board_name = "dt2814"; 278a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 279a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef outb(0, dev->iobase + DT2814_CSR); 2805f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(100); 281a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) { 2823f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_ERR "reset error (fatal)\n"); 283a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return -EIO; 284a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 285a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef i = inb(dev->iobase + DT2814_DATA); 286a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef i = inb(dev->iobase + DT2814_DATA); 287a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 288a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef irq = it->options[1]; 289a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#if 0 290a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (irq < 0) { 291a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef save_flags(flags); 292a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef sti(); 293a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef irqs = probe_irq_on(); 294a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 295a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef outb(0, dev->iobase + DT2814_CSR); 296a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 2975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(100); 298a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 299a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef irq = probe_irq_off(irqs); 300a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef restore_flags(flags); 3013f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) 3023f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_DEBUG "error probing irq (bad)\n"); 3033f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus 304a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 305a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef i = inb(dev->iobase + DT2814_DATA); 306a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef i = inb(dev->iobase + DT2814_DATA); 307a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 308a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#endif 309a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dev->irq = 0; 310a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (irq > 0) { 3115f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman if (request_irq(irq, dt2814_interrupt, 0, "dt2814", dev)) { 3123f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_WARNING "(irq %d unavailable)\n", irq); 313a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } else { 3143f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_INFO "( irq = %d )\n", irq); 315a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dev->irq = irq; 316a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 317a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } else if (irq == 0) { 3183f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_WARNING "(no irq)\n"); 319a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } else { 320a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#if 0 3213f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_DEBUG "(probe returned multiple irqs--bad)\n"); 322a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#else 3233f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_WARNING "(irq probe not implemented)\n"); 324a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef#endif 325a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 326a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 327c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_subdevices(dev, 1); 328c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 329a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return ret; 330c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton 331c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_private(dev, sizeof(struct dt2814_private)); 332c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 333a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return ret; 334a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 335a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s = dev->subdevices + 0; 336a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef dev->read_subdev = s; 337a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->type = COMEDI_SUBD_AI; 338a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; 339a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->n_chan = 16; /* XXX */ 340a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->len_chanlist = 1; 341a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->insn_read = dt2814_ai_insn_read; 342a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->do_cmd = dt2814_ai_cmd; 343a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->do_cmdtest = dt2814_ai_cmdtest; 344a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->maxdata = 0xfff; 345a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->range_table = &range_unknown; /* XXX */ 346a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 347a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 0; 348a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 349a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 350da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dt2814_detach(struct comedi_device *dev) 351a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 3523f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus printk(KERN_INFO "comedi%d: dt2814: remove\n", dev->minor); 353a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 3543f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus if (dev->irq) 3555f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman free_irq(dev->irq, dev); 3563f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus 3573f3ba29c78c4039a9fd746065ff89afec8bbc19aFelipe de Oliveira Tanus if (dev->iobase) 358a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef release_region(dev->iobase, DT2814_SIZE); 359a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 360a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return 0; 361a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 362a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 36370265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t dt2814_interrupt(int irq, void *d) 364a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef{ 365a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int lo, hi; 36671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = d; 36734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 368a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int data; 369a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 370a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!dev->attached) { 371a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef comedi_error(dev, "spurious interrupt"); 372a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return IRQ_HANDLED; 373a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 374a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 375a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s = dev->subdevices + 0; 376a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 377a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef hi = inb(dev->iobase + DT2814_DATA); 378a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef lo = inb(dev->iobase + DT2814_DATA); 379a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 380a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef data = (hi << 4) | (lo >> 4); 381a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 382a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (!(--devpriv->ntrig)) { 383a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef int i; 384a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 385a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef outb(0, dev->iobase + DT2814_CSR); 386a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef /* note: turning off timed mode triggers another 387a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef sample. */ 388a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 389a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef for (i = 0; i < DT2814_TIMEOUT; i++) { 390a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef if (inb(dev->iobase + DT2814_CSR) & DT2814_FINISH) 391a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef break; 392a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 393a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef inb(dev->iobase + DT2814_DATA); 394a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef inb(dev->iobase + DT2814_DATA); 395a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef 396a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef s->async->events |= COMEDI_CB_EOA; 397a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef } 398a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef comedi_event(dev, s); 399a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef return IRQ_HANDLED; 400a211ea977a4127a88fe0a5c4846e33d0e8b2309fDavid Schleef} 40190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 40290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 40390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 40490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 405