mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
To: akpm@osdl.org, linux-kernel@vger.kernel.org
Subject: [PATCH] s390 (4/6): 3270 console driver.
Date: Thu, 13 May 2004 21:15:00 +0200	[thread overview]
Message-ID: <20040513191500.GE2916@mschwid3.boeblingen.de.ibm.com> (raw)

[PATCH] s390: 3270 driver.

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

3270 device driver change:
 - Don't allow activation of views while the initial size sensing is still
   in progress. Replace RAW3270_FLAGS_SHUTDOWN with RAW3270_FLAGS_READY.
 - Make 3270 views loadable as modules.

diffstat:
 arch/s390/defconfig         |    2 
 drivers/s390/Kconfig        |   25 ++++++--
 drivers/s390/char/Makefile  |    5 +
 drivers/s390/char/raw3270.c |  129 +++++++++++++++++++++++++++++++-------------
 drivers/s390/char/raw3270.h |    7 +-
 drivers/s390/char/tty3270.c |   37 +++++++++++-
 6 files changed, 153 insertions(+), 52 deletions(-)

diff -urN linux-2.6/arch/s390/defconfig linux-2.6-s390/arch/s390/defconfig
--- linux-2.6/arch/s390/defconfig	Thu May 13 21:00:59 2004
+++ linux-2.6-s390/arch/s390/defconfig	Thu May 13 21:01:02 2004
@@ -178,6 +178,8 @@
 # S/390 character device drivers
 #
 CONFIG_TN3270=y
+CONFIG_TN3270_TTY=y
+CONFIG_TN3270_FS=m
 CONFIG_TN3270_CONSOLE=y
 CONFIG_TN3215=y
 CONFIG_TN3215_CONSOLE=y
diff -urN linux-2.6/drivers/s390/Kconfig linux-2.6-s390/drivers/s390/Kconfig
--- linux-2.6/drivers/s390/Kconfig	Mon May 10 04:33:13 2004
+++ linux-2.6-s390/drivers/s390/Kconfig	Thu May 13 21:01:02 2004
@@ -54,17 +54,28 @@
 comment "S/390 character device drivers"
 
 config TN3270
-	tristate "Support for locally attached 3270 tubes"
+	tristate "Support for locally attached 3270 terminals"
 	help
-	  Include support for IBM 3270 line-mode terminals.
+	  Include support for IBM 3270 terminals.
+
+config TN3270_TTY
+	tristate "Support for tty input/output on 3270 terminals"
+	depends on TN3270
+	help
+	  Include support for using an IBM 3270 terminal as a Linux tty.
+
+config TN3270_FS
+	tristate "Support for fullscreen applications on 3270 terminals"
+	depends on TN3270
+	help
+	  Include support for fullscreen applications on an IBM 3270 terminal.
 
 config TN3270_CONSOLE
-	bool "Support for console on 3270 line mode terminal"
-	depends on TN3270=y
+	bool "Support for console on 3270 terminal"
+	depends on TN3270=y && TN3270_TTY=y
 	help
-	  Include support for using an IBM 3270 line-mode terminal as a Linux
-	  system console.  Available only if 3270 support is compiled in
-	  statically.
+	  Include support for using an IBM 3270 terminal as a Linux system
+	  console.  Available only if 3270 support is compiled in statically.
 
 config TN3215
 	bool "Support for 3215 line mode terminal"
diff -urN linux-2.6/drivers/s390/char/Makefile linux-2.6-s390/drivers/s390/char/Makefile
--- linux-2.6/drivers/s390/char/Makefile	Mon May 10 04:32:29 2004
+++ linux-2.6-s390/drivers/s390/char/Makefile	Thu May 13 21:01:02 2004
@@ -4,9 +4,10 @@
 
 obj-y += ctrlchar.o keyboard.o defkeymap.o
 
