1 // SPDX-License-Identifier: GPL-2.0
3 * IBM/3270 Driver - fullscreen driver.
6 * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
7 * Rewritten for 2.5/2.6 by Martin Schwidefsky <schwidefsky@de.ibm.com>
8 * Copyright IBM Corp. 2003, 2009
11 #include <linux/memblock.h>
12 #include <linux/console.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/compat.h>
16 #include <linux/sched/signal.h>
17 #include <linux/module.h>
18 #include <linux/list.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
22 #include <asm/ccwdev.h>
24 #include <asm/ebcdic.h>
25 #include <asm/idals.h>
30 static struct raw3270_fn fs3270_fn
;
33 struct raw3270_view view
;
34 struct pid
*fs_pid
; /* Pid of controlling program. */
35 int read_command
; /* ccw command to use for reads. */
36 int write_command
; /* ccw command to use for writes. */
37 int attention
; /* Got attention. */
38 int active
; /* Fullscreen view is active. */
39 struct raw3270_request
*init
; /* single init request. */
40 wait_queue_head_t wait
; /* Init & attention wait queue. */
41 struct idal_buffer
*rdbuf
; /* full-screen-deactivate buffer */
42 size_t rdbuf_size
; /* size of data returned by RDBUF */
45 static DEFINE_MUTEX(fs3270_mutex
);
48 fs3270_wake_up(struct raw3270_request
*rq
, void *data
)
50 wake_up((wait_queue_head_t
*) data
);
54 fs3270_working(struct fs3270
*fp
)
57 * The fullscreen view is in working order if the view
58 * has been activated AND the initial request is finished.
60 return fp
->active
&& raw3270_request_final(fp
->init
);
64 fs3270_do_io(struct raw3270_view
*view
, struct raw3270_request
*rq
)
69 fp
= (struct fs3270
*) view
;
70 rq
->callback
= fs3270_wake_up
;
71 rq
->callback_data
= &fp
->wait
;
74 if (!fs3270_working(fp
)) {
75 /* Fullscreen view isn't ready yet. */
76 rc
= wait_event_interruptible(fp
->wait
,
81 rc
= raw3270_start(view
, rq
);
83 /* Started successfully. Now wait for completion. */
84 wait_event(fp
->wait
, raw3270_request_final(rq
));
86 } while (rc
== -EACCES
);
91 * Switch to the fullscreen view.
94 fs3270_reset_callback(struct raw3270_request
*rq
, void *data
)
98 fp
= (struct fs3270
*) rq
->view
;
99 raw3270_request_reset(rq
);
104 fs3270_restore_callback(struct raw3270_request
*rq
, void *data
)
108 fp
= (struct fs3270
*) rq
->view
;
109 if (rq
->rc
!= 0 || rq
->rescnt
!= 0) {
111 kill_pid(fp
->fs_pid
, SIGHUP
, 1);
114 raw3270_request_reset(rq
);
119 fs3270_activate(struct raw3270_view
*view
)
125 fp
= (struct fs3270
*) view
;
127 /* If an old init command is still running just return. */
128 if (!raw3270_request_final(fp
->init
))
131 if (fp
->rdbuf_size
== 0) {
132 /* No saved buffer. Just clear the screen. */
133 raw3270_request_set_cmd(fp
->init
, TC_EWRITEA
);
134 fp
->init
->callback
= fs3270_reset_callback
;
136 /* Restore fullscreen buffer saved by fs3270_deactivate. */
137 raw3270_request_set_cmd(fp
->init
, TC_EWRITEA
);
138 raw3270_request_set_idal(fp
->init
, fp
->rdbuf
);
139 fp
->init
->ccw
.count
= fp
->rdbuf_size
;
140 cp
= fp
->rdbuf
->data
[0];
149 fp
->init
->rescnt
= 0;
150 fp
->init
->callback
= fs3270_restore_callback
;
152 rc
= fp
->init
->rc
= raw3270_start_locked(view
, fp
->init
);
154 fp
->init
->callback(fp
->init
, NULL
);
161 * Shutdown fullscreen view.
164 fs3270_save_callback(struct raw3270_request
*rq
, void *data
)
168 fp
= (struct fs3270
*) rq
->view
;
170 /* Correct idal buffer element 0 address. */
171 fp
->rdbuf
->data
[0] -= 5;
172 fp
->rdbuf
->size
+= 5;
175 * If the rdbuf command failed or the idal buffer is
176 * to small for the amount of data returned by the
177 * rdbuf command, then we have no choice but to send
178 * a SIGHUP to the application.
180 if (rq
->rc
!= 0 || rq
->rescnt
== 0) {
182 kill_pid(fp
->fs_pid
, SIGHUP
, 1);
185 fp
->rdbuf_size
= fp
->rdbuf
->size
- rq
->rescnt
;
186 raw3270_request_reset(rq
);
191 fs3270_deactivate(struct raw3270_view
*view
)
195 fp
= (struct fs3270
*) view
;
198 /* If an old init command is still running just return. */
199 if (!raw3270_request_final(fp
->init
))
202 /* Prepare read-buffer request. */
203 raw3270_request_set_cmd(fp
->init
, TC_RDBUF
);
205 * Hackish: skip first 5 bytes of the idal buffer to make
206 * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
207 * in the activation command.
209 fp
->rdbuf
->data
[0] += 5;
210 fp
->rdbuf
->size
-= 5;
211 raw3270_request_set_idal(fp
->init
, fp
->rdbuf
);
212 fp
->init
->rescnt
= 0;
213 fp
->init
->callback
= fs3270_save_callback
;
215 /* Start I/O to read in the 3270 buffer. */
216 fp
->init
->rc
= raw3270_start_locked(view
, fp
->init
);
218 fp
->init
->callback(fp
->init
, NULL
);
222 fs3270_irq(struct fs3270
*fp
, struct raw3270_request
*rq
, struct irb
*irb
)
224 /* Handle ATTN. Set indication and wake waiters for attention. */
225 if (irb
->scsw
.cmd
.dstat
& DEV_STAT_ATTENTION
) {
231 if (irb
->scsw
.cmd
.dstat
& DEV_STAT_UNIT_CHECK
)
234 /* Normal end. Copy residual count. */
235 rq
->rescnt
= irb
->scsw
.cmd
.count
;
240 * Process reads from fullscreen 3270.
243 fs3270_read(struct file
*filp
, char __user
*data
, size_t count
, loff_t
*off
)
246 struct raw3270_request
*rq
;
247 struct idal_buffer
*ib
;
250 if (count
== 0 || count
> 65535)
252 fp
= filp
->private_data
;
255 ib
= idal_buffer_alloc(count
, 0);
258 rq
= raw3270_request_alloc(0);
260 if (fp
->read_command
== 0 && fp
->write_command
!= 0)
261 fp
->read_command
= 6;
262 raw3270_request_set_cmd(rq
, fp
->read_command
? : 2);
263 raw3270_request_set_idal(rq
, ib
);
264 rc
= wait_event_interruptible(fp
->wait
, fp
->attention
);
267 rc
= fs3270_do_io(&fp
->view
, rq
);
270 if (idal_buffer_to_user(ib
, data
, count
) != 0)
277 raw3270_request_free(rq
);
280 idal_buffer_free(ib
);
285 * Process writes to fullscreen 3270.
288 fs3270_write(struct file
*filp
, const char __user
*data
, size_t count
, loff_t
*off
)
291 struct raw3270_request
*rq
;
292 struct idal_buffer
*ib
;
296 fp
= filp
->private_data
;
299 ib
= idal_buffer_alloc(count
, 0);
302 rq
= raw3270_request_alloc(0);
304 if (idal_buffer_from_user(ib
, data
, count
) == 0) {
305 write_command
= fp
->write_command
? : 1;
306 if (write_command
== 5)
308 raw3270_request_set_cmd(rq
, write_command
);
309 raw3270_request_set_idal(rq
, ib
);
310 rc
= fs3270_do_io(&fp
->view
, rq
);
312 rc
= count
- rq
->rescnt
;
315 raw3270_request_free(rq
);
318 idal_buffer_free(ib
);
323 * process ioctl commands for the tube driver
326 fs3270_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
330 struct raw3270_iocb iocb
;
333 fp
= filp
->private_data
;
336 if (is_compat_task())
337 argp
= compat_ptr(arg
);
339 argp
= (char __user
*)arg
;
341 mutex_lock(&fs3270_mutex
);
344 fp
->read_command
= arg
;
347 fp
->write_command
= arg
;
350 rc
= put_user(fp
->read_command
, argp
);
353 rc
= put_user(fp
->write_command
, argp
);
356 iocb
.model
= fp
->view
.model
;
357 iocb
.line_cnt
= fp
->view
.rows
;
358 iocb
.col_cnt
= fp
->view
.cols
;
362 if (copy_to_user(argp
, &iocb
, sizeof(struct raw3270_iocb
)))
366 mutex_unlock(&fs3270_mutex
);
371 * Allocate fs3270 structure.
373 static struct fs3270
*
374 fs3270_alloc_view(void)
378 fp
= kzalloc(sizeof(struct fs3270
),GFP_KERNEL
);
380 return ERR_PTR(-ENOMEM
);
381 fp
->init
= raw3270_request_alloc(0);
382 if (IS_ERR(fp
->init
)) {
384 return ERR_PTR(-ENOMEM
);
390 * Free fs3270 structure.
393 fs3270_free_view(struct raw3270_view
*view
)
397 fp
= (struct fs3270
*) view
;
399 idal_buffer_free(fp
->rdbuf
);
400 raw3270_request_free(((struct fs3270
*) view
)->init
);
405 * Unlink fs3270 data structure from filp.
408 fs3270_release(struct raw3270_view
*view
)
412 fp
= (struct fs3270
*) view
;
414 kill_pid(fp
->fs_pid
, SIGHUP
, 1);
417 /* View to a 3270 device. Can be console, tty or fullscreen. */
418 static struct raw3270_fn fs3270_fn
= {
419 .activate
= fs3270_activate
,
420 .deactivate
= fs3270_deactivate
,
421 .intv
= (void *) fs3270_irq
,
422 .release
= fs3270_release
,
423 .free
= fs3270_free_view
427 * This routine is called whenever a 3270 fullscreen device is opened.
430 fs3270_open(struct inode
*inode
, struct file
*filp
)
433 struct idal_buffer
*ib
;
436 if (imajor(file_inode(filp
)) != IBM_FS3270_MAJOR
)
438 minor
= iminor(file_inode(filp
));
439 /* Check for minor 0 multiplexer. */
441 struct tty_struct
*tty
= get_current_tty();
442 if (!tty
|| tty
->driver
->major
!= IBM_TTY3270_MAJOR
) {
449 mutex_lock(&fs3270_mutex
);
450 /* Check if some other program is already using fullscreen mode. */
451 fp
= (struct fs3270
*) raw3270_find_view(&fs3270_fn
, minor
);
453 raw3270_put_view(&fp
->view
);
457 /* Allocate fullscreen view structure. */
458 fp
= fs3270_alloc_view();
464 init_waitqueue_head(&fp
->wait
);
465 fp
->fs_pid
= get_pid(task_pid(current
));
466 rc
= raw3270_add_view(&fp
->view
, &fs3270_fn
, minor
,
467 RAW3270_VIEW_LOCK_BH
);
469 fs3270_free_view(&fp
->view
);
473 /* Allocate idal-buffer. */
474 ib
= idal_buffer_alloc(2*fp
->view
.rows
*fp
->view
.cols
+ 5, 0);
476 raw3270_put_view(&fp
->view
);
477 raw3270_del_view(&fp
->view
);
483 rc
= raw3270_activate_view(&fp
->view
);
485 raw3270_put_view(&fp
->view
);
486 raw3270_del_view(&fp
->view
);
489 nonseekable_open(inode
, filp
);
490 filp
->private_data
= fp
;
492 mutex_unlock(&fs3270_mutex
);
497 * This routine is called when the 3270 tty is closed. We wait
498 * for the remaining request to be completed. Then we clean up.
501 fs3270_close(struct inode
*inode
, struct file
*filp
)
505 fp
= filp
->private_data
;
506 filp
->private_data
= NULL
;
510 raw3270_reset(&fp
->view
);
511 raw3270_put_view(&fp
->view
);
512 raw3270_del_view(&fp
->view
);
517 static const struct file_operations fs3270_fops
= {
518 .owner
= THIS_MODULE
, /* owner */
519 .read
= fs3270_read
, /* read */
520 .write
= fs3270_write
, /* write */
521 .unlocked_ioctl
= fs3270_ioctl
, /* ioctl */
522 .compat_ioctl
= fs3270_ioctl
, /* ioctl */
523 .open
= fs3270_open
, /* open */
524 .release
= fs3270_close
, /* release */
528 static void fs3270_create_cb(int minor
)
530 __register_chrdev(IBM_FS3270_MAJOR
, minor
, 1, "tub", &fs3270_fops
);
531 device_create(class3270
, NULL
, MKDEV(IBM_FS3270_MAJOR
, minor
),
532 NULL
, "3270/tub%d", minor
);
535 static void fs3270_destroy_cb(int minor
)
537 device_destroy(class3270
, MKDEV(IBM_FS3270_MAJOR
, minor
));
538 __unregister_chrdev(IBM_FS3270_MAJOR
, minor
, 1, "tub");
541 static struct raw3270_notifier fs3270_notifier
=
543 .create
= fs3270_create_cb
,
544 .destroy
= fs3270_destroy_cb
,
548 * 3270 fullscreen driver initialization.
555 rc
= __register_chrdev(IBM_FS3270_MAJOR
, 0, 1, "fs3270", &fs3270_fops
);
558 device_create(class3270
, NULL
, MKDEV(IBM_FS3270_MAJOR
, 0),
560 raw3270_register_notifier(&fs3270_notifier
);
567 raw3270_unregister_notifier(&fs3270_notifier
);
568 device_destroy(class3270
, MKDEV(IBM_FS3270_MAJOR
, 0));
569 __unregister_chrdev(IBM_FS3270_MAJOR
, 0, 1, "fs3270");
572 MODULE_LICENSE("GPL");
573 MODULE_ALIAS_CHARDEV_MAJOR(IBM_FS3270_MAJOR
);
575 module_init(fs3270_init
);
576 module_exit(fs3270_exit
);