From 2b79fb54ec69878f20defad03b7704b2255f1e75 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 13 Aug 2022 16:52:40 +0000 Subject: [PATCH 1/2] viocon(4): Support for use as console, not just as tty. --- sys/dev/virtio/viocon.c | 107 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c index 9d80be1fdc2d..ab0c34f63ca2 100644 --- a/sys/dev/virtio/viocon.c +++ b/sys/dev/virtio/viocon.c @@ -17,6 +17,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define VIOCON_CONSOLE + #include __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi Exp $"); @@ -33,6 +35,10 @@ __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi Exp $") #include #include +#ifdef VIOCON_CONSOLE +#include +#endif + #include #include @@ -117,6 +123,13 @@ struct viocon_port { uint16_t vp_cols; u_char *vp_rx_buf; u_char *vp_tx_buf; + +#ifdef VIOCON_CONSOLE + struct consdev vp_cntab; + unsigned int vp_pollpos; + unsigned int vp_polllen; + bool vp_polling; +#endif }; struct viocon_softc { @@ -153,6 +166,12 @@ void vioconstop(struct tty *, int); int vioconioctl(dev_t, u_long, void *, int, struct lwp *); struct tty *viocontty(dev_t dev); +#ifdef VIOCON_CONSOLE +static void viocon_cnpollc(dev_t, int); +static int viocon_cngetc(dev_t); +static void viocon_cnputc(dev_t, int); +#endif + CFATTACH_DECL_NEW(viocon, sizeof(struct viocon_softc), viocon_match, viocon_attach, /*detach*/NULL, /*activate*/NULL); @@ -228,6 +247,20 @@ viocon_attach(struct device *parent, struct device *self, void *aux) /*config_change*/NULL, /*req_flags*/0) != 0) goto err; +#ifdef VIOCON_CONSOLE + if (cn_tab == NULL) { + sc->sc_ports[0]->vp_cntab = (struct consdev) { + .cn_pollc = viocon_cnpollc, + .cn_getc = viocon_cngetc, + .cn_putc = viocon_cnputc, + .cn_dev = VIOCONDEV(device_unit(self), 0), + .cn_pri = CN_REMOTE, + }; + aprint_normal_dev(sc->sc_dev, "console\n"); + cn_tab = &sc->sc_ports[0]->vp_cntab; + } +#endif + return; err: kmem_free(sc->sc_vqs, nvqs * sizeof(sc->sc_vqs[0])); @@ -633,3 +666,77 @@ vioconioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) return error2; return ENOTTY; } + +#ifdef VIOCON_CONSOLE + +static void +viocon_cnpollc(dev_t dev, int on) +{ + struct viocon_port *vp = dev2port(dev); + int s; + + KASSERT((bool)on != vp->vp_polling); + + s = spltty(); + vp->vp_polling = on; + vioconhwiflow(vp->vp_tty, on); + splx(s); +} + +static int +viocon_cngetc(dev_t dev) +{ + struct viocon_softc *sc = dev2sc(dev); + struct viocon_port *vp = dev2port(dev); + struct virtqueue *vq = vp->vp_rx; + struct virtio_softc *vsc = sc->sc_virtio; + int slot, len; + + KASSERT(vp->vp_polling); + while (vp->vp_polllen == 0) { + if (virtio_dequeue(vsc, vq, &slot, &len) == 0) { + KASSERTMSG(slot >= 0, "slot=%d", slot); + KASSERTMSG(slot < vq->vq_num, "slot=%d", slot); + KASSERTMSG(len > 0, "len=%d", len); + KASSERTMSG(len <= BUFSIZE, "len=%d", len); + bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap, + slot * BUFSIZE, BUFSIZE, BUS_DMASYNC_POSTREAD); + vp->vp_polllen = len; + vp->vp_pollpos = slot * BUFSIZE; + } + } + KASSERT(vp->vp_pollpos <= vq->vq_num * BUFSIZE); + vp->vp_polllen--; + return vp->vp_rx_buf[vp->vp_pollpos++]; +} + +static void +viocon_cnputc(dev_t dev, int c) +{ + struct viocon_softc *sc = dev2sc(dev); + struct viocon_port *vp = dev2port(dev); + struct virtqueue *vq = vp->vp_tx; + struct virtio_softc *vsc = sc->sc_virtio; + int slot; + int s, error; + + s = spltty(); + KERNEL_LOCK(1, NULL); + (void)viocon_tx_drain(vp, vq); + error = virtio_enqueue_prep(vsc, vq, &slot); + if (error == 0) { + error = virtio_enqueue_reserve(vsc, vq, slot, 1); + KASSERTMSG(error == 0, "error=%d", error); + vp->vp_tx_buf[slot * BUFSIZE] = c; + bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap, + vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1, + BUS_DMASYNC_PREWRITE); + virtio_enqueue_p(vsc, vq, slot, vp->vp_dmamap, + vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1, 1); + virtio_enqueue_commit(vsc, vq, slot, 1); + } + KERNEL_UNLOCK_ONE(NULL); + splx(s); +} + +#endif From c0e4f60771831f5077ae17c6c5b40213ddd5d093 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 14 Aug 2022 22:05:57 +0000 Subject: [PATCH 2/2] viocon(4): Take console if cn_tab->cn_dev is NODEV too. --- sys/dev/virtio/viocon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c index ab0c34f63ca2..11aa72e240da 100644 --- a/sys/dev/virtio/viocon.c +++ b/sys/dev/virtio/viocon.c @@ -248,7 +248,7 @@ viocon_attach(struct device *parent, struct device *self, void *aux) goto err; #ifdef VIOCON_CONSOLE - if (cn_tab == NULL) { + if (cn_tab == NULL || cn_tab->cn_dev == NODEV) { sc->sc_ports[0]->vp_cntab = (struct consdev) { .cn_pollc = viocon_cnpollc, .cn_getc = viocon_cngetc,