1 /*
2  *  IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC
3  *
4  *  tubio.h -- All-Purpose header file
5  *
6  *
7  *
8  *
9  *
10  *  Author:  Richard Hitt
11  */
12 #include <linux/config.h>
13 
14 #include <linux/module.h>
15 #include <linux/version.h>
16 
17 #include <linux/major.h>
18 #ifndef IBM_TTY3270_MAJOR
19 #  define IBM_TTY3270_MAJOR 212
20 #endif /* IBM_TTY3270_MAJOR */
21 #ifndef IBM_FS3270_MAJOR
22 #  define IBM_FS3270_MAJOR 213
23 #endif /* IBM_FS3270_MAJOR */
24 
25 
26 #include <linux/slab.h>
27 #include <asm/irq.h>
28 #include <asm/io.h>
29 #include <asm/idals.h>
30 #include <linux/console.h>
31 #include <linux/interrupt.h>
32 #include <asm/ebcdic.h>
33 #include <asm/uaccess.h>
34 #include <linux/proc_fs.h>
35 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
36 #include <linux/devfs_fs_kernel.h>
37 #endif
38 
39 #define TUB(x) (('3'<<8)|(x))
40 #define TUBICMD TUB(3)
41 #define TUBOCMD TUB(4)
42 #define TUBGETI TUB(7)
43 #define TUBGETO TUB(8)
44 #define TUBSETMOD TUB(12)
45 #define TUBGETMOD TUB(13)
46 #define TIOPOLL TUB(32)
47 #define TIOPOKE TUB(33)
48 #define TIONPOKE TUB(34)
49 #define TIOTNORM TUB(35)
50 
51 /* Local Channel Commands */
52 #define TC_WRITE   0x01
53 #define TC_EWRITE  0x05
54 #define TC_READMOD 0x06
55 #define TC_EWRITEA 0x0d
56 #define TC_WRITESF 0x11
57 
58 /* Buffer Control Orders */
59 #define TO_SF 0x1d
60 #define TO_SBA 0x11
61 #define TO_IC 0x13
62 #define TO_PT 0x05
63 #define TO_RA 0x3c
64 #define TO_SFE 0x29
65 #define TO_EUA 0x12
66 #define TO_MF 0x2c
67 #define TO_SA 0x28
68 
69 /* Field Attribute Bytes */
70 #define TF_INPUT 0x40           /* Visible input */
71 #define TF_INPUTN 0x4c          /* Invisible input */
72 #define TF_INMDT 0xc1           /* Visible, Set-MDT */
73 #define TF_LOG 0x60
74 #define TF_STAT 0x60
75 
76 /* Character Attribute Bytes */
77 #define TAT_RESET 0x00
78 #define TAT_FIELD 0xc0
79 #define TAT_EXTHI 0x41
80 #define TAT_COLOR 0x42
81 #define TAT_CHARS 0x43
82 #define TAT_TRANS 0x46
83 
84 /* Extended-Highlighting Bytes */
85 #define TAX_RESET 0x00
86 #define TAX_BLINK 0xf1
87 #define TAX_REVER 0xf2
88 #define TAX_UNDER 0xf4
89 
90 /* Reset value */
91 #define TAR_RESET 0x00
92 
93 /* Color values */
94 #define TAC_RESET 0x00
95 #define TAC_BLUE 0xf1
96 #define TAC_RED 0xf2
97 #define TAC_PINK 0xf3
98 #define TAC_GREEN 0xf4
99 #define TAC_TURQ 0xf5
100 #define TAC_YELLOW 0xf6
101 #define TAC_WHITE 0xf7
102 #define TAC_DEFAULT 0x00
103 
104 /* Write Control Characters */
105 #define TW_NONE 0x40            /* No particular action */
106 #define TW_KR 0xc2              /* Keyboard restore */
107 #define TW_PLUSALARM 0x04       /* Add this bit for alarm */
108 
109 /* Attention-ID (AID) Characters */
110 #define TA_CLEAR 0x6d
111 #define TA_PA2 0x6e
112 #define TA_ENTER 0x7d
113 /* more to come */
114 
115 #define MIN(a, b) ((a) < (b)? (a): (b))
116 
117 #define TUB_BUFADR(adr, cpp) \
118 	tty3270_tub_bufadr(tubp, adr, cpp)
119 
120 #define TUB_EBCASC(addr, nr) codepage_convert(tub_ebcasc, addr, nr)
121 #define TUB_ASCEBC(addr, nr) codepage_convert(tub_ascebc, addr, nr)
122 
123 /*
124  *
125  * General global values for the tube driver
126  *
127  */
128 enum tubmode {
129 	TBM_LN,                 /* Line mode */
130 	TBM_FS,                 /* Fullscreen mode */
131 	TBM_FSLN                /* Line mode shelled out of fullscreen */
132 };
133 enum tubstat {              /* normal-mode status */
134 	TBS_RUNNING,            /* none of the following */
135 	TBS_MORE,               /* timed "MORE..." in status */
136 	TBS_HOLD                /* untimed "HOLDING" in status */
137 };
138 enum tubcmd {           /* normal-mode actions to do */
139 	TBC_CONOPEN,		/* Erase-write the console */
140 	TBC_OPEN,               /* Open the tty screen */
141 	TBC_UPDATE,             /* Add lines to the log, clear cmdline */
142 	TBC_UPDLOG,             /* Add lines to log */
143 	TBC_KRUPDLOG,           /* Add lines to log, reset kbd */
144 	TBC_CLEAR,              /* Build screen from scratch */
145 	TBC_CLRUPDLOG,          /* Do log & status, not cmdline */
146 	TBC_UPDSTAT,            /* Do status update only */
147 	TBC_CLRINPUT,           /* Clear input area only */
148 	TBC_UPDINPUT            /* Update input area only */
149 };
150 enum tubwhat {          /* echo what= proc actions */
151 	TW_BOGUS,               /* Nothing at all */
152 	TW_CONFIG               /* Output configuration info */
153 };
154 
155 
156 
157 
158 
159 #define TUBMAXMINS      256
160 #define TUB_DEV MKDEV(IBM_FS3270_MAJ, 0)        /* Generic /dev/3270/tub */
161 #define _GEOM_ROWS 24
162 #define _GEOM_COLS 80
163 #define GEOM_ROWS (tubp->geom_rows)
164 #define GEOM_COLS (tubp->geom_cols)
165 #define GEOM_MAXROWS 127
166 #define GEOM_MAXCOLS 132
167 #define GEOM_INPLEN (GEOM_COLS * 2 - 20)
168 #define GEOM_MAXINPLEN (GEOM_MAXCOLS * 2 - 20)
169 #define GEOM_INPUT (GEOM_COLS * (GEOM_ROWS - 2) - 1)  /* input atr posn */
170 #define GEOM_STAT (GEOM_INPUT + 1 + GEOM_INPLEN)
171 #define GEOM_LOG   (GEOM_COLS * GEOM_ROWS - 1)   /* log atr posn */
172 #define TS_RUNNING "Linux Running     "
173 #define TS_MORE    "Linux More...     "
174 #define DEFAULT_SCROLLTIME 5
175 #define TS_HOLD    "Linux Holding     "
176 /* data length used by tty3270_set_status_area: SBA (3), SF (2), data */
177 #define TS_LENGTH (sizeof TS_RUNNING + 3 + 2)
178 
179 typedef struct {
180 	int aid;                        /* What-to-do flags */
181 	char *string;                   /* Optional input string */
182 } aid_t;
183 #define AIDENTRY(ch, tubp)  (&((tubp)->tty_aid[(ch) & 0x3f]))
184 
185 /* For TUBGETMOD and TUBSETMOD.  Should include. */
186 typedef struct tubiocb {
187 	short model;
188 	short line_cnt;
189 	short col_cnt;
190 	short pf_cnt;
191 	short re_cnt;
192 	short map;
193 } tubiocb_t;
194 
195 /* Flags that go in int aid, above */
196 #define TA_CLEARKEY     0x01            /* Key does hardware CLEAR */
197 #define TA_SHORTREAD    0x02            /* Key does hardware shortread */
198 /* If both are off, key does hardware Read Modified. */
199 #define TA_DOENTER      0x04            /* Treat key like ENTER */
200 #define TA_DOSTRING     0x08            /* Use string and ENTER */
201 #define TA_DOSTRINGD    0x10            /* Display string & set MDT */
202 #define TA_CLEARLOG     0x20            /* Make key cause clear of log */
203 
204 /*
205  * Tube driver buffer control block
206  */
207 typedef struct bcb_s {
208 	char	*bc_buf;		/* Pointer to buffer */
209 	int	bc_len;			/* Length of buffer */
210 	int	bc_cnt;			/* Count of bytes buffered */
211 	int	bc_wr;			/* Posn to write next byte into */
212 	int	bc_rd;			/* Posn to read next byte from */
213 } bcb_t;
214 
215 typedef struct tub_s {
216 	int             minor;
217 	int             irq;
218 	int             irqrc;
219 	int             devno;
220 	int             geom_rows;
221 	int             geom_cols;
222 	tubiocb_t       tubiocb;
223 	int             lnopen;
224 	int             fsopen;
225 	int             icmd;
226 	int             ocmd;
227 	devstat_t       devstat;
228 	ccw1_t          rccw;
229 	ccw1_t          wccw;
230 	struct idal_buffer *wbuf;
231 	int             cswl;
232 	void            (*intv)(struct tub_s *, devstat_t *);
233 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
234 	struct wait_queue	*waitq;
235 #else
236 	wait_queue_head_t waitq;
237 #endif
238 	int             dstat;
239 	sense_t         sense;
240 	enum tubmode    mode;
241 	enum tubstat    stat;
242 	enum tubcmd     cmd;
243 	int             flags;		/* See below for values */
244 	struct tq_struct tqueue;
245 
246 	/* Stuff for fs-driver support */
247 	pid_t           fs_pid;         /* Pid if TBM_FS */
248 
249 
250 	/* Stuff for tty-driver support */
251 	struct tty_struct *tty;
252 	char *tty_input;		/* tty input area */
253 	int tty_inattr;         	/* input-area field attribute */
254 #define TTY_OUTPUT_SIZE 1024
255 	bcb_t tty_bcb;			/* Output buffer control info */
256 	int tty_oucol;                  /* Kludge */
257 	int tty_nextlogx;               /* next screen-log position */
258 	int tty_savecursor;		/* saved cursor position */
259 	int tty_scrolltime;             /* scrollforward wait time, sec */
260 	struct timer_list tty_stimer;   /* timer for scrolltime */
261 	aid_t tty_aid[64];              /* Aid descriptors */
262 	int tty_aidinit;                /* Boolean */
263 	int tty_showaidx;               /* Last aid x to set_aid */
264 	int tty_14bitadr;               /* 14-bit bufadrs okay */
265 #define MAX_TTY_ESCA 24			/* Set-Attribute-Order array */
266 	char tty_esca[MAX_TTY_ESCA];	/* SA array */
267 	int tty_escx;			/* Current index within it */
268 
269 	/* For command recall --- */
270 	char *(*tty_rclbufs)[];         /* Array of ptrs to recall bufs */
271 	int tty_rclk;                   /* Size of array tty_rclbufs */
272 	int tty_rclp;                   /* Index for most-recent cmd */
273 	int tty_rclb;                   /* Index for backscrolling */
274 
275 	/* Work area to contain the hardware write stream */
276 	char (*ttyscreen)[];            /* ptr to data stream area */
277 	int ttyscreenl;			/* its length */
278 	ccw1_t ttyccw;
279 } tub_t;
280 
281 /* values for flags: */
282 #define	TUB_WORKING	0x0001
283 #define	TUB_BHPENDING	0x0002
284 #define	TUB_RDPENDING	0x0004
285 #define	TUB_ALARM	0x0008
286 #define	TUB_SCROLLTIMING  0x0010
287 #define	TUB_ATTN	0x0020
288 #define	TUB_IACTIVE	0x0040
289 #define	TUB_SIZED	0x0080
290 #define	TUB_EXPECT_DE	0x0100
291 #define	TUB_UNSOL_DE	0x0200
292 #define	TUB_OPEN_STET	0x0400		/* No screen clear on open */
293 #define	TUB_UE_BUSY	0x0800
294 #define	TUB_INPUT_HACK	0x1000		/* Early init of command line */
295 
296 #ifdef CONFIG_TN3270_CONSOLE
297 /*
298  * Extra stuff for 3270 console support
299  */
300 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
301 #define	S390_CONSOLE_DEV MKDEV(TTY_MAJOR, 64)
302 #else
303 #define	S390_CONSOLE_DEV MKDEV(TTYAUX_MAJOR, 1)
304 #endif
305 extern int tub3270_con_devno;
306 extern char (*tub3270_con_output)[];
307 extern int tub3270_con_outputl;
308 extern int tub3270_con_ouwr;
309 extern int tub3270_con_oucount;
310 extern int tub3270_con_irq;
311 extern tub_t *tub3270_con_tubp;
312 extern struct tty_driver tty3270_con_driver;
313 #endif /* CONFIG_TN3270_CONSOLE */
314 
315 extern int tubnummins;
316 extern tub_t *(*tubminors)[TUBMAXMINS];
317 extern tub_t *(*(*tubirqs)[256])[256];
318 extern unsigned char tub_ascebc[256];
319 extern unsigned char tub_ebcasc[256];
320 extern unsigned char tub_ebcgraf[64];
321 extern int tubdebug;
322 extern int fs3270_major;
323 extern int tty3270_major;
324 extern int tty3270_proc_misc;
325 extern enum tubwhat tty3270_proc_what;
326 extern struct tty_driver tty3270_driver;
327 #ifdef CONFIG_DEVFS_FS
328 extern devfs_handle_t fs3270_devfs_dir;
329 extern void fs3270_devfs_register(tub_t *);
330 extern void fs3270_devfs_unregister(tub_t *);
331 #endif
332 
333 #ifndef spin_trylock_irqsave
334 #define spin_trylock_irqsave(lock, flags) \
335 ({ \
336 	int success; \
337 	__save_flags(flags); \
338 	__cli(); \
339 	success = spin_trylock(lock); \
340 	if (success == 0) \
341 		__restore_flags(flags); \
342 	success; \
343 })
344 #endif /* if not spin_trylock_irqsave */
345 
346 #ifndef s390irq_spin_trylock_irqsave
347 #define s390irq_spin_trylock_irqsave(irq, flags) \
348 	spin_trylock_irqsave(&(ioinfo[irq]->irq_lock), flags)
349 #endif /* if not s390irq_spin_trylock_irqsave */
350 
351 #define TUBLOCK(irq, flags) \
352 	s390irq_spin_lock_irqsave(irq, flags)
353 
354 #define TUBTRYLOCK(irq, flags) \
355 	s390irq_spin_trylock_irqsave(irq, flags)
356 
357 #define TUBUNLOCK(irq, flags) \
358 	s390irq_spin_unlock_irqrestore(irq, flags)
359 
360 /*
361  * Find tub_t * given fullscreen device's irq (subchannel number)
362  */
363 extern tub_t *tubfindbyirq(int);
364 #define IRQ2TUB(irq) tubfindbyirq(irq)
365 /*
366  * Find tub_t * given fullscreen device's inode pointer
367  * This algorithm takes into account /dev/3270/tub.
368  */
INODE2TUB(struct inode * ip)369 static inline tub_t *INODE2TUB(struct inode *ip)
370 {
371 	unsigned int minor = MINOR(ip->i_rdev);
372 	tub_t *tubp = NULL;
373 	if (minor == 0 && current->tty != NULL) {
374 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
375 #ifdef CONFIG_TN3270_CONSOLE
376 		if (tub3270_con_tubp != NULL &&
377 		    current->tty->device == S390_CONSOLE_DEV)
378 			minor = tub3270_con_tubp->minor;
379 		else
380 #endif
381 #endif
382 		if (MAJOR(current->tty->device) == IBM_TTY3270_MAJOR)
383 			minor = MINOR(current->tty->device);
384 	}
385 	if (minor <= tubnummins && minor > 0)
386 		tubp = (*tubminors)[minor];
387 	return tubp;
388 }
389 
390 /*
391  * Find tub_t * given non-fullscreen (tty) device's tty_struct pointer
392  */
TTY2TUB(struct tty_struct * tty)393 static inline tub_t *TTY2TUB(struct tty_struct *tty)
394 {
395 	unsigned int minor = MINOR(tty->device);
396 	tub_t *tubp = NULL;
397 
398 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
399 #ifdef CONFIG_TN3270_CONSOLE
400 	if (tty->device == S390_CONSOLE_DEV)
401 		tubp = tub3270_con_tubp;
402 	else
403 #endif
404 #endif
405 	if (minor <= tubnummins && minor > 0)
406 		tubp = (*tubminors)[minor];
407 	return tubp;
408 }
409 
410 extern void tub_inc_use_count(void);
411 extern void tub_dec_use_count(void);
412 extern int tub3270_movedata(bcb_t *, bcb_t *, int);
413 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
414 extern int tubmakemin(int, dev_info_t *);
415 #else
416 extern int tubmakemin(int, s390_dev_info_t *);
417 #endif
418 extern int tub3270_con_copy(tub_t *);
419 extern int tty3270_rcl_init(tub_t *);
420 extern int tty3270_rcl_set(tub_t *, char *, int);
421 extern void tty3270_rcl_fini(tub_t *);
422 extern int tty3270_rcl_get(tub_t *, char *, int, int);
423 extern void tty3270_rcl_put(tub_t *, char *, int);
424 extern void tty3270_rcl_sync(tub_t *);
425 extern void tty3270_rcl_purge(tub_t *);
426 extern int tty3270_rcl_resize(tub_t *, int);
427 extern int tty3270_size(tub_t *, long *);
428 extern int tty3270_aid_init(tub_t *);
429 extern void tty3270_aid_fini(tub_t *);
430 extern void tty3270_aid_reinit(tub_t *);
431 extern int tty3270_aid_get(tub_t *, int, int *, char **);
432 extern int tty3270_aid_set(tub_t *, char *, int);
433 extern int tty3270_build(tub_t *);
434 extern void tty3270_scl_settimer(tub_t *);
435 extern void tty3270_scl_resettimer(tub_t *);
436 extern int tty3270_scl_set(tub_t *, char *, int);
437 extern int tty3270_scl_init(tub_t *tubp);
438 extern void tty3270_scl_fini(tub_t *tubp);
439