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 & CMDF_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 /* Step 5: check channel list if it exists */ 292 293 return 0; 294} 295EXPORT_SYMBOL_GPL(ni_tio_cmdtest); 296 297int ni_tio_cancel(struct ni_gpct *counter) 298{ 299 unsigned cidx = counter->counter_index; 300 unsigned long flags; 301 302 ni_tio_arm(counter, 0, 0); 303 spin_lock_irqsave(&counter->lock, flags); 304 if (counter->mite_chan) 305 mite_dma_disarm(counter->mite_chan); 306 spin_unlock_irqrestore(&counter->lock, flags); 307 ni_tio_configure_dma(counter, false, false); 308 309 ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), 310 GI_GATE_INTERRUPT_ENABLE(cidx), 0x0); 311 return 0; 312} 313EXPORT_SYMBOL_GPL(ni_tio_cancel); 314 315 /* During buffered input counter operation for e-series, the gate 316 interrupt is acked automatically by the dma controller, due to the 317 Gi_Read/Write_Acknowledges_IRQ bits in the input select register. */ 318static int should_ack_gate(struct ni_gpct *counter) 319{ 320 unsigned long flags; 321 int retval = 0; 322 323 switch (counter->counter_dev->variant) { 324 case ni_gpct_variant_m_series: 325 /* not sure if 660x really supports gate 326 interrupts (the bits are not listed 327 in register-level manual) */ 328 case ni_gpct_variant_660x: 329 return 1; 330 case ni_gpct_variant_e_series: 331 spin_lock_irqsave(&counter->lock, flags); 332 { 333 if (counter->mite_chan == NULL || 334 counter->mite_chan->dir != COMEDI_INPUT || 335 (mite_done(counter->mite_chan))) { 336 retval = 1; 337 } 338 } 339 spin_unlock_irqrestore(&counter->lock, flags); 340 break; 341 } 342 return retval; 343} 344 345static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, 346 int *gate_error, 347 int *tc_error, 348 int *perm_stale_data, 349 int *stale_data) 350{ 351 unsigned cidx = counter->counter_index; 352 const unsigned short gxx_status = read_register(counter, 353 NITIO_SHARED_STATUS_REG(cidx)); 354 const unsigned short gi_status = read_register(counter, 355 NITIO_STATUS_REG(cidx)); 356 unsigned ack = 0; 357 358 if (gate_error) 359 *gate_error = 0; 360 if (tc_error) 361 *tc_error = 0; 362 if (perm_stale_data) 363 *perm_stale_data = 0; 364 if (stale_data) 365 *stale_data = 0; 366 367 if (gxx_status & GI_GATE_ERROR(cidx)) { 368 ack |= GI_GATE_ERROR_CONFIRM(cidx); 369 if (gate_error) { 370 /*660x don't support automatic acknowledgement 371 of gate interrupt via dma read/write 372 and report bogus gate errors */ 373 if (counter->counter_dev->variant != 374 ni_gpct_variant_660x) { 375 *gate_error = 1; 376 } 377 } 378 } 379 if (gxx_status & GI_TC_ERROR(cidx)) { 380 ack |= GI_TC_ERROR_CONFIRM(cidx); 381 if (tc_error) 382 *tc_error = 1; 383 } 384 if (gi_status & GI_TC) 385 ack |= GI_TC_INTERRUPT_ACK; 386 if (gi_status & GI_GATE_INTERRUPT) { 387 if (should_ack_gate(counter)) 388 ack |= GI_GATE_INTERRUPT_ACK; 389 } 390 if (ack) 391 write_register(counter, ack, NITIO_INT_ACK_REG(cidx)); 392 if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) & 393 GI_LOADING_ON_GATE) { 394 if (gxx_status & GI_STALE_DATA(cidx)) { 395 if (stale_data) 396 *stale_data = 1; 397 } 398 if (read_register(counter, NITIO_STATUS2_REG(cidx)) & 399 GI_PERMANENT_STALE(cidx)) { 400 dev_info(counter->counter_dev->dev->class_dev, 401 "%s: Gi_Permanent_Stale_Data detected.\n", 402 __func__); 403 if (perm_stale_data) 404 *perm_stale_data = 1; 405 } 406 } 407} 408 409void ni_tio_acknowledge(struct ni_gpct *counter) 410{ 411 ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); 412} 413EXPORT_SYMBOL_GPL(ni_tio_acknowledge); 414 415void ni_tio_handle_interrupt(struct ni_gpct *counter, 416 struct comedi_subdevice *s) 417{ 418 unsigned cidx = counter->counter_index; 419 unsigned gpct_mite_status; 420 unsigned long flags; 421 int gate_error; 422 int tc_error; 423 int perm_stale_data; 424 425 ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error, 426 &perm_stale_data, NULL); 427 if (gate_error) { 428 dev_notice(counter->counter_dev->dev->class_dev, 429 "%s: Gi_Gate_Error detected.\n", __func__); 430 s->async->events |= COMEDI_CB_OVERFLOW; 431 } 432 if (perm_stale_data) 433 s->async->events |= COMEDI_CB_ERROR; 434 switch (counter->counter_dev->variant) { 435 case ni_gpct_variant_m_series: 436 case ni_gpct_variant_660x: 437 if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) & 438 GI_DRQ_ERROR) { 439 dev_notice(counter->counter_dev->dev->class_dev, 440 "%s: Gi_DRQ_Error detected.\n", __func__); 441 s->async->events |= COMEDI_CB_OVERFLOW; 442 } 443 break; 444 case ni_gpct_variant_e_series: 445 break; 446 } 447 spin_lock_irqsave(&counter->lock, flags); 448 if (counter->mite_chan == NULL) { 449 spin_unlock_irqrestore(&counter->lock, flags); 450 return; 451 } 452 gpct_mite_status = mite_get_status(counter->mite_chan); 453 if (gpct_mite_status & CHSR_LINKC) { 454 writel(CHOR_CLRLC, 455 counter->mite_chan->mite->mite_io_addr + 456 MITE_CHOR(counter->mite_chan->channel)); 457 } 458 mite_sync_input_dma(counter->mite_chan, s); 459 spin_unlock_irqrestore(&counter->lock, flags); 460} 461EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt); 462 463void ni_tio_set_mite_channel(struct ni_gpct *counter, 464 struct mite_channel *mite_chan) 465{ 466 unsigned long flags; 467 468 spin_lock_irqsave(&counter->lock, flags); 469 counter->mite_chan = mite_chan; 470 spin_unlock_irqrestore(&counter->lock, flags); 471} 472EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel); 473 474static int __init ni_tiocmd_init_module(void) 475{ 476 return 0; 477} 478module_init(ni_tiocmd_init_module); 479 480static void __exit ni_tiocmd_cleanup_module(void) 481{ 482} 483module_exit(ni_tiocmd_cleanup_module); 484 485MODULE_AUTHOR("Comedi <comedi@comedi.org>"); 486MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters"); 487MODULE_LICENSE("GPL"); 488