diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-06-22 21:13:41 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-06-22 21:13:41 +0000 |
commit | 0b079107c7cba84791dceb493c8615f29f3edcd6 (patch) | |
tree | b7c59d35bc31b98fa6edb14e0f3d283737448991 | |
parent | 119511028ed9117c05ad46c3404d37ad1e4366e5 (diff) |
Add opalcons(4), a driver for the OPAL console.
-rw-r--r-- | sys/arch/powerpc64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/powerpc64/conf/files.powerpc64 | 8 | ||||
-rw-r--r-- | sys/arch/powerpc64/dev/opal.c | 49 | ||||
-rw-r--r-- | sys/arch/powerpc64/dev/opalcons.c | 248 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/conf.h | 2 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/conf.c | 4 |
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); |