tubttybld.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

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_unnext_char(tub_t *, char);
  17. static void tty3270_update_log_area(tub_t *, char **);
  18. static int tty3270_update_log_area_esc(tub_t *, char **, int *);
  19. static void tty3270_clear_log_area(tub_t *, char **);
  20. static void tty3270_tub_bufadr(tub_t *, int, char **);
  21. static void tty3270_set_bufadr(tub_t *, char **, int *);
  22. /*
  23.  * tty3270_clear_log_area(tub_t *tubp, char **cpp)
  24.  */
  25. static void
  26. tty3270_clear_log_area(tub_t *tubp, char **cpp)
  27. {
  28. *(*cpp)++ = TO_SBA;
  29. TUB_BUFADR(GEOM_LOG, cpp);
  30. *(*cpp)++ = TO_SF;
  31. *(*cpp)++ = TF_LOG;
  32. *(*cpp)++ = TO_RA;
  33. TUB_BUFADR(GEOM_INPUT, cpp);
  34. *(*cpp)++ = '';
  35. tubp->tty_oucol = tubp->tty_nextlogx = 0;
  36. *(*cpp)++ = TO_SBA;
  37. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  38. }
  39. static void
  40. tty3270_update_log_area(tub_t *tubp, char **cpp)
  41. {
  42. int lastx = GEOM_INPUT;
  43. int c;
  44. int next, fill, i;
  45. int sba_needed = 1;
  46. char *overrun = &(*tubp->ttyscreen)[tubp->ttyscreenl - TS_LENGTH];
  47. /* Check for possible ESC sequence work to do */
  48. if (tubp->tty_escx != 0) {
  49. /* If compiling new escape sequence */
  50. if (tubp->tty_esca[0] == 0x1b) {
  51. if (tty3270_update_log_area_esc(tubp, cpp, &sba_needed))
  52. return;
  53. /* If esc seq needs refreshing after a write */
  54. } else if (tubp->tty_esca[0] == TO_SA) {
  55. tty3270_set_bufadr(tubp, cpp, &sba_needed);
  56. for (i = 0; i < tubp->tty_escx; i++)
  57. *(*cpp)++ = tubp->tty_esca[i];
  58. } else {
  59. printk(KERN_WARNING "tty3270_update_log_area esca "
  60. "character surprising:  %.2xn", tubp->tty_esca[0]);
  61. }
  62. }
  63. /* Place characters */
  64. while (tubp->tty_bcb.bc_cnt != 0) {
  65. /* Check for room.  TAB could take up to 4 chars. */
  66. if (&(*cpp)[4] >= overrun)
  67. break;
  68. /* Fetch a character */
  69. if ((c = tty3270_next_char(tubp)) == -1)
  70. break;
  71. switch(c) {
  72. default:
  73. if (tubp->tty_nextlogx >= lastx) {
  74. if (sba_needed == 0 ||
  75.     tubp->stat == TBS_RUNNING) {
  76. tty3270_unnext_char(tubp, c);
  77. tubp->stat = TBS_MORE;
  78. tty3270_set_status_area(tubp, cpp);
  79. tty3270_scl_settimer(tubp);
  80. }
  81. goto do_return;
  82. }
  83. tty3270_set_bufadr(tubp, cpp, &sba_needed);
  84. /* Use blank if we don't know the character */
  85. *(*cpp)++ = tub_ascebc[(int)(c < ' '? ' ': c)];
  86. tubp->tty_nextlogx++;
  87. tubp->tty_oucol++;
  88. break;
  89. case 0x1b:              /* ESC */
  90. tubp->tty_escx = 0;
  91. if (tty3270_update_log_area_esc(tubp, cpp, &sba_needed))
  92. return;
  93. break;
  94. case 'r': /* 0x0d -- Carriage Return */
  95. tubp->tty_nextlogx -=
  96. tubp->tty_nextlogx % GEOM_COLS;
  97. sba_needed = 1;
  98. break;
  99. case 'n': /* 0x0a -- New Line */
  100. if (tubp->tty_oucol == GEOM_COLS) {
  101. tubp->tty_oucol = 0;
  102. break;
  103. }
  104. next = (tubp->tty_nextlogx + GEOM_COLS) /
  105. GEOM_COLS * GEOM_COLS;
  106. tubp->tty_nextlogx = next;
  107. tubp->tty_oucol = 0;
  108. sba_needed = 1;
  109. break;
  110. case 't': /* 0x09 -- Tabulate */
  111. tty3270_set_bufadr(tubp, cpp, &sba_needed);
  112. fill = (tubp->tty_nextlogx % GEOM_COLS) % 8;
  113. for (; fill < 8; fill++) {
  114. if (tubp->tty_nextlogx >= lastx)
  115. break;
  116. *(*cpp)++ = tub_ascebc[' '];
  117. tubp->tty_nextlogx++;
  118. tubp->tty_oucol++;
  119. }
  120. break;
  121. case 'a': /* 0x07 -- Alarm */
  122. tubp->flags |= TUB_ALARM;
  123. break;
  124. case 'f': /* 0x0c -- Form Feed */
  125. tty3270_clear_log_area(tubp, cpp);
  126. break;
  127. case 0xf: /* SuSE "exit alternate mode" */
  128. break;
  129. }
  130. }
  131. do_return:
  132. }
  133. #define NUMQUANT 8
  134. static int
  135. tty3270_update_log_area_esc(tub_t *tubp, char **cpp, int *sba_needed)
  136. {
  137. int c;
  138. int i, j;
  139. int start, end, next;
  140. int quant[NUMQUANT];
  141. char *overrun = &(*tubp->ttyscreen)[tubp->ttyscreenl - TS_LENGTH];
  142. char sabuf[NUMQUANT*3], *sap = sabuf, *cp;
  143. /* If starting a sequence, stuff ESC at [0] */
  144. if (tubp->tty_escx == 0)
  145. tubp->tty_esca[tubp->tty_escx++] = 0x1b;
  146. /* Now that sequence is started, see if room in buffer */
  147. if (&(*cpp)[NUMQUANT * 3] >= overrun)
  148. return tubp->tty_escx;
  149. /* Gather the rest of the sequence's characters */
  150. while (tubp->tty_escx < sizeof tubp->tty_esca) {
  151. if ((c = tty3270_next_char(tubp)) == -1)
  152. return tubp->tty_escx;
  153. if (tubp->tty_escx == 1) {
  154. switch(c) {
  155. case '[':
  156. tubp->tty_esca[tubp->tty_escx++] = c;
  157. continue;
  158. case '7':
  159. tubp->tty_savecursor = tubp->tty_nextlogx;
  160. goto done_return;
  161. case '8':
  162. next = tubp->tty_savecursor;
  163. goto do_setcur;
  164. default:
  165. goto error_return;
  166. }
  167. }
  168. tubp->tty_esca[tubp->tty_escx++] = c;
  169. if (c != ';' && (c < '0' || c > '9'))
  170. break;
  171. }
  172. /* Check for overrun */
  173. if (tubp->tty_escx == sizeof tubp->tty_esca)
  174. goto error_return;
  175. /* Parse potentially empty string "nn;nn;nn..." */
  176. i = -1;
  177. j = 2; /* skip ESC, [ */
  178. c = ';';
  179. do {
  180. if (c == ';') {
  181. if (++i == NUMQUANT)
  182. goto error_return;
  183. quant[i] = 0;
  184. } else if (c < '0' || c > '9') {
  185. break;
  186. } else {
  187. quant[i] = quant[i] * 10 + c - '0';
  188. }
  189. c = tubp->tty_esca[j];
  190. } while (j++ < tubp->tty_escx);
  191. /* Add 3270 data stream output to execute the sequence */
  192. switch(c) {
  193. case 'm': /* Set Attribute */
  194. for (next = 0; next <= i; next++) {
  195. int type = -1, value = 0;
  196. switch(quant[next]) {
  197. case 0: /* Reset */
  198. next = tubp->tty_nextlogx;
  199. tty3270_set_bufadr(tubp, cpp, sba_needed);
  200. *(*cpp)++ = TO_SA;
  201. *(*cpp)++ = TAT_EXTHI;
  202. *(*cpp)++ = TAX_RESET;
  203. *(*cpp)++ = TO_SA;
  204. *(*cpp)++ = TAT_COLOR;
  205. *(*cpp)++ = TAC_RESET;
  206. tubp->tty_nextlogx = next;
  207. *sba_needed = 1;
  208. sap = sabuf;
  209. break;
  210. case 1: /* Bright */
  211. break;
  212. case 2: /* Dim */
  213. break;
  214. case 4: /* Underscore */
  215. type = TAT_EXTHI; value = TAX_UNDER;
  216. break;
  217. case 5: /* Blink */
  218. type = TAT_EXTHI; value = TAX_BLINK;
  219. break;
  220. case 7: /* Reverse */
  221. type = TAT_EXTHI; value = TAX_REVER;
  222. break;
  223. case 8: /* Hidden */
  224. break; /* For now ... */
  225. /* Foreground Colors */
  226. case 30: /* Black */
  227. type = TAT_COLOR; value = TAC_DEFAULT;
  228. break;
  229. case 31: /* Red */
  230. type = TAT_COLOR; value = TAC_RED;
  231. break;
  232. case 32: /* Green */
  233. type = TAT_COLOR; value = TAC_GREEN;
  234. break;
  235. case 33: /* Yellow */
  236. type = TAT_COLOR; value = TAC_YELLOW;
  237. break;
  238. case 34: /* Blue */
  239. type = TAT_COLOR; value = TAC_BLUE;
  240. break;
  241. case 35: /* Magenta */
  242. type = TAT_COLOR; value = TAC_PINK;
  243. break;
  244. case 36: /* Cyan */
  245. type = TAT_COLOR; value = TAC_TURQ;
  246. break;
  247. case 37: /* White */
  248. type = TAT_COLOR; value = TAC_WHITE;
  249. break;
  250. case 39: /* Black */
  251. type = TAT_COLOR; value = TAC_DEFAULT;
  252. break;
  253. /* Background Colors */
  254. case 40: /* Black */
  255. case 41: /* Red */
  256. case 42: /* Green */
  257. case 43: /* Yellow */
  258. case 44: /* Blue */
  259. case 45: /* Magenta */
  260. case 46: /* Cyan */
  261. case 47: /* White */
  262. break; /* For now ... */
  263. /* Oops */
  264. default:
  265. break;
  266. }
  267. if (type != -1) {
  268. tty3270_set_bufadr(tubp, cpp, sba_needed);
  269. *(*cpp)++ = TO_SA;
  270. *(*cpp)++ = type;
  271. *(*cpp)++ = value;
  272. *sap++ = TO_SA;
  273. *sap++ = type;
  274. *sap++ = value;
  275. }
  276. }
  277. break;
  278. case 'H': /* Cursor Home */
  279. case 'f': /* Force Cursor Position */
  280. if (quant[0]) quant[0]--;
  281. if (quant[1]) quant[1]--;
  282. next = quant[0] * GEOM_COLS + quant[1];
  283. goto do_setcur;
  284. case 'A': /* Cursor Up */
  285. if (quant[i] == 0) quant[i] = 1;
  286. next = tubp->tty_nextlogx - GEOM_COLS * quant[i];
  287. goto do_setcur;
  288. case 'B': /* Cursor Down */
  289. if (quant[i] == 0) quant[i] = 1;
  290. next = tubp->tty_nextlogx + GEOM_COLS * quant[i];
  291. goto do_setcur;
  292. case 'C': /* Cursor Forward */
  293. if (quant[i] == 0) quant[i] = 1;
  294. next = tubp->tty_nextlogx % GEOM_COLS;
  295. start = tubp->tty_nextlogx - next;
  296. next = start + MIN(next + quant[i], GEOM_COLS - 1);
  297. goto do_setcur;
  298. case 'D': /* Cursor Backward */
  299. if (quant[i] == 0) quant[i] = 1;
  300. next = MIN(quant[i], tubp->tty_nextlogx % GEOM_COLS);
  301. next = tubp->tty_nextlogx - next;
  302. goto do_setcur;
  303. case 'G':
  304. if (quant[0]) quant[0]--;
  305. next = tubp->tty_nextlogx / GEOM_COLS * GEOM_COLS + quant[0];
  306. do_setcur:
  307. if (next < 0)
  308. break;
  309. tubp->tty_nextlogx = next;
  310. tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
  311. *sba_needed = 1;
  312. break;
  313. case 'r': /* Define scroll area */
  314. start = quant[0];
  315. if (start <= 0) start = 1;
  316. if (start > GEOM_ROWS - 2) start = GEOM_ROWS - 2;
  317. tubp->tty_nextlogx = (start - 1) * GEOM_COLS;
  318. tubp->tty_oucol = 0;
  319. *sba_needed = 1;
  320. break;
  321. case 'X': /* Erase for n chars from cursor */
  322. start = tubp->tty_nextlogx;
  323. end = start + (quant[0]?: 1);
  324. goto do_fill;
  325. case 'J': /* Erase to screen end from cursor */
  326. *(*cpp)++ = TO_SBA;
  327. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  328. *(*cpp)++ = TO_RA;
  329. TUB_BUFADR(GEOM_INPUT, cpp);
  330. *(*cpp)++ = tub_ascebc[' '];
  331. *(*cpp)++ = TO_SBA;
  332. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  333. break;
  334. case 'K':
  335. start = tubp->tty_nextlogx;
  336. end = (start + GEOM_COLS) / GEOM_COLS * GEOM_COLS;
  337. do_fill:
  338. if (start >= GEOM_INPUT)
  339. break;
  340. if (end > GEOM_INPUT)
  341. end = GEOM_INPUT;
  342. if (end <= start)
  343. break;
  344. *(*cpp)++ = TO_SBA;
  345. TUB_BUFADR(start, cpp);
  346. if (end - start > 4) {
  347. *(*cpp)++ = TO_RA;
  348. TUB_BUFADR(end, cpp);
  349. *(*cpp)++ = tub_ascebc[' '];
  350. } else while (start++ < end) {
  351. *(*cpp)++ = tub_ascebc[' '];
  352. }
  353. tubp->tty_nextlogx = end;
  354. tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
  355. *sba_needed = 1;
  356. break;
  357. }
  358. done_return:
  359. tubp->tty_escx = 0;
  360. cp = sabuf;
  361. while (cp != sap)
  362. tubp->tty_esca[tubp->tty_escx++] = *cp++;
  363. return 0;
  364. error_return:
  365. tubp->tty_escx = 0;
  366. return 0;
  367. }
  368. static int
  369. tty3270_next_char(tub_t *tubp)
  370. {
  371. int c;
  372. bcb_t *ib;
  373. ib = &tubp->tty_bcb;
  374. if (ib->bc_cnt == 0)
  375. return -1;
  376. c = ib->bc_buf[ib->bc_rd++];
  377. if (ib->bc_rd == ib->bc_len)
  378. ib->bc_rd = 0;
  379. ib->bc_cnt--;
  380. return c;
  381. }
  382. static void
  383. tty3270_unnext_char(tub_t *tubp, char c)
  384. {
  385. bcb_t *ib;
  386. ib = &tubp->tty_bcb;
  387. if (ib->bc_rd == 0)
  388. ib->bc_rd = ib->bc_len;
  389. ib->bc_buf[--ib->bc_rd] = c;
  390. ib->bc_cnt++;
  391. }
  392. static void
  393. tty3270_clear_input_area(tub_t *tubp, char **cpp)
  394. {
  395. *(*cpp)++ = TO_SBA;
  396. TUB_BUFADR(GEOM_INPUT, cpp);
  397. *(*cpp)++ = TO_SF;
  398. *(*cpp)++ = tubp->tty_inattr;
  399. *(*cpp)++ = TO_IC;
  400. *(*cpp)++ = TO_RA;
  401. TUB_BUFADR(GEOM_STAT, cpp);
  402. *(*cpp)++ = '';
  403. }
  404. static void
  405. tty3270_update_input_area(tub_t *tubp, char **cpp)
  406. {
  407. int len;
  408. *(*cpp)++ = TO_SBA;
  409. TUB_BUFADR(GEOM_INPUT, cpp);
  410. *(*cpp)++ = TO_SF;
  411. *(*cpp)++ = TF_INMDT;
  412. len = strlen(tubp->tty_input);
  413. memcpy(*cpp, tubp->tty_input, len);
  414. *cpp += len;
  415. *(*cpp)++ = TO_IC;
  416. len = GEOM_INPLEN - len;
  417. if (len > 4) {
  418. *(*cpp)++ = TO_RA;
  419. TUB_BUFADR(GEOM_STAT, cpp);
  420. *(*cpp)++ = '';
  421. } else {
  422. for (; len > 0; len--)
  423. *(*cpp)++ = '';
  424. }
  425. }
  426. /*
  427.  * tty3270_set_status_area(tub_t *tubp, char **cpp)
  428.  */
  429. static void
  430. tty3270_set_status_area(tub_t *tubp, char **cpp)
  431. {
  432. char *sp;
  433. if (tubp->stat == TBS_RUNNING)
  434. sp = TS_RUNNING;
  435. else if (tubp->stat == TBS_MORE)
  436. sp = TS_MORE;
  437. else if (tubp->stat == TBS_HOLD)
  438. sp = TS_HOLD;
  439. else
  440. sp = "Linux Whatstat";
  441. *(*cpp)++ = TO_SBA;
  442. TUB_BUFADR(GEOM_STAT, cpp);
  443. *(*cpp)++ = TO_SF;
  444. *(*cpp)++ = TF_STAT;
  445. memcpy(*cpp, sp, sizeof TS_RUNNING);
  446. TUB_ASCEBC(*cpp, sizeof TS_RUNNING);
  447. *cpp += sizeof TS_RUNNING;
  448. }
  449. /*
  450.  * tty3270_build() -- build an output stream
  451.  */
  452. int
  453. tty3270_build(tub_t *tubp)
  454. {
  455. char *cp, *startcp;
  456. int chancmd;
  457. int writecc = TW_KR;
  458. int force = 0;
  459. if (tubp->mode == TBM_FS)
  460. return 0;
  461. cp = startcp = *tubp->ttyscreen + 1;
  462. switch(tubp->cmd) {
  463. default:
  464. printk(KERN_WARNING "tty3270_build unknown command %dn", tubp->cmd);
  465. return 0;
  466. case TBC_OPEN:
  467. tbc_open:
  468. tubp->flags &= ~TUB_INPUT_HACK;
  469. chancmd = TC_EWRITEA;
  470. tty3270_clear_input_area(tubp, &cp);
  471. tty3270_set_status_area(tubp, &cp);
  472. tty3270_clear_log_area(tubp, &cp);
  473. break;
  474. case TBC_UPDLOG:
  475. if (tubp->flags & TUB_INPUT_HACK)
  476. goto tbc_open;
  477. chancmd = TC_WRITE;
  478. writecc = TW_NONE;
  479. tty3270_update_log_area(tubp, &cp);
  480. break;
  481. case TBC_KRUPDLOG:
  482. chancmd = TC_WRITE;
  483. force = 1;
  484. tty3270_update_log_area(tubp, &cp);
  485. break;
  486. case TBC_CLRUPDLOG:
  487. chancmd = TC_WRITE;
  488. tty3270_set_status_area(tubp, &cp);
  489. tty3270_clear_log_area(tubp, &cp);
  490. tty3270_update_log_area(tubp, &cp);
  491. break;
  492. case TBC_UPDATE:
  493. chancmd = TC_EWRITEA;
  494. tubp->tty_oucol = tubp->tty_nextlogx = 0;
  495. tty3270_clear_input_area(tubp, &cp);
  496. tty3270_set_status_area(tubp, &cp);
  497. tty3270_update_log_area(tubp, &cp);
  498. break;
  499. case TBC_UPDSTAT:
  500. chancmd = TC_WRITE;
  501. tty3270_set_status_area(tubp, &cp);
  502. break;
  503. case TBC_CLRINPUT:
  504. chancmd = TC_WRITE;
  505. tty3270_clear_input_area(tubp, &cp);
  506. break;
  507. case TBC_UPDINPUT:
  508. chancmd = TC_WRITE;
  509. tty3270_update_input_area(tubp, &cp);
  510. break;
  511. }
  512. /* Set Write Control Character and start I/O */
  513. if (force == 0 && cp == startcp &&
  514.     (tubp->flags & TUB_ALARM) == 0)
  515. return 0;
  516. if (tubp->flags & TUB_ALARM) {
  517. tubp->flags &= ~TUB_ALARM;
  518. writecc |= TW_PLUSALARM;
  519. }
  520. **tubp->ttyscreen = writecc;
  521. tubp->ttyccw.cmd_code = chancmd;
  522. tubp->ttyccw.flags = CCW_FLAG_SLI;
  523. tubp->ttyccw.cda = virt_to_phys(*tubp->ttyscreen);
  524. tubp->ttyccw.count = cp - *tubp->ttyscreen;
  525. tty3270_io(tubp);
  526. return 1;
  527. }
  528. static void
  529. tty3270_tub_bufadr(tub_t *tubp, int adr, char **cpp)
  530. {
  531. if (tubp->tty_14bitadr) {
  532. *(*cpp)++ = (adr >> 8) & 0x3f;
  533. *(*cpp)++ = adr & 0xff;
  534. } else {
  535. *(*cpp)++ = tub_ebcgraf[(adr >> 6) & 0x3f];
  536. *(*cpp)++ = tub_ebcgraf[adr & 0x3f];
  537. }
  538. }
  539. static void
  540. tty3270_set_bufadr(tub_t *tubp, char **cpp, int *sba_needed)
  541. {
  542. if (!*sba_needed)
  543. return;
  544. if (tubp->tty_nextlogx >= GEOM_INPUT) {
  545. tubp->tty_nextlogx = GEOM_INPUT - 1;
  546. tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
  547. }
  548. *(*cpp)++ = TO_SBA;
  549. TUB_BUFADR(tubp->tty_nextlogx, cpp);
  550. *sba_needed = 0;
  551. }