hwdrv_apci1516.c revision 25417922694e60f04cd4dc8448ada9236f18c532
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-1516 | Compiler : GCC | 33 | Module name : hwdrv_apci1516.c| Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Access For APCI-1516 | 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_apci1516.h" 55 56/* 57+----------------------------------------------------------------------------+ 58| Function Name : int i_APCI1516_Read1DigitalInput | 59| (struct comedi_device *dev,struct comedi_subdevice *s, | 60| struct comedi_insn *insn,unsigned int *data) | 61+----------------------------------------------------------------------------+ 62| Task : Return the status of the digital input | 63+----------------------------------------------------------------------------+ 64| Input Parameters : struct comedi_device *dev : Driver handle | 65| struct comedi_subdevice *s, :pointer to subdevice structure 66| struct comedi_insn *insn :pointer to insn structure | 67| unsigned int *data : Data Pointer to read status | 68+----------------------------------------------------------------------------+ 69| Output Parameters : -- | 70+----------------------------------------------------------------------------+ 71| Return Value : TRUE : No error occur | 72| : FALSE : Error occur. Return the error | 73| | 74+----------------------------------------------------------------------------+ 75*/ 76int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, 77 struct comedi_insn *insn, unsigned int *data) 78{ 79 unsigned int ui_TmpValue = 0; 80 unsigned int ui_Channel; 81 ui_Channel = CR_CHAN(insn->chanspec); 82 if (ui_Channel <= 7) { 83 ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP); 84 /* since only 1 channel reqd to bring it to last bit it is rotated */ 85 /* 8 +(chan - 1) times then ANDed with 1 for last bit. */ 86 *data = (ui_TmpValue >> ui_Channel) & 0x1; 87 } /* if(ui_Channel >= 0 && ui_Channel <=7) */ 88 else { 89 /* comedi_error(dev," \n chan spec wrong\n"); */ 90 return -EINVAL; /* "sorry channel spec wrong " */ 91 } /* else if(ui_Channel >= 0 && ui_Channel <=7) */ 92 93 return insn->n; 94} 95 96/* 97+----------------------------------------------------------------------------+ 98| Function Name : int i_APCI1516_ReadMoreDigitalInput | 99| (struct comedi_device *dev,struct comedi_subdevice *s, | 100| struct comedi_insn *insn,unsigned int *data) | 101+----------------------------------------------------------------------------+ 102| Task : Return the status of the Requested digital inputs | 103+----------------------------------------------------------------------------+ 104| Input Parameters : struct comedi_device *dev : Driver handle | 105| struct comedi_subdevice *s, :pointer to subdevice structure 106| struct comedi_insn *insn :pointer to insn structure | 107| unsigned int *data : Data Pointer to read status | 108+----------------------------------------------------------------------------+ 109| Output Parameters : -- | 110+----------------------------------------------------------------------------+ 111| Return Value : TRUE : No error occur | 112| : FALSE : Error occur. Return the error | 113| | 114+----------------------------------------------------------------------------+ 115*/ 116 117int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, 118 struct comedi_insn *insn, unsigned int *data) 119{ 120 121 unsigned int ui_PortValue = data[0]; 122 unsigned int ui_Mask = 0; 123 unsigned int ui_NoOfChannels; 124 125 ui_NoOfChannels = CR_CHAN(insn->chanspec); 126 127 *data = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP); 128 switch (ui_NoOfChannels) { 129 case 2: 130 ui_Mask = 3; 131 *data = (*data >> (2 * ui_PortValue)) & ui_Mask; 132 break; 133 case 4: 134 ui_Mask = 15; 135 *data = (*data >> (4 * ui_PortValue)) & ui_Mask; 136 break; 137 case 7: 138 break; 139 140 default: 141 printk("\nWrong parameters\n"); 142 return -EINVAL; /* "sorry channel spec wrong " */ 143 break; 144 } /* switch(ui_NoOfChannels) */ 145 146 return insn->n; 147} 148 149/* 150+----------------------------------------------------------------------------+ 151| Function Name : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev, 152| struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data) | 153| | 154+----------------------------------------------------------------------------+ 155| Task : Configures The Digital Output Subdevice. | 156+----------------------------------------------------------------------------+ 157| Input Parameters : struct comedi_device *dev : Driver handle | 158| unsigned int *data : Data Pointer contains | 159| configuration parameters as below | 160| struct comedi_subdevice *s, :pointer to subdevice structure 161| struct comedi_insn *insn :pointer to insn structure | 162| data[0] :1:Memory on | 163| 0:Memory off | 164| | 165| | 166+----------------------------------------------------------------------------+ 167| Output Parameters : -- | 168+----------------------------------------------------------------------------+ 169| Return Value : TRUE : No error occur | 170| : FALSE : Error occur. Return the error | 171| | 172+----------------------------------------------------------------------------+ 173*/ 174int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 175 struct comedi_insn *insn, unsigned int *data) 176{ 177 devpriv->b_OutputMemoryStatus = data[0]; 178 return insn->n; 179} 180 181/* 182+----------------------------------------------------------------------------+ 183| Function Name : int i_APCI1516_WriteDigitalOutput | 184| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, 185| unsigned int *data) | 186+----------------------------------------------------------------------------+ 187| Task : Writes port value To the selected port | 188+----------------------------------------------------------------------------+ 189| Input Parameters : struct comedi_device *dev : Driver handle | 190| struct comedi_subdevice *s, :pointer to subdevice structure 191| struct comedi_insn *insn :pointer to insn structure | 192| unsigned int *data : Data Pointer to read status | 193+----------------------------------------------------------------------------+ 194| Output Parameters : -- | 195+----------------------------------------------------------------------------+ 196| Return Value : TRUE : No error occur | 197| : FALSE : Error occur. Return the error | 198| | 199+----------------------------------------------------------------------------+ 200*/ 201 202int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 203 struct comedi_insn *insn, unsigned int *data) 204{ 205 unsigned int ui_Temp, ui_Temp1; 206 unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ 207 208 printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP); 209 210 if (devpriv->b_OutputMemoryStatus) { 211 ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP); 212 213 } /* if(devpriv->b_OutputMemoryStatus ) */ 214 else { 215 ui_Temp = 0; 216 } /* if(devpriv->b_OutputMemoryStatus ) */ 217 if (data[3] == 0) { 218 if (data[1] == 0) { 219 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; 220 outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP); 221 222 printk("EL311003 : d=%d @=%x\n", data[0], 223 devpriv->iobase + APCI1516_DIGITAL_OP); 224 225 } /* if(data[1]==0) */ 226 else { 227 if (data[1] == 1) { 228 switch (ui_NoOfChannel) { 229 230 case 2: 231 data[0] = 232 (data[0] << (2 * 233 data[2])) | ui_Temp; 234 break; 235 236 case 4: 237 data[0] = 238 (data[0] << (4 * 239 data[2])) | ui_Temp; 240 break; 241 242 case 7: 243 data[0] = data[0] | ui_Temp; 244 break; 245 246 default: 247 comedi_error(dev, " chan spec wrong"); 248 return -EINVAL; /* "sorry channel spec wrong " */ 249 250 } /* switch(ui_NoOfChannels) */ 251 252 outw(data[0], 253 devpriv->iobase + APCI1516_DIGITAL_OP); 254 255 printk("EL311003 : d=%d @=%x\n", data[0], 256 devpriv->iobase + APCI1516_DIGITAL_OP); 257 } /* if(data[1]==1) */ 258 else { 259 printk("\nSpecified channel not supported\n"); 260 } /* else if(data[1]==1) */ 261 } /* elseif(data[1]==0) */ 262 } /* if(data[3]==0) */ 263 else { 264 if (data[3] == 1) { 265 if (data[1] == 0) { 266 data[0] = ~data[0] & 0x1; 267 ui_Temp1 = 1; 268 ui_Temp1 = ui_Temp1 << ui_NoOfChannel; 269 ui_Temp = ui_Temp | ui_Temp1; 270 data[0] = (data[0] << ui_NoOfChannel) ^ 0xff; 271 data[0] = data[0] & ui_Temp; 272 outw(data[0], 273 devpriv->iobase + APCI1516_DIGITAL_OP); 274 275 printk("EL311003 : d=%d @=%x\n", data[0], 276 devpriv->iobase + APCI1516_DIGITAL_OP); 277 278 } /* if(data[1]==0) */ 279 else { 280 if (data[1] == 1) { 281 switch (ui_NoOfChannel) { 282 283 case 2: 284 data[0] = ~data[0] & 0x3; 285 ui_Temp1 = 3; 286 ui_Temp1 = 287 ui_Temp1 << 2 * data[2]; 288 ui_Temp = ui_Temp | ui_Temp1; 289 data[0] = 290 ((data[0] << (2 * 291 data 292 [2])) ^ 293 0xff) & ui_Temp; 294 break; 295 296 case 4: 297 data[0] = ~data[0] & 0xf; 298 ui_Temp1 = 15; 299 ui_Temp1 = 300 ui_Temp1 << 4 * data[2]; 301 ui_Temp = ui_Temp | ui_Temp1; 302 data[0] = 303 ((data[0] << (4 * 304 data 305 [2])) ^ 306 0xff) & ui_Temp; 307 break; 308 309 case 7: 310 break; 311 312 default: 313 comedi_error(dev, 314 " chan spec wrong"); 315 return -EINVAL; /* "sorry channel spec wrong " */ 316 317 } /* switch(ui_NoOfChannels) */ 318 319 outw(data[0], 320 devpriv->iobase + 321 APCI1516_DIGITAL_OP); 322 323 printk("EL311003 : d=%d @=%x\n", 324 data[0], 325 devpriv->iobase + 326 APCI1516_DIGITAL_OP); 327 } /* if(data[1]==1) */ 328 else { 329 printk("\nSpecified channel not supported\n"); 330 } /* else if(data[1]==1) */ 331 } /* elseif(data[1]==0) */ 332 } /* if(data[3]==1); */ 333 else { 334 printk("\nSpecified functionality does not exist\n"); 335 return -EINVAL; 336 } /* if else data[3]==1) */ 337 } /* if else data[3]==0) */ 338 return (insn->n);; 339} 340 341/* 342+----------------------------------------------------------------------------+ 343| Function Name : int i_APCI1516_ReadDigitalOutput | 344| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, 345| unsigned int *data) | 346+----------------------------------------------------------------------------+ 347| Task : Read value of the selected channel or port | 348+----------------------------------------------------------------------------+ 349| Input Parameters : struct comedi_device *dev : Driver handle | 350| struct comedi_subdevice *s, :pointer to subdevice structure 351| struct comedi_insn *insn :pointer to insn structure | 352| unsigned int *data : Data Pointer to read status | 353+----------------------------------------------------------------------------+ 354| Output Parameters : -- | 355+----------------------------------------------------------------------------+ 356| Return Value : TRUE : No error occur | 357| : FALSE : Error occur. Return the error | 358| | 359+----------------------------------------------------------------------------+ 360*/ 361 362int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 363 struct comedi_insn *insn, unsigned int *data) 364{ 365 366 unsigned int ui_Temp; 367 unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ 368 ui_Temp = data[0]; 369 *data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW); 370 if (ui_Temp == 0) { 371 *data = (*data >> ui_NoOfChannel) & 0x1; 372 } /* if(ui_Temp==0) */ 373 else { 374 if (ui_Temp == 1) { 375 switch (ui_NoOfChannel) { 376 377 case 2: 378 *data = (*data >> (2 * data[1])) & 3; 379 break; 380 381 case 4: 382 *data = (*data >> (4 * data[1])) & 15; 383 break; 384 385 case 7: 386 break; 387 388 default: 389 comedi_error(dev, " chan spec wrong"); 390 return -EINVAL; /* "sorry channel spec wrong " */ 391 392 } /* switch(ui_NoOfChannels) */ 393 } /* if(ui_Temp==1) */ 394 else { 395 printk("\nSpecified channel not supported \n"); 396 } /* elseif(ui_Temp==1) */ 397 } /* elseif(ui_Temp==0) */ 398 return insn->n; 399} 400 401/* 402+----------------------------------------------------------------------------+ 403| Function Name : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, 404| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | 405| | 406+----------------------------------------------------------------------------+ 407| Task : Configures The Watchdog | 408+----------------------------------------------------------------------------+ 409| Input Parameters : struct comedi_device *dev : Driver handle | 410| struct comedi_subdevice *s, :pointer to subdevice structure 411| struct comedi_insn *insn :pointer to insn structure | 412| unsigned int *data : Data Pointer to read status | 413+----------------------------------------------------------------------------+ 414| Output Parameters : -- | 415+----------------------------------------------------------------------------+ 416| Return Value : TRUE : No error occur | 417| : FALSE : Error occur. Return the error | 418| | 419+----------------------------------------------------------------------------+ 420*/ 421 422int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 423 struct comedi_insn *insn, unsigned int *data) 424{ 425 if (data[0] == 0) { 426 /* Disable the watchdog */ 427 outw(0x0, 428 devpriv->i_IobaseAddon + 429 APCI1516_WATCHDOG_ENABLEDISABLE); 430 /* Loading the Reload value */ 431 outw(data[1], 432 devpriv->i_IobaseAddon + 433 APCI1516_WATCHDOG_RELOAD_VALUE); 434 data[1] = data[1] >> 16; 435 outw(data[1], 436 devpriv->i_IobaseAddon + 437 APCI1516_WATCHDOG_RELOAD_VALUE + 2); 438 } /* if(data[0]==0) */ 439 else { 440 printk("\nThe input parameters are wrong\n"); 441 return -EINVAL; 442 } /* elseif(data[0]==0) */ 443 444 return insn->n; 445} 446 447 /* 448 +----------------------------------------------------------------------------+ 449 | Function Name : int i_APCI1516_StartStopWriteWatchdog | 450 | (struct comedi_device *dev,struct comedi_subdevice *s, 451 struct comedi_insn *insn,unsigned int *data); | 452 +----------------------------------------------------------------------------+ 453 | Task : Start / Stop The Watchdog | 454 +----------------------------------------------------------------------------+ 455 | Input Parameters : struct comedi_device *dev : Driver handle | 456 | struct comedi_subdevice *s, :pointer to subdevice structure 457 struct comedi_insn *insn :pointer to insn structure | 458 | unsigned int *data : Data Pointer to read status | 459 +----------------------------------------------------------------------------+ 460 | Output Parameters : -- | 461 +----------------------------------------------------------------------------+ 462 | Return Value : TRUE : No error occur | 463 | : FALSE : Error occur. Return the error | 464 | | 465 +----------------------------------------------------------------------------+ 466 */ 467 468int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 469 struct comedi_insn *insn, unsigned int *data) 470{ 471 switch (data[0]) { 472 case 0: /* stop the watchdog */ 473 outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); /* disable the watchdog */ 474 break; 475 case 1: /* start the watchdog */ 476 outw(0x0001, 477 devpriv->i_IobaseAddon + 478 APCI1516_WATCHDOG_ENABLEDISABLE); 479 break; 480 case 2: /* Software trigger */ 481 outw(0x0201, 482 devpriv->i_IobaseAddon + 483 APCI1516_WATCHDOG_ENABLEDISABLE); 484 break; 485 default: 486 printk("\nSpecified functionality does not exist\n"); 487 return -EINVAL; 488 } /* switch(data[0]) */ 489 return insn->n; 490} 491 492/* 493+----------------------------------------------------------------------------+ 494| Function Name : int i_APCI1516_ReadWatchdog | 495| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, 496 unsigned int *data); | 497+----------------------------------------------------------------------------+ 498| Task : Read The Watchdog | 499+----------------------------------------------------------------------------+ 500| Input Parameters : struct comedi_device *dev : Driver handle | 501| struct comedi_subdevice *s, :pointer to subdevice structure 502 struct comedi_insn *insn :pointer to insn structure | 503| unsigned int *data : Data Pointer to read status | 504+----------------------------------------------------------------------------+ 505| Output Parameters : -- | 506+----------------------------------------------------------------------------+ 507| Return Value : TRUE : No error occur | 508| : FALSE : Error occur. Return the error | 509| | 510+----------------------------------------------------------------------------+ 511*/ 512 513int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 514 struct comedi_insn *insn, unsigned int *data) 515{ 516 data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1; 517 return insn->n; 518} 519 520/* 521+----------------------------------------------------------------------------+ 522| Function Name : int i_APCI1516_Reset(struct comedi_device *dev) | | 523+----------------------------------------------------------------------------+ 524| Task :resets all the registers | 525+----------------------------------------------------------------------------+ 526| Input Parameters : struct comedi_device *dev 527+----------------------------------------------------------------------------+ 528| Output Parameters : -- | 529+----------------------------------------------------------------------------+ 530| Return Value : | 531| | 532+----------------------------------------------------------------------------+ 533*/ 534 535int i_APCI1516_Reset(struct comedi_device *dev) 536{ 537 outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP); /* RESETS THE DIGITAL OUTPUTS */ 538 outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); 539 outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE); 540 outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2); 541 return 0; 542} 543