linux/drivers/staging/comedi/drivers/ni_tiocmd.c
<<
>>
Prefs
   1/*
   2  comedi/drivers/ni_tiocmd.c
   3  Command support for NI general purpose counters
   4
   5  Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
   6
   7  This program is free software; you can redistribute it and/or modify
   8  it under the terms of the GNU General Public License as published by
   9  the Free Software Foundation; either version 2 of the License, or
  10  (at your option) any later version.
  11
  12  This program is distributed in the hope that it will be useful,
  13  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  GNU General Public License for more details.
  16*/
  17
  18/*
  19Driver: ni_tiocmd
  20Description: National Instruments general purpose counters command support
  21Devices:
  22Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
  23        Herman.Bruyninckx@mech.kuleuven.ac.be,
  24        Wim.Meeussen@mech.kuleuven.ac.be,
  25        Klaas.Gadeyne@mech.kuleuven.ac.be,
  26        Frank Mori Hess <fmhess@users.sourceforge.net>
  27Updated: Fri, 11 Apr 2008 12:32:35 +0100
  28Status: works
  29
  30This module is not used directly by end-users.  Rather, it
  31is used by other drivers (for example ni_660x and ni_pcimio)
  32to provide command support for NI's general purpose counters.
  33It was originally split out of ni_tio.c to stop the 'ni_tio'
  34module depending on the 'mite' module.
  35
  36References:
  37DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
  38DAQ 6601/6602 User Manual (NI 322137B-01)
  39340934b.pdf  DAQ-STC reference manual
  40
  41*/
  42/*
  43TODO:
  44        Support use of both banks X and Y
  45*/
  46
  47#include <linux/module.h>
  48#include "comedi_fc.h"
  49#include "ni_tio_internal.h"
  50#include "mite.h"
  51
  52static void ni_tio_configure_dma(struct ni_gpct *counter,
  53                                 bool enable, bool read)
  54{
  55        struct ni_gpct_device *counter_dev = counter->counter_dev;
  56        unsigned cidx = counter->counter_index;
  57        unsigned mask;
  58        unsigned bits;
  59
  60        mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ;
  61        bits = 0;
  62
  63        if (enable) {
  64                if (read)
  65                        bits |= GI_READ_ACKS_IRQ;
  66                else
  67                        bits |= GI_WRITE_ACKS_IRQ;
  68        }
  69        ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), mask, bits);
  70
  71        switch (counter_dev->variant) {
  72        case ni_gpct_variant_e_series:
  73                break;
  74        case ni_gpct_variant_m_series:
  75        case ni_gpct_variant_660x:
  76                mask = GI_DMA_ENABLE | GI_DMA_INT_ENA | GI_DMA_WRITE;
  77                bits = 0;
  78
  79                if (enable)
  80                        bits |= GI_DMA_ENABLE | GI_DMA_INT_ENA;
  81                if (!read)
  82                        bits |= GI_DMA_WRITE;
  83                ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), mask, bits);
  84                break;
  85        }
  86}
  87
  88static int ni_tio_input_inttrig(struct comedi_device *dev,
  89                                struct comedi_subdevice *s,
  90                                unsigned int trig_num)
  91{
  92        struct ni_gpct *counter = s->private;
  93        struct comedi_cmd *cmd = &s->async->cmd;
  94        unsigned long flags;
  95        int ret = 0;
  96
  97        if (trig_num != cmd->start_src)
  98                return -EINVAL;
  99
 100        spin_lock_irqsave(&counter->lock, flags);
 101        if (counter->mite_chan)
 102                mite_dma_arm(counter->mite_chan);
 103        else
 104                ret = -EIO;
 105        spin_unlock_irqrestore(&counter->lock, flags);
 106        if (ret < 0)
 107                return ret;
 108        ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
 109        s->async->inttrig = NULL;
 110
 111        return ret;
 112}
 113
 114static int ni_tio_input_cmd(struct comedi_subdevice *s)
 115{
 116        struct ni_gpct *counter = s->private;
 117        struct ni_gpct_device *counter_dev = counter->counter_dev;
 118        unsigned cidx = counter->counter_index;
 119        struct comedi_async *async = s->async;
 120        struct comedi_cmd *cmd = &async->cmd;
 121        int ret = 0;
 122
 123        /* write alloc the entire buffer */
 124        comedi_buf_write_alloc(s, async->prealloc_bufsz);
 125        counter->mite_chan->dir = COMEDI_INPUT;
 126        switch (counter_dev->variant) {
 127        case ni_gpct_variant_m_series:
 128        case ni_gpct_variant_660x:
 129                mite_prep_dma(counter->mite_chan, 32, 32);
 130                break;
 131        case ni_gpct_variant_e_series:
 132                mite_prep_dma(counter->mite_chan, 16, 32);
 133                break;
 134        default:
 135                BUG();
 136                break;
 137        }
 138        ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0);
 139        ni_tio_configure_dma(counter, true, true);
 140
 141        if (cmd->start_src == TRIG_INT) {
 142                async->inttrig = &ni_tio_input_inttrig;
 143        } else {        /* TRIG_NOW || TRIG_EXT || TRIG_OTHER */
 144                async->inttrig = NULL;
 145                mite_dma_arm(counter->mite_chan);
 146
 147                if (cmd->start_src == TRIG_NOW)
 148                        ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
 149                else if (cmd->start_src == TRIG_EXT)
 150                        ret = ni_tio_arm(counter, 1, cmd->start_arg);
 151        }
 152        return ret;
 153}
 154
 155static int ni_tio_output_cmd(struct comedi_subdevice *s)
 156{
 157        struct ni_gpct *counter = s->private;
 158
 159        dev_err(counter->counter_dev->dev->class_dev,
 160                "output commands not yet implemented.\n");
 161        return -ENOTSUPP;
 162
 163        counter->mite_chan->dir = COMEDI_OUTPUT;
 164        mite_prep_dma(counter->mite_chan, 32, 32);
 165        ni_tio_configure_dma(counter, true, false);
 166        mite_dma_arm(counter->mite_chan);
 167        return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
 168}
 169
 170static int ni_tio_cmd_setup(struct comedi_subdevice *s)
 171{
 172        struct comedi_cmd *cmd = &s->async->cmd;
 173        struct ni_gpct *counter = s->private;
 174        unsigned cidx = counter->counter_index;
 175        int set_gate_source = 0;
 176        unsigned gate_source;
 177        int retval = 0;
 178
 179        if (cmd->scan_begin_src == TRIG_EXT) {
 180                set_gate_source = 1;
 181                gate_source = cmd->scan_begin_arg;
 182        } else if (cmd->convert_src == TRIG_EXT) {
 183                set_gate_source = 1;
 184                gate_source = cmd->convert_arg;
 185        }
 186        if (set_gate_source)
 187                retval = ni_tio_set_gate_src(counter, 0, gate_source);
 188        if (cmd->flags & TRIG_WAKE_EOS) {
 189                ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
 190                                GI_GATE_INTERRUPT_ENABLE(cidx),
 191                                GI_GATE_INTERRUPT_ENABLE(cidx));
 192        }
 193        return retval;
 194}
 195
 196int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 197{
 198        struct ni_gpct *counter = s->private;
 199        struct comedi_async *async = s->async;
 200        struct comedi_cmd *cmd = &async->cmd;
 201        int retval = 0;
 202        unsigned long flags;
 203
 204        spin_lock_irqsave(&counter->lock, flags);
 205        if (counter->mite_chan == NULL) {
 206                dev_err(counter->counter_dev->dev->class_dev,
 207                        "commands only supported with DMA.  ");
 208                dev_err(counter->counter_dev->dev->class_dev,
 209                        "Interrupt-driven commands not yet implemented.\n");
 210                retval = -EIO;
 211        } else {
 212                retval = ni_tio_cmd_setup(s);
 213                if (retval == 0) {
 214                        if (cmd->flags & CMDF_WRITE)
 215                                retval = ni_tio_output_cmd(s);
 216                        else
 217                                retval = ni_tio_input_cmd(s);
 218                }
 219        }
 220        spin_unlock_irqrestore(&counter->lock, flags);
 221        return retval;
 222}
 223EXPORT_SYMBOL_GPL(ni_tio_cmd);
 224
 225int ni_tio_cmdtest(struct comedi_device *dev,
 226                   struct comedi_subdevice *s,
 227                   struct comedi_cmd *cmd)
 228{
 229        struct ni_gpct *counter = s->private;
 230        int err = 0;
 231        unsigned int sources;
 232
 233        /* Step 1 : check if triggers are trivially valid */
 234
 235        sources = TRIG_NOW | TRIG_INT | TRIG_OTHER;
 236        if (ni_tio_counting_mode_registers_present(counter->counter_dev))
 237                sources |= TRIG_EXT;
 238        err |= cfc_check_trigger_src(&cmd->start_src, sources);
 239
 240        err |= cfc_check_trigger_src(&cmd->scan_begin_src,
 241                                        TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER);
 242        err |= cfc_check_trigger_src(&cmd->convert_src,
 243                                        TRIG_NOW | TRIG_EXT | TRIG_OTHER);
 244        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 245        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 246
 247        if (err)
 248                return 1;
 249
 250        /* Step 2a : make sure trigger sources are unique */
 251
 252        err |= cfc_check_trigger_is_unique(cmd->start_src);
 253        err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
 254        err |= cfc_check_trigger_is_unique(cmd->convert_src);
 255
 256        /* Step 2b : and mutually compatible */
 257
 258        if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW)
 259                err |= -EINVAL;
 260
 261        if (err)
 262                return 2;
 263
 264        /* Step 3: check if arguments are trivially valid */
 265
 266        switch (cmd->start_src) {
 267        case TRIG_NOW:
 268        case TRIG_INT:
 269        case TRIG_OTHER:
 270                err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 271                break;
 272        case TRIG_EXT:
 273                /* start_arg is the start_trigger passed to ni_tio_arm() */
 274                break;
 275        }
 276
 277        if (cmd->scan_begin_src != TRIG_EXT)
 278                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 279
 280        if (cmd->convert_src != TRIG_EXT)
 281                err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 282
 283        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 284        err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 285
 286        if (err)
 287                return 3;
 288
 289        /* step 4: fix up any arguments */
 290
 291        if (err)
 292                return 4;
 293
 294        return 0;
 295}
 296EXPORT_SYMBOL_GPL(ni_tio_cmdtest);
 297
 298int ni_tio_cancel(struct ni_gpct *counter)
 299{
 300        unsigned cidx = counter->counter_index;
 301        unsigned long flags;
 302
 303        ni_tio_arm(counter, 0, 0);
 304        spin_lock_irqsave(&counter->lock, flags);
 305        if (counter->mite_chan)
 306                mite_dma_disarm(counter->mite_chan);
 307        spin_unlock_irqrestore(&counter->lock, flags);
 308        ni_tio_configure_dma(counter, false, false);
 309
 310        ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
 311                        GI_GATE_INTERRUPT_ENABLE(cidx), 0x0);
 312        return 0;
 313}
 314EXPORT_SYMBOL_GPL(ni_tio_cancel);
 315
 316        /* During buffered input counter operation for e-series, the gate
 317           interrupt is acked automatically by the dma controller, due to the
 318           Gi_Read/Write_Acknowledges_IRQ bits in the input select register.  */
 319static int should_ack_gate(struct ni_gpct *counter)
 320{
 321        unsigned long flags;
 322        int retval = 0;
 323
 324        switch (counter->counter_dev->variant) {
 325        case ni_gpct_variant_m_series:
 326        /*  not sure if 660x really supports gate
 327            interrupts (the bits are not listed
 328            in register-level manual) */
 329        case ni_gpct_variant_660x:
 330                return 1;
 331        case ni_gpct_variant_e_series:
 332                spin_lock_irqsave(&counter->lock, flags);
 333                {
 334                        if (counter->mite_chan == NULL ||
 335                            counter->mite_chan->dir != COMEDI_INPUT ||
 336                            (mite_done(counter->mite_chan))) {
 337                                retval = 1;
 338                        }
 339                }
 340                spin_unlock_irqrestore(&counter->lock, flags);
 341                break;
 342        }
 343        return retval;
 344}
 345
 346static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
 347                                           int *gate_error,
 348                                           int *tc_error,
 349                                           int *perm_stale_data,
 350                                           int *stale_data)
 351{
 352        unsigned cidx = counter->counter_index;
 353        const unsigned short gxx_status = read_register(counter,
 354                                                NITIO_SHARED_STATUS_REG(cidx));
 355        const unsigned short gi_status = read_register(counter,
 356                                                NITIO_STATUS_REG(cidx));
 357        unsigned ack = 0;
 358
 359        if (gate_error)
 360                *gate_error = 0;
 361        if (tc_error)
 362                *tc_error = 0;
 363        if (perm_stale_data)
 364                *perm_stale_data = 0;
 365        if (stale_data)
 366                *stale_data = 0;
 367
 368        if (gxx_status & GI_GATE_ERROR(cidx)) {
 369                ack |= GI_GATE_ERROR_CONFIRM(cidx);
 370                if (gate_error) {
 371                        /*660x don't support automatic acknowledgement
 372                          of gate interrupt via dma read/write
 373                           and report bogus gate errors */
 374                        if (counter->counter_dev->variant !=
 375                            ni_gpct_variant_660x) {
 376                                *gate_error = 1;
 377                        }
 378                }
 379        }
 380        if (gxx_status & GI_TC_ERROR(cidx)) {
 381                ack |= GI_TC_ERROR_CONFIRM(cidx);
 382                if (tc_error)
 383                        *tc_error = 1;
 384        }
 385        if (gi_status & GI_TC)
 386                ack |= GI_TC_INTERRUPT_ACK;
 387        if (gi_status & GI_GATE_INTERRUPT) {
 388                if (should_ack_gate(counter))
 389                        ack |= GI_GATE_INTERRUPT_ACK;
 390        }
 391        if (ack)
 392                write_register(counter, ack, NITIO_INT_ACK_REG(cidx));
 393        if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) &
 394            GI_LOADING_ON_GATE) {
 395                if (gxx_status & GI_STALE_DATA(cidx)) {
 396                        if (stale_data)
 397                                *stale_data = 1;
 398                }
 399                if (read_register(counter, NITIO_STATUS2_REG(cidx)) &
 400                    GI_PERMANENT_STALE(cidx)) {
 401                        dev_info(counter->counter_dev->dev->class_dev,
 402                                 "%s: Gi_Permanent_Stale_Data detected.\n",
 403                                 __func__);
 404                        if (perm_stale_data)
 405                                *perm_stale_data = 1;
 406                }
 407        }
 408}
 409
 410void ni_tio_acknowledge(struct ni_gpct *counter)
 411{
 412        ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
 413}
 414EXPORT_SYMBOL_GPL(ni_tio_acknowledge);
 415
 416void ni_tio_handle_interrupt(struct ni_gpct *counter,
 417                             struct comedi_subdevice *s)
 418{
 419        unsigned cidx = counter->counter_index;
 420        unsigned gpct_mite_status;
 421        unsigned long flags;
 422        int gate_error;
 423        int tc_error;
 424        int perm_stale_data;
 425
 426        ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error,
 427                                       &perm_stale_data, NULL);
 428        if (gate_error) {
 429                dev_notice(counter->counter_dev->dev->class_dev,
 430                           "%s: Gi_Gate_Error detected.\n", __func__);
 431                s->async->events |= COMEDI_CB_OVERFLOW;
 432        }
 433        if (perm_stale_data)
 434                s->async->events |= COMEDI_CB_ERROR;
 435        switch (counter->counter_dev->variant) {
 436        case ni_gpct_variant_m_series:
 437        case ni_gpct_variant_660x:
 438                if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) &
 439                    GI_DRQ_ERROR) {
 440                        dev_notice(counter->counter_dev->dev->class_dev,
 441                                   "%s: Gi_DRQ_Error detected.\n", __func__);
 442                        s->async->events |= COMEDI_CB_OVERFLOW;
 443                }
 444                break;
 445        case ni_gpct_variant_e_series:
 446                break;
 447        }
 448        spin_lock_irqsave(&counter->lock, flags);
 449        if (counter->mite_chan == NULL) {
 450                spin_unlock_irqrestore(&counter->lock, flags);
 451                return;
 452        }
 453        gpct_mite_status = mite_get_status(counter->mite_chan);
 454        if (gpct_mite_status & CHSR_LINKC) {
 455                writel(CHOR_CLRLC,
 456                       counter->mite_chan->mite->mite_io_addr +
 457                       MITE_CHOR(counter->mite_chan->channel));
 458        }
 459        mite_sync_input_dma(counter->mite_chan, s);
 460        spin_unlock_irqrestore(&counter->lock, flags);
 461}
 462EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt);
 463
 464void ni_tio_set_mite_channel(struct ni_gpct *counter,
 465                             struct mite_channel *mite_chan)
 466{
 467        unsigned long flags;
 468
 469        spin_lock_irqsave(&counter->lock, flags);
 470        counter->mite_chan = mite_chan;
 471        spin_unlock_irqrestore(&counter->lock, flags);
 472}
 473EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel);
 474
 475static int __init ni_tiocmd_init_module(void)
 476{
 477        return 0;
 478}
 479module_init(ni_tiocmd_init_module);
 480
 481static void __exit ni_tiocmd_cleanup_module(void)
 482{
 483}
 484module_exit(ni_tiocmd_cleanup_module);
 485
 486MODULE_AUTHOR("Comedi <comedi@comedi.org>");
 487MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters");
 488MODULE_LICENSE("GPL");
 489