Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed3cb6f0 authored by Richard Hitt's avatar Richard Hitt Committed by Linus Torvalds
Browse files

[PATCH] s390: 3270 fullscreen view



      Martin Schwidefsky <schwidefsky@de.ibm.com>

Fix fullscreen view of the 3270 device driver.

Signed-off-by: default avatarRichard Hitt <rbh00@utsglobal.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d89ea9b8
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include <asm/dasd.h>
#include <asm/cmb.h>
#include <asm/tape390.h>
#include <asm/ccwdev.h>
#include "../../../drivers/s390/char/raw3270.h"

static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
				unsigned long arg, struct file *f)
@@ -62,6 +64,13 @@ COMPATIBLE_IOCTL(BIODASDCMFENABLE)
COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
COMPATIBLE_IOCTL(BIODASDREADALLCMB)

COMPATIBLE_IOCTL(TUBICMD)
COMPATIBLE_IOCTL(TUBOCMD)
COMPATIBLE_IOCTL(TUBGETI)
COMPATIBLE_IOCTL(TUBGETO)
COMPATIBLE_IOCTL(TUBSETMOD)
COMPATIBLE_IOCTL(TUBGETMOD)

COMPATIBLE_IOCTL(TAPE390_DISPLAY)

/* s390 doesn't need handlers here */
+4 −3
Original line number Diff line number Diff line
@@ -213,6 +213,9 @@ con3270_update(struct con3270 *cp)
	struct string *s, *n;
	int rc;

	if (cp->view.dev)
		raw3270_activate_view(&cp->view);

	wrq = xchg(&cp->write, 0);
	if (!wrq) {
		con3270_set_timer(cp, 1);
@@ -489,8 +492,6 @@ con3270_write(struct console *co, const char *str, unsigned int count)
	unsigned char c;

	cp = condev;
	if (cp->view.dev)
		raw3270_activate_view(&cp->view);
	spin_lock_irqsave(&cp->view.lock, flags);
	while (count-- > 0) {
		c = *str++;
@@ -620,7 +621,7 @@ con3270_init(void)
		     (void (*)(unsigned long)) con3270_read_tasklet,
		     (unsigned long) condev->read);

	raw3270_add_view(&condev->view, &con3270_fn, 0);
	raw3270_add_view(&condev->view, &con3270_fn, 1);

	INIT_LIST_HEAD(&condev->freemem);
	for (i = 0; i < CON3270_STRING_PAGES; i++) {
+195 −39
Original line number Diff line number Diff line
@@ -33,8 +33,11 @@ struct fs3270 {
	int read_command;		/* ccw command to use for reads. */
	int write_command;		/* ccw command to use for writes. */
	int attention;			/* Got attention. */
	struct raw3270_request *clear;	/* single clear request. */
	wait_queue_head_t attn_wait;	/* Attention wait queue. */
	int active;			/* Fullscreen view is active. */
	struct raw3270_request *init;	/* single init request. */
	wait_queue_head_t wait;		/* Init & attention wait queue. */
	struct idal_buffer *rdbuf;	/* full-screen-deactivate buffer */
	size_t rdbuf_size;		/* size of data returned by RDBUF */
};

static void
@@ -43,58 +46,172 @@ fs3270_wake_up(struct raw3270_request *rq, void *data)
	wake_up((wait_queue_head_t *) data);
}

static inline int
fs3270_working(struct fs3270 *fp)
{
	/*
	 * The fullscreen view is in working order if the view
	 * has been activated AND the initial request is finished.
	 */
	return fp->active && raw3270_request_final(fp->init);
}

static int
fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq)
{
	wait_queue_head_t wq;
	struct fs3270 *fp;
	int rc;

	init_waitqueue_head(&wq);
	fp = (struct fs3270 *) view;
	rq->callback = fs3270_wake_up;
	rq->callback_data = &wq;
	rq->callback_data = &fp->wait;

	do {
		if (!fs3270_working(fp)) {
			/* Fullscreen view isn't ready yet. */
			rc = wait_event_interruptible(fp->wait,
						      fs3270_working(fp));
			if (rc != 0)
				break;
		}
		rc = raw3270_start(view, rq);
	if (rc)
		return rc;
		if (rc == 0) {
			/* Started sucessfully. Now wait for completion. */
	wait_event(wq, raw3270_request_final(rq));
	return rq->rc;
			wait_event(fp->wait, raw3270_request_final(rq));
		}
	} while (rc == -EACCES);
	return rc;
}

/*
 * Switch to the fullscreen view.
 */
