tubttybld.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC
  3.  *
  4.  *  tubttybld.c -- Linemode tty driver screen-building functions
  5.  *
  6.  *
  7.  *
  8.  *
  9.  *
  10.  *  Author:  Richard Hitt
  11.  */
  12. #include "tubio.h"
  13. extern int tty3270_io(tub_t *);
  14. static void tty3270_set_status_area(tub_t *, char **);
  15. static int tty3270_next_char(tub_t *);
  16. static void tty3270_update_log_area(tub_t *, char **);
  17. static void tty3270_update_log_area_esc(tub_t *, char **);
  18. static void tty3270_clear_log_area(tub_t *, char **);
  19. static void tty3270_tub_bufadr(tub_t *, int, char **);
  20. /*
  21.  * tty3270_clear_log_area(tub_t *tubp, char **cpp)
  22.  */
  23. static void
  24. tty3270_clear_log_area(tub_t *tubp, char **cpp)
  25. {
  26. *(*cpp)++ = TO_SBA;
  27. TUB_BUFADR(GEOM_LOG, cpp);
  28. *(*cpp)++ = TO_SF;
  29. *(*cpp)++ = TF_LOG;
  30. *(*cpp)++ = TO_RA;
  31. TUB_BUFADR(GEOM_INPUT, cpp);
  32. *(*cpp)++ = '';
  33. tubp->tty_oucol = tubp->tty_nextlogx = 0;
  34. *(*cpp)++ = TO_SBA;
  35. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  36. }
  37. static void
  38. tty3270_update_log_area(tub_t *tubp, char **cpp)
  39. {
  40. int lastx = GEOM_INPUT;
  41. int c;
  42. int next, fill, i;
  43. int sba_needed = 1;
  44. char *overrun = &(*tubp->ttyscreen)[tubp->ttyscreenl - TS_LENGTH];
  45. /* Place characters */
  46. while (tubp->tty_bcb.bc_cnt != 0) {
  47. if (tubp->tty_nextlogx >= lastx) {
  48. if (sba_needed == 0 || tubp->stat == TBS_RUNNING) {
  49. tubp->stat = TBS_MORE;
  50. tty3270_set_status_area(tubp, cpp);
  51. tty3270_scl_settimer(tubp);
  52. }
  53. break;
  54. }
  55. /* Check for room for another char + possible ESCs */
  56. if (&(*cpp)[tubp->tty_escx + 1] >= overrun)
  57. break;
  58. /* Fetch a character */
  59. if ((c = tty3270_next_char(tubp)) == -1)
  60. break;
  61. /* Add a Set-Buffer-Address Order if we haven't */
  62. if (sba_needed) {
  63. sba_needed = 0;
  64. *(*cpp)++ = TO_SBA;
  65. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  66. }
  67. switch(c) {
  68. default:
  69. if (c < ' ')    /* Blank it if we don't know it */
  70. c = ' ';
  71. for (i = 0; i < tubp->tty_escx; i++)
  72. *(*cpp)++ = tubp->tty_esca[i];
  73. tubp->tty_escx = 0;
  74. *(*cpp)++ = tub_ascebc[(int)c];
  75. tubp->tty_nextlogx++;
  76. tubp->tty_oucol++;
  77. break;
  78. case 0x1b:              /* ESC */
  79. tty3270_update_log_area_esc(tubp, cpp);
  80. break;
  81. case 'r':
  82. break;          /* completely ignore 0x0d = CR. */
  83. case 'n':
  84. if (tubp->tty_oucol == GEOM_COLS) {
  85. tubp->tty_oucol = 0;
  86. break;
  87. }
  88. next = (tubp->tty_nextlogx + GEOM_COLS) /
  89. GEOM_COLS * GEOM_COLS;
  90. next = MIN(next, lastx);
  91. fill = next - tubp->tty_nextlogx;
  92. if (fill < 5) {
  93. for (i = 0; i < fill; i++)
  94. *(*cpp)++ = tub_ascebc[' '];
  95. } else {
  96. *(*cpp)++ = TO_RA;
  97. TUB_BUFADR(next, cpp);
  98. *(*cpp)++ = tub_ascebc[' '];
  99. }
  100. tubp->tty_nextlogx = next;
  101. tubp->tty_oucol = 0;
  102. break;
  103. case 't':
  104. fill = (tubp->tty_nextlogx % GEOM_COLS) % 8;
  105. for (; fill < 8; fill++) {
  106. if (tubp->tty_nextlogx >= lastx)
  107. break;
  108. *(*cpp)++ = tub_ascebc[' '];
  109. tubp->tty_nextlogx++;
  110. tubp->tty_oucol++;
  111. }
  112. break;
  113. case 'a':
  114. tubp->flags |= TUB_ALARM;
  115. break;
  116. case 'f':
  117. tty3270_clear_log_area(tubp, cpp);
  118. break;
  119. }
  120. }
  121. }
  122. #define NUMQUANT 8
  123. static void
  124. tty3270_update_log_area_esc(tub_t *tubp, char **cpp)
  125. {
  126. int lastx = GEOM_INPUT;
  127. int c;
  128. int i;
  129. int start, next, fill;
  130. int quant[NUMQUANT];
  131. if ((c = tty3270_next_char(tubp)) != '[') {
  132. return;
  133. }
  134. /*
  135.  * Parse potentially empty string "nn;nn;nn..."
  136.  */
  137. i = -1;
  138. c = ';';
  139. do {
  140. if (c == ';') {
  141. if (++i == NUMQUANT)
  142. break;
  143. quant[i] = 0;
  144. } else if (c < '0' || c > '9') {
  145. break;
  146. } else {
  147. quant[i] = quant[i] * 10 + c - '0';
  148. }
  149. } while ((c = tty3270_next_char(tubp)) != -1);
  150. if (c == -1) {
  151. return;
  152. }
  153. if (i >= NUMQUANT) {
  154. return;
  155. }
  156. switch(c) {
  157. case -1:
  158. return;
  159. case 'm': /* Set Attribute */
  160. for (next = 0; next <= i; next++) {
  161. int type = -1, value = 0;
  162. if (tubp->tty_escx + 3 > MAX_TTY_ESCA)
  163. break;
  164. switch(quant[next]) {
  165. case 0: /* Reset */
  166. tubp->tty_esca[tubp->tty_escx++] = TO_SA;
  167. tubp->tty_esca[tubp->tty_escx++] = TAT_RESET;
  168. tubp->tty_esca[tubp->tty_escx++] = TAR_RESET;
  169. break;
  170. case 1: /* Bright */
  171. case 2: /* Dim */
  172. case 4: /* Underscore */
  173. case 5: /* Blink */
  174. case 7: /* Reverse */
  175. case 8: /* Hidden */
  176. break; /* For now ... */
  177. /* Foreground Colors */
  178. case 30: /* Black */
  179. type = TAT_COLOR; value = TAC_DEFAULT;
  180. break;
  181. case 31: /* Red */
  182. type = TAT_COLOR; value = TAC_RED;
  183. break;
  184. case 32: /* Green */
  185. type = TAT_COLOR; value = TAC_GREEN;
  186. break;
  187. case 33: /* Yellow */
  188. type = TAT_COLOR; value = TAC_YELLOW;
  189. break;
  190. case 34: /* Blue */
  191. type = TAT_COLOR; value = TAC_BLUE;
  192. break;
  193. case 35: /* Magenta */
  194. type = TAT_COLOR; value = TAC_PINK;
  195. break;
  196. case 36: /* Cyan */
  197. type = TAT_COLOR; value = TAC_TURQ;
  198. break;
  199. case 37: /* White */
  200. type = TAT_COLOR; value = TAC_WHITE;
  201. break;
  202. case 39: /* Black */
  203. type = TAT_COLOR; value = TAC_DEFAULT;
  204. break;
  205. /* Background Colors */
  206. case 40: /* Black */
  207. case 41: /* Red */
  208. case 42: /* Green */
  209. case 43: /* Yellow */
  210. case 44: /* Blue */
  211. case 45: /* Magenta */
  212. case 46: /* Cyan */
  213. case 47: /* White */
  214. break; /* For now ... */
  215. /* Oops */
  216. default:
  217. break;
  218. }
  219. if (type != -1) {
  220. tubp->tty_esca[tubp->tty_escx++] = TO_SA;
  221. tubp->tty_esca[tubp->tty_escx++] = type;
  222. tubp->tty_esca[tubp->tty_escx++] = value;
  223. }
  224. }
  225. break;
  226. case 'H': /* Cursor Home */
  227. case 'f': /* Force Cursor Position */
  228. return;
  229. case 'A': /* Cursor Up */
  230. return;
  231. case 'B': /* Cursor Down */
  232. return;
  233. case 'C': /* Cursor Forward */
  234. next = tubp->tty_nextlogx % GEOM_COLS;
  235. start = tubp->tty_nextlogx - next;
  236. next = start + MIN(next + quant[i], GEOM_COLS - 1);
  237. next = MIN(next, lastx);
  238. do_fill:
  239. fill = next - tubp->tty_nextlogx;
  240. if (fill < 5) {
  241. for (i = 0; i < fill; i++)
  242. *(*cpp)++ = tub_ascebc[' '];
  243. } else {
  244. *(*cpp)++ = TO_RA;
  245. TUB_BUFADR(next, cpp);
  246. *(*cpp)++ = tub_ascebc[' '];
  247. }
  248. tubp->tty_nextlogx = next;
  249. tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
  250. break;
  251. case 'D': /* Cursor Backward */
  252. next = MIN(quant[i], tubp->tty_nextlogx % GEOM_COLS);
  253. tubp->tty_nextlogx -= next;
  254. tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
  255. *(*cpp)++ = TO_SBA;
  256. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  257. break;
  258. case 'G':
  259. start = tubp->tty_nextlogx / GEOM_COLS * GEOM_COLS;
  260. next = MIN(quant[i], GEOM_COLS - 1) + start;
  261. next = MIN(next, lastx);
  262. goto do_fill;
  263. }
  264. }
  265. static int
  266. tty3270_next_char(tub_t *tubp)
  267. {
  268. int c;
  269. bcb_t *ib;
  270. ib = &tubp->tty_bcb;
  271. if (ib->bc_cnt == 0)
  272. return -1;
  273. c = ib->bc_buf[ib->bc_rd++];
  274. if (ib->bc_rd == ib->bc_len)
  275. ib->bc_rd = 0;
  276. ib->bc_cnt--;
  277. return c;
  278. }
  279. static void
  280. tty3270_clear_input_area(tub_t *tubp, char **cpp)
  281. {
  282. *(*cpp)++ = TO_SBA;
  283. TUB_BUFADR(GEOM_INPUT, cpp);
  284. *(*cpp)++ = TO_SF;
  285. *(*cpp)++ = tubp->tty_inattr;
  286. *(*cpp)++ = TO_IC;
  287. *(*cpp)++ = TO_RA;
  288. TUB_BUFADR(GEOM_STAT, cpp);
  289. *(*cpp)++ = '';
  290. }
  291. static void
  292. tty3270_update_input_area(tub_t *tubp, char **cpp)
  293. {
  294. int len;
  295. *(*cpp)++ = TO_SBA;
  296. TUB_BUFADR(GEOM_INPUT, cpp);
  297. *(*cpp)++ = TO_SF;
  298. *(*cpp)++ = TF_INMDT;
  299. len = strlen(tubp->tty_input);
  300. memcpy(*cpp, tubp->tty_input, len);
  301. *cpp += len;
  302. *(*cpp)++ = TO_IC;
  303. len = GEOM_INPLEN - len;
  304. if (len > 4) {
  305. *(*cpp)++ = TO_RA;
  306. TUB_BUFADR(GEOM_STAT, cpp);
  307. *(*cpp)++ = '';
  308. } else {
  309. for (; len > 0; len--)
  310. *(*cpp)++ = '';
  311. }
  312. }
  313. /*
  314.  * tty3270_set_status_area(tub_t *tubp, char **cpp)
  315.  */
  316. static void
  317. tty3270_set_status_area(tub_t *tubp, char **cpp)
  318. {
  319. char *sp;
  320. if (tubp->stat == TBS_RUNNING)
  321. sp = TS_RUNNING;
  322. else if (tubp->stat == TBS_MORE)
  323. sp = TS_MORE;
  324. else if (tubp->stat == TBS_HOLD)
  325. sp = TS_HOLD;
  326. else
  327. sp = "Linux Whatstat";
  328. *(*cpp)++ = TO_SBA;
  329. TUB_BUFADR(GEOM_STAT, cpp);
  330. *(*cpp)++ = TO_SF;
  331. *(*cpp)++ = TF_STAT;
  332. memcpy(*cpp, sp, sizeof TS_RUNNING);
  333. TUB_ASCEBC(*cpp, sizeof TS_RUNNING);
  334. *cpp += sizeof TS_RUNNING;
  335. }
  336. /*
  337.  * tty3270_build() -- build an output stream
  338.  */
  339. int
  340. tty3270_build(tub_t *tubp)
  341. {
  342. char *cp, *startcp;
  343. int chancmd;
  344. int writecc = TW_KR;
  345. int force = 0;
  346. if (tubp->mode == TBM_FS)
  347. return 0;
  348. cp = startcp = *tubp->ttyscreen + 1;
  349. switch(tubp->cmd) {
  350. default:
  351. printk(KERN_WARNING "tty3270_build unknown command %dn", tubp->cmd);
  352. return 0;
  353. case TBC_OPEN:
  354. tbc_open:
  355. tubp->flags &= ~TUB_INPUT_HACK;
  356. chancmd = TC_EWRITEA;
  357. tty3270_clear_input_area(tubp, &cp);
  358. tty3270_set_status_area(tubp, &cp);
  359. tty3270_clear_log_area(tubp, &cp);
  360. break;
  361. case TBC_UPDLOG:
  362. if (tubp->flags & TUB_INPUT_HACK)
  363. goto tbc_open;
  364. chancmd = TC_WRITE;
  365. writecc = TW_NONE;
  366. tty3270_update_log_area(tubp, &cp);
  367. break;
  368. case TBC_KRUPDLOG:
  369. chancmd = TC_WRITE;
  370. force = 1;
  371. tty3270_update_log_area(tubp, &cp);
  372. break;
  373. case TBC_CLRUPDLOG:
  374. chancmd = TC_WRITE;
  375. tty3270_set_status_area(tubp, &cp);
  376. tty3270_clear_log_area(tubp, &cp);
  377. tty3270_update_log_area(tubp, &cp);
  378. break;
  379. case TBC_UPDATE:
  380. chancmd = TC_EWRITEA;
  381. tubp->tty_oucol = tubp->tty_nextlogx = 0;
  382. tty3270_clear_input_area(tubp, &cp);
  383. tty3270_set_status_area(tubp, &cp);
  384. tty3270_update_log_area(tubp, &cp);
  385. break;
  386. case TBC_UPDSTAT:
  387. chancmd = TC_WRITE;
  388. tty3270_set_status_area(tubp, &cp);
  389. break;
  390. case TBC_CLRINPUT:
  391. chancmd = TC_WRITE;
  392. tty3270_clear_input_area(tubp, &cp);
  393. break;
  394. case TBC_UPDINPUT:
  395. chancmd = TC_WRITE;
  396. tty3270_update_input_area(tubp, &cp);
  397. break;
  398. }
  399. /* Set Write Control Character and start I/O */
  400. if (force == 0 && cp == startcp &&
  401.     (tubp->flags & TUB_ALARM) == 0)
  402. return 0;
  403. if (tubp->flags & TUB_ALARM) {
  404. tubp->flags &= ~TUB_ALARM;
  405. writecc |= TW_PLUSALARM;
  406. }
  407. **tubp->ttyscreen = writecc;
  408. tubp->ttyccw.cmd_code = chancmd;
  409. tubp->ttyccw.flags = CCW_FLAG_SLI;
  410. tubp->ttyccw.cda = virt_to_phys(*tubp->ttyscreen);
  411. tubp->ttyccw.count = cp - *tubp->ttyscreen;
  412. tty3270_io(tubp);
  413. return 1;
  414. }
  415. static void
  416. tty3270_tub_bufadr(tub_t *tubp, int adr, char **cpp)
  417. {
  418. if (tubp->tty_14bitadr) {
  419. *(*cpp)++ = (adr >> 8) & 0x3f;
  420. *(*cpp)++ = adr & 0xff;
  421. } else {
  422. *(*cpp)++ = tub_ebcgraf[(adr >> 6) & 0x3f];
  423. *(*cpp)++ = tub_ebcgraf[adr & 0x3f];
  424. }
  425. }