From 65b8a7ddc334ff14b450220a1219b56ca245c144 Mon Sep 17 00:00:00 2001
From: neirac <cneirabustos@gmail.com>
Date: Tue, 5 Oct 2021 18:02:55 +0000
Subject: [PATCH 2/2] wip for viocons

---
 usr/src/uts/common/io/viocons/viocons.c | 284 ++++++++++++++++++++++++
 usr/src/uts/common/io/viocons/viocons.h |  85 +++++++
 2 files changed, 369 insertions(+)
 create mode 100644 usr/src/uts/common/io/viocons/viocons.c
 create mode 100644 usr/src/uts/common/io/viocons/viocons.h

diff --git a/usr/src/uts/common/io/viocons/viocons.c b/usr/src/uts/common/io/viocons/viocons.c
new file mode 100644
index 0000000000..997a3d116c
--- /dev/null
+++ b/usr/src/uts/common/io/viocons/viocons.c
@@ -0,0 +1,284 @@
+/*
+* This file and its contents are supplied under the terms of the
+* Common Development and Distribution License ("CDDL"), version 1.0.
+* You may only use this file in accordance with the terms of version
+* 1.0 of the CDDL.
+*
+* A full copy of the text of the CDDL should have accompanied this
+* source.  A copy of the CDDL is also available via the Internet at
+* http://www.illumos.org/license/CDDL.
+*/
+
+/*
+* VIRTIO CONSOLE DRIVER
+*/
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/strsubr.h>
+#include <sys/kmem.h>
+#include <sys/conf.h>
+#include <sys/devops.h>
+#include <sys/ksynch.h>
+#include <sys/stat.h>
+#include <sys/modctl.h>
+#include <sys/debug.h>
+#include <sys/pci.h>
+#include <sys/ethernet.h>
+#include <sys/vlan.h>
+#include <sys/sysmacros.h>
+#include <sys/smbios.h>
+
+#include <sys/dlpi.h>
+#include <sys/taskq.h>
+
+#include <sys/pattr.h>
+#include <sys/strsun.h>
+
+#include <sys/random.h>
+#include <sys/containerof.h>
+#include <sys/stream.h>
+#include <inet/tcp.h>
+
+#include <sys/mac.h>
+#include <sys/mac_provider.h>
+#include <sys/mac_ether.h>
+
+
+#include "virtio.h"
+#include "viocons.h"
+
+
+static int viocons_quiesce(dev_info_t *);
+static int viocons_attach(dev_info_t *, ddi_attach_cmd_t);
+static int viocons_detach(dev_info_t *, ddi_detach_cmd_t);
+
+static const ddi_dma_attr_t vcons_dma_attr = {
+.dma_attr_version =		DMA_ATTR_V0,
+.dma_attr_addr_lo =		0x0000000000000000,
+.dma_attr_addr_hi =		0xFFFFFFFFFFFFFFFF,
+.dma_attr_count_max =		0x00000000FFFFFFFF,
+.dma_attr_align =		1,
+.dma_attr_burstsizes =		1,
+.dma_attr_minxfer =		1,
+.dma_attr_maxxfer =		0x00000000FFFFFFFF,
+.dma_attr_seg =			0x00000000FFFFFFFF,
+.dma_attr_sgllen =		1,
+.dma_attr_granular =		1,
+.dma_attr_flags =		0
+
+};
+
+
+static struct cb_ops viocons_cb_ops = {
+.cb_rev =			CB_REV,
+.cb_flag =			D_MP | D_NEW,
+
+.cb_open =			nulldev,
+.cb_close =			nulldev,
+.cb_strategy =			nodev,
+.cb_print =			nodev,
+.cb_dump =			nodev,
+.cb_read =			nodev,
+.cb_write =			nodev,
+.cb_ioctl =			nodev,
+.cb_devmap =			nodev,
+.cb_mmap =			nodev,
+.cb_segmap =			nodev,
+.cb_chpoll =			NULL,
+.cb_prop_op =			NULL,
+.cb_str =			NULL,
+.cb_aread =			nodev,
+.cb_awrite =			nodev,
+};
+
+static struct dev_ops viocons_dev_ops = {
+.devo_rev =			DEVO_REV,
+.devo_refcnt =			0,
+
+.devo_attach =			viocons_attach,
+.devo_detach =			viocons_detach,
+.devo_quiesce =			NULL,
+
+.devo_getinfo =			ddi_no_info,
+.devo_identify =		nulldev,
+.devo_probe =			nulldev,
+.devo_reset =			nodev,
+.devo_cb_ops =			NULL,
+.devo_bus_ops =			NULL,
+.devo_power =			NULL,
+};
+
+static struct modldrv viocons_modldrv = {
+.drv_modops =			&mod_driverops,
+.drv_linkinfo =			"VIRTIO console driver",
+.drv_dev_ops =			&viocons_dev_ops
+};
+
+static struct modlinkage viocons_modlinkage = {
+.ml_rev =			MODREV_1,
+.ml_linkage =			{ &viocons_modldrv, NULL }
+};
+static int
+viocons_quiesce(dev_info_t *dip)
+{
+viocons_t *viocons;
+
+if ((viocons = ddi_get_driver_private(dip)) == NULL) {
+	return (DDI_FAILURE);
+}
+
+return (virtio_quiesce(viocons->viocons_virtio));
+}
+
+/*
+* Virtqueue interrupt handlers
+*/
+
+static uint_t
+viocons_rx_handler(caddr_t arg0, caddr_t arg1)
+{
+	viocons_t *viocons = (viocons_t *)arg0;
+
+	dev_err(viocons->viocons_dip, CE_WARN, "hitting rx handler");
+	return (DDI_INTR_CLAIMED);
+}
+
+static uint_t
+viocons_tx_handler(caddr_t arg0, caddr_t arg1)
+{
+	viocons_t *viocons = (viocons_t *)arg0;
+	dev_err(viocons->viocons_dip, CE_WARN, "hitting tx handler");
+	return (DDI_INTR_CLAIMED);
+}
+
+
+static void
+viocons_tx_drain(viocons_t *viocons)
+{
+//TODO
+}
+
+static int
+viocons_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+	viocons_t *viocons;
+	virtio_t *vio;
+
+	if (cmd != DDI_ATTACH) {
+		return (DDI_FAILURE);
+	}
+
+	if ((vio = virtio_init(dip, VIRTIO_CONSOLE_WANTED_FEATURES, B_TRUE)) ==
+			NULL) {
+		dev_err(dip, CE_WARN, "failed to start Virtio init");
+		return (DDI_FAILURE);
+	}
+
+	viocons = kmem_zalloc(sizeof (*viocons), KM_SLEEP);
+	viocons->viocons_dip = dip;
+	viocons->viocons_virtio = vio;
+	ddi_set_driver_private(dip, viocons);
+
+	if ((viocons->viocons_rx_vq = virtio_queue_alloc(vio, VIRTIO_CONS_VIRTQ_RX_PORT,
+		 "p0rx", viocons_rx_handler, viocons, B_FALSE, 128)) == NULL) {
+		dev_err(dip, CE_WARN, "failed allocation rx vq");
+		goto fail;
+	}
+
+	if ((viocons->viocons_tx_vq = virtio_queue_alloc(vio, VIRTIO_CONS_VIRTQ_TX_PORT,
+		 "p0tx", viocons_tx_handler, viocons, B_FALSE, 128)) == NULL) {
+		dev_err(dip, CE_WARN, "failed allocation tx vq");
+		goto fail;
+	}
+	int cols = 999;
+	if (virtio_feature_present(vio, VIRTIO_CONSOLE_F_SIZE)) {
+		dev_err(dip, CE_WARN, "VIRTIO_CONSOLE_F_SIZE supported");
+	        cols  = virtio_dev_get16(vio,
+		    VIRTIO_VIOCONS_CONFIG_COLS);
+		dev_err(dip, CE_WARN, "cols %d", cols);
+
+	} else {
+		dev_err(dip, CE_WARN, "VIRTIO_CONSOLE_F_SIZE not supported?");
+		cols  = virtio_dev_get16(vio,
+		    VIRTIO_VIOCONS_CONFIG_COLS);
+		dev_err(dip, CE_WARN, "cols %d", cols);
+	}
+
+	virtio_dev_put32(vio,
+		VIRTIO_VIOCONS_CONFIG_EMERGE_WR , 'J');
+
+	if (virtio_init_complete(vio, 0) != DDI_SUCCESS) {
+		dev_err(dip, CE_WARN, "failed to complete Virtio init");
+		goto fail;
+	}
+
+	if (virtio_interrupts_enable(vio) != DDI_SUCCESS) {
+		dev_err(dip, CE_WARN, "failed to enable interrupts");
+		goto fail;
+	}
+
+	return (DDI_SUCCESS);
+
+fail:
+	if (vio != NULL) {
+		(void) virtio_fini(vio, B_TRUE);
+	}
+
+	kmem_free(viocons, sizeof (*viocons));
+	return (DDI_FAILURE);
+}
+
+static int
+viocons_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+	int r;
+        viocons_t *viocons;	
+
+	if (cmd != DDI_DETACH) {
+		return (DDI_FAILURE);
+	}
+
+	if ((viocons = ddi_get_driver_private(dip)) == NULL) {
+		return (DDI_FAILURE);
+	}
+
+	virtio_fini(viocons->viocons_virtio, B_FALSE);
+
+	if (viocons != NULL) 
+		kmem_free(viocons, sizeof (*viocons));
+
+	return (DDI_SUCCESS);
+}
+
+
+int
+_init(void)
+{
+	int ret;
+
+	if ((ret = mod_install(&viocons_modlinkage)) != DDI_SUCCESS) {
+	}
+
+	return (ret);
+}
+
+int
+_fini(void)
+{
+	int ret;
+
+	if ((ret = mod_remove(&viocons_modlinkage)) == DDI_SUCCESS) {
+	}
+
+	return (ret);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+	return (mod_info(&viocons_modlinkage, modinfop));
+}
diff --git a/usr/src/uts/common/io/viocons/viocons.h b/usr/src/uts/common/io/viocons/viocons.h
new file mode 100644
index 0000000000..1e44d2c17b
--- /dev/null
+++ b/usr/src/uts/common/io/viocons/viocons.h
@@ -0,0 +1,85 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * VIRTIO SERIAL CONSOLE DRIVER
+ */
+
+#ifndef _VIOCONS_H
+#define	_VIOCONS_H
+
+#include "virtio.h"
+#include "sys/tty.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * VIRTIO CONSOLE FEATURE BITS
+ */
+
+#define	VIRTIO_CONSOLE_F_SIZE		(1ULL << 0)
+#define	VIRTIO_CONSOLE_F_MULTIPORT	(1ULL << 1)
+#define	VIRTIO_CONSOLE_F_EMERG_WRITE 	(1ULL << 2)
+#define VIRTIO_CONSOLE_WANTED_FEATURES ( VIRTIO_CONSOLE_F_SIZE | \
+					 VIRTIO_CONSOLE_F_EMERG_WRITE )
+
+
+struct viocons_config {
+	uint16_t rows;
+	uint16_t cols;
+	uint32_t max_nr_ports;
+	uint32_t emerg_wr;	
+};
+
+/*
+ * VIRTIO CONSOLE CONFIGURATION REGISTERS
+ */
+#define	VIRTIO_VIOCONS_CONFIG_ROWS		0x00	/* 16 R   */
+#define	VIRTIO_VIOCONS_CONFIG_COLS		0x02	/* 16 R   */
+#define	VIRTIO_VIOCONS_CONFIG_MAX_PORTS		0x04	/* 32 R   */
+#define	VIRTIO_VIOCONS_CONFIG_EMERGE_WR		0x08	/* 32 R   */
+
+/*
+ * VIRTIO CONSOLE VIRTQUEUES INDEXES
+ */
+
+#define	VIRTIO_CONS_VIRTQ_RX_PORT			0
+#define	VIRTIO_CONS_VIRTQ_TX_PORT			1
+
+
+/*
+ * TYPE DEFINITIONS
+ */
+
+typedef struct viocons viocons_t;
+
+struct viocons {
+	dev_info_t			*viocons_dip;
+	virtio_t			*viocons_virtio;
+
+	virtio_queue_t			*viocons_rx_vq;
+	virtio_queue_t			*viocons_tx_vq;
+
+	kmutex_t			viocons_mutex;
+	kcondvar_t			viocons_cv;
+
+	virtio_dma_t			*viocons_dma;
+	virtio_chain_t			*viocons_chain;
+	ddi_dma_attr_t		 	viocons_dma_attr;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VIOCONS_H */
-- 
2.33.1