static void
fs3270_reset_callback(struct raw3270_request *rq, void *data)
{
	struct fs3270 *fp;

	fp = (struct fs3270 *) rq->view;
	raw3270_request_reset(rq);
	wake_up(&fp->wait);
}

static void
fs3270_restore_callback(struct raw3270_request *rq, void *data)
{
	struct fs3270 *fp;

	fp = (struct fs3270 *) rq->view;
	if (rq->rc != 0 || rq->rescnt != 0) {
		if (fp->fs_pid)
			kill_proc(fp->fs_pid, SIGHUP, 1);
	}
	fp->rdbuf_size = 0;
	raw3270_request_reset(rq);
	wake_up(&fp->wait);
}

/*
 * Switch to the fullscreen view.
 */
static int
fs3270_activate(struct raw3270_view *view)
{
	struct fs3270 *fp;
	char *cp;
	int rc;

	fp = (struct fs3270 *) view;
	raw3270_request_set_cmd(fp->clear, TC_EWRITEA);
	fp->clear->callback = fs3270_reset_callback;
	return raw3270_start(view, fp->clear);

	/* If an old init command is still running just return. */
	if (!raw3270_request_final(fp->init))
		return 0;

	if (fp->rdbuf_size == 0) {
		/* No saved buffer. Just clear the screen. */
		raw3270_request_set_cmd(fp->init, TC_EWRITEA);
		fp->init->callback = fs3270_reset_callback;
	} else {
		/* Restore fullscreen buffer saved by fs3270_deactivate. */
		raw3270_request_set_cmd(fp->init, TC_EWRITEA);
		raw3270_request_set_idal(fp->init, fp->rdbuf);
		fp->init->ccw.count = fp->rdbuf_size;
		cp = fp->rdbuf->data[0];
		cp[0] = TW_KR;
		cp[1] = TO_SBA;
		cp[2] = cp[6];
		cp[3] = cp[7];
		cp[4] = TO_IC;
		cp[5] = TO_SBA;
		cp[6] = 0x40;
		cp[7] = 0x40;
		fp->init->rescnt = 0;
		fp->init->callback = fs3270_restore_callback;
	}
	rc = fp->init->rc = raw3270_start_locked(view, fp->init);
	if (rc)
		fp->init->callback(fp->init, NULL);
	else
		fp->active = 1;
	return rc;
}

/*
 * Shutdown fullscreen view.
 */
static void
fs3270_save_callback(struct raw3270_request *rq, void *data)
{
	struct fs3270 *fp;

	fp = (struct fs3270 *) rq->view;

	/* Correct idal buffer element 0 address. */
	fp->rdbuf->data[0] -= 5;
	fp->rdbuf->size += 5;

	/*
	 * If the rdbuf command failed or the idal buffer is
	 * to small for the amount of data returned by the
	 * rdbuf command, then we have no choice but to send
	 * a SIGHUP to the application.
	 */
	if (rq->rc != 0 || rq->rescnt == 0) {
		if (fp->fs_pid)
			kill_proc(fp->fs_pid, SIGHUP, 1);
		fp->rdbuf_size = 0;
	} else
		fp->rdbuf_size = fp->rdbuf->size - rq->rescnt;
	raw3270_request_reset(rq);
	wake_up(&fp->wait);
}

static void
fs3270_deactivate(struct raw3270_view *view)
{
	// FIXME: is this a good idea? The user program using fullscreen 3270
	// will die just because a console message appeared. On the other
	// hand the fullscreen device is unoperational now.
	struct fs3270 *fp;

	fp = (struct fs3270 *) view;
	if (fp->fs_pid != 0)
		kill_proc(fp->fs_pid, SIGHUP, 1);
	fp->fs_pid = 0;
	fp->active = 0;

	/* If an old init command is still running just return. */
	if (!raw3270_request_final(fp->init))
		return;

	/* Prepare read-buffer request. */
	raw3270_request_set_cmd(fp->init, TC_RDBUF);
	/*
	 * Hackish: skip first 5 bytes of the idal buffer to make
	 * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
	 * in the activation command.
	 */
	fp->rdbuf->data[0] += 5;
	fp->rdbuf->size -= 5;
	raw3270_request_set_idal(fp->init, fp->rdbuf);
	fp->init->rescnt = 0;
	fp->init->callback = fs3270_save_callback;

	/* Start I/O to read in the 3270 buffer. */
	fp->init->rc = raw3270_start_locked(view, fp->init);
	if (fp->init->rc)
		fp->init->callback(fp->init, NULL);
}

