hwdrv_apci1564.c revision 74b894e56abcb2403894b268100773f4aabe1999
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 shoud 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-1564 | Compiler : GCC | 33 | Module name : hwdrv_apci1564.c| Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Acces For APCI-1564 | 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 55#include <linux/delay.h> 56#include "hwdrv_apci1564.h" 57 58//Global variables 59UINT ui_InterruptStatus_1564 = 0; 60UINT ui_InterruptData, ui_Type; 61 62/* 63+----------------------------------------------------------------------------+ 64| Function Name : int i_APCI1564_ConfigDigitalInput | 65| (struct comedi_device *dev,struct comedi_subdevice *s, | 66| struct comedi_insn *insn,unsigned int *data) | 67+----------------------------------------------------------------------------+ 68| Task : Configures the digital input Subdevice | 69+----------------------------------------------------------------------------+ 70| Input Parameters : struct comedi_device *dev : Driver handle | 71| unsigned int *data : Data Pointer contains | 72| configuration parameters as below | 73| | 74| data[0] : 1 Enable Digital Input Interrupt | 75| 0 Disable Digital Input Interrupt | 76| data[1] : 0 ADDIDATA Interrupt OR LOGIC | 77| : 1 ADDIDATA Interrupt AND LOGIC | 78| data[2] : Interrupt mask for the mode 1 | 79| data[3] : Interrupt mask for the mode 2 | 80| | 81+----------------------------------------------------------------------------+ 82| Output Parameters : -- | 83+----------------------------------------------------------------------------+ 84| Return Value : TRUE : No error occur | 85| : FALSE : Error occur. Return the error | 86| | 87+----------------------------------------------------------------------------+ 88*/ 89int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 90 struct comedi_insn * insn, unsigned int * data) 91{ 92 devpriv->tsk_Current = current; 93 /*******************************/ 94 /* Set the digital input logic */ 95 /*******************************/ 96 if (data[0] == ADDIDATA_ENABLE) { 97 data[2] = data[2] << 4; 98 data[3] = data[3] << 4; 99 outl(data[2], 100 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 101 APCI1564_DIGITAL_IP_INTERRUPT_MODE1); 102 outl(data[3], 103 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 104 APCI1564_DIGITAL_IP_INTERRUPT_MODE2); 105 if (data[1] == ADDIDATA_OR) { 106 outl(0x4, 107 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 108 APCI1564_DIGITAL_IP_IRQ); 109 } // if (data[1] == ADDIDATA_OR) 110 else { 111 outl(0x6, 112 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 113 APCI1564_DIGITAL_IP_IRQ); 114 } // else if (data[1] == ADDIDATA_OR) 115 } // if (data[0] == ADDIDATA_ENABLE) 116 else { 117 outl(0x0, 118 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 119 APCI1564_DIGITAL_IP_INTERRUPT_MODE1); 120 outl(0x0, 121 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 122 APCI1564_DIGITAL_IP_INTERRUPT_MODE2); 123 outl(0x0, 124 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 125 APCI1564_DIGITAL_IP_IRQ); 126 } // else if (data[0] == ADDIDATA_ENABLE) 127 128 return insn->n; 129} 130 131/* 132+----------------------------------------------------------------------------+ 133| Function Name : int i_APCI1564_Read1DigitalInput | 134| (struct comedi_device *dev,struct comedi_subdevice *s, | 135| struct comedi_insn *insn,unsigned int *data) | 136+----------------------------------------------------------------------------+ 137| Task : Return the status of the digital input | 138+----------------------------------------------------------------------------+ 139| Input Parameters : struct comedi_device *dev : Driver handle | 140| UINT ui_Channel : Channel number to read | 141| unsigned int *data : Data Pointer to read status | 142+----------------------------------------------------------------------------+ 143| Output Parameters : -- | 144+----------------------------------------------------------------------------+ 145| Return Value : TRUE : No error occur | 146| : FALSE : Error occur. Return the error | 147| | 148+----------------------------------------------------------------------------+ 149*/ 150int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 151 struct comedi_insn * insn, unsigned int * data) 152{ 153 UINT ui_TmpValue = 0; 154 UINT ui_Channel; 155 156 ui_Channel = CR_CHAN(insn->chanspec); 157 if (ui_Channel >= 0 && ui_Channel <= 31) { 158 ui_TmpValue = 159 (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); 160 // since only 1 channel reqd to bring it to last bit it is rotated 161 // 8 +(chan - 1) times then ANDed with 1 for last bit. 162 *data = (ui_TmpValue >> ui_Channel) & 0x1; 163 } // if (ui_Channel >= 0 && ui_Channel <=31) 164 else { 165 comedi_error(dev, "Not a valid channel number !!! \n"); 166 return -EINVAL; // "sorry channel spec wrong " 167 } //else if (ui_Channel >= 0 && ui_Channel <=31) 168 return insn->n; 169} 170 171/* 172+----------------------------------------------------------------------------+ 173| Function Name : int i_APCI1564_ReadMoreDigitalInput | 174| (struct comedi_device *dev,struct comedi_subdevice *s, | 175| struct comedi_insn *insn,unsigned int *data) | 176+----------------------------------------------------------------------------+ 177| Task : Return the status of the Requested digital inputs | 178+----------------------------------------------------------------------------+ 179| Input Parameters : struct comedi_device *dev : Driver handle | 180| UINT ui_NoOfChannels : No Of Channels To be Read | 181| UINT *data : Data Pointer to read status | 182+----------------------------------------------------------------------------+ 183| Output Parameters : -- | 184+----------------------------------------------------------------------------+ 185| Return Value : TRUE : No error occur | 186| : FALSE : Error occur. Return the error | 187| | 188+----------------------------------------------------------------------------+ 189*/ 190int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 191 struct comedi_insn * insn, unsigned int * data) 192{ 193 UINT ui_PortValue = data[0]; 194 UINT ui_Mask = 0; 195 UINT ui_NoOfChannels; 196 197 ui_NoOfChannels = CR_CHAN(insn->chanspec); 198 if (data[1] == 0) { 199 *data = (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); 200 switch (ui_NoOfChannels) { 201 case 2: 202 ui_Mask = 3; 203 *data = (*data >> (2 * ui_PortValue)) & ui_Mask; 204 break; 205 case 4: 206 ui_Mask = 15; 207 *data = (*data >> (4 * ui_PortValue)) & ui_Mask; 208 break; 209 case 8: 210 ui_Mask = 255; 211 *data = (*data >> (8 * ui_PortValue)) & ui_Mask; 212 break; 213 case 16: 214 ui_Mask = 65535; 215 *data = (*data >> (16 * ui_PortValue)) & ui_Mask; 216 break; 217 case 31: 218 break; 219 default: 220 comedi_error(dev, "Not a valid Channel number !!!\n"); 221 return -EINVAL; // "sorry channel spec wrong " 222 break; 223 } // switch (ui_NoOfChannels) 224 } // if (data[1]==0) 225 else { 226 if (data[1] == 1) { 227 *data = ui_InterruptStatus_1564; 228 } // if (data[1]==1) 229 } // else if (data[1]==0) 230 return insn->n; 231} 232 233/* 234+----------------------------------------------------------------------------+ 235| Function Name : int i_APCI1564_ConfigDigitalOutput | 236| (struct comedi_device *dev,struct comedi_subdevice *s, | 237| struct comedi_insn *insn,unsigned int *data) | 238+----------------------------------------------------------------------------+ 239| Task : Configures The Digital Output Subdevice. | 240+----------------------------------------------------------------------------+ 241| Input Parameters : struct comedi_device *dev : Driver handle | 242| UINT *data : Data Pointer contains | 243| configuration parameters as below | 244| | 245| data[1] : 1 Enable VCC Interrupt | 246| 0 Disable VCC Interrupt | 247| data[2] : 1 Enable CC Interrupt | 248| 0 Disable CC Interrupt | 249| | 250+----------------------------------------------------------------------------+ 251| Output Parameters : -- | 252+----------------------------------------------------------------------------+ 253| Return Value : TRUE : No error occur | 254| : FALSE : Error occur. Return the error | 255| | 256+----------------------------------------------------------------------------+ 257*/ 258int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, 259 struct comedi_insn * insn, unsigned int * data) 260{ 261 ULONG ul_Command = 0; 262 263 if ((data[0] != 0) && (data[0] != 1)) { 264 comedi_error(dev, 265 "Not a valid Data !!! ,Data should be 1 or 0\n"); 266 return -EINVAL; 267 } // if ((data[0]!=0) && (data[0]!=1)) 268 if (data[0]) { 269 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; 270 } // if (data[0]) 271 else { 272 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; 273 } // else if (data[0]) 274 if (data[1] == ADDIDATA_ENABLE) { 275 ul_Command = ul_Command | 0x1; 276 } // if (data[1] == ADDIDATA_ENABLE) 277 else { 278 ul_Command = ul_Command & 0xFFFFFFFE; 279 } // else if (data[1] == ADDIDATA_ENABLE) 280 if (data[2] == ADDIDATA_ENABLE) { 281 ul_Command = ul_Command | 0x2; 282 } // if (data[2] == ADDIDATA_ENABLE) 283 else { 284 ul_Command = ul_Command & 0xFFFFFFFD; 285 } // else if (data[2] == ADDIDATA_ENABLE) 286 outl(ul_Command, 287 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 288 APCI1564_DIGITAL_OP_INTERRUPT); 289 ui_InterruptData = 290 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 291 APCI1564_DIGITAL_OP_INTERRUPT); 292 devpriv->tsk_Current = current; 293 return insn->n; 294} 295 296/* 297+----------------------------------------------------------------------------+ 298| Function Name : int i_APCI1564_WriteDigitalOutput | 299| (struct comedi_device *dev,struct comedi_subdevice *s, | 300| struct comedi_insn *insn,unsigned int *data) | 301+----------------------------------------------------------------------------+ 302| Task : Writes port value To the selected port | 303+----------------------------------------------------------------------------+ 304| Input Parameters : struct comedi_device *dev : Driver handle | 305| UINT ui_NoOfChannels : No Of Channels To Write | 306| UINT *data : Data Pointer to read status | 307+----------------------------------------------------------------------------+ 308| Output Parameters : -- | 309+----------------------------------------------------------------------------+ 310| Return Value : TRUE : No error occur | 311| : FALSE : Error occur. Return the error | 312| | 313+----------------------------------------------------------------------------+ 314*/ 315int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, 316 struct comedi_insn * insn, unsigned int * data) 317{ 318 UINT ui_Temp, ui_Temp1; 319 UINT ui_NoOfChannel; 320 321 ui_NoOfChannel = CR_CHAN(insn->chanspec); 322 if (devpriv->b_OutputMemoryStatus) { 323 ui_Temp = 324 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 325 APCI1564_DIGITAL_OP_RW); 326 } // if (devpriv->b_OutputMemoryStatus ) 327 else { 328 ui_Temp = 0; 329 } // else if (devpriv->b_OutputMemoryStatus ) 330 if (data[3] == 0) { 331 if (data[1] == 0) { 332 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; 333 outl(data[0], 334 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 335 APCI1564_DIGITAL_OP_RW); 336 } // if (data[1]==0) 337 else { 338 if (data[1] == 1) { 339 switch (ui_NoOfChannel) { 340 case 2: 341 data[0] = 342 (data[0] << (2 * 343 data[2])) | ui_Temp; 344 break; 345 case 4: 346 data[0] = 347 (data[0] << (4 * 348 data[2])) | ui_Temp; 349 break; 350 case 8: 351 data[0] = 352 (data[0] << (8 * 353 data[2])) | ui_Temp; 354 break; 355 case 16: 356 data[0] = 357 (data[0] << (16 * 358 data[2])) | ui_Temp; 359 break; 360 case 31: 361 data[0] = data[0] | ui_Temp; 362 break; 363 default: 364 comedi_error(dev, " chan spec wrong"); 365 return -EINVAL; // "sorry channel spec wrong " 366 } // switch (ui_NoOfChannels) 367 outl(data[0], 368 devpriv->i_IobaseAmcc + 369 APCI1564_DIGITAL_OP + 370 APCI1564_DIGITAL_OP_RW); 371 } // if (data[1]==1) 372 else { 373 printk("\nSpecified channel not supported\n"); 374 } // else if (data[1]==1) 375 } // else if (data[1]==0) 376 } //if(data[3]==0) 377 else { 378 if (data[3] == 1) { 379 if (data[1] == 0) { 380 data[0] = ~data[0] & 0x1; 381 ui_Temp1 = 1; 382 ui_Temp1 = ui_Temp1 << ui_NoOfChannel; 383 ui_Temp = ui_Temp | ui_Temp1; 384 data[0] = 385 (data[0] << ui_NoOfChannel) ^ 386 0xffffffff; 387 data[0] = data[0] & ui_Temp; 388 outl(data[0], 389 devpriv->i_IobaseAmcc + 390 APCI1564_DIGITAL_OP + 391 APCI1564_DIGITAL_OP_RW); 392 } // if (data[1]==0) 393 else { 394 if (data[1] == 1) { 395 switch (ui_NoOfChannel) { 396 case 2: 397 data[0] = ~data[0] & 0x3; 398 ui_Temp1 = 3; 399 ui_Temp1 = 400 ui_Temp1 << 2 * data[2]; 401 ui_Temp = ui_Temp | ui_Temp1; 402 data[0] = 403 ((data[0] << (2 * 404 data 405 [2])) ^ 406 0xffffffff) & ui_Temp; 407 break; 408 case 4: 409 data[0] = ~data[0] & 0xf; 410 ui_Temp1 = 15; 411 ui_Temp1 = 412 ui_Temp1 << 4 * data[2]; 413 ui_Temp = ui_Temp | ui_Temp1; 414 data[0] = 415 ((data[0] << (4 * 416 data 417 [2])) ^ 418 0xffffffff) & ui_Temp; 419 break; 420 case 8: 421 data[0] = ~data[0] & 0xff; 422 ui_Temp1 = 255; 423 ui_Temp1 = 424 ui_Temp1 << 8 * data[2]; 425 ui_Temp = ui_Temp | ui_Temp1; 426 data[0] = 427 ((data[0] << (8 * 428 data 429 [2])) ^ 430 0xffffffff) & ui_Temp; 431 break; 432 case 16: 433 data[0] = ~data[0] & 0xffff; 434 ui_Temp1 = 65535; 435 ui_Temp1 = 436 ui_Temp1 << 16 * 437 data[2]; 438 ui_Temp = ui_Temp | ui_Temp1; 439 data[0] = 440 ((data[0] << (16 * 441 data 442 [2])) ^ 443 0xffffffff) & ui_Temp; 444 break; 445 case 31: 446 break; 447 default: 448 comedi_error(dev, 449 " chan spec wrong"); 450 return -EINVAL; // "sorry channel spec wrong " 451 } //switch(ui_NoOfChannels) 452 outl(data[0], 453 devpriv->i_IobaseAmcc + 454 APCI1564_DIGITAL_OP + 455 APCI1564_DIGITAL_OP_RW); 456 } // if (data[1]==1) 457 else { 458 printk("\nSpecified channel not supported\n"); 459 } // else if (data[1]==1) 460 } // else if (data[1]==0) 461 } // if (data[3]==1); 462 else { 463 printk("\nSpecified functionality does not exist\n"); 464 return -EINVAL; 465 } // else if (data[3]==1) 466 } // else if (data[3]==0) 467 return insn->n; 468} 469 470/* 471+----------------------------------------------------------------------------+ 472| Function Name : int i_APCI1564_ReadDigitalOutput | 473| (struct comedi_device *dev,struct comedi_subdevice *s, | 474| struct comedi_insn *insn,unsigned int *data) | 475+----------------------------------------------------------------------------+ 476| Task : Read value of the selected channel or port | 477+----------------------------------------------------------------------------+ 478| Input Parameters : struct comedi_device *dev : Driver handle | 479| UINT ui_NoOfChannels : No Of Channels To read | 480| UINT *data : Data Pointer to read status | 481+----------------------------------------------------------------------------+ 482| Output Parameters : -- | 483+----------------------------------------------------------------------------+ 484| Return Value : TRUE : No error occur | 485| : FALSE : Error occur. Return the error | 486| | 487+----------------------------------------------------------------------------+ 488*/ 489int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, 490 struct comedi_insn * insn, unsigned int * data) 491{ 492 UINT ui_Temp; 493 UINT ui_NoOfChannel; 494 495 ui_NoOfChannel = CR_CHAN(insn->chanspec); 496 ui_Temp = data[0]; 497 *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 498 APCI1564_DIGITAL_OP_RW); 499 if (ui_Temp == 0) { 500 *data = (*data >> ui_NoOfChannel) & 0x1; 501 } // if (ui_Temp==0) 502 else { 503 if (ui_Temp == 1) { 504 switch (ui_NoOfChannel) { 505 case 2: 506 *data = (*data >> (2 * data[1])) & 3; 507 break; 508 509 case 4: 510 *data = (*data >> (4 * data[1])) & 15; 511 break; 512 513 case 8: 514 *data = (*data >> (8 * data[1])) & 255; 515 break; 516 517 case 16: 518 *data = (*data >> (16 * data[1])) & 65535; 519 break; 520 521 case 31: 522 break; 523 524 default: 525 comedi_error(dev, " chan spec wrong"); 526 return -EINVAL; // "sorry channel spec wrong " 527 break; 528 } // switch(ui_NoOfChannels) 529 } // if (ui_Temp==1) 530 else { 531 printk("\nSpecified channel not supported \n"); 532 } // else if (ui_Temp==1) 533 } // else if (ui_Temp==0) 534 return insn->n; 535} 536 537/* 538+----------------------------------------------------------------------------+ 539| Function Name : int i_APCI1564_ConfigTimerCounterWatchdog | 540| (struct comedi_device *dev,struct comedi_subdevice *s, | 541| struct comedi_insn *insn,unsigned int *data) | 542+----------------------------------------------------------------------------+ 543| Task : Configures The Timer , Counter or Watchdog | 544+----------------------------------------------------------------------------+ 545| Input Parameters : struct comedi_device *dev : Driver handle | 546| UINT *data : Data Pointer contains | 547| configuration parameters as below | 548| | 549| data[0] : 0 Configure As Timer | 550| 1 Configure As Counter | 551| 2 Configure As Watchdog | 552| data[1] : 1 Enable Interrupt | 553| 0 Disable Interrupt | 554| data[2] : Time Unit | 555| data[3] : Reload Value | 556| data[4] : Timer Mode | 557| data[5] : Timer Counter Watchdog Number| 558 data[6] : Counter Direction 559+----------------------------------------------------------------------------+ 560| Output Parameters : -- | 561+----------------------------------------------------------------------------+ 562| Return Value : TRUE : No error occur | 563| : FALSE : Error occur. Return the error | 564| | 565+----------------------------------------------------------------------------+ 566*/ 567int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev, 568 struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) 569{ 570 ULONG ul_Command1 = 0; 571 devpriv->tsk_Current = current; 572 if (data[0] == ADDIDATA_WATCHDOG) { 573 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; 574 575 //Disable the watchdog 576 outl(0x0, 577 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + 578 APCI1564_TCW_PROG); 579 //Loading the Reload value 580 outl(data[3], 581 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + 582 APCI1564_TCW_RELOAD_VALUE); 583 } // if (data[0]==ADDIDATA_WATCHDOG) 584 else if (data[0] == ADDIDATA_TIMER) { 585 //First Stop The Timer 586 ul_Command1 = 587 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 588 APCI1564_TCW_PROG); 589 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 590 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Stop The Timer 591 592 devpriv->b_TimerSelectMode = ADDIDATA_TIMER; 593 if (data[1] == 1) { 594 outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES 595 outl(0x0, 596 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 597 APCI1564_DIGITAL_IP_IRQ); 598 outl(0x0, 599 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 600 APCI1564_DIGITAL_OP_IRQ); 601 outl(0x0, 602 devpriv->i_IobaseAmcc + 603 APCI1564_DIGITAL_OP_WATCHDOG + 604 APCI1564_TCW_IRQ); 605 outl(0x0, 606 devpriv->iobase + APCI1564_COUNTER1 + 607 APCI1564_TCW_IRQ); 608 outl(0x0, 609 devpriv->iobase + APCI1564_COUNTER2 + 610 APCI1564_TCW_IRQ); 611 outl(0x0, 612 devpriv->iobase + APCI1564_COUNTER3 + 613 APCI1564_TCW_IRQ); 614 outl(0x0, 615 devpriv->iobase + APCI1564_COUNTER4 + 616 APCI1564_TCW_IRQ); 617 } // if (data[1]==1) 618 else { 619 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //disable Timer interrupt 620 } // else if (data[1]==1) 621 622 // Loading Timebase 623 624 outl(data[2], 625 devpriv->i_IobaseAmcc + APCI1564_TIMER + 626 APCI1564_TCW_TIMEBASE); 627 628 //Loading the Reload value 629 outl(data[3], 630 devpriv->i_IobaseAmcc + APCI1564_TIMER + 631 APCI1564_TCW_RELOAD_VALUE); 632 633 ul_Command1 = 634 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 635 APCI1564_TCW_PROG); 636 ul_Command1 = 637 (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; 638 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //mode 2 639 } // else if (data[0]==ADDIDATA_TIMER) 640 else if (data[0] == ADDIDATA_COUNTER) { 641 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; 642 devpriv->b_ModeSelectRegister = data[5]; 643 644 //First Stop The Counter 645 ul_Command1 = 646 inl(devpriv->iobase + ((data[5] - 1) * 0x20) + 647 APCI1564_TCW_PROG); 648 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 649 outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); //Stop The Timer 650 651 /************************/ 652 /* Set the reload value */ 653 /************************/ 654 outl(data[3], 655 devpriv->iobase + ((data[5] - 1) * 0x20) + 656 APCI1564_TCW_RELOAD_VALUE); 657 658 /******************************/ 659 /* Set the mode : */ 660 /* - Disable the hardware */ 661 /* - Disable the counter mode */ 662 /* - Disable the warning */ 663 /* - Disable the reset */ 664 /* - Disable the timer mode */ 665 /* - Enable the counter mode */ 666 /******************************/ 667 ul_Command1 = 668 (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL | 669 (ULONG) ((ULONG) data[4] << 16UL); 670 outl(ul_Command1, 671 devpriv->iobase + ((data[5] - 1) * 0x20) + 672 APCI1564_TCW_PROG); 673 674 // Enable or Disable Interrupt 675 ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1); 676 outl(ul_Command1, 677 devpriv->iobase + ((data[5] - 1) * 0x20) + 678 APCI1564_TCW_PROG); 679 680 /*****************************/ 681 /* Set the Up/Down selection */ 682 /*****************************/ 683 ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18); 684 outl(ul_Command1, 685 devpriv->iobase + ((data[5] - 1) * 0x20) + 686 APCI1564_TCW_PROG); 687 } // else if (data[0]==ADDIDATA_COUNTER) 688 else { 689 printk(" Invalid subdevice."); 690 } // else if (data[0]==ADDIDATA_WATCHDOG) 691 692 return insn->n; 693} 694 695/* 696+----------------------------------------------------------------------------+ 697| Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog | 698| (struct comedi_device *dev,struct comedi_subdevice *s, | 699| struct comedi_insn *insn,unsigned int *data) | 700+----------------------------------------------------------------------------+ 701| Task : Start / Stop The Selected Timer , Counter or Watchdog | 702+----------------------------------------------------------------------------+ 703| Input Parameters : struct comedi_device *dev : Driver handle | 704| UINT *data : Data Pointer contains | 705| configuration parameters as below | 706| | 707| data[0] : 0 Timer | 708| 1 Counter | 709| 2 Watchdog | | data[1] : 1 Start | 710| 0 Stop | 711| 2 Trigger | 712| Clear (Only Counter) | 713+----------------------------------------------------------------------------+ 714| Output Parameters : -- | 715+----------------------------------------------------------------------------+ 716| Return Value : TRUE : No error occur | 717| : FALSE : Error occur. Return the error | 718| | 719+----------------------------------------------------------------------------+ 720*/ 721int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev, 722 struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) 723{ 724 ULONG ul_Command1 = 0; 725 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 726 switch (data[1]) { 727 case 0: //stop the watchdog 728 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); //disable the watchdog 729 break; 730 case 1: //start the watchdog 731 outl(0x0001, 732 devpriv->i_IobaseAmcc + 733 APCI1564_DIGITAL_OP_WATCHDOG + 734 APCI1564_TCW_PROG); 735 break; 736 case 2: //Software trigger 737 outl(0x0201, 738 devpriv->i_IobaseAmcc + 739 APCI1564_DIGITAL_OP_WATCHDOG + 740 APCI1564_TCW_PROG); 741 break; 742 default: 743 printk("\nSpecified functionality does not exist\n"); 744 return -EINVAL; 745 } // switch (data[1]) 746 } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) 747 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 748 if (data[1] == 1) { 749 ul_Command1 = 750 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 751 APCI1564_TCW_PROG); 752 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; 753 754 //Enable the Timer 755 outl(ul_Command1, 756 devpriv->i_IobaseAmcc + APCI1564_TIMER + 757 APCI1564_TCW_PROG); 758 } // if (data[1]==1) 759 else if (data[1] == 0) { 760 //Stop The Timer 761 762 ul_Command1 = 763 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 764 APCI1564_TCW_PROG); 765 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; 766 outl(ul_Command1, 767 devpriv->i_IobaseAmcc + APCI1564_TIMER + 768 APCI1564_TCW_PROG); 769 } // else if(data[1]==0) 770 } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) 771 if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { 772 ul_Command1 = 773 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - 774 1) * 0x20) + APCI1564_TCW_PROG); 775 if (data[1] == 1) { 776 //Start the Counter subdevice 777 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; 778 } // if (data[1] == 1) 779 else if (data[1] == 0) { 780 // Stops the Counter subdevice 781 ul_Command1 = 0; 782 783 } // else if (data[1] == 0) 784 else if (data[1] == 2) { 785 // Clears the Counter subdevice 786 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400; 787 } // else if (data[1] == 3) 788 outl(ul_Command1, 789 devpriv->iobase + ((devpriv->b_ModeSelectRegister - 790 1) * 0x20) + APCI1564_TCW_PROG); 791 } // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) 792 return insn->n; 793} 794 795/* 796+----------------------------------------------------------------------------+ 797| Function Name : int i_APCI1564_ReadTimerCounterWatchdog | 798| (struct comedi_device *dev,struct comedi_subdevice *s, | 799| struct comedi_insn *insn,unsigned int *data) | 800+----------------------------------------------------------------------------+ 801| Task : Read The Selected Timer , Counter or Watchdog | 802+----------------------------------------------------------------------------+ 803| Input Parameters : struct comedi_device *dev : Driver handle | 804| UINT *data : Data Pointer contains | 805| configuration parameters as below | 806| | 807 808+----------------------------------------------------------------------------+ 809| Output Parameters : -- | 810+----------------------------------------------------------------------------+ 811| Return Value : TRUE : No error occur | 812| : FALSE : Error occur. Return the error | 813| | 814+----------------------------------------------------------------------------+ 815*/ 816int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev, 817 struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) 818{ 819 ULONG ul_Command1 = 0; 820 821 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 822 // Stores the status of the Watchdog 823 data[0] = 824 inl(devpriv->i_IobaseAmcc + 825 APCI1564_DIGITAL_OP_WATCHDOG + 826 APCI1564_TCW_TRIG_STATUS) & 0x1; 827 data[1] = 828 inl(devpriv->i_IobaseAmcc + 829 APCI1564_DIGITAL_OP_WATCHDOG); 830 } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) 831 else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 832 // Stores the status of the Timer 833 data[0] = 834 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 835 APCI1564_TCW_TRIG_STATUS) & 0x1; 836 837 // Stores the Actual value of the Timer 838 data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER); 839 } // else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) 840 else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { 841 // Read the Counter Actual Value. 842 data[0] = 843 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - 844 1) * 0x20) + 845 APCI1564_TCW_SYNC_ENABLEDISABLE); 846 ul_Command1 = 847 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - 848 1) * 0x20) + APCI1564_TCW_TRIG_STATUS); 849 850 /***********************************/ 851 /* Get the software trigger status */ 852 /***********************************/ 853 data[1] = (unsigned char) ((ul_Command1 >> 1) & 1); 854 855 /***********************************/ 856 /* Get the hardware trigger status */ 857 /***********************************/ 858 data[2] = (unsigned char) ((ul_Command1 >> 2) & 1); 859 860 /*********************************/ 861 /* Get the software clear status */ 862 /*********************************/ 863 data[3] = (unsigned char) ((ul_Command1 >> 3) & 1); 864 865 /***************************/ 866 /* Get the overflow status */ 867 /***************************/ 868 data[4] = (unsigned char) ((ul_Command1 >> 0) & 1); 869 } // else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) 870 else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) 871 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG) 872 && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) { 873 printk("\n Invalid Subdevice !!!\n"); 874 } // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) 875 return insn->n; 876} 877 878/* 879+----------------------------------------------------------------------------+ 880| Function Name : int i_APCI1564_ReadInterruptStatus | 881| (struct comedi_device *dev,struct comedi_subdevice *s, | 882| struct comedi_insn *insn,unsigned int *data) | 883+----------------------------------------------------------------------------+ 884| Task :Reads the interrupt status register | 885+----------------------------------------------------------------------------+ 886| Input Parameters : | 887+----------------------------------------------------------------------------+ 888| Output Parameters : -- | 889+----------------------------------------------------------------------------+ 890| Return Value : | 891| | 892+----------------------------------------------------------------------------+ 893*/ 894 895int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s, 896 struct comedi_insn * insn, unsigned int * data) 897{ 898 *data = ui_Type; 899 return insn->n; 900} 901 902/* 903+----------------------------------------------------------------------------+ 904| Function Name : static void v_APCI1564_Interrupt | 905| (int irq , void *d) | 906+----------------------------------------------------------------------------+ 907| Task : Interrupt handler for the interruptible digital inputs | 908+----------------------------------------------------------------------------+ 909| Input Parameters : int irq : irq number | 910| void *d : void pointer | 911+----------------------------------------------------------------------------+ 912| Output Parameters : -- | 913+----------------------------------------------------------------------------+ 914| Return Value : TRUE : No error occur | 915| : FALSE : Error occur. Return the error | 916| | 917+----------------------------------------------------------------------------+ 918*/ 919static void v_APCI1564_Interrupt(int irq, void *d) 920{ 921 struct comedi_device *dev = d; 922 UINT ui_DO, ui_DI; 923 UINT ui_Timer; 924 UINT ui_C1, ui_C2, ui_C3, ui_C4; 925 ULONG ul_Command2 = 0; 926 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 927 APCI1564_DIGITAL_IP_IRQ) & 0x01; 928 ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 929 APCI1564_DIGITAL_OP_IRQ) & 0x01; 930 ui_Timer = 931 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 932 APCI1564_TCW_IRQ) & 0x01; 933 ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 + 934 APCI1564_TCW_IRQ) & 0x1; 935 ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 + 936 APCI1564_TCW_IRQ) & 0x1; 937 ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 + 938 APCI1564_TCW_IRQ) & 0x1; 939 ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 + 940 APCI1564_TCW_IRQ) & 0x1; 941 if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 942 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { 943 printk("\nInterrupt from unknown source\n"); 944 } // if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) 945 946 if (ui_DI == 1) { 947 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 948 APCI1564_DIGITAL_IP_IRQ); 949 outl(0x0, 950 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 951 APCI1564_DIGITAL_IP_IRQ); 952 ui_InterruptStatus_1564 = 953 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + 954 APCI1564_DIGITAL_IP_INTERRUPT_STATUS); 955 ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0; 956 send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample 957 outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); //enable the interrupt 958 return; 959 } 960 961 if (ui_DO == 1) { 962 // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. 963 ui_Type = 964 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 965 APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3; 966 //Disable the Interrupt 967 outl(0x0, 968 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + 969 APCI1564_DIGITAL_OP_INTERRUPT); 970 971 //Sends signal to user space 972 send_sig(SIGIO, devpriv->tsk_Current, 0); 973 974 } // if (ui_DO) 975 976 if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) { 977 // Disable Timer Interrupt 978 ul_Command2 = 979 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + 980 APCI1564_TCW_PROG); 981 outl(0x0, 982 devpriv->i_IobaseAmcc + APCI1564_TIMER + 983 APCI1564_TCW_PROG); 984 985 //Send a signal to from kernel to user space 986 send_sig(SIGIO, devpriv->tsk_Current, 0); 987 988 // Enable Timer Interrupt 989 990 outl(ul_Command2, 991 devpriv->i_IobaseAmcc + APCI1564_TIMER + 992 APCI1564_TCW_PROG); 993 } // if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) 994 995 if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { 996 // Disable Counter Interrupt 997 ul_Command2 = 998 inl(devpriv->iobase + APCI1564_COUNTER1 + 999 APCI1564_TCW_PROG); 1000 outl(0x0, 1001 devpriv->iobase + APCI1564_COUNTER1 + 1002 APCI1564_TCW_PROG); 1003 1004 //Send a signal to from kernel to user space 1005 send_sig(SIGIO, devpriv->tsk_Current, 0); 1006 1007 // Enable Counter Interrupt 1008 outl(ul_Command2, 1009 devpriv->iobase + APCI1564_COUNTER1 + 1010 APCI1564_TCW_PROG); 1011 } // if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) 1012 1013 if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { 1014 // Disable Counter Interrupt 1015 ul_Command2 = 1016 inl(devpriv->iobase + APCI1564_COUNTER2 + 1017 APCI1564_TCW_PROG); 1018 outl(0x0, 1019 devpriv->iobase + APCI1564_COUNTER2 + 1020 APCI1564_TCW_PROG); 1021 1022 //Send a signal to from kernel to user space 1023 send_sig(SIGIO, devpriv->tsk_Current, 0); 1024 1025 // Enable Counter Interrupt 1026 outl(ul_Command2, 1027 devpriv->iobase + APCI1564_COUNTER2 + 1028 APCI1564_TCW_PROG); 1029 } // if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) 1030 1031 if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { 1032 // Disable Counter Interrupt 1033 ul_Command2 = 1034 inl(devpriv->iobase + APCI1564_COUNTER3 + 1035 APCI1564_TCW_PROG); 1036 outl(0x0, 1037 devpriv->iobase + APCI1564_COUNTER3 + 1038 APCI1564_TCW_PROG); 1039 1040 //Send a signal to from kernel to user space 1041 send_sig(SIGIO, devpriv->tsk_Current, 0); 1042 1043 // Enable Counter Interrupt 1044 outl(ul_Command2, 1045 devpriv->iobase + APCI1564_COUNTER3 + 1046 APCI1564_TCW_PROG); 1047 } // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) 1048 1049 if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { 1050 // Disable Counter Interrupt 1051 ul_Command2 = 1052 inl(devpriv->iobase + APCI1564_COUNTER4 + 1053 APCI1564_TCW_PROG); 1054 outl(0x0, 1055 devpriv->iobase + APCI1564_COUNTER4 + 1056 APCI1564_TCW_PROG); 1057 1058 //Send a signal to from kernel to user space 1059 send_sig(SIGIO, devpriv->tsk_Current, 0); 1060 1061 // Enable Counter Interrupt 1062 outl(ul_Command2, 1063 devpriv->iobase + APCI1564_COUNTER4 + 1064 APCI1564_TCW_PROG); 1065 } // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) 1066 return; 1067} 1068 1069/* 1070+----------------------------------------------------------------------------+ 1071| Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | | 1072+----------------------------------------------------------------------------+ 1073| Task :resets all the registers | 1074+----------------------------------------------------------------------------+ 1075| Input Parameters : struct comedi_device *dev 1076+----------------------------------------------------------------------------+ 1077| Output Parameters : -- | 1078+----------------------------------------------------------------------------+ 1079| Return Value : | 1080| | 1081+----------------------------------------------------------------------------+ 1082*/ 1083 1084int i_APCI1564_Reset(struct comedi_device * dev) 1085{ 1086 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); //disable the interrupts 1087 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register 1088 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt 1089 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); 1090 devpriv->b_DigitalOutputRegister = 0; 1091 ui_Type = 0; 1092 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); //Resets the output channels 1093 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); //Disables the interrupt. 1094 outl(0x0, 1095 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + 1096 APCI1564_TCW_RELOAD_VALUE); 1097 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER); 1098 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); 1099 1100 outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); 1101 outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); 1102 outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); 1103 outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); 1104 return 0; 1105} 1106