Index: sys/dev/virtio/console/virtio_console.c =================================================================== --- sys/dev/virtio/console/virtio_console.c +++ sys/dev/virtio/console/virtio_console.c @@ -74,6 +74,11 @@ struct vtcon_softc *vtcport_sc; struct vtcon_softc_port *vtcport_scport; struct tty *vtcport_tty; + struct consdev *vtcport_consdev; + char *vtcport_name; + char *vtcport_buf; + uint32_t vtcport_buf_len; + uint32_t vtcport_buf_pos; struct virtqueue *vtcport_invq; struct virtqueue *vtcport_outvq; int vtcport_id; @@ -228,6 +233,24 @@ .tsw_free = vtcon_tty_free, }; +static cn_probe_t vtcon_cnprobe; +static cn_init_t vtcon_cninit; +static cn_term_t vtcon_cnterm; +static cn_getc_t vtcon_cngetc; +static cn_putc_t vtcon_cnputc; +static cn_grab_t vtcon_cngrab; +static cn_ungrab_t vtcon_cnungrab; + +const struct consdev_ops vtcon_cnops = { + .cn_probe = vtcon_cnprobe, + .cn_init = vtcon_cninit, + .cn_term = vtcon_cnterm, + .cn_getc = vtcon_cngetc, + .cn_putc = vtcon_cnputc, + .cn_grab = vtcon_cngrab, + .cn_ungrab = vtcon_cnungrab, +}; + static device_method_t vtcon_methods[] = { /* Device methods. */ DEVMETHOD(device_probe, vtcon_probe), @@ -252,6 +275,99 @@ MODULE_VERSION(virtio_console, 1); MODULE_DEPEND(virtio_console, virtio, 1, 1, 1); +static void +vtcon_cnregister(struct vtcon_port *port) +{ + struct consdev *cp; + + cp = port->vtcport_consdev; + if (cp == NULL) { + cp = malloc(sizeof(struct consdev), M_DEVBUF, + M_WAITOK | M_ZERO); + cp->cn_ops = &vtcon_cnops; + cp->cn_arg = port; + cp->cn_pri = CN_REMOTE; + if (port->vtcport_name != NULL) { + strlcpy(cp->cn_name, port->vtcport_name, + sizeof(cp->cn_name)); + } else { + snprintf(cp->cn_name, sizeof(cp->cn_name), "%s%r.%r", + VTCON_TTY_PREFIX, + device_get_unit(port->vtcport_sc->vtcon_dev), + port->vtcport_id); + } + port->vtcport_consdev = cp; + } + + /* Attach the port as console. */ + cnadd(cp); +} + +static void +vtcon_cngrab(struct consdev *cp) +{ +} + +static void +vtcon_cnungrab(struct consdev *cp) +{ +} + +static void +vtcon_cnprobe(struct consdev *cp) +{ +} + +static void +vtcon_cninit(struct consdev *cp) +{ +} + +static void +vtcon_cnterm(struct consdev *cp) +{ +} + +static int +vtcon_cngetc(struct consdev *cp) +{ + struct vtcon_port *port; + struct virtqueue *vq; + uint32_t len; + int ret; + + port = cp->cn_arg; + vq = port->vtcport_invq; + if (port->vtcport_buf == NULL) { + port->vtcport_buf = virtqueue_dequeue(vq, &len); + if (port->vtcport_buf == NULL) + return (-1); + port->vtcport_buf_len = len; + port->vtcport_buf_pos = 0; + } + + ret = port->vtcport_buf[port->vtcport_buf_pos]; + port->vtcport_buf_pos++; + if (port->vtcport_buf_pos == port->vtcport_buf_len) { + vtcon_port_requeue_buf(port, port->vtcport_buf); + virtqueue_notify(vq); + port->vtcport_buf = NULL; + } + return (ret); +} + +static void +vtcon_cnputc(struct consdev *cp, int c) +{ + struct vtcon_port *port = cp->cn_arg; + char cv = c; + + /*VTCON_PORT_LOCK(port);*/ + if ((port->vtcport_flags & VTCON_PORT_FLAG_GONE) == 0) + vtcon_port_out(port, &cv, 1); + /*VTCON_PORT_UNLOCK(port);*/ +} + static int vtcon_modevent(module_t mod, int type, void *unused) { @@ -773,6 +889,7 @@ port->vtcport_flags |= VTCON_PORT_FLAG_CONSOLE; vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1); VTCON_PORT_UNLOCK(port); + vtcon_cnregister(port); } static void @@ -818,6 +935,7 @@ return; } + port->vtcport_name = strndup(name, len, M_DEVBUF); tty_makealias(port->vtcport_tty, "vtcon/%*s", (int)len, name); } @@ -1160,6 +1278,10 @@ port->vtcport_flags |= VTCON_PORT_FLAG_GONE; + if (port->vtcport_consdev != NULL) + cnremove(port->vtcport_consdev); + free(port->vtcport_name, M_DEVBUF); + if (tp != NULL) { atomic_add_int(&vtcon_pending_free, 1); tty_rel_gone(tp);