linux/drivers/staging/comedi/drivers/ni_daq_dio24.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/ni_daq_dio24.c
   3    Driver for National Instruments PCMCIA DAQ-Card DIO-24
   4    Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es>
   5
   6    PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13
   7    from the pcmcia package.
   8    The initial developer of the pcmcia dummy_cs.c code is David A. Hinds
   9    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  10    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  11
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 2 of the License, or
  15    (at your option) any later version.
  16
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21
  22    You should have received a copy of the GNU General Public License
  23    along with this program; if not, write to the Free Software
  24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25
  26************************************************************************
  27*/
  28/*
  29Driver: ni_daq_dio24
  30Description: National Instruments PCMCIA DAQ-Card DIO-24
  31Author: Daniel Vecino Castel <dvecino@able.es>
  32Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24)
  33Status: ?
  34Updated: Thu, 07 Nov 2002 21:53:06 -0800
  35
  36This is just a wrapper around the 8255.o driver to properly handle
  37the PCMCIA interface.
  38*/
  39
  40                            /* #define LABPC_DEBUG *//*  enable debugging messages */
  41#undef LABPC_DEBUG
  42
  43#include <linux/interrupt.h>
  44#include "../comedidev.h"
  45
  46#include <linux/ioport.h>
  47
  48#include "8255.h"
  49
  50#include <pcmcia/cs_types.h>
  51#include <pcmcia/cs.h>
  52#include <pcmcia/cistpl.h>
  53#include <pcmcia/cisreg.h>
  54#include <pcmcia/ds.h>
  55
  56static struct pcmcia_device *pcmcia_cur_dev = NULL;
  57
  58#define DIO24_SIZE 4            /*  size of io region used by board */
  59
  60static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
  61static int dio24_detach(struct comedi_device *dev);
  62
  63enum dio24_bustype { pcmcia_bustype };
  64
  65struct dio24_board_struct {
  66        const char *name;
  67        int device_id;          /*  device id for pcmcia board */
  68        enum dio24_bustype bustype;     /*  PCMCIA */
  69        int have_dio;           /*  have 8255 chip */
  70        /*  function pointers so we can use inb/outb or readb/writeb as appropriate */
  71        unsigned int (*read_byte) (unsigned int address);
  72        void (*write_byte) (unsigned int byte, unsigned int address);
  73};
  74
  75static const struct dio24_board_struct dio24_boards[] = {
  76        {
  77         .name = "daqcard-dio24",
  78         .device_id = 0x475c,   /*  0x10b is manufacturer id, 0x475c is device id */
  79         .bustype = pcmcia_bustype,
  80         .have_dio = 1,
  81         },
  82        {
  83         .name = "ni_daq_dio24",
  84         .device_id = 0x475c,   /*  0x10b is manufacturer id, 0x475c is device id */
  85         .bustype = pcmcia_bustype,
  86         .have_dio = 1,
  87         },
  88};
  89
  90/*
  91 * Useful for shorthand access to the particular board structure
  92 */
  93#define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
  94
  95struct dio24_private {
  96
  97        int data;               /* number of data points left to be taken */
  98};
  99
 100#define devpriv ((struct dio24_private *)dev->private)
 101
 102static struct comedi_driver driver_dio24 = {
 103        .driver_name = "ni_daq_dio24",
 104        .module = THIS_MODULE,
 105        .attach = dio24_attach,
 106        .detach = dio24_detach,
 107        .num_names = ARRAY_SIZE(dio24_boards),
 108        .board_name = &dio24_boards[0].name,
 109        .offset = sizeof(struct dio24_board_struct),
 110};
 111
 112static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 113{
 114        struct comedi_subdevice *s;
 115        unsigned long iobase = 0;
 116#ifdef incomplete
 117        unsigned int irq = 0;
 118#endif
 119        struct pcmcia_device *link;
 120
 121        /* allocate and initialize dev->private */
 122        if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
 123                return -ENOMEM;
 124
 125        /*  get base address, irq etc. based on bustype */
 126        switch (thisboard->bustype) {
 127        case pcmcia_bustype:
 128                link = pcmcia_cur_dev;  /* XXX hack */
 129                if (!link)
 130                        return -EIO;
 131                iobase = link->io.BasePort1;
 132#ifdef incomplete
 133                irq = link->irq.AssignedIRQ;
 134#endif
 135                break;
 136        default:
 137                printk("bug! couldn't determine board type\n");
 138                return -EINVAL;
 139                break;
 140        }
 141        printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
 142               thisboard->name, iobase);
 143#ifdef incomplete
 144        if (irq) {
 145                printk(", irq %u", irq);
 146        }
 147#endif
 148
 149        printk("\n");
 150
 151        if (iobase == 0) {
 152                printk("io base address is zero!\n");
 153                return -EINVAL;
 154        }
 155
 156        dev->iobase = iobase;
 157
 158#ifdef incomplete
 159        /* grab our IRQ */
 160        dev->irq = irq;
 161#endif
 162
 163        dev->board_name = thisboard->name;
 164
 165        if (alloc_subdevices(dev, 1) < 0)
 166                return -ENOMEM;
 167
 168        /* 8255 dio */
 169        s = dev->subdevices + 0;
 170        subdev_8255_init(dev, s, NULL, dev->iobase);
 171
 172        return 0;
 173};
 174
 175static int dio24_detach(struct comedi_device *dev)
 176{
 177        printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
 178
 179        if (dev->subdevices)
 180                subdev_8255_cleanup(dev, dev->subdevices + 0);
 181
 182        if (thisboard->bustype != pcmcia_bustype && dev->iobase)
 183                release_region(dev->iobase, DIO24_SIZE);
 184        if (dev->irq)
 185                free_irq(dev->irq, dev);
 186
 187        return 0;
 188};
 189
 190/* PCMCIA crap */
 191
 192/*
 193   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
 194   you do not define PCMCIA_DEBUG at all, all the debug code will be
 195   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
 196   be present but disabled -- but it can then be enabled for specific
 197   modules at load time with a 'pc_debug=#' option to insmod.
 198*/
 199#ifdef PCMCIA_DEBUG
 200static int pc_debug = PCMCIA_DEBUG;
 201module_param(pc_debug, int, 0644);
 202#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 203static char *version = "ni_daq_dio24.c, based on dummy_cs.c";
 204#else
 205#define DEBUG(n, args...)
 206#endif
 207
 208/*====================================================================*/
 209
 210static void dio24_config(struct pcmcia_device *link);
 211static void dio24_release(struct pcmcia_device *link);
 212static int dio24_cs_suspend(struct pcmcia_device *p_dev);
 213static int dio24_cs_resume(struct pcmcia_device *p_dev);
 214
 215/*
 216   The attach() and detach() entry points are used to create and destroy
 217   "instances" of the driver, where each instance represents everything
 218   needed to manage one actual PCMCIA card.
 219*/
 220
 221static int dio24_cs_attach(struct pcmcia_device *);
 222static void dio24_cs_detach(struct pcmcia_device *);
 223
 224/*
 225   You'll also need to prototype all the functions that will actually
 226   be used to talk to your device.  See 'memory_cs' for a good example
 227   of a fully self-sufficient driver; the other drivers rely more or
 228   less on other parts of the kernel.
 229*/
 230
 231/*
 232   The dev_info variable is the "key" that is used to match up this
 233   device driver with appropriate cards, through the card configuration
 234   database.
 235*/
 236
 237static const dev_info_t dev_info = "ni_daq_dio24";
 238
 239struct local_info_t {
 240        struct pcmcia_device *link;
 241        dev_node_t node;
 242        int stop;
 243        struct bus_operations *bus;
 244};
 245
 246/*======================================================================
 247
 248    dio24_cs_attach() creates an "instance" of the driver, allocating
 249    local data structures for one device.  The device is registered
 250    with Card Services.
 251
 252    The dev_link structure is initialized, but we don't actually
 253    configure the card at this point -- we wait until we receive a
 254    card insertion event.
 255
 256======================================================================*/
 257
 258static int dio24_cs_attach(struct pcmcia_device *link)
 259{
 260        struct local_info_t *local;
 261
 262        printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
 263
 264        DEBUG(0, "dio24_cs_attach()\n");
 265
 266        /* Allocate space for private device-specific data */
 267        local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
 268        if (!local)
 269                return -ENOMEM;
 270        local->link = link;
 271        link->priv = local;
 272
 273        /* Interrupt setup */
 274        link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 275        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 276        link->irq.Handler = NULL;
 277
 278        /*
 279           General socket configuration defaults can go here.  In this
 280           client, we assume very little, and rely on the CIS for almost
 281           everything.  In most clients, many details (i.e., number, sizes,
 282           and attributes of IO windows) are fixed by the nature of the
 283           device, and can be hard-wired here.
 284         */
 285        link->conf.Attributes = 0;
 286        link->conf.IntType = INT_MEMORY_AND_IO;
 287
 288        pcmcia_cur_dev = link;
 289
 290        dio24_config(link);
 291
 292        return 0;
 293}                               /* dio24_cs_attach */
 294
 295/*======================================================================
 296
 297    This deletes a driver "instance".  The device is de-registered
 298    with Card Services.  If it has been released, all local data
 299    structures are freed.  Otherwise, the structures will be freed
 300    when the device is released.
 301
 302======================================================================*/
 303
 304static void dio24_cs_detach(struct pcmcia_device *link)
 305{
 306
 307        printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
 308
 309        DEBUG(0, "dio24_cs_detach(0x%p)\n", link);
 310
 311        if (link->dev_node) {
 312                ((struct local_info_t *)link->priv)->stop = 1;
 313                dio24_release(link);
 314        }
 315
 316        /* This points to the parent local_info_t struct */
 317        if (link->priv)
 318                kfree(link->priv);
 319
 320}                               /* dio24_cs_detach */
 321
 322/*======================================================================
 323
 324    dio24_config() is scheduled to run after a CARD_INSERTION event
 325    is received, to configure the PCMCIA socket, and to make the
 326    device available to the system.
 327
 328======================================================================*/
 329
 330static void dio24_config(struct pcmcia_device *link)
 331{
 332        struct local_info_t *dev = link->priv;
 333        tuple_t tuple;
 334        cisparse_t parse;
 335        int last_ret;
 336        u_char buf[64];
 337        win_req_t req;
 338        memreq_t map;
 339        cistpl_cftable_entry_t dflt = { 0 };
 340
 341        printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
 342
 343        DEBUG(0, "dio24_config(0x%p)\n", link);
 344
 345        /*
 346           This reads the card's CONFIG tuple to find its configuration
 347           registers.
 348         */
 349        tuple.DesiredTuple = CISTPL_CONFIG;
 350        tuple.Attributes = 0;
 351        tuple.TupleData = buf;
 352        tuple.TupleDataMax = sizeof(buf);
 353        tuple.TupleOffset = 0;
 354
 355        last_ret = pcmcia_get_first_tuple(link, &tuple);
 356        if (last_ret) {
 357                cs_error(link, GetFirstTuple, last_ret);
 358                goto cs_failed;
 359        }
 360
 361        last_ret = pcmcia_get_tuple_data(link, &tuple);
 362        if (last_ret) {
 363                cs_error(link, GetTupleData, last_ret);
 364                goto cs_failed;
 365        }
 366
 367        last_ret = pcmcia_parse_tuple(&tuple, &parse);
 368        if (last_ret) {
 369                cs_error(link, ParseTuple, last_ret);
 370                goto cs_failed;
 371        }
 372        link->conf.ConfigBase = parse.config.base;
 373        link->conf.Present = parse.config.rmask[0];
 374
 375        /*
 376           In this loop, we scan the CIS for configuration table entries,
 377           each of which describes a valid card configuration, including
 378           voltage, IO window, memory window, and interrupt settings.
 379
 380           We make no assumptions about the card to be configured: we use
 381           just the information available in the CIS.  In an ideal world,
 382           this would work for any PCMCIA card, but it requires a complete
 383           and accurate CIS.  In practice, a driver usually "knows" most of
 384           these things without consulting the CIS, and most client drivers
 385           will only use the CIS to fill in implementation-defined details.
 386         */
 387        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 388
 389        last_ret = pcmcia_get_first_tuple(link, &tuple);
 390        if (last_ret) {
 391                cs_error(link, GetFirstTuple, last_ret);
 392                goto cs_failed;
 393        }
 394        while (1) {
 395                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 396                if (pcmcia_get_tuple_data(link, &tuple) != 0)
 397                        goto next_entry;
 398                if (pcmcia_parse_tuple(&tuple, &parse) != 0)
 399                        goto next_entry;
 400
 401                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 402                        dflt = *cfg;
 403                if (cfg->index == 0)
 404                        goto next_entry;
 405                link->conf.ConfigIndex = cfg->index;
 406
 407                /* Does this card need audio output? */
 408                if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
 409                        link->conf.Attributes |= CONF_ENABLE_SPKR;
 410                        link->conf.Status = CCSR_AUDIO_ENA;
 411                }
 412
 413                /* Do we need to allocate an interrupt? */
 414                if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
 415                        link->conf.Attributes |= CONF_ENABLE_IRQ;
 416
 417                /* IO window settings */
 418                link->io.NumPorts1 = link->io.NumPorts2 = 0;
 419                if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
 420                        cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
 421                        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
 422                        if (!(io->flags & CISTPL_IO_8BIT))
 423                                link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
 424                        if (!(io->flags & CISTPL_IO_16BIT))
 425                                link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 426                        link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
 427                        link->io.BasePort1 = io->win[0].base;
 428                        link->io.NumPorts1 = io->win[0].len;
 429                        if (io->nwin > 1) {
 430                                link->io.Attributes2 = link->io.Attributes1;
 431                                link->io.BasePort2 = io->win[1].base;
 432                                link->io.NumPorts2 = io->win[1].len;
 433                        }
 434                        /* This reserves IO space but doesn't actually enable it */
 435                        if (pcmcia_request_io(link, &link->io) != 0)
 436                                goto next_entry;
 437                }
 438
 439                if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
 440                        cistpl_mem_t *mem =
 441                            (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
 442                        req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
 443                        req.Attributes |= WIN_ENABLE;
 444                        req.Base = mem->win[0].host_addr;
 445                        req.Size = mem->win[0].len;
 446                        if (req.Size < 0x1000)
 447                                req.Size = 0x1000;
 448                        req.AccessSpeed = 0;
 449                        if (pcmcia_request_window(&link, &req, &link->win))
 450                                goto next_entry;
 451                        map.Page = 0;
 452                        map.CardOffset = mem->win[0].card_addr;
 453                        if (pcmcia_map_mem_page(link->win, &map))
 454                                goto next_entry;
 455                }
 456                /* If we got this far, we're cool! */
 457                break;
 458
 459next_entry:
 460
 461                last_ret = pcmcia_get_next_tuple(link, &tuple);
 462                if (last_ret) {
 463                        cs_error(link, GetNextTuple, last_ret);
 464                        goto cs_failed;
 465                }
 466        }
 467
 468        /*
 469           Allocate an interrupt line.  Note that this does not assign a
 470           handler to the interrupt, unless the 'Handler' member of the
 471           irq structure is initialized.
 472         */
 473        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
 474                last_ret = pcmcia_request_irq(link, &link->irq);
 475                if (last_ret) {
 476                        cs_error(link, RequestIRQ, last_ret);
 477                        goto cs_failed;
 478                }
 479        }
 480
 481        /*
 482           This actually configures the PCMCIA socket -- setting up
 483           the I/O windows and the interrupt mapping, and putting the
 484           card and host interface into "Memory and IO" mode.
 485         */
 486        last_ret = pcmcia_request_configuration(link, &link->conf);
 487        if (last_ret) {
 488                cs_error(link, RequestConfiguration, last_ret);
 489                goto cs_failed;
 490        }
 491
 492        /*
 493           At this point, the dev_node_t structure(s) need to be
 494           initialized and arranged in a linked list at link->dev.
 495         */
 496        sprintf(dev->node.dev_name, "ni_daq_dio24");
 497        dev->node.major = dev->node.minor = 0;
 498        link->dev_node = &dev->node;
 499
 500        /* Finally, report what we've done */
 501        printk(KERN_INFO "%s: index 0x%02x",
 502               dev->node.dev_name, link->conf.ConfigIndex);
 503        if (link->conf.Attributes & CONF_ENABLE_IRQ)
 504                printk(", irq %d", link->irq.AssignedIRQ);
 505        if (link->io.NumPorts1)
 506                printk(", io 0x%04x-0x%04x", link->io.BasePort1,
 507                       link->io.BasePort1 + link->io.NumPorts1 - 1);
 508        if (link->io.NumPorts2)
 509                printk(" & 0x%04x-0x%04x", link->io.BasePort2,
 510                       link->io.BasePort2 + link->io.NumPorts2 - 1);
 511        if (link->win)
 512                printk(", mem 0x%06lx-0x%06lx", req.Base,
 513                       req.Base + req.Size - 1);
 514        printk("\n");
 515
 516        return;
 517
 518cs_failed:
 519        printk(KERN_INFO "Fallo");
 520        dio24_release(link);
 521
 522}                               /* dio24_config */
 523
 524static void dio24_release(struct pcmcia_device *link)
 525{
 526        DEBUG(0, "dio24_release(0x%p)\n", link);
 527
 528        pcmcia_disable_device(link);
 529}                               /* dio24_release */
 530
 531/*======================================================================
 532
 533    The card status event handler.  Mostly, this schedules other
 534    stuff to run after an event is received.
 535
 536    When a CARD_REMOVAL event is received, we immediately set a
 537    private flag to block future accesses to this device.  All the
 538    functions that actually access the device should check this flag
 539    to make sure the card is still present.
 540
 541======================================================================*/
 542
 543static int dio24_cs_suspend(struct pcmcia_device *link)
 544{
 545        struct local_info_t *local = link->priv;
 546
 547        /* Mark the device as stopped, to block IO until later */
 548        local->stop = 1;
 549        return 0;
 550}                               /* dio24_cs_suspend */
 551
 552static int dio24_cs_resume(struct pcmcia_device *link)
 553{
 554        struct local_info_t *local = link->priv;
 555
 556        local->stop = 0;
 557        return 0;
 558}                               /* dio24_cs_resume */
 559
 560/*====================================================================*/
 561
 562static struct pcmcia_device_id dio24_cs_ids[] = {
 563        /* N.B. These IDs should match those in dio24_boards */
 564        PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),        /* daqcard-dio24 */
 565        PCMCIA_DEVICE_NULL
 566};
 567
 568MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
 569
 570struct pcmcia_driver dio24_cs_driver = {
 571        .probe = dio24_cs_attach,
 572        .remove = dio24_cs_detach,
 573        .suspend = dio24_cs_suspend,
 574        .resume = dio24_cs_resume,
 575        .id_table = dio24_cs_ids,
 576        .owner = THIS_MODULE,
 577        .drv = {
 578                .name = dev_info,
 579                },
 580};
 581
 582static int __init init_dio24_cs(void)
 583{
 584        printk("ni_daq_dio24: HOLA SOY YO!\n");
 585        DEBUG(0, "%s\n", version);
 586        pcmcia_register_driver(&dio24_cs_driver);
 587        return 0;
 588}
 589
 590static void __exit exit_dio24_cs(void)
 591{
 592        DEBUG(0, "ni_dio24: unloading\n");
 593        pcmcia_unregister_driver(&dio24_cs_driver);
 594}
 595
 596int __init init_module(void)
 597{
 598        int ret;
 599
 600        ret = init_dio24_cs();
 601        if (ret < 0)
 602                return ret;
 603
 604        return comedi_driver_register(&driver_dio24);
 605}
 606
 607void __exit cleanup_module(void)
 608{
 609        exit_dio24_cs();
 610        comedi_driver_unregister(&driver_dio24);
 611}
 612