1/** 2@verbatim 3 4Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. 5 6 ADDI-DATA GmbH 7 Dieselstrasse 3 8 D-77833 Ottersweier 9 Tel: +19(0)7223/9493-0 10 Fax: +49(0)7223/9493-92 11 http://www.addi-data.com 12 info@addi-data.com 13 14This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 15 16This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 18@endverbatim 19*/ 20/* 21 +-----------------------------------------------------------------------+ 22 | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | 23 +-----------------------------------------------------------------------+ 24 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | 25 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | 26 +-----------------------------------------------------------------------+ 27 | Project : APCI-3120 | Compiler : GCC | 28 | Module name : hwdrv_apci3120.c| Version : 2.96 | 29 +-------------------------------+---------------------------------------+ 30 | Project manager: Eric Stolz | Date : 02/12/2002 | 31 +-----------------------------------------------------------------------+ 32 | Description :APCI3120 Module. Hardware abstraction Layer for APCI3120| 33 +-----------------------------------------------------------------------+ 34 | UPDATE'S | 35 +-----------------------------------------------------------------------+ 36 | Date | Author | Description of updates | 37 +----------+-----------+------------------------------------------------+ 38 | | | | 39 | | | | 40 +----------+-----------+------------------------------------------------+ 41*/ 42 43#include <linux/delay.h> 44 45/* 46 * ADDON RELATED ADDITIONS 47 */ 48/* Constant */ 49#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 50#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 51#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L 52#define APCI3120_AMWEN_ENABLE 0x02 53#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 54#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L 55#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L 56#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L 57#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 58#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 59#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 60 61/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */ 62#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C 63#define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2) 64#define APCI3120_ADD_ON_MWAR_LOW 0x24 65#define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2) 66#define APCI3120_ADD_ON_MWTC_LOW 0x058 67#define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2) 68 69/* AMCC */ 70#define APCI3120_AMCC_OP_MCSR 0x3C 71#define APCI3120_AMCC_OP_REG_INTCSR 0x38 72 73/* for transfer count enable bit */ 74#define AGCSTS_TC_ENABLE 0x10000000 75 76/* used for test on mixture of BIP/UNI ranges */ 77#define APCI3120_BIPOLAR_RANGES 4 78 79#define APCI3120_ADDRESS_RANGE 16 80 81#define APCI3120_DISABLE 0 82#define APCI3120_ENABLE 1 83 84#define APCI3120_START 1 85#define APCI3120_STOP 0 86 87#define APCI3120_EOC_MODE 1 88#define APCI3120_EOS_MODE 2 89#define APCI3120_DMA_MODE 3 90 91/* DIGITAL INPUT-OUTPUT DEFINE */ 92 93#define APCI3120_DIGITAL_OUTPUT 0x0d 94#define APCI3120_RD_STATUS 0x02 95#define APCI3120_RD_FIFO 0x00 96 97/* digital output insn_write ON /OFF selection */ 98#define APCI3120_SET4DIGITALOUTPUTON 1 99#define APCI3120_SET4DIGITALOUTPUTOFF 0 100 101/* analog output SELECT BIT */ 102#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000 103#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000 104#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000 105#define APCI3120_ANALOG_OP_CHANNEL_4 0xc000 106#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000 107#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000 108#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000 109#define APCI3120_ANALOG_OP_CHANNEL_8 0xc000 110 111/* Enable external trigger bit in nWrAddress */ 112#define APCI3120_ENABLE_EXT_TRIGGER 0x8000 113 114/* ANALOG OUTPUT AND INPUT DEFINE */ 115#define APCI3120_UNIPOLAR 0x80 116#define APCI3120_BIPOLAR 0x00 117#define APCI3120_ANALOG_OUTPUT_1 0x08 118#define APCI3120_ANALOG_OUTPUT_2 0x0a 119#define APCI3120_1_GAIN 0x00 120#define APCI3120_2_GAIN 0x10 121#define APCI3120_5_GAIN 0x20 122#define APCI3120_10_GAIN 0x30 123#define APCI3120_SEQ_RAM_ADDRESS 0x06 124#define APCI3120_RESET_FIFO 0x0c 125#define APCI3120_TIMER_0_MODE_2 0x01 126#define APCI3120_TIMER_0_MODE_4 0x2 127#define APCI3120_SELECT_TIMER_0_WORD 0x00 128#define APCI3120_ENABLE_TIMER0 0x1000 129#define APCI3120_CLEAR_PR 0xf0ff 130#define APCI3120_CLEAR_PA 0xfff0 131#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA) 132 133/* nWrMode_Select */ 134#define APCI3120_ENABLE_SCAN 0x8 135#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN) 136#define APCI3120_ENABLE_EOS_INT 0x2 137 138#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT) 139#define APCI3120_ENABLE_EOC_INT 0x1 140#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT) 141#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER \ 142 (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) 143#define APCI3120_DISABLE_ALL_INTERRUPT \ 144 (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) 145 146/* status register bits */ 147#define APCI3120_EOC 0x8000 148#define APCI3120_EOS 0x2000 149 150/* software trigger dummy register */ 151#define APCI3120_START_CONVERSION 0x02 152 153/* TIMER DEFINE */ 154#define APCI3120_QUARTZ_A 70 155#define APCI3120_QUARTZ_B 50 156#define APCI3120_TIMER 1 157#define APCI3120_WATCHDOG 2 158#define APCI3120_TIMER_DISABLE 0 159#define APCI3120_TIMER_ENABLE 1 160#define APCI3120_ENABLE_TIMER2 0x4000 161#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) 162#define APCI3120_ENABLE_TIMER_INT 0x04 163#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT) 164#define APCI3120_WRITE_MODE_SELECT 0x0e 165#define APCI3120_SELECT_TIMER_0_WORD 0x00 166#define APCI3120_SELECT_TIMER_1_WORD 0x01 167#define APCI3120_TIMER_1_MODE_2 0x4 168 169/* $$ BIT FOR MODE IN nCsTimerCtr1 */ 170#define APCI3120_TIMER_2_MODE_0 0x0 171#define APCI3120_TIMER_2_MODE_2 0x10 172#define APCI3120_TIMER_2_MODE_5 0x30 173 174/* $$ BIT FOR MODE IN nCsTimerCtr0 */ 175#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02 176#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03 177 178#define APCI3120_TIMER_CRT0 0x0d 179#define APCI3120_TIMER_CRT1 0x0c 180 181#define APCI3120_TIMER_VALUE 0x04 182#define APCI3120_TIMER_STATUS_REGISTER 0x0d 183#define APCI3120_RD_STATUS 0x02 184#define APCI3120_WR_ADDRESS 0x00 185#define APCI3120_ENABLE_WATCHDOG 0x20 186#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG) 187#define APCI3120_ENABLE_TIMER_COUNTER 0x10 188#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER) 189#define APCI3120_FC_TIMER 0x1000 190#define APCI3120_ENABLE_TIMER0 0x1000 191#define APCI3120_ENABLE_TIMER1 0x2000 192#define APCI3120_ENABLE_TIMER2 0x4000 193#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0) 194#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1) 195#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) 196 197#define APCI3120_TIMER2_SELECT_EOS 0xc0 198#define APCI3120_COUNTER 3 199#define APCI3120_DISABLE_ALL_TIMER (APCI3120_DISABLE_TIMER0 & \ 200 APCI3120_DISABLE_TIMER1 & \ 201 APCI3120_DISABLE_TIMER2) 202 203#define MAX_ANALOGINPUT_CHANNELS 32 204 205struct str_AnalogReadInformation { 206 /* EOC or EOS */ 207 unsigned char b_Type; 208 /* Interrupt use or not */ 209 unsigned char b_InterruptFlag; 210 /* Selection of the conversion time */ 211 unsigned int ui_ConvertTiming; 212 /* Number of channel to read */ 213 unsigned char b_NbrOfChannel; 214 /* Number of the channel to be read */ 215 unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS]; 216 /* Gain of each channel */ 217 unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS]; 218}; 219 220/* ANALOG INPUT RANGE */ 221static const struct comedi_lrange range_apci3120_ai = { 222 8, { 223 BIP_RANGE(10), 224 BIP_RANGE(5), 225 BIP_RANGE(2), 226 BIP_RANGE(1), 227 UNI_RANGE(10), 228 UNI_RANGE(5), 229 UNI_RANGE(2), 230 UNI_RANGE(1) 231 } 232}; 233 234/* ANALOG OUTPUT RANGE */ 235static const struct comedi_lrange range_apci3120_ao = { 236 2, { 237 BIP_RANGE(10), 238 UNI_RANGE(10) 239 } 240}; 241 242 243/* FUNCTION DEFINITIONS */ 244static int apci3120_ai_insn_config(struct comedi_device *dev, 245 struct comedi_subdevice *s, 246 struct comedi_insn *insn, 247 unsigned int *data) 248{ 249 const struct addi_board *this_board = dev->board_ptr; 250 struct addi_private *devpriv = dev->private; 251 unsigned int i; 252 253 if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE)) 254 return -1; 255 256 /* Check for Conversion time to be added */ 257 devpriv->ui_EocEosConversionTime = data[2]; 258 259 if (data[0] == APCI3120_EOS_MODE) { 260 261 /* Test the number of the channel */ 262 for (i = 0; i < data[3]; i++) { 263 264 if (CR_CHAN(data[4 + i]) >= 265 this_board->i_NbrAiChannel) { 266 dev_err(dev->class_dev, "bad channel list\n"); 267 return -2; 268 } 269 } 270 271 devpriv->b_InterruptMode = APCI3120_EOS_MODE; 272 273 if (data[1]) 274 devpriv->b_EocEosInterrupt = APCI3120_ENABLE; 275 else 276 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 277 /* Copy channel list and Range List to devpriv */ 278 devpriv->ui_AiNbrofChannels = data[3]; 279 for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) 280 devpriv->ui_AiChannelList[i] = data[4 + i]; 281 282 } else { /* EOC */ 283 devpriv->b_InterruptMode = APCI3120_EOC_MODE; 284 if (data[1]) 285 devpriv->b_EocEosInterrupt = APCI3120_ENABLE; 286 else 287 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 288 } 289 290 return insn->n; 291} 292 293/* 294 * This function will first check channel list is ok or not and then 295 * initialize the sequence RAM with the polarity, Gain,Channel number. 296 * If the last argument of function "check"is 1 then it only checks 297 * the channel list is ok or not. 298 */ 299static int apci3120_setup_chan_list(struct comedi_device *dev, 300 struct comedi_subdevice *s, 301 int n_chan, 302 unsigned int *chanlist, 303 char check) 304{ 305 struct addi_private *devpriv = dev->private; 306 unsigned int i; 307 unsigned int gain; 308 unsigned short us_TmpValue; 309 310 /* correct channel and range number check itself comedi/range.c */ 311 if (n_chan < 1) { 312 if (!check) 313 dev_err(dev->class_dev, 314 "range/channel list is empty!\n"); 315 return 0; 316 } 317 /* All is ok, so we can setup channel/range list */ 318 if (check) 319 return 1; 320 321 /* Code to set the PA and PR...Here it set PA to 0 */ 322 devpriv->us_OutputRegister = 323 devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR; 324 devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8; 325 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); 326 327 for (i = 0; i < n_chan; i++) { 328 /* store range list to card */ 329 us_TmpValue = CR_CHAN(chanlist[i]); /* get channel number */ 330 331 if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) 332 us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff); /* set bipolar */ 333 else 334 us_TmpValue |= APCI3120_UNIPOLAR; /* enable unipolar */ 335 336 gain = CR_RANGE(chanlist[i]); /* get gain number */ 337 us_TmpValue |= ((gain & 0x03) << 4); /* <<4 for G0 and G1 bit in RAM */ 338 us_TmpValue |= i << 8; /* To select the RAM LOCATION */ 339 outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS); 340 } 341 return 1; /* we can serve this with scan logic */ 342} 343 344/* 345 * Reads analog input in synchronous mode EOC and EOS is selected 346 * as per configured if no conversion time is set uses default 347 * conversion time 10 microsec. 348 */ 349static int apci3120_ai_insn_read(struct comedi_device *dev, 350 struct comedi_subdevice *s, 351 struct comedi_insn *insn, 352 unsigned int *data) 353{ 354 const struct addi_board *this_board = dev->board_ptr; 355 struct addi_private *devpriv = dev->private; 356 unsigned short us_ConvertTiming, us_TmpValue, i; 357 unsigned char b_Tmp; 358 359 /* fix conversion time to 10 us */ 360 if (!devpriv->ui_EocEosConversionTime) 361 us_ConvertTiming = 10; 362 else 363 us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000); /* nano to useconds */ 364 365 /* Clear software registers */ 366 devpriv->b_TimerSelectMode = 0; 367 devpriv->b_ModeSelectRegister = 0; 368 devpriv->us_OutputRegister = 0; 369 370 if (insn->unused[0] == 222) { /* second insn read */ 371 for (i = 0; i < insn->n; i++) 372 data[i] = devpriv->ui_AiReadData[i]; 373 } else { 374 devpriv->tsk_Current = current; /* Save the current process task structure */ 375 376 /* 377 * Testing if board have the new Quartz and calculate the time value 378 * to set in the timer 379 */ 380 us_TmpValue = 381 (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS); 382 383 /* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */ 384 if ((us_TmpValue & 0x00B0) == 0x00B0 385 || !strcmp(this_board->pc_DriverName, "apci3001")) { 386 us_ConvertTiming = (us_ConvertTiming * 2) - 2; 387 } else { 388 us_ConvertTiming = 389 ((us_ConvertTiming * 12926) / 10000) - 1; 390 } 391 392 us_TmpValue = (unsigned short) devpriv->b_InterruptMode; 393 394 switch (us_TmpValue) { 395 396 case APCI3120_EOC_MODE: 397 398 /* 399 * Testing the interrupt flag and set the EOC bit Clears the FIFO 400 */ 401 inw(devpriv->iobase + APCI3120_RESET_FIFO); 402 403 /* Initialize the sequence array */ 404 if (!apci3120_setup_chan_list(dev, s, 1, 405 &insn->chanspec, 0)) 406 return -EINVAL; 407 408 /* Initialize Timer 0 mode 4 */ 409 devpriv->b_TimerSelectMode = 410 (devpriv-> 411 b_TimerSelectMode & 0xFC) | 412 APCI3120_TIMER_0_MODE_4; 413 outb(devpriv->b_TimerSelectMode, 414 devpriv->iobase + APCI3120_TIMER_CRT1); 415 416 /* Reset the scan bit and Disables the EOS, DMA, EOC interrupt */ 417 devpriv->b_ModeSelectRegister = 418 devpriv-> 419 b_ModeSelectRegister & APCI3120_DISABLE_SCAN; 420 421 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { 422 423 /* Disables the EOS,DMA and enables the EOC interrupt */ 424 devpriv->b_ModeSelectRegister = 425 (devpriv-> 426 b_ModeSelectRegister & 427 APCI3120_DISABLE_EOS_INT) | 428 APCI3120_ENABLE_EOC_INT; 429 inw(devpriv->iobase); 430 431 } else { 432 devpriv->b_ModeSelectRegister = 433 devpriv-> 434 b_ModeSelectRegister & 435 APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; 436 } 437 438 outb(devpriv->b_ModeSelectRegister, 439 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 440 441 /* Sets gate 0 */ 442 devpriv->us_OutputRegister = 443 (devpriv-> 444 us_OutputRegister & APCI3120_CLEAR_PA_PR) | 445 APCI3120_ENABLE_TIMER0; 446 outw(devpriv->us_OutputRegister, 447 devpriv->iobase + APCI3120_WR_ADDRESS); 448 449 /* Select Timer 0 */ 450 b_Tmp = ((devpriv-> 451 b_DigitalOutputRegister) & 0xF0) | 452 APCI3120_SELECT_TIMER_0_WORD; 453 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 454 455 /* Set the conversion time */ 456 outw(us_ConvertTiming, 457 devpriv->iobase + APCI3120_TIMER_VALUE); 458 459 us_TmpValue = 460 (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS); 461 462 if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) { 463 464 do { 465 /* Waiting for the end of conversion */ 466 us_TmpValue = 467 inw(devpriv->iobase + 468 APCI3120_RD_STATUS); 469 } while ((us_TmpValue & APCI3120_EOC) == 470 APCI3120_EOC); 471 472 /* Read the result in FIFO and put it in insn data pointer */ 473 us_TmpValue = inw(devpriv->iobase + 0); 474 *data = us_TmpValue; 475 476 inw(devpriv->iobase + APCI3120_RESET_FIFO); 477 } 478 479 break; 480 481 case APCI3120_EOS_MODE: 482 483 inw(devpriv->iobase); 484 /* Clears the FIFO */ 485 inw(devpriv->iobase + APCI3120_RESET_FIFO); 486 /* clear PA PR and disable timer 0 */ 487 488 devpriv->us_OutputRegister = 489 (devpriv-> 490 us_OutputRegister & APCI3120_CLEAR_PA_PR) | 491 APCI3120_DISABLE_TIMER0; 492 493 outw(devpriv->us_OutputRegister, 494 devpriv->iobase + APCI3120_WR_ADDRESS); 495 496 if (!apci3120_setup_chan_list(dev, s, 497 devpriv->ui_AiNbrofChannels, 498 devpriv->ui_AiChannelList, 0)) 499 return -EINVAL; 500 501 /* Initialize Timer 0 mode 2 */ 502 devpriv->b_TimerSelectMode = 503 (devpriv-> 504 b_TimerSelectMode & 0xFC) | 505 APCI3120_TIMER_0_MODE_2; 506 outb(devpriv->b_TimerSelectMode, 507 devpriv->iobase + APCI3120_TIMER_CRT1); 508 509 /* Select Timer 0 */ 510 b_Tmp = ((devpriv-> 511 b_DigitalOutputRegister) & 0xF0) | 512 APCI3120_SELECT_TIMER_0_WORD; 513 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 514 515 /* Set the conversion time */ 516 outw(us_ConvertTiming, 517 devpriv->iobase + APCI3120_TIMER_VALUE); 518 519 /* Set the scan bit */ 520 devpriv->b_ModeSelectRegister = 521 devpriv-> 522 b_ModeSelectRegister | APCI3120_ENABLE_SCAN; 523 outb(devpriv->b_ModeSelectRegister, 524 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 525 526 /* If Interrupt function is loaded */ 527 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { 528 /* Disables the EOC,DMA and enables the EOS interrupt */ 529 devpriv->b_ModeSelectRegister = 530 (devpriv-> 531 b_ModeSelectRegister & 532 APCI3120_DISABLE_EOC_INT) | 533 APCI3120_ENABLE_EOS_INT; 534 inw(devpriv->iobase); 535 536 } else 537 devpriv->b_ModeSelectRegister = 538 devpriv-> 539 b_ModeSelectRegister & 540 APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; 541 542 outb(devpriv->b_ModeSelectRegister, 543 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 544 545 inw(devpriv->iobase + APCI3120_RD_STATUS); 546 547 /* Sets gate 0 */ 548 devpriv->us_OutputRegister = 549 devpriv-> 550 us_OutputRegister | APCI3120_ENABLE_TIMER0; 551 outw(devpriv->us_OutputRegister, 552 devpriv->iobase + APCI3120_WR_ADDRESS); 553 554 /* Start conversion */ 555 outw(0, devpriv->iobase + APCI3120_START_CONVERSION); 556 557 /* Waiting of end of conversion if interrupt is not installed */ 558 if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) { 559 /* Waiting the end of conversion */ 560 do { 561 us_TmpValue = 562 inw(devpriv->iobase + 563 APCI3120_RD_STATUS); 564 } while ((us_TmpValue & APCI3120_EOS) != 565 APCI3120_EOS); 566 567 for (i = 0; i < devpriv->ui_AiNbrofChannels; 568 i++) { 569 /* Read the result in FIFO and write them in shared memory */ 570 us_TmpValue = inw(devpriv->iobase); 571 data[i] = (unsigned int) us_TmpValue; 572 } 573 574 devpriv->b_InterruptMode = APCI3120_EOC_MODE; /* Restore defaults */ 575 } 576 break; 577 578 default: 579 dev_err(dev->class_dev, "inputs wrong\n"); 580 581 } 582 devpriv->ui_EocEosConversionTime = 0; /* re initializing the variable */ 583 } 584 585 return insn->n; 586 587} 588 589static int apci3120_reset(struct comedi_device *dev) 590{ 591 struct addi_private *devpriv = dev->private; 592 unsigned int i; 593 unsigned short us_TmpValue; 594 595 devpriv->ai_running = 0; 596 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 597 devpriv->b_InterruptMode = APCI3120_EOC_MODE; 598 devpriv->ui_EocEosConversionTime = 0; /* set eoc eos conv time to 0 */ 599 600 /* variables used in timer subdevice */ 601 devpriv->b_Timer2Mode = 0; 602 devpriv->b_Timer2Interrupt = 0; 603 devpriv->b_ExttrigEnable = 0; /* Disable ext trigger */ 604 605 /* Disable all interrupts, watchdog for the anolog output */ 606 devpriv->b_ModeSelectRegister = 0; 607 outb(devpriv->b_ModeSelectRegister, 608 dev->iobase + APCI3120_WRITE_MODE_SELECT); 609 610 /* Disables all counters, ext trigger and clears PA, PR */ 611 devpriv->us_OutputRegister = 0; 612 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); 613 614 /* 615 * Code to set the all anolog o/p channel to 0v 8191 is decimal 616 * value for zero(0 v)volt in bipolar mode(default) 617 */ 618 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 1 */ 619 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 2 */ 620 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 3 */ 621 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 4 */ 622 623 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 5 */ 624 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 6 */ 625 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 7 */ 626 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 8 */ 627 628 udelay(10); 629 630 inw(dev->iobase + 0); /* make a dummy read */ 631 inb(dev->iobase + APCI3120_RESET_FIFO); /* flush FIFO */ 632 inw(dev->iobase + APCI3120_RD_STATUS); /* flush A/D status register */ 633 634 /* code to reset the RAM sequence */ 635 for (i = 0; i < 16; i++) { 636 us_TmpValue = i << 8; /* select the location */ 637 outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS); 638 } 639 return 0; 640} 641 642static int apci3120_exttrig_enable(struct comedi_device *dev) 643{ 644 struct addi_private *devpriv = dev->private; 645 646 devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER; 647 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); 648 return 0; 649} 650 651static int apci3120_exttrig_disable(struct comedi_device *dev) 652{ 653 struct addi_private *devpriv = dev->private; 654 655 devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER; 656 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); 657 return 0; 658} 659 660static int apci3120_cancel(struct comedi_device *dev, 661 struct comedi_subdevice *s) 662{ 663 struct addi_private *devpriv = dev->private; 664 665 /* Disable A2P Fifo write and AMWEN signal */ 666 outw(0, devpriv->i_IobaseAddon + 4); 667 668 /* Disable Bus Master ADD ON */ 669 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); 670 outw(0, devpriv->i_IobaseAddon + 2); 671 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); 672 outw(0, devpriv->i_IobaseAddon + 2); 673 674 /* Disable BUS Master PCI */ 675 outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); 676 677 /* Disable ext trigger */ 678 apci3120_exttrig_disable(dev); 679 680 devpriv->us_OutputRegister = 0; 681 /* stop counters */ 682 outw(devpriv-> 683 us_OutputRegister & APCI3120_DISABLE_TIMER0 & 684 APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS); 685 686 outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS); 687 688 /* DISABLE_ALL_INTERRUPT */ 689 outb(APCI3120_DISABLE_ALL_INTERRUPT, 690 dev->iobase + APCI3120_WRITE_MODE_SELECT); 691 /* Flush FIFO */ 692 inb(dev->iobase + APCI3120_RESET_FIFO); 693 inw(dev->iobase + APCI3120_RD_STATUS); 694 devpriv->ui_AiActualScan = 0; 695 s->async->cur_chan = 0; 696 devpriv->ui_DmaActualBuffer = 0; 697 698 devpriv->ai_running = 0; 699 devpriv->b_InterruptMode = APCI3120_EOC_MODE; 700 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 701 apci3120_reset(dev); 702 return 0; 703} 704 705static int apci3120_ai_cmdtest(struct comedi_device *dev, 706 struct comedi_subdevice *s, 707 struct comedi_cmd *cmd) 708{ 709 int err = 0; 710 711 /* Step 1 : check if triggers are trivially valid */ 712 713 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); 714 err |= cfc_check_trigger_src(&cmd->scan_begin_src, 715 TRIG_TIMER | TRIG_FOLLOW); 716 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); 717 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 718 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 719 720 if (err) 721 return 1; 722 723 /* Step 2a : make sure trigger sources are unique */ 724 725 err |= cfc_check_trigger_is_unique(cmd->start_src); 726 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); 727 err |= cfc_check_trigger_is_unique(cmd->stop_src); 728 729 /* Step 2b : and mutually compatible */ 730 731 if (err) 732 return 2; 733 734 /* Step 3: check if arguments are trivially valid */ 735 736 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 737 738 if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */ 739 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000); 740 741 if (cmd->scan_begin_src == TRIG_TIMER) { 742 if (cmd->convert_arg) 743 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 744 10000); 745 } else { 746 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000); 747 } 748 749 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); 750 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 751 752 if (cmd->stop_src == TRIG_COUNT) 753 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); 754 else /* TRIG_NONE */ 755 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 756 757 if (err) 758 return 3; 759 760 /* step 4: fix up any arguments */ 761 762 if (cmd->scan_begin_src == TRIG_TIMER && 763 cmd->scan_begin_arg < cmd->convert_arg * cmd->scan_end_arg) { 764 cmd->scan_begin_arg = cmd->convert_arg * cmd->scan_end_arg; 765 err |= -EINVAL; 766 } 767 768 if (err) 769 return 4; 770 771 return 0; 772} 773 774/* 775 * This is used for analog input cyclic acquisition. 776 * Performs the command operations. 777 * If DMA is configured does DMA initialization otherwise does the 778 * acquisition with EOS interrupt. 779 */ 780static int apci3120_cyclic_ai(int mode, 781 struct comedi_device *dev, 782 struct comedi_subdevice *s) 783{ 784 const struct addi_board *this_board = dev->board_ptr; 785 struct addi_private *devpriv = dev->private; 786 struct comedi_cmd *cmd = &s->async->cmd; 787 unsigned char b_Tmp; 788 unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 = 789 0, dmalen1 = 0, ui_TimerValue2 = 790 0, ui_TimerValue0, ui_ConvertTiming; 791 unsigned short us_TmpValue; 792 793 /* Resets the FIFO */ 794 inb(dev->iobase + APCI3120_RESET_FIFO); 795 796 devpriv->ai_running = 1; 797 798 /* clear software registers */ 799 devpriv->b_TimerSelectMode = 0; 800 devpriv->us_OutputRegister = 0; 801 devpriv->b_ModeSelectRegister = 0; 802 803 /* Clear Timer Write TC int */ 804 outl(APCI3120_CLEAR_WRITE_TC_INT, 805 devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR); 806 807 /* Disables All Timer */ 808 /* Sets PR and PA to 0 */ 809 devpriv->us_OutputRegister = devpriv->us_OutputRegister & 810 APCI3120_DISABLE_TIMER0 & 811 APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR; 812 813 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); 814 815 /* Resets the FIFO */ 816 /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ 817 inb(devpriv->iobase + APCI3120_RESET_FIFO); 818 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 819 820 devpriv->ui_AiActualScan = 0; 821 s->async->cur_chan = 0; 822 devpriv->ui_DmaActualBuffer = 0; 823 824 /* value for timer2 minus -2 has to be done */ 825 ui_TimerValue2 = cmd->stop_arg - 2; 826 ui_ConvertTiming = cmd->convert_arg; 827 828 if (mode == 2) 829 ui_DelayTiming = cmd->scan_begin_arg; 830 831 /* Initializes the sequence array */ 832 if (!apci3120_setup_chan_list(dev, s, devpriv->ui_AiNbrofChannels, 833 cmd->chanlist, 0)) 834 return -EINVAL; 835 836 us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS); 837 838 /* EL241003 Begin: add this section to replace floats calculation by integer calculations */ 839 /* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */ 840 if ((us_TmpValue & 0x00B0) == 0x00B0 841 || !strcmp(this_board->pc_DriverName, "apci3001")) { 842 ui_TimerValue0 = ui_ConvertTiming * 2 - 2000; 843 ui_TimerValue0 = ui_TimerValue0 / 1000; 844 845 if (mode == 2) { 846 ui_DelayTiming = ui_DelayTiming / 1000; 847 ui_TimerValue1 = ui_DelayTiming * 2 - 200; 848 ui_TimerValue1 = ui_TimerValue1 / 100; 849 } 850 } else { 851 ui_ConvertTiming = ui_ConvertTiming / 1000; 852 ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000; 853 ui_TimerValue0 = ui_TimerValue0 / 10000; 854 855 if (mode == 2) { 856 ui_DelayTiming = ui_DelayTiming / 1000; 857 ui_TimerValue1 = ui_DelayTiming * 12926 - 1; 858 ui_TimerValue1 = ui_TimerValue1 / 1000000; 859 } 860 } 861 /* EL241003 End */ 862 863 if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) 864 apci3120_exttrig_enable(dev); /* activate EXT trigger */ 865 switch (mode) { 866 case 1: 867 /* init timer0 in mode 2 */ 868 devpriv->b_TimerSelectMode = 869 (devpriv-> 870 b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2; 871 outb(devpriv->b_TimerSelectMode, 872 dev->iobase + APCI3120_TIMER_CRT1); 873 874 /* Select Timer 0 */ 875 b_Tmp = ((devpriv-> 876 b_DigitalOutputRegister) & 0xF0) | 877 APCI3120_SELECT_TIMER_0_WORD; 878 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); 879 /* Set the conversion time */ 880 outw(((unsigned short) ui_TimerValue0), 881 dev->iobase + APCI3120_TIMER_VALUE); 882 break; 883 884 case 2: 885 /* init timer1 in mode 2 */ 886 devpriv->b_TimerSelectMode = 887 (devpriv-> 888 b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2; 889 outb(devpriv->b_TimerSelectMode, 890 dev->iobase + APCI3120_TIMER_CRT1); 891 892 /* Select Timer 1 */ 893 b_Tmp = ((devpriv-> 894 b_DigitalOutputRegister) & 0xF0) | 895 APCI3120_SELECT_TIMER_1_WORD; 896 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); 897 /* Set the conversion time */ 898 outw(((unsigned short) ui_TimerValue1), 899 dev->iobase + APCI3120_TIMER_VALUE); 900 901 /* init timer0 in mode 2 */ 902 devpriv->b_TimerSelectMode = 903 (devpriv-> 904 b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2; 905 outb(devpriv->b_TimerSelectMode, 906 dev->iobase + APCI3120_TIMER_CRT1); 907 908 /* Select Timer 0 */ 909 b_Tmp = ((devpriv-> 910 b_DigitalOutputRegister) & 0xF0) | 911 APCI3120_SELECT_TIMER_0_WORD; 912 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); 913 914 /* Set the conversion time */ 915 outw(((unsigned short) ui_TimerValue0), 916 dev->iobase + APCI3120_TIMER_VALUE); 917 break; 918 919 } 920 /* common for all modes */ 921 /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ 922 devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & 923 APCI3120_DISABLE_SCAN; 924 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 925 926 outb(devpriv->b_ModeSelectRegister, 927 dev->iobase + APCI3120_WRITE_MODE_SELECT); 928 929 /* If DMA is disabled */ 930 if (devpriv->us_UseDma == APCI3120_DISABLE) { 931 /* disable EOC and enable EOS */ 932 devpriv->b_InterruptMode = APCI3120_EOS_MODE; 933 devpriv->b_EocEosInterrupt = APCI3120_ENABLE; 934 935 devpriv->b_ModeSelectRegister = 936 (devpriv-> 937 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) | 938 APCI3120_ENABLE_EOS_INT; 939 outb(devpriv->b_ModeSelectRegister, 940 dev->iobase + APCI3120_WRITE_MODE_SELECT); 941 942 if (cmd->stop_src == TRIG_COUNT) { 943 /* 944 * configure Timer2 For counting EOS Reset gate 2 of Timer 2 to 945 * disable it (Set Bit D14 to 0) 946 */ 947 devpriv->us_OutputRegister = 948 devpriv-> 949 us_OutputRegister & APCI3120_DISABLE_TIMER2; 950 outw(devpriv->us_OutputRegister, 951 dev->iobase + APCI3120_WR_ADDRESS); 952 953 /* DISABLE TIMER intERRUPT */ 954 devpriv->b_ModeSelectRegister = 955 devpriv-> 956 b_ModeSelectRegister & 957 APCI3120_DISABLE_TIMER_INT & 0xEF; 958 outb(devpriv->b_ModeSelectRegister, 959 dev->iobase + APCI3120_WRITE_MODE_SELECT); 960 961 /* (1) Init timer 2 in mode 0 and write timer value */ 962 devpriv->b_TimerSelectMode = 963 (devpriv-> 964 b_TimerSelectMode & 0x0F) | 965 APCI3120_TIMER_2_MODE_0; 966 outb(devpriv->b_TimerSelectMode, 967 dev->iobase + APCI3120_TIMER_CRT1); 968 969 /* Writing LOW unsigned short */ 970 b_Tmp = ((devpriv-> 971 b_DigitalOutputRegister) & 0xF0) | 972 APCI3120_SELECT_TIMER_2_LOW_WORD; 973 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); 974 outw(ui_TimerValue2 & 0xffff, 975 dev->iobase + APCI3120_TIMER_VALUE); 976 977 /* Writing HIGH unsigned short */ 978 b_Tmp = ((devpriv-> 979 b_DigitalOutputRegister) & 0xF0) | 980 APCI3120_SELECT_TIMER_2_HIGH_WORD; 981 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); 982 outw((ui_TimerValue2 >> 16) & 0xffff, 983 dev->iobase + APCI3120_TIMER_VALUE); 984 985 /* (2) Reset FC_TIMER BIT Clearing timer status register */ 986 inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); 987 /* enable timer counter and disable watch dog */ 988 devpriv->b_ModeSelectRegister = 989 (devpriv-> 990 b_ModeSelectRegister | 991 APCI3120_ENABLE_TIMER_COUNTER) & 992 APCI3120_DISABLE_WATCHDOG; 993 /* select EOS clock input for timer 2 */ 994 devpriv->b_ModeSelectRegister = 995 devpriv-> 996 b_ModeSelectRegister | 997 APCI3120_TIMER2_SELECT_EOS; 998 /* Enable timer2 interrupt */ 999 devpriv->b_ModeSelectRegister = 1000 devpriv-> 1001 b_ModeSelectRegister | 1002 APCI3120_ENABLE_TIMER_INT; 1003 outb(devpriv->b_ModeSelectRegister, 1004 dev->iobase + APCI3120_WRITE_MODE_SELECT); 1005 devpriv->b_Timer2Mode = APCI3120_COUNTER; 1006 devpriv->b_Timer2Interrupt = APCI3120_ENABLE; 1007 } 1008 } else { 1009 /* If DMA Enabled */ 1010 unsigned int scan_bytes = cmd->scan_end_arg * sizeof(short); 1011 1012 devpriv->b_InterruptMode = APCI3120_DMA_MODE; 1013 1014 /* Disables the EOC, EOS interrupt */ 1015 devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & 1016 APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT; 1017 1018 outb(devpriv->b_ModeSelectRegister, 1019 dev->iobase + APCI3120_WRITE_MODE_SELECT); 1020 1021 dmalen0 = devpriv->ui_DmaBufferSize[0]; 1022 dmalen1 = devpriv->ui_DmaBufferSize[1]; 1023 1024 if (cmd->stop_src == TRIG_COUNT) { 1025 /* 1026 * Must we fill full first buffer? And must we fill 1027 * full second buffer when first is once filled? 1028 */ 1029 if (dmalen0 > (cmd->stop_arg * scan_bytes)) { 1030 dmalen0 = cmd->stop_arg * scan_bytes; 1031 } else if (dmalen1 > (cmd->stop_arg * scan_bytes - 1032 dmalen0)) 1033 dmalen1 = cmd->stop_arg * scan_bytes - 1034 dmalen0; 1035 } 1036 1037 if (cmd->flags & CMDF_WAKE_EOS) { 1038 /* don't we want wake up every scan? */ 1039 if (dmalen0 > scan_bytes) { 1040 dmalen0 = scan_bytes; 1041 if (cmd->scan_end_arg & 1) 1042 dmalen0 += 2; 1043 } 1044 if (dmalen1 > scan_bytes) { 1045 dmalen1 = scan_bytes; 1046 if (cmd->scan_end_arg & 1) 1047 dmalen1 -= 2; 1048 if (dmalen1 < 4) 1049 dmalen1 = 4; 1050 } 1051 } else { /* isn't output buff smaller that our DMA buff? */ 1052 if (dmalen0 > s->async->prealloc_bufsz) 1053 dmalen0 = s->async->prealloc_bufsz; 1054 if (dmalen1 > s->async->prealloc_bufsz) 1055 dmalen1 = s->async->prealloc_bufsz; 1056 } 1057 devpriv->ui_DmaBufferUsesize[0] = dmalen0; 1058 devpriv->ui_DmaBufferUsesize[1] = dmalen1; 1059 1060 /* Initialize DMA */ 1061 1062 /* 1063 * Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS 1064 * register 1 1065 */ 1066 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; 1067 outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS); 1068 1069 /* changed since 16 bit interface for add on */ 1070 /* ENABLE BUS MASTER */ 1071 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); 1072 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, 1073 devpriv->i_IobaseAddon + 2); 1074 1075 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); 1076 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, 1077 devpriv->i_IobaseAddon + 2); 1078 1079 /* 1080 * TO VERIFIED BEGIN JK 07.05.04: Comparison between WIN32 and Linux 1081 * driver 1082 */ 1083 outw(0x1000, devpriv->i_IobaseAddon + 2); 1084 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 1085 1086 /* 2 No change */ 1087 /* A2P FIFO MANAGEMENT */ 1088 /* A2P fifo reset & transfer control enable */ 1089 outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc + 1090 APCI3120_AMCC_OP_MCSR); 1091 1092 /* 1093 * 3 1094 * beginning address of dma buf The 32 bit address of dma buffer 1095 * is converted into two 16 bit addresses Can done by using _attach 1096 * and put into into an array array used may be for differnet pages 1097 */ 1098 1099 /* DMA Start Address Low */ 1100 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); 1101 outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF), 1102 devpriv->i_IobaseAddon + 2); 1103 1104 /* DMA Start Address High */ 1105 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); 1106 outw((devpriv->ul_DmaBufferHw[0] / 65536), 1107 devpriv->i_IobaseAddon + 2); 1108 1109 /* 1110 * 4 1111 * amount of bytes to be transferred set transfer count used ADDON 1112 * MWTC register commented testing 1113 */ 1114 1115 /* Nbr of acquisition LOW */ 1116 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); 1117 outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF), 1118 devpriv->i_IobaseAddon + 2); 1119 1120 /* Nbr of acquisition HIGH */ 1121 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); 1122 outw((devpriv->ui_DmaBufferUsesize[0] / 65536), 1123 devpriv->i_IobaseAddon + 2); 1124 1125 /* 1126 * 5 1127 * To configure A2P FIFO testing outl( 1128 * FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); 1129 */ 1130 1131 /* A2P FIFO RESET */ 1132 /* 1133 * TO VERIFY BEGIN JK 07.05.04: Comparison between WIN32 and Linux 1134 * driver 1135 */ 1136 outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); 1137 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 1138 1139 /* 1140 * 6 1141 * ENABLE A2P FIFO WRITE AND ENABLE AMWEN AMWEN_ENABLE | 1142 * A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 1143 */ 1144 1145 /* 1146 * 7 1147 * initialise end of dma interrupt AINT_WRITE_COMPL = 1148 * ENABLE_WRITE_TC_INT(ADDI) 1149 */ 1150 /* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */ 1151 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | 1152 APCI3120_ENABLE_WRITE_TC_INT), 1153 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); 1154 1155 /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ 1156 /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */ 1157 outw(3, devpriv->i_IobaseAddon + 4); 1158 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 1159 1160 /* A2P FIFO RESET */ 1161 /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ 1162 outl(0x04000000UL, 1163 devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR); 1164 /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ 1165 } 1166 1167 if (devpriv->us_UseDma == APCI3120_DISABLE && 1168 cmd->stop_src == TRIG_COUNT) { 1169 /* set gate 2 to start conversion */ 1170 devpriv->us_OutputRegister = 1171 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2; 1172 outw(devpriv->us_OutputRegister, 1173 dev->iobase + APCI3120_WR_ADDRESS); 1174 } 1175 1176 switch (mode) { 1177 case 1: 1178 /* set gate 0 to start conversion */ 1179 devpriv->us_OutputRegister = 1180 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; 1181 outw(devpriv->us_OutputRegister, 1182 dev->iobase + APCI3120_WR_ADDRESS); 1183 break; 1184 case 2: 1185 /* set gate 0 and gate 1 */ 1186 devpriv->us_OutputRegister = 1187 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1; 1188 devpriv->us_OutputRegister = 1189 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; 1190 outw(devpriv->us_OutputRegister, 1191 dev->iobase + APCI3120_WR_ADDRESS); 1192 break; 1193 1194 } 1195 1196 return 0; 1197 1198} 1199 1200/* 1201 * Does asynchronous acquisition. 1202 * Determines the mode 1 or 2. 1203 */ 1204static int apci3120_ai_cmd(struct comedi_device *dev, 1205 struct comedi_subdevice *s) 1206{ 1207 struct addi_private *devpriv = dev->private; 1208 struct comedi_cmd *cmd = &s->async->cmd; 1209 1210 /* loading private structure with cmd structure inputs */ 1211 devpriv->ui_AiNbrofChannels = cmd->chanlist_len; 1212 1213 if (cmd->start_src == TRIG_EXT) 1214 devpriv->b_ExttrigEnable = APCI3120_ENABLE; 1215 else 1216 devpriv->b_ExttrigEnable = APCI3120_DISABLE; 1217 1218 if (cmd->scan_begin_src == TRIG_FOLLOW) 1219 return apci3120_cyclic_ai(1, dev, s); 1220 /* TRIG_TIMER */ 1221 return apci3120_cyclic_ai(2, dev, s); 1222} 1223 1224/* 1225 * This function copies the data from DMA buffer to the Comedi buffer. 1226 */ 1227static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev, 1228 struct comedi_subdevice *s, 1229 unsigned short *dma_buffer, 1230 unsigned int num_samples) 1231{ 1232 struct addi_private *devpriv = dev->private; 1233 struct comedi_cmd *cmd = &s->async->cmd; 1234 1235 devpriv->ui_AiActualScan += 1236 (s->async->cur_chan + num_samples) / cmd->scan_end_arg; 1237 s->async->cur_chan += num_samples; 1238 s->async->cur_chan %= cmd->scan_end_arg; 1239 1240 cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short)); 1241} 1242 1243/* 1244 * This is a handler for the DMA interrupt. 1245 * This function copies the data to Comedi Buffer. 1246 * For continuous DMA it reinitializes the DMA operation. 1247 * For single mode DMA it stop the acquisition. 1248 */ 1249static void apci3120_interrupt_dma(int irq, void *d) 1250{ 1251 struct comedi_device *dev = d; 1252 struct addi_private *devpriv = dev->private; 1253 struct comedi_subdevice *s = dev->read_subdev; 1254 struct comedi_cmd *cmd = &s->async->cmd; 1255 unsigned int next_dma_buf, samplesinbuf; 1256 unsigned long low_word, high_word, var; 1257 unsigned int ui_Tmp; 1258 1259 samplesinbuf = 1260 devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] - 1261 inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC); 1262 1263 if (samplesinbuf < 1264 devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) { 1265 dev_err(dev->class_dev, "Interrupted DMA transfer!\n"); 1266 } 1267 if (samplesinbuf & 1) { 1268 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n"); 1269 apci3120_cancel(dev, s); 1270 return; 1271 } 1272 samplesinbuf = samplesinbuf >> 1; /* number of received samples */ 1273 if (devpriv->b_DmaDoubleBuffer) { 1274 /* switch DMA buffers if is used double buffering */ 1275 next_dma_buf = 1 - devpriv->ui_DmaActualBuffer; 1276 1277 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; 1278 outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS); 1279 1280 /* changed since 16 bit interface for add on */ 1281 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); 1282 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, 1283 devpriv->i_IobaseAddon + 2); 1284 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); 1285 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); /* 0x1000 is out putted in windows driver */ 1286 1287 var = devpriv->ul_DmaBufferHw[next_dma_buf]; 1288 low_word = var & 0xffff; 1289 var = devpriv->ul_DmaBufferHw[next_dma_buf]; 1290 high_word = var / 65536; 1291 1292 /* DMA Start Address Low */ 1293 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); 1294 outw(low_word, devpriv->i_IobaseAddon + 2); 1295 1296 /* DMA Start Address High */ 1297 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); 1298 outw(high_word, devpriv->i_IobaseAddon + 2); 1299 1300 var = devpriv->ui_DmaBufferUsesize[next_dma_buf]; 1301 low_word = var & 0xffff; 1302 var = devpriv->ui_DmaBufferUsesize[next_dma_buf]; 1303 high_word = var / 65536; 1304 1305 /* Nbr of acquisition LOW */ 1306 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); 1307 outw(low_word, devpriv->i_IobaseAddon + 2); 1308 1309 /* Nbr of acquisition HIGH */ 1310 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); 1311 outw(high_word, devpriv->i_IobaseAddon + 2); 1312 1313 /* 1314 * To configure A2P FIFO 1315 * ENABLE A2P FIFO WRITE AND ENABLE AMWEN 1316 * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 1317 */ 1318 outw(3, devpriv->i_IobaseAddon + 4); 1319 /* initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */ 1320 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | 1321 APCI3120_ENABLE_WRITE_TC_INT), 1322 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); 1323 1324 } 1325 if (samplesinbuf) { 1326 v_APCI3120_InterruptDmaMoveBlock16bit(dev, s, 1327 devpriv->ul_DmaBufferVirtual[devpriv-> 1328 ui_DmaActualBuffer], samplesinbuf); 1329 1330 if (!(cmd->flags & CMDF_WAKE_EOS)) { 1331 s->async->events |= COMEDI_CB_EOS; 1332 comedi_event(dev, s); 1333 } 1334 } 1335 if (cmd->stop_src == TRIG_COUNT) 1336 if (devpriv->ui_AiActualScan >= cmd->stop_arg) { 1337 /* all data sampled */ 1338 apci3120_cancel(dev, s); 1339 s->async->events |= COMEDI_CB_EOA; 1340 comedi_event(dev, s); 1341 return; 1342 } 1343 1344 if (devpriv->b_DmaDoubleBuffer) { /* switch dma buffers */ 1345 devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer; 1346 } else { 1347 /* 1348 * restart DMA if is not used double buffering 1349 * ADDED REINITIALISE THE DMA 1350 */ 1351 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; 1352 outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS); 1353 1354 /* changed since 16 bit interface for add on */ 1355 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); 1356 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, 1357 devpriv->i_IobaseAddon + 2); 1358 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); 1359 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); 1360 /* 1361 * A2P FIFO MANAGEMENT 1362 * A2P fifo reset & transfer control enable 1363 */ 1364 outl(APCI3120_A2P_FIFO_MANAGEMENT, 1365 devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); 1366 1367 var = devpriv->ul_DmaBufferHw[0]; 1368 low_word = var & 0xffff; 1369 var = devpriv->ul_DmaBufferHw[0]; 1370 high_word = var / 65536; 1371 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); 1372 outw(low_word, devpriv->i_IobaseAddon + 2); 1373 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); 1374 outw(high_word, devpriv->i_IobaseAddon + 2); 1375 1376 var = devpriv->ui_DmaBufferUsesize[0]; 1377 low_word = var & 0xffff; /* changed */ 1378 var = devpriv->ui_DmaBufferUsesize[0]; 1379 high_word = var / 65536; 1380 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); 1381 outw(low_word, devpriv->i_IobaseAddon + 2); 1382 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); 1383 outw(high_word, devpriv->i_IobaseAddon + 2); 1384 1385 /* 1386 * To configure A2P FIFO 1387 * ENABLE A2P FIFO WRITE AND ENABLE AMWEN 1388 * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 1389 */ 1390 outw(3, devpriv->i_IobaseAddon + 4); 1391 /* initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */ 1392 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | 1393 APCI3120_ENABLE_WRITE_TC_INT), 1394 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); 1395 } 1396} 1397 1398/* 1399 * This function handles EOS interrupt. 1400 * This function copies the acquired data(from FIFO) to Comedi buffer. 1401 */ 1402static int apci3120_interrupt_handle_eos(struct comedi_device *dev) 1403{ 1404 struct addi_private *devpriv = dev->private; 1405 struct comedi_subdevice *s = dev->read_subdev; 1406 int n_chan, i; 1407 int err = 1; 1408 1409 n_chan = devpriv->ui_AiNbrofChannels; 1410 1411 for (i = 0; i < n_chan; i++) 1412 err &= comedi_buf_put(s, inw(dev->iobase + 0)); 1413 1414 s->async->events |= COMEDI_CB_EOS; 1415 1416 if (err == 0) 1417 s->async->events |= COMEDI_CB_OVERFLOW; 1418 1419 comedi_event(dev, s); 1420 1421 return 0; 1422} 1423 1424static void apci3120_interrupt(int irq, void *d) 1425{ 1426 struct comedi_device *dev = d; 1427 struct addi_private *devpriv = dev->private; 1428 struct comedi_subdevice *s = dev->read_subdev; 1429 unsigned short int_daq; 1430 unsigned int int_amcc, ui_Check, i; 1431 unsigned short us_TmpValue; 1432 unsigned char b_DummyRead; 1433 1434 ui_Check = 1; 1435 1436 int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; /* get IRQ reasons */ 1437 int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* get AMCC int register */ 1438 1439 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) { 1440 dev_err(dev->class_dev, "IRQ from unknown source\n"); 1441 return; 1442 } 1443 1444 outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* shutdown IRQ reasons in AMCC */ 1445 1446 int_daq = (int_daq >> 12) & 0xF; 1447 1448 if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) { 1449 /* Disable ext trigger */ 1450 apci3120_exttrig_disable(dev); 1451 devpriv->b_ExttrigEnable = APCI3120_DISABLE; 1452 } 1453 /* clear the timer 2 interrupt */ 1454 inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER); 1455 1456 if (int_amcc & MASTER_ABORT_INT) 1457 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); 1458 if (int_amcc & TARGET_ABORT_INT) 1459 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); 1460 1461 /* Ckeck if EOC interrupt */ 1462 if (((int_daq & 0x8) == 0) 1463 && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) { 1464 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { 1465 1466 /* Read the AI Value */ 1467 devpriv->ui_AiReadData[0] = 1468 (unsigned int) inw(devpriv->iobase + 0); 1469 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 1470 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 1471 } else { 1472 /* Disable EOC Interrupt */ 1473 devpriv->b_ModeSelectRegister = 1474 devpriv-> 1475 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT; 1476 outb(devpriv->b_ModeSelectRegister, 1477 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 1478 1479 } 1480 } 1481 1482 /* Check If EOS interrupt */ 1483 if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) { 1484 1485 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { /* enable this in without DMA ??? */ 1486 1487 if (devpriv->ai_running) { 1488 ui_Check = 0; 1489 apci3120_interrupt_handle_eos(dev); 1490 devpriv->ui_AiActualScan++; 1491 devpriv->b_ModeSelectRegister = 1492 devpriv-> 1493 b_ModeSelectRegister | 1494 APCI3120_ENABLE_EOS_INT; 1495 outb(devpriv->b_ModeSelectRegister, 1496 dev->iobase + 1497 APCI3120_WRITE_MODE_SELECT); 1498 } else { 1499 ui_Check = 0; 1500 for (i = 0; i < devpriv->ui_AiNbrofChannels; 1501 i++) { 1502 us_TmpValue = inw(devpriv->iobase + 0); 1503 devpriv->ui_AiReadData[i] = 1504 (unsigned int) us_TmpValue; 1505 } 1506 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; 1507 devpriv->b_InterruptMode = APCI3120_EOC_MODE; 1508 1509 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 1510 1511 } 1512 1513 } else { 1514 devpriv->b_ModeSelectRegister = 1515 devpriv-> 1516 b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; 1517 outb(devpriv->b_ModeSelectRegister, 1518 dev->iobase + APCI3120_WRITE_MODE_SELECT); 1519 devpriv->b_EocEosInterrupt = APCI3120_DISABLE; /* Default settings */ 1520 devpriv->b_InterruptMode = APCI3120_EOC_MODE; 1521 } 1522 1523 } 1524 /* Timer2 interrupt */ 1525 if (int_daq & 0x1) { 1526 1527 switch (devpriv->b_Timer2Mode) { 1528 case APCI3120_COUNTER: 1529 devpriv->b_ModeSelectRegister = 1530 devpriv-> 1531 b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; 1532 outb(devpriv->b_ModeSelectRegister, 1533 dev->iobase + APCI3120_WRITE_MODE_SELECT); 1534 1535 /* stop timer 2 */ 1536 devpriv->us_OutputRegister = 1537 devpriv-> 1538 us_OutputRegister & APCI3120_DISABLE_ALL_TIMER; 1539 outw(devpriv->us_OutputRegister, 1540 dev->iobase + APCI3120_WR_ADDRESS); 1541 1542 /* stop timer 0 and timer 1 */ 1543 apci3120_cancel(dev, s); 1544 1545 /* UPDATE-0.7.57->0.7.68comedi_done(dev,s); */ 1546 s->async->events |= COMEDI_CB_EOA; 1547 comedi_event(dev, s); 1548 1549 break; 1550 1551 case APCI3120_TIMER: 1552 1553 /* Send a signal to from kernel to user space */ 1554 send_sig(SIGIO, devpriv->tsk_Current, 0); 1555 break; 1556 1557 case APCI3120_WATCHDOG: 1558 1559 /* Send a signal to from kernel to user space */ 1560 send_sig(SIGIO, devpriv->tsk_Current, 0); 1561 break; 1562 1563 default: 1564 1565 /* disable Timer Interrupt */ 1566 devpriv->b_ModeSelectRegister = 1567 devpriv-> 1568 b_ModeSelectRegister & 1569 APCI3120_DISABLE_TIMER_INT; 1570 1571 outb(devpriv->b_ModeSelectRegister, 1572 dev->iobase + APCI3120_WRITE_MODE_SELECT); 1573 1574 } 1575 1576 b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); 1577 1578 } 1579 1580 if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) { 1581 if (devpriv->ai_running) { 1582 1583 /* Clear Timer Write TC int */ 1584 outl(APCI3120_CLEAR_WRITE_TC_INT, 1585 devpriv->i_IobaseAmcc + 1586 APCI3120_AMCC_OP_REG_INTCSR); 1587 1588 /* Clears the timer status register */ 1589 inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); 1590 /* do some data transfer */ 1591 apci3120_interrupt_dma(irq, d); 1592 } else { 1593 /* Stops the Timer */ 1594 outw(devpriv-> 1595 us_OutputRegister & APCI3120_DISABLE_TIMER0 & 1596 APCI3120_DISABLE_TIMER1, 1597 dev->iobase + APCI3120_WR_ADDRESS); 1598 } 1599 1600 } 1601} 1602 1603/* 1604 * Configure Timer 2 1605 * 1606 * data[0] = TIMER configure as timer 1607 * = WATCHDOG configure as watchdog 1608 * data[1] = Timer constant 1609 * data[2] = Timer2 interrupt (1)enable or(0) disable 1610 */ 1611static int apci3120_config_insn_timer(struct comedi_device *dev, 1612 struct comedi_subdevice *s, 1613 struct comedi_insn *insn, 1614 unsigned int *data) 1615{ 1616 const struct addi_board *this_board = dev->board_ptr; 1617 struct addi_private *devpriv = dev->private; 1618 unsigned int ui_Timervalue2; 1619 unsigned short us_TmpValue; 1620 unsigned char b_Tmp; 1621 1622 if (!data[1]) 1623 dev_err(dev->class_dev, "No timer constant!\n"); 1624 1625 devpriv->b_Timer2Interrupt = (unsigned char) data[2]; /* save info whether to enable or disable interrupt */ 1626 1627 ui_Timervalue2 = data[1] / 1000; /* convert nano seconds to u seconds */ 1628 1629 us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS); 1630 1631 /* 1632 * EL250804: Testing if board APCI3120 have the new Quartz or if it 1633 * is an APCI3001 and calculate the time value to set in the timer 1634 */ 1635 if ((us_TmpValue & 0x00B0) == 0x00B0 1636 || !strcmp(this_board->pc_DriverName, "apci3001")) { 1637 /* Calculate the time value to set in the timer */ 1638 ui_Timervalue2 = ui_Timervalue2 / 50; 1639 } else { 1640 /* Calculate the time value to set in the timer */ 1641 ui_Timervalue2 = ui_Timervalue2 / 70; 1642 } 1643 1644 /* Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) */ 1645 devpriv->us_OutputRegister = 1646 devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2; 1647 outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS); 1648 1649 /* Disable TIMER Interrupt */ 1650 devpriv->b_ModeSelectRegister = 1651 devpriv-> 1652 b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF; 1653 1654 /* Disable Eoc and Eos Interrupts */ 1655 devpriv->b_ModeSelectRegister = 1656 devpriv-> 1657 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT & 1658 APCI3120_DISABLE_EOS_INT; 1659 outb(devpriv->b_ModeSelectRegister, 1660 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 1661 if (data[0] == APCI3120_TIMER) { /* initialize timer */ 1662 /* Set the Timer 2 in mode 2(Timer) */ 1663 devpriv->b_TimerSelectMode = 1664 (devpriv-> 1665 b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2; 1666 outb(devpriv->b_TimerSelectMode, 1667 devpriv->iobase + APCI3120_TIMER_CRT1); 1668 1669 /* 1670 * Configure the timer 2 for writing the LOW unsigned short of timer 1671 * is Delay value You must make a b_tmp variable with 1672 * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 1673 * you can set the digital output and configure the timer 2,and if 1674 * you don't make this, digital output are erase (Set to 0) 1675 */ 1676 1677 /* Writing LOW unsigned short */ 1678 b_Tmp = ((devpriv-> 1679 b_DigitalOutputRegister) & 0xF0) | 1680 APCI3120_SELECT_TIMER_2_LOW_WORD; 1681 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1682 outw(ui_Timervalue2 & 0xffff, 1683 devpriv->iobase + APCI3120_TIMER_VALUE); 1684 1685 /* Writing HIGH unsigned short */ 1686 b_Tmp = ((devpriv-> 1687 b_DigitalOutputRegister) & 0xF0) | 1688 APCI3120_SELECT_TIMER_2_HIGH_WORD; 1689 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1690 outw((ui_Timervalue2 >> 16) & 0xffff, 1691 devpriv->iobase + APCI3120_TIMER_VALUE); 1692 /* timer2 in Timer mode enabled */ 1693 devpriv->b_Timer2Mode = APCI3120_TIMER; 1694 1695 } else { /* Initialize Watch dog */ 1696 1697 /* Set the Timer 2 in mode 5(Watchdog) */ 1698 devpriv->b_TimerSelectMode = 1699 (devpriv-> 1700 b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5; 1701 outb(devpriv->b_TimerSelectMode, 1702 devpriv->iobase + APCI3120_TIMER_CRT1); 1703 1704 /* 1705 * Configure the timer 2 for writing the LOW unsigned short of timer 1706 * is Delay value You must make a b_tmp variable with 1707 * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 1708 * you can set the digital output and configure the timer 2,and if 1709 * you don't make this, digital output are erase (Set to 0) 1710 */ 1711 1712 /* Writing LOW unsigned short */ 1713 b_Tmp = ((devpriv-> 1714 b_DigitalOutputRegister) & 0xF0) | 1715 APCI3120_SELECT_TIMER_2_LOW_WORD; 1716 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1717 outw(ui_Timervalue2 & 0xffff, 1718 devpriv->iobase + APCI3120_TIMER_VALUE); 1719 1720 /* Writing HIGH unsigned short */ 1721 b_Tmp = ((devpriv-> 1722 b_DigitalOutputRegister) & 0xF0) | 1723 APCI3120_SELECT_TIMER_2_HIGH_WORD; 1724 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1725 1726 outw((ui_Timervalue2 >> 16) & 0xffff, 1727 devpriv->iobase + APCI3120_TIMER_VALUE); 1728 /* watchdog enabled */ 1729 devpriv->b_Timer2Mode = APCI3120_WATCHDOG; 1730 1731 } 1732 1733 return insn->n; 1734 1735} 1736 1737/* 1738 * To start and stop the timer 1739 * 1740 * data[0] = 1 (start) 1741 * = 0 (stop) 1742 * = 2 (write new value) 1743 * data[1] = new value 1744 * 1745 * devpriv->b_Timer2Mode = 0 DISABLE 1746 * = 1 Timer 1747 * = 2 Watch dog 1748 */ 1749static int apci3120_write_insn_timer(struct comedi_device *dev, 1750 struct comedi_subdevice *s, 1751 struct comedi_insn *insn, 1752 unsigned int *data) 1753{ 1754 const struct addi_board *this_board = dev->board_ptr; 1755 struct addi_private *devpriv = dev->private; 1756 unsigned int ui_Timervalue2 = 0; 1757 unsigned short us_TmpValue; 1758 unsigned char b_Tmp; 1759 1760 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) 1761 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { 1762 dev_err(dev->class_dev, "timer2 not configured\n"); 1763 return -EINVAL; 1764 } 1765 1766 if (data[0] == 2) { /* write new value */ 1767 if (devpriv->b_Timer2Mode != APCI3120_TIMER) { 1768 dev_err(dev->class_dev, 1769 "timer2 not configured in TIMER MODE\n"); 1770 return -EINVAL; 1771 } 1772 1773 if (data[1]) 1774 ui_Timervalue2 = data[1]; 1775 else 1776 ui_Timervalue2 = 0; 1777 } 1778 1779 switch (data[0]) { 1780 case APCI3120_START: 1781 1782 /* Reset FC_TIMER BIT */ 1783 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); 1784 if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */ 1785 /* Enable Timer */ 1786 devpriv->b_ModeSelectRegister = 1787 devpriv->b_ModeSelectRegister & 0x0B; 1788 } else { /* start watch dog */ 1789 /* Enable WatchDog */ 1790 devpriv->b_ModeSelectRegister = 1791 (devpriv-> 1792 b_ModeSelectRegister & 0x0B) | 1793 APCI3120_ENABLE_WATCHDOG; 1794 } 1795 1796 /* enable disable interrupt */ 1797 if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) { 1798 1799 devpriv->b_ModeSelectRegister = 1800 devpriv-> 1801 b_ModeSelectRegister | 1802 APCI3120_ENABLE_TIMER_INT; 1803 /* save the task structure to pass info to user */ 1804 devpriv->tsk_Current = current; 1805 } else { 1806 1807 devpriv->b_ModeSelectRegister = 1808 devpriv-> 1809 b_ModeSelectRegister & 1810 APCI3120_DISABLE_TIMER_INT; 1811 } 1812 outb(devpriv->b_ModeSelectRegister, 1813 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 1814 1815 if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */ 1816 /* For Timer mode is Gate2 must be activated timer started */ 1817 devpriv->us_OutputRegister = 1818 devpriv-> 1819 us_OutputRegister | APCI3120_ENABLE_TIMER2; 1820 outw(devpriv->us_OutputRegister, 1821 devpriv->iobase + APCI3120_WR_ADDRESS); 1822 } 1823 1824 break; 1825 1826 case APCI3120_STOP: 1827 if (devpriv->b_Timer2Mode == APCI3120_TIMER) { 1828 /* Disable timer */ 1829 devpriv->b_ModeSelectRegister = 1830 devpriv-> 1831 b_ModeSelectRegister & 1832 APCI3120_DISABLE_TIMER_COUNTER; 1833 } else { 1834 /* Disable WatchDog */ 1835 devpriv->b_ModeSelectRegister = 1836 devpriv-> 1837 b_ModeSelectRegister & 1838 APCI3120_DISABLE_WATCHDOG; 1839 } 1840 /* Disable timer interrupt */ 1841 devpriv->b_ModeSelectRegister = 1842 devpriv-> 1843 b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; 1844 1845 /* Write above states to register */ 1846 outb(devpriv->b_ModeSelectRegister, 1847 devpriv->iobase + APCI3120_WRITE_MODE_SELECT); 1848 1849 /* Reset Gate 2 */ 1850 devpriv->us_OutputRegister = 1851 devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT; 1852 outw(devpriv->us_OutputRegister, 1853 devpriv->iobase + APCI3120_WR_ADDRESS); 1854 1855 /* Reset FC_TIMER BIT */ 1856 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); 1857 1858 break; 1859 1860 case 2: /* write new value to Timer */ 1861 if (devpriv->b_Timer2Mode != APCI3120_TIMER) { 1862 dev_err(dev->class_dev, 1863 "timer2 not configured in TIMER MODE\n"); 1864 return -EINVAL; 1865 } 1866 us_TmpValue = 1867 (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS); 1868 1869 /* 1870 * EL250804: Testing if board APCI3120 have the new Quartz or if it 1871 * is an APCI3001 and calculate the time value to set in the timer 1872 */ 1873 if ((us_TmpValue & 0x00B0) == 0x00B0 1874 || !strcmp(this_board->pc_DriverName, "apci3001")) { 1875 /* Calculate the time value to set in the timer */ 1876 ui_Timervalue2 = ui_Timervalue2 / 50; 1877 } else { 1878 /* Calculate the time value to set in the timer */ 1879 ui_Timervalue2 = ui_Timervalue2 / 70; 1880 } 1881 /* Writing LOW unsigned short */ 1882 b_Tmp = ((devpriv-> 1883 b_DigitalOutputRegister) & 0xF0) | 1884 APCI3120_SELECT_TIMER_2_LOW_WORD; 1885 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1886 1887 outw(ui_Timervalue2 & 0xffff, 1888 devpriv->iobase + APCI3120_TIMER_VALUE); 1889 1890 /* Writing HIGH unsigned short */ 1891 b_Tmp = ((devpriv-> 1892 b_DigitalOutputRegister) & 0xF0) | 1893 APCI3120_SELECT_TIMER_2_HIGH_WORD; 1894 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1895 1896 outw((ui_Timervalue2 >> 16) & 0xffff, 1897 devpriv->iobase + APCI3120_TIMER_VALUE); 1898 1899 break; 1900 default: 1901 return -EINVAL; /* Not a valid input */ 1902 } 1903 1904 return insn->n; 1905} 1906 1907/* 1908 * Read the Timer value 1909 * 1910 * for Timer: data[0]= Timer constant 1911 * 1912 * for watchdog: data[0] = 0 (still running) 1913 * = 1 (run down) 1914 */ 1915static int apci3120_read_insn_timer(struct comedi_device *dev, 1916 struct comedi_subdevice *s, 1917 struct comedi_insn *insn, 1918 unsigned int *data) 1919{ 1920 struct addi_private *devpriv = dev->private; 1921 unsigned char b_Tmp; 1922 unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue; 1923 1924 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) 1925 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { 1926 dev_err(dev->class_dev, "timer2 not configured\n"); 1927 } 1928 if (devpriv->b_Timer2Mode == APCI3120_TIMER) { 1929 1930 /* Read the LOW unsigned short of Timer 2 register */ 1931 b_Tmp = ((devpriv-> 1932 b_DigitalOutputRegister) & 0xF0) | 1933 APCI3120_SELECT_TIMER_2_LOW_WORD; 1934 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1935 1936 us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE); 1937 1938 /* Read the HIGH unsigned short of Timer 2 register */ 1939 b_Tmp = ((devpriv-> 1940 b_DigitalOutputRegister) & 0xF0) | 1941 APCI3120_SELECT_TIMER_2_HIGH_WORD; 1942 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); 1943 1944 us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE); 1945 1946 /* combining both words */ 1947 data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16)); 1948 1949 } else { /* Read watch dog status */ 1950 1951 us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS); 1952 us_StatusValue = 1953 ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1; 1954 if (us_StatusValue == 1) { 1955 /* RESET FC_TIMER BIT */ 1956 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); 1957 } 1958 data[0] = us_StatusValue; /* when data[0] = 1 then the watch dog has rundown */ 1959 } 1960 return insn->n; 1961} 1962 1963static int apci3120_di_insn_bits(struct comedi_device *dev, 1964 struct comedi_subdevice *s, 1965 struct comedi_insn *insn, 1966 unsigned int *data) 1967{ 1968 struct addi_private *devpriv = dev->private; 1969 unsigned int val; 1970 1971 /* the input channels are bits 11:8 of the status reg */ 1972 val = inw(devpriv->iobase + APCI3120_RD_STATUS); 1973 data[1] = (val >> 8) & 0xf; 1974 1975 return insn->n; 1976} 1977 1978static int apci3120_do_insn_bits(struct comedi_device *dev, 1979 struct comedi_subdevice *s, 1980 struct comedi_insn *insn, 1981 unsigned int *data) 1982{ 1983 struct addi_private *devpriv = dev->private; 1984 1985 if (comedi_dio_update_state(s, data)) { 1986 /* The do channels are bits 7:4 of the do register */ 1987 devpriv->b_DigitalOutputRegister = s->state << 4; 1988 1989 outb(devpriv->b_DigitalOutputRegister, 1990 devpriv->iobase + APCI3120_DIGITAL_OUTPUT); 1991 } 1992 1993 data[1] = s->state; 1994 1995 return insn->n; 1996} 1997 1998static int apci3120_ao_insn_write(struct comedi_device *dev, 1999 struct comedi_subdevice *s, 2000 struct comedi_insn *insn, 2001 unsigned int *data) 2002{ 2003 struct addi_private *devpriv = dev->private; 2004 unsigned int ui_Range, ui_Channel; 2005 unsigned short us_TmpValue; 2006 2007 ui_Range = CR_RANGE(insn->chanspec); 2008 ui_Channel = CR_CHAN(insn->chanspec); 2009 2010 if (ui_Range) { /* if 1 then unipolar */ 2011 2012 if (data[0] != 0) 2013 data[0] = 2014 ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 << 2015 13) | (data[0] + 8191)); 2016 else 2017 data[0] = 2018 ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 << 2019 13) | 8192); 2020 2021 } else { /* if 0 then bipolar */ 2022 data[0] = 2023 ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) | 2024 data[0]); 2025 2026 } 2027 2028 do { /* Waiting of DA_READY BIT */ 2029 us_TmpValue = 2030 ((unsigned short) inw(devpriv->iobase + 2031 APCI3120_RD_STATUS)) & 0x0001; 2032 } while (us_TmpValue != 0x0001); 2033 2034 if (ui_Channel <= 3) 2035 /* 2036 * for channel 0-3 out at the register 1 (wrDac1-8) data[i] 2037 * typecasted to ushort since word write is to be done 2038 */ 2039 outw((unsigned short) data[0], 2040 devpriv->iobase + APCI3120_ANALOG_OUTPUT_1); 2041 else 2042 /* 2043 * for channel 4-7 out at the register 2 (wrDac5-8) data[i] 2044 * typecasted to ushort since word write is to be done 2045 */ 2046 outw((unsigned short) data[0], 2047 devpriv->iobase + APCI3120_ANALOG_OUTPUT_2); 2048 2049 return insn->n; 2050} 2051