xref: /netbsd/sys/arch/sparc/sparc/openprom.c (revision bf9ec67e)
1 /*	$NetBSD: openprom.c,v 1.12 2001/12/04 00:05:07 darrenr Exp $ */
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *	This product includes software developed by the University of
14  *	California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  *
44  *	@(#)openprom.c	8.1 (Berkeley) 6/11/93
45  */
46 #include "opt_sparc_arch.h"
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/errno.h>
51 #include <sys/fcntl.h>
52 #include <sys/ioctl.h>
53 #include <sys/malloc.h>
54 #include <sys/conf.h>
55 #include <sys/device.h>
56 
57 #include <machine/bsd_openprom.h>
58 #include <machine/promlib.h>
59 #include <machine/openpromio.h>
60 #include <machine/conf.h>
61 
62 static	int lastnode;			/* speed hack */
63 extern	int optionsnode;		/* node ID of ROM's options */
64 
65 static int openpromcheckid __P((int, int));
66 static int openpromgetstr __P((int, char *, char **));
67 
68 int
69 openpromopen(dev, flags, mode, p)
70 	dev_t dev;
71 	int flags, mode;
72 	struct proc *p;
73 {
74 #if defined(SUN4)
75 	if (cputyp==CPU_SUN4)
76 		return (ENODEV);
77 #endif
78 
79 	return (0);
80 }
81 
82 int
83 openpromclose(dev, flags, mode, p)
84 	dev_t dev;
85 	int flags, mode;
86 	struct proc *p;
87 {
88 
89 	return (0);
90 }
91 
92 /*
93  * Verify target ID is valid (exists in the OPENPROM tree), as
94  * listed from node ID sid forward.
95  */
96 static int
97 openpromcheckid(sid, tid)
98 	int sid, tid;
99 {
100 
101 	for (; sid != 0; sid = nextsibling(sid))
102 		if (sid == tid || openpromcheckid(firstchild(sid), tid))
103 			return (1);
104 
105 	return (0);
106 }
107 
108 static int
109 openpromgetstr(len, user, cpp)
110 	int len;
111 	char *user, **cpp;
112 {
113 	int error;
114 	char *cp;
115 
116 	/* Reject obvious bogus requests */
117 	if ((u_int)len > (8 * 1024) - 1)
118 		return (ENAMETOOLONG);
119 
120 	*cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK);
121 	error = copyin(user, cp, len);
122 	cp[len] = '\0';
123 	return (error);
124 }
125 
126 int
127 openpromioctl(dev, cmd, data, flags, p)
128 	dev_t dev;
129 	u_long cmd;
130 	caddr_t data;
131 	int flags;
132 	struct proc *p;
133 {
134 	struct opiocdesc *op;
135 	int node, len, ok, error, s;
136 	char *name, *value, *nextprop;
137 
138 	/* All too easy... */
139 	if (cmd == OPIOCGETOPTNODE) {
140 		*(int *)data = optionsnode;
141 		return (0);
142 	}
143 
144 	/* Verify node id */
145 	op = (struct opiocdesc *)data;
146 	node = op->op_nodeid;
147 	if (node != 0 && node != lastnode && node != optionsnode) {
148 		/* Not an easy one, must search for it */
149 		s = splhigh();
150 		ok = openpromcheckid(findroot(), node);
151 		splx(s);
152 		if (!ok)
153 			return (EINVAL);
154 		lastnode = node;
155 	}
156 
157 	name = value = NULL;
158 	error = 0;
159 	switch (cmd) {
160 
161 	case OPIOCGET:
162 		if ((flags & FREAD) == 0)
163 			return (EBADF);
164 		if (node == 0)
165 			return (EINVAL);
166 		error = openpromgetstr(op->op_namelen, op->op_name, &name);
167 		if (error)
168 			break;
169 		s = splhigh();
170 		len = prom_proplen(node, name);
171 		splx(s);
172 		if (len > op->op_buflen) {
173 			error = ENOMEM;
174 			break;
175 		}
176 		op->op_buflen = len;
177 		/* -1 means no entry; 0 means no value */
178 		if (len <= 0)
179 			break;
180 		value = malloc(len, M_TEMP, M_WAITOK);
181 		s = splhigh();
182 		error = PROM_getprop(node, name, 1, &len, (void **)&value);
183 		splx(s);
184 		if (error != 0)
185 			break;
186 		error = copyout(value, op->op_buf, len);
187 		break;
188 
189 	case OPIOCSET:
190 		if ((flags & FWRITE) == 0)
191 			return (EBADF);
192 		if (node == 0)
193 			return (EINVAL);
194 		error = openpromgetstr(op->op_namelen, op->op_name, &name);
195 		if (error)
196 			break;
197 		error = openpromgetstr(op->op_buflen, op->op_buf, &value);
198 		if (error)
199 			break;
200 		s = splhigh();
201 		len = prom_setprop(node, name, value, op->op_buflen + 1);
202 		splx(s);
203 		if (len != op->op_buflen)
204 			error = EINVAL;
205 		break;
206 
207 	case OPIOCNEXTPROP:
208 		if ((flags & FREAD) == 0)
209 			return (EBADF);
210 		if (node == 0)
211 			return (EINVAL);
212 		error = openpromgetstr(op->op_namelen, op->op_name, &name);
213 		if (error)
214 			break;
215 		s = splhigh();
216 		nextprop = prom_nextprop(node, name);
217 		splx(s);
218 		len = strlen(nextprop);
219 		if (len > op->op_buflen)
220 			len = op->op_buflen;
221 		else
222 			op->op_buflen = len;
223 		error = copyout(nextprop, op->op_buf, len);
224 		break;
225 
226 	case OPIOCGETNEXT:
227 		if ((flags & FREAD) == 0)
228 			return (EBADF);
229 		s = splhigh();
230 		node = nextsibling(node);
231 		splx(s);
232 		*(int *)data = lastnode = node;
233 		break;
234 
235 	case OPIOCGETCHILD:
236 		if ((flags & FREAD) == 0)
237 			return (EBADF);
238 		if (node == 0)
239 			return (EINVAL);
240 		s = splhigh();
241 		node = firstchild(node);
242 		splx(s);
243 		*(int *)data = lastnode = node;
244 		break;
245 
246 	default:
247 		return (ENOTTY);
248 	}
249 
250 	if (name)
251 		free(name, M_TEMP);
252 	if (value)
253 		free(value, M_TEMP);
254 
255 	return (error);
256 }
257