]> Zhao Yanbai Git Server - minix.git/commitdiff
TTY: use libchardriver; clean up 67/867/3
authorDavid van Moolenbroek <david@minix3.org>
Wed, 11 Sep 2013 10:48:10 +0000 (12:48 +0200)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:52 +0000 (09:04 +0100)
- writing to a PTY master side blocks if there is not already a
  blocked reader on the slave side, and select now reflects this;
- internally, TTY now uses a test based on "caller != NONE" rather
  than "grant != GRANT_INVALID" to identify whether a call is
  currently ongoing;
- "offset" fields have been removed as they equal the corresponding
  "cum" fields;
- improved variable typing and function naming here and there;
- various other small fixes.

Change-Id: I6b51452888942e864b4e034e8c8490576184a23e

15 files changed:
distrib/sets/lists/minix/mi
drivers/tty/Makefile
drivers/tty/arch/earm/console.c
drivers/tty/arch/earm/keyboard.c
drivers/tty/arch/earm/rs232.c
drivers/tty/arch/i386/console.c
drivers/tty/arch/i386/keyboard.c
drivers/tty/arch/i386/rs232.c
drivers/tty/pty.c
drivers/tty/tty.c
drivers/tty/tty.h
include/minix/Makefile
include/minix/com.h
include/minix/tty.h [deleted file]
include/sys/ioc_tty.h

index 4f5a1493d00491340fc2221af1b8fc2680a5d1b2..ad6db8febbd999b010d3426c7be3745b3d61a7d7 100644 (file)
 ./usr/include/minix/sysutil.h          minix-sys
 ./usr/include/minix/termios.h          minix-sys
 ./usr/include/minix/timers.h           minix-sys
-./usr/include/minix/tty.h              minix-sys
+./usr/include/minix/tty.h              minix-sys       obsolete
 ./usr/include/minix/type.h             minix-sys
 ./usr/include/minix/types.h            minix-sys       obsolete
 ./usr/include/minix/u64.h              minix-sys
index 6f0336eac823a09e09cdfae1b51b0661d877d01d..5575a4ccf41ed231a4cf899e50e0ed32ef7567c6 100644 (file)
@@ -6,8 +6,8 @@ PROG=   tty
 
 SRCS +=        tty.c pty.c
 
-DPADD+=        ${LIBSYS} ${LIBTIMERS}
-LDADD+=        -lsys -ltimers
+DPADD+=        ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS}
+LDADD+=        -lchardriver -lsys -ltimers
 
 MAN=
 
index 3c820bceaea6b07a70b47016a906ca3f05b6ef87..04a5aff345bbe9e7bf9abb090847c200e01f30a2 100644 (file)
@@ -4,7 +4,7 @@
 #include "tty.h"
 
 void
-do_video(message *m)
+do_video(message *m, int ipc_status)
 {
 }
 
@@ -19,7 +19,7 @@ cons_stop(void)
 }
 
 int
-con_loadfont(message *m)
+con_loadfont(endpoint_t endpt, cp_grant_id_t grant)
 {
        return 0;
 }
index 7ab1ef158e9a4ac6e4df6ef04b93c50fcf43b0f9..cf278378bc6bd45ad56de2dd870bc759087d7faa 100644 (file)
@@ -19,12 +19,7 @@ do_kb_inject(message *m)
 }
 
 void
-do_kbd(message *m)
-{
-}
-
-void
-do_kbdaux(message *m)
+do_kbd(message *m, int ipc_status)
 {
 }
 
@@ -34,7 +29,7 @@ kb_init_once(void)
 }
 
 int
-kbd_loadmap(message *m)
+kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant)
 {
        return 0;
 }
index f8b40cefd386dd45fa1a5e3351bd954daddf7e0d..9d30c8e48c57cc9f44ab92ee380e4be59e3b17ed 100644 (file)
@@ -237,11 +237,11 @@ rs_write(register tty_t *tp, int try)
                if (tp->tty_outcaller == KERNEL) {
                        /* We're trying to print on kernel's behalf */
                        memcpy(rs->ohead,
-                               (void *) tp->tty_outgrant + tp->tty_outoffset,
+                               (char *) tp->tty_outgrant + tp->tty_outcum,
                                count);
                } else {
                        if ((r = sys_safecopyfrom(tp->tty_outcaller,
-                               tp->tty_outgrant, tp->tty_outoffset,
+                               tp->tty_outgrant, tp->tty_outcum,
                                (vir_bytes) rs->ohead, count)) != OK) {
                                return 0;
                        }
@@ -262,24 +262,21 @@ rs_write(register tty_t *tp, int try)
                rs_ostart(rs);
                if ((rs->ohead += ocount) >= bufend(rs->obuf))
                        rs->ohead -= buflen(rs->obuf);
-               tp->tty_outoffset += count;
                tp->tty_outcum += count;
                if ((tp->tty_outleft -= count) == 0) {
                        /* Output is finished, reply to the writer. */
-                       tty_reply(DEV_REVIVE, tp->tty_outcaller,
-                               tp->tty_outproc, tp->tty_outgrant,
+                       chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
                                tp->tty_outcum);
                        tp->tty_outcum = 0;
-                       tp->tty_outgrant = GRANT_INVALID;
+                       tp->tty_outcaller = NONE;
                }
 
        }
        if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
                /* Oops, the line has hung up. */
-               tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-                       tp->tty_outgrant, EIO);
+               chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
                tp->tty_outleft = tp->tty_outcum = 0;
-               tp->tty_outgrant = GRANT_INVALID;
+               tp->tty_outcaller = NONE;
        }
 
        return 1;
index 16652bf307442e334b96f5137126593c621ec58c..d8034190c05f282a920bdd0de6be9a118d5f1b38 100644 (file)
 
 #include <minix/drivers.h>
 #include <termios.h>
-#include <assert.h>
 #include <sys/ioctl.h>
 #include <sys/vm.h>
 #include <sys/video.h>
 #include <sys/mman.h>
-#include <minix/tty.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/sys_config.h>
-#include <minix/vm.h>
 #include "tty.h"
 
 /* Set this to 1 if you want console output duplicated on the first
@@ -142,6 +136,18 @@ static void vid_vid_copy(int src, int dst, int count);
 static void get_6845(int reg, unsigned *val);
 #endif
 
+static int video_open(devminor_t minor, int access, endpoint_t user_endpt);
+static int video_close(devminor_t minor);
+static int video_ioctl(devminor_t minor, unsigned long request,
+       endpoint_t endpt, cp_grant_id_t grant, int flags,
+       endpoint_t user_endpt, cdev_id_t id);
+
+static struct chardriver video_tab = {
+  .cdr_open    = video_open,
+  .cdr_close   = video_close,
+  .cdr_ioctl   = video_ioctl
+};
+
 /*===========================================================================*
  *                             cons_write                                   *
  *===========================================================================*/
@@ -174,16 +180,14 @@ int try;
        if (count > sizeof(buf)) count = sizeof(buf);
        if (tp->tty_outcaller == KERNEL) {
                /* We're trying to print on kernel's behalf */
-               memcpy(buf, (void *) tp->tty_outgrant + tp->tty_outoffset,
-                       count);
+               memcpy(buf, (char *) tp->tty_outgrant + tp->tty_outcum, count);
        } else {
                if ((result = sys_safecopyfrom(tp->tty_outcaller,
-                               tp->tty_outgrant, tp->tty_outoffset,
+                               tp->tty_outgrant, tp->tty_outcum,
                                (vir_bytes) buf, count)) != OK) {
                        break;
                }
        }
-       tp->tty_outoffset += count;
        tbuf = buf;
 
        /* Update terminal data structure. */
@@ -215,10 +219,10 @@ int try;
 
   /* Reply to the writer if all output is finished or if an error occured. */
   if (tp->tty_outleft == 0 || result != OK) {
-       tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-               tp->tty_outgrant, result != OK ? result : tp->tty_outcum);
+       chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
+               result != OK ? result : tp->tty_outcum);
        tp->tty_outcum = tp->tty_outleft = 0;
-       tp->tty_outgrant = GRANT_INVALID;
+       tp->tty_outcaller = NONE;
   }
 
   return 0;
@@ -807,83 +811,68 @@ static void beep()
   }
 }
 
-
 /*===========================================================================*
- *                             do_video                                     *
+ *                             video_open                                   *
  *===========================================================================*/
-void do_video(message *m)
+static int video_open(devminor_t minor, int UNUSED(access),
+       endpoint_t UNUSED(user_endpt))
 {
-       int r;
-
-       /* Execute the requested device driver function. */
-       r= EINVAL;      /* just in case */
-       switch (m->m_type) {
-           case DEV_OPEN:
-               /* Should grant IOPL */
-               disable_console();
-               tty_reply(DEV_OPEN_REPL, m->m_source, m->USER_ENDPT,
-                       (cp_grant_id_t) m->IO_GRANT, OK);
-               return;
-           case DEV_CLOSE:
-               reenable_console();
-               tty_reply(DEV_CLOSE_REPL, m->m_source, m->USER_ENDPT,
-                       (cp_grant_id_t) m->IO_GRANT, OK);
-               return;
-           case DEV_IOCTL_S:
-               switch(m->REQUEST) {
-                 case TIOCMAPMEM:
-                 case TIOCUNMAPMEM: {
-                       int r, do_map;
-                       struct mapreqvm mapreqvm;
-
-                       do_map= (m->REQUEST == TIOCMAPMEM);     /* else unmap */
-
-                       r = sys_safecopyfrom(m->m_source,
-                               (cp_grant_id_t) m->IO_GRANT, 0,
-                               (vir_bytes) &mapreqvm, sizeof(mapreqvm));
-
-                       if (r != OK)
-                       {
-                               printf("tty: sys_safecopyfrom failed\n");
-                               break;
-                       }
+  /* Should grant IOPL */
+  disable_console();
+  return OK;
+}
 
-                       /* In safe ioctl mode, the POSITION field contains
-                        * the endpt number of the original requestor.
-                        * USER_ENDPT is always FS.
-                        */
-
-                       if(do_map) {
-                               mapreqvm.vaddr_ret = vm_map_phys(m->POSITION,
-                               (void *) mapreqvm.phys_offset, mapreqvm.size);
-                               if((r = sys_safecopyto(m->m_source,
-                                 (cp_grant_id_t) m->IO_GRANT, 0,
-                                 (vir_bytes) &mapreqvm,
-                                 sizeof(mapreqvm))) != OK) {
-                                 printf("tty: sys_safecopyto failed\n");
-                               }
-                       } else {
-                               r = vm_unmap_phys(m->POSITION, 
-                                       mapreqvm.vaddr, mapreqvm.size);
-                       }
-                       break;
-                 }
-               default:
-                       r= ENOTTY;
-                       break;
-               }
-               break;
+/*===========================================================================*
+ *                             video_close                                  *
+ *===========================================================================*/
+static int video_close(devminor_t minor)
+{
+  reenable_console();
+  return OK;
+}
 
-           default:
-               printf(
-               "Warning, TTY(video) got unexpected request %d from %d\n",
-                       m->m_type, m->m_source);
-               r= EINVAL;
+/*===========================================================================*
+ *                             video_ioctl                                  *
+ *===========================================================================*/
+static int video_ioctl(devminor_t minor, unsigned long request,
+       endpoint_t endpt, cp_grant_id_t grant, int flags,
+       endpoint_t user_endpt, cdev_id_t id)
+{
+  struct mapreqvm mapreqvm;
+  int r, do_map;
+
+  switch (request) {
+  case TIOCMAPMEM:
+  case TIOCUNMAPMEM:
+       do_map = (request == TIOCMAPMEM);       /* else unmap */
+
+       if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &mapreqvm,
+               sizeof(mapreqvm))) != OK)
+               return r;
+
+       if (do_map) {
+               mapreqvm.vaddr_ret = vm_map_phys(user_endpt,
+                       (void *) mapreqvm.phys_offset, mapreqvm.size);
+               r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &mapreqvm,
+                       sizeof(mapreqvm));
+       } else {
+               r = vm_unmap_phys(user_endpt, mapreqvm.vaddr, mapreqvm.size);
        }
-       tty_reply(DEV_REVIVE, m->m_source, m->USER_ENDPT,
-               (cp_grant_id_t) m->IO_GRANT, r);
+
+       return r;
+
+  default:
+       return ENOTTY;
+  }
 }
 
+/*===========================================================================*
+ *                             do_video                                     *
+ *===========================================================================*/
+void do_video(message *m, int ipc_status)
+{
+  chardriver_process(&video_tab, m, ipc_status);
+}
 
 /*===========================================================================*
  *                             beep_x                                       *
@@ -1137,12 +1126,11 @@ void select_console(int cons_line)
 /*===========================================================================*
  *                             con_loadfont                                 *
  *===========================================================================*/
