gpio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: gpio.c
  4. 文件版本: 01.01
  5. 创建作者: zhaoyang
  6. 创建日期: 2023-12-14
  7. 功能说明: gpio驱动程序。
  8. 其它说明:
  9. 修改记录:
  10. [old]-->drop
  11. gpio0: a0111000.gpio -> gpiochip480 -> GPIO0_0
  12. gpio1: a0112000.gpio -> gpiochip448 -> GPIO1_0
  13. gpio2: a0387000.gpio -> gpiochip416 -> GPIO2_0
  14. gpio3: a0388000.gpio -> gpiochip384 -> GPIO3_0
  15. gpio4: a0919000.gpio -> gpiochip352 -> GPIO4_0
  16. gpio5: a091a000.gpio -> gpiochip320 -> GPIO5_0
  17. gpio6: a091b000.gpio -> gpiochip288 -> GPIO6_0
  18. gpio7: a091c000.gpio -> gpiochip256 -> GPIO7_0
  19. PDO0_1 --> GPIO5_22 --> gpio342
  20. PDO1_1 --> GPIO5_23 --> gpio343
  21. PDO2_1 --> GPIO5_24 --> gpio344
  22. PDO3_1 --> GPIO5_25 --> gpio345
  23. KOUT0 --> GPIO4_29 --> gpio381
  24. KOUT1 --> GPIO4_30 --> gpio382
  25. KOUT2 --> GPIO4_31 --> gpio383
  26. KOUT3 --> GPIO5_0 --> gpio320
  27. KOUT4 --> GPIO5_1 --> gpio321
  28. KOUT5 --> GPIO5_2 --> gpio322
  29. KOUT6 --> GPIO5_3 --> gpio323
  30. KOUT7 --> GPIO5_4 --> gpio324
  31. KOUT8 --> GPIO5_5 --> gpio325
  32. KOUT9 --> GPIO5_6 --> gpio326
  33. // sunxi 20220530 KOUT10 --> GPIO5_7 --> gpio327
  34. // sunxi 20220530 KOUT_EN0 --> GPIO5_8 --> gpio328
  35. // sunxi 20220530 KOUT_EN1 --> GPIO5_9 --> gpio329
  36. KOUT10 --> GPIO2_21 --> gpio437
  37. KOUT_EN0 --> GPIO3_18 --> gpio402
  38. KOUT_EN1 --> GPIO3_19 --> gpio403
  39. RUN led --> GPIO3_17 --> gpio401
  40. ERR led --> GPIO3_20 --> gpio404
  41. // sunxi 20220609 esam_pwr --> GPIO0_10 --> gpio490
  42. esam_pwr --> GPIO2_21 --> gpio437
  43. WTD --> GPIO0_31 --> gpio511
  44. [new]-->applay
  45. gpio0: a0111000.gpio -> gpiochip0 -> GPIO0_0
  46. gpio1: a0112000.gpio -> gpiochip32 -> GPIO1_0
  47. gpio2: a0387000.gpio -> gpiochip64 -> GPIO2_0
  48. gpio3: a0388000.gpio -> gpiochip96 -> GPIO3_0
  49. gpio4: a0919000.gpio -> gpiochip128 -> GPIO4_0
  50. gpio5: a091a000.gpio -> gpiochip160 -> GPIO5_0
  51. gpio6: a091b000.gpio -> gpiochip192 -> GPIO6_0
  52. gpio7: a091c000.gpio -> gpiochip224 -> GPIO7_0
  53. PDO0_1 --> GPIO5_22 --> gpio182
  54. PDO1_1 --> GPIO5_23 --> gpio183
  55. PDO2_1 --> GPIO5_24 --> gpio184
  56. PDO3_1 --> GPIO5_25 --> gpio185
  57. KOUT0 --> GPIO4_29 --> gpio157
  58. KOUT1 --> GPIO4_30 --> gpio158
  59. KOUT2 --> GPIO4_31 --> gpio159
  60. KOUT3 --> GPIO5_0 --> gpio160
  61. KOUT4 --> GPIO5_1 --> gpio161
  62. KOUT5 --> GPIO5_2 --> gpio162
  63. KOUT6 --> GPIO5_3 --> gpio163
  64. KOUT7 --> GPIO5_4 --> gpio164
  65. KOUT8 --> GPIO5_5 --> gpio165
  66. KOUT9 --> GPIO5_6 --> gpio166
  67. // zhaoyang 20231214 KOUT10 --> GPIO5_7 --> gpio167
  68. // zhaoyang 20231214 KOUT_EN0 --> GPIO5_8 --> gpio168
  69. // zhaoyang 20231214 KOUT_EN1 --> GPIO5_9 --> gpio169
  70. KOUT10 --> GPIO2_21 --> gpio85
  71. KOUT_EN0 --> GPIO3_18 --> gpio114
  72. KOUT_EN1 --> GPIO3_19 --> gpio115
  73. RUN led --> GPIO3_17 --> gpio113
  74. ERR led --> GPIO3_20 --> gpio116
  75. // zhaoyang 20231214 esam_pwr --> GPIO0_10 --> gpio10
  76. esam_pwr --> GPIO2_21 --> gpio85
  77. WTD --> GPIO0_31 --> gpio31
  78. T536 start ↓↓↓↓↓↓
  79. RUN_LED --> PB7
  80. ERR_LED --> PF4
  81. ESAM_PWR --> PL7
  82. LINE_LOSS_SET --> PM5
  83. T536 end ↑↑↑↑↑↑
  84. */
  85. /*------------------------------- 头文件 --------------------------------------
  86. */
  87. #include "bspconfig.h"
  88. #include "gpio.h"
  89. #include "head.h"
  90. /*------------------------------- 宏定义 --------------------------------------
  91. */
  92. #if CFG_BSP_DEBUG
  93. #define _GPIO_DEBUG
  94. #endif
  95. /*------------------------------ 全局变量 -------------------------------------
  96. */
  97. unsigned short kc_pwm0_stu;
  98. unsigned short kc_pwm1_stu;
  99. unsigned short kc_kout0_stu;
  100. unsigned short kc_kout1_stu;
  101. extern uint32_t g_yx_buf[2]; //预留64个遥信
  102. /*------------------------------ 函数声明 -------------------------------------
  103. */
  104. extern unsigned int change_di_ch(unsigned int di);
  105. int gpio_val_fd[DO_NUM];
  106. const int gpio_val[DO_NUM] = {96, 97, 98, 99, 100, 101, 102, 103, 104, 105};
  107. int gpio_val_fd_other[GPIO_NUM_OTHER];
  108. const int gpio_val_other[GPIO_NUM_OTHER] ={39,164,359,389};
  109. // static int gpio_watchdog_val = 0;
  110. static int gpio_run_led_val = 0;
  111. /*------------------------------ 外部函数 -------------------------------------
  112. */
  113. /******************************************************************************
  114. 函数名称: gpio_init
  115. 函数版本: 01.01
  116. 创建作者: sunxi
  117. 创建日期: 2008-06-26
  118. 函数说明: gpio初始化。
  119. 参数说明: 无
  120. 返回值: 成功返回0.
  121. 修改记录:
  122. */
  123. int gpio_init(void)
  124. {
  125. int i, j;
  126. int exportfd, directionfd;
  127. char num[10];
  128. char path[50] = "";
  129. //do
  130. exportfd = open("/sys/class/gpio/export", O_WRONLY);
  131. if (exportfd < 0)
  132. {
  133. printf("Cannot open GPIO to export it\n");
  134. return -1;
  135. }
  136. #ifndef GW_AREA_MAIN_2021
  137. for (i = 0; i < DO_NUM; i ++)
  138. {
  139. sprintf(num, "%d", gpio_val[i]);
  140. write(exportfd, num, 4);
  141. gpio_val_fd[i] = -1;
  142. }
  143. #endif
  144. for (i = 0; i < GPIO_NUM_OTHER; i ++)
  145. {
  146. sprintf(num, "%d", gpio_val_other[i]);
  147. write(exportfd, num, 4);
  148. gpio_val_fd_other[i] = -1;
  149. }
  150. close(exportfd);
  151. #ifndef GW_AREA_MAIN_2021
  152. for (i = 0; i < DO_NUM; i ++)
  153. {
  154. sprintf(path, "/sys/class/gpio/gpio%d/value", gpio_val[i]);
  155. gpio_val_fd[i] = open(path, O_RDWR);
  156. if (gpio_val_fd[i] < 0)
  157. {
  158. printf("Cannot open GPIO%d value!\n", gpio_val[i]);
  159. for(j = 0; j < i; j ++)
  160. {
  161. close(gpio_val_fd[j]);
  162. gpio_val_fd[j] = -1;
  163. }
  164. return -4;
  165. }
  166. }
  167. // Update the direction of the GPIO to be an output
  168. for (i = 0; i < DO_NUM; i ++)
  169. {
  170. sprintf(path, "/sys/class/gpio/gpio%d/direction", gpio_val[i]);
  171. directionfd = open(path, O_RDWR);
  172. if (directionfd < 0)
  173. {
  174. printf("Cannot open GPIO%d direction!\n", gpio_val[i]);
  175. return -2;
  176. }
  177. write(directionfd, "out", 4);
  178. write(gpio_val_fd[i], "1", 2);
  179. close(directionfd);
  180. }
  181. #endif
  182. msleep(10);// 延时10ms
  183. for (i = 0; i < GPIO_NUM_OTHER; i ++)
  184. {
  185. sprintf(path, "/sys/class/gpio/gpio%d/value", gpio_val_other[i]);
  186. gpio_val_fd_other[i] = open(path, O_RDWR);
  187. if (gpio_val_fd_other[i] < 0)
  188. {
  189. printf("Cannot open GPIO%d value!\n", gpio_val_other[i]);
  190. for(j = 0; j < i; j ++)
  191. {
  192. close(gpio_val_fd_other[j]);
  193. gpio_val_fd_other[j] = -1;
  194. }
  195. #ifndef GW_AREA_MAIN_2021
  196. for(j = 0; j < DO_NUM; j ++)
  197. {
  198. close(gpio_val_fd[j]);
  199. gpio_val_fd[j] = -1;
  200. }
  201. #endif
  202. return -5;
  203. }
  204. }
  205. for (i = 0; i < GPIO_NUM_OTHER; i ++)
  206. {
  207. sprintf(path, "/sys/class/gpio/gpio%d/direction", gpio_val_other[i]);
  208. directionfd = open(path, O_RDWR);
  209. if (directionfd < 0)
  210. {
  211. printf("Cannot open GPIO%d direction!\n", gpio_val_other[i]);
  212. return -3;
  213. }
  214. write(directionfd, "out", 4);
  215. close(directionfd);
  216. }
  217. kc_pwm0_stu = 0;
  218. kc_pwm1_stu = 0;
  219. kc_kout0_stu=0;
  220. kc_kout1_stu=0;
  221. //其他与底层GPIO相关的配置再此处添加 比如 LED WATCHDOG jack.liu 202009010
  222. // write(gpio_val_fd_other[WATCHDOG], "0", 2);//TODO: 需根据实际硬件重新对应匹配
  223. // gpio_watchdog_val = 0;
  224. write(gpio_val_fd_other[RUN_LED], "0", 2);
  225. gpio_run_led_val = 0;
  226. //上电默认切换到外部232串口
  227. //后续根据投退判断是否需要切换到线损的维护口
  228. write(gpio_val_fd_other[LINE_LOSS_SET], "0", 2);
  229. //首次上电,开出合闸,会导致第六路也开出,需要初始化关闭
  230. // write(gpio_val_fd[DO_OUT1], "1", 2);
  231. //开启esam供电
  232. write(gpio_val_fd_other[ESAM_PWR], "0", 2);
  233. #ifndef GW_AREA_MAIN_2021
  234. for (i = 0; i < DO_NUM; i ++)
  235. {
  236. write(gpio_val_fd[i], "1", 2);
  237. }
  238. #endif
  239. return 0;
  240. }
  241. int gpio_exit(void)
  242. {
  243. int i;
  244. int unexportfd;
  245. char num[10];
  246. unexportfd = open("/sys/class/gpio/unexport", O_WRONLY);
  247. if (unexportfd < 0)
  248. {
  249. printf("Cannot open GPIO to unexport it\n");
  250. return -1;
  251. }
  252. #ifndef GW_AREA_MAIN_2021
  253. for (i = 0; i < DO_NUM; i ++)
  254. {
  255. if(gpio_val_fd[i] >= 0)
  256. {
  257. close(gpio_val_fd[i]);
  258. gpio_val_fd[i] = -1;
  259. }
  260. sprintf(num, "%d", gpio_val[i]);
  261. write(unexportfd, num, 4);
  262. }
  263. #endif
  264. for (i = 0; i < GPIO_NUM_OTHER; i ++)
  265. {
  266. if(gpio_val_fd_other[i] >= 0)
  267. {
  268. close(gpio_val_fd_other[i]);
  269. gpio_val_fd_other[i] = -1;
  270. }
  271. sprintf(num, "%d", gpio_val_other[i]);
  272. write(unexportfd, num, 4);
  273. }
  274. close(unexportfd);
  275. return 0;
  276. }
  277. /******************************************************************************
  278. 函数名称: gpio_get_kin
  279. 函数版本: 01.01
  280. 创建作者: sunxi
  281. 创建日期: 2008-09-16
  282. 函数说明: 得到开入的状态。
  283. 参数说明: 无
  284. 返回值: 返回开入的状态,每个bit代表一个开入量。
  285. 修改记录:
  286. */
  287. unsigned int gpio_get_kin(unsigned int addr)
  288. {
  289. register unsigned int dw;
  290. unsigned int value[3];
  291. value[0] = *(volatile unsigned int *)addr;
  292. value[1] = *(volatile unsigned int *)addr;
  293. value[2] = *(volatile unsigned int *)addr;
  294. dw = (value[0] & value[1]) | (value[0] & value[2]) | (value[1] & value[2]);
  295. return dw;
  296. }
  297. /******************************************************************************
  298. 函数名称: gpio_get_di
  299. 函数版本: 01.01
  300. 创建作者:
  301. 创建日期: 2014-11-28
  302. 函数说明: 得到开入的状态
  303. 参数说明: 无
  304. 返回值: 返回开入的状态,每个bit代表一个开入量。
  305. 修改记录:
  306. */
  307. unsigned int gpio_get_di(void)
  308. {
  309. return 0;
  310. #ifndef GW_AREA_MAIN_2021
  311. unsigned int dw = 0;
  312. dw = g_yx_buf[0];//这里保存的是共享内存的yx值,156us更新一次
  313. return change_di_ch(~dw);//取反---因为没有短接时,值为1. 所以要取反为0才行
  314. #endif
  315. }
  316. /******************************************************************************
  317. 函数名称: gpio_di_fj
  318. 函数版本: 01.01
  319. 创建作者:
  320. 创建日期: 2014-11-28
  321. 函数说明: 读取开出返校遥信值,控制板遥信为YX17~YX18
  322. YX17:选择, YX18:执行
  323. 参数说明: 无
  324. 返回值: 返回遥信值
  325. 修改记录:
  326. */
  327. #ifdef DO_KOUT_CHECK
  328. unsigned short gpio_di_fj(unsigned char index)//(void)
  329. #else
  330. unsigned short gpio_di_fj(void)
  331. #endif
  332. {
  333. unsigned int di=0;
  334. unsigned short ret=0;
  335. di = gpio_get_di();
  336. #ifdef DO_KOUT_CHECK
  337. //V4-20;
  338. //ret = (unsigned short)((di >>19) & 0x0001);
  339. ret = (unsigned short)((di >>index) & 0x0001);
  340. #else
  341. ret = (unsigned short)((di >> 23) & 0x0001);//dtu
  342. #endif
  343. return ret;
  344. }
  345. static void gpio_kouten_do(int on, unsigned int kouten)
  346. {
  347. // if (kouten > KOUT_EN1)
  348. // return;
  349. // if(on)
  350. // {
  351. // write(gpio_val_fd_other[KOUT_EN0+kouten], "1", 2);
  352. // }
  353. // else
  354. // {
  355. // write(gpio_val_fd_other[KOUT_EN0+kouten], "0", 2);
  356. // }
  357. }
  358. /******************************************************************************
  359. 函数名称: gpio_kout_do
  360. 函数版本: 01.01
  361. 创建作者:
  362. 创建日期: 2014-11-28
  363. 函数说明: 开出
  364. 参数说明: on: 1开出, 0回收
  365. kout: 那一路
  366. 返回值: 无
  367. 修改记录:
  368. */
  369. void gpio_kout_do(int on, unsigned int kout)
  370. {
  371. //if (kout > (DO_NUM-DO_OUT0))
  372. // return;
  373. if(on)
  374. {
  375. if((kout==6) || (kout==7))
  376. {
  377. // gpio_kouten_do(1,KOUT_EN1);
  378. kc_kout1_stu |= (1 << kout);
  379. }
  380. else
  381. {
  382. // gpio_kouten_do(1,KOUT_EN0);
  383. kc_kout0_stu |= (1 << kout);
  384. }
  385. write(gpio_val_fd[kout+DO_OUT0], "0", 2);
  386. }
  387. else
  388. {
  389. write(gpio_val_fd[kout+DO_OUT0], "1", 2);
  390. if((kout==6) || (kout==7))
  391. {
  392. kc_kout1_stu &= ~(1 << kout);
  393. }
  394. else
  395. {
  396. kc_kout0_stu &= ~(1 << kout);
  397. }
  398. if ((kc_pwm1_stu== 0) &&(kc_kout1_stu == 0))
  399. {
  400. // gpio_kouten_do(0,KOUT_EN1);
  401. }
  402. if ((kc_kout0_stu == 0) && (kc_pwm0_stu==0))
  403. {
  404. // gpio_kouten_do(0,KOUT_EN0);
  405. }
  406. }
  407. }
  408. /******************************************************************************
  409. 函数名称: gpio_pwm_do
  410. 函数版本: 01.01
  411. 创建作者:
  412. 创建日期: 2014-11-28
  413. 函数说明: pwm开出,由于存在kc_pwm_stu,只允许在同一控制路径中开出(例如同一中断或同一线程).
  414. 参数说明: on: 1开出, 0回收
  415. 返回值: 无
  416. 修改记录:
  417. */
  418. void gpio_pwm_do(int on, unsigned int kout)
  419. {
  420. // if (kout >= DO_NUM)
  421. // return;
  422. if(on)
  423. {
  424. if((kout==0) || (kout==1))
  425. {
  426. // gpio_kouten_do(1,KOUT_EN1);
  427. kc_pwm1_stu |= (1 << kout);
  428. }
  429. else
  430. {
  431. // gpio_kouten_do(1,KOUT_EN0);
  432. kc_pwm0_stu |= (1 << kout);
  433. }
  434. write(gpio_val_fd[kout], "0", 2);
  435. }
  436. else
  437. {
  438. write(gpio_val_fd[kout], "1", 2);
  439. if((kout==0) || (kout==1))
  440. {
  441. kc_pwm1_stu &= ~(1 << kout);
  442. }
  443. else
  444. {
  445. kc_pwm0_stu &= ~(1 << kout);
  446. }
  447. if ((kc_pwm1_stu== 0) &&(kc_kout1_stu == 0))
  448. {
  449. // gpio_kouten_do(0,KOUT_EN1);
  450. }
  451. if ((kc_kout0_stu == 0) && (kc_pwm0_stu==0))
  452. {
  453. // gpio_kouten_do(0,KOUT_EN0);
  454. }
  455. }
  456. }
  457. /******************************************************************************
  458. 函数名称: gpio_get_wirelessin
  459. 函数版本: 01.01
  460. 创建作者: sunxi
  461. 创建日期: 2008-09-16
  462. 函数说明: 得到无线遥控的状态。
  463. 参数说明: 无
  464. 返回值: 返回开入的状态,每个bit代表一个开入量。
  465. 修改记录:
  466. */
  467. unsigned int gpio_get_wirelessin(void)
  468. {
  469. register unsigned int dw = 0;
  470. return dw;
  471. }
  472. unsigned int gpio_get_version(void)
  473. {
  474. register unsigned int dw = 0;
  475. return dw;
  476. }
  477. unsigned int gpio_get_addr(void)
  478. {
  479. register unsigned int dw = 0;
  480. return dw;
  481. }
  482. /******************************************************************************
  483. 函数名称: gpio_watchdog_reset
  484. 函数版本: 01.01
  485. 创建作者: sunxi
  486. 创建日期: 2008-09-16
  487. 函数说明: 复位看门狗。
  488. 参数说明: 无。
  489. 返回值: 无。
  490. 修改记录:
  491. */
  492. // void gpio_watchdog_reset(void)
  493. // {
  494. // if(gpio_watchdog_val)
  495. // {
  496. // gpio_watchdog_val = 0;
  497. // write(gpio_val_fd_other[WATCHDOG], "0", 2);
  498. // }
  499. // else
  500. // {
  501. // gpio_watchdog_val = 1;
  502. // write(gpio_val_fd_other[WATCHDOG], "1", 2);
  503. // }
  504. // return;
  505. // }
  506. void _led_run_err(void)
  507. {
  508. //运行指示灯,每隔0.5s改变状态一次
  509. if(!gpio_run_led_val)
  510. {
  511. gpio_run_led_val = 1;
  512. write(gpio_val_fd_other[RUN_LED], "0", 2);
  513. //错误指示灯,跟随RUN灯闪动
  514. if(rt_err_count())
  515. {
  516. write(gpio_val_fd_other[ERR_LED], "0", 2);
  517. }
  518. }
  519. else
  520. {
  521. gpio_run_led_val = 0;
  522. write(gpio_val_fd_other[RUN_LED], "1", 2);
  523. write(gpio_val_fd_other[ERR_LED], "1", 2);
  524. }
  525. }
  526. void esam_power_ctrl(int on)
  527. {
  528. if(on)
  529. write(gpio_val_fd_other[ESAM_PWR], "1", 2);
  530. else
  531. write(gpio_val_fd_other[ESAM_PWR], "0", 2);
  532. }
  533. /*------------------------------ 内部函数 -------------------------------------
  534. */
  535. /*------------------------------ 测试函数 -------------------------------------
  536. */
  537. #ifdef _GPIO_DEBUG
  538. #include "ustimer.h"
  539. #include "rt.h"
  540. int gpio_test(void)
  541. {
  542. int ret = 0;
  543. //unsigned int i;
  544. //gpio_kouten_do(1,KOUT_EN1);
  545. #if 1
  546. while(1)
  547. {
  548. sleep(5);
  549. gpio_kout_do(1,DO_OUT2-DO_OUT0);
  550. //gpio_kout_do(1,DO_OUT3-DO_OUT0);
  551. // gpio_pwm_do(1,DO_PWM1);
  552. sleep(5);
  553. gpio_kout_do(0,DO_OUT2-DO_OUT0);
  554. //gpio_kout_do(0,DO_OUT3-DO_OUT0);
  555. // gpio_pwm_do(0,DO_PWM1);
  556. /*
  557. for(i=DO_OUT0; i<DO_NUM; i++)
  558. {
  559. rt_printf("kout number = %d!\n\r", i);
  560. //msleep();
  561. sleep(1);
  562. gpio_kout_do(1,i-DO_OUT0);
  563. sleep(1);
  564. gpio_kout_do(0,i-DO_OUT0);
  565. }
  566. */
  567. }
  568. #endif
  569. return ret;
  570. }
  571. #endif