linux/drivers/staging/comedi/drivers/ni_mio_cs.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/ni_mio_cs.c
   3    Hardware driver for NI PCMCIA MIO E series cards
   4
   5    COMEDI - Linux Control and Measurement Device Interface
   6    Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
   7
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 2 of the License, or
  11    (at your option) any later version.
  12
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17
  18    You should have received a copy of the GNU General Public License
  19    along with this program; if not, write to the Free Software
  20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21
  22*/
  23/*
  24Driver: ni_mio_cs
  25Description: National Instruments DAQCard E series
  26Author: ds
  27Status: works
  28Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs),
  29  DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E
  30Updated: Thu Oct 23 19:43:17 CDT 2003
  31
  32See the notes in the ni_atmio.o driver.
  33*/
  34/*
  35        The real guts of the driver is in ni_mio_common.c, which is
  36        included by all the E series drivers.
  37
  38        References for specifications:
  39
  40           341080a.pdf  DAQCard E Series Register Level Programmer Manual
  41
  42*/
  43
  44#include "../comedidev.h"
  45
  46#include <linux/delay.h>
  47
  48#include "ni_stc.h"
  49#include "8255.h"
  50
  51#include <pcmcia/cistpl.h>
  52#include <pcmcia/ds.h>
  53
  54#undef DEBUG
  55
  56#define ATMIO 1
  57#undef PCIMIO
  58
  59/*
  60 *  AT specific setup
  61 */
  62
  63#define NI_SIZE 0x20
  64
  65#define MAX_N_CALDACS 32
  66
  67static const struct ni_board_struct ni_boards[] = {
  68        {
  69                .device_id      = 0x010d,
  70                .name           = "DAQCard-ai-16xe-50",
  71                .n_adchan       = 16,
  72                .adbits         = 16,
  73                .ai_fifo_depth  = 1024,
  74                .gainlkup       = ai_gain_8,
  75                .ai_speed       = 5000,
  76                .num_p0_dio_channels = 8,
  77                .caldac         = { dac8800, dac8043 },
  78        }, {
  79                .device_id      = 0x010c,
  80                .name           = "DAQCard-ai-16e-4",
  81                .n_adchan       = 16,
  82                .adbits         = 12,
  83                .ai_fifo_depth  = 1024,
  84                .gainlkup       = ai_gain_16,
  85                .ai_speed       = 4000,
  86                .num_p0_dio_channels = 8,
  87                .caldac         = { mb88341 },          /* verified */
  88        }, {
  89                .device_id      = 0x02c4,
  90                .name           = "DAQCard-6062E",
  91                .n_adchan       = 16,
  92                .adbits         = 12,
  93                .ai_fifo_depth  = 8192,
  94                .gainlkup       = ai_gain_16,
  95                .ai_speed       = 2000,
  96                .n_aochan       = 2,
  97                .aobits         = 12,
  98                .ao_fifo_depth  = 2048,
  99                .ao_range_table = &range_bipolar10,
 100                .ao_speed       = 1176,
 101                .num_p0_dio_channels = 8,
 102                .caldac         = { ad8804_debug },     /* verified */
 103         }, {
 104                /* specs incorrect! */
 105                .device_id      = 0x075e,
 106                .name           = "DAQCard-6024E",
 107                .n_adchan       = 16,
 108                .adbits         = 12,
 109                .ai_fifo_depth  = 1024,
 110                .gainlkup       = ai_gain_4,
 111                .ai_speed       = 5000,
 112                .n_aochan       = 2,
 113                .aobits         = 12,
 114                .ao_range_table = &range_bipolar10,
 115                .ao_speed       = 1000000,
 116                .num_p0_dio_channels = 8,
 117                .caldac         = { ad8804_debug },
 118        }, {
 119                /* specs incorrect! */
 120                .device_id      = 0x0245,
 121                .name           = "DAQCard-6036E",
 122                .n_adchan       = 16,
 123                .adbits         = 16,
 124                .ai_fifo_depth  = 1024,
 125                .alwaysdither   = 1,
 126                .gainlkup       = ai_gain_4,
 127                .ai_speed       = 5000,
 128                .n_aochan       = 2,
 129                .aobits         = 16,
 130                .ao_range_table = &range_bipolar10,
 131                .ao_speed       = 1000000,
 132                .num_p0_dio_channels = 8,
 133                .caldac         = { ad8804_debug },
 134         },
 135#if 0
 136        {
 137                .device_id      = 0x0000,       /* unknown */
 138                .name           = "DAQCard-6715",
 139                .n_aochan       = 8,
 140                .aobits         = 12,
 141                .ao_671x        = 8192,
 142                .num_p0_dio_channels = 8,
 143                .caldac         = { mb88341, mb88341 },
 144        },
 145#endif
 146};
 147
 148#define interrupt_pin(a)        0
 149
 150#define IRQ_POLARITY 1
 151
 152struct ni_private {
 153
 154        struct pcmcia_device *link;
 155
 156NI_PRIVATE_COMMON};
 157
 158/* How we access registers */
 159
 160#define ni_writel(a, b)         (outl((a), (b)+dev->iobase))
 161#define ni_readl(a)             (inl((a)+dev->iobase))
 162#define ni_writew(a, b)         (outw((a), (b)+dev->iobase))
 163#define ni_readw(a)             (inw((a)+dev->iobase))
 164#define ni_writeb(a, b)         (outb((a), (b)+dev->iobase))
 165#define ni_readb(a)             (inb((a)+dev->iobase))
 166
 167/* How we access windowed registers */
 168
 169/* We automatically take advantage of STC registers that can be
 170 * read/written directly in the I/O space of the board.  The
 171 * DAQCard devices map the low 8 STC registers to iobase+addr*2. */
 172
 173static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
 174{
 175        struct ni_private *devpriv = dev->private;
 176        unsigned long flags;
 177
 178        spin_lock_irqsave(&devpriv->window_lock, flags);
 179        if (addr < 8) {
 180                ni_writew(data, addr * 2);
 181        } else {
 182                ni_writew(addr, Window_Address);
 183                ni_writew(data, Window_Data);
 184        }
 185        spin_unlock_irqrestore(&devpriv->window_lock, flags);
 186}
 187
 188static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
 189{
 190        struct ni_private *devpriv = dev->private;
 191        unsigned long flags;
 192        uint16_t ret;
 193
 194        spin_lock_irqsave(&devpriv->window_lock, flags);
 195        if (addr < 8) {
 196                ret = ni_readw(addr * 2);
 197        } else {
 198                ni_writew(addr, Window_Address);
 199                ret = ni_readw(Window_Data);
 200        }
 201        spin_unlock_irqrestore(&devpriv->window_lock, flags);
 202
 203        return ret;
 204}
 205
 206#include "ni_mio_common.c"
 207
 208static const void *ni_getboardtype(struct comedi_device *dev,
 209                                   struct pcmcia_device *link)
 210{
 211        static const struct ni_board_struct *board;
 212        int i;
 213
 214        for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
 215                board = &ni_boards[i];
 216                if (board->device_id == link->card_id)
 217                        return board;
 218        }
 219        return NULL;
 220}
 221
 222static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 223{
 224        int base, ret;
 225
 226        p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 227        p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 228
 229        for (base = 0x000; base < 0x400; base += 0x20) {
 230                p_dev->resource[0]->start = base;
 231                ret = pcmcia_request_io(p_dev);
 232                if (!ret)
 233                        return 0;
 234        }
 235        return -ENODEV;
 236}
 237
 238static int mio_cs_auto_attach(struct comedi_device *dev,
 239                              unsigned long context)
 240{
 241        struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
 242        static const struct ni_board_struct *board;
 243        struct ni_private *devpriv;
 244        int ret;
 245
 246        board = ni_getboardtype(dev, link);
 247        if (!board)
 248                return -ENODEV;
 249        dev->board_ptr = board;
 250        dev->board_name = board->name;
 251
 252        link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 253        ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop);
 254        if (ret)
 255                return ret;
 256        dev->iobase = link->resource[0]->start;
 257
 258        link->priv = dev;
 259        ret = pcmcia_request_irq(link, ni_E_interrupt);
 260        if (ret)
 261                return ret;
 262        dev->irq = link->irq;
 263
 264        ret = ni_alloc_private(dev);
 265        if (ret)
 266                return ret;
 267
 268        devpriv = dev->private;
 269        devpriv->stc_writew     = mio_cs_win_out;
 270        devpriv->stc_readw      = mio_cs_win_in;
 271        devpriv->stc_writel     = win_out2;
 272        devpriv->stc_readl      = win_in2;
 273
 274        return ni_E_init(dev);
 275}
 276
 277static void mio_cs_detach(struct comedi_device *dev)
 278{
 279        mio_common_detach(dev);
 280        comedi_pcmcia_disable(dev);
 281}
 282
 283static struct comedi_driver driver_ni_mio_cs = {
 284        .driver_name    = "ni_mio_cs",
 285        .module         = THIS_MODULE,
 286        .auto_attach    = mio_cs_auto_attach,
 287        .detach         = mio_cs_detach,
 288};
 289
 290static int cs_attach(struct pcmcia_device *link)
 291{
 292        return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
 293}
 294
 295static const struct pcmcia_device_id ni_mio_cs_ids[] = {
 296        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d),        /* DAQCard-ai-16xe-50 */
 297        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c),        /* DAQCard-ai-16e-4 */
 298        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4),        /* DAQCard-6062E */
 299        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e),        /* DAQCard-6024E */
 300        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245),        /* DAQCard-6036E */
 301        PCMCIA_DEVICE_NULL
 302};
 303MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids);
 304
 305static struct pcmcia_driver ni_mio_cs_driver = {
 306        .name           = "ni_mio_cs",
 307        .owner          = THIS_MODULE,
 308        .id_table       = ni_mio_cs_ids,
 309        .probe          = cs_attach,
 310        .remove         = comedi_pcmcia_auto_unconfig,
 311};
 312module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);
 313
 314MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
 315MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
 316MODULE_LICENSE("GPL");
 317
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.