-int con_loadfont(m)
-message *m;
+int con_loadfont(endpoint_t endpt, cp_grant_id_t grant)
 {
   
 /* Load a font into the EGA or VGA adapter. */
-  int result;
+  int r, r2;
   static struct sequence seq1[7] = {
        { GA_SEQUENCER_INDEX, 0x00, 0x01 },
        { GA_SEQUENCER_INDEX, 0x02, 0x04 },
@@ -1164,17 +1152,14 @@ message *m;
 
   seq2[6].value= color ? 0x0E : 0x0A;
 
-  result = ga_program(seq1);   /* bring font memory into view */
+  r = ga_program(seq1);                /* bring font memory into view */
+  if (r != OK) return r;
 
-  if(sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0,
-       (vir_bytes) font_memory, GA_FONT_SIZE) != OK) {
-       printf("tty: copying from %d failed\n", m->m_source);
-       return EFAULT;
-  }
+  r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) font_memory, GA_FONT_SIZE);
 
-  result = ga_program(seq2);   /* restore */
+  r2 = ga_program(seq2);       /* restore */
 
-  return(result);
+  return(r != OK ? r : r2);
 }
 
 /*===========================================================================*
index 6a737fa3497e67f400e5140ba2e7645f7b214a6c..3b601da3366172d55c03db4d264af6a0ad95eca8 100644 (file)
@@ -123,19 +123,17 @@ static obs_t sfkey_obs[12];       /* observers for SHIFT F1-F12 */
 
 static struct kbd
 {
-       int minor;
+       devminor_t minor;
        int nr_open;
        char buf[KBD_BUFSZ];
        int offset;
        int avail;
-       int req_size;
-       int req_proc;
+       size_t req_size;
+       cdev_id_t req_id;
        cp_grant_id_t req_grant;
-       vir_bytes req_addr_offset;
-       int incaller;
-       int select_ops;
-       int select_proc;
-       int select_minor; /* sanity check only, can be removed */
+       endpoint_t req_caller;
+       unsigned int select_ops;
+       endpoint_t select_proc;
 } kbd, kbdaux;
 
 /* Data that is to be sent to the keyboard. Each byte is ACKed by the
@@ -155,7 +153,6 @@ static long sticky_alt_mode = 0;
 static long debug_fkeys = 1;
 static timer_t tmr_kbd_wd;
 
-static void handle_req(struct kbd *kbdp, message *m);
 static void kbc_cmd0(int cmd);
 static void kbc_cmd1(int cmd, int data);
 static int kbc_read(void);
@@ -171,220 +168,284 @@ static int kb_read(struct tty *tp, int try);
 static unsigned map_key(int scode);
 static void kbd_watchdog(timer_t *tmrp);
 
-int micro_delay(u32_t usecs)
+static int kbd_open(devminor_t minor, int access, endpoint_t user_endpt);
+static int kbd_close(devminor_t minor);
+static ssize_t kbd_read(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static ssize_t kbd_write(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static int kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
+static int kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
+
+static struct chardriver kbd_tab = {
+       .cdr_open       = kbd_open,
+       .cdr_close      = kbd_close,
+       .cdr_read       = kbd_read,
+       .cdr_write      = kbd_write,
+       .cdr_ioctl      = kbd_ioctl,
+       .cdr_cancel     = kbd_cancel,
+       .cdr_select     = kbd_select
+};
+
+/*===========================================================================*
+ *                             line2kbd                                     *
+ *===========================================================================*/
+static struct kbd *
+line2kbd(devminor_t minor)
 {
-       /* TTY can't use the library micro_delay() as that calls PM. */
-       tickdelay(micros_to_ticks(usecs));
-       return OK;
+       switch (minor) {
+       case KBD_MINOR:         return &kbd;
+       case KBDAUX_MINOR:      return &kbdaux;
+       default:                return NULL;
+       }
 }
 
 /*===========================================================================*
- *                             do_kbd                                       *
+ *                             kbd_open                                     *
  *===========================================================================*/
-void do_kbd(message *m)
+static int
+kbd_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt))
 {
-       handle_req(&kbd, m);
-}
+       struct kbd *kbdp;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
 
+       kbdp->nr_open++;
+       return OK;
+}
 
 /*===========================================================================*
- *                             do_kbdaux                                    *
+ *                             kbd_close                                    *
  *===========================================================================*/
-void do_kbdaux(message *m)
+static int
+kbd_close(devminor_t minor)
 {
-       handle_req(&kbdaux, m);
+       struct kbd *kbdp;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+
+       kbdp->nr_open--;
+       if (kbdp->nr_open < 0) {
+               printf("TTY(kbd): open count is negative\n");
+               kbdp->nr_open= 0;
+       }
+       if (kbdp->nr_open == 0)
+               kbdp->avail= 0;
+
+       return OK;
 }
 
+/*===========================================================================*
+ *                             kbd_read                                     *
+ *===========================================================================*/
+static ssize_t
+kbd_read(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
+{
+       ssize_t n, r;
+       struct kbd *kbdp;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+
+       /* We handle only one request at a time. */
+       if (kbdp->req_size)
+               return EIO;
+
+       if ((ssize_t) size <= 0)
+               return EINVAL;
+
+       /* If no data is available, suspend the caller. */
+       if (kbdp->avail == 0) {
+               if (flags & FLG_OP_NONBLOCK)
+                       return EAGAIN;
+               kbdp->req_size = size;
+               kbdp->req_id = id;
+               kbdp->req_grant = grant;
+               kbdp->req_caller = endpt;
+               return EDONTREPLY;
+       }
+
+       /* Handle read request. */
+       n = kbdp->avail;
+       if (n > (ssize_t) size)
+               n = size;
+       if (kbdp->offset + n > KBD_BUFSZ)
+               n = KBD_BUFSZ - kbdp->offset;
+       if (n <= 0)
+               panic("do_kbd(READ): bad n: %d", n);
+       r = sys_safecopyto(endpt, grant, 0,
+           (vir_bytes) &kbdp->buf[kbdp->offset], n);
+       if (r == OK) {
+               kbdp->offset = (kbdp->offset + n) % KBD_BUFSZ;
+               kbdp->avail -= n;
+               r = n;
+       } else
+               printf("TTY(kbd): copy in read kbd failed: %d\n", r);
+
+       return r;
+}
 
 /*===========================================================================*
- *                             handle_req                                   *
+ *                             kbd_write                                    *
  *===========================================================================*/
-static void handle_req(kbdp, m)
-struct kbd *kbdp;
-message *m;
+static ssize_t
+kbd_write(devminor_t minor, u64_t UNUSED(position), endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
 {
-       int i, n, r, ops, watch;
+       struct kbd *kbdp;
        unsigned char c;
+       size_t i;
+       int r;
 
-       /* Execute the requested device driver function. */
-       r= EINVAL;      /* just in case */
-       switch (m->m_type) {
-           case DEV_OPEN:
-               kbdp->nr_open++;
-               tty_reply(DEV_OPEN_REPL, m->m_source, m->USER_ENDPT,
-                       (cp_grant_id_t) m->IO_GRANT, OK);
-               return;
-           case DEV_CLOSE:
-               kbdp->nr_open--;
-               if (kbdp->nr_open < 0)
-               {
-                       printf("TTY(kbd): open count is negative\n");
-                       kbdp->nr_open= 0;
-               }
-               if (kbdp->nr_open == 0)
-                       kbdp->avail= 0;
-               tty_reply(DEV_CLOSE_REPL, m->m_source, m->USER_ENDPT,
-                       (cp_grant_id_t) m->IO_GRANT, OK);
-               return;
-           case DEV_READ_S:
-               if (kbdp->req_size)
-               {
-                       /* We handle only request at a time */
-                       r= EIO;
-                       break;
-               }
-               if (kbdp->avail == 0)
-               {
-                       if (m->FLAGS & FLG_OP_NONBLOCK) {
-                               r = EAGAIN;
-                               break;
-                       }
-                       /* Should record proc */
-                       kbdp->req_size= m->COUNT;
-                       kbdp->req_proc= m->USER_ENDPT;
-                       kbdp->req_grant= (cp_grant_id_t) m->IO_GRANT;
-                       kbdp->req_addr_offset= 0;
-                       kbdp->incaller= m->m_source;
-                       return;
-               }
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+       if (kbdp != &kbdaux) {
+               printf("TTY(kbd): write to keyboard not implemented\n");
+               return EINVAL;
+       }
 
-               /* Handle read request */
-               n= kbdp->avail;
-               if (n > m->COUNT)
-                       n= m->COUNT;
-               if (kbdp->offset + n > KBD_BUFSZ)
-                       n= KBD_BUFSZ-kbdp->offset;
-               if (n <= 0)
-                       panic("do_kbd(READ): bad n: %d", n);
-               r= sys_safecopyto(m->m_source, (cp_grant_id_t) m->IO_GRANT, 0, 
-                       (vir_bytes) &kbdp->buf[kbdp->offset], n);
-               if (r == OK)
-               {
-                       kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
-                       kbdp->avail -= n;
-                       r= n;
+       /*
+        * Assume that output to AUX only happens during initialization and we
+        * can afford to lose input. This should be fixed at a later time.
+        */
+       for (i = 0; i < size; i++) {
+               r = sys_safecopyfrom(endpt, grant, i, (vir_bytes) &c, 1);
+               if (r != OK)
+                       return i ? i : r;
+               kbc_cmd1(KBC_WRITE_AUX, c);
+       }
+
+       return r;
+}
+
+/*===========================================================================*
+ *                             kbd_ioctl                                    *
+ *===========================================================================*/
+static int
+kbd_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t UNUSED(user_endpt),
+       cdev_id_t id)
+{
+       struct kbd *kbdp;
+       kio_leds_t leds;
+       kio_bell_t bell;
+       clock_t ticks;
+       unsigned char b;
+       int r;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+       if (kbdp != &kbd)
+               return ENOTTY;  /* we only support ioctls on keyboards now */
+
+       switch (request) {
+       case KIOCSLEDS:
+               r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &leds,
+                   sizeof(leds));
+               if (r != OK)
+                       return r;
+
+               b = 0;
+               if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
+               if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
+               if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
+               if (kbdout.avail == 0)
+                       kbdout.offset = 0;
+               if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ) {
+                       /* Output buffer is full. Ignore this command.
+                        * Reset ACK flag.
+                        */
+                       kbdout.expect_ack = 0;
                } else {
-                       printf("copy in read kbd failed: %d\n", r);
+                       kbdout.buf[kbdout.offset+kbdout.avail] = LED_CODE;
+                       kbdout.buf[kbdout.offset+kbdout.avail+1] = b;
+                       kbdout.avail += 2;
                }
+               if (!kbdout.expect_ack)
+                       kbd_send();
 
-               break;
+               return OK;
 
-           case DEV_WRITE_S:
-               if (kbdp != &kbdaux)
-               {
-                       printf("write to keyboard not implemented\n");
-                       r= EINVAL;
-                       break;
-               }
+       case KIOCBELL:
+               r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &bell,
+                   sizeof(bell));
+               if (r != OK)
+                       return r;
 
-               /* Assume that output to AUX only happens during
-                * initialization and we can afford to lose input. This should
-                * be fixed at a later time.
-                */
-               for (i= 0; i<m->COUNT; i++)
-               {
-                       r= sys_safecopyfrom(m->m_source, (cp_grant_id_t)
-                               m->IO_GRANT, i, (vir_bytes) &c, 1);
-                       if (r != OK)
-                               break;
-                       kbc_cmd1(KBC_WRITE_AUX, c);
-               }
-               r= i;
-               break;
+               ticks = bell.kb_duration.tv_usec * system_hz / 1000000;
+               ticks += bell.kb_duration.tv_sec * system_hz;
+               if (!ticks)
+                       ticks++;
+               beep_x(bell.kb_pitch, ticks);
 
-           case CANCEL:
-               kbdp->req_size= 0;
-               r= EAGAIN;
-               break;
-           case DEV_SELECT:
-               ops = m->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR);
-               watch = (m->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0;
-               
-               r= 0;
-               if (kbdp->avail && (ops & SEL_RD))
-               {
-                       r |= SEL_RD;
-                       break;
-               }
+               return OK;
 
-               if (ops && watch)
-               {
-                       kbdp->select_ops |= ops;
-                       kbdp->select_proc= m->m_source;
-                       kbdp->select_minor= m->DEV_MINOR;
-               }
-               assert(kbdp->minor == m->DEV_MINOR);
-               select_reply(DEV_SEL_REPL1, m->m_source, m->DEV_MINOR, r);
-               return;
-           case DEV_IOCTL_S:
-               if (kbdp == &kbd && m->REQUEST == KIOCSLEDS)
-               {
-                       kio_leds_t leds;
-                       unsigned char b;
-
-                       
-                       r= sys_safecopyfrom(m->m_source, (cp_grant_id_t)
-                               m->IO_GRANT, 0, (vir_bytes) &leds,
-                               sizeof(leds));
-                       if (r != OK)
-                               break;
-                       b= 0;
-                       if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
-                       if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
-                       if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
-                       if (kbdout.avail == 0)
-                               kbdout.offset= 0;
-                       if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ)
-                       {
-                               /* Output buffer is full. Ignore this command.
-                                * Reset ACK flag.
-                                */
-                               kbdout.expect_ack= 0;
-                       }
-                       else
-                       {
-                               kbdout.buf[kbdout.offset+kbdout.avail]=
-                                       LED_CODE;
-                               kbdout.buf[kbdout.offset+kbdout.avail+1]= b;
-                               kbdout.avail += 2;
-                        }
-                        if (!kbdout.expect_ack)
-                               kbd_send();
-                        r= OK;
-                        break;
-               }
-               if (kbdp == &kbd && m->REQUEST == KIOCBELL)
-               {
-                       kio_bell_t bell;
-                       clock_t ticks;
-
-                       r = sys_safecopyfrom(m->m_source, (cp_grant_id_t)
-                               m->IO_GRANT, 0, (vir_bytes) &bell,
-                               sizeof(bell));
-                       if (r != OK)
-                               break;
-
-                       ticks= bell.kb_duration.tv_usec * system_hz / 1000000;
-                       ticks += bell.kb_duration.tv_sec * system_hz;
-                       if (!ticks)
-                               ticks++;
-                       beep_x(bell.kb_pitch, ticks);
-
-                       r= OK;
-                       break;
-               }
-               r= ENOTTY;
-               break;
+       default:
+               return ENOTTY;
+       }
+}
+
+/*===========================================================================*
+ *                             kbd_cancel                                   *
+ *===========================================================================*/
+static int
+kbd_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
+{
+       struct kbd *kbdp;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+
+       if (kbdp->req_size > 0 && endpt == kbdp->req_caller &&
+           id == kbdp->req_id)
+               return EINTR;
+
+       return EDONTREPLY;
+}
+
+/*===========================================================================*
+ *                             kbd_select                                   *
+ *===========================================================================*/
+static int
+kbd_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
+{
+       struct kbd *kbdp;
+       int watch, ready_ops;
+
+       if ((kbdp = line2kbd(minor)) == NULL)
+               return ENXIO;
+
+       watch = (ops & SEL_NOTIFY);
+       ops &= (SEL_RD | SEL_WR | SEL_ERR);
+
+       ready_ops = 0;
+       if (kbdp->avail && (ops & SEL_RD))
+               ready_ops |= SEL_RD;
+       if (ops & SEL_WR)
+               ready_ops |= SEL_WR;    /* writes never block */
 
-           default:            
-               printf("Warning, TTY(kbd) got unexpected request %d from %d\n",
-                       m->m_type, m->m_source);
-               r= EINVAL;
+       ops &= ~ready_ops;
+       if (ops && watch) {
+               kbdp->select_ops |= ops;
+               kbdp->select_proc = endpt;
        }
-       tty_reply(DEV_REVIVE, m->m_source, m->USER_ENDPT,
-               (cp_grant_id_t) m->IO_GRANT, r);
+
+       return ready_ops;
 }
 
