Enable TIOCUCNTL to be able to set ns8250's break detected condition.
authormpi <mpi@openbsd.org>
Mon, 8 Jan 2018 11:58:27 +0000 (11:58 +0000)
committermpi <mpi@openbsd.org>
Mon, 8 Jan 2018 11:58:27 +0000 (11:58 +0000)
It is now possible to send BREAK commands to vmd(8) independently of
the serial terminal emulator.

Happy virtual ddb(4) hacking!

No objection from mlarkin@, ok nicm@, ccardenas@, deraadt@

usr.sbin/vmd/ns8250.c
usr.sbin/vmd/vmd.c

index 259d3f6..0e95615 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.c,v 1.12 2017/09/15 02:35:39 mlarkin Exp $ */
+/* $OpenBSD: ns8250.c,v 1.13 2018/01/08 11:58:27 mpi Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -16,6 +16,7 @@
  */
 
 #include <sys/types.h>
+#include <sys/ttycom.h>
 
 #include <dev/ic/comreg.h>
 
@@ -132,6 +133,30 @@ com_rcv_event(int fd, short kind, void *arg)
        mutex_unlock(&com1_dev.mutex);
 }
 
+/*
+ * com_rcv_handle_break
+ *
+ * Set/clear break detected contidion based on received TIOCUCNTL_{S,C}BRK.
+ */
+static int
+com_rcv_handle_break(struct ns8250_dev *com, uint8_t cmd)
+{
+       switch (cmd) {
+       case 0: /* DATA */
+               return 0;
+       case TIOCUCNTL_SBRK:
+               com->regs.lsr |= LSR_BI;
+               break;
+       case TIOCUCNTL_CBRK:
+               com->regs.lsr &= ~LSR_BI;
+               break;
+       default:
+               log_warnx("unexpected UCNTL ioctl: %d", cmd);
+       }
+
+       return 1;
+}
+
 /*
  * com_rcv
  *
@@ -141,7 +166,7 @@ com_rcv_event(int fd, short kind, void *arg)
 static void
 com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
 {
-       char ch;
+       char buf[2];
        ssize_t sz;
 
        /*
@@ -149,7 +174,7 @@ com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
         * If so, consume the character, buffer it into the com1 data register
         * assert IRQ4, and set the line status register RXRDY bit.
         */
-       sz = read(com->fd, &ch, sizeof(char));
+       sz = read(com->fd, buf, sizeof(buf));
        if (sz == -1) {
                /*
                 * If we get EAGAIN, we'll retry and get the character later.
@@ -158,11 +183,14 @@ com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
                 */
                if (errno != EAGAIN)
                        log_warn("unexpected read error on com device");
-       } else if (sz != 1)
-               log_warnx("unexpected read return value on com device");
+       } else if (sz != 1 && sz != 2)
+               log_warnx("unexpected read return value %zd on com device", sz);
        else {
+               if (com_rcv_handle_break(com, buf[0]))
+                       buf[1] = 0;
+
                com->regs.lsr |= LSR_RXRDY;
-               com->regs.data = ch;
+               com->regs.data = buf[1];
 
                if (com->regs.ier & IER_ERXRDY) {
                        com->regs.iir |= IIR_RXRDY;
index f0ca847..450e8f8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmd.c,v 1.77 2018/01/03 05:39:56 ccardenas Exp $      */
+/*     $OpenBSD: vmd.c,v 1.78 2018/01/08 11:58:27 mpi Exp $    */
 
 /*
  * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -22,6 +22,7 @@
 #include <sys/cdefs.h>
 #include <sys/stat.h>
 #include <sys/tty.h>
+#include <sys/ttycom.h>
 #include <sys/ioctl.h>
 
 #include <stdio.h>
@@ -800,7 +801,7 @@ vmd_configure(void)
         * stdio - for malloc and basic I/O including events.
         * rpath - for reload to open and read the configuration files.
         * wpath - for opening disk images and tap devices.
-        * tty - for openpty.
+        * tty - for openpty and TIOCUCNTL.
         * proc - run kill to terminate its children safely.
         * sendfd - for disks, interfaces and other fds.
         * recvfd - for send and receive.
@@ -1273,6 +1274,7 @@ vm_opentty(struct vmd_vm *vm)
        uid_t                    uid;
        gid_t                    gid;
        mode_t                   mode;
+       int                      on;
 
        /*
         * Open tty with pre-opened PTM fd
@@ -1280,6 +1282,13 @@ vm_opentty(struct vmd_vm *vm)
        if ((ioctl(env->vmd_ptmfd, PTMGET, &ptm) == -1))
                return (-1);
 
+       /*
+        * We use user ioctl(2) mode to pass break commands.
+        */
+       on = 1;
+       if (ioctl(ptm.cfd, TIOCUCNTL, &on))
+               fatal("could not enable user ioctl mode");
+
        vm->vm_tty = ptm.cfd;
        close(ptm.sfd);
        if ((vm->vm_ttyname = strdup(ptm.sn)) == NULL)