-tub3270-objs := raw3270.o tty3270.o fs3270.o
-obj-$(CONFIG_TN3270) += tub3270.o
+obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
+obj-$(CONFIG_TN3270_TTY) += tty3270.o
+obj-$(CONFIG_TN3270_FS) += fs3270.o
 
 obj-$(CONFIG_TN3215) += con3215.o
 
diff -urN linux-2.6/drivers/s390/char/raw3270.c linux-2.6-s390/drivers/s390/char/raw3270.c
--- linux-2.6/drivers/s390/char/raw3270.c	Mon May 10 04:33:13 2004
+++ linux-2.6-s390/drivers/s390/char/raw3270.c	Thu May 13 21:01:02 2004
@@ -47,11 +47,11 @@
 #define RAW3270_FLAGS_14BITADDR	0	/* 14-bit buffer addresses */
 #define RAW3270_FLAGS_BUSY	1	/* Device busy, leave it alone */
 #define RAW3270_FLAGS_ATTN	2	/* Device sent an ATTN interrupt */
-#define RAW3270_FLAGS_SHUTDOWN	4	/* Device is in offline processing */
+#define RAW3270_FLAGS_READY	4	/* Device is useable by views */
 #define RAW3270_FLAGS_CONSOLE	8	/* Device is the console. */
 
-/* Lock to protect global data of raw3270 (devices, views, etc). */
-static spinlock_t raw3270_lock = SPIN_LOCK_UNLOCKED;
+/* Semaphore to protect global data of raw3270 (devices, views, etc). */
+static DECLARE_MUTEX(raw3270_sem);
 
 /* List of 3270 devices. */
 static struct list_head raw3270_devices = LIST_HEAD_INIT(raw3270_devices);
@@ -308,7 +308,7 @@
 	rp = view->dev;
 	if (!rp || rp->view != view)
 		rc = -EACCES;
-	else if (test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags))
+	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
 		rc = -ENODEV;
 	else
 		rc =  __raw3270_start(rp, view, rq);
@@ -603,7 +603,6 @@
 {
 	static const unsigned char wbuf[] =
 		{ 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };
-	unsigned long flags;
 	struct raw3270_ua *uap;
 	unsigned short count;
 	int rc;
@@ -638,6 +637,8 @@
 	/* Wait for attention interrupt. */
 #ifdef CONFIG_TN3270_CONSOLE
 	if (raw3270_registered == 0) {
+		unsigned long flags;
+
 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
 		while (!test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags))
 			wait_cons_dev();
@@ -764,7 +765,7 @@
 	 * Add device to list and find the smallest unused minor
 	 * number for it.
 	 */
-	spin_lock(&raw3270_lock);
+	down(&raw3270_sem);
 	/* Keep the list sorted. */
 	minor = 0;
 	rp->minor = -1;
@@ -781,7 +782,7 @@
 		rp->minor = minor;
 		list_add_tail(&rp->list, &raw3270_devices);
 	}
-	spin_unlock(&raw3270_lock);
+	up(&raw3270_sem);
 	/* No free minor number? Then give up. */
 	if (rp->minor == -1)
 		return -EUSERS;
@@ -811,6 +812,7 @@
 	raw3270_reset_device(rp);
 	raw3270_size_device(rp);
 	raw3270_reset_device(rp);
+	set_bit(RAW3270_FLAGS_READY, &rp->flags);
 	return rp;
 }
 
@@ -872,7 +874,7 @@
 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
 	if (rp->view == view)
 		rc = 0;
