2 * drivers/s390/char/fs3270.c
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 (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
11 #include <linux/config.h>
12 #include <linux/bootmem.h>
13 #include <linux/console.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
16 #include <linux/list.h>
17 #include <linux/types.h>
19 #include <asm/ccwdev.h>
21 #include <asm/cpcmd.h>
22 #include <asm/ebcdic.h>
23 #include <asm/idals.h>
28 struct raw3270_fn fs3270_fn
;
31 struct raw3270_view view
;
32 pid_t fs_pid
; /* Pid of controlling program. */
33 int read_command
; /* ccw command to use for reads. */
34 int write_command
; /* ccw command to use for writes. */
35 int attention
; /* Got attention. */
36 int active
; /* Fullscreen view is active. */
37 struct raw3270_request
*init
; /* single init request. */
38 wait_queue_head_t wait
; /* Init & attention wait queue. */
39 struct idal_buffer
*rdbuf
; /* full-screen-deactivate buffer */
40 size_t rdbuf_size
; /* size of data returned by RDBUF */
44 fs3270_wake_up(struct raw3270_request
*rq
, void *data
)
46 wake_up((wait_queue_head_t
*) data
);
50 fs3270_working(struct fs3270
*fp
)
53 * The fullscreen view is in working order if the view
54 * has been activated AND the initial request is finished.
56 return fp
->active
&& raw3270_request_final(fp
->init
);
60 fs3270_do_io(struct raw3270_view
*view
, struct raw3270_request
*rq
)
65 fp
= (struct fs3270
*) view
;
66 rq
->callback
= fs3270_wake_up
;
67 rq
->callback_data
= &fp
->wait
;
70 if (!fs3270_working(fp
)) {
71 /* Fullscreen view isn't ready yet. */
72 rc
= wait_event_interruptible(fp
->wait
,
77 rc
= raw3270_start(view
, rq
);
79 /* Started sucessfully. Now wait for completion. */
80 wait_event(fp
->wait
, raw3270_request_final(rq
));
82 } while (rc
== -EACCES
);
87 * Switch to the fullscreen view.
90 fs3270_reset_callback(struct raw3270_request
*rq
, void *data
)
94 fp
= (struct fs3270
*) rq
->view
;
95 raw3270_request_reset(rq
);
100 fs3270_restore_callback(struct raw3270_request
*rq
, void *data
)
104 fp
= (struct fs3270
*) rq
->view
;
105 if (rq
->rc
!= 0 || rq
->rescnt
!= 0) {
107 kill_proc(fp
->fs_pid
, SIGHUP
, 1);
110 raw3270_request_reset(rq
);
115 fs3270_activate(struct raw3270_view
*view
)
121 fp
= (struct fs3270
*) view
;
123 /* If an old init command is still running just return. */
124 if (!raw3270_request_final(fp
->init
))
127 if (fp
->rdbuf_size
== 0) {
128 /* No saved buffer. Just clear the screen. */
129 raw3270_request_set_cmd(fp
->init
, TC_EWRITEA
);
130 fp
->init
->callback
= fs3270_reset_callback
;
132 /* Restore fullscreen buffer saved by fs3270_deactivate. */
133 raw3270_request_set_cmd(fp
->init
, TC_EWRITEA
);
134 raw3270_request_set_idal(fp
->init
, fp
->rdbuf
);
135 fp
->init
->ccw
.count
= fp
->rdbuf_size
;
136 cp
= fp
->rdbuf
->data
[0];
145 fp
->init
->rescnt
= 0;
146 fp
->init
->callback
= fs3270_restore_callback
;
148 rc
= fp
->init
->rc
= raw3270_start_locked(view
, fp
->init
);
150 fp
->init
->callback(fp
->init
, NULL
);
157 * Shutdown fullscreen view.
160 fs3270_save_callback(struct raw3270_request
*rq
, void *data
)
164 fp
= (struct fs3270
*) rq
->view
;
166 /* Correct idal buffer element 0 address. */
167 fp
->rdbuf
->data
[0] -= 5;
168 fp
->rdbuf
->size
+= 5;
171 * If the rdbuf command failed or the idal buffer is
172 * to small for the amount of data returned by the
173 * rdbuf command, then we have no choice but to send
174 * a SIGHUP to the application.
176 if (rq
->rc
!= 0 || rq
->rescnt
== 0) {
178 kill_proc(fp
->fs_pid
, SIGHUP
, 1);
181 fp
->rdbuf_size
= fp
->rdbuf
->size
- rq
->rescnt
;
182 raw3270_request_reset(rq
);
187 fs3270_deactivate(struct raw3270_view
*view
)
191 fp
= (struct fs3270
*) view
;
194 /* If an old init command is still running just return. */
195 if (!raw3270_request_final(fp
->init
))
198 /* Prepare read-buffer request. */
199 raw3270_request_set_cmd(fp
->init
, TC_RDBUF
);
201 * Hackish: skip first 5 bytes of the idal buffer to make
202 * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
203 * in the activation command.
205 fp
->rdbuf
->data
[0] += 5;
206 fp
->rdbuf
->size
-= 5;
207 raw3270_request_set_idal(fp
->init
, fp
->rdbuf
);
208 fp
->init
->rescnt
= 0;
209 fp
->init
->callback
= fs3270_save_callback
;
211 /* Start I/O to read in the 3270 buffer. */
212 fp
->init
->rc
= raw3270_start_locked(view
, fp
->init
);
214 fp
->init
->callback(fp
->init
, NULL
);
218 fs3270_irq(struct fs3270
*fp
, struct raw3270_request
*rq
, struct irb
*irb
)
220 /* Handle ATTN. Set indication and wake waiters for attention. */
221 if (irb
->scsw
.dstat
& DEV_STAT_ATTENTION
) {
227 if (irb
->scsw
.dstat
& DEV_STAT_UNIT_CHECK
)
230 /* Normal end. Copy residual count. */
231 rq
->rescnt
= irb
->scsw
.count
;
233 return RAW3270_IO_DONE
;
237 * Process reads from fullscreen 3270.
240 fs3270_read(struct file
*filp
, char *data
, size_t count
, loff_t
*off
)
243 struct raw3270_request
*rq
;
244 struct idal_buffer
*ib
;
247 if (count
== 0 || count
> 65535)
249 fp
= filp
->private_data
;
252 ib
= idal_buffer_alloc(count
, 0);
255 rq
= raw3270_request_alloc(0);
257 if (fp
->read_command
== 0 && fp
->write_command
!= 0)
258 fp
->read_command
= 6;
259 raw3270_request_set_cmd(rq
, fp
->read_command
? : 2);
260 raw3270_request_set_idal(rq
, ib
);
261 rc
= wait_event_interruptible(fp
->wait
, fp
->attention
);
264 rc
= fs3270_do_io(&fp
->view
, rq
);
267 if (idal_buffer_to_user(ib
, data
, count
) != 0)
274 raw3270_request_free(rq
);
277 idal_buffer_free(ib
);
282 * Process writes to fullscreen 3270.
285 fs3270_write(struct file
*filp
, const char *data
, size_t count
, loff_t
*off
)
288 struct raw3270_request
*rq
;
289 struct idal_buffer
*ib
;
293 fp
= filp
->private_data
;
296 ib
= idal_buffer_alloc(count
, 0);
299 rq
= raw3270_request_alloc(0);
301 if (idal_buffer_from_user(ib
, data
, count
) == 0) {
302 write_command
= fp
->write_command
? : 1;
303 if (write_command
== 5)
305 raw3270_request_set_cmd(rq
, write_command
);
306 raw3270_request_set_idal(rq
, ib
);
307 rc
= fs3270_do_io(&fp
->view
, rq
);
309 rc
= count
- rq
->rescnt
;
312 raw3270_request_free(rq
);
315 idal_buffer_free(ib
);
320 * process ioctl commands for the tube driver
323 fs3270_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
326 struct raw3270_iocb iocb
;
329 fp
= filp
->private_data
;
336 fp
->read_command
= arg
;
339 fp
->write_command
= arg
;
342 rc
= put_user(fp
->read_command
, (char *) arg
);
345 rc
= put_user(fp
->write_command
,(char *) arg
);
348 iocb
.model
= fp
->view
.model
;
349 iocb
.line_cnt
= fp
->view
.rows
;
350 iocb
.col_cnt
= fp
->view
.cols
;
354 if (copy_to_user((char *) arg
, &iocb
,
355 sizeof(struct raw3270_iocb
)))
364 * Allocate fs3270 structure.
366 static struct fs3270
*
367 fs3270_alloc_view(void)
371 fp
= (struct fs3270
*) kmalloc(sizeof(struct fs3270
),GFP_KERNEL
);
373 return ERR_PTR(-ENOMEM
);
374 memset(fp
, 0, sizeof(struct fs3270
));
375 fp
->init
= raw3270_request_alloc(0);
376 if (IS_ERR(fp
->init
)) {
378 return ERR_PTR(-ENOMEM
);
384 * Free fs3270 structure.
387 fs3270_free_view(struct raw3270_view
*view
)
391 fp
= (struct fs3270
*) view
;
393 idal_buffer_free(fp
->rdbuf
);
394 raw3270_request_free(((struct fs3270
*) view
)->init
);
399 * Unlink fs3270 data structure from filp.
402 fs3270_release(struct raw3270_view
*view
)
406 /* View to a 3270 device. Can be console, tty or fullscreen. */
407 struct raw3270_fn fs3270_fn
= {
408 .activate
= fs3270_activate
,
409 .deactivate
= fs3270_deactivate
,
410 .intv
= (void *) fs3270_irq
,
411 .release
= fs3270_release
,
412 .free
= fs3270_free_view
416 * This routine is called whenever a 3270 fullscreen device is opened.
419 fs3270_open(struct inode
*inode
, struct file
*filp
)
422 struct idal_buffer
*ib
;
425 if (imajor(filp
->f_dentry
->d_inode
) != IBM_FS3270_MAJOR
)
427 minor
= iminor(filp
->f_dentry
->d_inode
);
428 /* Check for minor 0 multiplexer. */
430 if (!current
->signal
->tty
)
432 if (current
->signal
->tty
->driver
->major
!= IBM_TTY3270_MAJOR
)
434 minor
= current
->signal
->tty
->index
+ RAW3270_FIRSTMINOR
;
436 /* Check if some other program is already using fullscreen mode. */
437 fp
= (struct fs3270
*) raw3270_find_view(&fs3270_fn
, minor
);
439 raw3270_put_view(&fp
->view
);
442 /* Allocate fullscreen view structure. */
443 fp
= fs3270_alloc_view();
447 init_waitqueue_head(&fp
->wait
);
448 fp
->fs_pid
= current
->pid
;
449 rc
= raw3270_add_view(&fp
->view
, &fs3270_fn
, minor
);
451 fs3270_free_view(&fp
->view
);
455 /* Allocate idal-buffer. */
456 ib
= idal_buffer_alloc(2*fp
->view
.rows
*fp
->view
.cols
+ 5, 0);
458 raw3270_put_view(&fp
->view
);
459 raw3270_del_view(&fp
->view
);
464 rc
= raw3270_activate_view(&fp
->view
);
466 raw3270_put_view(&fp
->view
);
467 raw3270_del_view(&fp
->view
);
470 filp
->private_data
= fp
;
475 * This routine is called when the 3270 tty is closed. We wait
476 * for the remaining request to be completed. Then we clean up.
479 fs3270_close(struct inode
*inode
, struct file
*filp
)
483 fp
= filp
->private_data
;
484 filp
->private_data
= 0;
487 raw3270_reset(&fp
->view
);
488 raw3270_put_view(&fp
->view
);
489 raw3270_del_view(&fp
->view
);
494 static struct file_operations fs3270_fops
= {
495 .owner
= THIS_MODULE
, /* owner */
496 .read
= fs3270_read
, /* read */
497 .write
= fs3270_write
, /* write */
498 .unlocked_ioctl
= fs3270_ioctl
, /* ioctl */
499 .compat_ioctl
= fs3270_ioctl
, /* ioctl */
500 .open
= fs3270_open
, /* open */
501 .release
= fs3270_close
, /* release */
505 * 3270 fullscreen driver initialization.
512 rc
= register_chrdev(IBM_FS3270_MAJOR
, "fs3270", &fs3270_fops
);
514 printk(KERN_ERR
"fs3270 can't get major number %d: errno %d\n",
515 IBM_FS3270_MAJOR
, rc
);
524 unregister_chrdev(IBM_FS3270_MAJOR
, "fs3270");
527 MODULE_LICENSE("GPL");
528 MODULE_ALIAS_CHARDEV_MAJOR(IBM_FS3270_MAJOR
);
530 module_init(fs3270_init
);
531 module_exit(fs3270_exit
);