static int
@@ -103,7 +220,7 @@ fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
	/* Handle ATTN. Set indication and wake waiters for attention. */
	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
		fp->attention = 1;
		wake_up(&fp->attn_wait);
		wake_up(&fp->wait);
	}

	if (rq) {
@@ -125,7 +242,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
	struct fs3270 *fp;
	struct raw3270_request *rq;
	struct idal_buffer *ib;
	int rc;
	ssize_t rc;
	
	if (count == 0 || count > 65535)
		return -EINVAL;
@@ -133,7 +250,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
	if (!fp)
		return -ENODEV;
	ib = idal_buffer_alloc(count, 0);
	if (!ib)
	if (IS_ERR(ib))
		return -ENOMEM;
	rq = raw3270_request_alloc(0);
	if (!IS_ERR(rq)) {
@@ -141,10 +258,19 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
			fp->read_command = 6;
		raw3270_request_set_cmd(rq, fp->read_command ? : 2);
		raw3270_request_set_idal(rq, ib);
		wait_event(fp->attn_wait, fp->attention);
		rc = wait_event_interruptible(fp->wait, fp->attention);
		fp->attention = 0;
		if (rc == 0) {
			rc = fs3270_do_io(&fp->view, rq);
		if (rc == 0 && idal_buffer_to_user(ib, data, count))
			if (rc == 0) {
				count -= rq->rescnt;
				if (idal_buffer_to_user(ib, data, count) != 0)
					rc = -EFAULT;
				else
					rc = count;

			}
		}
		raw3270_request_free(rq);
	} else
		rc = PTR_ERR(rq);
@@ -162,13 +288,13 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
	struct raw3270_request *rq;
	struct idal_buffer *ib;
	int write_command;
	int rc;
	ssize_t rc;

	fp = filp->private_data;
	if (!fp)
		return -ENODEV;
	ib = idal_buffer_alloc(count, 0);
	if (!ib)
	if (IS_ERR(ib))
		return -ENOMEM;
	rq = raw3270_request_alloc(0);
	if (!IS_ERR(rq)) {
@@ -179,6 +305,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
			raw3270_request_set_cmd(rq, write_command);
			raw3270_request_set_idal(rq, ib);
			rc = fs3270_do_io(&fp->view, rq);
			if (rc == 0)
				rc = count - rq->rescnt;
		} else
			rc = -EFAULT;
		raw3270_request_free(rq);
@@ -232,7 +360,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
}

/*
 * Allocate tty3270 structure.
 * Allocate fs3270 structure.
 */
static struct fs3270 *
fs3270_alloc_view(void)
@@ -243,8 +371,8 @@ fs3270_alloc_view(void)
	if (!fp)
		return ERR_PTR(-ENOMEM);
	memset(fp, 0, sizeof(struct fs3270));
	fp->clear = raw3270_request_alloc(0);
	if (!IS_ERR(fp->clear)) {
	fp->init = raw3270_request_alloc(0);
	if (IS_ERR(fp->init)) {
		kfree(fp);
		return ERR_PTR(-ENOMEM);
	}
@@ -252,12 +380,17 @@ fs3270_alloc_view(void)
}

/*
 * Free tty3270 structure.
 * Free fs3270 structure.
 */
static void
fs3270_free_view(struct raw3270_view *view)
{
	raw3270_request_free(((struct fs3270 *) view)->clear);
	struct fs3270 *fp;

	fp = (struct fs3270 *) view;
	if (fp->rdbuf)
		idal_buffer_free(fp->rdbuf);
	raw3270_request_free(((struct fs3270 *) view)->init);
	kfree(view);
}

@@ -285,11 +418,20 @@ static int
fs3270_open(struct inode *inode, struct file *filp)
{
	struct fs3270 *fp;
	struct idal_buffer *ib;
	int minor, rc;

	if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
		return -ENODEV;
	minor = iminor(filp->f_dentry->d_inode);
	/* Check for minor 0 multiplexer. */
	if (minor == 0) {
		if (!current->signal->tty)
			return -ENODEV;
		if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
			return -ENODEV;
		minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
	}
	/* Check if some other program is already using fullscreen mode. */
	fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
	if (!IS_ERR(fp)) {
@@ -301,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp)
	if (IS_ERR(fp))
		return PTR_ERR(fp);

	init_waitqueue_head(&fp->attn_wait);
	init_waitqueue_head(&fp->wait);
	fp->fs_pid = current->pid;
	rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
	if (rc) {
@@ -309,8 +451,18 @@ fs3270_open(struct inode *inode, struct file *filp)
		return rc;
	}

	/* Allocate idal-buffer. */
	ib = idal_buffer_alloc(2*fp->view.rows*fp->view.cols + 5, 0);
	if (IS_ERR(ib)) {
		raw3270_put_view(&fp->view);
		raw3270_del_view(&fp->view);
		return PTR_ERR(fp);
	}
	fp->rdbuf = ib;

	rc = raw3270_activate_view(&fp->view);
	if (rc) {
		raw3270_put_view(&fp->view);
		raw3270_del_view(&fp->view);
		return rc;
	}
@@ -329,8 +481,12 @@ fs3270_close(struct inode *inode, struct file *filp)

	fp = filp->private_data;
	filp->private_data = 0;
	if (fp)
	if (fp) {
		fp->fs_pid = 0;
		raw3270_reset(&fp->view);
		raw3270_put_view(&fp->view);
		raw3270_del_view(&fp->view);
	}
	return 0;
}

