date and time created 93/04/20 23:38:08 by torek
authorChris Torek <torek@ucbvax.Berkeley.EDU>
Wed, 21 Apr 1993 14:38:08 +0000 (06:38 -0800)
committerChris Torek <torek@ucbvax.Berkeley.EDU>
Wed, 21 Apr 1993 14:38:08 +0000 (06:38 -0800)
SCCS-vsn: sys/sparc/sparc/openprom.c 7.1

usr/src/sys/sparc/sparc/openprom.c [new file with mode: 0644]

diff --git a/usr/src/sys/sparc/sparc/openprom.c b/usr/src/sys/sparc/sparc/openprom.c
new file mode 100644 (file)
index 0000000..435ba4b
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1992 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)openprom.c  7.1 (Berkeley) %G%
+ *
+ * from: $Header: openprom.c,v 1.2 93/04/20 11:16:14 torek Exp $
+ */
+
+#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 <machine/bsd_openprom.h>
+#include <machine/openpromio.h>
+
+static int lastnode;                   /* speed hack */
+extern int optionsnode;                /* node ID of ROM's options */
+extern struct promvec *promvec;
+
+int
+openpromopen(dev, flags, mode)
+       dev_t dev;
+       int flags, mode;
+{
+
+       return (0);
+}
+
+int
+openpromclose(dev, flags, mode)
+       dev_t dev;
+       int flags, mode;
+{
+
+       return (0);
+}
+
+static int
+openpromcheckid(sid, tid)
+       register int sid, tid;
+{
+       register struct nodeops *no;
+
+       no = promvec->pv_nodeops;
+       while ((sid = no->no_nextnode(sid)) != 0)
+               if (sid == tid || openpromcheckid(no->no_child(sid), tid))
+                       return (1);
+
+       return (0);
+}
+
+static int
+openpromgetstr(len, user, cpp)
+       int len;
+       char *user, **cpp;
+{
+       register int error;
+       register 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, cmd, data, flags, p)
+       dev_t dev;
+       int cmd;
+       caddr_t data;
+       int flags;
+       struct proc *p;
+{
+       register struct opiocdesc *op;
+       register int node, len, ok, error, s;
+       char *name, *value, *nextprop;
+       register struct nodeops *no;
+
+       /* 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(0, node);
+               splx(s);
+               if (!ok)
+                       return (EINVAL);
+               lastnode = node;
+       }
+
+       name = value = NULL;
+       no = promvec->pv_nodeops;
+       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();
+               len = no->no_proplen(node, name);
+               splx(s);
+               if (len > op->op_buflen)
+                       len = op->op_buflen;
+               else
+                       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();
+               (void)no->no_getprop(node, name, value);
+               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();
+               len = no->no_setprop(node, name, 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;
+               s = splhigh();
+               nextprop = no->no_nextprop(node, name);
+               splx(s);
+               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 = no->no_nextnode(node);
+               splx(s);
+               *(int *)data = lastnode = node;
+               break;
+
+       case OPIOCGETCHILD:
+               if ((flags & FREAD) == 0)
+                       return (EBADF);
+               if (node == 0)
+                       return (EINVAL);
+               s = splhigh();
+               node = no->no_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);
+}