+/*===========================================================================*
+ *                             do_kbd                                       *
+ *===========================================================================*/
+void
+do_kbd(message *m, int ipc_status)
+{
+       chardriver_process(&kbd_tab, m, ipc_status);
+}
 
 /*===========================================================================*
  *                             map_key                                      *
@@ -469,7 +530,7 @@ void kbd_interrupt(message *UNUSED(m_ptr))
                if (n <= 0)
                        panic("kbd_interrupt: bad n: %d", n);
                kbdp->req_size= 0;
-               r= sys_safecopyto(kbdp->incaller, kbdp->req_grant, 0,
+               r= sys_safecopyto(kbdp->req_caller, kbdp->req_grant, 0,
                        (vir_bytes)&kbdp->buf[kbdp->offset], n);
                if (r == OK)
                {
@@ -478,14 +539,12 @@ void kbd_interrupt(message *UNUSED(m_ptr))
                        r= n;
                } else printf("copy in revive kbd failed: %d\n", r);
 
-               tty_reply(DEV_REVIVE, kbdp->incaller, kbdp->req_proc,
-                       kbdp->req_grant, r);
-               kbdp->req_grant = GRANT_INVALID;
+               chardriver_reply_task(kbdp->req_caller, kbdp->req_id, r);
+               kbdp->req_caller = NONE;
        }
        /* Only satisfy pending select if characters weren't just read. */
        if (kbdp->avail && (kbdp->select_ops & SEL_RD)) {
-               assert(kbdp->select_minor == kbdp->minor);
-               select_reply(DEV_SEL_REPL2, kbdp->select_proc, kbdp->minor,
+               chardriver_reply_select(kbdp->select_proc, kbdp->minor,
                        SEL_RD);
                kbdp->select_ops &= ~SEL_RD;
        }
@@ -1024,12 +1083,10 @@ void kb_init_once(void)
 /*===========================================================================*
  *                             kbd_loadmap                                  *
  *===========================================================================*/
-int kbd_loadmap(m)
-message *m;
+int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant)
 {
 /* Load a new keymap. */
-  return sys_safecopyfrom(m->m_source, (cp_grant_id_t) m->IO_GRANT,
-       0, (vir_bytes) keymap, (vir_bytes) sizeof(keymap));
+  return sys_safecopyfrom(endpt, grant, 0, (vir_bytes) keymap, sizeof(keymap));
 }
 
 /*===========================================================================*
index 21821627db8b8a532a42be95ba8146a614dbcee5..9fe52d2ab74cdee7ceb4d0e61632b4a8e1796037 100644 (file)
@@ -246,10 +246,11 @@ static int rs_write(register tty_t *tp, int try)
        /* Copy from user space to the RS232 output buffer. */
        if (tp->tty_outcaller == KERNEL) {
                /* We're trying to print on kernel's behalf */
-               memcpy(rs->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset, count);
+               memcpy(rs->ohead, (char *) tp->tty_outgrant + tp->tty_outcum,
+                       count);
        } else {
                if ((r = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant,
-                       tp->tty_outoffset, (vir_bytes) rs->ohead, count)) != OK)
+                       tp->tty_outcum, (vir_bytes) rs->ohead, count)) != OK)
                                printf("TTY: sys_safecopyfrom() failed: %d", r);
        }
 
@@ -265,22 +266,20 @@ static int rs_write(register tty_t *tp, int try)
        rs_ostart(rs);
        if ((rs->ohead += ocount) >= bufend(rs->obuf))
                rs->ohead -= buflen(rs->obuf);
-       tp->tty_outoffset += count;
        tp->tty_outcum += count;
        if ((tp->tty_outleft -= count) == 0) {
                /* Output is finished, reply to the writer. */
-               tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-                       tp->tty_outgrant, tp->tty_outcum);
+               chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
+                       tp->tty_outcum);
                tp->tty_outcum = 0;
-               tp->tty_outgrant = GRANT_INVALID;
+               tp->tty_outcaller = NONE;
        }
   }
   if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
        /* Oops, the line has hung up. */
-       tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-               tp->tty_outgrant, EIO);
+       chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
        tp->tty_outleft = tp->tty_outcum = 0;
-       tp->tty_outgrant = GRANT_INVALID;
+       tp->tty_outcaller = NONE;
   }
 
   return 1;
index 8b6bc30ef9a6c742212fb7b99b74e484c67440e5..f59de63747f747f9fecac1ab4310d2469417decc 100644 (file)
@@ -9,20 +9,16 @@
  * This file takes care of copying data between the tty/pty device pairs and
  * the open/read/write/close calls on the pty devices.  The TTY task takes
  * care of the input and output processing (interrupt, backspace, raw I/O,
- * etc.) using the pty_read() and pty_write() functions as the "keyboard" and
- * "screen" functions of the ttypX devices.
+ * etc.) using the pty_slave_read() and pty_slave_write() functions as the
+ * "keyboard" and "screen" functions of the ttypX devices.
  * Be careful when reading this code, the terms "reading" and "writing" are
- * used both for the tty and the pty end of the pseudo tty.  Writes to one
- * end are to be read at the other end and vice-versa.
+ * used both for the tty (slave) and the pty (master) end of the pseudo tty.
+ * Writes to one end are to be read at the other end and vice-versa.
  */
 
 #include <minix/drivers.h>
-#include <assert.h>
 #include <termios.h>
 #include <signal.h>
-#include <minix/com.h>
-#include <minix/callnr.h>
-#include <sys/select.h>
 #include "tty.h"
 
 #if NR_PTYS > 0