+88 −12
Original line number Diff line number Diff line
@@ -25,6 +25,12 @@

#include "raw3270.h"

#include <linux/major.h>
#include <linux/kdev_t.h>
#include <linux/device.h>

struct class *class3270;

/* The main 3270 data structure. */
struct raw3270 {
	struct list_head list;
@@ -41,6 +47,8 @@ struct raw3270 {
	struct timer_list timer;	/* Device timer. */

	unsigned char *ascebc;		/* ascii -> ebcdic table */
	struct class_device *clttydev;	/* 3270-class tty device ptr */
	struct class_device *cltubdev;	/* 3270-class tub device ptr */
};

/* raw3270->flags */
@@ -316,6 +324,22 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
	return rc;
}

int
raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
{
	struct raw3270 *rp;
	int rc;

	rp = view->dev;
	if (!rp || rp->view != view)
		rc = -EACCES;
	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
		rc = -ENODEV;
	else
		rc =  __raw3270_start(rp, view, rq);
	return rc;
}

int
raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
{
@@ -744,6 +768,22 @@ raw3270_reset_device(struct raw3270 *rp)
	return rc;
}

int
raw3270_reset(struct raw3270_view *view)
{
	struct raw3270 *rp;
	int rc;

	rp = view->dev;
	if (!rp || rp->view != view)
		rc = -EACCES;
	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
		rc = -ENODEV;
	else
		rc = raw3270_reset_device(view->dev);
	return rc;
}

/*
 * Setup new 3270 device.
 */
@@ -774,11 +814,12 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)

	/*
	 * Add device to list and find the smallest unused minor
	 * number for it.
	 * number for it. Note: there is no device with minor 0,
	 * see special case for fs3270.c:fs3270_open().
	 */
	down(&raw3270_sem);
	/* Keep the list sorted. */
	minor = 0;
	minor = RAW3270_FIRSTMINOR;
	rp->minor = -1;
	list_for_each(l, &raw3270_devices) {
		tmp = list_entry(l, struct raw3270, list);
@@ -789,7 +830,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
		}
		minor++;
	}
	if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {
	if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
		rp->minor = minor;
		list_add_tail(&rp->list, &raw3270_devices);
	}
@@ -941,10 +982,11 @@ raw3270_deactivate_view(struct raw3270_view *view)
		list_add_tail(&view->list, &rp->view_list);
		/* Try to activate another view. */
		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
			list_for_each_entry(view, &rp->view_list, list)
				if (view->fn->activate(view) == 0) {
			list_for_each_entry(view, &rp->view_list, list) {
				rp->view = view;
				if (view->fn->activate(view) == 0)
					break;
				rp->view = 0;
			}
		}
	}
