hwdrv_apci035.c revision 08b93e7bda617a623ffae77940e4acfa31204367
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-035 | Compiler : GCC | 33 | Module name : hwdrv_apci035.c | Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Acces For APCI-035 | 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_apci035.h" 55static int i_WatchdogNbr = 0; 56static int i_Temp = 0; 57static int i_Flag = 1; 58/* 59+----------------------------------------------------------------------------+ 60| Function Name : int i_APCI035_ConfigTimerWatchdog | 61| (struct comedi_device *dev,struct comedi_subdevice *s, | 62| struct comedi_insn *insn,unsigned int *data) | 63+----------------------------------------------------------------------------+ 64| Task : Configures The Timer , Counter or Watchdog | 65+----------------------------------------------------------------------------+ 66| Input Parameters : struct comedi_device *dev : Driver handle | 67| unsigned int *data : Data Pointer contains | 68| configuration parameters as below | 69| | 70| data[0] : 0 Configure As Timer | 71| 1 Configure As Watchdog | 72| data[1] : Watchdog number 73| data[2] : Time base Unit | 74| data[3] : Reload Value | 75| data[4] : External Trigger | 76| 1:Enable 77| 0:Disable 78| data[5] :External Trigger Level 79| 00 Trigger Disabled 80| 01 Trigger Enabled (Low level) 81| 10 Trigger Enabled (High Level) 82| 11 Trigger Enabled (High/Low level) 83| data[6] : External Gate | 84| 1:Enable 85| 0:Disable 86| data[7] : External Gate level 87| 00 Gate Disabled 88| 01 Gate Enabled (Low level) 89| 10 Gate Enabled (High Level) 90| data[8] :Warning Relay 91| 1: ENABLE 92| 0: DISABLE 93| data[9] :Warning Delay available 94| data[10] :Warning Relay Time unit 95| data[11] :Warning Relay Time Reload value 96| data[12] :Reset Relay 97| 1 : ENABLE 98| 0 : DISABLE 99| data[13] :Interrupt 100| 1 : ENABLE 101| 0 : DISABLE 102| 103| 104+----------------------------------------------------------------------------+ 105| Output Parameters : -- | 106+----------------------------------------------------------------------------+ 107| Return Value : TRUE : No error occur | 108| : FALSE : Error occur. Return the error | 109| | 110+----------------------------------------------------------------------------+ 111*/ 112int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 113 struct comedi_insn *insn, unsigned int *data) 114{ 115 unsigned int ui_Status = 0; 116 unsigned int ui_Command = 0; 117 unsigned int ui_Mode = 0; 118 i_Temp = 0; 119 devpriv->tsk_Current = current; 120 devpriv->b_TimerSelectMode = data[0]; 121 i_WatchdogNbr = data[1]; 122 if (data[0] == 0) { 123 ui_Mode = 2; 124 } else { 125 ui_Mode = 0; 126 } 127/* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */ 128 ui_Command = 0; 129/* ui_Command = ui_Command & 0xFFFFF9FEUL; */ 130 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 131 ui_Command = 0; 132 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 133/************************/ 134/* Set the reload value */ 135/************************/ 136 outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4); 137/*********************/ 138/* Set the time unit */ 139/*********************/ 140 outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8); 141 if (data[0] == ADDIDATA_TIMER) { 142 143 /******************************/ 144 /* Set the mode : */ 145 /* - Disable the hardware */ 146 /* - Disable the counter mode */ 147 /* - Disable the warning */ 148 /* - Disable the reset */ 149 /* - Enable the timer mode */ 150 /* - Set the timer mode */ 151 /******************************/ 152 153 ui_Command = 154 (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL; 155 156 } /* if (data[0] == ADDIDATA_TIMER) */ 157 else { 158 if (data[0] == ADDIDATA_WATCHDOG) { 159 160 /******************************/ 161 /* Set the mode : */ 162 /* - Disable the hardware */ 163 /* - Disable the counter mode */ 164 /* - Disable the warning */ 165 /* - Disable the reset */ 166 /* - Disable the timer mode */ 167 /******************************/ 168 169 ui_Command = ui_Command & 0xFFF819E2UL; 170 171 } else { 172 printk("\n The parameter for Timer/watchdog selection is in error\n"); 173 return -EINVAL; 174 } 175 } 176 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 177 ui_Command = 0; 178 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 179/********************************/ 180/* Disable the hardware trigger */ 181/********************************/ 182 ui_Command = ui_Command & 0xFFFFF89FUL; 183 if (data[4] == ADDIDATA_ENABLE) { 184 /**********************************/ 185 /* Set the hardware trigger level */ 186 /**********************************/ 187 ui_Command = ui_Command | (data[5] << 5); 188 } 189 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 190 ui_Command = 0; 191 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 192/*****************************/ 193/* Disable the hardware gate */ 194/*****************************/ 195 ui_Command = ui_Command & 0xFFFFF87FUL; 196 if (data[6] == ADDIDATA_ENABLE) { 197/*******************************/ 198/* Set the hardware gate level */ 199/*******************************/ 200 ui_Command = ui_Command | (data[7] << 7); 201 } 202 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 203 ui_Command = 0; 204 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 205/*******************************/ 206/* Disable the hardware output */ 207/*******************************/ 208 ui_Command = ui_Command & 0xFFFFF9FBUL; 209/*********************************/ 210/* Set the hardware output level */ 211/*********************************/ 212 ui_Command = ui_Command | (data[8] << 2); 213 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 214 if (data[9] == ADDIDATA_ENABLE) { 215 /************************/ 216 /* Set the reload value */ 217 /************************/ 218 outl(data[11], 219 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24); 220 /**********************/ 221 /* Set the time unite */ 222 /**********************/ 223 outl(data[10], 224 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28); 225 } 226 227 ui_Command = 0; 228 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 229 /*******************************/ 230 /* Disable the hardware output */ 231 /*******************************/ 232 ui_Command = ui_Command & 0xFFFFF9F7UL; 233 /*********************************/ 234 /* Set the hardware output level */ 235 /*********************************/ 236 ui_Command = ui_Command | (data[12] << 3); 237 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 238 /*************************************/ 239 /** Enable the watchdog interrupt **/ 240 /*************************************/ 241 ui_Command = 0; 242 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 243/*******************************/ 244/* Set the interrupt selection */ 245/*******************************/ 246 ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16); 247 248 ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1); 249 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 250 251 return insn->n; 252} 253 254/* 255+----------------------------------------------------------------------------+ 256| Function Name : int i_APCI035_StartStopWriteTimerWatchdog | 257| (struct comedi_device *dev,struct comedi_subdevice *s, | 258| struct comedi_insn *insn,unsigned int *data) | 259+----------------------------------------------------------------------------+ 260| Task : Start / Stop The Selected Timer , or Watchdog | 261+----------------------------------------------------------------------------+ 262| Input Parameters : struct comedi_device *dev : Driver handle | 263| unsigned int *data : Data Pointer contains | 264| configuration parameters as below | 265| | 266| data[0] : 0 - Stop Selected Timer/Watchdog | 267| 1 - Start Selected Timer/Watchdog | 268| 2 - Trigger Selected Timer/Watchdog | 269| 3 - Stop All Timer/Watchdog | 270| 4 - Start All Timer/Watchdog | 271| 5 - Trigger All Timer/Watchdog | 272| | 273+----------------------------------------------------------------------------+ 274| Output Parameters : -- | 275+----------------------------------------------------------------------------+ 276| Return Value : TRUE : No error occur | 277| : FALSE : Error occur. Return the error | 278| | 279+----------------------------------------------------------------------------+ 280*/ 281int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev, 282 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) 283{ 284 unsigned int ui_Command = 0; 285 int i_Count = 0; 286 if (data[0] == 1) { 287 ui_Command = 288 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 289 /**********************/ 290 /* Start the hardware */ 291 /**********************/ 292 ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL; 293 outl(ui_Command, 294 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 295 } /* if (data[0]==1) */ 296 if (data[0] == 2) { 297 ui_Command = 298 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 299 /***************************/ 300 /* Set the trigger command */ 301 /***************************/ 302 ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL; 303 outl(ui_Command, 304 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 305 } 306 307 if (data[0] == 0) /* Stop The Watchdog */ 308 { 309 /* Stop The Watchdog */ 310 ui_Command = 0; 311/* 312* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); 313* ui_Command = ui_Command & 0xFFFFF9FEUL; 314*/ 315 outl(ui_Command, 316 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); 317 } /* if (data[1]==0) */ 318 if (data[0] == 3) /* stop all Watchdogs */ 319 { 320 ui_Command = 0; 321 for (i_Count = 1; i_Count <= 4; i_Count++) { 322 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 323 ui_Command = 0x2UL; 324 } else { 325 ui_Command = 0x10UL; 326 } 327 i_WatchdogNbr = i_Count; 328 outl(ui_Command, 329 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 330 0); 331 } 332 333 } 334 if (data[0] == 4) /* start all Watchdogs */ 335 { 336 ui_Command = 0; 337 for (i_Count = 1; i_Count <= 4; i_Count++) { 338 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 339 ui_Command = 0x1UL; 340 } else { 341 ui_Command = 0x8UL; 342 } 343 i_WatchdogNbr = i_Count; 344 outl(ui_Command, 345 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 346 0); 347 } 348 } 349 if (data[0] == 5) /* trigger all Watchdogs */ 350 { 351 ui_Command = 0; 352 for (i_Count = 1; i_Count <= 4; i_Count++) { 353 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { 354 ui_Command = 0x4UL; 355 } else { 356 ui_Command = 0x20UL; 357 } 358 359 i_WatchdogNbr = i_Count; 360 outl(ui_Command, 361 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 362 0); 363 } 364 i_Temp = 1; 365 } 366 return insn->n; 367} 368 369/* 370+----------------------------------------------------------------------------+ 371| Function Name : int i_APCI035_ReadTimerWatchdog | 372| (struct comedi_device *dev,struct comedi_subdevice *s, | 373| struct comedi_insn *insn,unsigned int *data) | 374+----------------------------------------------------------------------------+ 375| Task : Read The Selected Timer , Counter or Watchdog | 376+----------------------------------------------------------------------------+ 377| Input Parameters : struct comedi_device *dev : Driver handle | 378| unsigned int *data : Data Pointer contains | 379| configuration parameters as below | 380| | 381| | 382+----------------------------------------------------------------------------+ 383| Output Parameters : data[0] : software trigger status 384| data[1] : hardware trigger status 385| data[2] : Software clear status 386| data[3] : Overflow status 387| data[4] : Timer actual value 388| 389 390+----------------------------------------------------------------------------+ 391| Return Value : TRUE : No error occur | 392| : FALSE : Error occur. Return the error | 393| | 394+----------------------------------------------------------------------------+ 395*/ 396int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 397 struct comedi_insn *insn, unsigned int *data) 398{ 399 unsigned int ui_Status = 0; /* Status register */ 400 i_WatchdogNbr = insn->unused[0]; 401 402 /******************/ 403 /* Get the status */ 404 /******************/ 405 406 ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16); 407 408 /***********************************/ 409 /* Get the software trigger status */ 410 /***********************************/ 411 412 data[0] = ((ui_Status >> 1) & 1); 413 /***********************************/ 414 /* Get the hardware trigger status */ 415 /***********************************/ 416 data[1] = ((ui_Status >> 2) & 1); 417 /*********************************/ 418 /* Get the software clear status */ 419 /*********************************/ 420 data[2] = ((ui_Status >> 3) & 1); 421 /***************************/ 422 /* Get the overflow status */ 423 /***************************/ 424 data[3] = ((ui_Status >> 0) & 1); 425 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 426 data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); 427 428 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ 429 430 return insn->n; 431} 432 433/* 434+----------------------------------------------------------------------------+ 435| Function Name : int i_APCI035_ConfigAnalogInput | 436| (struct comedi_device *dev,struct comedi_subdevice *s, | 437| struct comedi_insn *insn,unsigned int *data) | 438+----------------------------------------------------------------------------+ 439| Task : Configures The Analog Input Subdevice | 440+----------------------------------------------------------------------------+ 441| Input Parameters : struct comedi_device *dev : Driver handle | 442| struct comedi_subdevice *s : Subdevice Pointer | 443| struct comedi_insn *insn : Insn Structure Pointer | 444| unsigned int *data : Data Pointer contains | 445| configuration parameters as below | 446| data[0] : Warning delay value 447| | 448+----------------------------------------------------------------------------+ 449| Output Parameters : -- | 450+----------------------------------------------------------------------------+ 451| Return Value : TRUE : No error occur | 452| : FALSE : Error occur. Return the error | 453| | 454+----------------------------------------------------------------------------+ 455*/ 456int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, 457 struct comedi_insn *insn, unsigned int *data) 458{ 459 devpriv->tsk_Current = current; 460 outl(0x200 | 0, devpriv->iobase + 128 + 0x4); 461 outl(0, devpriv->iobase + 128 + 0); 462/********************************/ 463/* Initialise the warning value */ 464/********************************/ 465 outl(0x300 | 0, devpriv->iobase + 128 + 0x4); 466 outl((data[0] << 8), devpriv->iobase + 128 + 0); 467 outl(0x200000UL, devpriv->iobase + 128 + 12); 468 469 return insn->n; 470} 471 472/* 473+----------------------------------------------------------------------------+ 474| Function Name : int i_APCI035_ReadAnalogInput | 475| (struct comedi_device *dev,struct comedi_subdevice *s, | 476| struct comedi_insn *insn,unsigned int *data) | 477+----------------------------------------------------------------------------+ 478| Task : Read value of the selected channel | 479+----------------------------------------------------------------------------+ 480| Input Parameters : struct comedi_device *dev : Driver handle | 481| unsigned int ui_NoOfChannels : No Of Channels To read | 482| unsigned int *data : Data Pointer to read status | 483+----------------------------------------------------------------------------+ 484| Output Parameters : -- | 485| data[0] : Digital Value Of Input | 486| | 487+----------------------------------------------------------------------------+ 488| Return Value : TRUE : No error occur | 489| : FALSE : Error occur. Return the error | 490| | 491+----------------------------------------------------------------------------+ 492*/ 493int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, 494 struct comedi_insn *insn, unsigned int *data) 495{ 496 unsigned int ui_CommandRegister = 0; 497/******************/ 498/* Set the start */ 499/******************/ 500 ui_CommandRegister = 0x80000; 501 /******************************/ 502 /* Write the command register */ 503 /******************************/ 504 outl(ui_CommandRegister, devpriv->iobase + 128 + 8); 505 506/***************************************/ 507/* Read the digital value of the input */ 508/***************************************/ 509 data[0] = inl(devpriv->iobase + 128 + 28); 510 return insn->n; 511} 512 513/* 514+----------------------------------------------------------------------------+ 515| Function Name : int i_APCI035_Reset(struct comedi_device *dev) | 516| | 517+----------------------------------------------------------------------------+ 518| Task :Resets the registers of the card | 519+----------------------------------------------------------------------------+ 520| Input Parameters : | 521+----------------------------------------------------------------------------+ 522| Output Parameters : -- | 523+----------------------------------------------------------------------------+ 524| Return Value : | 525| | 526+----------------------------------------------------------------------------+ 527*/ 528int i_APCI035_Reset(struct comedi_device *dev) 529{ 530 int i_Count = 0; 531 for (i_Count = 1; i_Count <= 4; i_Count++) { 532 i_WatchdogNbr = i_Count; 533 outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); /* stop all timers */ 534 } 535 outl(0x0, devpriv->iobase + 128 + 12); /* Disable the warning delay */ 536 537 return 0; 538} 539 540/* 541+----------------------------------------------------------------------------+ 542| Function Name : static void v_APCI035_Interrupt | 543| (int irq , void *d) | 544+----------------------------------------------------------------------------+ 545| Task : Interrupt processing Routine | 546+----------------------------------------------------------------------------+ 547| Input Parameters : int irq : irq number | 548| void *d : void pointer | 549+----------------------------------------------------------------------------+ 550| Output Parameters : -- | 551+----------------------------------------------------------------------------+ 552| Return Value : TRUE : No error occur | 553| : FALSE : Error occur. Return the error | 554| | 555+----------------------------------------------------------------------------+ 556*/ 557static void v_APCI035_Interrupt(int irq, void *d) 558{ 559 struct comedi_device *dev = d; 560 unsigned int ui_StatusRegister1 = 0; 561 unsigned int ui_StatusRegister2 = 0; 562 unsigned int ui_ReadCommand = 0; 563 unsigned int ui_ChannelNumber = 0; 564 unsigned int ui_DigitalTemperature = 0; 565 if (i_Temp == 1) { 566 i_WatchdogNbr = i_Flag; 567 i_Flag = i_Flag + 1; 568 } 569 /**************************************/ 570 /* Read the interrupt status register of temperature Warning */ 571 /**************************************/ 572 ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16); 573 /**************************************/ 574 /* Read the interrupt status register for Watchdog/timer */ 575 /**************************************/ 576 577 ui_StatusRegister2 = 578 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20); 579 580 if ((((ui_StatusRegister1) & 0x8) == 0x8)) /* Test if warning relay interrupt */ 581 { 582 /**********************************/ 583 /* Disable the temperature warning */ 584 /**********************************/ 585 ui_ReadCommand = inl(devpriv->iobase + 128 + 12); 586 ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL; 587 outl(ui_ReadCommand, devpriv->iobase + 128 + 12); 588 /***************************/ 589 /* Read the channel number */ 590 /***************************/ 591 ui_ChannelNumber = inl(devpriv->iobase + 128 + 60); 592 /**************************************/ 593 /* Read the digital temperature value */ 594 /**************************************/ 595 ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60); 596 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 597 } /* if (((ui_StatusRegister1 & 0x8) == 0x8)) */ 598 599 else { 600 if ((ui_StatusRegister2 & 0x1) == 0x1) { 601 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 602 } 603 } /* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */ 604 605 return; 606} 607