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

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