@@ -32,21 +28,19 @@ typedef struct pty {
   tty_t                *tty;           /* associated TTY structure */
   char         state;          /* flags: busy, closed, ... */
 
-  /* Read call on /dev/ptypX. */
-  int          rdcaller;       /* process making the call (usually FS) */
-  int          rdproc;         /* process that wants to read from the pty */
-  cp_grant_id_t        rdgrant;        /* grant for readers address space */
-  vir_bytes    rdoffset;       /* offset in above grant */
-  int          rdleft;         /* # bytes yet to be read */
-  int          rdcum;          /* # bytes written so far */
-
-  /* Write call to /dev/ptypX. */
-  int          wrcaller;       /* process making the call (usually FS) */
-  int          wrproc;         /* process that wants to write to the pty */
-  cp_grant_id_t        wrgrant;        /* grant for writers address space */
-  vir_bytes    wroffset;       /* offset in above grant */
-  int          wrleft;         /* # bytes yet to be written */
-  int          wrcum;          /* # bytes written so far */
+  /* Read call on master (/dev/ptypX). */
+  endpoint_t   rdcaller;       /* process making the call, or NONE if none */
+  cdev_id_t    rdid;           /* ID of suspended read request */
+  cp_grant_id_t        rdgrant;        /* grant for reader's address space */
+  size_t       rdleft;         /* # bytes yet to be read */
+  size_t       rdcum;          /* # bytes written so far */
+
+  /* Write call to master (/dev/ptypX). */
+  endpoint_t   wrcaller;       /* process making the call, or NONE if none*/
+  cdev_id_t    wrid;           /* ID of suspended write request */
+  cp_grant_id_t        wrgrant;        /* grant for writer's address space */
+  size_t       wrleft;         /* # bytes yet to be written */
+  size_t       wrcum;          /* # bytes written so far */
 
   /* Output buffer. */
   int          ocount;         /* # characters in the buffer */
@@ -54,9 +48,8 @@ typedef struct pty {
   char         obuf[2048];     /* buffer for bytes going to the pty reader */
 
   /* select() data. */
-  int          select_ops;     /* Which operations do we want to know about? */
-  int          select_proc;    /* Who wants to know about it? */
-  dev_t                select_minor;   /* sanity check only, can be removed */
+  unsigned int select_ops;     /* Which operations do we want to know about? */
+  endpoint_t   select_proc;    /* Who wants to know about it? */
 } pty_t;
 
 #define TTY_ACTIVE     0x01    /* tty is open/active */
@@ -66,159 +59,288 @@ typedef struct pty {
 
 static pty_t pty_table[NR_PTYS];       /* PTY bookkeeping */
 
-static int pty_write(tty_t *tp, int try);
-static void pty_echo(tty_t *tp, int c);
 static void pty_start(pty_t *pp);
 static void pty_finish(pty_t *pp);
-static int pty_read(tty_t *tp, int try);
-static int pty_close(tty_t *tp, int try);
-static int pty_icancel(tty_t *tp, int try);
-static int pty_ocancel(tty_t *tp, int try);
-static void pty_select(tty_t *tp, message *m);
+
+static int pty_master_open(devminor_t minor, int access,
+       endpoint_t user_endpt);
+static int pty_master_close(devminor_t minor);
+static ssize_t pty_master_read(devminor_t minor, u64_t position,
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id);
+static ssize_t pty_master_write(devminor_t minor, u64_t position,
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id);
+static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int pty_master_select(devminor_t minor, unsigned int ops,
+       endpoint_t endpt);
+
+static struct chardriver pty_master_tab = {
+  .cdr_open    = pty_master_open,
+  .cdr_close   = pty_master_close,
+  .cdr_read    = pty_master_read,
+  .cdr_write   = pty_master_write,
+  .cdr_cancel  = pty_master_cancel,
+  .cdr_select  = pty_master_select
+};
 
 /*===========================================================================*
- *                             do_pty                                       *
+ *                             pty_master_open                              *
  *===========================================================================*/
-void do_pty(tty_t *tp, message *m_ptr)
+static int pty_master_open(devminor_t minor, int UNUSED(access),
+       endpoint_t UNUSED(user_endpt))
 {
-/* Perform an open/close/read/write call on a /dev/ptypX device. */
-  pty_t *pp = tp->tty_priv;
+  tty_t *tp;
+  pty_t *pp;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
+
+  if (pp->state & PTY_ACTIVE)
+       return EIO;
+
+  pp->state |= PTY_ACTIVE;
+  pp->rdcum = 0;
+  pp->wrcum = 0;
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                             pty_master_close                             *
+ *===========================================================================*/
+static int pty_master_close(devminor_t minor)
+{
+  tty_t *tp;
+  pty_t *pp;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
+
+  if ((pp->state & (TTY_ACTIVE | TTY_CLOSED)) != TTY_ACTIVE) {
+       pp->state = 0;
+  } else {
+       pp->state |= PTY_CLOSED;
+       sigchar(tp, SIGHUP, 1);
+  }
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                             pty_master_read                              *
+ *===========================================================================*/
+static ssize_t pty_master_read(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
+{
+  tty_t *tp;
+  pty_t *pp;
+  ssize_t r;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
+
+  /* Check, store information on the reader, do I/O. */
+  if (pp->state & TTY_CLOSED)
+       return 0; /* EOF */
+
+  if (pp->rdcaller != NONE || pp->rdleft != 0 || pp->rdcum != 0)
+       return EIO;
+
+  if (size <= 0)
+       return EINVAL;
+
+  pp->rdcaller = endpt;
+  pp->rdid = id;
+  pp->rdgrant = grant;
+  pp->rdleft = size;
+  pty_start(pp);
+
+  handle_events(tp);
+
+  if (pp->rdleft == 0) {
+       pp->rdcaller = NONE;
+       return EDONTREPLY;              /* already done */
+  }
+
+  if (flags & FLG_OP_NONBLOCK) {
+       r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
+       pp->rdleft = pp->rdcum = 0;
+       pp->rdcaller = NONE;
+       return r;
+  }
+
+  return EDONTREPLY;                   /* do suspend */
+}
+
+/*===========================================================================*
+ *                             pty_master_write                             *
+ *===========================================================================*/
+static ssize_t pty_master_write(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
+{
+  tty_t *tp;
+  pty_t *pp;
+  ssize_t r;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
+
+  /* Check, store information on the writer, do I/O. */
+  if (pp->state & TTY_CLOSED)
+       return EIO;
+
+  if (pp->wrcaller != NONE || pp->wrleft != 0 || pp->wrcum != 0)
+       return EIO;
+
+  if (size <= 0)
+       return EINVAL;
+
+  pp->wrcaller = endpt;
+  pp->wrid = id;
+  pp->wrgrant = grant;
+  pp->wrleft = size;
+
+  handle_events(tp);
+
+  if (pp->wrleft == 0) {
+       pp->wrcaller = NONE;
+       return EDONTREPLY;              /* already done */
+  }
+
+  if (flags & FLG_OP_NONBLOCK) {
+       r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
+       pp->wrleft = pp->wrcum = 0;
+       pp->wrcaller = NONE;
+       return r;
+  }
+
+  return EDONTREPLY;                   /* do suspend */
+}
+
+/*===========================================================================*
+ *                             pty_master_cancel                            *
+ *===========================================================================*/
+static int pty_master_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
+{
+  tty_t *tp;
+  pty_t *pp;
   int r;
 
-  switch (m_ptr->m_type) {
-    case DEV_READ_S:
-       /* Check, store information on the reader, do I/O. */
-       if (pp->state & TTY_CLOSED) {
-               r = 0;
-               break;
-       }
-       if (pp->rdleft != 0 || pp->rdcum != 0) {
-               r = EIO;
-               break;
-       }
-       if (m_ptr->COUNT <= 0) {
-               r = EINVAL;
-               break;
-       }
-       if (pp->rdgrant != GRANT_INVALID) {
-               r = ENOBUFS;
-               break;
-       }
-       pp->rdcaller = m_ptr->m_source;
-       pp->rdproc = m_ptr->USER_ENDPT;
-       pp->rdgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-       pp->rdoffset = 0;
-       pp->rdleft = m_ptr->COUNT;
-       pty_start(pp);
-       handle_events(tp);
-       if (pp->rdleft == 0) {
-               pp->rdgrant = GRANT_INVALID;
-               return;                 /* already done */
-       }
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
 
-       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
-               r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
-               pp->rdleft = pp->rdcum = 0;
-               pp->rdgrant = GRANT_INVALID;
-       } else {
-               return;                 /* do suspend */
-       }
-       break;
+  if (pp->rdcaller == endpt && pp->rdid == id) {
+       /* Cancel a read from a PTY. */
+       r = pp->rdcum > 0 ? pp->rdcum : EINTR;
+       pp->rdleft = pp->rdcum = 0;
+       pp->rdcaller = NONE;
+       return r;
+  }
 
-    case DEV_WRITE_S:
-       /* Check, store information on the writer, do I/O. */
-       if (pp->state & TTY_CLOSED) {
-               r = EIO;
-               break;
-       }
-       if (pp->wrleft != 0 || pp->wrcum != 0) {
-               r = EIO;
-               break;
-       }
-       if (m_ptr->COUNT <= 0) {
-               r = EINVAL;
-               break;
-       }
-       if (pp->wrgrant != GRANT_INVALID) {
-               r = ENOBUFS;
-               break;
-       }
-       pp->wrcaller = m_ptr->m_source;
-       pp->wrproc = m_ptr->USER_ENDPT;
-       pp->wrgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-       pp->wroffset = 0;
-       pp->wrleft = m_ptr->COUNT;
-       handle_events(tp);
-       if (pp->wrleft == 0) {
-               pp->wrgrant = GRANT_INVALID;
-               return;                 /* already done */
-       }
+  if (pp->wrcaller == endpt && pp->wrid == id) {
+       /* Cancel a write to a PTY. */
+       r = pp->wrcum > 0 ? pp->wrcum : EINTR;
+       pp->wrleft = pp->wrcum = 0;
+       pp->wrcaller = NONE;
+       return r;
+  }
 
-       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
-               r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
-               pp->wrleft = pp->wrcum = 0;
-               pp->wrgrant = GRANT_INVALID;
-               r = EAGAIN;
-       } else {
-               return;                 /* do suspend */
-       }
-       break;
+  /* Request not found. */
+  return EDONTREPLY;
+}
 
-    case DEV_OPEN:
-       if (!(pp->state & PTY_ACTIVE)) {
-               pp->state |= PTY_ACTIVE;
-               pp->rdcum = 0;
-               pp->wrcum = 0;
-               r = OK;
-       } else {
-               r = EIO;
-       }
-       tty_reply(DEV_OPEN_REPL, m_ptr->m_source, m_ptr->USER_ENDPT,
-               (cp_grant_id_t) m_ptr->IO_GRANT, r);
-       return;
+/*===========================================================================*
+ *                             select_try_pty                               *
+ *===========================================================================*/
+static int select_try_pty(tty_t *tp, int ops)
+{
+  pty_t *pp = tp->tty_priv;
+  int r = 0;
 
-    case DEV_CLOSE:
-       if ((pp->state & (TTY_ACTIVE | TTY_CLOSED)) != TTY_ACTIVE) {
-               pp->state = 0;
-       } else {
-               pp->state |= PTY_CLOSED;
-               sigchar(tp, SIGHUP, 1);
-       }
-       tty_reply(DEV_CLOSE_REPL, m_ptr->m_source, m_ptr->USER_ENDPT,
-               (cp_grant_id_t) m_ptr->IO_GRANT, OK);
-       return;
-
-    case DEV_SELECT:
-       pty_select(tp, m_ptr);
-       return;
-
-    case CANCEL:
-       r = EINTR;
-       if (m_ptr->USER_ENDPT == pp->rdproc) {
-               /* Cancel a read from a PTY. */
-               r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
-               pp->rdleft = pp->rdcum = 0;
-               pp->rdgrant = GRANT_INVALID;
-       }
-       if (m_ptr->USER_ENDPT == pp->wrproc) {
-               /* Cancel a write to a PTY. */
-               r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
-               pp->wrleft = pp->wrcum = 0;
-               pp->wrgrant = GRANT_INVALID;
-       }
-       break;
+  if (ops & SEL_WR)  {
+       /* Write won't block on error. */
+       if (pp->state & TTY_CLOSED) r |= SEL_WR;
+       else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
+       else if (tp->tty_inleft > 0) r |= SEL_WR;       /* There's a reader. */
+  }
 
-    default:
-       r = EINVAL;
+  if (ops & SEL_RD) {
+       /* Read won't block on error. */
+       if (pp->state & TTY_CLOSED) r |= SEL_RD;
+       else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
+       else if (pp->ocount > 0) r |= SEL_RD;           /* Actual data. */
   }
-  tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, r);
+
+  return r;
 }
 
 /*===========================================================================*
- *                             pty_write                                    *
+ *                             select_retry_pty                             *
  *===========================================================================*/
-static int pty_write(tty_t *tp, int try)
+void select_retry_pty(tty_t *tp)
+{
+  pty_t *pp = tp->tty_priv;
+  devminor_t minor;
+  int r;
+
+  /* See if the pty side of a pty is ready to return a select. */
+  if (pp->select_ops && (r = select_try_pty(tp, pp->select_ops))) {
+       minor = PTYPX_MINOR + (int) (pp - pty_table);
+       chardriver_reply_select(pp->select_proc, minor, r);
+       pp->select_ops &= ~r;
+  }
+}
+
+/*===========================================================================*
+ *                             pty_master_select                            *
+ *===========================================================================*/
+static int pty_master_select(devminor_t minor, unsigned int ops,
+       endpoint_t endpt)
+{
+  tty_t *tp;
+  pty_t *pp;
+  int ready_ops, watch;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+  pp = tp->tty_priv;
+
+  watch = (ops & SEL_NOTIFY);
+  ops &= (SEL_RD | SEL_WR | SEL_ERR);
+
+  ready_ops = select_try_pty(tp, ops);
+
+  ops &= ~ready_ops;
+  if (ops && watch) {
+       pp->select_ops |= ops;
+       pp->select_proc = endpt;
+  }
+
+  return ready_ops;
+}
+
+/*===========================================================================*
+ *                             do_pty                                       *
+ *===========================================================================*/
+void do_pty(message *m_ptr, int ipc_status)
+{
+/* Process a request for a PTY master (/dev/ptypX) device. */
+
+  chardriver_process(&pty_master_tab, m_ptr, ipc_status);
+}
+
+/*===========================================================================*
+ *                             pty_slave_write                              *
+ *===========================================================================*/
+static int pty_slave_write(tty_t *tp, int try)
 {
 /* (*dev_write)() routine for PTYs.  Transfer bytes from the writer on
  * /dev/ttypX to the output buffer.
@@ -226,15 +348,13 @@ static int pty_write(tty_t *tp, int try)
   pty_t *pp = tp->tty_priv;
   int count, ocount, s;
 
-
   /* PTY closed down? */
   if (pp->state & PTY_CLOSED) {
        if (try) return 1;
        if (tp->tty_outleft > 0) {
-               tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-                       tp->tty_outgrant, EIO);
+               chardriver_reply_task(tp->tty_outcaller, tp->tty_outid, EIO);
                tp->tty_outleft = tp->tty_outcum = 0;
-               tp->tty_outgrant = GRANT_INVALID;
+               tp->tty_outcaller = NONE;
        }
        return 0;
   }
@@ -252,11 +372,11 @@ static int pty_write(tty_t *tp, int try)
        /* Copy from user space to the PTY output buffer. */
        if (tp->tty_outcaller == KERNEL) {
                /* We're trying to print on kernel's behalf */
-               memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset,
+               memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outcum,
                        count);
        } else {
                if ((s = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant,
-                               tp->tty_outoffset, (vir_bytes) pp->ohead,
+                               tp->tty_outcum, (vir_bytes) pp->ohead,
                                count)) != OK) {
                        break;
                }
@@ -275,15 +395,13 @@ static int pty_write(tty_t *tp, int try)
                pp->ohead -= buflen(pp->obuf);
        pty_start(pp);
 
-       tp->tty_outoffset += count;
-
        tp->tty_outcum += count;
        if ((tp->tty_outleft -= count) == 0) {
                /* Output is finished, reply to the writer. */
-               tty_reply(DEV_REVIVE, tp->tty_outcaller, tp->tty_outproc,
-                       tp->tty_outgrant, tp->tty_outcum);
+               chardriver_reply_task(tp->tty_outcaller, tp->tty_outid,
+                       tp->tty_outcum);
                tp->tty_outcum = 0;
-               tp->tty_outgrant = GRANT_INVALID;
+               tp->tty_outcaller = NONE;
        }
   }
   pty_finish(pp);
@@ -291,9 +409,9 @@ static int pty_write(tty_t *tp, int try)
 }
 
 /*===========================================================================*
- *                             pty_echo                                     *
+ *                             pty_slave_echo                               *
  *===========================================================================*/
-static void pty_echo(tty_t *tp, int c)
+static void pty_slave_echo(tty_t *tp, int c)
 {
 /* Echo one character.  (Like pty_write, but only one character, optionally.) */
 
@@ -330,11 +448,10 @@ static void pty_start(pty_t *pp)
        if (count == 0) break;
 
        /* Copy from the output buffer to the readers address space. */
-       if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant,
-               pp->rdoffset, (vir_bytes) pp->otail, count)) != OK) {
+       if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum,
+               (vir_bytes) pp->otail, count)) != OK) {
                break;
        }
-       pp->rdoffset += count;
 
        /* Bookkeeping. */
        pp->ocount -= count;
@@ -352,19 +469,18 @@ static void pty_finish(pty_t *pp)
 /* Finish the read request of a PTY reader if there is at least one byte
  * transferred.
  */
+
   if (pp->rdcum > 0) {
-       tty_reply(DEV_REVIVE, pp->rdcaller, pp->rdproc, pp->rdgrant,
-               pp->rdcum);
+       chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum);
        pp->rdleft = pp->rdcum = 0;
-       pp->rdgrant = GRANT_INVALID;
+       pp->rdcaller = NONE;
   }
