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