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 struct raw3270_request
*clear
; /* single clear request. */
37 wait_queue_head_t attn_wait
; /* Attention wait queue. */
41 fs3270_wake_up(struct raw3270_request
*rq
, void *data
)
43 wake_up((wait_queue_head_t
*) data
);
47 fs3270_do_io(struct raw3270_view
*view
, struct raw3270_request
*rq
)
52 init_waitqueue_head(&wq
);
53 rq
->callback
= fs3270_wake_up
;
54 rq
->callback_data
= &wq
;
55 rc
= raw3270_start(view
, rq
);
58 /* Started sucessfully. Now wait for completion. */
59 wait_event(wq
, raw3270_request_final(rq
));
64 fs3270_reset_callback(struct raw3270_request
*rq
, void *data
)
66 raw3270_request_reset(rq
);
70 * Switch to the fullscreen view.
73 fs3270_activate(struct raw3270_view
*view
)
77 fp
= (struct fs3270
*) view
;
78 raw3270_request_set_cmd(fp
->clear
, TC_EWRITEA
);
79 fp
->clear
->callback
= fs3270_reset_callback
;
80 return raw3270_start(view
, fp
->clear
);
84 * Shutdown fullscreen view.
87 fs3270_deactivate(struct raw3270_view
*view
)
89 // FIXME: is this a good idea? The user program using fullscreen 3270
90 // will die just because a console message appeared. On the other
91 // hand the fullscreen device is unoperational now.
94 fp
= (struct fs3270
*) view
;
96 kill_proc(fp
->fs_pid
, SIGHUP
, 1);
101 fs3270_irq(struct fs3270
*fp
, struct raw3270_request
*rq
, struct irb
*irb
)
103 /* Handle ATTN. Set indication and wake waiters for attention. */
104 if (irb
->scsw
.dstat
& DEV_STAT_ATTENTION
) {
106 wake_up(&fp
->attn_wait
);
110 if (irb
->scsw
.dstat
& DEV_STAT_UNIT_CHECK
)
113 /* Normal end. Copy residual count. */
114 rq
->rescnt
= irb
->scsw
.count
;
116 return RAW3270_IO_DONE
;
120 * Process reads from fullscreen 3270.
123 fs3270_read(struct file
*filp
, char *data
, size_t count
, loff_t
*off
)
126 struct raw3270_request
*rq
;
127 struct idal_buffer
*ib
;
130 if (count
== 0 || count
> 65535)
132 fp
= filp
->private_data
;
135 ib
= idal_buffer_alloc(count
, 0);
138 rq
= raw3270_request_alloc(0);
140 if (fp
->read_command
== 0 && fp
->write_command
!= 0)
141 fp
->read_command
= 6;
142 raw3270_request_set_cmd(rq
, fp
->read_command
? : 2);
143 raw3270_request_set_idal(rq
, ib
);
144 wait_event(fp
->attn_wait
, fp
->attention
);
145 rc
= fs3270_do_io(&fp
->view
, rq
);
146 if (rc
== 0 && idal_buffer_to_user(ib
, data
, count
))
148 raw3270_request_free(rq
);
151 idal_buffer_free(ib
);
156 * Process writes to fullscreen 3270.
159 fs3270_write(struct file
*filp
, const char *data
, size_t count
, loff_t
*off
)
162 struct raw3270_request
*rq
;
163 struct idal_buffer
*ib
;
167 fp
= filp
->private_data
;
170 ib
= idal_buffer_alloc(count
, 0);
173 rq
= raw3270_request_alloc(0);
175 if (idal_buffer_from_user(ib
, data
, count
) == 0) {
176 write_command
= fp
->write_command
? : 1;
177 if (write_command
== 5)
179 raw3270_request_set_cmd(rq
, write_command
);
180 raw3270_request_set_idal(rq
, ib
);
181 rc
= fs3270_do_io(&fp
->view
, rq
);
184 raw3270_request_free(rq
);
187 idal_buffer_free(ib
);
192 * process ioctl commands for the tube driver
195 fs3270_ioctl(struct inode
*inode
, struct file
*filp
,
196 unsigned int cmd
, unsigned long arg
)
199 struct raw3270_iocb iocb
;
202 fp
= filp
->private_data
;
208 fp
->read_command
= arg
;
211 fp
->write_command
= arg
;
214 rc
= put_user(fp
->read_command
, (char *) arg
);
217 rc
= put_user(fp
->write_command
,(char *) arg
);
220 iocb
.model
= fp
->view
.model
;
221 iocb
.line_cnt
= fp
->view
.rows
;
222 iocb
.col_cnt
= fp
->view
.cols
;
226 if (copy_to_user((char *) arg
, &iocb
,
227 sizeof(struct raw3270_iocb
)))
235 * Allocate tty3270 structure.
237 static struct fs3270
*
238 fs3270_alloc_view(void)
242 fp
= (struct fs3270
*) kmalloc(sizeof(struct fs3270
),GFP_KERNEL
);
244 return ERR_PTR(-ENOMEM
);
245 memset(fp
, 0, sizeof(struct fs3270
));
246 fp
->clear
= raw3270_request_alloc(0);
247 if (!IS_ERR(fp
->clear
)) {
249 return ERR_PTR(-ENOMEM
);
255 * Free tty3270 structure.
258 fs3270_free_view(struct raw3270_view
*view
)
260 raw3270_request_free(((struct fs3270
*) view
)->clear
);
265 * Unlink fs3270 data structure from filp.
268 fs3270_release(struct raw3270_view
*view
)
272 /* View to a 3270 device. Can be console, tty or fullscreen. */
273 struct raw3270_fn fs3270_fn
= {
274 .activate
= fs3270_activate
,
275 .deactivate
= fs3270_deactivate
,
276 .intv
= (void *) fs3270_irq
,
277 .release
= fs3270_release
,
278 .free
= fs3270_free_view
282 * This routine is called whenever a 3270 fullscreen device is opened.
285 fs3270_open(struct inode
*inode
, struct file
*filp
)
290 if (imajor(filp
->f_dentry
->d_inode
) != IBM_FS3270_MAJOR
)
292 minor
= iminor(filp
->f_dentry
->d_inode
);
293 /* Check if some other program is already using fullscreen mode. */
294 fp
= (struct fs3270
*) raw3270_find_view(&fs3270_fn
, minor
);
296 raw3270_put_view(&fp
->view
);
299 /* Allocate fullscreen view structure. */
300 fp
= fs3270_alloc_view();
304 init_waitqueue_head(&fp
->attn_wait
);
305 fp
->fs_pid
= current
->pid
;
306 rc
= raw3270_add_view(&fp
->view
, &fs3270_fn
, minor
);
308 fs3270_free_view(&fp
->view
);
312 rc
= raw3270_activate_view(&fp
->view
);
314 raw3270_del_view(&fp
->view
);
317 filp
->private_data
= fp
;
322 * This routine is called when the 3270 tty is closed. We wait
323 * for the remaining request to be completed. Then we clean up.
326 fs3270_close(struct inode
*inode
, struct file
*filp
)
330 fp
= filp
->private_data
;
331 filp
->private_data
= 0;
333 raw3270_del_view(&fp
->view
);
337 static struct file_operations fs3270_fops
= {
338 .owner
= THIS_MODULE
, /* owner */
339 .read
= fs3270_read
, /* read */
340 .write
= fs3270_write
, /* write */
341 .ioctl
= fs3270_ioctl
, /* ioctl */
342 .open
= fs3270_open
, /* open */
343 .release
= fs3270_close
, /* release */
347 * 3270 fullscreen driver initialization.
354 rc
= register_chrdev(IBM_FS3270_MAJOR
, "fs3270", &fs3270_fops
);
356 printk(KERN_ERR
"fs3270 can't get major number %d: errno %d\n",
357 IBM_FS3270_MAJOR
, rc
);
366 unregister_chrdev(IBM_FS3270_MAJOR
, "fs3270");
369 MODULE_LICENSE("GPL");
370 MODULE_ALIAS_CHARDEV_MAJOR(IBM_FS3270_MAJOR
);
372 module_init(fs3270_init
);
373 module_exit(fs3270_exit
);