APCI1710_Ssi.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 : 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 } 481 while ((dw_StatusReg & 0x1) != 482 0); 483 484 /******************************/ 485 /* Read the SSI counter value */ 486 /******************************/ 487 488 dw_CounterValue = 489 inl(devpriv-> 490 s_BoardInfos. 491 ui_Address + 4 + 492 (b_SelectedSSI * 4) + 493 (64 * b_ModulNbr)); 494 495 b_Length = 496 devpriv-> 497 s_ModuleInfo 498 [b_ModulNbr]. 499 s_SSICounterInfo. 500 b_SSIProfile / 2; 501 502 if ((b_Length * 2) != 503 devpriv-> 504 s_ModuleInfo 505 [b_ModulNbr]. 506 s_SSICounterInfo. 507 b_SSIProfile) { 508 b_Length++; 509 } 510 511 b_Schift = 512 b_Length - 513 devpriv-> 514 s_ModuleInfo 515 [b_ModulNbr]. 516 s_SSICounterInfo. 517 b_PositionTurnLength; 518 519 *pul_Position1 = 520 dw_CounterValue >> 521 b_Schift; 522 523 dw_And = 1; 524 525 for (b_Cpt = 0; 526 b_Cpt < 527 devpriv-> 528 s_ModuleInfo 529 [b_ModulNbr]. 530 s_SSICounterInfo. 531 b_PositionTurnLength; 532 b_Cpt++) { 533 dw_And = dw_And * 2; 534 } 535 536 *pul_Position1 = 537 *pul_Position1 & 538 ((dw_And) - 1); 539 540 *pul_TurnCpt1 = 541 dw_CounterValue >> 542 b_Length; 543 544 dw_And = 1; 545 546 for (b_Cpt = 0; 547 b_Cpt < 548 devpriv-> 549 s_ModuleInfo 550 [b_ModulNbr]. 551 s_SSICounterInfo. 552 b_TurnCptLength; 553 b_Cpt++) { 554 dw_And = dw_And * 2; 555 } 556 557 *pul_TurnCpt1 = 558 *pul_TurnCpt1 & 559 ((dw_And) - 1); 560 } else { 561 /*****************************/ 562 /* The selected SSI is wrong */ 563 /*****************************/ 564 565 DPRINTK("The selected SSI is wrong\n"); 566 i_ReturnValue = -5; 567 } 568 break; 569 570 case APCI1710_SSI_READALLVALUE: 571 dw_And1 = 1; 572 573 for (b_Cpt = 0; 574 b_Cpt < 575 devpriv-> 576 s_ModuleInfo[b_ModulNbr]. 577 s_SSICounterInfo. 578 b_PositionTurnLength; b_Cpt++) { 579 dw_And1 = dw_And1 * 2; 580 } 581 582 dw_And2 = 1; 583 584 for (b_Cpt = 0; 585 b_Cpt < 586 devpriv-> 587 s_ModuleInfo[b_ModulNbr]. 588 s_SSICounterInfo. 589 b_TurnCptLength; b_Cpt++) { 590 dw_And2 = dw_And2 * 2; 591 } 592 593 /************************/ 594 /* Start the conversion */ 595 /************************/ 596 597 outl(0, devpriv->s_BoardInfos. 598 ui_Address + 8 + 599 (64 * b_ModulNbr)); 600 601 do { 602 /*******************/ 603 /* Read the status */ 604 /*******************/ 605 606 dw_StatusReg = 607 inl(devpriv-> 608 s_BoardInfos. 609 ui_Address + 610 (64 * b_ModulNbr)); 611 } 612 while ((dw_StatusReg & 0x1) != 0); 613 614 for (b_SSICpt = 0; b_SSICpt < 3; 615 b_SSICpt++) { 616 /******************************/ 617 /* Read the SSI counter value */ 618 /******************************/ 619 620 dw_CounterValue = 621 inl(devpriv-> 622 s_BoardInfos. 623 ui_Address + 4 + 624 (b_SSICpt * 4) + 625 (64 * b_ModulNbr)); 626 627 b_Length = 628 devpriv-> 629 s_ModuleInfo 630 [b_ModulNbr]. 631 s_SSICounterInfo. 632 b_SSIProfile / 2; 633 634 if ((b_Length * 2) != 635 devpriv-> 636 s_ModuleInfo 637 [b_ModulNbr]. 638 s_SSICounterInfo. 639 b_SSIProfile) { 640 b_Length++; 641 } 642 643 b_Schift = 644 b_Length - 645 devpriv-> 646 s_ModuleInfo 647 [b_ModulNbr]. 648 s_SSICounterInfo. 649 b_PositionTurnLength; 650 651 pul_Position[b_SSICpt] = 652 dw_CounterValue >> 653 b_Schift; 654 pul_Position[b_SSICpt] = 655 pul_Position[b_SSICpt] & 656 ((dw_And1) - 1); 657 658 pul_TurnCpt[b_SSICpt] = 659 dw_CounterValue >> 660 b_Length; 661 pul_TurnCpt[b_SSICpt] = 662 pul_TurnCpt[b_SSICpt] & 663 ((dw_And2) - 1); 664 } 665 break; 666 667 default: 668 printk("Read Type Inputs Wrong\n"); 669 670 } /* switch ending */ 671 672 } else { 673 /***********************/ 674 /* SSI not initialised */ 675 /***********************/ 676 677 DPRINTK("SSI not initialised\n"); 678 i_ReturnValue = -4; 679 } 680 } else { 681 /**********************************/ 682 /* The module is not a SSI module */ 683 /**********************************/ 684 685 DPRINTK("The module is not a SSI module\n"); 686 i_ReturnValue = -3; 687 688 } 689 } else { 690 /***********************/ 691 /* Module number error */ 692 /***********************/ 693 694 DPRINTK("Module number error\n"); 695 i_ReturnValue = -2; 696 } 697 698 return (i_ReturnValue); 699} 700 701/* 702+----------------------------------------------------------------------------+ 703| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput | 704| (unsigned char_ b_BoardHandle, | 705| unsigned char_ b_ModulNbr, | 706| unsigned char_ b_InputChannel, | 707| unsigned char *_ pb_ChannelStatus) | 708+----------------------------------------------------------------------------+ 709| Task : 710 (0) Set the digital output from selected SSI moule | 711| (b_ModuleNbr) ON 712 (1) Set the digital output from selected SSI moule | 713| (b_ModuleNbr) OFF 714 (2)Read the status from selected SSI digital input | 715| (b_InputChannel) 716 (3)Read the status from all SSI digital inputs from | 717| selected SSI module (b_ModulNbr) | 718+----------------------------------------------------------------------------+ 719| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| 720| unsigned char_ b_ModulNbr CR_AREF : Module number to | 721| configure (0 to 3) | 722| unsigned char_ b_InputChannel CR_CHAN : Selection from digital | 723| data[0] which IOTYPE input ( 0 to 2) | 724+----------------------------------------------------------------------------+ 725| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel | 726| data[0] status | 727| 0 : Channle is not active| 728| 1 : Channle is active | 729+----------------------------------------------------------------------------+ 730| Return Value : 0: No error | 731| -1: The handle parameter of the board is wrong | 732| -2: The module parameter is wrong | 733| -3: The module is not a SSI module | 734| -4: The selected SSI digital input is wrong | 735+----------------------------------------------------------------------------+ 736*/ 737 738int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s, 739 struct comedi_insn *insn, unsigned int *data) 740{ 741 int i_ReturnValue = 0; 742 unsigned int dw_StatusReg; 743 unsigned char b_ModulNbr; 744 unsigned char b_InputChannel; 745 unsigned char *pb_ChannelStatus; 746 unsigned char *pb_InputStatus; 747 unsigned char b_IOType; 748 i_ReturnValue = insn->n; 749 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); 750 b_IOType = (unsigned char) data[0]; 751 752 /**************************/ 753 /* Test the module number */ 754 /**************************/ 755 756 if (b_ModulNbr < 4) { 757 /***********************/ 758 /* Test if SSI counter */ 759 /***********************/ 760 761 if ((devpriv->s_BoardInfos. 762 dw_MolduleConfiguration[b_ModulNbr] & 763 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { 764 switch (b_IOType) { 765 case APCI1710_SSI_SET_CHANNELON: 766 /*****************************/ 767 /* Set the digital output ON */ 768 /*****************************/ 769 770 outl(1, devpriv->s_BoardInfos.ui_Address + 16 + 771 (64 * b_ModulNbr)); 772 break; 773 774 case APCI1710_SSI_SET_CHANNELOFF: 775 /******************************/ 776 /* Set the digital output OFF */ 777 /******************************/ 778 779 outl(0, devpriv->s_BoardInfos.ui_Address + 16 + 780 (64 * b_ModulNbr)); 781 break; 782 783 case APCI1710_SSI_READ_1CHANNEL: 784 /******************************************/ 785 /* Test the digital imnput channel number */ 786 /******************************************/ 787 788 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec); 789 pb_ChannelStatus = (unsigned char *) & data[0]; 790 791 if (b_InputChannel <= 2) { 792 /**************************/ 793 /* Read all digital input */ 794 /**************************/ 795 796 dw_StatusReg = 797 inl(devpriv->s_BoardInfos. 798 ui_Address + (64 * b_ModulNbr)); 799 *pb_ChannelStatus = 800 (unsigned char) (((~dw_StatusReg) >> (4 + 801 b_InputChannel)) 802 & 1); 803 } else { 804 /********************************/ 805 /* Selected digital input error */ 806 /********************************/ 807 808 DPRINTK("Selected digital input error\n"); 809 i_ReturnValue = -4; 810 } 811 break; 812 813 case APCI1710_SSI_READ_ALLCHANNEL: 814 /**************************/ 815 /* Read all digital input */ 816 /**************************/ 817 pb_InputStatus = (unsigned char *) & data[0]; 818 819 dw_StatusReg = 820 inl(devpriv->s_BoardInfos.ui_Address + 821 (64 * b_ModulNbr)); 822 *pb_InputStatus = 823 (unsigned char) (((~dw_StatusReg) >> 4) & 7); 824 break; 825 826 default: 827 printk("IO type wrong\n"); 828 829 } /* switch end */ 830 } else { 831 /**********************************/ 832 /* The module is not a SSI module */ 833 /**********************************/ 834 835 DPRINTK("The module is not a SSI module\n"); 836 i_ReturnValue = -3; 837 } 838 } else { 839 /***********************/ 840 /* Module number error */ 841 /***********************/ 842 843 DPRINTK("Module number error\n"); 844 i_ReturnValue = -2; 845 } 846 847 return (i_ReturnValue); 848} 849