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 18You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20You should also find the complete GPL in the COPYING file accompanying this source code. 21 22@endverbatim 23*/ 24/*. 25 26 +-----------------------------------------------------------------------+ 27 | (C) ADDI-DATA GmbH DieselstraÃe 3 D-77833 Ottersweier | 28 +-----------------------------------------------------------------------+ 29 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | 30 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | 31 +-------------------------------+---------------------------------------+ 32 | Project : APCI-3501 | Compiler : GCC | 33 | Module name : hwdrv_apci3501.c| Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Access For APCI-3501 | 38 +-----------------------------------------------------------------------+ 39 | UPDATES | 40 +----------+-----------+------------------------------------------------+ 41 | Date | Author | Description of updates | 42 +----------+-----------+------------------------------------------------+ 43 | | | | 44 | | | | 45 | | | | 46 +----------+-----------+------------------------------------------------+ 47*/ 48 49/* 50+----------------------------------------------------------------------------+ 51| Included files | 52+----------------------------------------------------------------------------+ 53*/ 54#include "hwdrv_apci3501.h" 55 56/* 57+----------------------------------------------------------------------------+ 58| Function Name : int i_APCI3501_ReadDigitalInput | 59| (struct comedi_device *dev,struct comedi_subdevice *s, | 60| struct comedi_insn *insn,unsigned int *data) | 61+----------------------------------------------------------------------------+ 62| Task : Read value of the selected channel or port | 63+----------------------------------------------------------------------------+ 64| Input Parameters : struct comedi_device *dev : Driver handle | 65| unsigned int ui_NoOfChannels : No Of Channels To read | 66| unsigned int *data : Data Pointer to read status | 67+----------------------------------------------------------------------------+ 68| Output Parameters : -- | 69+----------------------------------------------------------------------------+ 70| Return Value : TRUE : No error occur | 71| : FALSE : Error occur. Return the error | 72| | 73+----------------------------------------------------------------------------+ 74*/ 75 76int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, 77 struct comedi_insn *insn, unsigned int *data) 78{ 79 unsigned int ui_Temp; 80 unsigned int ui_NoOfChannel; 81 ui_NoOfChannel = CR_CHAN(insn->chanspec); 82 ui_Temp = data[0]; 83 *data = inl(devpriv->iobase + APCI3501_DIGITAL_IP); 84 if (ui_Temp == 0) { 85 *data = (*data >> ui_NoOfChannel) & 0x1; 86 } /* if (ui_Temp==0) */ 87 else { 88 if (ui_Temp == 1) { 89 90 *data = *data & 0x3; 91 } /* if (ui_Temp==1) */ 92 else { 93 printk("\nSpecified channel not supported \n"); 94 } /* elseif (ui_Temp==1) */ 95 } /* elseif (ui_Temp==0) */ 96 return insn->n; 97} 98 99/* 100+----------------------------------------------------------------------------+ 101| Function Name : int i_APCI3501_ConfigDigitalOutput | 102| (struct comedi_device *dev,struct comedi_subdevice *s, | 103| struct comedi_insn *insn,unsigned int *data) | 104+----------------------------------------------------------------------------+ 105| Task : Configures The Digital Output Subdevice. | 106+----------------------------------------------------------------------------+ 107| Input Parameters : struct comedi_device *dev : Driver handle | 108| unsigned int *data : Data Pointer contains | 109| configuration parameters as below | 110| | 111| data[1] : 1 Enable VCC Interrupt | 112| 0 Disable VCC Interrupt | 113| data[2] : 1 Enable CC Interrupt | 114| 0 Disable CC Interrupt | 115| | 116+----------------------------------------------------------------------------+ 117| Output Parameters : -- | 118+----------------------------------------------------------------------------+ 119| Return Value : TRUE : No error occur | 120| : FALSE : Error occur. Return the error | 121| | 122+----------------------------------------------------------------------------+ 123*/ 124int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 125 struct comedi_insn *insn, unsigned int *data) 126{ 127 128 if ((data[0] != 0) && (data[0] != 1)) { 129 comedi_error(dev, 130 "Not a valid Data !!! ,Data should be 1 or 0\n"); 131 return -EINVAL; 132 } /* if ( (data[0]!=0) && (data[0]!=1) ) */ 133 if (data[0]) { 134 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; 135 } /* if (data[0]) */ 136 else { 137 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; 138 } /* else if (data[0]) */ 139 return insn->n; 140} 141 142/* 143+----------------------------------------------------------------------------+ 144| Function Name : int i_APCI3501_WriteDigitalOutput | 145| (struct comedi_device *dev,struct comedi_subdevice *s, | 146| struct comedi_insn *insn,unsigned int *data) | 147+----------------------------------------------------------------------------+ 148| Task : writes To the digital Output Subdevice | 149+----------------------------------------------------------------------------+ 150| Input Parameters : struct comedi_device *dev : Driver handle | 151| struct comedi_subdevice *s : Subdevice Pointer | 152| struct comedi_insn *insn : Insn Structure Pointer | 153| unsigned int *data : Data Pointer contains | 154| configuration parameters as below | 155| | 156+----------------------------------------------------------------------------+ 157| Output Parameters : -- | 158+----------------------------------------------------------------------------+ 159| Return Value : TRUE : No error occur | 160| : FALSE : Error occur. Return the error | 161| | 162+----------------------------------------------------------------------------+ 163*/ 164int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 165 struct comedi_insn *insn, unsigned int *data) 166{ 167 unsigned int ui_Temp, ui_Temp1; 168 unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ 169 if (devpriv->b_OutputMemoryStatus) { 170 ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP); 171 } /* if(devpriv->b_OutputMemoryStatus ) */ 172 else { 173 ui_Temp = 0; 174 } /* if(devpriv->b_OutputMemoryStatus ) */ 175 if (data[3] == 0) { 176 if (data[1] == 0) { 177 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; 178 outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP); 179 } /* if(data[1]==0) */ 180 else { 181 if (data[1] == 1) { 182 data[0] = (data[0] << (2 * data[2])) | ui_Temp; 183 outl(data[0], 184 devpriv->iobase + APCI3501_DIGITAL_OP); 185 } /* if(data[1]==1) */ 186 else { 187 printk("\nSpecified channel not supported\n"); 188 } /* else if(data[1]==1) */ 189 } /* elseif(data[1]==0) */ 190 } /* if(data[3]==0) */ 191 else { 192 if (data[3] == 1) { 193 if (data[1] == 0) { 194 data[0] = ~data[0] & 0x1; 195 ui_Temp1 = 1; 196 ui_Temp1 = ui_Temp1 << ui_NoOfChannel; 197 ui_Temp = ui_Temp | ui_Temp1; 198 data[0] = 199 (data[0] << ui_NoOfChannel) ^ 200 0xffffffff; 201 data[0] = data[0] & ui_Temp; 202 outl(data[0], 203 devpriv->iobase + APCI3501_DIGITAL_OP); 204 } /* if(data[1]==0) */ 205 else { 206 if (data[1] == 1) { 207 data[0] = ~data[0] & 0x3; 208 ui_Temp1 = 3; 209 ui_Temp1 = ui_Temp1 << 2 * data[2]; 210 ui_Temp = ui_Temp | ui_Temp1; 211 data[0] = 212 ((data[0] << (2 * 213 data[2])) ^ 214 0xffffffff) & ui_Temp; 215 outl(data[0], 216 devpriv->iobase + 217 APCI3501_DIGITAL_OP); 218 } /* if(data[1]==1) */ 219 else { 220 printk("\nSpecified channel not supported\n"); 221 } /* else if(data[1]==1) */ 222 } /* elseif(data[1]==0) */ 223 } /* if(data[3]==1); */ 224 else { 225 printk("\nSpecified functionality does not exist\n"); 226 return -EINVAL; 227 } /* if else data[3]==1) */ 228 } /* if else data[3]==0) */ 229 return insn->n; 230} 231 232/* 233+----------------------------------------------------------------------------+ 234| Function Name : int i_APCI3501_ReadDigitalOutput | 235| (struct comedi_device *dev,struct comedi_subdevice *s, | 236| struct comedi_insn *insn,unsigned int *data) | 237+----------------------------------------------------------------------------+ 238| Task : Read value of the selected channel or port | 239+----------------------------------------------------------------------------+ 240| Input Parameters : struct comedi_device *dev : Driver handle | 241| unsigned int ui_NoOfChannels : No Of Channels To read | 242| unsigned int *data : Data Pointer to read status | 243+----------------------------------------------------------------------------+ 244| Output Parameters : -- | 245+----------------------------------------------------------------------------+ 246| Return Value : TRUE : No error occur | 247| : FALSE : Error occur. Return the error | 248| | 249+----------------------------------------------------------------------------+ 250*/ 251int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 252 struct comedi_insn *insn, unsigned int *data) 253{ 254 unsigned int ui_Temp; 255 unsigned int ui_NoOfChannel; 256 257 ui_NoOfChannel = CR_CHAN(insn->chanspec); 258 ui_Temp = data[0]; 259 *data = inl(devpriv->iobase + APCI3501_DIGITAL_OP); 260 if (ui_Temp == 0) { 261 *data = (*data >> ui_NoOfChannel) & 0x1; 262 } /* if (ui_Temp==0) */ 263 else { 264 if (ui_Temp == 1) { 265 *data = *data & 0x3; 266 267 } /* if (ui_Temp==1) */ 268 else { 269 printk("\nSpecified channel not supported \n"); 270 } /* else if (ui_Temp==1) */ 271 } /* else if (ui_Temp==0) */ 272 return insn->n; 273} 274 275/* 276+----------------------------------------------------------------------------+ 277| Function Name : int i_APCI3501_ConfigAnalogOutput | 278| (struct comedi_device *dev,struct comedi_subdevice *s, | 279| struct comedi_insn *insn,unsigned int *data) | 280+----------------------------------------------------------------------------+ 281| Task : Configures The Analog Output Subdevice | 282+----------------------------------------------------------------------------+ 283| Input Parameters : struct comedi_device *dev : Driver handle | 284| struct comedi_subdevice *s : Subdevice Pointer | 285| struct comedi_insn *insn : Insn Structure Pointer | 286| unsigned int *data : Data Pointer contains | 287| configuration parameters as below | 288| | 289| data[0] : Voltage Mode | 290| 0:Mode 0 | 291| 1:Mode 1 | 292| | 293+----------------------------------------------------------------------------+ 294| Output Parameters : -- | 295+----------------------------------------------------------------------------+ 296| Return Value : TRUE : No error occur | 297| : FALSE : Error occur. Return the error | 298| | 299+----------------------------------------------------------------------------+ 300*/ 301int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s, 302 struct comedi_insn *insn, unsigned int *data) 303{ 304 outl(data[0], 305 devpriv->iobase + APCI3501_ANALOG_OUTPUT + 306 APCI3501_AO_VOLT_MODE); 307 308 if (data[0]) { 309 devpriv->b_InterruptMode = MODE1; 310 } else { 311 devpriv->b_InterruptMode = MODE0; 312 } 313 return insn->n; 314} 315 316/* 317+----------------------------------------------------------------------------+ 318| Function Name : int i_APCI3501_WriteAnalogOutput | 319| (struct comedi_device *dev,struct comedi_subdevice *s, | 320| struct comedi_insn *insn,unsigned int *data) | 321+----------------------------------------------------------------------------+ 322| Task : Writes To the Selected Anlog Output Channel | 323+----------------------------------------------------------------------------+ 324| Input Parameters : struct comedi_device *dev : Driver handle | 325| struct comedi_subdevice *s : Subdevice Pointer | 326| struct comedi_insn *insn : Insn Structure Pointer | 327| unsigned int *data : Data Pointer contains | 328| configuration parameters as below | 329| | 330| | 331+----------------------------------------------------------------------------+ 332| Output Parameters : -- | 333+----------------------------------------------------------------------------+ 334| Return Value : TRUE : No error occur | 335| : FALSE : Error occur. Return the error | 336| | 337+----------------------------------------------------------------------------+ 338*/ 339int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s, 340 struct comedi_insn *insn, unsigned int *data) 341{ 342 unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0; 343 344 ul_Channel_no = CR_CHAN(insn->chanspec); 345 346 if (devpriv->b_InterruptMode == MODE1) { 347 ul_Polarity = 0x80000000; 348 if ((*data < 0) || (*data > 16384)) { 349 printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); 350 } 351 352 } /* end if(devpriv->b_InterruptMode==MODE1) */ 353 else { 354 ul_Polarity = 0; 355 if ((*data < 0) || (*data > 8192)) { 356 printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); 357 } 358 359 } /* end else */ 360 361 if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) { 362 printk("\nIn WriteAnalogOutput :: Not Valid Channel\n"); 363 } /* end if((ul_Channel_no<0)||(ul_Channel_no>7)) */ 364 365 ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); 366 367 while (ul_DAC_Ready == 0) { 368 ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); 369 ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1; 370 } 371 372 if (ul_DAC_Ready) { 373/* Output the Value on the output channels. */ 374 ul_Command1 = 375 (unsigned int) ((unsigned int) (ul_Channel_no & 0xFF) | 376 (unsigned int) ((*data << 0x8) & 0x7FFFFF00L) | 377 (unsigned int) (ul_Polarity)); 378 outl(ul_Command1, 379 devpriv->iobase + APCI3501_ANALOG_OUTPUT + 380 APCI3501_AO_PROG); 381 } 382 383 return insn->n; 384} 385 386/* 387+----------------------------------------------------------------------------+ 388| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog | 389| (struct comedi_device *dev,struct comedi_subdevice *s, | 390| struct comedi_insn *insn,unsigned int *data) | 391+----------------------------------------------------------------------------+ 392| Task : Configures The Timer , Counter or Watchdog | 393+----------------------------------------------------------------------------+ 394| Input Parameters : struct comedi_device *dev : Driver handle | 395| unsigned int *data : Data Pointer contains | 396| configuration parameters as below | 397| | 398| data[0] : 0 Configure As Timer | 399| 1 Configure As Counter | 400| 2 Configure As Watchdog | 401| data[1] : 1 Enable Interrupt | 402| 0 Disable Interrupt | 403| data[2] : Time Unit | 404| data[3] : Reload Value | 405+----------------------------------------------------------------------------+ 406| Output Parameters : -- | 407+----------------------------------------------------------------------------+ 408| Return Value : TRUE : No error occur | 409| : FALSE : Error occur. Return the error | 410| | 411+----------------------------------------------------------------------------+ 412*/ 413int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev, 414 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) 415{ 416 unsigned int ul_Command1 = 0; 417 devpriv->tsk_Current = current; 418 if (data[0] == ADDIDATA_WATCHDOG) { 419 420 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; 421 /* Disable the watchdog */ 422 outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Wa */ 423 424 if (data[1] == 1) { 425 /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ 426 outl(0x02, 427 devpriv->iobase + APCI3501_WATCHDOG + 428 APCI3501_TCW_PROG); 429 } else { 430 outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Timer interrupt */ 431 } 432 433 /* Loading the Timebase value */ 434 outl(data[2], 435 devpriv->iobase + APCI3501_WATCHDOG + 436 APCI3501_TCW_TIMEBASE); 437 438 /* Loading the Reload value */ 439 outl(data[3], 440 devpriv->iobase + APCI3501_WATCHDOG + 441 APCI3501_TCW_RELOAD_VALUE); 442 /* Set the mode */ 443 ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL; /* e2->e0 */ 444 outl(ul_Command1, 445 devpriv->iobase + APCI3501_WATCHDOG + 446 APCI3501_TCW_PROG); 447 } /* end if(data[0]==ADDIDATA_WATCHDOG) */ 448 449 else if (data[0] == ADDIDATA_TIMER) { 450 /* First Stop The Timer */ 451 ul_Command1 = 452 inl(devpriv->iobase + APCI3501_WATCHDOG + 453 APCI3501_TCW_PROG); 454 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 455 outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* Stop The Timer */ 456 devpriv->b_TimerSelectMode = ADDIDATA_TIMER; 457 if (data[1] == 1) { 458 /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ 459 outl(0x02, 460 devpriv->iobase + APCI3501_WATCHDOG + 461 APCI3501_TCW_PROG); 462 } else { 463 outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Timer interrupt */ 464 } 465 466 /* Loading Timebase */ 467 outl(data[2], 468 devpriv->iobase + APCI3501_WATCHDOG + 469 APCI3501_TCW_TIMEBASE); 470 471 /* Loading the Reload value */ 472 outl(data[3], 473 devpriv->iobase + APCI3501_WATCHDOG + 474 APCI3501_TCW_RELOAD_VALUE); 475 476 /* printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); */ 477 ul_Command1 = 478 inl(devpriv->iobase + APCI3501_WATCHDOG + 479 APCI3501_TCW_PROG); 480 ul_Command1 = 481 (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; 482 outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* mode 2 */ 483 484 } /* end if(data[0]==ADDIDATA_TIMER) */ 485 486 return insn->n; 487} 488 489/* 490+----------------------------------------------------------------------------+ 491| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog | 492| (struct comedi_device *dev,struct comedi_subdevice *s, | 493| struct comedi_insn *insn,unsigned int *data) | 494+----------------------------------------------------------------------------+ 495| Task : Start / Stop The Selected Timer , Counter or Watchdog | 496+----------------------------------------------------------------------------+ 497| Input Parameters : struct comedi_device *dev : Driver handle | 498| unsigned int *data : Data Pointer contains | 499| configuration parameters as below | 500| | 501| data[0] : 0 Timer | 502| 1 Counter | 503| 2 Watchdog | | data[1] : 1 Start | 504| 0 Stop | 2 Trigger | 505+----------------------------------------------------------------------------+ 506| Output Parameters : -- | 507+----------------------------------------------------------------------------+ 508| Return Value : TRUE : No error occur | 509| : FALSE : Error occur. Return the error | 510| | 511+----------------------------------------------------------------------------+ 512*/ 513 514int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev, 515 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) 516{ 517 unsigned int ul_Command1 = 0; 518 int i_Temp; 519 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 520 521 if (data[1] == 1) { 522 ul_Command1 = 523 inl(devpriv->iobase + APCI3501_WATCHDOG + 524 APCI3501_TCW_PROG); 525 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; 526 /* Enable the Watchdog */ 527 outl(ul_Command1, 528 devpriv->iobase + APCI3501_WATCHDOG + 529 APCI3501_TCW_PROG); 530 } 531 532 else if (data[1] == 0) /* Stop The Watchdog */ 533 { 534 /* Stop The Watchdog */ 535 ul_Command1 = 536 inl(devpriv->iobase + APCI3501_WATCHDOG + 537 APCI3501_TCW_PROG); 538 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 539 outl(0x0, 540 devpriv->iobase + APCI3501_WATCHDOG + 541 APCI3501_TCW_PROG); 542 } else if (data[1] == 2) { 543 ul_Command1 = 544 inl(devpriv->iobase + APCI3501_WATCHDOG + 545 APCI3501_TCW_PROG); 546 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; 547 outl(ul_Command1, 548 devpriv->iobase + APCI3501_WATCHDOG + 549 APCI3501_TCW_PROG); 550 } /* if(data[1]==2) */ 551 } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */ 552 553 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 554 if (data[1] == 1) { 555 556 ul_Command1 = 557 inl(devpriv->iobase + APCI3501_WATCHDOG + 558 APCI3501_TCW_PROG); 559 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; 560 /* Enable the Timer */ 561 outl(ul_Command1, 562 devpriv->iobase + APCI3501_WATCHDOG + 563 APCI3501_TCW_PROG); 564 } else if (data[1] == 0) { 565 /* Stop The Timer */ 566 ul_Command1 = 567 inl(devpriv->iobase + APCI3501_WATCHDOG + 568 APCI3501_TCW_PROG); 569 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 570 outl(ul_Command1, 571 devpriv->iobase + APCI3501_WATCHDOG + 572 APCI3501_TCW_PROG); 573 } 574 575 else if (data[1] == 2) { 576 /* Trigger the Timer */ 577 ul_Command1 = 578 inl(devpriv->iobase + APCI3501_WATCHDOG + 579 APCI3501_TCW_PROG); 580 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; 581 outl(ul_Command1, 582 devpriv->iobase + APCI3501_WATCHDOG + 583 APCI3501_TCW_PROG); 584 } 585 586 } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ 587 i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG + 588 APCI3501_TCW_TRIG_STATUS) & 0x1; 589 return insn->n; 590} 591 592/* 593+----------------------------------------------------------------------------+ 594| Function Name : int i_APCI3501_ReadTimerCounterWatchdog | 595| (struct comedi_device *dev,struct comedi_subdevice *s, | 596| struct comedi_insn *insn,unsigned int *data) | 597+----------------------------------------------------------------------------+ 598| Task : Read The Selected Timer , Counter or Watchdog | 599+----------------------------------------------------------------------------+ 600| Input Parameters : struct comedi_device *dev : Driver handle | 601| unsigned int *data : Data Pointer contains | 602| configuration parameters as below | 603| | 604| data[0] : 0 Timer | 605| 1 Counter | 606| 2 Watchdog | | data[1] : Timer Counter Watchdog Number | 607+----------------------------------------------------------------------------+ 608| Output Parameters : -- | 609+----------------------------------------------------------------------------+ 610| Return Value : TRUE : No error occur | 611| : FALSE : Error occur. Return the error | 612| | 613+----------------------------------------------------------------------------+ 614*/ 615 616int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev, 617 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) 618{ 619 620 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 621 data[0] = 622 inl(devpriv->iobase + APCI3501_WATCHDOG + 623 APCI3501_TCW_TRIG_STATUS) & 0x1; 624 data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG); 625 } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */ 626 627 else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 628 data[0] = 629 inl(devpriv->iobase + APCI3501_WATCHDOG + 630 APCI3501_TCW_TRIG_STATUS) & 0x1; 631 data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG); 632 } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ 633 634 else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) 635 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) { 636 printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n"); 637 } 638 return insn->n; 639} 640 641/* 642+----------------------------------------------------------------------------+ 643| Function Name : int i_APCI3501_Reset(struct comedi_device *dev) | 644| | 645+----------------------------------------------------------------------------+ 646| Task :Resets the registers of the card | 647+----------------------------------------------------------------------------+ 648| Input Parameters : | 649+----------------------------------------------------------------------------+ 650| Output Parameters : -- | 651+----------------------------------------------------------------------------+ 652| Return Value : | 653| | 654+----------------------------------------------------------------------------+ 655*/ 656 657int i_APCI3501_Reset(struct comedi_device *dev) 658{ 659 int i_Count = 0, i_temp = 0; 660 unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0; 661 outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP); 662 outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT + 663 APCI3501_AO_VOLT_MODE); 664 665 ul_Polarity = 0x80000000; 666 667 for (i_Count = 0; i_Count <= 7; i_Count++) { 668 ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); 669 670 while (ul_DAC_Ready == 0) { 671 ul_DAC_Ready = 672 inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); 673 ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1; 674 } 675 676 if (ul_DAC_Ready) { 677 /* Output the Value on the output channels. */ 678 ul_Command1 = 679 (unsigned int) ((unsigned int) (i_Count & 0xFF) | 680 (unsigned int) ((i_temp << 0x8) & 0x7FFFFF00L) | 681 (unsigned int) (ul_Polarity)); 682 outl(ul_Command1, 683 devpriv->iobase + APCI3501_ANALOG_OUTPUT + 684 APCI3501_AO_PROG); 685 } 686 } 687 688 return 0; 689} 690 691/* 692+----------------------------------------------------------------------------+ 693| Function Name : static void v_APCI3501_Interrupt | 694| (int irq , void *d) | 695+----------------------------------------------------------------------------+ 696| Task : Interrupt processing Routine | 697+----------------------------------------------------------------------------+ 698| Input Parameters : int irq : irq number | 699| void *d : void pointer | 700+----------------------------------------------------------------------------+ 701| Output Parameters : -- | 702+----------------------------------------------------------------------------+ 703| Return Value : TRUE : No error occur | 704| : FALSE : Error occur. Return the error | 705| | 706+----------------------------------------------------------------------------+ 707*/ 708void v_APCI3501_Interrupt(int irq, void *d) 709{ 710 int i_temp; 711 struct comedi_device *dev = d; 712 unsigned int ui_Timer_AOWatchdog; 713 unsigned long ul_Command1; 714 /* Disable Interrupt */ 715 ul_Command1 = 716 inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); 717 718 ul_Command1 = (ul_Command1 & 0xFFFFF9FDul); 719 outl(ul_Command1, 720 devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); 721 722 ui_Timer_AOWatchdog = 723 inl(devpriv->iobase + APCI3501_WATCHDOG + 724 APCI3501_TCW_IRQ) & 0x1; 725 726 if ((!ui_Timer_AOWatchdog)) { 727 comedi_error(dev, "IRQ from unknown source"); 728 return; 729 } 730 731/* 732* Enable Interrupt Send a signal to from kernel to user space 733*/ 734 send_sig(SIGIO, devpriv->tsk_Current, 0); 735 ul_Command1 = 736 inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); 737 ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); 738 outl(ul_Command1, 739 devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); 740 i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG + 741 APCI3501_TCW_TRIG_STATUS) & 0x1; 742 return; 743} 744