-
 }
 
 /*===========================================================================*
- *                             pty_read                                     *
+ *                             pty_slave_read                               *
  *===========================================================================*/
-static int pty_read(tty_t *tp, int try)
+static int pty_slave_read(tty_t *tp, int try)
 {
 /* Offer bytes from the PTY writer for input on the TTY.  (Do it one byte at
  * a time, 99% of the writes will be for one byte, so no sense in being smart.)
@@ -375,10 +491,10 @@ static int pty_read(tty_t *tp, int try)
   if (pp->state & PTY_CLOSED) {
        if (try) return 1;
        if (tp->tty_inleft > 0) {
-               tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc,
-                       tp->tty_ingrant, tp->tty_incum);
+               chardriver_reply_task(tp->tty_incaller, tp->tty_inid,
+                       tp->tty_incum);
                tp->tty_inleft = tp->tty_incum = 0;
-               tp->tty_ingrant = GRANT_INVALID;
+               tp->tty_incaller = NONE;
        }
        return 1;
   }
@@ -393,12 +509,11 @@ static int pty_read(tty_t *tp, int try)
        int s;
 
        /* Transfer one character to 'c'. */
-       if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wroffset,
+       if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wrcum,
                (vir_bytes) &c, 1)) != OK) {
                printf("pty: safecopy failed (error %d)\n", s);
                break;
        }
-       pp->wroffset++;
 
        /* Input processing. */
        if (in_process(tp, &c, 1, -1) == 0) break;
@@ -406,10 +521,9 @@ static int pty_read(tty_t *tp, int try)
        /* PTY writer bookkeeping. */
        pp->wrcum++;
        if (--pp->wrleft == 0) {
-               tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant,
-                       pp->wrcum);
+               chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum);
                pp->wrcum = 0;
-               pp->wrgrant = GRANT_INVALID;
+               pp->wrcaller = NONE;
        }
   }
 
@@ -417,9 +531,9 @@ static int pty_read(tty_t *tp, int try)
 }
 
 /*===========================================================================*
- *                             pty_open                                     *
+ *                             pty_slave_open                               *
  *===========================================================================*/
-static int pty_open(tty_t *tp, int UNUSED(try))
+static int pty_slave_open(tty_t *tp, int UNUSED(try))
 {
 /* The tty side has been opened. */
   pty_t *pp = tp->tty_priv;
@@ -435,9 +549,9 @@ static int pty_open(tty_t *tp, int UNUSED(try))
 }
 
 /*===========================================================================*
- *                             pty_close                                    *
+ *                             pty_slave_close                              *
  *===========================================================================*/
-static int pty_close(tty_t *tp, int UNUSED(try))
+static int pty_slave_close(tty_t *tp, int UNUSED(try))
 {
 /* The tty side has closed, so shut down the pty side. */
   pty_t *pp = tp->tty_priv;
@@ -445,17 +559,15 @@ static int pty_close(tty_t *tp, int UNUSED(try))
   if (!(pp->state & PTY_ACTIVE)) return 0;
 
   if (pp->rdleft > 0) {
-       tty_reply(DEV_REVIVE, pp->rdcaller, pp->rdproc, pp->rdgrant,
-               pp->rdcum);
+       chardriver_reply_task(pp->rdcaller, pp->rdid, pp->rdcum);
        pp->rdleft = pp->rdcum = 0;
-       pp->rdgrant = GRANT_INVALID;
+       pp->rdcaller = NONE;
   }
 
   if (pp->wrleft > 0) {
-       tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant,
-               pp->wrcum);
-       pp->wrcum = 0;
-       pp->wrgrant = GRANT_INVALID;
+       chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum);
+       pp->wrleft = pp->wrcum = 0;
+       pp->wrcaller = NONE;
   }
 
   if (pp->state & PTY_CLOSED) pp->state = 0;
@@ -465,27 +577,26 @@ static int pty_close(tty_t *tp, int UNUSED(try))
 }
 
 /*===========================================================================*
- *                             pty_icancel                                  *
+ *                             pty_slave_icancel                            *
  *===========================================================================*/
-static int pty_icancel(tty_t *tp, int UNUSED(try))
+static int pty_slave_icancel(tty_t *tp, int UNUSED(try))
 {
 /* Discard waiting input. */
   pty_t *pp = tp->tty_priv;
 
   if (pp->wrleft > 0) {
-       tty_reply(DEV_REVIVE, pp->wrcaller, pp->wrproc, pp->wrgrant,
-               pp->wrcum + pp->wrleft);
+       chardriver_reply_task(pp->wrcaller, pp->wrid, pp->wrcum + pp->wrleft);
        pp->wrcum = pp->wrleft = 0;
-       pp->wrgrant = GRANT_INVALID;
+       pp->wrcaller = NONE;
   }
 
   return 0;
 }
 
 /*===========================================================================*
- *                             pty_ocancel                                  *
+ *                             pty_slave_ocancel                            *
  *===========================================================================*/
-static int pty_ocancel(tty_t *tp, int UNUSED(try))
+static int pty_slave_ocancel(tty_t *tp, int UNUSED(try))
 {
 /* Drain the output buffer. */
   pty_t *pp = tp->tty_priv;
@@ -509,86 +620,21 @@ void pty_init(tty_t *tp)
   pp = tp->tty_priv = &pty_table[line];
   pp->tty = tp;
   pp->select_ops = 0;
-  pp->rdgrant = GRANT_INVALID;
-  pp->wrgrant = GRANT_INVALID;
+  pp->rdcaller = NONE;
+  pp->wrcaller = NONE;
 
   /* Set up output queue. */
   pp->ohead = pp->otail = pp->obuf;
 
   /* Fill in TTY function hooks. */
-  tp->tty_devread = pty_read;
-  tp->tty_devwrite = pty_write;
-  tp->tty_echo = pty_echo;
-  tp->tty_icancel = pty_icancel;
-  tp->tty_ocancel = pty_ocancel;
-  tp->tty_open = pty_open;
-  tp->tty_close = pty_close;
+  tp->tty_devread = pty_slave_read;
+  tp->tty_devwrite = pty_slave_write;
+  tp->tty_echo = pty_slave_echo;
+  tp->tty_icancel = pty_slave_icancel;
+  tp->tty_ocancel = pty_slave_ocancel;
+  tp->tty_open = pty_slave_open;
+  tp->tty_close = pty_slave_close;
   tp->tty_select_ops = 0;
 }
 
-/*===========================================================================*
- *                             select_try_pty                               *
- *===========================================================================*/
-static int select_try_pty(tty_t *tp, int ops)
-{
-       pty_t *pp = tp->tty_priv;
-       int r = 0;
-
-       if (ops & SEL_WR)  {
-               /* Write won't block on error. */
-               if (pp->state & TTY_CLOSED) r |= SEL_WR;
-               else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
-               else r |= SEL_WR;
-       }
-
-       if (ops & SEL_RD) {
-               /* Read won't block on error. */
-               if (pp->state & TTY_CLOSED) r |= SEL_RD;
-               else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
-               else if (pp->ocount > 0) r |= SEL_RD;   /* Actual data. */
-       }
-
-       return r;
-}
-
-/*===========================================================================*
- *                             select_retry_pty                             *
- *===========================================================================*/
-void select_retry_pty(tty_t *tp)
-{
-       pty_t *pp = tp->tty_priv;
-       dev_t minor;
-       int r;
-
-       /* See if the pty side of a pty is ready to return a select. */
-       if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) {
-               minor = PTYPX_MINOR + (int) (pp - pty_table);
-               assert(minor == pp->select_minor);
-               select_reply(DEV_SEL_REPL2, pp->select_proc, minor, r);
-               pp->select_ops &= ~r;
-       }
-}
-
-/*===========================================================================*
- *                             pty_select                                   *
- *===========================================================================*/
-static void pty_select(tty_t *tp, message *m)
-{
-       pty_t *pp = tp->tty_priv;
-       int ops, ready_ops = 0, watch;
-
-       ops = m->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR);
-       watch = (m->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0;
-
-       ready_ops = select_try_pty(tp, ops);
-
-       if (!ready_ops && ops && watch) {
-               pp->select_ops |= ops;
-               pp->select_proc = m->m_source;
-               pp->select_minor = m->DEV_MINOR;
-       }
-
-       select_reply(DEV_SEL_REPL1, m->m_source, m->DEV_MINOR, ready_ops);
-}
-
 #endif /* NR_PTYS > 0 */
index 387a2a6e42757d1ebed63557606b674ccc717f7e..e1f55dad0ade3e9b981a1f2e0dae5fd8482f8cf0 100644 (file)
 #include <termios.h>
 #include <sys/ioc_tty.h>
 #include <signal.h>
-#include <minix/callnr.h>
-#include <minix/sys_config.h>
-#include <minix/tty.h>
 #include <minix/keymap.h>
-#include <minix/endpoint.h>
 #include "tty.h"
 
 #include <sys/time.h>
@@ -101,13 +97,6 @@ struct kmessages kmess;
 
 static void tty_timed_out(timer_t *tp);
 static void settimer(tty_t *tty_ptr, int enable);
-static void do_cancel(tty_t *tp, message *m_ptr);
-static void do_ioctl(tty_t *tp, message *m_ptr);
-static void do_open(tty_t *tp, message *m_ptr);
-static void do_close(tty_t *tp, message *m_ptr);
-static void do_read(tty_t *tp, message *m_ptr);
-static void do_write(tty_t *tp, message *m_ptr);
-static void do_select(tty_t *tp, message *m_ptr);
 static void in_transfer(tty_t *tp);
 static int tty_echo(tty_t *tp, int ch);
 static void rawecho(tty_t *tp, int ch);
@@ -118,12 +107,32 @@ static void setattr(tty_t *tp);
 static void tty_icancel(tty_t *tp);
 static void tty_init(void);
 static void do_new_kmess(void);
-static tty_t * line2tty(int line);
 static void set_console_line(char term[CONS_ARG]);
 static void set_kernel_color(char color[CONS_ARG]);
 static void set_color(tty_t *tp, int color);
 static void reset_color(tty_t *tp);
 
