hwdrv_apci2016.c revision dc8af06898c4326cee1739e2bc100bed2b601721
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-2016 | Compiler : GCC | 33 | Module name : hwdrv_apci2016.c| Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Acces For APCI-2016 | 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_apci2016.h" 55 56/* 57+----------------------------------------------------------------------------+ 58| Function Name : int i_APCI2016_ConfigDigitalOutput | 59| (struct comedi_device *dev,struct comedi_subdevice *s, | 60| struct comedi_insn *insn,unsigned int *data) | 61+----------------------------------------------------------------------------+ 62| Task : Configures The Digital Output Subdevice. | 63+----------------------------------------------------------------------------+ 64| Input Parameters : struct comedi_device *dev : Driver handle | 65| unsigned int *data : Data Pointer contains | 66| configuration parameters as below | 67| | 68| data[0] : 1 Digital Memory On | 69| 0 Digital Memory Off | 70+----------------------------------------------------------------------------+ 71| Output Parameters : -- | 72+----------------------------------------------------------------------------+ 73| Return Value : TRUE : No error occur | 74| : FALSE : Error occur. Return the error | 75| | 76+----------------------------------------------------------------------------+ 77*/ 78int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 79 struct comedi_insn *insn, unsigned int *data) 80{ 81 if ((data[0] != 0) && (data[0] != 1)) { 82 comedi_error(dev, 83 "Not a valid Data !!! ,Data should be 1 or 0\n"); 84 return -EINVAL; 85 } /* if ((data[0]!=0) && (data[0]!=1)) */ 86 if (data[0]) { 87 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; 88 } /* if (data[0] */ 89 else { 90 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; 91 } /* else if (data[0] */ 92 return insn->n; 93} 94 95/* 96+----------------------------------------------------------------------------+ 97| Function Name : int i_APCI2016_WriteDigitalOutput | 98| (struct comedi_device *dev,struct comedi_subdevice *s, | 99| struct comedi_insn *insn,unsigned int *data) | 100+----------------------------------------------------------------------------+ 101| Task : Writes port value To the selected port | 102+----------------------------------------------------------------------------+ 103| Input Parameters : struct comedi_device *dev : Driver handle | 104| unsigned int ui_NoOfChannels : No Of Channels To Write | 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*/ 114int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 115 struct comedi_insn *insn, unsigned int *data) 116{ 117 unsigned int ui_NoOfChannel; 118 unsigned int ui_Temp, ui_Temp1; 119 ui_NoOfChannel = CR_CHAN(insn->chanspec); 120 if (ui_NoOfChannel > 15) { 121 comedi_error(dev, 122 "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); 123 return -EINVAL; 124 } /* if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */ 125 if (devpriv->b_OutputMemoryStatus) { 126 ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP); 127 } /* if (devpriv->b_OutputMemoryStatus ) */ 128 else { 129 ui_Temp = 0; 130 } /* else if (devpriv->b_OutputMemoryStatus ) */ 131 if ((data[1] != 0) && (data[1] != 1)) { 132 comedi_error(dev, 133 "Invalid Data[1] value !!!, Data[1] should be 0 or 1\n"); 134 return -EINVAL; 135 } /* if ((data[1]!=0) && (data[1]!=1)) */ 136 137 if (data[3] == 0) { 138 if (data[1] == 0) { 139 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; 140 outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP); 141 } /* if (data[1]==0) */ 142 else { 143 if (data[1] == 1) { 144 switch (ui_NoOfChannel) { 145 case 2: 146 data[0] = 147 (data[0] << (2 * 148 data[2])) | ui_Temp; 149 break; 150 case 4: 151 data[0] = 152 (data[0] << (4 * 153 data[2])) | ui_Temp; 154 break; 155 case 8: 156 data[0] = 157 (data[0] << (8 * 158 data[2])) | ui_Temp; 159 break; 160 case 15: 161 data[0] = data[0] | ui_Temp; 162 break; 163 default: 164 comedi_error(dev, " chan spec wrong"); 165 return -EINVAL; /* "sorry channel spec wrong " */ 166 } /* switch(ui_NoOfChannels) */ 167 outw(data[0], 168 devpriv->iobase + APCI2016_DIGITAL_OP); 169 } /* if (data[1]==1) */ 170 else { 171 printk("\nSpecified channel not supported\n"); 172 } /* else if (data[1]==1) */ 173 } /* else if (data[1]==0) */ 174 } /* if (data[3]==0) */ 175 else { 176 if (data[3] == 1) { 177 if (data[1] == 0) { 178 data[0] = ~data[0] & 0x1; 179 ui_Temp1 = 1; 180 ui_Temp1 = ui_Temp1 << ui_NoOfChannel; 181 ui_Temp = ui_Temp | ui_Temp1; 182 data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff; 183 data[0] = data[0] & ui_Temp; 184 outw(data[0], 185 devpriv->iobase + APCI2016_DIGITAL_OP); 186 } /* if (data[1]==0) */ 187 else { 188 if (data[1] == 1) { 189 switch (ui_NoOfChannel) { 190 case 2: 191 data[0] = ~data[0] & 0x3; 192 ui_Temp1 = 3; 193 ui_Temp1 = 194 ui_Temp1 << 2 * data[2]; 195 ui_Temp = ui_Temp | ui_Temp1; 196 data[0] = 197 ((data[0] << (2 * 198 data 199 [2])) ^ 200 0xffff) & ui_Temp; 201 break; 202 case 4: 203 data[0] = ~data[0] & 0xf; 204 ui_Temp1 = 15; 205 ui_Temp1 = 206 ui_Temp1 << 4 * data[2]; 207 ui_Temp = ui_Temp | ui_Temp1; 208 data[0] = 209 ((data[0] << (4 * 210 data 211 [2])) ^ 212 0xffff) & ui_Temp; 213 break; 214 case 8: 215 data[0] = ~data[0] & 0xff; 216 ui_Temp1 = 255; 217 ui_Temp1 = 218 ui_Temp1 << 8 * data[2]; 219 ui_Temp = ui_Temp | ui_Temp1; 220 data[0] = 221 ((data[0] << (8 * 222 data 223 [2])) ^ 224 0xffff) & ui_Temp; 225 break; 226 case 15: 227 break; 228 default: 229 comedi_error(dev, 230 " chan spec wrong"); 231 return -EINVAL; /* "sorry channel spec wrong " */ 232 } /* switch(ui_NoOfChannels) */ 233 outw(data[0], 234 devpriv->iobase + 235 APCI2016_DIGITAL_OP); 236 } /* if(data[1]==1) */ 237 else { 238 printk("\nSpecified channel not supported\n"); 239 } /* else if(data[1]==1) */ 240 } /* elseif(data[1]==0) */ 241 } /* if(data[3]==1); */ 242 else { 243 printk("\nSpecified functionality does not exist\n"); 244 return -EINVAL; 245 } /* if else data[3]==1) */ 246 } /* if else data[3]==0) */ 247 return insn->n; 248} 249 250/* 251+----------------------------------------------------------------------------+ 252| Function Name : int i_APCI2016_BitsDigitalOutput | 253| (struct comedi_device *dev,struct comedi_subdevice *s, | 254| struct comedi_insn *insn,unsigned int *data) | 255+----------------------------------------------------------------------------+ 256| Task : Read value of the selected channel or port | 257+----------------------------------------------------------------------------+ 258| Input Parameters : struct comedi_device *dev : Driver handle | 259| unsigned int ui_NoOfChannels : No Of Channels To read | 260| unsigned int *data : Data Pointer to read status | 261+----------------------------------------------------------------------------+ 262| Output Parameters : -- | 263+----------------------------------------------------------------------------+ 264| Return Value : TRUE : No error occur | 265| : FALSE : Error occur. Return the error | 266| | 267+----------------------------------------------------------------------------+ 268*/ 269int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, 270 struct comedi_insn *insn, unsigned int *data) 271{ 272 unsigned int ui_Temp; 273 unsigned int ui_NoOfChannel; 274 ui_NoOfChannel = CR_CHAN(insn->chanspec); 275 if (ui_NoOfChannel > 15) { 276 comedi_error(dev, 277 "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); 278 return -EINVAL; 279 } /* if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */ 280 if ((data[0] != 0) && (data[0] != 1)) { 281 comedi_error(dev, 282 "Invalid Data[0] value !!!, Data[0] should be 0 or 1\n"); 283 return -EINVAL; 284 } /* if ((data[0]!=0) && (data[0]!=1)) */ 285 ui_Temp = data[0]; 286 *data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW); 287 if (ui_Temp == 0) { 288 *data = (*data >> ui_NoOfChannel) & 0x1; 289 } /* if (ui_Temp==0) */ 290 else { 291 if (ui_Temp == 1) { 292 switch (ui_NoOfChannel) { 293 case 2: 294 *data = (*data >> (2 * data[1])) & 3; 295 break; 296 297 case 4: 298 *data = (*data >> (4 * data[1])) & 15; 299 break; 300 301 case 8: 302 *data = (*data >> (8 * data[1])) & 255; 303 break; 304 305 case 15: 306 break; 307 308 default: 309 comedi_error(dev, " chan spec wrong"); 310 return -EINVAL; /* "sorry channel spec wrong " */ 311 } /* switch(ui_NoOfChannel) */ 312 } /* if (ui_Temp==1) */ 313 else { 314 printk("\nSpecified channel not supported \n"); 315 } /* else if (ui_Temp==1) */ 316 } /* if (ui_Temp==0) */ 317 return insn->n; 318} 319 320/* 321+----------------------------------------------------------------------------+ 322| Function Name : int i_APCI2016_ConfigWatchdog | 323| (struct comedi_device *dev,struct comedi_subdevice *s, | 324| struct comedi_insn *insn,unsigned int *data) | 325+----------------------------------------------------------------------------+ 326| Task : Configures The Watchdog | 327+----------------------------------------------------------------------------+ 328| Input Parameters : struct comedi_device *dev : Driver handle | 329| struct comedi_subdevice *s, :pointer to subdevice structure | 330| struct comedi_insn *insn :pointer to insn structure | 331| unsigned int *data : Data Pointer to read status | 332+----------------------------------------------------------------------------+ 333| Output Parameters : -- | 334+----------------------------------------------------------------------------+ 335| Return Value : TRUE : No error occur | 336| : FALSE : Error occur. Return the error | 337| | 338+----------------------------------------------------------------------------+ 339*/ 340int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 341 struct comedi_insn *insn, unsigned int *data) 342{ 343 344 if (data[0] == 0) { 345 /* Disable the watchdog */ 346 outw(0x0, 347 devpriv->i_IobaseAddon + 348 APCI2016_WATCHDOG_ENABLEDISABLE); 349 /* Loading the Reload value */ 350 outw(data[1], 351 devpriv->i_IobaseAddon + 352 APCI2016_WATCHDOG_RELOAD_VALUE); 353 data[1] = data[1] >> 16; 354 outw(data[1], 355 devpriv->i_IobaseAddon + 356 APCI2016_WATCHDOG_RELOAD_VALUE + 2); 357 } else { 358 printk("\nThe input parameters are wrong\n"); 359 } 360 return insn->n; 361} 362 363/* 364+----------------------------------------------------------------------------+ 365| Function Name : int i_APCI2016_StartStopWriteWatchdog | 366| (struct comedi_device *dev,struct comedi_subdevice *s, | 367| struct comedi_insn *insn,unsigned int *data) | 368+----------------------------------------------------------------------------+ 369| Task : Start / Stop The Watchdog | 370+----------------------------------------------------------------------------+ 371| Input Parameters : struct comedi_device *dev : Driver handle | 372| struct comedi_subdevice *s, :pointer to subdevice structure | 373| struct comedi_insn *insn :pointer to insn structure | 374| unsigned int *data : Data Pointer to read status | 375+----------------------------------------------------------------------------+ 376| Output Parameters : -- | 377+----------------------------------------------------------------------------+ 378| Return Value : TRUE : No error occur | 379| : FALSE : Error occur. Return the error | 380| | 381+----------------------------------------------------------------------------+ 382*/ 383int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 384 struct comedi_insn *insn, unsigned int *data) 385{ 386 387 switch (data[0]) { 388 case 0: /* stop the watchdog */ 389 outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); /* disable the watchdog */ 390 break; 391 case 1: /* start the watchdog */ 392 outw(0x0001, 393 devpriv->i_IobaseAddon + 394 APCI2016_WATCHDOG_ENABLEDISABLE); 395 break; 396 case 2: /* Software trigger */ 397 outw(0x0201, 398 devpriv->i_IobaseAddon + 399 APCI2016_WATCHDOG_ENABLEDISABLE); 400 break; 401 default: 402 printk("\nSpecified functionality does not exist\n"); 403 return -EINVAL; 404 } /* switch(data[0]) */ 405 406 return insn->n; 407} 408 409/* 410+----------------------------------------------------------------------------+ 411| Function Name : int i_APCI2016_ReadWatchdog | 412| (struct comedi_device *dev,struct comedi_subdevice *s, | 413| struct comedi_insn *insn,unsigned int *data) | 414+----------------------------------------------------------------------------+ 415| Task : Read The Watchdog | 416+----------------------------------------------------------------------------+ 417| Input Parameters : struct comedi_device *dev : Driver handle | 418| struct comedi_subdevice *s, :pointer to subdevice structure | 419| struct comedi_insn *insn :pointer to insn structure | 420| unsigned int *data : Data Pointer to read status | 421+----------------------------------------------------------------------------+ 422| Output Parameters : -- | 423+----------------------------------------------------------------------------+ 424| Return Value : TRUE : No error occur | 425| : FALSE : Error occur. Return the error | 426| | 427+----------------------------------------------------------------------------+ 428*/ 429 430int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, 431 struct comedi_insn *insn, unsigned int *data) 432{ 433 udelay(5); 434 data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1; 435 return insn->n; 436} 437 438/* 439+----------------------------------------------------------------------------+ 440| Function Name : int i_APCI2016_Reset(struct comedi_device *dev) | | 441+----------------------------------------------------------------------------+ 442| Task :resets all the registers | 443+----------------------------------------------------------------------------+ 444| Input Parameters : struct comedi_device *dev 445+----------------------------------------------------------------------------+ 446| Output Parameters : -- | 447+----------------------------------------------------------------------------+ 448| Return Value : | 449| | 450+----------------------------------------------------------------------------+ 451*/ 452 453int i_APCI2016_Reset(struct comedi_device *dev) 454{ 455 outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP); /* Resets the digital output channels */ 456 outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); 457 outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE); 458 outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2); 459 return 0; 460} 461