APCI1710_Ssi.c revision ff89514f8d46f470ffafeda129138ce73efd4c60
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 : API APCI1710 | Compiler : gcc | 33 | Module name : SSI.C | Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-----------------------------------------------------------------------+ 37 | Description : APCI-1710 SSI counter module | 38 | | 39 | | 40 +-----------------------------------------------------------------------+ 41 | UPDATES | 42 +-----------------------------------------------------------------------+ 43 | Date | Author | Description of updates | 44 +----------+-----------+------------------------------------------------+ 45 | 13/05/98 | S. Weber | SSI digital input / output implementation | 46 |----------|-----------|------------------------------------------------| 47 | 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 | 48 | | | Änderung in InitSSI Funktion | 49 | | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 | 50 | | | | 51 +-----------------------------------------------------------------------+ 52 | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | 53 | | | available | 54 +-----------------------------------------------------------------------+ 55*/ 56 57/* 58+----------------------------------------------------------------------------+ 59| Included files | 60+----------------------------------------------------------------------------+ 61*/ 62 63#include "APCI1710_Ssi.h" 64 65/* 66+----------------------------------------------------------------------------+ 67| Function Name : _INT_ i_APCI1710_InitSSI | 68| (unsigned char_ b_BoardHandle, | 69| unsigned char_ b_ModulNbr, | 70| unsigned char_ b_SSIProfile, | 71| unsigned char_ b_PositionTurnLength, | 72| unsigned char_ b_TurnCptLength, | 73| unsigned char_ b_PCIInputClock, | 74| ULONG_ ul_SSIOutputClock, | 75| unsigned char_ b_SSICountingMode) | 76+----------------------------------------------------------------------------+ 77| Task : Configure the SSI operating mode from selected module | 78| (b_ModulNbr). You must calling this function be for you| 79| call any other function witch access of SSI. | 80+----------------------------------------------------------------------------+ 81| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| 82| unsigned char_ b_ModulNbr : Module number to | 83| configure (0 to 3) | 84| unsigned char_ b_SSIProfile : Selection from SSI | 85| profile length (2 to 32).| 86| unsigned char_ b_PositionTurnLength : Selection from SSI | 87| position data length | 88| (1 to 31). | 89| unsigned char_ b_TurnCptLength : Selection from SSI turn | 90| counter data length | 91| (1 to 31). | 92| unsigned char b_PCIInputClock : Selection from PCI bus | 93| clock | 94| - APCI1710_30MHZ : | 95| The PC have a PCI bus | 96| clock from 30 MHz | 97| - APCI1710_33MHZ : | 98| The PC have a PCI bus | 99| clock from 33 MHz | 100| ULONG_ ul_SSIOutputClock : Selection from SSI output| 101| clock. | 102| From 229 to 5 000 000 Hz| 103| for 30 MHz selection. | 104| From 252 to 5 000 000 Hz| 105| for 33 MHz selection. | 106| unsigned char b_SSICountingMode : SSI counting mode | 107| selection | 108| - APCI1710_BINARY_MODE : | 109| Binary counting mode. | 110| - APCI1710_GRAY_MODE : | 111| Gray counting mode. 112 113 b_ModulNbr = CR_AREF(insn->chanspec); 114 b_SSIProfile = (unsigned char) data[0]; 115 b_PositionTurnLength= (unsigned char) data[1]; 116 b_TurnCptLength = (unsigned char) data[2]; 117 b_PCIInputClock = (unsigned char) data[3]; 118 ul_SSIOutputClock = (unsigned int) data[4]; 119 b_SSICountingMode = (unsigned char) data[5]; | 120+----------------------------------------------------------------------------+ 121| Output Parameters : - | 122+----------------------------------------------------------------------------+ 123| Return Value : 0: No error | 124| -1: The handle parameter of the board is wrong | 125| -2: The module parameter is wrong | 126| -3: The module is not a SSI module | 127| -4: The selected SSI profile length is wrong | 128| -5: The selected SSI position data length is wrong | 129| -6: The selected SSI turn counter data length is wrong | 130| -7: The selected PCI input clock is wrong | 131| -8: The selected SSI output clock is wrong | 132| -9: The selected SSI counting mode parameter is wrong | 133+----------------------------------------------------------------------------+ 134*/ 135 136int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s, 137 struct comedi_insn *insn, unsigned int *data) 138{ 139 int i_ReturnValue = 0; 140 unsigned int ui_TimerValue; 141 unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength, 142 b_PCIInputClock, b_SSICountingMode; 143 unsigned int ul_SSIOutputClock; 144 145 b_ModulNbr = CR_AREF(insn->chanspec); 146 b_SSIProfile = (unsigned char) data[0]; 147 b_PositionTurnLength = (unsigned char) data[1]; 148 b_TurnCptLength = (unsigned char) data[2]; 149 b_PCIInputClock = (unsigned char) data[3]; 150 ul_SSIOutputClock = (unsigned int) data[4]; 151 b_SSICountingMode = (unsigned char) data[5]; 152 153 i_ReturnValue = insn->n; 154 /**************************/ 155 /* Test the module number */ 156 /**************************/ 157 158 if (b_ModulNbr < 4) { 159 /***********************/ 160 /* Test if SSI counter */ 161 /***********************/ 162 163 if ((devpriv->s_BoardInfos. 164 dw_MolduleConfiguration[b_ModulNbr] & 165 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { 166 /*******************************/ 167 /* Test the SSI profile length */ 168 /*******************************/ 169 170 /* CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */ 171 if (b_SSIProfile >= 2 && b_SSIProfile < 33) { 172 /*************************************/ 173 /* Test the SSI position data length */ 174 /*************************************/ 175 176 if (b_PositionTurnLength > 0 177 && b_PositionTurnLength < 32) { 178 /*****************************************/ 179 /* Test the SSI turn counter data length */ 180 /*****************************************/ 181 182 if (b_TurnCptLength > 0 183 && b_TurnCptLength < 32) { 184 /***************************/ 185 /* Test the profile length */ 186 /***************************/ 187 188 if ((b_TurnCptLength + 189 b_PositionTurnLength) 190 <= b_SSIProfile) { 191 /****************************/ 192 /* Test the PCI input clock */ 193 /****************************/ 194 195 if (b_PCIInputClock == 196 APCI1710_30MHZ 197 || 198 b_PCIInputClock 199 == 200 APCI1710_33MHZ) 201 { 202 /*************************/ 203 /* Test the output clock */ 204 /*************************/ 205 206 if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) { 207 if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) { 208 /**********************/ 209 /* Save configuration */ 210 /**********************/ 211 devpriv-> 212 s_ModuleInfo 213 [b_ModulNbr]. 214 s_SSICounterInfo. 215 b_SSIProfile 216 = 217 b_SSIProfile; 218 219 devpriv-> 220 s_ModuleInfo 221 [b_ModulNbr]. 222 s_SSICounterInfo. 223 b_PositionTurnLength 224 = 225 b_PositionTurnLength; 226 227 devpriv-> 228 s_ModuleInfo 229 [b_ModulNbr]. 230 s_SSICounterInfo. 231 b_TurnCptLength 232 = 233 b_TurnCptLength; 234 235 /*********************************/ 236 /* Initialise the profile length */ 237 /*********************************/ 238 239 if (b_SSICountingMode == APCI1710_BINARY_MODE) { 240 241 outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); 242 } else { 243 244 outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); 245 } 246 247 /******************************/ 248 /* Calculate the output clock */ 249 /******************************/ 250 251 ui_TimerValue 252 = 253 (unsigned int) 254 ( 255 ((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock); 256 257 /************************/ 258 /* Initialise the timer */ 259 /************************/ 260 261 outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); 262 263 /********************************/ 264 /* Initialise the counting mode */ 265 /********************************/ 266 267 outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); 268 269 devpriv-> 270 s_ModuleInfo 271 [b_ModulNbr]. 272 s_SSICounterInfo. 273 b_SSIInit 274 = 275 1; 276 } else { 277 /*****************************************************/ 278 /* The selected SSI counting mode parameter is wrong */ 279 /*****************************************************/ 280 281 DPRINTK("The selected SSI counting mode parameter is wrong\n"); 282 i_ReturnValue 283 = 284 -9; 285 } 286 } else { 287 /******************************************/ 288 /* The selected SSI output clock is wrong */ 289 /******************************************/ 290 291 DPRINTK("The selected SSI output clock is wrong\n"); 292 i_ReturnValue 293 = 294 -8; 295 } 296 } else { 297 /*****************************************/ 298 /* The selected PCI input clock is wrong */ 299 /*****************************************/ 300 301 DPRINTK("The selected PCI input clock is wrong\n"); 302 i_ReturnValue = 303 -7; 304 } 305 } else { 306 /********************************************/ 307 /* The selected SSI profile length is wrong */ 308 /********************************************/ 309 310 DPRINTK("The selected SSI profile length is wrong\n"); 311 i_ReturnValue = -4; 312 } 313 } else { 314 /******************************************************/ 315 /* The selected SSI turn counter data length is wrong */ 316 /******************************************************/ 317 318 DPRINTK("The selected SSI turn counter data length is wrong\n"); 319 i_ReturnValue = -6; 320 } 321 } else { 322 /**************************************************/ 323 /* The selected SSI position data length is wrong */ 324 /**************************************************/ 325 326 DPRINTK("The selected SSI position data length is wrong\n"); 327 i_ReturnValue = -5; 328 } 329 } else { 330 /********************************************/ 331 /* The selected SSI profile length is wrong */ 332 /********************************************/ 333 334 DPRINTK("The selected SSI profile length is wrong\n"); 335 i_ReturnValue = -4; 336 } 337 } else { 338 /**********************************/ 339 /* The module is not a SSI module */ 340 /**********************************/ 341 342 DPRINTK("The module is not a SSI module\n"); 343 i_ReturnValue = -3; 344 } 345 } else { 346 /***********************/ 347 /* Module number error */ 348 /***********************/ 349 350 DPRINTK("Module number error\n"); 351 i_ReturnValue = -2; 352 } 353 354 return i_ReturnValue; 355} 356 357/* 358+----------------------------------------------------------------------------+ 359| Function Name : _INT_ i_APCI1710_Read1SSIValue | 360| (unsigned char_ b_BoardHandle, | 361| unsigned char_ b_ModulNbr, | 362| unsigned char_ b_SelectedSSI, | 363| PULONG_ pul_Position, | 364| PULONG_ pul_TurnCpt) 365 int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s, 366 struct comedi_insn *insn,unsigned int *data) | 367+----------------------------------------------------------------------------+ 368| Task : 369 370 371 Read the selected SSI counter (b_SelectedSSI) from | 372| selected module (b_ModulNbr). 373 or Read all SSI counter (b_SelectedSSI) from | 374| selected module (b_ModulNbr). | 375+----------------------------------------------------------------------------+ 376| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| 377| unsigned char_ b_ModulNbr : Module number to | 378| configure (0 to 3) | 379| unsigned char_ b_SelectedSSI : Selection from SSI | 380| counter (0 to 2) 381 382 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); 383 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi) 384 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec); 385| 386+----------------------------------------------------------------------------+ 387| Output Parameters : PULONG_ pul_Position : SSI position in the turn | 388| PULONG_ pul_TurnCpt : Number of turns 389 390pul_Position = (unsigned int *) &data[0]; 391 pul_TurnCpt = (unsigned int *) &data[1]; | 392+----------------------------------------------------------------------------+ 393| Return Value : 0: No error | 394| -1: The handle parameter of the board is wrong | 395| -2: The module parameter is wrong | 396| -3: The module is not a SSI module | 397| -4: SSI not initialised see function | 398| "i_APCI1710_InitSSI" | 399| -5: The selected SSI is wrong | 400+----------------------------------------------------------------------------+ 401*/ 402 403int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s, 404 struct comedi_insn *insn, unsigned int *data) 405{ 406 int i_ReturnValue = 0; 407 unsigned char b_Cpt; 408 unsigned char b_Length; 409 unsigned char b_Schift; 410 unsigned char b_SSICpt; 411 unsigned int dw_And; 412 unsigned int dw_And1; 413 unsigned int dw_And2; 414 unsigned int dw_StatusReg; 415 unsigned int dw_CounterValue; 416 unsigned char b_ModulNbr; 417 unsigned char b_SelectedSSI; 418 unsigned char b_ReadType; 419 unsigned int *pul_Position; 420 unsigned int *pul_TurnCpt; 421 unsigned int *pul_Position1; 422 unsigned int *pul_TurnCpt1; 423 424 i_ReturnValue = insn->n; 425 pul_Position1 = (unsigned int *) &data[0]; 426/* For Read1 */ 427 pul_TurnCpt1 = (unsigned int *) &data[1]; 428/* For Read all */ 429 pul_Position = (unsigned int *) &data[0]; /* 0-2 */ 430 pul_TurnCpt = (unsigned int *) &data[3]; /* 3-5 */ 431 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); 432 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); 433 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec); 434 435 /**************************/ 436 /* Test the module number */ 437 /**************************/ 438 439 if (b_ModulNbr < 4) { 440 /***********************/ 441 /* Test if SSI counter */ 442 /***********************/ 443 444 if ((devpriv->s_BoardInfos. 445 dw_MolduleConfiguration[b_ModulNbr] & 446 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { 447 /***************************/ 448 /* Test if SSI initialised */ 449 /***************************/ 450 451 if (devpriv->s_ModuleInfo[b_ModulNbr]. 452 s_SSICounterInfo.b_SSIInit == 1) { 453 454 switch (b_ReadType) { 455 456 case APCI1710_SSI_READ1VALUE: 457 /****************************************/ 458 /* Test the selected SSI counter number */ 459 /****************************************/ 460 461 if (b_SelectedSSI < 3) { 462 /************************/ 463 /* Start the conversion */ 464 /************************/ 465 466 outl(0, devpriv->s_BoardInfos. 467 ui_Address + 8 + 468 (64 * b_ModulNbr)); 469 470 do { 471 /*******************/ 472 /* Read the status */ 473 /*******************/ 474 475 dw_StatusReg = 476 inl(devpriv-> 477 s_BoardInfos. 478 ui_Address + 479 (64 * b_ModulNbr)); 480 } while ((dw_StatusReg & 0x1) 481 != 0); 482 483 /******************************/ 484 /* Read the SSI counter value */ 485 /******************************/ 486 487 dw_CounterValue = 488 inl(devpriv-> 489 s_BoardInfos. 490 ui_Address + 4 + 491 (b_SelectedSSI * 4) + 492 (64 * b_ModulNbr)); 493 494 b_Length = 495 devpriv-> 496 s_ModuleInfo 497 [b_ModulNbr]. 498 s_SSICounterInfo. 499 b_SSIProfile / 2; 500 501 if ((b_Length * 2) != 502 devpriv-> 503 s_ModuleInfo 504 [b_ModulNbr]. 505 s_SSICounterInfo. 506 b_SSIProfile) { 507 b_Length++; 508 } 509 510 b_Schift = 511 b_Length - 512 devpriv-> 513 s_ModuleInfo 514 [b_ModulNbr]. 515 s_SSICounterInfo. 516 b_PositionTurnLength; 517 518 *pul_Position1 = 519 dw_CounterValue >> 520 b_Schift; 521 522 dw_And = 1; 523 524 for (b_Cpt = 0; 525 b_Cpt < 526 devpriv-> 527 s_ModuleInfo 528 [b_ModulNbr]. 529 s_SSICounterInfo. 530 b_PositionTurnLength; 531 b_Cpt++) { 532 dw_And = dw_And * 2; 533 } 534 535 *pul_Position1 = 536 *pul_Position1 & 537 ((dw_And) - 1); 538 539 *pul_TurnCpt1 = 540 dw_CounterValue >> 541 b_Length; 542 543 dw_And = 1; 544 545 for (b_Cpt = 0; 546 b_Cpt < 547 devpriv-> 548 s_ModuleInfo 549 [b_ModulNbr]. 550 s_SSICounterInfo. 551 b_TurnCptLength; 552 b_Cpt++) { 553 dw_And = dw_And * 2; 554 } 555 556 *pul_TurnCpt1 = 557 *pul_TurnCpt1 & 558 ((dw_And) - 1); 559 } else { 560 /*****************************/ 561 /* The selected SSI is wrong */ 562 /*****************************/ 563 564 DPRINTK("The selected SSI is wrong\n"); 565 i_ReturnValue = -5; 566 } 567 break; 568 569 case APCI1710_SSI_READALLVALUE: 570 dw_And1 = 1; 571 572 for (b_Cpt = 0; 573 b_Cpt < 574 devpriv-> 575 s_ModuleInfo[b_ModulNbr]. 576 s_SSICounterInfo. 577 b_PositionTurnLength; b_Cpt++) { 578 dw_And1 = dw_And1 * 2; 579 } 580 581 dw_And2 = 1; 582 583 for (b_Cpt = 0; 584 b_Cpt < 585 devpriv-> 586 s_ModuleInfo[b_ModulNbr]. 587 s_SSICounterInfo. 588 b_TurnCptLength; b_Cpt++) { 589 dw_And2 = dw_And2 * 2; 590 } 591 592 /************************/ 593 /* Start the conversion */ 594 /************************/ 595 596 outl(0, devpriv->s_BoardInfos. 597 ui_Address + 8 + 598 (64 * b_ModulNbr)); 599 600 do { 601 /*******************/ 602 /* Read the status */ 603 /*******************/ 604 605 dw_StatusReg = 606 inl(devpriv-> 607 s_BoardInfos. 608 ui_Address + 609 (64 * b_ModulNbr)); 610 } while ((dw_StatusReg & 0x1) != 0); 611 612 for (b_SSICpt = 0; b_SSICpt < 3; 613 b_SSICpt++) { 614 /******************************/ 615 /* Read the SSI counter value */ 616 /******************************/ 617 618 dw_CounterValue = 619 inl(devpriv-> 620 s_BoardInfos. 621 ui_Address + 4 + 622 (b_SSICpt * 4) + 623 (64 * b_ModulNbr)); 624 625 b_Length = 626 devpriv-> 627 s_ModuleInfo 628 [b_ModulNbr]. 629 s_SSICounterInfo. 630 b_SSIProfile / 2; 631 632 if ((b_Length * 2) != 633 devpriv-> 634 s_ModuleInfo 635 [b_ModulNbr]. 636 s_SSICounterInfo. 637 b_SSIProfile) { 638 b_Length++; 639 } 640 641 b_Schift = 642 b_Length - 643 devpriv-> 644 s_ModuleInfo 645 [b_ModulNbr]. 646 s_SSICounterInfo. 647 b_PositionTurnLength; 648 649 pul_Position[b_SSICpt] = 650 dw_CounterValue >> 651 b_Schift; 652 pul_Position[b_SSICpt] = 653 pul_Position[b_SSICpt] & 654 ((dw_And1) - 1); 655 656 pul_TurnCpt[b_SSICpt] = 657 dw_CounterValue >> 658 b_Length; 659 pul_TurnCpt[b_SSICpt] = 660 pul_TurnCpt[b_SSICpt] & 661 ((dw_And2) - 1); 662 } 663 break; 664 665 default: 666 printk("Read Type Inputs Wrong\n"); 667 668 } /* switch ending */ 669 670 } else { 671 /***********************/ 672 /* SSI not initialised */ 673 /***********************/ 674 675 DPRINTK("SSI not initialised\n"); 676 i_ReturnValue = -4; 677 } 678 } else { 679 /**********************************/ 680 /* The module is not a SSI module */ 681 /**********************************/ 682 683 DPRINTK("The module is not a SSI module\n"); 684 i_ReturnValue = -3; 685 686 } 687 } else { 688 /***********************/ 689 /* Module number error */ 690 /***********************/ 691 692 DPRINTK("Module number error\n"); 693 i_ReturnValue = -2; 694 } 695 696 return i_ReturnValue; 697} 698 699/* 700+----------------------------------------------------------------------------+ 701| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput | 702| (unsigned char_ b_BoardHandle, | 703| unsigned char_ b_ModulNbr, | 704| unsigned char_ b_InputChannel, | 705| unsigned char *_ pb_ChannelStatus) | 706+----------------------------------------------------------------------------+ 707| Task : 708 (0) Set the digital output from selected SSI moule | 709| (b_ModuleNbr) ON 710 (1) Set the digital output from selected SSI moule | 711| (b_ModuleNbr) OFF 712 (2)Read the status from selected SSI digital input | 713| (b_InputChannel) 714 (3)Read the status from all SSI digital inputs from | 715| selected SSI module (b_ModulNbr) | 716+----------------------------------------------------------------------------+ 717| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| 718| unsigned char_ b_ModulNbr CR_AREF : Module number to | 719| configure (0 to 3) | 720| unsigned char_ b_InputChannel CR_CHAN : Selection from digital | 721| data[0] which IOTYPE input ( 0 to 2) | 722+----------------------------------------------------------------------------+ 723| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel | 724| data[0] status | 725| 0 : Channle is not active| 726| 1 : Channle is active | 727+----------------------------------------------------------------------------+ 728| Return Value : 0: No error | 729| -1: The handle parameter of the board is wrong | 730| -2: The module parameter is wrong | 731| -3: The module is not a SSI module | 732| -4: The selected SSI digital input is wrong | 733+----------------------------------------------------------------------------+ 734*/ 735 736int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s, 737 struct comedi_insn *insn, unsigned int *data) 738{ 739 int i_ReturnValue = 0; 740 unsigned int dw_StatusReg; 741 unsigned char b_ModulNbr; 742 unsigned char b_InputChannel; 743 unsigned char *pb_ChannelStatus; 744 unsigned char *pb_InputStatus; 745 unsigned char b_IOType; 746 i_ReturnValue = insn->n; 747 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); 748 b_IOType = (unsigned char) data[0]; 749 750 /**************************/ 751 /* Test the module number */ 752 /**************************/ 753 754 if (b_ModulNbr < 4) { 755 /***********************/ 756 /* Test if SSI counter */ 757 /***********************/ 758 759 if ((devpriv->s_BoardInfos. 760 dw_MolduleConfiguration[b_ModulNbr] & 761 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { 762 switch (b_IOType) { 763 case APCI1710_SSI_SET_CHANNELON: 764 /*****************************/ 765 /* Set the digital output ON */ 766 /*****************************/ 767 768 outl(1, devpriv->s_BoardInfos.ui_Address + 16 + 769 (64 * b_ModulNbr)); 770 break; 771 772 case APCI1710_SSI_SET_CHANNELOFF: 773 /******************************/ 774 /* Set the digital output OFF */ 775 /******************************/ 776 777 outl(0, devpriv->s_BoardInfos.ui_Address + 16 + 778 (64 * b_ModulNbr)); 779 break; 780 781 case APCI1710_SSI_READ_1CHANNEL: 782 /******************************************/ 783 /* Test the digital imnput channel number */ 784 /******************************************/ 785 786 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec); 787 pb_ChannelStatus = (unsigned char *) &data[0]; 788 789 if (b_InputChannel <= 2) { 790 /**************************/ 791 /* Read all digital input */ 792 /**************************/ 793 794 dw_StatusReg = 795 inl(devpriv->s_BoardInfos. 796 ui_Address + (64 * b_ModulNbr)); 797 *pb_ChannelStatus = 798 (unsigned char) (((~dw_StatusReg) >> (4 + 799 b_InputChannel)) 800 & 1); 801 } else { 802 /********************************/ 803 /* Selected digital input error */ 804 /********************************/ 805 806 DPRINTK("Selected digital input error\n"); 807 i_ReturnValue = -4; 808 } 809 break; 810 811 case APCI1710_SSI_READ_ALLCHANNEL: 812 /**************************/ 813 /* Read all digital input */ 814 /**************************/ 815 pb_InputStatus = (unsigned char *) &data[0]; 816 817 dw_StatusReg = 818 inl(devpriv->s_BoardInfos.ui_Address + 819 (64 * b_ModulNbr)); 820 *pb_InputStatus = 821 (unsigned char) (((~dw_StatusReg) >> 4) & 7); 822 break; 823 824 default: 825 printk("IO type wrong\n"); 826 827 } /* switch end */ 828 } else { 829 /**********************************/ 830 /* The module is not a SSI module */ 831 /**********************************/ 832 833 DPRINTK("The module is not a SSI module\n"); 834 i_ReturnValue = -3; 835 } 836 } else { 837 /***********************/ 838 /* Module number error */ 839 /***********************/ 840 841 DPRINTK("Module number error\n"); 842 i_ReturnValue = -2; 843 } 844 845 return i_ReturnValue; 846} 847