+static int do_open(devminor_t minor, int access, endpoint_t user_endpt);
+static int do_close(devminor_t minor);
+static ssize_t do_read(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static ssize_t do_write(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
+static int do_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
+
+static struct chardriver tty_tab = {
+       .cdr_open       = do_open,
+       .cdr_close      = do_close,
+       .cdr_read       = do_read,
+       .cdr_write      = do_write,
+       .cdr_ioctl      = do_ioctl,
+       .cdr_cancel     = do_cancel,
+       .cdr_select     = do_select
+};
+
 /* Default attributes. */
 static struct termios termios_defaults = {
   TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF,
@@ -160,7 +169,7 @@ int main(void)
   message tty_mess;            /* buffer for all incoming messages */
   int ipc_status;
   unsigned line;
-  int r, code;
+  int r;
   register tty_t *tp;
 
   /* SEF local startup. */
@@ -217,7 +226,6 @@ int main(void)
 
        switch (tty_mess.m_type) { 
        case TTY_FKEY_CONTROL:          /* (un)register a fkey observer */
-       case OLD_FKEY_CONTROL:          /* old number */
                do_fkey_ctl(&tty_mess);
                continue;
        case INPUT_EVENT:
@@ -227,76 +235,34 @@ int main(void)
                ;                       /* do nothing; end switch */
        }
 
+       if (!IS_DEV_RQ(tty_mess.m_type)) {
+               chardriver_process(&tty_tab, &tty_mess, ipc_status);
+               continue;
+       }
+
        /* Only device requests should get to this point.
         * All requests have a minor device number.
         */
        line = tty_mess.DEVICE;
-       if (line == CONS_MINOR || line == LOG_MINOR) {
-               /* /dev/log output goes to /dev/console */
-               if (consoleline != CONS_MINOR) {
-                       /* Console output must redirected */
-                       line = consoleline;
-                       tty_mess.DEVICE = line;
-               }
-       }
-       if (line == KBD_MINOR) {
-               do_kbd(&tty_mess);
-               continue;
-       } else if (line == KBDAUX_MINOR) {
-               do_kbdaux(&tty_mess);
+       if (line == KBD_MINOR || line == KBDAUX_MINOR) {
+               do_kbd(&tty_mess, ipc_status);
                continue;
        } else if (line == VIDEO_MINOR) {
-               do_video(&tty_mess);
+               do_video(&tty_mess, ipc_status);
                continue;
-       } else {
-               tp = line2tty(line);
-
+       } else if (line - PTYPX_MINOR < NR_PTYS &&
+                       tty_mess.m_type != DEV_IOCTL_S) {
                /* Terminals and pseudo terminals belong together. We can only
                 * make a distinction between the two based on position in the
                 * tty_table and not on minor number (i.e., use ispty macro).
                 * Hence this special case.
                 */
-               if (line - PTYPX_MINOR < NR_PTYS &&
-                                               tty_mess.m_type != DEV_IOCTL_S){
-                       do_pty(tp, &tty_mess);
-                       continue;
-               }
-       }
-
-       /* If the device doesn't exist or is not configured return ENXIO. */
-       if (tp == NULL || ! tty_active(tp)) {
-               if (tty_mess.m_source == LOG_PROC_NR)
-                       continue;
-
-               /* Can all of these occur? Probably not. We're by far most
-                * likely to see DEV_OPEN, but better safe than sorry..
-                */
-               switch (tty_mess.m_type) {
-               case DEV_OPEN:  code = DEV_OPEN_REPL; break;
-               case DEV_CLOSE: code = DEV_CLOSE_REPL; break;
-               default:        code = DEV_REVIVE; break;
-               }
-
-               tty_reply(code, tty_mess.m_source, tty_mess.USER_ENDPT,
-                       (cp_grant_id_t) tty_mess.IO_GRANT, ENXIO);
+               do_pty(&tty_mess, ipc_status);
                continue;
        }
 
        /* Execute the requested device driver function. */
-       switch (tty_mess.m_type) {
-           case DEV_READ_S:     do_read(tp, &tty_mess);          break;
-           case DEV_WRITE_S:    do_write(tp, &tty_mess);         break;
-           case DEV_IOCTL_S:    do_ioctl(tp, &tty_mess);         break;
-           case DEV_OPEN:       do_open(tp, &tty_mess);          break;
-           case DEV_CLOSE:      do_close(tp, &tty_mess);         break;
-           case DEV_SELECT:     do_select(tp, &tty_mess);        break;
-           case CANCEL:         do_cancel(tp, &tty_mess);        break;
-           default:            
-               printf("Warning, TTY got unexpected request %d from %d\n",
-                       tty_mess.m_type, tty_mess.m_source);
-               tty_reply(DEV_REVIVE, tty_mess.m_source, tty_mess.USER_ENDPT,
-                       (cp_grant_id_t) tty_mess.IO_GRANT, EINVAL);
-       }
+       chardriver_process(&tty_tab, &tty_mess, ipc_status);
   }
 
   return 0;
@@ -305,47 +271,41 @@ int main(void)
 static void
 set_color(tty_t *tp, int color)
 {
-       message msg;
        char buf[8];
 
        buf[0] = '\033';
        snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color);
-       memset(&msg, 0, sizeof(msg));
-       msg.m_source = KERNEL;
-       msg.IO_GRANT = buf;
-       msg.COUNT = sizeof(buf);
-       do_write(tp, &msg);
+       do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
+               FLG_OP_NONBLOCK, 0);
 }
 
 static void
 reset_color(tty_t *tp)
 {
-       message msg;
        char buf[8];
 
 #define SGR_COLOR_RESET        39
        buf[0] = '\033';
        snprintf(&buf[1], sizeof(buf) - 1, "[0;%dm", SGR_COLOR_RESET);
-       memset(&msg, 0, sizeof(msg));
-       msg.m_source = KERNEL;
-       msg.IO_GRANT = buf;
-       msg.COUNT = sizeof(buf);
-       do_write(tp, &msg);
+       do_write(tp->tty_minor, 0, KERNEL, (cp_grant_id_t) buf, sizeof(buf),
+               FLG_OP_NONBLOCK, 0);
 }
 
-static tty_t *
-line2tty(int line)
+tty_t *
+line2tty(devminor_t line)
 {
 /* Convert a terminal line to tty_table pointer */
 
        tty_t* tp;
 
+       /* /dev/log goes to /dev/console, and both may be redirected. */
+       if (line == CONS_MINOR || line == LOG_MINOR)
+               line = consoleline;
+
        if (line == KBD_MINOR || line == KBDAUX_MINOR || line == VIDEO_MINOR) {
                return(NULL);
        } else if ((line - CONS_MINOR) < NR_CONS) {
                tp = tty_addr(line - CONS_MINOR);
-       } else if (line == LOG_MINOR) {
-               tp = tty_addr(consoleline);
        } else if ((line - RS232_MINOR) < NR_RS_LINES) {
                tp = tty_addr(line - RS232_MINOR + NR_CONS);
        } else if ((line - TTYPX_MINOR) < NR_PTYS) {
@@ -356,6 +316,9 @@ line2tty(int line)
                tp = NULL;
        }
 
+       if (tp != NULL && !tty_active(tp))
+               tp = NULL;
+
        return(tp);
 }
 
@@ -430,7 +393,7 @@ set_console_line(char term[CONS_ARG])
        }
 
        /* Serial lines */
-       assert(NR_RS_LINES <= 9);/* bellow assumes this is the case */
+       assert(NR_RS_LINES <= 9);/* below assumes this is the case */
        for (i = 0; i < NR_RS_LINES; i++) {
                char sercons[6];
                strlcpy(sercons, "tty00", sizeof(sercons));
@@ -465,7 +428,6 @@ do_new_kmess(void)
        static int prev_next = 0;
        int next, bytes, copy, restore = 0;
        tty_t *tp, rtp;
-       message print_kmsg;
 
        assert(_minix_kerninfo);
        kmess_ptr = _minix_kerninfo->kmessages;
@@ -491,7 +453,7 @@ do_new_kmess(void)
                }
 
                tp = line2tty(consoleline);
-               if (tp == NULL || !tty_active(tp))
+               if (tp == NULL)
                        panic("Don't know where to send kernel messages");
                if (tp->tty_outleft > 0) {
                        /* Terminal is already printing */
@@ -502,11 +464,9 @@ do_new_kmess(void)
 
                if (kernel_msg_color != 0)
                        set_color(tp, kernel_msg_color);
-               memset(&print_kmsg, 0, sizeof(print_kmsg));
-               print_kmsg.m_source = KERNEL;
-               print_kmsg.IO_GRANT = kernel_buf_copy;
-               print_kmsg.COUNT = bytes;
-               do_write(tp, &print_kmsg);
+               do_write(tp->tty_minor, 0, KERNEL,
+                       (cp_grant_id_t) kernel_buf_copy, bytes,
+                       FLG_OP_NONBLOCK, 0);
                if (kernel_msg_color != 0)
                        reset_color(tp);
                if (restore) {
@@ -541,141 +501,138 @@ static void sef_cb_signal_handler(int signo)
 /*===========================================================================*
  *                             do_read                                      *
  *===========================================================================*/
-static void do_read(tp, m_ptr)
-register tty_t *tp;            /* pointer to tty struct */
-register message *m_ptr;       /* pointer to message sent to the task */
+static ssize_t do_read(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
 {
 /* A process wants to read from a terminal. */
+  tty_t *tp;
   int r;
 
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+
   /* Check if there is already a process hanging in a read, check if the
    * parameters are correct, do I/O.
    */
-  if (tp->tty_inleft > 0) {
-       r = EIO;
-  } else
-  if (m_ptr->COUNT <= 0) {
-       r = EINVAL;
-  } else if (tp->tty_ingrant != GRANT_INVALID) {
-       /* This is actually a fundamental problem with TTY; it can handle
-        * only one reader per minor device. If we don't return an error,
-        * we'll overwrite the previous reader and that process will get
-        * stuck forever. */
-       r = ENOBUFS;
-  } else {
-       /* Copy information from the message to the tty struct. */
-       tp->tty_incaller = m_ptr->m_source;
-       tp->tty_inproc = m_ptr->USER_ENDPT;
-       tp->tty_ingrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-       tp->tty_inoffset = 0;
-       tp->tty_inleft = m_ptr->COUNT;
-
-       if (!(tp->tty_termios.c_lflag & ICANON)
-                                       && tp->tty_termios.c_cc[VTIME] > 0) {
-               if (tp->tty_termios.c_cc[VMIN] == 0) {
-                       /* MIN & TIME specify a read timer that finishes the
-                        * read in TIME/10 seconds if no bytes are available.
-                        */
-                       settimer(tp, TRUE);
-                       tp->tty_min = 1;
-               } else {
-                       /* MIN & TIME specify an inter-byte timer that may
-                        * have to be cancelled if there are no bytes yet.
-                        */
-                       if (tp->tty_eotct == 0) {
-                               settimer(tp, FALSE);
-                               tp->tty_min = tp->tty_termios.c_cc[VMIN];
-                       }
+  if (tp->tty_incaller != NONE || tp->tty_inleft > 0)
+       return EIO;
+  if (size <= 0)
+       return EINVAL;
+
+  /* Copy information from the message to the tty struct. */
+  tp->tty_incaller = endpt;
+  tp->tty_inid = id;
+  tp->tty_ingrant = grant;
+  assert(tp->tty_incum == 0);
+  tp->tty_inleft = size;
+
+  if (!(tp->tty_termios.c_lflag & ICANON) && tp->tty_termios.c_cc[VTIME] > 0) {
+       if (tp->tty_termios.c_cc[VMIN] == 0) {
+               /* MIN & TIME specify a read timer that finishes the
+                * read in TIME/10 seconds if no bytes are available.
+                */
+               settimer(tp, TRUE);
+               tp->tty_min = 1;
+       } else {
+               /* MIN & TIME specify an inter-byte timer that may
+                * have to be cancelled if there are no bytes yet.
+                */
+               if (tp->tty_eotct == 0) {
+                       settimer(tp, FALSE);
+                       tp->tty_min = tp->tty_termios.c_cc[VMIN];
                }
        }
+  }
 
-       /* Anything waiting in the input buffer? Clear it out... */
-       in_transfer(tp);
-       /* ...then go back for more. */
-       handle_events(tp);
-       if (tp->tty_inleft == 0)  {
-               return;                 /* already done */
-       }
+  /* Anything waiting in the input buffer? Clear it out... */
+  in_transfer(tp);
+  /* ...then go back for more. */
+  handle_events(tp);
+  if (tp->tty_inleft == 0)
+       return EDONTREPLY;      /* already done */
 
-       /* There were no bytes in the input queue available. */
-       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
-               tty_icancel(tp);
-               r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
-               tp->tty_inleft = tp->tty_incum = 0;
-               tp->tty_ingrant = GRANT_INVALID;
-       } else {
-               return;                 /* suspend the caller */
-       }
+  /* There were no bytes in the input queue available. */
+  if (flags & FLG_OP_NONBLOCK) {
+       tty_icancel(tp);
+       r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
+       tp->tty_inleft = tp->tty_incum = 0;
+       tp->tty_incaller = NONE;
+       return r;
   }
-  tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, r);
+
   if (tp->tty_select_ops)
-       select_retry(tp);
+       select_retry(tp);
+
+  return EDONTREPLY;           /* suspend the caller */
 }
 
 /*===========================================================================*
  *                             do_write                                     *
  *===========================================================================*/
-static void do_write(tp, m_ptr)
-register tty_t *tp;
-register message *m_ptr;       /* pointer to message sent to the task */
+static ssize_t do_write(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
 {
 /* A process wants to write on a terminal. */
+  tty_t *tp;
   int r;
 
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+
   /* Check if there is already a process hanging in a write, check if the
    * parameters are correct, do I/O.
    */
-  if (tp->tty_outleft > 0) {
-       r = EIO;
-  } else
-  if (m_ptr->COUNT <= 0) {
-       r = EINVAL;
-  } else {
-       /* Copy message parameters to the tty structure. */
-       tp->tty_outcaller = m_ptr->m_source;
-       tp->tty_outproc = m_ptr->USER_ENDPT;
-       tp->tty_outgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-       tp->tty_outoffset = 0;
-       tp->tty_outleft = m_ptr->COUNT;
-
-       /* Try to write. */
-       handle_events(tp);
-       if (tp->tty_outleft == 0)
-               return; /* already done */
-
-       /* None or not all the bytes could be written. */
-       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
-               r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
-               tp->tty_outleft = tp->tty_outcum = 0;
-               tp->tty_outgrant = GRANT_INVALID;
-       } else {
-               return;                 /* suspend the caller */
-       }
+  if (tp->tty_outcaller != NONE || tp->tty_outleft > 0)
+       return EIO;
+  if (size <= 0)
+       return EINVAL;
+
+  /* Copy message parameters to the tty structure. */
+  tp->tty_outcaller = endpt;
+  tp->tty_outid = id;
+  tp->tty_outgrant = grant;
+  assert(tp->tty_outcum == 0);
+  tp->tty_outleft = size;
+
+  /* Try to write. */
+  handle_events(tp);
+  if (tp->tty_outleft == 0)
+       return EDONTREPLY;      /* already done */
+
+  /* None or not all the bytes could be written. */
+  if (flags & FLG_OP_NONBLOCK) {
+       r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
+       tp->tty_outleft = tp->tty_outcum = 0;
+       tp->tty_outcaller = NONE;
+       return r;
   }
-  tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, r);
+
+  if (tp->tty_select_ops)
+       select_retry(tp);
+
+  return EDONTREPLY;           /* suspend the caller */
 }
 
 /*===========================================================================*
  *                             do_ioctl                                     *
  *===========================================================================*/
-static void do_ioctl(tp, m_ptr)
-register tty_t *tp;
-message *m_ptr;                        /* pointer to message sent to task */
+static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
 {
-/* Perform an IOCTL on this terminal. Posix termios calls are handled
- * by the IOCTL system call
+/* Perform an IOCTL on this terminal. POSIX termios calls are handled
+ * by the IOCTL system call.
  */
-
-  int r;
-  union {
-       int i;
-  } param;
+  tty_t *tp;
+  int i, r;
   size_t size;
 
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+
   /* Size of the ioctl parameter. */
-  switch (m_ptr->REQUEST) {
+  switch (request) {
     case TCGETS:        /* Posix tcgetattr function */
     case TCSETS:        /* Posix tcsetattr function, TCSANOW option */ 
     case TCSETSW:       /* Posix tcsetattr function, TCSADRAIN option */
@@ -709,60 +666,55 @@ message *m_ptr;                   /* pointer to message sent to task */
   }
 
   r = OK;
-  switch (m_ptr->REQUEST) {
+  switch (request) {
     case TCGETS:
        /* Get the termios attributes. */
-       r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, 0,
-               (vir_bytes) &tp->tty_termios, (vir_bytes) size);
+       r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &tp->tty_termios,
+               size);
        break;
 
     case TCSETSW:
     case TCSETSF:
     case TCDRAIN:
        if (tp->tty_outleft > 0) {
-               if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
-                       r = EAGAIN;
-               } else {
-                       /* Wait for all ongoing output processing to finish. */
-                       tp->tty_iocaller = m_ptr->m_source;
-                       tp->tty_ioproc = m_ptr->USER_ENDPT;
-                       tp->tty_ioreq = m_ptr->REQUEST;
-                       tp->tty_iogrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-                       return;
-               }
-               break;
+               if (flags & FLG_OP_NONBLOCK)
+                       return EAGAIN;
+               /* Wait for all ongoing output processing to finish. */
+               tp->tty_iocaller = endpt;
+               tp->tty_ioid = id;
+               tp->tty_ioreq = request;
+               tp->tty_iogrant = grant;
+               return EDONTREPLY;      /* suspend the caller */
        }
-       if (m_ptr->REQUEST == TCDRAIN) break;
-       if (m_ptr->REQUEST == TCSETSF) tty_icancel(tp);
+       if (request == TCDRAIN) break;
+       if (request == TCSETSF) tty_icancel(tp);
        /*FALL THROUGH*/
     case TCSETS:
        /* Set the termios attributes. */
-       r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT,
-               0, (vir_bytes) &tp->tty_termios, (vir_bytes) size);
+       r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &tp->tty_termios,
+               size);
        if (r != OK) break;
        setattr(tp);
        break;
 
     case TCFLSH:
-       r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT,
-               0, (vir_bytes) &param.i, (vir_bytes) size);
+       r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i, size);
        if (r != OK) break;
-       switch (param.i) {
-           case TCIFLUSH:      tty_icancel(tp);                            break;
-           case TCOFLUSH:      (*tp->tty_ocancel)(tp, 0);                  break;
-           case TCIOFLUSH:     tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break;
-           default:            r = EINVAL;
+       switch (i) {
+       case TCIFLUSH:  tty_icancel(tp);                            break;
+       case TCOFLUSH:  (*tp->tty_ocancel)(tp, 0);                  break;
+       case TCIOFLUSH: tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break;
+       default:        r = EINVAL;
        }
        break;
 
     case TCFLOW:
-       r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT,
-               0, (vir_bytes) &param.i, (vir_bytes) size);
+       r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i, size);
        if (r != OK) break;
