summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2007-11-12 19:23:27 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2007-11-12 19:23:27 +0000
commit7aa82accbdad6274d7668812ae027fb883c604e5 (patch)
tree2309ab37ce1d6115bd4800681bb19ff3de8390fb /sys/arch
parentbcf71d9542d48d30c2efd636c550eb0269823fcc (diff)
/dev/openprom
ok miod@, deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/macppc/conf/files.macppc3
-rw-r--r--sys/arch/macppc/include/conf.h11
-rw-r--r--sys/arch/macppc/include/openpromio.h57
-rw-r--r--sys/arch/macppc/macppc/conf.c3
-rw-r--r--sys/arch/macppc/macppc/openfirm.c60
-rw-r--r--sys/arch/macppc/macppc/openprom.c263
6 files changed, 393 insertions, 4 deletions
diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc
index 866b24fc712..3c38a3d14bb 100644
--- a/sys/arch/macppc/conf/files.macppc
+++ b/sys/arch/macppc/conf/files.macppc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.macppc,v 1.57 2007/10/14 17:29:04 kettenis Exp $
+# $OpenBSD: files.macppc,v 1.58 2007/11/12 19:23:26 kettenis Exp $
#
# macppc-specific configuration info
@@ -17,6 +17,7 @@ file arch/macppc/macppc/mem.c
file arch/macppc/macppc/dma.c
file arch/macppc/macppc/ofw_machdep.c
file arch/macppc/macppc/openfirm.c
+file arch/macppc/macppc/openprom.c
file dev/cninit.c
file arch/macppc/macppc/ofwreal.S
file arch/macppc/macppc/db_interface.c ddb
diff --git a/sys/arch/macppc/include/conf.h b/sys/arch/macppc/include/conf.h
index cbb0768028c..37acf78e894 100644
--- a/sys/arch/macppc/include/conf.h
+++ b/sys/arch/macppc/include/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.11 2005/12/31 21:22:34 miod Exp $ */
+/* $OpenBSD: conf.h,v 1.12 2007/11/12 19:23:26 kettenis Exp $ */
/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
/*
@@ -45,3 +45,12 @@ cdev_decl(mm);
cdev_decl(apm);
cdev_decl(zs);
+
+/* open, close, ioctl */
+#define cdev_openprom_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) nullop, 0, (dev_type_poll((*))) enodev, \
+ (dev_type_mmap((*))) enodev }
+
+cdev_decl(openprom);
diff --git a/sys/arch/macppc/include/openpromio.h b/sys/arch/macppc/include/openpromio.h
new file mode 100644
index 00000000000..fc60d81b2e5
--- /dev/null
+++ b/sys/arch/macppc/include/openpromio.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: openpromio.h,v 1.1 2007/11/12 19:23:26 kettenis Exp $ */
+/* $NetBSD: openpromio.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)openpromio.h 8.1 (Berkeley) 6/11/93
+ */
+
+struct opiocdesc {
+ int op_nodeid; /* passed or returned node id */
+ int op_namelen; /* length of op_name */
+ char *op_name; /* pointer to field name */
+ int op_buflen; /* length of op_buf (value-result) */
+ char *op_buf; /* pointer to field value */
+};
+
+#define OPIOCGET _IOWR('O', 1, struct opiocdesc) /* get openprom field */
+#define OPIOCSET _IOW('O', 2, struct opiocdesc) /* set openprom field */
+#define OPIOCNEXTPROP _IOWR('O', 3, struct opiocdesc) /* get next property */
+#define OPIOCGETOPTNODE _IOR('O', 4, int) /* get openprom field */
+#define OPIOCGETNEXT _IOWR('O', 5, int) /* get next node of node */
+#define OPIOCGETCHILD _IOWR('O', 6, int) /* get first child of node */
diff --git a/sys/arch/macppc/macppc/conf.c b/sys/arch/macppc/macppc/conf.c
index 2aab846bcee..bf64f90c367 100644
--- a/sys/arch/macppc/macppc/conf.c
+++ b/sys/arch/macppc/macppc/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.32 2007/07/24 10:18:24 mk Exp $ */
+/* $OpenBSD: conf.c,v 1.33 2007/11/12 19:23:26 kettenis Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -237,6 +237,7 @@ struct cdevsw cdevsw[] = {
cdev_gpio_init(NGPIO,gpio), /* 79: GPIO interface */
cdev_bio_init(NBIO,bio), /* 80: ioctl tunnel */
cdev_bthub_init(NBTHUB,bthub), /* 81: bthub */
+ cdev_openprom_init(1,openprom), /* 82: /dev/openprom */
};
int nchrdev = sizeof cdevsw / sizeof cdevsw[0];
diff --git a/sys/arch/macppc/macppc/openfirm.c b/sys/arch/macppc/macppc/openfirm.c
index 3d1837ffaf9..56f15981320 100644
--- a/sys/arch/macppc/macppc/openfirm.c
+++ b/sys/arch/macppc/macppc/openfirm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openfirm.c,v 1.9 2007/10/14 17:26:59 kettenis Exp $ */
+/* $OpenBSD: openfirm.c,v 1.10 2007/11/12 19:23:26 kettenis Exp $ */
/* $NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $ */
/*
@@ -164,6 +164,64 @@ OF_getprop(int handle, char *prop, void *buf, int buflen)
}
int
+OF_setprop(int handle, char *prop, const void *buf, int buflen)
+{
+ static struct {
+ char *name;
+ int nargs;
+ int nreturns;
+ int phandle;
+ char *prop;
+ void *buf;
+ int buflen;
+ int size;
+ } args = {
+ "setprop",
+ 4,
+ 1,
+ };
+
+ ofw_stack();
+ if (buflen > NBPG)
+ return -1;
+ args.phandle = handle;
+ args.prop = prop;
+ ofbcopy(buf, OF_buf, buflen);
+ args.buf = OF_buf;
+ args.buflen = buflen;
+ if (openfirmware(&args) == -1)
+ return -1;
+ return args.size;
+}
+
+int
+OF_nextprop(int handle, char *prop, void *nextprop)
+{
+ static struct {
+ const char *name;
+ int nargs;
+ int nreturns;
+ int phandle;
+ const char *prop;
+ char *buf;
+ int flag;
+ } args = {
+ "nextprop",
+ 3,
+ 1,
+ };
+
+ ofw_stack();
+ args.phandle = handle;
+ args.prop = prop;
+ args.buf = OF_buf;
+ if (openfirmware(&args) == -1)
+ return -1;
+ strlcpy(nextprop, OF_buf, 32);
+ return args.flag;
+}
+
+int
OF_interpret(char *cmd, int nreturns, ...)
{
va_list ap;
diff --git a/sys/arch/macppc/macppc/openprom.c b/sys/arch/macppc/macppc/openprom.c
new file mode 100644
index 00000000000..4214edc0ac6
--- /dev/null
+++ b/sys/arch/macppc/macppc/openprom.c
@@ -0,0 +1,263 @@
+/* $OpenBSD: openprom.c,v 1.1 2007/11/12 19:23:26 kettenis Exp $ */
+/* $NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)openprom.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/openpromio.h>
+#include <machine/autoconf.h>
+#include <machine/conf.h>
+
+#include <dev/ofw/openfirm.h>
+
+#define OPROMMAXPARAM 32
+
+static int lastnode; /* speed hack */
+static int optionsnode; /* node ID of ROM's options */
+
+static int openpromcheckid(int, int);
+static int openpromgetstr(int, char *, char **);
+
+int
+openpromopen(dev_t dev, int flags, int mode, struct proc *p)
+{
+ return (0);
+}
+
+int
+openpromclose(dev_t dev, int flags, int mode, struct proc *p)
+{
+ return (0);
+}
+
+/*
+ * Verify target ID is valid (exists in the OPENPROM tree), as
+ * listed from node ID sid forward.
+ */
+int
+openpromcheckid(int sid, int tid)
+{
+ for (; sid != 0; sid = OF_peer(sid))
+ if (sid == tid || openpromcheckid(OF_child(sid), tid))
+ return (1);
+
+ return (0);
+}
+
+int
+openpromgetstr(int len, char *user, char **cpp)
+{
+ int error;
+ char *cp;
+
+ /* Reject obvious bogus requests */
+ if ((u_int)len > (8 * 1024) - 1)
+ return (ENAMETOOLONG);
+
+ *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK);
+ error = copyin(user, cp, len);
+ cp[len] = '\0';
+ return (error);
+}
+
+int
+openpromioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ struct opiocdesc *op;
+ int node, len, ok, error, s;
+ char *name, *value, *nextprop;
+ static char buf[32]; /* XXX */
+
+ if (optionsnode == 0) {
+ s = splhigh();
+ optionsnode = OF_getnodebyname(0, "options");
+ splx(s);
+ }
+
+ /* All too easy... */
+ if (cmd == OPIOCGETOPTNODE) {
+ *(int *)data = optionsnode;
+ return (0);
+ }
+
+ /* Verify node id */
+ op = (struct opiocdesc *)data;
+ node = op->op_nodeid;
+ if (node != 0 && node != lastnode && node != optionsnode) {
+ /* Not an easy one, must search for it */
+ s = splhigh();
+ ok = openpromcheckid(OF_peer(0), node);
+ splx(s);
+ if (!ok)
+ return (EINVAL);
+ lastnode = node;
+ }
+
+ name = value = NULL;
+ error = 0;
+ switch (cmd) {
+
+ case OPIOCGET:
+ if ((flags & FREAD) == 0)
+ return (EBADF);
+ if (node == 0)
+ return (EINVAL);
+ error = openpromgetstr(op->op_namelen, op->op_name, &name);
+ if (error)
+ break;
+ s = splhigh();
+ strlcpy(buf, name, 32); /* XXX */
+ len = OF_getproplen(node, buf);
+ splx(s);
+ if (len > op->op_buflen) {
+ error = ENOMEM;
+ break;
+ }
+ op->op_buflen = len;
+ /* -1 means no entry; 0 means no value */
+ if (len <= 0)
+ break;
+ value = malloc(len, M_TEMP, M_WAITOK);
+ s = splhigh();
+ strlcpy(buf, name, 32); /* XXX */
+ OF_getprop(node, buf, value, len);
+ splx(s);
+ error = copyout(value, op->op_buf, len);
+ break;
+
+ case OPIOCSET:
+ if ((flags & FWRITE) == 0)
+ return (EBADF);
+ if (node == 0)
+ return (EINVAL);
+ error = openpromgetstr(op->op_namelen, op->op_name, &name);
+ if (error)
+ break;
+ error = openpromgetstr(op->op_buflen, op->op_buf, &value);
+ if (error)
+ break;
+ s = splhigh();
+ strlcpy(buf, name, 32); /* XXX */
+ len = OF_setprop(node, buf, value, op->op_buflen + 1);
+ splx(s);
+ if (len != op->op_buflen)
+ error = EINVAL;
+ break;
+
+ case OPIOCNEXTPROP:
+ if ((flags & FREAD) == 0)
+ return (EBADF);
+ if (node == 0)
+ return (EINVAL);
+ error = openpromgetstr(op->op_namelen, op->op_name, &name);
+ if (error)
+ break;
+ if (op->op_buflen <= 0) {
+ error = ENAMETOOLONG;
+ break;
+ }
+ value = nextprop = malloc(OPROMMAXPARAM, M_TEMP, M_WAITOK);
+ if (nextprop == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ s = splhigh();
+ strlcpy(buf, name, 32); /* XXX */
+ error = OF_nextprop(node, buf, nextprop);
+ splx(s);
+ if (error == -1) {
+ error = EINVAL;
+ break;
+ }
+ if (error == 0) {
+ char nul = '\0';
+
+ op->op_buflen = 0;
+ error = copyout(&nul, op->op_buf, sizeof(char));
+ break;
+ }
+ len = strlen(nextprop);
+ if (len > op->op_buflen)
+ len = op->op_buflen;
+ else
+ op->op_buflen = len;
+ error = copyout(nextprop, op->op_buf, len);
+ break;
+
+ case OPIOCGETNEXT:
+ if ((flags & FREAD) == 0)
+ return (EBADF);
+ s = splhigh();
+ node = OF_peer(node);
+ splx(s);
+ *(int *)data = lastnode = node;
+ break;
+
+ case OPIOCGETCHILD:
+ if ((flags & FREAD) == 0)
+ return (EBADF);
+ if (node == 0)
+ return (EINVAL);
+ s = splhigh();
+ node = OF_child(node);
+ splx(s);
+ *(int *)data = lastnode = node;
+ break;
+
+ default:
+ return (ENOTTY);
+ }
+
+ if (name)
+ free(name, M_TEMP);
+ if (value)
+ free(value, M_TEMP);
+
+ return (error);
+}