@@ -961,6 +1003,8 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
	struct raw3270 *rp;
	int rc;

	if (minor <= 0)
		return -ENODEV;
	down(&raw3270_sem);
	rc = -ENODEV;
	list_for_each_entry(rp, &raw3270_devices, list) {
@@ -976,7 +1020,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
			view->cols = rp->cols;
			view->ascebc = rp->ascebc;
			spin_lock_init(&view->lock);
			list_add_tail(&view->list, &rp->view_list);
			list_add(&view->list, &rp->view_list);
			rc = 0;
		}
		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -1039,7 +1083,7 @@ raw3270_del_view(struct raw3270_view *view)
	if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
		/* Try to activate another view. */
		list_for_each_entry(nv, &rp->view_list, list) {
			if (nv->fn->activate(view) == 0) {
			if (nv->fn->activate(nv) == 0) {
				rp->view = nv;
				break;
			}
@@ -1063,6 +1107,12 @@ raw3270_delete_device(struct raw3270 *rp)

	/* Remove from device chain. */
	down(&raw3270_sem);
	if (rp->clttydev)
		class_device_destroy(class3270,
				     MKDEV(IBM_TTY3270_MAJOR, rp->minor));
	if (rp->cltubdev)
		class_device_destroy(class3270,
				     MKDEV(IBM_FS3270_MAJOR, rp->minor));
	list_del_init(&rp->list);
	up(&raw3270_sem);

@@ -1129,6 +1179,16 @@ raw3270_create_attributes(struct raw3270 *rp)
{
	//FIXME: check return code
	sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
	rp->clttydev =
		class_device_create(class3270,
				    MKDEV(IBM_TTY3270_MAJOR, rp->minor),
				    &rp->cdev->dev, "tty%s",
				    rp->cdev->dev.bus_id);
	rp->cltubdev =
		class_device_create(class3270,
				    MKDEV(IBM_FS3270_MAJOR, rp->minor),
				    &rp->cdev->dev, "tub%s",
				    rp->cdev->dev.bus_id);
}

/*
@@ -1189,13 +1249,13 @@ raw3270_set_online (struct ccw_device *cdev)
		return PTR_ERR(rp);
	rc = raw3270_reset_device(rp);
	if (rc)
		return rc;
		goto failure;
	rc = raw3270_size_device(rp);
	if (rc)
		return rc;
		goto failure;
	rc = raw3270_reset_device(rp);
	if (rc)
		return rc;
		goto failure;
	raw3270_create_attributes(rp);
	set_bit(RAW3270_FLAGS_READY, &rp->flags);
	down(&raw3270_sem);
@@ -1203,6 +1263,10 @@ raw3270_set_online (struct ccw_device *cdev)
		np->notifier(rp->minor, 1);
	up(&raw3270_sem);
	return 0;

failure:
	raw3270_delete_device(rp);
	return rc;
}

/*
@@ -1217,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev)
	struct raw3270_notifier *np;

	rp = cdev->dev.driver_data;
	/*
	 * _remove is the opposite of _probe; it's probe that
	 * should set up rp.  raw3270_remove gets entered for
	 * devices even if they haven't been varied online.
	 * Thus, rp may validly be NULL here.
	 */
	if (rp == NULL)
		return;
	clear_bit(RAW3270_FLAGS_READY, &rp->flags);

	sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
@@ -1301,6 +1373,7 @@ raw3270_init(void)
	if (rc == 0) {
		/* Create attributes for early (= console) device. */
		down(&raw3270_sem);
		class3270 = class_create(THIS_MODULE, "3270");
		list_for_each_entry(rp, &raw3270_devices, list) {
			get_device(&rp->cdev->dev);
			raw3270_create_attributes(rp);
@@ -1314,6 +1387,7 @@ static void
raw3270_exit(void)
{
	ccw_driver_unregister(&raw3270_ccw_driver);
	class_destroy(class3270);
}

MODULE_LICENSE("GPL");
@@ -1335,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view);
EXPORT_SYMBOL(raw3270_activate_view);
EXPORT_SYMBOL(raw3270_deactivate_view);
EXPORT_SYMBOL(raw3270_start);
EXPORT_SYMBOL(raw3270_start_locked);
EXPORT_SYMBOL(raw3270_start_irq);
EXPORT_SYMBOL(raw3270_reset);
EXPORT_SYMBOL(raw3270_register_notifier);
EXPORT_SYMBOL(raw3270_unregister_notifier);
EXPORT_SYMBOL(raw3270_wait_queue);
+6 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

/* Local Channel Commands */
#define TC_WRITE	0x01		/* Write */
#define TC_RDBUF	0x02		/* Read Buffer */
#define TC_EWRITE	0x05		/* Erase write */
#define TC_READMOD	0x06		/* Read modified */
#define TC_EWRITEA	0x0d		/* Erase write alternate */
@@ -76,7 +77,8 @@
#define TW_KR		0xc2		/* Keyboard restore */
#define TW_PLUSALARM	0x04		/* Add this bit for alarm */

#define RAW3270_MAXDEVS	256
#define RAW3270_FIRSTMINOR	1	/* First minor number */
#define RAW3270_MAXDEVS		255	/* Max number of 3270 devices */

/* For TUBGETMOD and TUBSETMOD. Should include. */
struct raw3270_iocb {
@@ -166,7 +168,10 @@ void raw3270_del_view(struct raw3270_view *);
void raw3270_deactivate_view(struct raw3270_view *);
struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int);
int raw3270_start(struct raw3270_view *, struct raw3270_request *);
int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
int raw3270_reset(struct raw3270_view *);
struct raw3270_view *raw3270_view(struct raw3270_view *);

/* Reference count inliner for view structures. */
static inline void
Loading