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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC
  3.  *
  4.  *  tubttysiz.c -- Linemode screen-size determiner
  5.  *
  6.  *
  7.  *
  8.  *
  9.  *
  10.  *  Author:  Richard Hitt
  11.  */
  12. #include "tubio.h"
  13. static int tty3270_size_io(tub_t *tubp);
  14. static void tty3270_size_int(tub_t *tubp, devstat_t *dsp);
  15. static int tty3270_size_wait(tub_t *tubp, long *flags, int stat);
  16. /*
  17.  * Structure representing Usable Area Query Reply Base
  18.  */
  19. typedef struct {
  20. short l;                /* Length of this structured field */
  21. char sfid;              /* 0x81 if Query Reply */
  22. char qcode;             /* 0x81 if Usable Area */
  23. #define QCODE_UA 0x81
  24. char flags0;
  25. #define FLAGS0_ADDR 0x0f
  26. #define FLAGS0_ADDR_12_14       1       /* 12/14-bit adrs ok */
  27. #define FLAGS0_ADDR_12_14_16    3       /* 12/14/16-bit adrs ok */
  28. char flags1;
  29. short w;                /* Width of usable area */
  30. short h;                /* Heigth of usavle area */
  31. char units;             /* 0x00:in; 0x01:mm */
  32. int xr;
  33. int yr;
  34. char aw;
  35. char ah;
  36. short buffsz;           /* Character buffer size, bytes */
  37. char xmin;
  38. char ymin;
  39. char xmax;
  40. char ymax;
  41. } __attribute__ ((packed)) uab_t;
  42. /*
  43.  * Structure representing Alternate Usable Area Self-Defining Parameter
  44.  */
  45. typedef struct {
  46. char l;                 /* Length of this Self-Defining Parm */
  47. char sdpid;             /* 0x02 if Alternate Usable Area */
  48. #define SDPID_AUA 0x02
  49. char res;
  50. char auaid;             /* 0x01 is Id for the A U A */
  51. short wauai;            /* Width of AUAi */
  52. short hauai;            /* Height of AUAi */
  53. char auaunits;          /* 0x00:in, 0x01:mm */
  54. int auaxr;
  55. int auayr;
  56. char awauai;
  57. char ahauai;
  58. } __attribute__ ((packed)) aua_t;
  59. /*
  60.  * Structure representing one followed by the other
  61.  */
  62. typedef struct {
  63. uab_t uab;
  64. aua_t aua;
  65. } __attribute__ ((packed)) ua_t;
  66. /*
  67.  * Try to determine screen size using Read Partition (Query)
  68.  */
  69. int
  70. tty3270_size(tub_t *tubp, long *flags)
  71. {
  72. char wbuf[7] = { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };
  73. int     rc = 0;
  74. int     count;
  75. unsigned char *cp;
  76. ua_t *uap;
  77. char miniscreen[256];
  78. char (*screen)[];
  79. int screenl;
  80. int geom_rows, geom_cols, fourteenbitadr;
  81. void (*oldint)(struct tub_s *, devstat_t *);
  82. if (tubp->flags & TUB_SIZED)
  83. return 0;
  84. fourteenbitadr = 0;
  85. geom_rows = tubp->geom_rows;
  86. geom_cols = tubp->geom_cols;
  87. oldint = tubp->intv;
  88. tubp->intv = tty3270_size_int;
  89. if (tubp->cmd == TBC_CONOPEN) {
  90. tubp->ttyccw.cmd_code = TC_EWRITEA;
  91. cp = miniscreen;
  92. *cp++ = TW_KR;
  93. /* more? */
  94. tubp->ttyccw.flags = CCW_FLAG_SLI;
  95. tubp->ttyccw.cda = virt_to_phys(miniscreen);
  96. tubp->ttyccw.count = (char *)cp - miniscreen;
  97. rc = tty3270_size_io(tubp);
  98. rc = tty3270_size_wait(tubp, flags, 0);
  99. }
  100. tubp->ttyccw.cmd_code = TC_WRITESF;
  101. tubp->ttyccw.flags = CCW_FLAG_SLI;
  102. tubp->ttyccw.cda = virt_to_phys(wbuf);
  103. tubp->ttyccw.count = sizeof wbuf;
  104. try_again:
  105. rc = tty3270_size_io(tubp);
  106. if (rc)
  107. printk("tty3270_size_io returned %dn", rc);
  108. rc = tty3270_size_wait(tubp, flags, 0);
  109. if (rc != 0) {
  110. goto do_return;
  111. }
  112. /*
  113.  * Unit-Check Processing:
  114.  * Expect Command Reject or Intervention Required.
  115.  * For Command Reject assume old hdwe/software and
  116.  * set a default size of 80x24.
  117.  * For Intervention Required, wait for signal pending
  118.  * or Unsolicited Device End; if the latter, retry.
  119.  */
  120. if (tubp->dstat & DEV_STAT_UNIT_CHECK) {
  121. if (tubp->sense.data[0] & SNS0_CMD_REJECT) {
  122. goto use_diag210; /* perhaps it's tn3270 */
  123. } else if (tubp->sense.data[0] & SNS0_INTERVENTION_REQ) {
  124. if ((rc = tty3270_size_wait(tubp, flags,
  125.     DEV_STAT_DEV_END)))
  126. goto do_return;
  127. goto try_again;
  128. } else {
  129. printk("tty3270_size(): unkn sense %.2xn",
  130. tubp->sense.data[0]);
  131. goto do_return;
  132. }
  133. }
  134. if ((rc = tty3270_size_wait(tubp, flags, DEV_STAT_ATTENTION)))
  135. goto do_return;
  136. /* Set up a read ccw and issue it */
  137. tubp->ttyccw.cmd_code = TC_READMOD;
  138. tubp->ttyccw.flags = CCW_FLAG_SLI;
  139. tubp->ttyccw.cda = virt_to_phys(miniscreen);
  140. tubp->ttyccw.count = sizeof miniscreen;
  141. tty3270_size_io(tubp);
  142. rc = tty3270_size_wait(tubp, flags, 0);
  143. if (rc != 0)
  144. goto do_return;
  145. count = sizeof miniscreen - tubp->cswl;
  146. cp = miniscreen;
  147. if (*cp++ != 0x88)
  148. goto do_return;
  149. uap = (void *)cp;
  150. if (uap->uab.qcode != QCODE_UA)
  151. goto do_return;
  152. geom_rows = uap->uab.h;
  153. geom_cols = uap->uab.w;
  154. if ((uap->uab.flags0 & FLAGS0_ADDR) == FLAGS0_ADDR_12_14 ||
  155.     (uap->uab.flags0 & FLAGS0_ADDR) == FLAGS0_ADDR_12_14_16)
  156. fourteenbitadr = 1;
  157. if (uap->uab.l <= sizeof uap->uab)
  158. goto do_return;
  159. if (uap->aua.sdpid != SDPID_AUA) {
  160. printk("AUA sdpid was 0x%.2x, expecting 0x%.2xn",
  161. uap->aua.sdpid, SDPID_AUA);
  162. goto do_return;
  163. }
  164. geom_rows = uap->aua.hauai;
  165. geom_cols = uap->aua.wauai;
  166. goto do_return;
  167. use_diag210:
  168. if (MACHINE_IS_VM) {
  169. diag210_t d210;
  170. d210.vrdcdvno = tubp->devno;
  171. d210.vrdclen = sizeof d210;
  172. rc = diag210(&d210);
  173. if (rc) {
  174. printk("tty3270_size: diag210 for 0x%.4x "
  175. "returned %dn", tubp->devno, rc);
  176. goto do_return;
  177. }
  178. switch(d210.vrdccrmd) {
  179. case 2:
  180. geom_rows = 24;
  181. geom_cols = 80;
  182. goto do_return;
  183. case 3:
  184. geom_rows = 32;
  185. geom_cols = 80;
  186. goto do_return;
  187. case 4:
  188. geom_rows = 43;
  189. geom_cols = 80;
  190. goto do_return;
  191. case 5:
  192. geom_rows = 27;
  193. geom_cols = 132;
  194. goto do_return;
  195. default:
  196. printk("vrdccrmd is 0x%.8xn", d210.vrdccrmd);
  197. }
  198. }
  199. do_return:
  200. if (geom_rows == 0) {
  201. geom_rows = _GEOM_ROWS;
  202. geom_cols = _GEOM_COLS;
  203. }
  204. tubp->tubiocb.pf_cnt = 24;
  205. tubp->tubiocb.re_cnt = 20;
  206. tubp->tubiocb.map = 0;
  207. screenl = geom_rows * geom_cols + 100;
  208. screen = (char (*)[])kmalloc(screenl, GFP_KERNEL);
  209. if (screen == NULL) {
  210. printk("ttyscreen size %d unavailablen", screenl);
  211. } else {
  212. if (tubp->ttyscreen)
  213. kfree(tubp->ttyscreen);
  214. tubp->tubiocb.line_cnt = tubp->geom_rows = geom_rows;
  215. tubp->tubiocb.col_cnt = tubp->geom_cols = geom_cols;
  216. tubp->tty_14bitadr = fourteenbitadr;
  217. tubp->ttyscreen = screen;
  218. tubp->ttyscreenl = screenl;
  219. if (geom_rows == 24 && geom_cols == 80)
  220. tubp->tubiocb.model = 2;
  221. else if (geom_rows == 32 && geom_cols == 80)
  222. tubp->tubiocb.model = 3;
  223. else if (geom_rows == 43 && geom_cols == 80)
  224. tubp->tubiocb.model = 4;
  225. else if (geom_rows == 27 && geom_cols == 132)
  226. tubp->tubiocb.model = 5;
  227. else
  228. tubp->tubiocb.model = 0;
  229. tubp->flags |= TUB_SIZED;
  230. }
  231. if (rc == 0 && tubp->ttyscreen == NULL)
  232. rc = -ENOMEM;
  233. tubp->intv = oldint;
  234. return rc;
  235. }
  236. static int
  237. tty3270_size_io(tub_t *tubp)
  238. {
  239. tubp->flags |= TUB_WORKING;
  240. tubp->dstat = 0;
  241. return do_IO(tubp->irq, &tubp->ttyccw, tubp->irq, 0, 0);
  242. }
  243. static void
  244. tty3270_size_int(tub_t *tubp, devstat_t *dsp)
  245. {
  246. #define DEV_NOT_WORKING 
  247.   (DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_CHECK)
  248. tubp->dstat = dsp->dstat;
  249. if (dsp->dstat & DEV_STAT_CHN_END)
  250. tubp->cswl = dsp->rescnt;
  251. if (dsp->dstat & DEV_NOT_WORKING)
  252. tubp->flags &= ~TUB_WORKING;
  253. if (dsp->dstat & DEV_STAT_UNIT_CHECK)
  254. tubp->sense = dsp->ii.sense;
  255. wake_up_interruptible(&tubp->waitq);
  256. }
  257. /*
  258.  * Wait for something.  If the third arg is zero, wait until
  259.  * tty3270_size_int() turns off TUB_WORKING.  If the third arg
  260.  * is not zero, it is a device-status bit; wait until dstat
  261.  * has the bit turned on.  Never wait if signal is pending.
  262.  * Return 0 unless signal pending, in which case -ERESTARTSYS.
  263.  */
  264. static int
  265. tty3270_size_wait(tub_t *tubp, long *flags, int stat)
  266. {
  267. DECLARE_WAITQUEUE(wait, current);
  268. add_wait_queue(&tubp->waitq, &wait);
  269. while (!signal_pending(current) &&
  270.     (stat? (tubp->dstat & stat) == 0:
  271.      (tubp->flags & TUB_WORKING) != 0)) {
  272. current->state = TASK_INTERRUPTIBLE;
  273. TUBUNLOCK(tubp->irq, *flags);
  274. schedule();
  275. current->state = TASK_RUNNING;
  276. TUBLOCK(tubp->irq, *flags);
  277. }
  278. remove_wait_queue(&tubp->waitq, &wait);
  279. return signal_pending(current)? -ERESTARTSYS: 0;
  280. }