hwdrv_apci035.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
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-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" 55int i_WatchdogNbr = 0; 56int i_Temp = 0; 57int 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 /* Get the status */ 403 /******************/ 404 ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16); 405 /***********************************/ 406 /* Get the software trigger status */ 407 /***********************************/ 408 data[0] = ((ui_Status >> 1) & 1); 409 /***********************************/ 410 /* Get the hardware trigger status */ 411 /***********************************/ 412 data[1] = ((ui_Status >> 2) & 1); 413 /*********************************/ 414 /* Get the software clear status */ 415 /*********************************/ 416 data[2] = ((ui_Status >> 3) & 1); 417 /***************************/ 418 /* Get the overflow status */ 419 /***************************/ 420 data[3] = ((ui_Status >> 0) & 1); 421 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { 422 data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); 423 424 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */ 425 426 return insn->n; 427} 428 429/* 430+----------------------------------------------------------------------------+ 431| Function Name : int i_APCI035_ConfigAnalogInput | 432| (struct comedi_device *dev,struct comedi_subdevice *s, | 433| struct comedi_insn *insn,unsigned int *data) | 434+----------------------------------------------------------------------------+ 435| Task : Configures The Analog Input Subdevice | 436+----------------------------------------------------------------------------+ 437| Input Parameters : struct comedi_device *dev : Driver handle | 438| struct comedi_subdevice *s : Subdevice Pointer | 439| struct comedi_insn *insn : Insn Structure Pointer | 440| unsigned int *data : Data Pointer contains | 441| configuration parameters as below | 442| data[0] : Warning delay value 443| | 444+----------------------------------------------------------------------------+ 445| Output Parameters : -- | 446+----------------------------------------------------------------------------+ 447| Return Value : TRUE : No error occur | 448| : FALSE : Error occur. Return the error | 449| | 450+----------------------------------------------------------------------------+ 451*/ 452int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, 453 struct comedi_insn *insn, unsigned int *data) 454{ 455 devpriv->tsk_Current = current; 456 outl(0x200 | 0, devpriv->iobase + 128 + 0x4); 457 outl(0, devpriv->iobase + 128 + 0); 458/********************************/ 459/* Initialise the warning value */ 460/********************************/ 461 outl(0x300 | 0, devpriv->iobase + 128 + 0x4); 462 outl((data[0] << 8), devpriv->iobase + 128 + 0); 463 outl(0x200000UL, devpriv->iobase + 128 + 12); 464 465 return insn->n; 466} 467 468/* 469+----------------------------------------------------------------------------+ 470| Function Name : int i_APCI035_ReadAnalogInput | 471| (struct comedi_device *dev,struct comedi_subdevice *s, | 472| struct comedi_insn *insn,unsigned int *data) | 473+----------------------------------------------------------------------------+ 474| Task : Read value of the selected channel | 475+----------------------------------------------------------------------------+ 476| Input Parameters : struct comedi_device *dev : Driver handle | 477| unsigned int ui_NoOfChannels : No Of Channels To read | 478| unsigned int *data : Data Pointer to read status | 479+----------------------------------------------------------------------------+ 480| Output Parameters : -- | 481| data[0] : Digital Value Of Input | 482| | 483+----------------------------------------------------------------------------+ 484| Return Value : TRUE : No error occur | 485| : FALSE : Error occur. Return the error | 486| | 487+----------------------------------------------------------------------------+ 488*/ 489int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, 490 struct comedi_insn *insn, unsigned int *data) 491{ 492 unsigned int ui_CommandRegister = 0; 493/******************/ 494/* Set the start */ 495/******************/ 496 ui_CommandRegister = 0x80000; 497 /******************************/ 498 /* Write the command register */ 499 /******************************/ 500 outl(ui_CommandRegister, devpriv->iobase + 128 + 8); 501 502/***************************************/ 503/* Read the digital value of the input */ 504/***************************************/ 505 data[0] = inl(devpriv->iobase + 128 + 28); 506 return insn->n; 507} 508 509/* 510+----------------------------------------------------------------------------+ 511| Function Name : int i_APCI035_Reset(struct comedi_device *dev) | 512| | 513+----------------------------------------------------------------------------+ 514| Task :Resets the registers of the card | 515+----------------------------------------------------------------------------+ 516| Input Parameters : | 517+----------------------------------------------------------------------------+ 518| Output Parameters : -- | 519+----------------------------------------------------------------------------+ 520| Return Value : | 521| | 522+----------------------------------------------------------------------------+ 523*/ 524int i_APCI035_Reset(struct comedi_device *dev) 525{ 526 int i_Count = 0; 527 for (i_Count = 1; i_Count <= 4; i_Count++) { 528 i_WatchdogNbr = i_Count; 529 outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); /* stop all timers */ 530 } 531 outl(0x0, devpriv->iobase + 128 + 12); /* Disable the warning delay */ 532 533 return 0; 534} 535 536/* 537+----------------------------------------------------------------------------+ 538| Function Name : static void v_APCI035_Interrupt | 539| (int irq , void *d) | 540+----------------------------------------------------------------------------+ 541| Task : Interrupt processing Routine | 542+----------------------------------------------------------------------------+ 543| Input Parameters : int irq : irq number | 544| void *d : void pointer | 545+----------------------------------------------------------------------------+ 546| Output Parameters : -- | 547+----------------------------------------------------------------------------+ 548| Return Value : TRUE : No error occur | 549| : FALSE : Error occur. Return the error | 550| | 551+----------------------------------------------------------------------------+ 552*/ 553static void v_APCI035_Interrupt(int irq, void *d) 554{ 555 struct comedi_device *dev = d; 556 unsigned int ui_StatusRegister1 = 0; 557 unsigned int ui_StatusRegister2 = 0; 558 unsigned int ui_ReadCommand = 0; 559 unsigned int ui_ChannelNumber = 0; 560 unsigned int ui_DigitalTemperature = 0; 561 if (i_Temp == 1) { 562 i_WatchdogNbr = i_Flag; 563 i_Flag = i_Flag + 1; 564 } 565 /**************************************/ 566 /* Read the interrupt status register of temperature Warning */ 567 /**************************************/ 568 ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16); 569 /**************************************/ 570 /* Read the interrupt status register for Watchdog/timer */ 571 /**************************************/ 572 573 ui_StatusRegister2 = 574 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20); 575 576 if ((((ui_StatusRegister1) & 0x8) == 0x8)) /* Test if warning relay interrupt */ 577 { 578 /**********************************/ 579 /* Disable the temperature warning */ 580 /**********************************/ 581 ui_ReadCommand = inl(devpriv->iobase + 128 + 12); 582 ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL; 583 outl(ui_ReadCommand, devpriv->iobase + 128 + 12); 584 /***************************/ 585 /* Read the channel number */ 586 /***************************/ 587 ui_ChannelNumber = inl(devpriv->iobase + 128 + 60); 588 /**************************************/ 589 /* Read the digital temperature value */ 590 /**************************************/ 591 ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60); 592 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 593 } /* if (((ui_StatusRegister1 & 0x8) == 0x8)) */ 594 595 else { 596 if ((ui_StatusRegister2 & 0x1) == 0x1) { 597 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 598 } 599 } /* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */ 600 601 return; 602} 603