patch-2.3.99-pre8 linux/drivers/s390/char/hwc_tty.c
Next file: linux/drivers/s390/misc/Makefile
Previous file: linux/drivers/s390/char/hwc_rw.h
Back to the patch index
Back to the overall index
- Lines: 266
- Date:
Fri May 12 11:41:44 2000
- Orig file:
v2.3.99-pre7/linux/drivers/s390/char/hwc_tty.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc_tty.c linux/drivers/s390/char/hwc_tty.c
@@ -0,0 +1,265 @@
+/*
+ * 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 <[email protected]>
+ *
+ * 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 == NULL)
+ return;
+ 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 && (
+ /* hat is 0xb0 in codepage 037 (US etc.) and thus */
+ /* converted to 0x5e in ascii ('^') */
+ strncmp (buf, "^c", 2) == 0 ||
+ /* hat is 0xb0 in several other codepages (German, */
+ /* UK, ...) and thus converted to ascii octal 252 */
+ strncmp (buf, "\0252c", 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 ||
+ strncmp (buf, "\0252d", 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 ||
+ strncmp (buf, "\0252z", 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) ||
+ strncmp (buf + count - 2, "\0252n", 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));
+ memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct));
+ 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, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])