/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 832 lines · 387 code · 107 blank · 338 comment · 65 complexity · 1701c56b0426f5bfb1ca22a84320ace4 MD5 · raw file

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