2 * IBM/3270 Driver -- Copyright (C) UTS Global LLC
4 * tubfs.c -- Fullscreen driver
10 * Author: Richard Hitt
14 int fs3270_major = -1; /* init to impossible -1 */
16 static int fs3270_open(struct inode *, struct file *);
17 static int fs3270_close(struct inode *, struct file *);
18 static int fs3270_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
19 static ssize_t fs3270_read(struct file *, char *, size_t, loff_t *);
20 static ssize_t fs3270_write(struct file *, const char *, size_t, loff_t *);
21 static int fs3270_wait(tub_t *, long *);
22 static void fs3270_int(tub_t *tubp, devstat_t *dsp);
23 extern void tty3270_refresh(tub_t *);
25 static struct file_operations fs3270_fops = {
26 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
27 owner: THIS_MODULE, /* owner */
29 read: fs3270_read, /* read */
30 write: fs3270_write, /* write */
31 ioctl: fs3270_ioctl, /* ioctl */
32 open: fs3270_open, /* open */
33 release:fs3270_close, /* release */
36 #ifdef CONFIG_DEVFS_FS
37 devfs_handle_t fs3270_devfs_dir;
38 devfs_handle_t fs3270_devfs_tub;
39 extern struct file_operations tty_fops;
41 void fs3270_devfs_register(tub_t *tubp)
45 sprintf(name, "tub%.4x", tubp->devno);
46 devfs_register(fs3270_devfs_dir, name, DEVFS_FL_DEFAULT,
47 IBM_FS3270_MAJOR, tubp->minor,
48 S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL);
49 sprintf(name, "tty%.4x", tubp->devno);
50 tty_register_devfs_name(&tty3270_driver, 0, tubp->minor,
51 fs3270_devfs_dir, name);
54 void fs3270_devfs_unregister(tub_t *tubp)
57 devfs_handle_t handle;
59 sprintf(name, "tub%.4x", tubp->devno);
60 handle = devfs_find_handle (fs3270_devfs_dir, name,
61 IBM_FS3270_MAJOR, tubp->minor,
62 DEVFS_SPECIAL_CHR, 0);
63 devfs_unregister (handle);
64 sprintf(name, "tty%.4x", tubp->devno);
65 handle = devfs_find_handle (fs3270_devfs_dir, name,
66 IBM_TTY3270_MAJOR, tubp->minor,
67 DEVFS_SPECIAL_CHR, 0);
68 devfs_unregister(handle);
73 * fs3270_init() -- Initialize fullscreen tubes
80 #ifdef CONFIG_DEVFS_FS
81 rc = devfs_register_chrdev (IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
83 printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n",
84 IBM_FS3270_MAJOR, rc);
87 fs3270_devfs_dir = devfs_mk_dir(NULL, "3270", NULL);
89 devfs_register(fs3270_devfs_dir, "tub", DEVFS_FL_DEFAULT,
91 S_IFCHR | S_IRUGO | S_IWUGO,
94 rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
96 printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n",
97 IBM_FS3270_MAJOR, rc);
101 fs3270_major = IBM_FS3270_MAJOR;
106 * fs3270_fini() -- Uninitialize fullscreen tubes
111 if (fs3270_major != -1) {
112 #ifdef CONFIG_DEVFS_FS
113 devfs_unregister(fs3270_devfs_tub);
114 devfs_unregister(fs3270_devfs_dir);
116 unregister_chrdev(fs3270_major, "fs3270");
125 fs3270_open(struct inode *ip, struct file *fp)
130 /* See INODE2TUB(ip) for handling of "/dev/3270/tub" */
131 if ((tubp = INODE2TUB(ip)) == NULL)
134 TUBLOCK(tubp->irq, flags);
135 if (tubp->mode == TBM_FS || tubp->mode == TBM_FSLN) {
136 TUBUNLOCK(tubp->irq, flags);
141 fp->private_data = ip;
143 tubp->intv = fs3270_int;
145 tubp->fs_pid = current->pid;
147 TUBUNLOCK(tubp->irq, flags);
152 * fs3270_close aka release: free the irq
155 fs3270_close(struct inode *ip, struct file *fp)
160 if ((tubp = INODE2TUB(ip)) == NULL)
163 fs3270_wait(tubp, &flags);
169 tty3270_refresh(tubp);
170 TUBUNLOCK(tubp->irq, flags);
175 * fs3270_release() called from tty3270_hangup()
178 fs3270_release(tub_t *tubp)
182 if (tubp->mode != TBM_FS)
184 fs3270_wait(tubp, &flags);
190 /*tty3270_refresh(tubp);*/
191 TUBUNLOCK(tubp->irq, flags);
195 * fs3270_wait(tub_t *tubp, int *flags) -- Wait to use tube
196 * Entered without irq lock
199 * * Value is 0 or -ERESTARTSYS
202 fs3270_wait(tub_t *tubp, long *flags)
204 DECLARE_WAITQUEUE(wait, current);
206 TUBLOCK(tubp->irq, *flags);
207 add_wait_queue(&tubp->waitq, &wait);
208 while (!signal_pending(current) &&
209 ((tubp->mode != TBM_FS) ||
210 (tubp->flags & (TUB_WORKING | TUB_RDPENDING)) != 0)) {
211 current->state = TASK_INTERRUPTIBLE;
212 TUBUNLOCK(tubp->irq, *flags);
214 current->state = TASK_RUNNING;
215 TUBLOCK(tubp->irq, *flags);
217 remove_wait_queue(&tubp->waitq, &wait);
218 return signal_pending(current)? -ERESTARTSYS: 0;
222 * fs3270_io(tubp, ccw1_t*) -- start I/O on the tube
223 * Entered with irq lock held, WORKING off
226 fs3270_io(tub_t *tubp, ccw1_t *ccwp)
230 rc = do_IO(tubp->irq, ccwp, tubp->irq, 0, 0);
231 tubp->flags |= TUB_WORKING;
237 * fs3270_bh(tubp) -- Perform back-half processing
240 fs3270_bh(void *data)
246 TUBLOCK(tubp->irq, flags);
247 tubp->flags &= ~TUB_BHPENDING;
249 if (tubp->wbuf) { /* if we were writing */
250 idal_buffer_free(tubp->wbuf);
254 if ((tubp->flags & (TUB_ATTN | TUB_RDPENDING)) ==
255 (TUB_ATTN | TUB_RDPENDING)) {
256 fs3270_io(tubp, &tubp->rccw);
257 tubp->flags &= ~(TUB_ATTN | TUB_RDPENDING);
260 if ((tubp->flags & TUB_WORKING) == 0)
261 wake_up_interruptible(&tubp->waitq);
263 TUBUNLOCK(tubp->irq, flags);
267 * fs3270_sched_bh(tubp) -- Schedule the back half
268 * Irq lock must be held on entry and remains held on exit.
271 fs3270_sched_bh(tub_t *tubp)
273 if (tubp->flags & TUB_BHPENDING)
275 tubp->flags |= TUB_BHPENDING;
276 tubp->tqueue.routine = fs3270_bh;
277 tubp->tqueue.data = tubp;
278 queue_task(&tubp->tqueue, &tq_immediate);
279 mark_bh(IMMEDIATE_BH);
283 * fs3270_int(tubp, prp) -- Process interrupt from tube in FS mode
284 * This routine is entered with irq lock held (see do_IRQ in s390io.c)
287 fs3270_int(tub_t *tubp, devstat_t *dsp)
289 #define DEV_UE_BUSY \
290 (DEV_STAT_CHN_END | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP)
293 /* XXX needs more work; must save 2d arg to fs370_io() */
294 /* Handle CE-DE-UE and subsequent UDE */
295 if (dsp->dstat == DEV_UE_BUSY) {
296 tubp->flags |= TUB_UE_BUSY;
298 } else if (tubp->flags & TUB_UE_BUSY) {
299 tubp->flags &= ~TUB_UE_BUSY;
300 if (dsp->dstat == DEV_STAT_DEV_END &&
301 (tubp->flags & TUB_WORKING) != 0) {
309 if (dsp->dstat & DEV_STAT_ATTENTION)
310 tubp->flags |= TUB_ATTN;
312 if (dsp->dstat & DEV_STAT_CHN_END) {
313 tubp->cswl = dsp->rescnt;
314 if ((dsp->dstat & DEV_STAT_DEV_END) == 0)
315 tubp->flags |= TUB_EXPECT_DE;
317 tubp->flags &= ~TUB_EXPECT_DE;
318 } else if (dsp->dstat & DEV_STAT_DEV_END) {
319 if ((tubp->flags & TUB_EXPECT_DE) == 0)
320 tubp->flags |= TUB_UNSOL_DE;
321 tubp->flags &= ~TUB_EXPECT_DE;
323 if (dsp->dstat & DEV_STAT_DEV_END)
324 tubp->flags &= ~TUB_WORKING;
326 if ((tubp->flags & TUB_WORKING) == 0)
327 fs3270_sched_bh(tubp);
331 * process ioctl commands for the tube driver
334 fs3270_ioctl(struct inode *ip, struct file *fp,
335 unsigned int cmd, unsigned long arg)
341 if ((tubp = INODE2TUB(ip)) == NULL)
343 if ((rc = fs3270_wait(tubp, &flags))) {
344 TUBUNLOCK(tubp->irq, flags);
349 case TUBICMD: tubp->icmd = arg; break;
350 case TUBOCMD: tubp->ocmd = arg; break;
351 case TUBGETI: put_user(tubp->icmd, (char *)arg); break;
352 case TUBGETO: put_user(tubp->ocmd, (char *)arg); break;
354 if (copy_to_user((char *)arg, &tubp->tubiocb,
355 sizeof tubp->tubiocb))
359 TUBUNLOCK(tubp->irq, flags);
364 * process read commands for the tube driver
367 fs3270_read(struct file *fp, char *dp, size_t len, loff_t *off)
373 struct idal_buffer *idal_buffer;
375 if (len == 0 || len > 65535) {
379 if ((tubp = INODE2TUB((struct inode *)fp->private_data)) == NULL)
382 if((idal_buffer = idal_buffer_alloc(len, 0)) == NULL) {
387 if ((rc = fs3270_wait(tubp, &flags)) != 0) {
388 TUBUNLOCK(tubp->irq, flags);
393 if (tubp->icmd == 0 && tubp->ocmd != 0) tubp->icmd = 6;
394 cp->cmd_code = tubp->icmd?:2;
395 idal_buffer_set_cda(idal_buffer, cp);
396 cp->flags |= CCW_FLAG_SLI;
397 tubp->flags |= TUB_RDPENDING;
398 TUBUNLOCK(tubp->irq, flags);
400 if ((rc = fs3270_wait(tubp, &flags)) != 0) {
401 tubp->flags &= ~TUB_RDPENDING;
403 TUBUNLOCK(tubp->irq, flags);
406 TUBUNLOCK(tubp->irq, flags);
409 if (idal_buffer_to_user(idal_buffer, dp, len) != 0) {
415 idal_buffer_free(idal_buffer);
421 * process write commands for the tube driver
424 fs3270_write(struct file *fp, const char *dp, size_t len, loff_t *off)
430 struct idal_buffer *idal_buffer;
432 if (len > 65535 || len == 0)
435 /* Locate the tube */
436 if ((tubp = INODE2TUB((struct inode *)fp->private_data)) == NULL)
439 if ((idal_buffer = idal_buffer_alloc(len, 0)) == NULL)
442 if (idal_buffer_from_user(idal_buffer, dp, len) != 0) {
447 /* Wait till tube's not working or signal is pending */
448 if ((rc = fs3270_wait(tubp, &flags))) {
450 TUBUNLOCK(tubp->irq, flags);
454 /* Make CCW and start I/O. Back end will free buffers & idal. */
456 cp->cmd_code = tubp->ocmd? tubp->ocmd == 5? 13: tubp->ocmd: 1;
457 tubp->wbuf = idal_buffer;
458 idal_buffer_set_cda(idal_buffer, cp);
459 cp->flags |= CCW_FLAG_SLI;
461 TUBUNLOCK(tubp->irq, flags);
466 idal_buffer_free(idal_buffer);