summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-06-22 21:13:41 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-06-22 21:13:41 +0000
commit0b079107c7cba84791dceb493c8615f29f3edcd6 (patch)
treeb7c59d35bc31b98fa6edb14e0f3d283737448991
parent119511028ed9117c05ad46c3404d37ad1e4366e5 (diff)
Add opalcons(4), a driver for the OPAL console.
-rw-r--r--sys/arch/powerpc64/conf/GENERIC3
-rw-r--r--sys/arch/powerpc64/conf/files.powerpc648
-rw-r--r--sys/arch/powerpc64/dev/opal.c49
-rw-r--r--sys/arch/powerpc64/dev/opalcons.c248
-rw-r--r--sys/arch/powerpc64/include/conf.h2
-rw-r--r--sys/arch/powerpc64/powerpc64/conf.c4
6 files changed, 309 insertions, 5 deletions
diff --git a/sys/arch/powerpc64/conf/GENERIC b/sys/arch/powerpc64/conf/GENERIC
index 55ad10af9db..38b2d03b009 100644
--- a/sys/arch/powerpc64/conf/GENERIC
+++ b/sys/arch/powerpc64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.7 2020/06/14 19:09:59 kettenis Exp $
+# $OpenBSD: GENERIC,v 1.8 2020/06/22 21:13:40 kettenis Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -20,6 +20,7 @@ config bsd swap generic
mainbus0 at root
cpu0 at mainbus?
opal0 at fdt?
+opalcons* at fdt?
phb* at fdt?
pci* at phb?
xive* at fdt?
diff --git a/sys/arch/powerpc64/conf/files.powerpc64 b/sys/arch/powerpc64/conf/files.powerpc64
index e586dd0c1e2..233d5405627 100644
--- a/sys/arch/powerpc64/conf/files.powerpc64
+++ b/sys/arch/powerpc64/conf/files.powerpc64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.powerpc64,v 1.12 2020/06/13 22:58:42 kettenis Exp $
+# $OpenBSD: files.powerpc64,v 1.13 2020/06/22 21:13:40 kettenis Exp $
maxpartitions 16
maxusers 2 8 128
@@ -56,10 +56,14 @@ include "dev/ata/files.ata"
include "dev/mii/files.mii"
include "dev/pci/files.pci"
-device opal
+device opal: fdt
attach opal at fdt
file arch/powerpc64/dev/opal.c opal
+device opalcons
+attach opalcons at fdt
+file arch/powerpc64/dev/opalcons.c opalcons needs-flag
+
device phb: pcibus
attach phb at fdt
file arch/powerpc64/dev/phb.c phb
diff --git a/sys/arch/powerpc64/dev/opal.c b/sys/arch/powerpc64/dev/opal.c
index c86755da085..5e8f97fbed9 100644
--- a/sys/arch/powerpc64/dev/opal.c
+++ b/sys/arch/powerpc64/dev/opal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: opal.c,v 1.3 2020/06/19 22:20:08 kettenis Exp $ */
+/* $OpenBSD: opal.c,v 1.4 2020/06/22 21:13:40 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
*
@@ -44,6 +44,7 @@ struct cfdriver opal_cd = {
NULL, "opal", DV_DULL
};
+void opal_attach_node(struct opal_softc *, int);
int opal_gettime(struct todr_chip_handle *, struct timeval *);
int opal_settime(struct todr_chip_handle *, struct timeval *);
@@ -77,6 +78,52 @@ opal_attach(struct device *parent, struct device *self, void *aux)
sc->sc_todr.todr_gettime = opal_gettime;
sc->sc_todr.todr_settime = opal_settime;
todr_attach(&sc->sc_todr);
+
+ node = OF_getnodebyname(faa->fa_node, "consoles");
+ if (node) {
+ for (node = OF_child(node); node; node = OF_peer(node))
+ opal_attach_node(sc, node);
+ }
+}
+
+int
+opal_print(void *aux, const char *pnp)
+{
+ struct fdt_attach_args *faa = aux;
+ char name[32];
+
+ if (!pnp)
+ return (QUIET);
+
+ if (OF_getprop(faa->fa_node, "name", name, sizeof(name)) > 0) {
+ name[sizeof(name) - 1] = 0;
+ printf("\"%s\"", name);
+ } else
+ printf("node %u", faa->fa_node);
+
+ printf(" at %s", pnp);
+
+ return (UNCONF);
+}
+
+void
+opal_attach_node(struct opal_softc *sc, int node)
+{
+ struct fdt_attach_args faa;
+ char buf[32];
+
+ if (OF_getproplen(node, "compatible") <= 0)
+ return;
+
+ if (OF_getprop(node, "status", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "disabled") == 0)
+ return;
+
+ memset(&faa, 0, sizeof(faa));
+ faa.fa_name = "";
+ faa.fa_node = node;
+
+ config_found(&sc->sc_dev, &faa, opal_print);
}
int
diff --git a/sys/arch/powerpc64/dev/opalcons.c b/sys/arch/powerpc64/dev/opalcons.c
new file mode 100644
index 00000000000..889131d9da9
--- /dev/null
+++ b/sys/arch/powerpc64/dev/opalcons.c
@@ -0,0 +1,248 @@
+/* $OpenBSD: opalcons.c,v 1.1 2020/06/22 21:13:40 kettenis Exp $ */
+/*
+ * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+
+#include <machine/bus.h>
+#include <machine/conf.h>
+#include <machine/fdt.h>
+#include <machine/opal.h>
+
+#include <dev/cons.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+struct opalcons_softc {
+ struct device sc_dev;
+ uint64_t sc_reg;
+
+ struct tty *sc_tty;
+};
+
+int opalcons_match(struct device *, void *, void *);
+void opalcons_attach(struct device *, struct device *, void *);
+
+struct cfattach opalcons_ca = {
+ sizeof (struct opalcons_softc), opalcons_match, opalcons_attach
+};
+
+struct cfdriver opalcons_cd = {
+ NULL, "opalcons", DV_DULL
+};
+
+void opalconsstart(struct tty *);
+int opalconsparam(struct tty *, struct termios *);
+
+int
+opalcons_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "ibm,opal-console-raw");
+}
+
+void
+opalcons_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct opalcons_softc *sc = (struct opalcons_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ int maj;
+
+ sc->sc_reg = OF_getpropint(faa->fa_node, "reg", 0);
+
+ if (1) {
+ /* Locate the major number. */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == opalconsopen)
+ break;
+ cn_tab->cn_dev = makedev(maj, self->dv_unit);
+
+ printf(": console");
+ }
+
+ printf("\n");
+}
+
+struct opalcons_softc *
+opalcons_sc(dev_t dev)
+{
+ int unit = minor(dev);
+
+ if (unit >= opalcons_cd.cd_ndevs)
+ return NULL;
+ return (struct opalcons_softc *)opalcons_cd.cd_devs[unit];
+}
+
+void
+opalcons_putc(dev_t dev, int c)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ uint64_t len = 1;
+ char ch = c;
+
+ opal_console_write(sc->sc_reg, opal_phys(&len), opal_phys(&ch));
+}
+
+int
+opalconsopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ struct tty *tp;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ if (sc->sc_tty)
+ tp = sc->sc_tty;
+ else
+ tp = sc->sc_tty = ttymalloc(0);
+
+ tp->t_oproc = opalconsstart;
+ tp->t_param = opalconsparam;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ ttsetwater(tp);
+ } else if ((tp->t_state & TS_XCLUDE) && suser(p))
+ return EBUSY;
+ tp->t_state |= TS_CARR_ON;
+
+ return (*linesw[tp->t_line].l_open)(dev, tp, p);
+}
+
+int
+opalconsclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ struct tty *tp;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ tp = sc->sc_tty;
+ (*linesw[tp->t_line].l_close)(tp, flag, p);
+ ttyclose(tp);
+ return 0;
+}
+
+int
+opalconsread(dev_t dev, struct uio *uio, int flag)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ struct tty *tp;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ tp = sc->sc_tty;
+ return (*linesw[tp->t_line].l_read)(tp, uio, flag);
+}
+
+int
+opalconswrite(dev_t dev, struct uio *uio, int flag)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ struct tty *tp;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ tp = sc->sc_tty;
+ return (*linesw[tp->t_line].l_write)(tp, uio, flag);
+}
+
+int
+opalconsioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+ struct tty *tp;
+ int error;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ tp = sc->sc_tty;
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+
+ return ENOTTY;
+}
+
+void
+opalconsstart(struct tty *tp)
+{
+ int s;
+
+ s = spltty();
+ if (tp->t_state & (TS_TTSTOP | TS_BUSY)) {
+ splx(s);
+ return;
+ }
+ ttwakeupwr(tp);
+ tp->t_state |= TS_BUSY;
+ while (tp->t_outq.c_cc != 0)
+ opalcons_putc(tp->t_dev, getc(&tp->t_outq));
+ tp->t_state &= ~TS_BUSY;
+ splx(s);
+}
+
+int
+opalconsstop(struct tty *tp, int flag)
+{
+ int s;
+
+ s = spltty();
+ if (tp->t_state & TS_BUSY)
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ splx(s);
+ return 0;
+}
+
+struct tty *
+opalconstty(dev_t dev)
+{
+ struct opalcons_softc *sc = opalcons_sc(dev);
+
+ if (sc == NULL)
+ return NULL;
+
+ return sc->sc_tty;
+}
+
+int
+opalconsparam(struct tty *tp, struct termios *t)
+{
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return 0;
+}
diff --git a/sys/arch/powerpc64/include/conf.h b/sys/arch/powerpc64/include/conf.h
index 611ce00bb3c..c73e197f389 100644
--- a/sys/arch/powerpc64/include/conf.h
+++ b/sys/arch/powerpc64/include/conf.h
@@ -1 +1,3 @@
#include <sys/conf.h>
+
+cdev_decl(opalcons);
diff --git a/sys/arch/powerpc64/powerpc64/conf.c b/sys/arch/powerpc64/powerpc64/conf.c
index ffe7fff00a0..7b7edc1b836 100644
--- a/sys/arch/powerpc64/powerpc64/conf.c
+++ b/sys/arch/powerpc64/powerpc64/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.2 2020/06/07 09:34:20 kettenis Exp $ */
+/* $OpenBSD: conf.c,v 1.3 2020/06/22 21:13:40 kettenis Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@@ -46,6 +46,7 @@ struct bdevsw bdevsw[] =
int nblkdev = nitems(bdevsw);
#include "pty.h"
+#include "opalcons.h"
struct cdevsw cdevsw[] =
{
@@ -57,6 +58,7 @@ struct cdevsw cdevsw[] =
cdev_tty_init(NPTY,pts), /* 5: pseudo-tty slave */
cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */
cdev_ptm_init(NPTY,ptm), /* XX: pseudo-tty ptm device */
+ cdev_tty_init(NOPALCONS,opalcons), /* XX: OPAL console */
};
int nchrdev = nitems(cdevsw);