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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  IBM/3270 Driver -- Copyright (C) 2000, 2001 UTS Global LLC
  3.  *
  4.  *  tubtty.c -- Linemode tty driver
  5.  *
  6.  *
  7.  *
  8.  *
  9.  *
  10.  *  Author:  Richard Hitt
  11.  */
  12. #include <linux/config.h>
  13. #include "tubio.h"
  14. /* Initialization & uninitialization for tubtty */
  15. int tty3270_init(void);
  16. void tty3270_fini(void);
  17. /* Interface routines from the upper tty layer to the tty driver */
  18. static int tty3270_open(struct tty_struct *, struct file *);
  19. static void tty3270_close(struct tty_struct *, struct file *);
  20. static int tty3270_write(struct tty_struct *, int,
  21.         const unsigned char *, int);
  22. static void tty3270_put_char(struct tty_struct *, unsigned char);
  23. static void tty3270_flush_chars(struct tty_struct *);
  24. static int tty3270_write_room(struct tty_struct *);
  25. static int tty3270_chars_in_buffer(struct tty_struct *);
  26. static int tty3270_ioctl(struct tty_struct *, struct file *,
  27. unsigned int cmd, unsigned long arg);
  28. static void tty3270_set_termios(struct tty_struct *, struct termios *);
  29. static void tty3270_hangup(struct tty_struct *);
  30. static void tty3270_flush_buffer(struct tty_struct *);
  31. static int tty3270_read_proc(char *, char **, off_t, int, int *, void *);
  32. static int tty3270_write_proc(struct file *, const char *,
  33. unsigned long, void *);
  34. /* tty3270 utility functions */
  35. static void tty3270_bh(void *);
  36.        void tty3270_sched_bh(tub_t *);
  37. static int tty3270_wait(tub_t *, long *);
  38.        void tty3270_int(tub_t *, devstat_t *);
  39.        int tty3270_try_logging(tub_t *);
  40. static void tty3270_start_input(tub_t *);
  41. static void tty3270_do_input(tub_t *);
  42. static void tty3270_do_enter(tub_t *, char *, int);
  43. static void tty3270_do_showi(tub_t *, char *, int);
  44.        int tty3270_io(tub_t *);
  45. static int tty3270_show_tube(int, char *, int);
  46. int tty3270_major = -1;
  47. struct tty_driver tty3270_driver;
  48. int tty3270_refcount;
  49. struct tty_struct *tty3270_table[TUBMAXMINS];
  50. struct termios *tty3270_termios[TUBMAXMINS];
  51. struct termios *tty3270_termios_locked[TUBMAXMINS];
  52. #ifdef CONFIG_TN3270_CONSOLE
  53. int con3270_major = -1;
  54. struct tty_driver con3270_driver;
  55. int con3270_refcount;
  56. struct tty_struct *con3270_table[1];
  57. struct termios *con3270_termios[1];
  58. struct termios *con3270_termios_locked[1];
  59. #endif /* CONFIG_TN3270_CONSOLE */
  60. int tty3270_proc_index;
  61. int tty3270_proc_data;
  62. int tty3270_proc_misc;
  63. enum tubwhat tty3270_proc_what;
  64. /*
  65.  * tty3270_init() -- Register the tty3270 driver
  66.  */
  67. int
  68. tty3270_init(void)
  69. {
  70. struct tty_driver *td = &tty3270_driver;
  71. int rc;
  72. /* Initialize for tty driver */
  73. td->magic = TTY_DRIVER_MAGIC;
  74. td->driver_name = "tty3270";
  75. td->name = "tty3270";
  76. td->major = IBM_TTY3270_MAJOR;
  77. td->minor_start = 0;
  78. td->num = TUBMAXMINS;
  79. td->type = TTY_DRIVER_TYPE_SYSTEM;
  80. td->subtype = SYSTEM_TYPE_TTY;
  81. td->init_termios = tty_std_termios;
  82. td->flags = TTY_DRIVER_RESET_TERMIOS;
  83. #ifdef CONFIG_DEVFS_FS
  84. td->flags |= TTY_DRIVER_NO_DEVFS;
  85. #endif
  86. td->refcount = &tty3270_refcount;
  87. td->table = tty3270_table;
  88. td->termios = tty3270_termios;
  89. td->termios_locked = tty3270_termios_locked;
  90. td->open = tty3270_open;
  91. td->close = tty3270_close;
  92. td->write = tty3270_write;
  93. td->put_char = tty3270_put_char;
  94. td->flush_chars = tty3270_flush_chars;
  95. td->write_room = tty3270_write_room;
  96. td->chars_in_buffer = tty3270_chars_in_buffer;
  97. td->ioctl = tty3270_ioctl;
  98. td->ioctl = NULL;
  99. td->set_termios = tty3270_set_termios;
  100. td->throttle = NULL;
  101. td->unthrottle = NULL;
  102. td->stop = NULL;
  103. td->start = NULL;
  104. td->hangup = tty3270_hangup;
  105. td->break_ctl = NULL;
  106. td->flush_buffer = tty3270_flush_buffer;
  107. td->set_ldisc = NULL;
  108. td->wait_until_sent = NULL;
  109. td->send_xchar = NULL;
  110. td->read_proc = tty3270_read_proc;
  111. td->write_proc = tty3270_write_proc;
  112. rc = tty_register_driver(td);
  113. if (rc) {
  114. printk(KERN_ERR "tty3270 registration failed with %dn", rc);
  115. } else {
  116. tty3270_major = IBM_TTY3270_MAJOR;
  117. if (td->proc_entry != NULL)
  118. td->proc_entry->mode = S_IRUGO | S_IWUGO;
  119. }
  120. #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
  121. #ifdef CONFIG_TN3270_CONSOLE
  122. if (CONSOLE_IS_3270) {
  123. tty3270_con_driver = *td;
  124. td = &tty3270_con_driver;
  125. td->driver_name = "con3270";
  126. td->name = "con3270";
  127. td->major = MAJOR(S390_CONSOLE_DEV);
  128. td->minor_start = MINOR(S390_CONSOLE_DEV);
  129. td->num = 1;
  130. td->refcount = &con3270_refcount;
  131. td->table = con3270_table;
  132. td->termios = con3270_termios;
  133. td->termios_locked = con3270_termios_locked;
  134. rc = tty_register_driver(td);
  135. if (rc) {
  136. printk(KERN_ERR
  137.        "con3270 registration failed with %dn", rc);
  138. } else {
  139. con3270_major = MAJOR(S390_CONSOLE_DEV);
  140. if (td->proc_entry != NULL)
  141. td->proc_entry->mode = S_IRUGO | S_IWUGO;
  142. }
  143. }
  144. #endif /* ifdef CONFIG_TN3270_CONSOLE */
  145. #endif /* if LINUX_VERSION_CODE */
  146. return rc;
  147. }
  148. /*
  149.  * tty3270_fini() -- Uninitialize linemode tubes
  150.  */
  151. void
  152. tty3270_fini(void)
  153. {
  154. if (tty3270_major != -1) {
  155. tty_unregister_driver(&tty3270_driver);
  156. tty3270_major = -1;
  157. }
  158. #ifdef CONFIG_TN3270_CONSOLE
  159. if (CONSOLE_IS_3270 && con3270_major != -1) {
  160. tty_unregister_driver(&con3270_driver);
  161. con3270_major = -1;
  162. }
  163. #endif
  164. }
  165. static int 
  166. tty3270_open(struct tty_struct *tty, struct file *filp)
  167. {
  168. tub_t *tubp;
  169. long flags;
  170. int rc;
  171. int cmd;
  172. if ((tubp = TTY2TUB(tty)) == NULL) {
  173. return -ENODEV;
  174. }
  175. tub_inc_use_count();
  176. if ((rc = tty3270_wait(tubp, &flags)) != 0)
  177. goto do_fail;
  178. if (tubp->lnopen > 0) {
  179. tubp->lnopen++;
  180. TUBUNLOCK(tubp->irq, flags);
  181. return 0;
  182. }
  183. if (tubp->flags & TUB_OPEN_STET) {
  184. cmd = TBC_UPDLOG;
  185. } else {
  186. cmd = TBC_OPEN;
  187. tubp->flags &= ~TUB_SIZED;
  188. }
  189. if ((rc = tty3270_size(tubp, &flags)) != 0)
  190. goto do_fail;
  191. if ((rc = tty3270_rcl_init(tubp)) != 0)
  192. goto do_fail;
  193. if ((rc = tty3270_aid_init(tubp)) != 0)
  194. goto do_fail;
  195. if ((rc = tty3270_scl_init(tubp)) != 0)
  196. goto do_fail;
  197. tubp->mode = TBM_LN;
  198. tubp->intv = tty3270_int;
  199. tubp->tty = tty;
  200. tubp->lnopen = 1;
  201. tty->driver_data = tubp;
  202. tty->winsize.ws_row = tubp->geom_rows - 2;
  203. tty->winsize.ws_col = tubp->geom_cols;
  204. if (tubp->tty_input == NULL)
  205. tubp->tty_input = kmalloc(GEOM_INPLEN, GFP_KERNEL|GFP_DMA);
  206. tubp->tty_inattr = TF_INPUT;
  207. tubp->cmd = cmd;
  208. tty3270_build(tubp);
  209. TUBUNLOCK(tubp->irq, flags);
  210. return 0;
  211. do_fail:
  212. tty3270_scl_fini(tubp);
  213. tty3270_aid_fini(tubp);
  214. tty3270_rcl_fini(tubp);
  215. TUBUNLOCK(tubp->irq, flags);
  216. tub_dec_use_count();
  217. return rc;
  218. }
  219. static void
  220. tty3270_close(struct tty_struct *tty, struct file *filp)
  221. {
  222. tub_t *tubp;
  223. long flags;
  224. if ((tubp = tty->driver_data) == NULL)
  225. return;
  226. tty3270_wait(tubp, &flags);
  227. if (--tubp->lnopen > 0)
  228. goto do_return;
  229. tubp->tty = NULL;
  230. tty->driver_data = NULL;
  231. tty3270_aid_fini(tubp);
  232. tty3270_rcl_fini(tubp);
  233. tty3270_scl_fini(tubp);
  234. do_return:
  235. tub_dec_use_count();
  236. TUBUNLOCK(tubp->irq, flags);
  237. }
  238. static int 
  239. tty3270_write(struct tty_struct *tty, int fromuser,
  240. const unsigned char *buf, int count)
  241. {
  242. tub_t *tubp;
  243. long flags;
  244. bcb_t obcb;
  245. int rc = 0;
  246. if ((tubp = tty->driver_data) == NULL)
  247. return -1;
  248. #ifdef CONFIG_TN3270_CONSOLE
  249. if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp)
  250. tub3270_con_copy(tubp);
  251. #endif /* CONFIG_TN3270_CONSOLE */
  252. obcb.bc_buf = (char *)buf;
  253. obcb.bc_len = obcb.bc_cnt = obcb.bc_wr = count;
  254. obcb.bc_rd = 0;
  255. TUBLOCK(tubp->irq, flags);
  256. rc = tub3270_movedata(&obcb, &tubp->tty_bcb, fromuser);
  257. tty3270_try_logging(tubp);
  258. TUBUNLOCK(tubp->irq, flags);
  259. return rc;
  260. static void
  261. tty3270_put_char(struct tty_struct *tty, unsigned char ch)
  262. {
  263. long flags;
  264. tub_t *tubp;
  265. bcb_t *ob;
  266. if ((tubp = tty->driver_data) == NULL)
  267. return;
  268. TUBLOCK(tubp->irq, flags);
  269. ob = &tubp->tty_bcb;
  270. if (ob->bc_cnt < ob->bc_len) {
  271. ob->bc_buf[ob->bc_wr++] = ch;
  272. if (ob->bc_wr == ob->bc_len)
  273. ob->bc_wr = 0;
  274. ob->bc_cnt++;
  275. }
  276. tty3270_try_logging(tubp);
  277. TUBUNLOCK(tubp->irq, flags);
  278. }
  279. static void
  280. tty3270_flush_chars(struct tty_struct *tty)
  281. {
  282. tub_t *tubp;
  283. long flags;
  284. if ((tubp = tty->driver_data) == NULL)
  285. return;
  286. TUBLOCK(tubp->irq, flags);
  287. tty3270_try_logging(tubp);
  288. TUBUNLOCK(tubp->irq, flags);
  289. }
  290. static int 
  291. tty3270_write_room(struct tty_struct *tty)
  292. {
  293. tub_t *tubp;
  294. bcb_t *ob;
  295. if ((tubp = tty->driver_data) == NULL)
  296. return -1;
  297. ob = &tubp->tty_bcb;
  298. return ob->bc_len - ob->bc_cnt;
  299. }
  300. static int
  301. tty3270_chars_in_buffer(struct tty_struct *tty)
  302. {
  303. tub_t *tubp;
  304. bcb_t *ob;
  305. if ((tubp = tty->driver_data) == NULL)
  306. return -1;
  307. ob = &tubp->tty_bcb;
  308. return ob->bc_cnt;
  309. }
  310. static int
  311. tty3270_ioctl(struct tty_struct *tty, struct file *file,
  312. unsigned int cmd, unsigned long arg)
  313. {
  314. tub_t *tubp;
  315. long flags;
  316. int ret = 0;
  317. struct termios termios;
  318. if ((tubp = tty->driver_data) == NULL)
  319. return -ENODEV;
  320. TUBLOCK(tubp->irq, flags);
  321. if (tty->flags * (1 << TTY_IO_ERROR)) {
  322. ret = -EIO;
  323. goto do_return;
  324. }
  325. switch(cmd) {
  326. case TCGETS:
  327. ret = -ENOIOCTLCMD;
  328. goto do_return;
  329. case TCFLSH:            /* arg:  2 or 0 */
  330. ret = -ENOIOCTLCMD;
  331. goto do_return;
  332. case TCSETSF:
  333. if (user_termios_to_kernel_termios(&termios,
  334.     (struct termios *)arg)) {
  335. ret = -EFAULT;
  336. goto do_return;
  337. }
  338. ret = -ENOIOCTLCMD;
  339. goto do_return;
  340. case TCGETA:
  341. ret = -ENOIOCTLCMD;
  342. goto do_return;
  343. case TCSETA:
  344. if (user_termio_to_kernel_termios(&termios,
  345.     (struct termio *)arg)) {
  346. ret = -EFAULT;
  347. goto do_return;
  348. }
  349. ret = -ENOIOCTLCMD;
  350. goto do_return;
  351. default:
  352. ret = -ENOIOCTLCMD;
  353. break;
  354. }
  355. do_return:
  356. TUBUNLOCK(tubp->irq, flags);
  357. return ret;
  358. }
  359. static void
  360. tty3270_set_termios(struct tty_struct *tty, struct termios *old)
  361. {
  362. tub_t *tubp;
  363. long flags;
  364. int new;
  365. if ((tubp = tty->driver_data) == NULL)
  366. return;
  367. if (tty3270_wait(tubp, &flags) != 0) {
  368. TUBUNLOCK(tubp->irq, flags);
  369. return;
  370. }
  371. new = L_ICANON(tty)? L_ECHO(tty)? TF_INPUT: TF_INPUTN:
  372. tubp->tty_inattr;
  373. if (new != tubp->tty_inattr) {
  374. tubp->tty_inattr = new;
  375. tubp->cmd = TBC_CLRINPUT;
  376. tty3270_build(tubp);
  377. }
  378. TUBUNLOCK(tubp->irq, flags);
  379. }
  380. static void
  381. tty3270_flush_buffer(struct tty_struct *tty)
  382. {
  383. tub_t *tubp;
  384. bcb_t *ob;
  385. long flags;
  386. if ((tubp = tty->driver_data) == NULL)
  387. return;
  388. if (tubp->mode == TBM_FS && tubp->fs_pid != 0) {
  389. kill_proc(tubp->fs_pid, SIGHUP, 1);
  390. }
  391. if ((tubp->flags & TUB_OPEN_STET) == 0) {
  392. ob = &tubp->tty_bcb;
  393. TUBLOCK(tubp->irq, flags);
  394. ob->bc_rd = 0;
  395. ob->bc_wr = 0;
  396. ob->bc_cnt = 0;
  397. TUBUNLOCK(tubp->irq, flags);
  398. }
  399. wake_up_interruptible(&tty->write_wait);
  400. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  401.     tty->ldisc.write_wakeup)
  402. (tty->ldisc.write_wakeup)(tty);
  403. }
  404. static int
  405. tty3270_read_proc(char *buf, char **start, off_t off, int count,
  406. int *eof, void *data)
  407. {
  408. tub_t *tubp;
  409. int begin = 0;
  410. int i;
  411. int rc;
  412. int len = 0;
  413. if (tty3270_proc_what == TW_CONFIG) {
  414. /*
  415.  * Describe the 3270 configuration in ascii lines.
  416.  * Line 1: 0 <fsmajor> 0
  417.  * Console line: <devnum> CONSOLE <minor>
  418.  * Other lines: <devnum> <ttymajor> <minor>
  419.  */
  420. len += sprintf(buf + len, "0 %d 0n", fs3270_major);
  421. for (i = 1; i <= tubnummins; i++) {
  422. tubp = (*tubminors)[i];
  423. #ifdef CONFIG_TN3270_CONSOLE
  424. if (CONSOLE_IS_3270 && tubp == tub3270_con_tubp)
  425. len += sprintf(buf + len, "%.4x CONSOLE %dn",
  426.        tubp->devno, i);
  427. else
  428. #endif
  429. len += sprintf(buf + len, "%.4x %d %dn",
  430.        tubp->devno, tty3270_major, i);
  431. if (begin + len > off + count)
  432. break;
  433. if (begin + len < off) {
  434. begin += len;
  435. len = 0;
  436. }
  437. }
  438. if (i > tubnummins)
  439. *eof = 1;
  440. if (off >= begin + len) {
  441. rc = 0;
  442. } else {
  443. *start = buf + off - begin;
  444. rc = MIN(count, begin + len - off);
  445. }
  446. if (*eof && rc == 0)
  447. tty3270_proc_what = TW_BOGUS;
  448. return rc;
  449. }
  450. len += sprintf(buf, "There are %d devices.  fs major is %d, "
  451. "tty major is %d.n", tubnummins, fs3270_major,
  452. tty3270_major);
  453. len += sprintf(buf+len, "        index=%d data=%d misc=%dn",
  454. tty3270_proc_index,
  455. tty3270_proc_data,
  456. tty3270_proc_misc);
  457. /*
  458.  * Display info for the tube with minor nr in index
  459.  */
  460. len += tty3270_show_tube(tty3270_proc_index, buf+len, count-len);
  461. *eof = 1;
  462. if (off >= begin + len)
  463. return 0;
  464. *start = buf + off - begin;
  465. return MIN(count, begin + len - off);
  466. }
  467. static int
  468. tty3270_write_proc(struct file *file, const char *buffer,
  469. unsigned long count, void *data)
  470. {
  471. char mybuf[GEOM_MAXINPLEN];
  472. int mycount;
  473. tub_t *tubp;
  474. struct tty_struct *tty;
  475. kdev_t device;
  476. int rc;
  477. mycount = MIN(count, sizeof mybuf - 1);
  478. if (copy_from_user(mybuf, buffer, mycount) != 0)
  479. return -EFAULT;
  480. mybuf[mycount] = '';
  481. /*
  482.  * User-mode settings affect only the current tty ---
  483.  */
  484. tubp = NULL;
  485. tty = current->tty;
  486. device = tty? tty->device: 0;
  487. if (device) {
  488. if (MAJOR(device) == IBM_TTY3270_MAJOR)
  489. tubp = (*tubminors)[MINOR(device)];
  490. #ifdef CONFIG_TN3270_CONSOLE
  491. #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
  492. if (CONSOLE_IS_3270 && device == S390_CONSOLE_DEV)
  493. tubp = tub3270_con_tubp;
  494. #endif /* LINUX_VERSION_CODE */
  495. #endif /* CONFIG_TN3270_CONSOLE */
  496. }
  497. if (tubp) {
  498. if ((rc = tty3270_aid_set(tubp, mybuf, mycount + 1)))
  499. return rc > 0? count: rc;
  500. if ((rc = tty3270_rcl_set(tubp, mybuf, mycount + 1)))
  501. return rc > 0? count: rc;
  502. if ((rc = tty3270_scl_set(tubp, mybuf, mycount + 1)))
  503. return rc > 0? count: rc;
  504. }
  505. /*
  506.  * Superuser-mode settings affect the driver overall ---
  507.  */
  508. if (!suser()) {
  509. return -EPERM;
  510. } else if (strncmp(mybuf, "index=", 6) == 0) {
  511. tty3270_proc_index = simple_strtoul(mybuf + 6, 0,0);
  512. return count;
  513. } else if (strncmp(mybuf, "data=", 5) == 0) {
  514. tty3270_proc_data = simple_strtoul(mybuf + 5, 0, 0);
  515. return count;
  516. } else if (strncmp(mybuf, "misc=", 5) == 0) {
  517. tty3270_proc_misc = simple_strtoul(mybuf + 5, 0, 0);
  518. return count;
  519. } else if (strncmp(mybuf, "what=", 5) == 0) {
  520. if (strcmp(mybuf+5, "bogus") == 0)
  521. tty3270_proc_what = 0;
  522. else if (strncmp(mybuf+5, "config", 6) == 0)
  523. tty3270_proc_what = TW_CONFIG;
  524. return count;
  525. } else {
  526. return -EINVAL;
  527. }
  528. }
  529. static void
  530. tty3270_hangup(struct tty_struct *tty)
  531. {
  532. tub_t *tubp;
  533. extern void fs3270_release(tub_t *);
  534. if ((tubp = tty->driver_data) == NULL)
  535. return;
  536. tty3270_rcl_purge(tubp);
  537. tty3270_aid_reinit(tubp);
  538. fs3270_release(tubp);
  539. }
  540. /*
  541.  * tty3270_bh(tubp) -- Perform back-half processing
  542.  */
  543. static void
  544. tty3270_bh(void *data)
  545. {
  546. tub_t *tubp;
  547. ioinfo_t *ioinfop;
  548. long flags;
  549. struct tty_struct *tty;
  550. ioinfop = ioinfo[(tubp = data)->irq];
  551. while (TUBTRYLOCK(tubp->irq, flags) == 0) {
  552. if (ioinfop->ui.flags.unready == 1)
  553. return;
  554. }
  555. if (ioinfop->ui.flags.unready == 1 ||
  556.     ioinfop->ui.flags.ready == 0)
  557. goto do_unlock;
  558. tubp->flags &= ~TUB_BHPENDING;
  559. tty = tubp->tty;
  560. if (tubp->flags & TUB_UNSOL_DE) {
  561. tubp->flags &= ~TUB_UNSOL_DE;
  562. if (tty != NULL) {
  563. tty_hangup(tty);
  564. wake_up_interruptible(&tubp->waitq);
  565. goto do_unlock;
  566. }
  567. }
  568. if (tubp->flags & TUB_IACTIVE) {        /* If read ended, */
  569. tty3270_do_input(tubp);
  570. tubp->flags &= ~TUB_IACTIVE;
  571. }
  572. if ((tubp->flags & TUB_WORKING) == 0) {
  573. if (tubp->flags & TUB_ATTN) {
  574. tty3270_start_input(tubp);
  575. tubp->flags &= ~TUB_ATTN;
  576. } else if (tty3270_try_logging(tubp) == 0) {
  577. wake_up_interruptible(&tubp->waitq);
  578. }
  579. }
  580. if (tty != NULL) {
  581. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  582.     tty->ldisc.write_wakeup != NULL)
  583. (tty->ldisc.write_wakeup)(tty);
  584. wake_up_interruptible(&tty->write_wait);
  585. }
  586. do_unlock:
  587. TUBUNLOCK(tubp->irq, flags);
  588. }
  589. /*
  590.  * tty3270_sched_bh(tubp) -- Schedule the back half
  591.  * Irq lock must be held on entry and remains held on exit.
  592.  */
  593. void
  594. tty3270_sched_bh(tub_t *tubp)
  595. {
  596. if (tubp->flags & TUB_BHPENDING)
  597. return;
  598. tubp->flags |= TUB_BHPENDING;
  599. tubp->tqueue.routine = tty3270_bh;
  600. tubp->tqueue.data = tubp;
  601. queue_task(&tubp->tqueue, &tq_immediate);
  602. mark_bh(IMMEDIATE_BH);
  603. }
  604. /*
  605.  * tty3270_io() -- Perform line-mode reads and writes here
  606.  */
  607. int 
  608. tty3270_io(tub_t *tubp)
  609. {
  610. int rc;
  611. ccw1_t *ccwp;
  612. tubp->flags |= TUB_WORKING;
  613. tubp->dstat = 0;
  614. ccwp = &tubp->ttyccw;
  615. rc = do_IO(tubp->irq, ccwp, tubp->irq, 0, 0);
  616. return rc;
  617. }
  618. /*
  619.  * tty3270_wait(tubp) -- Wait until TUB_WORKING is off
  620.  * On entry the lock must not be held; on exit it is held.
  621.  */
  622. static int
  623. tty3270_wait(tub_t *tubp, long *flags)
  624. {
  625. DECLARE_WAITQUEUE(wait, current);
  626. TUBLOCK(tubp->irq, *flags);
  627. add_wait_queue(&tubp->waitq, &wait);
  628. while (!signal_pending(current) &&
  629.     (tubp->flags & TUB_WORKING) != 0) {
  630. current->state = TASK_INTERRUPTIBLE;
  631. TUBUNLOCK(tubp->irq, *flags);
  632. schedule();
  633. current->state = TASK_RUNNING;
  634. TUBLOCK(tubp->irq, *flags);
  635. }
  636. remove_wait_queue(&tubp->waitq, &wait);
  637. return signal_pending(current)? -ERESTARTSYS: 0;
  638. }
  639. void
  640. tty3270_int(tub_t *tubp, devstat_t *dsp)
  641. {
  642. #define DEV_UE_BUSY 
  643. (DEV_STAT_CHN_END | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP)
  644. #define DEV_NOT_WORKING 
  645. (DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_CHECK)
  646. tubp->dstat = dsp->dstat;
  647. /* Handle CE-DE-UE and subsequent UDE */
  648. if (dsp->dstat == DEV_UE_BUSY) {
  649. tubp->flags |= TUB_UE_BUSY;
  650. return;
  651. } else if (tubp->flags & TUB_UE_BUSY) {
  652. tubp->flags &= ~TUB_UE_BUSY;
  653. if (dsp->dstat == DEV_STAT_DEV_END &&
  654.     (tubp->flags & TUB_WORKING) != 0) {
  655. tty3270_io(tubp);
  656. return;
  657. }
  658. }
  659. /* Handle ATTN */
  660. if (dsp->dstat & DEV_STAT_ATTENTION)
  661. tubp->flags |= TUB_ATTN;
  662. if (dsp->dstat & DEV_STAT_CHN_END) {
  663. tubp->cswl = dsp->rescnt;
  664. if ((dsp->dstat & DEV_STAT_DEV_END) == 0)
  665. tubp->flags |= TUB_EXPECT_DE;
  666. else
  667. tubp->flags &= ~TUB_EXPECT_DE;
  668. } else if (dsp->dstat & DEV_STAT_DEV_END) {
  669. if ((tubp->flags & TUB_EXPECT_DE) == 0)
  670. tubp->flags |= TUB_UNSOL_DE;
  671. tubp->flags &= ~TUB_EXPECT_DE;
  672. }
  673. if (dsp->dstat & DEV_NOT_WORKING)
  674. tubp->flags &= ~TUB_WORKING;
  675. if (dsp->dstat & DEV_STAT_UNIT_CHECK)
  676. tubp->sense = dsp->ii.sense;
  677. if ((tubp->flags & TUB_WORKING) == 0)
  678. tty3270_sched_bh(tubp);
  679. }
  680. /*
  681.  * tty3270_refresh(), called by fs3270_close() when tubp->fsopen == 0.
  682.  * On entry, lock is held.
  683.  */
  684. void
  685. tty3270_refresh(tub_t *tubp)
  686. {
  687. if (tubp->lnopen) {
  688. tubp->mode = TBM_LN;
  689. tubp->intv = tty3270_int;
  690. tty3270_scl_resettimer(tubp);
  691. tubp->cmd = TBC_UPDATE;
  692. tty3270_build(tubp);
  693. }
  694. }
  695. int
  696. tty3270_try_logging(tub_t *tubp)
  697. {
  698. if (tubp->flags & TUB_WORKING)
  699. return 0;
  700. if (tubp->mode == TBM_FS)
  701. return 0;
  702. if (tubp->stat == TBS_HOLD)
  703. return 0;
  704. if (tubp->stat == TBS_MORE)
  705. return 0;
  706. #ifdef CONFIG_TN3270_CONSOLE
  707. if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp)
  708. tub3270_con_copy(tubp);
  709. #endif /* CONFIG_TN3270_CONSOLE */
  710. if (tubp->tty_bcb.bc_cnt == 0)
  711. return 0;
  712. if (tubp->intv != tty3270_int)
  713. return 0;
  714. tubp->cmd = TBC_UPDLOG;
  715. return tty3270_build(tubp);
  716. }
  717. /* tty3270 utility functions */
  718. static void
  719. tty3270_start_input(tub_t *tubp)
  720. {
  721. if (tubp->tty_input == NULL)
  722. return;
  723. tubp->ttyccw.cda = virt_to_phys(tubp->tty_input);
  724. tubp->ttyccw.cmd_code = TC_READMOD;
  725. tubp->ttyccw.count = GEOM_INPLEN;
  726. tubp->ttyccw.flags = CCW_FLAG_SLI;
  727. tty3270_io(tubp);
  728. tubp->flags |= TUB_IACTIVE;
  729. }
  730. static void
  731. tty3270_do_input(tub_t *tubp)
  732. {
  733. int count;
  734. char *in;
  735. int aidflags;
  736. char *aidstring;
  737. count = GEOM_INPLEN - tubp->cswl;
  738. if ((in = tubp->tty_input) == NULL)
  739. goto do_build;
  740. tty3270_aid_get(tubp, in[0], &aidflags, &aidstring);
  741. if (aidflags & TA_CLEARKEY) {
  742. tubp->stat = TBS_RUNNING;
  743. tty3270_scl_resettimer(tubp);
  744. tubp->cmd = TBC_UPDATE;
  745. } else if (aidflags & TA_CLEARLOG) {
  746. tubp->stat = TBS_RUNNING;
  747. tty3270_scl_resettimer(tubp);
  748. tubp->cmd = TBC_CLRUPDLOG;
  749. } else if (aidflags & TA_DOENTER) {
  750. if (count <= 6) {
  751. switch(tubp->stat) {
  752. case TBS_MORE:
  753. tubp->stat = TBS_HOLD;
  754. tty3270_scl_resettimer(tubp);
  755. break;
  756. case TBS_HOLD:
  757. tubp->stat = TBS_MORE;
  758. tty3270_scl_settimer(tubp);
  759. break;
  760. case TBS_RUNNING:
  761.                                 tty3270_do_enter(tubp, in + 6, 0);
  762. break;
  763. }
  764. tubp->cmd = TBC_UPDSTAT;
  765. goto do_build;
  766. }
  767. in += 6;
  768. count -= 6;
  769. TUB_EBCASC(in, count);
  770. tubp->cmd = TBC_CLRINPUT;
  771. tty3270_do_enter(tubp, in, count);
  772. } else if ((aidflags & TA_DOSTRING) != 0 && aidstring != NULL) {
  773. tubp->cmd = TBC_KRUPDLOG;
  774. tty3270_do_enter(tubp, aidstring, strlen(aidstring));
  775. } else if ((aidflags & TA_DOSTRINGD) != 0 && aidstring != NULL) {
  776. tty3270_do_showi(tubp, aidstring, strlen(aidstring));
  777. tubp->cmd = TBC_UPDINPUT;
  778. } else {
  779. if (in[0] != 0x60)
  780. tubp->flags |= TUB_ALARM;
  781. tubp->cmd = TBC_KRUPDLOG;
  782. }
  783. do_build:
  784. tty3270_build(tubp);
  785. }
  786. static void
  787. tty3270_do_enter(tub_t *tubp, char *cp, int count)
  788. {
  789. struct tty_struct *tty;
  790. int func = -1;
  791. if ((tty = tubp->tty) == NULL)
  792. return;
  793. if (count < 0)
  794. return;
  795. if (count == 2 && (cp[0] == '^' || cp[0] == '252')) {
  796. switch(cp[1]) {
  797. case 'c':  case 'C':
  798. func = INTR_CHAR(tty);
  799. break;
  800. case 'd':  case 'D':
  801. func = EOF_CHAR(tty);
  802. break;
  803. case 'z':  case 'Z':
  804. func = SUSP_CHAR(tty);
  805. break;
  806. }
  807. } else if (count == 2 && cp[0] == 0x1b) {        /* if ESC */
  808. int inc = 0;
  809. char buf[GEOM_INPLEN + 1];
  810. int len;
  811. switch(cp[1]) {
  812. case 'k':  case 'K':
  813. inc = -1;
  814. break;
  815. case 'j':  case 'J':
  816. inc = 1;
  817. break;
  818. }
  819. if (inc == 0)
  820. goto not_rcl;
  821. len = tty3270_rcl_get(tubp, buf, sizeof buf, inc);
  822. if (len == 0) {
  823. tubp->flags |= TUB_ALARM;
  824. return;
  825. }
  826. tty3270_do_showi(tubp, buf, len);
  827. tubp->cmd = TBC_UPDINPUT;
  828. return;
  829. }
  830. not_rcl:
  831. if (func != -1) {
  832. *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  833. *tty->flip.char_buf_ptr++ = func;
  834. tty->flip.count++;
  835. } else {
  836. tty3270_rcl_put(tubp, cp, count);
  837. memcpy(tty->flip.char_buf_ptr, cp, count);
  838. /* Add newline unless line ends with "^n" */
  839. if (count < 2 || cp[count - 1] != 'n' ||
  840.     (cp[count - 2] != '^' && cp[count - 2] != '252')) {
  841. tty->flip.char_buf_ptr[count] = 'n';
  842. count++;
  843. } else {
  844. count -= 2;     /* Lop trailing "^n" from text */
  845. }
  846. memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count);
  847. tty->flip.char_buf_ptr += count;
  848. tty->flip.flag_buf_ptr += count;
  849. tty->flip.count += count;
  850. }
  851. tty_flip_buffer_push(tty);
  852. }
  853. static void
  854. tty3270_do_showi(tub_t *tubp, char *cp, int cl)
  855. {
  856. if (cl > GEOM_INPLEN)
  857. cl = GEOM_INPLEN;
  858. memset(tubp->tty_input, 0, GEOM_INPLEN);
  859. memcpy(tubp->tty_input, cp, cl);
  860. TUB_ASCEBC(tubp->tty_input, cl);
  861. }
  862. /* Debugging routine */
  863. static int
  864. tty3270_show_tube(int minor, char *buf, int count)
  865. {
  866. tub_t *tubp;
  867. struct tty_struct *tty;
  868. struct termios *mp;
  869. int len;
  870. /*012345678901234567890123456789012345678901234567890123456789       */
  871. /*Info for tub_t[dd] at xxxxxxxx:                                    */
  872. /*    geom:  rows=dd cols=dd model=d                                 */
  873. /*    lnopen=dd     fsopen=dd   waitq=xxxxxxxx                       */
  874. /*    dstat=xx      mode=dd     stat=dd     flags=xxxx               */
  875. /*    oucount=dddd  ourd=ddddd  ouwr=ddddd  nextlogx=ddddd           */
  876. /*    tty=xxxxxxxx                                                   */
  877. /*    write_wait=xxxxxxxx read_wait=xxxxxxxx                         */
  878. /*    iflag=xxxxxxxx oflag=xxxxxxxx cflag=xxxxxxxx lflag=xxxxxxxx    */
  879. if (minor < 0 || minor > tubnummins ||
  880.     (tubp = (*tubminors)[minor]) == NULL)
  881. return sprintf(buf, "No tube at index=%dn", minor);
  882. tty = tubp->tty;
  883. len = 0;
  884. len += sprintf(buf+len, "Info for tub_t[%d] at %p:n", minor, tubp);
  885. len += sprintf(buf+len, "inattr is at %pn", &tubp->tty_inattr);
  886. len += sprintf(buf+len, "    geom:  rows=%.2d cols=%.2d model=%.1dn",
  887.        tubp->geom_rows, tubp->geom_cols, tubp->tubiocb.model);
  888. len += sprintf(buf+len,
  889.        "    lnopen=%-2d     fsopen=%-2d   waitq=%pn",
  890.        tubp->lnopen, tubp->fsopen, &tubp->waitq);
  891. len += sprintf(buf+len, "    dstat=%.2x      mode=%-2d     "
  892.        "stat=%-2d     flags=%-4xn", tubp->dstat,
  893.        tubp->mode, tubp->stat, tubp->flags);
  894. #ifdef RBH_FIXTHIS
  895. len += sprintf(buf+len,
  896.        "    oucount=%-4d  ourd=%-5d  ouwr=%-5d"
  897.        "  nextlogx=%-5dn", tubp->tty_oucount,
  898.        tubp->tty_ourd, tubp->tty_ouwr, tubp->tty_nextlogx);
  899. #endif
  900. len += sprintf(buf+len, "    tty=%pn",tubp->tty);
  901. if (tty)
  902. len += sprintf(buf+len,
  903. "    write_wait=%p read_wait=%pn",
  904. &tty->write_wait, &tty->read_wait);
  905. if (tty && ((mp = tty->termios)))
  906. len += sprintf(buf+len,"    iflag=%.8x oflag=%.8x "
  907.        "cflag=%.8x lflag=%.8xn", mp->c_iflag,
  908.        mp->c_oflag, mp->c_cflag, mp->c_lflag);
  909. return len;
  910. }