-       switch (param.i) {
+       switch (i) {
            case TCOOFF:
            case TCOON:
-               tp->tty_inhibited = (param.i == TCOOFF);
+               tp->tty_inhibited = (i == TCOOFF);
                tp->tty_events = 1;
                break;
            case TCIOFF:
@@ -781,27 +733,24 @@ message *m_ptr;                   /* pointer to message sent to task */
        break;
 
     case TIOCGWINSZ:
-       r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT, 0,
-               (vir_bytes) &tp->tty_winsize, (vir_bytes) size);
+       r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &tp->tty_winsize,
+               size);
        break;
 
     case TIOCSWINSZ:
-       r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->IO_GRANT,
-               0, (vir_bytes) &tp->tty_winsize, (vir_bytes) size);
+       r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &tp->tty_winsize,
+               size);
        sigchar(tp, SIGWINCH, 0);
        break;
 
     case KIOCSMAP:
        /* Load a new keymap (only /dev/console). */
-       if (isconsole(tp)) r = kbd_loadmap(m_ptr);
+       if (isconsole(tp)) r = kbd_loadmap(endpt, grant);
        break;
 
-    case TIOCSFON_OLD:
-       printf("TTY: old TIOCSFON ignored.\n");
-       break;
     case TIOCSFON:
        /* Load a font into an EGA or VGA card (hs@hck.hr) */
-       if (isconsole(tp)) r = con_loadfont(m_ptr);
+       if (isconsole(tp)) r = con_loadfont(endpt, grant);
        break;
 
 /* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is 
@@ -813,30 +762,30 @@ message *m_ptr;                   /* pointer to message sent to task */
        r = ENOTTY;
   }
 
-  /* Send the reply. */
-  tty_reply(DEV_REVIVE, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, r);
+  return r;
 }
 
 /*===========================================================================*
  *                             do_open                                      *
  *===========================================================================*/
-static void do_open(tp, m_ptr)
-register tty_t *tp;
-message *m_ptr;                        /* pointer to message sent to task */
+static int do_open(devminor_t minor, int access, endpoint_t user_endpt)
 {
 /* A tty line has been opened.  Make it the callers controlling tty if
  * O_NOCTTY is *not* set and it is not the log device.  1 is returned if
  * the tty is made the controlling tty, otherwise OK or an error code.
  */
+  tty_t *tp;
   int r = OK;
 
-  if (m_ptr->DEVICE == LOG_MINOR) {
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+
+  if (minor == LOG_MINOR) {
        /* The log device is a write-only diagnostics device. */
-       if (m_ptr->COUNT & R_BIT) r = EACCES;
+       if (access & R_BIT) return EACCES;
   } else {
-       if (!(m_ptr->COUNT & O_NOCTTY)) {
-               tp->tty_pgrp = m_ptr->USER_ENDPT;
+       if (!(access & O_NOCTTY)) {
+               tp->tty_pgrp = user_endpt;
                r = 1;
        }
        tp->tty_openct++;
@@ -845,20 +794,22 @@ message *m_ptr;                   /* pointer to message sent to task */
                (*tp->tty_open)(tp, 0);
        }
   }
-  tty_reply(DEV_OPEN_REPL, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, r);
+
+  return r;
 }
 
 /*===========================================================================*
  *                             do_close                                     *
  *===========================================================================*/
-static void do_close(tp, m_ptr)
-register tty_t *tp;
-message *m_ptr;                        /* pointer to message sent to task */
+static int do_close(devminor_t minor)
 {
 /* A tty line has been closed.  Clean up the line if it is the last close. */
+  tty_t *tp;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
 
-  if (m_ptr->DEVICE != LOG_MINOR && --tp->tty_openct == 0) {
+  if (minor != LOG_MINOR && --tp->tty_openct == 0) {
        tp->tty_pgrp = 0;
        tty_icancel(tp);
        (*tp->tty_ocancel)(tp, 0);
@@ -867,53 +818,49 @@ message *m_ptr;                   /* pointer to message sent to task */
        tp->tty_winsize = winsize_defaults;
        setattr(tp);
   }
-  tty_reply(DEV_CLOSE_REPL, m_ptr->m_source, m_ptr->USER_ENDPT,
-       (cp_grant_id_t) m_ptr->IO_GRANT, OK);
+
+  return OK;
 }
 
 /*===========================================================================*
  *                             do_cancel                                    *
  *===========================================================================*/
-static void do_cancel(tp, m_ptr)
-register tty_t *tp;
-message *m_ptr;                        /* pointer to message sent to task */
+static int do_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
 {
 /* A signal has been sent to a process that is hanging trying to read or write.
  * The pending read or write must be finished off immediately.
  */
-  endpoint_t proc_nr;
-  cp_grant_id_t grant;
-  int mode;
-  int r = EDONTREPLY;
+  tty_t *tp;
+  int r;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
 
   /* Check the parameters carefully, to avoid cancelling twice. */
-  proc_nr = m_ptr->USER_ENDPT;
-  grant = (cp_grant_id_t) m_ptr->IO_GRANT;
-  mode = m_ptr->COUNT;
-  if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc &&
-       tp->tty_ingrant == grant) {
+  r = EDONTREPLY;
+  if (tp->tty_inleft != 0 && endpt == tp->tty_incaller && id == tp->tty_inid) {
        /* Process was reading when killed.  Clean up input. */
        tty_icancel(tp); 
        r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
        tp->tty_inleft = tp->tty_incum = 0;
-       tp->tty_ingrant = GRANT_INVALID;
-  } 
-  if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc &&
-       tp->tty_outgrant == grant) {
+       tp->tty_incaller = NONE;
+  } else if (tp->tty_outleft != 0 && endpt == tp->tty_outcaller &&
+       id == tp->tty_outid) {
        /* Process was writing when killed.  Clean up output. */
        r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
        tp->tty_outleft = tp->tty_outcum = 0;
-       tp->tty_outgrant = GRANT_INVALID;
-  } 
-  if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
+       tp->tty_outcaller = NONE;
+  } else if (tp->tty_ioreq != 0 && endpt == tp->tty_iocaller &&
+       id == tp->tty_ioid) {
        /* Process was waiting for output to drain. */
-       tp->tty_ioreq = 0;
        r = EINTR;
+       tp->tty_ioreq = 0;
+       tp->tty_iocaller = NONE;
   }
-  tp->tty_events = 1;
-  /* Only reply if we found a matching request. */
   if (r != EDONTREPLY)
-       tty_reply(DEV_REVIVE, m_ptr->m_source, proc_nr, grant, r);
+       tp->tty_events = 1;
+  /* Only reply if we found a matching request. */
+  return r;
 }
 
 int select_try(struct tty *tp, int ops)
@@ -955,14 +902,43 @@ int select_retry(struct tty *tp)
        int ops;
 
        if (tp->tty_select_ops && (ops = select_try(tp, tp->tty_select_ops))) {
-               assert(tp->tty_select_minor == tp->tty_minor);
-               select_reply(DEV_SEL_REPL2, tp->tty_select_proc, tp->tty_minor,
+               chardriver_reply_select(tp->tty_select_proc, tp->tty_minor,
                        ops);
                tp->tty_select_ops &= ~ops;
        }
        return OK;
 }
 
+/*===========================================================================*
+ *                             do_select                                    *
+ *===========================================================================*/
+static int do_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
+{
+  tty_t *tp;
+  int ready_ops, watch;
+
+  if ((tp = line2tty(minor)) == NULL)
+       return ENXIO;
+
+  /* Translated minor numbers are a problem when sending late replies. */
+  if (tp->tty_minor != minor)
+       return EBADF;
+
+  watch = (ops & SEL_NOTIFY);
+  ops &= (SEL_RD | SEL_WR | SEL_ERR);
+
+  ready_ops = select_try(tp, ops);
+
+  ops &= ~ready_ops;
+  if (ops && watch) {
+       tp->tty_select_ops |= ops;
+       tp->tty_select_proc = endpt;
+  }
+
+  assert(tp->tty_minor == minor);
+  return ready_ops;
+}
+
 /*===========================================================================*
  *                             handle_events                                *
  *===========================================================================*/
@@ -979,8 +955,8 @@ tty_t *tp;                  /* TTY to check for events. */
  * to avoid swamping the TTY task.  Messages may be overwritten when the
  * lines are fast or when there are races between different lines, input
  * and output, because MINIX only provides single buffering for interrupt
- * messages (in proc.c).  This is handled by explicitly checking each line
- * for fresh input and completed output on each interrupt.
+ * messages.  This is handled by explicitly checking each line for fresh input
+ * and completed output on each interrupt.
  */
 
   do {
@@ -1001,10 +977,9 @@ tty_t *tp;                        /* TTY to check for events. */
 
   /* Reply if enough bytes are available. */
   if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
-       tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc,
-               tp->tty_ingrant, tp->tty_incum);
+       chardriver_reply_task(tp->tty_incaller, tp->tty_inid, tp->tty_incum);
        tp->tty_inleft = tp->tty_incum = 0;
-       tp->tty_ingrant = GRANT_INVALID;
+       tp->tty_incaller = NONE;
   }
   if (tp->tty_select_ops)
   {
@@ -1045,10 +1020,8 @@ register tty_t *tp;              /* pointer to terminal to read from */
                if (++bp == bufend(buf)) {
                        /* Temp buffer full, copy to user space. */
                        sys_safecopyto(tp->tty_incaller,
-                               tp->tty_ingrant, tp->tty_inoffset,
-                               (vir_bytes) buf,
-                               (vir_bytes) buflen(buf));
-                       tp->tty_inoffset += buflen(buf);
+                               tp->tty_ingrant, tp->tty_incum,
+                               (vir_bytes) buf, (vir_bytes) buflen(buf));
                        tp->tty_incum += buflen(buf);
                        bp = buf;
                }