-	else if (test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags))
+	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
 		rc = -ENODEV;
 	else {
 		oldview = 0;
@@ -921,7 +923,7 @@
 		list_del_init(&view->list);
 		list_add_tail(&view->list, &rp->view_list);
 		/* Try to activate another view. */
-		if (!test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags)) {
+		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
 			list_for_each_entry(view, &rp->view_list, list)
 				if (view->fn->activate(view) == 0) {
 					rp->view = view;
@@ -942,13 +944,13 @@
 	struct raw3270 *rp;
 	int rc;
 
-	spin_lock(&raw3270_lock);
+	down(&raw3270_sem);
 	rc = -ENODEV;
 	list_for_each_entry(rp, &raw3270_devices, list) {
 		if (rp->minor != minor)
 			continue;
 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
-		if (!test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags)) {
+		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
 			atomic_set(&view->ref_count, 2);
 			view->dev = rp;
 			view->fn = fn;
@@ -963,7 +965,7 @@
 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
 		break;
 	}
-	spin_unlock(&raw3270_lock);
+	up(&raw3270_sem);
 	return rc;
 }
 
@@ -977,25 +979,26 @@
 	struct raw3270_view *view, *tmp;
 	unsigned long flags;
 
-	spin_lock(&raw3270_lock);
+	down(&raw3270_sem);
 	view = ERR_PTR(-ENODEV);
 	list_for_each_entry(rp, &raw3270_devices, list) {
 		if (rp->minor != minor)
 			continue;
 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
-		if (!test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags)) {
+		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
+			view = ERR_PTR(-ENOENT);
 			list_for_each_entry(tmp, &rp->view_list, list) {
 				if (tmp->fn == fn) {
 					raw3270_get_view(tmp);
 					view = tmp;
+					break;
 				}
 			}
-		} else
-			view = ERR_PTR(-ENOENT);
+		}
 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
 		break;
 	}
-	spin_unlock(&raw3270_lock);
+	up(&raw3270_sem);
 	return view;
 }
 
@@ -1007,6 +1010,7 @@
 {
 	unsigned long flags;
 	struct raw3270 *rp;
+	struct raw3270_view *nv;
 
 	rp = view->dev;
 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
@@ -1015,17 +1019,18 @@
 		rp->view = 0;
 	}
 	list_del_init(&view->list);
-	if (!rp->view && !test_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags)) {
+	if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
 		/* Try to activate another view. */
-		list_for_each_entry(view, &rp->view_list, list)
-			if (view->fn->activate(view) == 0) {
-				rp->view = view;
+		list_for_each_entry(nv, &rp->view_list, list) {
+			if (nv->fn->activate(view) == 0) {
+				rp->view = nv;
 				break;
 			}
+		}
 	}
 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
 	/* Wait for reference counter to drop to zero. */
-	atomic_dec(&view->ref_count);
+	atomic_sub(2, &view->ref_count);
 	wait_event(raw3270_wait_queue, atomic_read(&view->ref_count) == 0);
 	if (view->fn->free)
 		view->fn->free(view);
@@ -1040,9 +1045,9 @@
 	struct ccw_device *cdev;
 
 	/* Remove from device chain. */
-	spin_lock(&raw3270_lock);
+	down(&raw3270_sem);
 	list_del_init(&rp->list);
-	spin_unlock(&raw3270_lock);
+	up(&raw3270_sem);
 
 	/* Disconnect from ccw_device. */
 	cdev = rp->cdev;
@@ -1109,8 +1114,48 @@
 	sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
 }
 
