ni_tiocmd.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
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 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22/* 23Driver: ni_tiocmd 24Description: National Instruments general purpose counters command support 25Devices: 26Author: J.P. Mellor <jpmellor@rose-hulman.edu>, 27 Herman.Bruyninckx@mech.kuleuven.ac.be, 28 Wim.Meeussen@mech.kuleuven.ac.be, 29 Klaas.Gadeyne@mech.kuleuven.ac.be, 30 Frank Mori Hess <fmhess@users.sourceforge.net> 31Updated: Fri, 11 Apr 2008 12:32:35 +0100 32Status: works 33 34This module is not used directly by end-users. Rather, it 35is used by other drivers (for example ni_660x and ni_pcimio) 36to provide command support for NI's general purpose counters. 37It was originally split out of ni_tio.c to stop the 'ni_tio' 38module depending on the 'mite' module. 39 40References: 41DAQ 660x Register-Level Programmer Manual (NI 370505A-01) 42DAQ 6601/6602 User Manual (NI 322137B-01) 43340934b.pdf DAQ-STC reference manual 44 45*/ 46/* 47TODO: 48 Support use of both banks X and Y 49*/ 50 51#include "ni_tio_internal.h" 52#include "mite.h" 53 54MODULE_AUTHOR("Comedi <comedi@comedi.org>"); 55MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters"); 56MODULE_LICENSE("GPL"); 57 58static void ni_tio_configure_dma(struct ni_gpct *counter, short enable, 59 short read_not_write) 60{ 61 struct ni_gpct_device *counter_dev = counter->counter_dev; 62 unsigned input_select_bits = 0; 63 64 if (enable) { 65 if (read_not_write) { 66 input_select_bits |= Gi_Read_Acknowledges_Irq; 67 } else { 68 input_select_bits |= Gi_Write_Acknowledges_Irq; 69 } 70 } 71 ni_tio_set_bits(counter, 72 NITIO_Gi_Input_Select_Reg(counter->counter_index), 73 Gi_Read_Acknowledges_Irq | Gi_Write_Acknowledges_Irq, 74 input_select_bits); 75 switch (counter_dev->variant) { 76 case ni_gpct_variant_e_series: 77 break; 78 case ni_gpct_variant_m_series: 79 case ni_gpct_variant_660x: 80 { 81 unsigned gi_dma_config_bits = 0; 82 83 if (enable) { 84 gi_dma_config_bits |= Gi_DMA_Enable_Bit; 85 gi_dma_config_bits |= Gi_DMA_Int_Bit; 86 } 87 if (read_not_write == 0) { 88 gi_dma_config_bits |= Gi_DMA_Write_Bit; 89 } 90 ni_tio_set_bits(counter, 91 NITIO_Gi_DMA_Config_Reg(counter->counter_index), 92 Gi_DMA_Enable_Bit | Gi_DMA_Int_Bit | 93 Gi_DMA_Write_Bit, gi_dma_config_bits); 94 } 95 break; 96 } 97} 98 99static int ni_tio_input_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, 100 unsigned int trignum) 101{ 102 unsigned long flags; 103 int retval = 0; 104 struct ni_gpct *counter = s->private; 105 106 BUG_ON(counter == NULL); 107 if (trignum != 0) 108 return -EINVAL; 109 110 comedi_spin_lock_irqsave(&counter->lock, flags); 111 if (counter->mite_chan) 112 mite_dma_arm(counter->mite_chan); 113 else 114 retval = -EIO; 115 comedi_spin_unlock_irqrestore(&counter->lock, flags); 116 if (retval < 0) 117 return retval; 118 retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); 119 s->async->inttrig = NULL; 120 121 return retval; 122} 123 124static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async) 125{ 126 struct ni_gpct_device *counter_dev = counter->counter_dev; 127 struct comedi_cmd *cmd = &async->cmd; 128 int retval = 0; 129 130 /* write alloc the entire buffer */ 131 comedi_buf_write_alloc(async, async->prealloc_bufsz); 132 counter->mite_chan->dir = COMEDI_INPUT; 133 switch (counter_dev->variant) { 134 case ni_gpct_variant_m_series: 135 case ni_gpct_variant_660x: 136 mite_prep_dma(counter->mite_chan, 32, 32); 137 break; 138 case ni_gpct_variant_e_series: 139 mite_prep_dma(counter->mite_chan, 16, 32); 140 break; 141 default: 142 BUG(); 143 break; 144 } 145 ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), 146 Gi_Save_Trace_Bit, 0); 147 ni_tio_configure_dma(counter, 1, 1); 148 switch (cmd->start_src) { 149 case TRIG_NOW: 150 async->inttrig = NULL; 151 mite_dma_arm(counter->mite_chan); 152 retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); 153 break; 154 case TRIG_INT: 155 async->inttrig = &ni_tio_input_inttrig; 156 break; 157 case TRIG_EXT: 158 async->inttrig = NULL; 159 mite_dma_arm(counter->mite_chan); 160 retval = ni_tio_arm(counter, 1, cmd->start_arg); 161 case TRIG_OTHER: 162 async->inttrig = NULL; 163 mite_dma_arm(counter->mite_chan); 164 break; 165 default: 166 BUG(); 167 break; 168 } 169 return retval; 170} 171 172static int ni_tio_output_cmd(struct ni_gpct *counter, struct comedi_async *async) 173{ 174 rt_printk("ni_tio: output commands not yet implemented.\n"); 175 return -ENOTSUPP; 176 177 counter->mite_chan->dir = COMEDI_OUTPUT; 178 mite_prep_dma(counter->mite_chan, 32, 32); 179 ni_tio_configure_dma(counter, 1, 0); 180 mite_dma_arm(counter->mite_chan); 181 return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); 182} 183 184static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async) 185{ 186 struct comedi_cmd *cmd = &async->cmd; 187 int set_gate_source = 0; 188 unsigned gate_source; 189 int retval = 0; 190 191 if (cmd->scan_begin_src == TRIG_EXT) { 192 set_gate_source = 1; 193 gate_source = cmd->scan_begin_arg; 194 } else if (cmd->convert_src == TRIG_EXT) { 195 set_gate_source = 1; 196 gate_source = cmd->convert_arg; 197 } 198 if (set_gate_source) { 199 retval = ni_tio_set_gate_src(counter, 0, gate_source); 200 } 201 if (cmd->flags & TRIG_WAKE_EOS) { 202 ni_tio_set_bits(counter, 203 NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), 204 Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 205 Gi_Gate_Interrupt_Enable_Bit(counter->counter_index)); 206 } 207 return retval; 208} 209 210int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async) 211{ 212 struct comedi_cmd *cmd = &async->cmd; 213 int retval = 0; 214 unsigned long flags; 215 216 comedi_spin_lock_irqsave(&counter->lock, flags); 217 if (counter->mite_chan == NULL) { 218 rt_printk 219 ("ni_tio: commands only supported with DMA. Interrupt-driven commands not yet implemented.\n"); 220 retval = -EIO; 221 } else { 222 retval = ni_tio_cmd_setup(counter, async); 223 if (retval == 0) { 224 if (cmd->flags & CMDF_WRITE) { 225 retval = ni_tio_output_cmd(counter, async); 226 } else { 227 retval = ni_tio_input_cmd(counter, async); 228 } 229 } 230 } 231 comedi_spin_unlock_irqrestore(&counter->lock, flags); 232 return retval; 233} 234 235int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd) 236{ 237 int err = 0; 238 int tmp; 239 int sources; 240 241 /* step 1: make sure trigger sources are trivially valid */ 242 243 tmp = cmd->start_src; 244 sources = TRIG_NOW | TRIG_INT | TRIG_OTHER; 245 if (ni_tio_counting_mode_registers_present(counter->counter_dev)) 246 sources |= TRIG_EXT; 247 cmd->start_src &= sources; 248 if (!cmd->start_src || tmp != cmd->start_src) 249 err++; 250 251 tmp = cmd->scan_begin_src; 252 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER; 253 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 254 err++; 255 256 tmp = cmd->convert_src; 257 sources = TRIG_NOW | TRIG_EXT | TRIG_OTHER; 258 cmd->convert_src &= sources; 259 if (!cmd->convert_src || tmp != cmd->convert_src) 260 err++; 261 262 tmp = cmd->scan_end_src; 263 cmd->scan_end_src &= TRIG_COUNT; 264 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 265 err++; 266 267 tmp = cmd->stop_src; 268 cmd->stop_src &= TRIG_NONE; 269 if (!cmd->stop_src || tmp != cmd->stop_src) 270 err++; 271 272 if (err) 273 return 1; 274 275 /* step 2: make sure trigger sources are unique... */ 276 277 if (cmd->start_src != TRIG_NOW && 278 cmd->start_src != TRIG_INT && 279 cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_OTHER) 280 err++; 281 if (cmd->scan_begin_src != TRIG_FOLLOW && 282 cmd->scan_begin_src != TRIG_EXT && 283 cmd->scan_begin_src != TRIG_OTHER) 284 err++; 285 if (cmd->convert_src != TRIG_OTHER && 286 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) 287 err++; 288 if (cmd->stop_src != TRIG_NONE) 289 err++; 290 /* ... and mutually compatible */ 291 if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW) 292 err++; 293 294 if (err) 295 return 2; 296 297 /* step 3: make sure arguments are trivially compatible */ 298 if (cmd->start_src != TRIG_EXT) { 299 if (cmd->start_arg != 0) { 300 cmd->start_arg = 0; 301 err++; 302 } 303 } 304 if (cmd->scan_begin_src != TRIG_EXT) { 305 if (cmd->scan_begin_arg) { 306 cmd->scan_begin_arg = 0; 307 err++; 308 } 309 } 310 if (cmd->convert_src != TRIG_EXT) { 311 if (cmd->convert_arg) { 312 cmd->convert_arg = 0; 313 err++; 314 } 315 } 316 317 if (cmd->scan_end_arg != cmd->chanlist_len) { 318 cmd->scan_end_arg = cmd->chanlist_len; 319 err++; 320 } 321 322 if (cmd->stop_src == TRIG_NONE) { 323 if (cmd->stop_arg != 0) { 324 cmd->stop_arg = 0; 325 err++; 326 } 327 } 328 329 if (err) 330 return 3; 331 332 /* step 4: fix up any arguments */ 333 334 if (err) 335 return 4; 336 337 return 0; 338} 339 340int ni_tio_cancel(struct ni_gpct *counter) 341{ 342 unsigned long flags; 343 344 ni_tio_arm(counter, 0, 0); 345 comedi_spin_lock_irqsave(&counter->lock, flags); 346 if (counter->mite_chan) { 347 mite_dma_disarm(counter->mite_chan); 348 } 349 comedi_spin_unlock_irqrestore(&counter->lock, flags); 350 ni_tio_configure_dma(counter, 0, 0); 351 352 ni_tio_set_bits(counter, 353 NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), 354 Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 0x0); 355 return 0; 356} 357 358 /* During buffered input counter operation for e-series, the gate interrupt is acked 359 automatically by the dma controller, due to the Gi_Read/Write_Acknowledges_IRQ bits 360 in the input select register. */ 361static int should_ack_gate(struct ni_gpct *counter) 362{ 363 unsigned long flags; 364 int retval = 0; 365 366 switch (counter->counter_dev->variant) { 367 case ni_gpct_variant_m_series: 368 case ni_gpct_variant_660x: /* not sure if 660x really supports gate interrupts (the bits are not listed in register-level manual) */ 369 return 1; 370 break; 371 case ni_gpct_variant_e_series: 372 comedi_spin_lock_irqsave(&counter->lock, flags); 373 { 374 if (counter->mite_chan == NULL || 375 counter->mite_chan->dir != COMEDI_INPUT || 376 (mite_done(counter->mite_chan))) { 377 retval = 1; 378 } 379 } 380 comedi_spin_unlock_irqrestore(&counter->lock, flags); 381 break; 382 } 383 return retval; 384} 385 386void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, 387 int *tc_error, int *perm_stale_data, int *stale_data) 388{ 389 const unsigned short gxx_status = read_register(counter, 390 NITIO_Gxx_Status_Reg(counter->counter_index)); 391 const unsigned short gi_status = read_register(counter, 392 NITIO_Gi_Status_Reg(counter->counter_index)); 393 unsigned ack = 0; 394 395 if (gate_error) 396 *gate_error = 0; 397 if (tc_error) 398 *tc_error = 0; 399 if (perm_stale_data) 400 *perm_stale_data = 0; 401 if (stale_data) 402 *stale_data = 0; 403 404 if (gxx_status & Gi_Gate_Error_Bit(counter->counter_index)) { 405 ack |= Gi_Gate_Error_Confirm_Bit(counter->counter_index); 406 if (gate_error) { 407 /*660x don't support automatic acknowledgement of gate interrupt via dma read/write 408 and report bogus gate errors */ 409 if (counter->counter_dev->variant != 410 ni_gpct_variant_660x) { 411 *gate_error = 1; 412 } 413 } 414 } 415 if (gxx_status & Gi_TC_Error_Bit(counter->counter_index)) { 416 ack |= Gi_TC_Error_Confirm_Bit(counter->counter_index); 417 if (tc_error) 418 *tc_error = 1; 419 } 420 if (gi_status & Gi_TC_Bit) { 421 ack |= Gi_TC_Interrupt_Ack_Bit; 422 } 423 if (gi_status & Gi_Gate_Interrupt_Bit) { 424 if (should_ack_gate(counter)) 425 ack |= Gi_Gate_Interrupt_Ack_Bit; 426 } 427 if (ack) 428 write_register(counter, ack, 429 NITIO_Gi_Interrupt_Acknowledge_Reg(counter-> 430 counter_index)); 431 if (ni_tio_get_soft_copy(counter, 432 NITIO_Gi_Mode_Reg(counter-> 433 counter_index)) & Gi_Loading_On_Gate_Bit) { 434 if (gxx_status & Gi_Stale_Data_Bit(counter->counter_index)) { 435 if (stale_data) 436 *stale_data = 1; 437 } 438 if (read_register(counter, 439 NITIO_Gxx_Joint_Status2_Reg(counter-> 440 counter_index)) & 441 Gi_Permanent_Stale_Bit(counter->counter_index)) { 442 rt_printk("%s: Gi_Permanent_Stale_Data detected.\n", 443 __FUNCTION__); 444 if (perm_stale_data) 445 *perm_stale_data = 1; 446 } 447 } 448} 449 450void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice * s) 451{ 452 unsigned gpct_mite_status; 453 unsigned long flags; 454 int gate_error; 455 int tc_error; 456 int perm_stale_data; 457 458 ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error, 459 &perm_stale_data, NULL); 460 if (gate_error) { 461 rt_printk("%s: Gi_Gate_Error detected.\n", __FUNCTION__); 462 s->async->events |= COMEDI_CB_OVERFLOW; 463 } 464 if (perm_stale_data) { 465 s->async->events |= COMEDI_CB_ERROR; 466 } 467 switch (counter->counter_dev->variant) { 468 case ni_gpct_variant_m_series: 469 case ni_gpct_variant_660x: 470 if (read_register(counter, 471 NITIO_Gi_DMA_Status_Reg(counter-> 472 counter_index)) & Gi_DRQ_Error_Bit) { 473 rt_printk("%s: Gi_DRQ_Error detected.\n", __FUNCTION__); 474 s->async->events |= COMEDI_CB_OVERFLOW; 475 } 476 break; 477 case ni_gpct_variant_e_series: 478 break; 479 } 480 comedi_spin_lock_irqsave(&counter->lock, flags); 481 if (counter->mite_chan == NULL) { 482 comedi_spin_unlock_irqrestore(&counter->lock, flags); 483 return; 484 } 485 gpct_mite_status = mite_get_status(counter->mite_chan); 486 if (gpct_mite_status & CHSR_LINKC) { 487 writel(CHOR_CLRLC, 488 counter->mite_chan->mite->mite_io_addr + 489 MITE_CHOR(counter->mite_chan->channel)); 490 } 491 mite_sync_input_dma(counter->mite_chan, s->async); 492 comedi_spin_unlock_irqrestore(&counter->lock, flags); 493} 494 495void ni_tio_set_mite_channel(struct ni_gpct *counter, 496 struct mite_channel *mite_chan) 497{ 498 unsigned long flags; 499 500 comedi_spin_lock_irqsave(&counter->lock, flags); 501 counter->mite_chan = mite_chan; 502 comedi_spin_unlock_irqrestore(&counter->lock, flags); 503} 504 505static int __init ni_tiocmd_init_module(void) 506{ 507 return 0; 508} 509 510module_init(ni_tiocmd_init_module); 511 512static void __exit ni_tiocmd_cleanup_module(void) 513{ 514} 515 516module_exit(ni_tiocmd_cleanup_module); 517 518EXPORT_SYMBOL_GPL(ni_tio_cmd); 519EXPORT_SYMBOL_GPL(ni_tio_cmdtest); 520EXPORT_SYMBOL_GPL(ni_tio_cancel); 521EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt); 522EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel); 523EXPORT_SYMBOL_GPL(ni_tio_acknowledge_and_confirm); 524