patch-2.2.14 linux/drivers/s390/char/hwc_tty.c

Next file: linux/drivers/s390/ebcdic.c
Previous file: linux/drivers/s390/char/hwc_rw.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.13/linux/drivers/s390/char/hwc_tty.c linux/drivers/s390/char/hwc_tty.c
@@ -0,0 +1,234 @@
+/*
+ *  drivers/s390/char/hwc_tty.c
+ *    HWC line mode terminal driver.
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Peschke <peschke@fh-brandenburg.de>
+ *
+ *  Thanks to Martin Schwidefsky.
+ */
+
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/uaccess.h>
+
+#include "hwc_rw.h"
+
+#define HWC_TTY_PRINT_HEADER "hwc tty driver: "
+#define HWC_TTY_BUF_SIZE 512
+
+typedef struct {
+	struct tty_struct *tty;
+	unsigned char buf[HWC_TTY_BUF_SIZE];
+	unsigned short int buf_count;
+	spinlock_t lock;
+} hwc_tty_data_struct;
+
+static hwc_tty_data_struct hwc_tty_data;
+static struct tty_driver hwc_tty_driver;
+static struct tty_struct * hwc_tty_table[1];
+static struct termios * hwc_tty_termios[1];
+static struct termios * hwc_tty_termios_locked[1];
+static int hwc_tty_refcount = 0;
+
+extern struct termios  tty_std_termios;
+
+static int hwc_tty_open(struct tty_struct *tty,
+                         struct file       *filp)
+{
+	if (MINOR(tty->device) - tty->driver.minor_start)
+		return -ENODEV;
+
+	tty->driver_data = &hwc_tty_data;
+	hwc_tty_data.buf_count = 0;
+	hwc_tty_data.tty = tty;
+	tty->low_latency = 0;
+
+	return 0;
+}
+
+void wake_up_hwc_tty(void)
+{
+	if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+			hwc_tty_data.tty->ldisc.write_wakeup)
+		(hwc_tty_data.tty->ldisc.write_wakeup)(hwc_tty_data.tty);
+	wake_up_interruptible(&hwc_tty_data.tty->write_wait);
+}
+
+static void hwc_tty_close(struct tty_struct *tty,
+                           struct file *filp)
+{
+	if (MINOR(tty->device) != tty->driver.minor_start) {
+		printk(KERN_WARNING HWC_TTY_PRINT_HEADER
+			"do not close hwc tty because of wrong device number");
+		return;
+	}
+
+	hwc_tty_data.tty = NULL;
+}
+
+static int hwc_tty_write_room (struct tty_struct *tty)
+{
+	int retval;
+
+	retval = hwc_write_room(IN_BUFS_TOTAL);
+	return retval;
+}
+
+static int hwc_tty_write(struct tty_struct   *tty,
+			  int                  from_user,
+	                  const unsigned char *buf,
+       		          int                  count)
+{
+	int retval;
+
+	if (hwc_tty_data.buf_count > 0)
+	{
+		hwc_write(0, hwc_tty_data.buf, hwc_tty_data.buf_count);
+		hwc_tty_data.buf_count = 0;
+	}
+	retval = hwc_write(from_user, buf, count);
+	return retval;
+}
+
+static void hwc_tty_put_char(struct tty_struct *tty,
+                              unsigned char ch)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwc_tty_data.lock, flags);
+	if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE)
+	{
+		hwc_write(0, hwc_tty_data.buf, hwc_tty_data.buf_count);
+		hwc_tty_data.buf_count = 0;
+	}
+	hwc_tty_data.buf[hwc_tty_data.buf_count] = ch;
+	hwc_tty_data.buf_count++;
+	spin_unlock_irqrestore(&hwc_tty_data.lock, flags);
+}
+
+static void hwc_tty_flush_chars(struct tty_struct *tty)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwc_tty_data.lock, flags);
+	hwc_write(0, hwc_tty_data.buf, hwc_tty_data.buf_count);
+	hwc_tty_data.buf_count = 0;
+	spin_unlock_irqrestore(&hwc_tty_data.lock, flags);
+}
+
+
+static int hwc_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	int retval;
+
+	retval = hwc_chars_in_buffer(IN_BUFS_TOTAL);
+	return retval;
+}
+
+static void hwc_tty_flush_buffer(struct tty_struct *tty)
+{
+	wake_up_hwc_tty();
+}
+
+static int hwc_tty_ioctl(
+	struct tty_struct *tty,
+	struct file * file,
+	unsigned int cmd,
+	unsigned long arg)
+{
+        if (tty->flags & (1 << TTY_IO_ERROR))
+                return -EIO;
+
+	return hwc_ioctl(cmd, arg);
+}
+
+void store_hwc_input(unsigned char* buf, unsigned int count)
+{
+	struct tty_struct *tty = hwc_tty_data.tty;
+
+	if (tty != NULL) {
+		if (count == 2 && strncmp(buf, "^c", 2) == 0) {
+			tty->flip.count++;
+			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+			*tty->flip.char_buf_ptr++ = INTR_CHAR(tty);
+		} else if (count == 2 && strncmp(buf, "^d", 2) == 0) {
+			tty->flip.count++;
+			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+			*tty->flip.char_buf_ptr++ = EOF_CHAR(tty);
+		} else if (count == 2 && strncmp(buf, "^z", 2) == 0) {
+			tty->flip.count++;
+			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+			*tty->flip.char_buf_ptr++ = SUSP_CHAR(tty);
+		} else {
+			memcpy(tty->flip.char_buf_ptr, buf, count);
+			if (count < 2 ||
+			    strncmp(buf + count - 2, "^n", 2)) {
+				tty->flip.char_buf_ptr[count] = '\n';
+				count++;
+			} else	count -= 2;
+			memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count);
+			tty->flip.char_buf_ptr += count;
+			tty->flip.flag_buf_ptr += count;
+			tty->flip.count += count;
+		}
+		tty_flip_buffer_push(tty);
+		wake_up_hwc_tty();
+	}
+}
+
+void hwc_tty_init(void)
+{
+	memset (&hwc_tty_driver, 0, sizeof(struct tty_driver));
+	hwc_tty_driver.magic = TTY_DRIVER_MAGIC;
+	hwc_tty_driver.driver_name = "tty_hwc";
+	hwc_tty_driver.name = "ttyS";
+	hwc_tty_driver.name_base = 0;
+	hwc_tty_driver.major = TTY_MAJOR;
+	hwc_tty_driver.minor_start = 64;
+	hwc_tty_driver.num = 1;
+	hwc_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
+	hwc_tty_driver.subtype = SYSTEM_TYPE_TTY;
+	hwc_tty_driver.init_termios = tty_std_termios;
+	hwc_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
+	hwc_tty_driver.init_termios.c_oflag = ONLCR;
+	hwc_tty_driver.init_termios.c_lflag = ISIG | ECHO;
+	hwc_tty_driver.flags = TTY_DRIVER_REAL_RAW;
+	hwc_tty_driver.refcount = &hwc_tty_refcount;
+	
+	hwc_tty_driver.table = hwc_tty_table;
+	hwc_tty_driver.termios = hwc_tty_termios;
+	hwc_tty_driver.termios_locked = hwc_tty_termios_locked;
+
+	hwc_tty_driver.open = hwc_tty_open;
+	hwc_tty_driver.close = NULL /* hwc_tty_close */;
+	hwc_tty_driver.write = hwc_tty_write;
+	hwc_tty_driver.put_char = hwc_tty_put_char;
+	hwc_tty_driver.flush_chars = hwc_tty_flush_chars;
+	hwc_tty_driver.write_room = hwc_tty_write_room;
+	hwc_tty_driver.chars_in_buffer = hwc_tty_chars_in_buffer;
+	hwc_tty_driver.flush_buffer = hwc_tty_flush_buffer;
+	hwc_tty_driver.ioctl = hwc_tty_ioctl;
+	
+	hwc_tty_driver.throttle = NULL;
+	hwc_tty_driver.unthrottle = NULL;
+	hwc_tty_driver.send_xchar = NULL;
+	hwc_tty_driver.set_termios = NULL;
+	hwc_tty_driver.set_ldisc = NULL;
+	hwc_tty_driver.stop = NULL; 
+	hwc_tty_driver.start = NULL; 
+	hwc_tty_driver.hangup = NULL;
+	hwc_tty_driver.break_ctl = NULL;
+	hwc_tty_driver.wait_until_sent = NULL;
+	hwc_tty_driver.read_proc = NULL;
+	hwc_tty_driver.write_proc = NULL;
+
+	if (tty_register_driver(&hwc_tty_driver))
+		panic("Couldn't register hwc_tty driver\n");
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)