-/* Hackish. A notifier chain would be cleaner. */
-extern void tty3270_notifier(int index, int active);
+/*
+ * Notifier for device addition/removal
+ */
+struct raw3270_notifier {
+	struct list_head list;
+	void (*notifier)(int, int);
+};
+
+static struct list_head raw3270_notifier = LIST_HEAD_INIT(raw3270_notifier);
+
+int raw3270_register_notifier(void (*notifier)(int, int))
+{
+	struct raw3270_notifier *np;
+	struct raw3270 *rp;
+
+	np = kmalloc(sizeof(struct raw3270_notifier), GFP_KERNEL);
+	if (!np)
+		return -ENOMEM;
+	np->notifier = notifier;
+	down(&raw3270_sem);
+	list_add_tail(&np->list, &raw3270_notifier);
+	list_for_each_entry(rp, &raw3270_devices, list) {
+		get_device(&rp->cdev->dev);
+		notifier(rp->minor, 1);
+	}
+	up(&raw3270_sem);
+	return 0;
+}
+
+void raw3270_unregister_notifier(void (*notifier)(int, int))
+{
+	struct raw3270_notifier *np;
+
+	down(&raw3270_sem);
+	list_for_each_entry(np, &raw3270_notifier, list)
+		if (np->notifier == notifier) {
+			list_del(&np->list);
+			kfree(np);
+			break;
+		}
+	up(&raw3270_sem);
+}
 
 /*
  * Set 3270 device online.
@@ -1119,6 +1164,7 @@
 raw3270_set_online (struct ccw_device *cdev)
 {
 	struct raw3270 *rp;
+	struct raw3270_notifier *np;
 
 	rp = raw3270_create_device(cdev);
 	if (IS_ERR(rp))
@@ -1127,7 +1173,11 @@
 	raw3270_size_device(rp);
 	raw3270_reset_device(rp);
 	raw3270_create_attributes(rp);
-	tty3270_notifier(rp->minor, 1);
+	set_bit(RAW3270_FLAGS_READY, &rp->flags);
+	down(&raw3270_sem);
+	list_for_each_entry(np, &raw3270_notifier, list)
+		np->notifier(rp->minor, 1);
+	up(&raw3270_sem);
 	return 0;
 }
 
@@ -1140,9 +1190,10 @@
 	unsigned long flags;
 	struct raw3270 *rp;
 	struct raw3270_view *v;
+	struct raw3270_notifier *np;
 
 	rp = cdev->dev.driver_data;
-	set_bit(RAW3270_FLAGS_SHUTDOWN, &rp->flags);
+	clear_bit(RAW3270_FLAGS_READY, &rp->flags);
 
 	sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
 
@@ -1162,7 +1213,10 @@
 	}
 	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
 
-	tty3270_notifier(rp->minor, 0);
+	down(&raw3270_sem);
+	list_for_each_entry(np, &raw3270_notifier, list)
+		np->notifier(rp->minor, 0);
+	up(&raw3270_sem);
 
 	/* Reset 3270 device. */
 	raw3270_reset_device(rp);
@@ -1210,7 +1264,7 @@
 	.set_offline	= &raw3270_set_offline,
 };
 
-int
+static int
 raw3270_init(void)
 {
 	struct raw3270 *rp;
@@ -1222,18 +1276,17 @@
 	rc = ccw_driver_register(&raw3270_ccw_driver);
 	if (rc == 0) {
 		/* Create attributes for early (= console) device. */
-		spin_lock(&raw3270_lock);
+		down(&raw3270_sem);
 		list_for_each_entry(rp, &raw3270_devices, list) {
 			get_device(&rp->cdev->dev);
 			raw3270_create_attributes(rp);
-			tty3270_notifier(rp->minor, 1);
 		}
-		spin_unlock(&raw3270_lock);
+		up(&raw3270_sem);
 	}
 	return rc;
 }
 