@@ -1068,19 +1041,16 @@ register tty_t *tp;             /* pointer to terminal to read from */
   if (bp > buf) {
        /* Leftover characters in the buffer. */
        count = bp - buf;
-       sys_safecopyto(tp->tty_incaller,
-               tp->tty_ingrant, tp->tty_inoffset,
+       sys_safecopyto(tp->tty_incaller, tp->tty_ingrant, tp->tty_incum,
                (vir_bytes) buf, (vir_bytes) count);
-       tp->tty_inoffset += count;
        tp->tty_incum += count;
   }
 
   /* Usually reply to the reader, possibly even if incum == 0 (EOF). */
   if (tp->tty_inleft == 0) {
-       tty_reply(DEV_REVIVE, tp->tty_incaller, tp->tty_inproc,
-               tp->tty_ingrant, tp->tty_incum);
+       chardriver_reply_task(tp->tty_incaller, tp->tty_inid, tp->tty_incum);
        tp->tty_inleft = tp->tty_incum = 0;
-       tp->tty_ingrant = GRANT_INVALID;
+       tp->tty_incaller = NONE;
   }
 }
 
@@ -1510,9 +1480,8 @@ tty_t *tp;
        if (result == OK) setattr(tp);
   }
   tp->tty_ioreq = 0;
-  tty_reply(DEV_REVIVE, tp->tty_iocaller, tp->tty_ioproc, tp->tty_iogrant,
-       result);
-  tp->tty_iogrant = GRANT_INVALID;
+  chardriver_reply_task(tp->tty_iocaller, tp->tty_ioid, result);
+  tp->tty_iocaller = NONE;
 }
 
 /*===========================================================================*
@@ -1571,57 +1540,6 @@ tty_t *tp;
   (*tp->tty_ioctl)(tp, 0);
 }
 
-/*===========================================================================*
- *                             tty_reply                                    *
- *===========================================================================*/
-void 
-tty_reply_f(
-file, line, code, replyee, proc_nr, grant, status)
-char *file;
-int line;
-int code;                      /* DEV_OPEN_REPL, DEV_CLOSE_REPL, DEV_REVIVE */
-endpoint_t replyee;            /* destination address for the reply */
-endpoint_t proc_nr;            /* to whom should the reply go? */
-cp_grant_id_t grant;           /* which grant was involved? */
-int status;                    /* reply code */
-{
-  message m;
-
-  assert(code == DEV_OPEN_REPL || code == DEV_CLOSE_REPL || code == DEV_REVIVE);
-
-  /* Don't reply to KERNEL (kernel messages) */
-  if (replyee == KERNEL) return;
-
-  memset(&m, 0, sizeof(m));
-
-  m.REP_ENDPT = proc_nr;
-  m.REP_IO_GRANT = grant;
-  m.REP_STATUS = status;
-
-  status = _sendcall(replyee, code, &m);
-  if (status != OK)
-       printf("tty`tty_reply: send to %d failed: %d\n", replyee, status);
-}
-
-/*===========================================================================*
- *                             select_reply                                 *
- *===========================================================================*/
-void select_reply(int code, endpoint_t replyee, dev_t minor, int ops)
-{
-  message m;
-  int status;
-
-  memset(&m, 0, sizeof(m));
-
-  m.DEV_MINOR = minor;
-  m.DEV_SEL_OPS = ops;
-
-  status = _sendcall(replyee, code, &m);
-  if (status != OK)
-       printf("tty`select_reply: send to %d failed: %d\n", replyee, status);
-}
-
-
 /*===========================================================================*
  *                             sigchar                                      *
  *===========================================================================*/
@@ -1696,7 +1614,7 @@ static void tty_init()
 
        tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
        tp->tty_min = 1;
-       tp->tty_ingrant = tp->tty_outgrant = tp->tty_iogrant = GRANT_INVALID;
+       tp->tty_incaller = tp->tty_outcaller = tp->tty_iocaller = NONE;
        tp->tty_termios = termios_defaults;
        tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
                          tp->tty_open = tty_devnop;
@@ -1750,27 +1668,3 @@ int enable;                      /* set timer if true, otherwise unset */
        cancel_timer(&tty_ptr->tty_tmr);
   }
 }
-
-/*===========================================================================*
- *                             do_select                                    *
- *===========================================================================*/
-static void do_select(tp, m_ptr)
-register tty_t *tp;            /* pointer to tty struct */
-register message *m_ptr;       /* pointer to message sent to the task */
-{
-       int ops, ready_ops = 0, watch;
-
-       ops = m_ptr->DEV_SEL_OPS & (SEL_RD|SEL_WR|SEL_ERR);
-       watch = (m_ptr->DEV_SEL_OPS & SEL_NOTIFY) ? 1 : 0;
-
-       ready_ops = select_try(tp, ops);
-
-       if (!ready_ops && ops && watch) {
-               tp->tty_select_ops |= ops;
-               tp->tty_select_proc = m_ptr->m_source;
-               tp->tty_select_minor = m_ptr->DEV_MINOR;
-       }
-
-       assert(tp->tty_minor == m_ptr->DEV_MINOR);
-       select_reply(DEV_SEL_REPL1, m_ptr->m_source, tp->tty_minor, ready_ops);
-}
index 1933692df3ff7891536779408fa398e65c5b5963..baca8dcc3c19794656b29ba86620242a189ca6af 100644 (file)
@@ -1,5 +1,6 @@
 /*     tty.h - Terminals       */
 
+#include <minix/chardriver.h>
 #include <timers.h>
 
 #undef lock
@@ -34,7 +35,7 @@ typedef void(*devfunarg_t) (struct tty *tp, int c);
 typedef struct tty {
   int tty_events;              /* set when TTY should inspect this line */
   int tty_index;               /* index into TTY table */
-  int tty_minor;               /* device minor number */
+  devminor_t tty_minor;                /* device minor number */
 
   /* Input queue.  Typed characters are stored here until read by a program. */
   u16_t *tty_inhead;           /* pointer to place where next char goes */
@@ -61,27 +62,24 @@ typedef struct tty {
   char tty_openct;             /* count of number of opens of this tty */
 
   /* Information about incomplete I/O requests is stored here. */
-  endpoint_t tty_incaller;     /* process that made the call (usually VFS) */
-  endpoint_t tty_inproc;       /* process that wants to read from tty */
+  endpoint_t tty_incaller;     /* process that made the call, or NONE */
+  cdev_id_t tty_inid;          /* ID of suspended read request */
   cp_grant_id_t tty_ingrant;   /* grant where data is to go */
-  vir_bytes tty_inoffset;      /* offset into grant */
-  int tty_inleft;              /* how many chars are still needed */
-  int tty_incum;               /* # chars input so far */
-  endpoint_t tty_outcaller;    /* process that made the call (usually VFS) */
-  endpoint_t tty_outproc;      /* process that wants to write to tty */
+  size_t tty_inleft;           /* how many chars are still needed */
+  size_t tty_incum;            /* # chars input so far */
+  endpoint_t tty_outcaller;    /* process that made the call, or NONE */
+  cdev_id_t tty_outid;         /* ID of suspended write request */
   cp_grant_id_t tty_outgrant;  /* grant where data comes from */
-  vir_bytes tty_outoffset;     /* offset into grant */
-  int tty_outleft;             /* # chars yet to be output */
-  int tty_outcum;              /* # chars output so far */
-  endpoint_t tty_iocaller;     /* process that made the call (usually VFS) */
-  endpoint_t tty_ioproc;       /* process that wants to do an ioctl */
-  int tty_ioreq;               /* ioctl request code */
+  size_t tty_outleft;          /* # chars yet to be output */
+  size_t tty_outcum;           /* # chars output so far */
+  endpoint_t tty_iocaller;     /* process that made the call, or NONE */
+  cdev_id_t tty_ioid;          /* ID of suspended ioctl request */
+  unsigned int tty_ioreq;      /* ioctl request code */
   cp_grant_id_t tty_iogrant;   /* virtual address of ioctl buffer or grant */
 
   /* select() data */
   int tty_select_ops;          /* which operations are interesting */
   endpoint_t tty_select_proc;  /* which process wants notification */
-  dev_t tty_select_minor;      /* sanity check only, can be removed */
 
   /* Miscellaneous. */
   devfun_t tty_ioctl;          /* set line speed, etc. at the device level */
@@ -135,14 +133,11 @@ extern struct kmessages kmess;
 void handle_events(struct tty *tp);
 void sigchar(struct tty *tp, int sig, int mayflush);
 void tty_task(void);
+tty_t *line2tty(devminor_t minor);
 int in_process(struct tty *tp, char *buf, int count, int scode);
 void out_process(struct tty *tp, char *bstart, char *bpos, char *bend,
        int *icount, int *ocount);
 void tty_wakeup(clock_t now);
-#define tty_reply(c, r, p, g, s) tty_reply_f(__FILE__, __LINE__, (c), (r), (p), (g), (s))
-void tty_reply_f(char *f, int l, int code, endpoint_t replyee,
-       endpoint_t proc_nr, cp_grant_id_t grant, int status);
-void select_reply(int code, endpoint_t replyee, dev_t minor, int ops);
 int select_try(struct tty *tp, int ops);
 int select_retry(struct tty *tp);
 
@@ -155,22 +150,21 @@ void kputc(int c);
 void cons_stop(void);
 void scr_init(struct tty *tp);
 void toggle_scroll(void);
-int con_loadfont(message *m);
+int con_loadfont(endpoint_t endpt, cp_grant_id_t grant);
 void select_console(int cons_line);
 void beep_x( unsigned freq, clock_t dur);
-void do_video(message *m);
+void do_video(message *m, int ipc_status);
 
 /* keyboard.c */
 void kb_init(struct tty *tp);
 void kb_init_once(void);
-int kbd_loadmap(message *m);
+int kbd_loadmap(endpoint_t endpt, cp_grant_id_t grant);
 void do_fkey_ctl(message *m);
 void kbd_interrupt(message *m);
-void do_kbd(message *m);
+void do_kbd(message *m, int ipc_status);
 void do_kb_inject(message *m);
-void do_kbdaux(message *m);
 
 /* pty.c */
-void do_pty(struct tty *tp, message *m_ptr);
+void do_pty(message *m_ptr, int ipc_status);
 void pty_init(struct tty *tp);
 void select_retry_pty(struct tty *tp);
index b8a3273bc52454dfd01fd551f4ac6ddbc2915c62..030ebc3873ef05b4243caa70044ed2ff9d25809c 100644 (file)
@@ -18,7 +18,7 @@ INCS+=        acpi.h audio_fw.h bitmap.h \
        reboot.h rs.h safecopies.h sched.h sef.h sffs.h \
        sound.h spin.h sys_config.h sysinfo.h \
        syslib.h sysutil.h termios.h timers.h type.h \
-       tty.h u64.h usb.h usb_ch9.h vbox.h \
+       u64.h usb.h usb_ch9.h vbox.h \
        vboxfs.h vboxif.h vboxtype.h vm.h \
        vfsif.h vtreefs.h libminixfs.h netsock.h \
        virtio.h
index 60ae42ef7ad4c3248f9e96d459396edb003020ef..7f9fee92b73fa3f56767590f9d154e83eab51556 100644 (file)
 
 
 #define TTY_FKEY_CONTROL       (TTY_RQ_BASE + 1) /* control an F-key at TTY */
-#define OLD_FKEY_CONTROL       98      /* previously used for TTY_FKEY_CONTROL */
 #  define FKEY_REQUEST      m2_i1      /* request to perform at TTY */
 #  define    FKEY_MAP          10      /* observe function key */
 #  define    FKEY_UNMAP                11      /* stop observing function key */
diff --git a/include/minix/tty.h b/include/minix/tty.h
deleted file mode 100644 (file)
index fcf8d2f..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#ifndef _MINIX_TTY_H
-#define _MINIX_TTY_H
-
-#include <sys/types.h>
-
-#define TTYMAGIC       0xb105
-
-/* A struct that the tty driver can use to pass values to the boot monitor.
- * Currently only the value of the origin of the first vty (console), so the
- * boot monitor can properly display it when panicing (tty isn't scheduled
- * to switch to the first vty). It's written at the end of video memory
- * (video memory base + video memory size - sizeof(struct boot_tty_info).
- */
-
-struct boot_tty_info {
-       u16_t   reserved[30];   /* reserved, set to 0 */
-       u16_t   consorigin;     /* origin in video memory of console */
-       u16_t   conscursor;     /* position of cursor of console */
-       u16_t   flags;          /* flags indicating which fields are valid */
-       u16_t   magic;          /* magic number indicating struct is valid */
-};
-
-#define BTIF_CONSORIGIN        0x01    /* consorigin is set */
-#define BTIF_CONSCURSOR        0x02    /* conscursor is set */
-
-#endif
-
index ff42c13a5fe137826850b5477bae588df8da5299..c51361f75d33bf16fb4c813d4ab8fabdb0e5a310 100644 (file)
@@ -22,7 +22,6 @@
 #define        TIOCSWINSZ      _IOW('T', 17, struct winsize)
 #define        TIOCGPGRP       _IOW('T', 18, int)
 #define        TIOCSPGRP       _IOW('T', 19, int)
-#define TIOCSFON_OLD   _IOW('T', 20, u8_t [8192])
 #define TIOCSFON       _IOW_BIG(1, u8_t [8192])
 
 /* Keyboard ioctls. */