-void
+static void
 raw3270_exit(void)
 {
 	ccw_driver_unregister(&raw3270_ccw_driver);
@@ -1241,8 +1294,9 @@
 
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(raw3270_init);
-EXPORT_SYMBOL(raw3270_exit);
+module_init(raw3270_init);
+module_exit(raw3270_exit);
+
 EXPORT_SYMBOL(raw3270_request_alloc);
 EXPORT_SYMBOL(raw3270_request_free);
 EXPORT_SYMBOL(raw3270_request_reset);
@@ -1258,3 +1312,6 @@
 EXPORT_SYMBOL(raw3270_deactivate_view);
 EXPORT_SYMBOL(raw3270_start);
 EXPORT_SYMBOL(raw3270_start_irq);
+EXPORT_SYMBOL(raw3270_register_notifier);
+EXPORT_SYMBOL(raw3270_unregister_notifier);
+EXPORT_SYMBOL(raw3270_wait_queue);
diff -urN linux-2.6/drivers/s390/char/raw3270.h linux-2.6-s390/drivers/s390/char/raw3270.h
--- linux-2.6/drivers/s390/char/raw3270.h	Mon May 10 04:32:52 2004
+++ linux-2.6-s390/drivers/s390/char/raw3270.h	Thu May 13 21:01:02 2004
@@ -78,9 +78,6 @@
 
 #define RAW3270_MAXDEVS	256
 
-int raw3270_init(void);
-void raw3270_exit(void);
-
 /* For TUBGETMOD and TUBSETMOD. Should include. */
 struct raw3270_iocb {
 	short model;
@@ -190,6 +187,10 @@
 struct raw3270 *raw3270_setup_console(struct ccw_device *cdev);
 void raw3270_wait_cons_dev(struct raw3270 *);
 
+/* Notifier for device addition/removal */
+int raw3270_register_notifier(void (*notifier)(int, int));
+void raw3270_unregister_notifier(void (*notifier)(int, int));
+
 /*
  * Little memory allocator for string objects. 
  */
diff -urN linux-2.6/drivers/s390/char/tty3270.c linux-2.6-s390/drivers/s390/char/tty3270.c
--- linux-2.6/drivers/s390/char/tty3270.c	Mon May 10 04:32:26 2004
+++ linux-2.6-s390/drivers/s390/char/tty3270.c	Thu May 13 21:01:02 2004
@@ -35,6 +35,7 @@
 #define TTY3270_STRING_PAGES 5
 
 struct tty_driver *tty3270_driver;
+static int tty3270_max_index;
 
 struct raw3270_fn tty3270_fn;
 
@@ -836,6 +837,22 @@
 	tty3270_free_view((struct tty3270 *) view);
 }
 
+/*
+ * Delayed freeing of tty3270 views.
+ */
+static void
+tty3270_del_views(void)
+{
+	struct tty3270 *tp;
+	int i;
+
+	for (i = 0; i < tty3270_max_index; i++) {
+		tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, i);
+		if (!IS_ERR(tp))
+			raw3270_del_view(&tp->view);
+	}
+}
+
 struct raw3270_fn tty3270_fn = {
 	.activate = tty3270_activate,
 	.deactivate = tty3270_deactivate,
@@ -867,6 +884,12 @@
 		tp->inattr = TF_INPUT;
 		return 0;
 	}
+	if (tty3270_max_index < tty->index + 1)
+		tty3270_max_index = tty->index + 1;
+
+	/* Quick exit if there is no device for tty->index. */
+	if (PTR_ERR(tp) == -ENODEV)
+		return -ENODEV;
 
 	/* Allocate tty3270 structure on first open. */
 	tp = tty3270_alloc_view();
@@ -1778,9 +1801,6 @@
 	struct tty_driver *driver;
 	int ret;
 
-	ret = raw3270_init();
-	if (ret)
-		return ret;
 	driver = alloc_tty_driver(256);
 	if (!driver)
 		return -ENOMEM;
@@ -1807,6 +1827,14 @@
 		return ret;
 	}
 	tty3270_driver = driver;
+	ret = raw3270_register_notifier(tty3270_notifier);
+	if (ret) {
+		printk(KERN_ERR "tty3270 notifier registration failed "
+		       "with %d\n", ret);
+		put_tty_driver(driver);
+		return ret;
+
+	}
 	return 0;
 }
 
@@ -1815,10 +1843,11 @@
 {
 	struct tty_driver *driver;
 
+	raw3270_unregister_notifier(tty3270_notifier);
 	driver = tty3270_driver;
 	tty3270_driver = 0;
 	tty_unregister_driver(driver);
-	raw3270_exit();
+	tty3270_del_views();
 }
 
 MODULE_LICENSE("GPL");

             reply	other threads:[~2004-05-13 19:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-13 19:15 Martin Schwidefsky [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-04-28 16:50 Martin Schwidefsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040513191500.GE2916@mschwid3.boeblingen.de.ibm.com \
    --to=schwidefsky@de.ibm.com \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®