xref: /titanic_52/usr/src/lib/efcode/engine/properties.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <string.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <fcode/private.h>
34*7c478bd9Sstevel@tonic-gate #include <fcode/log.h>
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate void
37*7c478bd9Sstevel@tonic-gate create_prop(fcode_env_t *env, char *name)
38*7c478bd9Sstevel@tonic-gate {
39*7c478bd9Sstevel@tonic-gate 	push_a_string(env, name);
40*7c478bd9Sstevel@tonic-gate 	property(env);
41*7c478bd9Sstevel@tonic-gate }
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate void
44*7c478bd9Sstevel@tonic-gate create_int_prop(fcode_env_t *env, char *name, int val)
45*7c478bd9Sstevel@tonic-gate {
46*7c478bd9Sstevel@tonic-gate 	PUSH(DS, val);
47*7c478bd9Sstevel@tonic-gate 	encode_int(env);
48*7c478bd9Sstevel@tonic-gate 	create_prop(env, name);
49*7c478bd9Sstevel@tonic-gate }
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate void
52*7c478bd9Sstevel@tonic-gate create_string_prop(fcode_env_t *env, char *name, char *val)
53*7c478bd9Sstevel@tonic-gate {
54*7c478bd9Sstevel@tonic-gate 	push_a_string(env, val);
55*7c478bd9Sstevel@tonic-gate 	encode_string(env);
56*7c478bd9Sstevel@tonic-gate 	create_prop(env, name);
57*7c478bd9Sstevel@tonic-gate }
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static int
60*7c478bd9Sstevel@tonic-gate addr_cmp(void *a, void *b)
61*7c478bd9Sstevel@tonic-gate {
62*7c478bd9Sstevel@tonic-gate 	return ((uchar_t *)a == (uchar_t *)b);
63*7c478bd9Sstevel@tonic-gate }
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static void *
66*7c478bd9Sstevel@tonic-gate add_property_buffer(fcode_env_t *env, int len)
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	void *data = MALLOC(len+1);
69*7c478bd9Sstevel@tonic-gate 	return (add_resource(&env->propbufs, data, addr_cmp));
70*7c478bd9Sstevel@tonic-gate }
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate static void
73*7c478bd9Sstevel@tonic-gate free_property_buffer(fcode_env_t *env, void *buffer)
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate 	free_resource(&env->propbufs, buffer, addr_cmp);
76*7c478bd9Sstevel@tonic-gate 	FREE(buffer);
77*7c478bd9Sstevel@tonic-gate }
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /*
80*7c478bd9Sstevel@tonic-gate  * Golden Rule:
81*7c478bd9Sstevel@tonic-gate  * DO NOT cache the value of the head of the property list *before*
82*7c478bd9Sstevel@tonic-gate  * looking up a property.
83*7c478bd9Sstevel@tonic-gate  * This routine is also responsible for purging dead properties
84*7c478bd9Sstevel@tonic-gate  * and that *can* affect the head pointer.
85*7c478bd9Sstevel@tonic-gate  * you have been warned!
86*7c478bd9Sstevel@tonic-gate  */
87*7c478bd9Sstevel@tonic-gate prop_t *
88*7c478bd9Sstevel@tonic-gate find_property(device_t *d, char *name)
89*7c478bd9Sstevel@tonic-gate {
90*7c478bd9Sstevel@tonic-gate 	prop_t *p = d->properties, *prev;
91*7c478bd9Sstevel@tonic-gate 	prop_t *found = NULL;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	prev = NULL;
94*7c478bd9Sstevel@tonic-gate 	while (p && !found) {
95*7c478bd9Sstevel@tonic-gate 		if (p->name) {
96*7c478bd9Sstevel@tonic-gate 			if (strcmp(name, p->name) == 0) {
97*7c478bd9Sstevel@tonic-gate 				found = p;
98*7c478bd9Sstevel@tonic-gate 			}
99*7c478bd9Sstevel@tonic-gate 			prev = p;
100*7c478bd9Sstevel@tonic-gate 			p = p->next;
101*7c478bd9Sstevel@tonic-gate 		} else {
102*7c478bd9Sstevel@tonic-gate 			prop_t *dead;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 			if (prev)
105*7c478bd9Sstevel@tonic-gate 				prev->next = p->next;
106*7c478bd9Sstevel@tonic-gate 			else {
107*7c478bd9Sstevel@tonic-gate 				/* last prop in chain */
108*7c478bd9Sstevel@tonic-gate 				d->properties = p->next;
109*7c478bd9Sstevel@tonic-gate 			}
110*7c478bd9Sstevel@tonic-gate 			dead = p;
111*7c478bd9Sstevel@tonic-gate 			p = p->next;
112*7c478bd9Sstevel@tonic-gate 			FREE(dead->name);
113*7c478bd9Sstevel@tonic-gate 			FREE(dead->data);
114*7c478bd9Sstevel@tonic-gate 			FREE(dead);
115*7c478bd9Sstevel@tonic-gate 		}
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 	return (found);
118*7c478bd9Sstevel@tonic-gate }
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate static prop_t *
121*7c478bd9Sstevel@tonic-gate stack_find_property(fcode_env_t *env, device_t *d)
122*7c478bd9Sstevel@tonic-gate {
123*7c478bd9Sstevel@tonic-gate 	char *propname;
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	propname = pop_a_string(env, NULL);
126*7c478bd9Sstevel@tonic-gate 	return (find_property(d, propname));
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate void
130*7c478bd9Sstevel@tonic-gate property(fcode_env_t *env)
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate 	int datalen;
133*7c478bd9Sstevel@tonic-gate 	char *propname, *srcptr;
134*7c478bd9Sstevel@tonic-gate 	prop_t *p;
135*7c478bd9Sstevel@tonic-gate 	device_t *d;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 4, "property");
138*7c478bd9Sstevel@tonic-gate 	if (MYSELF) {
139*7c478bd9Sstevel@tonic-gate 		d = MYSELF->device;
140*7c478bd9Sstevel@tonic-gate 	} else {
141*7c478bd9Sstevel@tonic-gate 		d = env->current_device;
142*7c478bd9Sstevel@tonic-gate 		if (!d) {
143*7c478bd9Sstevel@tonic-gate 			void *buffer;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 			two_drop(env);
146*7c478bd9Sstevel@tonic-gate 			if ((buffer = pop_a_string(env, NULL)) != NULL)
147*7c478bd9Sstevel@tonic-gate 				free_property_buffer(env, buffer);
148*7c478bd9Sstevel@tonic-gate 			return;
149*7c478bd9Sstevel@tonic-gate 		}
150*7c478bd9Sstevel@tonic-gate 	}
151*7c478bd9Sstevel@tonic-gate 	propname = pop_a_string(env, NULL);
152*7c478bd9Sstevel@tonic-gate 	p = find_property(d, propname);
153*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
154*7c478bd9Sstevel@tonic-gate 		p = MALLOC(sizeof (prop_t));
155*7c478bd9Sstevel@tonic-gate 		p->next = d->properties;
156*7c478bd9Sstevel@tonic-gate 		d->properties = p;
157*7c478bd9Sstevel@tonic-gate 		p->name = STRDUP(propname);
158*7c478bd9Sstevel@tonic-gate 	} else if (p->data)
159*7c478bd9Sstevel@tonic-gate 		FREE(p->data);	/* release old resources */
160*7c478bd9Sstevel@tonic-gate 	srcptr = pop_a_string(env, &datalen);
161*7c478bd9Sstevel@tonic-gate 	p->data = MALLOC(datalen+1);
162*7c478bd9Sstevel@tonic-gate 	p->size = datalen;
163*7c478bd9Sstevel@tonic-gate 	memcpy(p->data, srcptr, datalen);
164*7c478bd9Sstevel@tonic-gate 	p->data[datalen] = 0;
165*7c478bd9Sstevel@tonic-gate 	if (srcptr)
166*7c478bd9Sstevel@tonic-gate 		free_property_buffer(env, srcptr);
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate prop_t *
170*7c478bd9Sstevel@tonic-gate lookup_package_property(fcode_env_t *env, char *propname, device_t *d)
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	prop_t *p;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	p = find_property(d, propname);
175*7c478bd9Sstevel@tonic-gate 	if (p) {
176*7c478bd9Sstevel@tonic-gate 		return (p);
177*7c478bd9Sstevel@tonic-gate 	}
178*7c478bd9Sstevel@tonic-gate 	if (d->vectors.get_package_prop) {
179*7c478bd9Sstevel@tonic-gate 		static prop_t sp;
180*7c478bd9Sstevel@tonic-gate 		fstack_t fail, n;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 		/* recreate the FORTH environment for the remote call */
183*7c478bd9Sstevel@tonic-gate 		push_a_string(env, propname);
184*7c478bd9Sstevel@tonic-gate 		REVERT_PHANDLE(env, n, d);
185*7c478bd9Sstevel@tonic-gate 		PUSH(DS, n);
186*7c478bd9Sstevel@tonic-gate 		d->vectors.get_package_prop(env);
187*7c478bd9Sstevel@tonic-gate 		fail = POP(DS);
188*7c478bd9Sstevel@tonic-gate 		if (fail)
189*7c478bd9Sstevel@tonic-gate 			return (NULL);
190*7c478bd9Sstevel@tonic-gate 		sp.size = POP(DS);
191*7c478bd9Sstevel@tonic-gate 		sp.data = (uchar_t *)POP(DS);
192*7c478bd9Sstevel@tonic-gate 		sp.name = propname;
193*7c478bd9Sstevel@tonic-gate 		sp.next = NULL;
194*7c478bd9Sstevel@tonic-gate 		return (&sp);
195*7c478bd9Sstevel@tonic-gate 	}
196*7c478bd9Sstevel@tonic-gate 	return (NULL);
197*7c478bd9Sstevel@tonic-gate }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate void
200*7c478bd9Sstevel@tonic-gate get_package_property(fcode_env_t *env)
201*7c478bd9Sstevel@tonic-gate {
202*7c478bd9Sstevel@tonic-gate 	prop_t *p;
203*7c478bd9Sstevel@tonic-gate 	device_t *d;
204*7c478bd9Sstevel@tonic-gate 	char *propname;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "get-package-property");
207*7c478bd9Sstevel@tonic-gate 	CONVERT_PHANDLE(env, d, POP(DS));
208*7c478bd9Sstevel@tonic-gate 	propname = pop_a_string(env, NULL);
209*7c478bd9Sstevel@tonic-gate 	p = lookup_package_property(env, propname, d);
210*7c478bd9Sstevel@tonic-gate 	if (p) {
211*7c478bd9Sstevel@tonic-gate 		PUSH(DS, (fstack_t)p->data);
212*7c478bd9Sstevel@tonic-gate 		PUSH(DS, p->size);
213*7c478bd9Sstevel@tonic-gate 		PUSH(DS, FALSE);
214*7c478bd9Sstevel@tonic-gate 	} else
215*7c478bd9Sstevel@tonic-gate 		PUSH(DS, TRUE);
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate void
219*7c478bd9Sstevel@tonic-gate get_inherited_prop(fcode_env_t *env)
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate 	instance_t *ih;
222*7c478bd9Sstevel@tonic-gate 	device_t *dev;
223*7c478bd9Sstevel@tonic-gate 	prop_t *prop;
224*7c478bd9Sstevel@tonic-gate 	char *pname;
225*7c478bd9Sstevel@tonic-gate 	int plen;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	/*
228*7c478bd9Sstevel@tonic-gate 	 * First, we look thru the in-memory device tree for the property.
229*7c478bd9Sstevel@tonic-gate 	 * If we don't find it, we call get_inherited_prop, which "knows" it's
230*7c478bd9Sstevel@tonic-gate 	 * not going to find the property below the attachment point.
231*7c478bd9Sstevel@tonic-gate 	 */
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "get-inherited-property");
234*7c478bd9Sstevel@tonic-gate 	pname = pop_a_string(env, &plen);
235*7c478bd9Sstevel@tonic-gate 	ih = MYSELF;
236*7c478bd9Sstevel@tonic-gate 	if (ih) {
237*7c478bd9Sstevel@tonic-gate 		for (; ih; ih = ih->parent) {
238*7c478bd9Sstevel@tonic-gate 			dev = ih->device;
239*7c478bd9Sstevel@tonic-gate 			prop = find_property(dev, pname);
240*7c478bd9Sstevel@tonic-gate 			if (prop) {
241*7c478bd9Sstevel@tonic-gate 				PUSH(DS, (fstack_t)prop->data);
242*7c478bd9Sstevel@tonic-gate 				PUSH(DS, (fstack_t)prop->size);
243*7c478bd9Sstevel@tonic-gate 				PUSH(DS, FALSE);
244*7c478bd9Sstevel@tonic-gate 				return;
245*7c478bd9Sstevel@tonic-gate 			}
246*7c478bd9Sstevel@tonic-gate 		}
247*7c478bd9Sstevel@tonic-gate 		if (dev->vectors.get_inherited_prop) {
248*7c478bd9Sstevel@tonic-gate 			push_a_string(env, pname);
249*7c478bd9Sstevel@tonic-gate 			dev->vectors.get_inherited_prop(env);
250*7c478bd9Sstevel@tonic-gate 			return;
251*7c478bd9Sstevel@tonic-gate 		}
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 	PUSH(DS, TRUE);
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate void
257*7c478bd9Sstevel@tonic-gate delete_property(fcode_env_t *env)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "delete-property");
260*7c478bd9Sstevel@tonic-gate 	if (MYSELF) {
261*7c478bd9Sstevel@tonic-gate 		prop_t *p;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 		p = stack_find_property(env, MYSELF->device);
264*7c478bd9Sstevel@tonic-gate 		if (p) {
265*7c478bd9Sstevel@tonic-gate 			/*
266*7c478bd9Sstevel@tonic-gate 			 * write the name as NULL; the space will be free'd
267*7c478bd9Sstevel@tonic-gate 			 * the next time a property lookup passes this node
268*7c478bd9Sstevel@tonic-gate 			 */
269*7c478bd9Sstevel@tonic-gate 			p->name = NULL;
270*7c478bd9Sstevel@tonic-gate 		}
271*7c478bd9Sstevel@tonic-gate 	} else {
272*7c478bd9Sstevel@tonic-gate 		two_drop(env);
273*7c478bd9Sstevel@tonic-gate 	}
274*7c478bd9Sstevel@tonic-gate }
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate void
277*7c478bd9Sstevel@tonic-gate get_my_property(fcode_env_t *env)
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "get-my-property");
280*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)MYSELF);
281*7c478bd9Sstevel@tonic-gate 	ihandle_to_phandle(env);
282*7c478bd9Sstevel@tonic-gate 	get_package_property(env);
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate void
286*7c478bd9Sstevel@tonic-gate encode_string(fcode_env_t *env)
287*7c478bd9Sstevel@tonic-gate {
288*7c478bd9Sstevel@tonic-gate 	char *str;
289*7c478bd9Sstevel@tonic-gate 	char *prop;
290*7c478bd9Sstevel@tonic-gate 	int len;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "encode-string");
293*7c478bd9Sstevel@tonic-gate 	str = pop_a_string(env, &len);
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	prop = add_property_buffer(env, len);
296*7c478bd9Sstevel@tonic-gate 	memcpy(prop, str, len);
297*7c478bd9Sstevel@tonic-gate 	prop[len] = 0;
298*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)prop);
299*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len + 1);
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate void
303*7c478bd9Sstevel@tonic-gate encode_int(fcode_env_t *env)
304*7c478bd9Sstevel@tonic-gate {
305*7c478bd9Sstevel@tonic-gate 	uchar_t *ptr;
306*7c478bd9Sstevel@tonic-gate 	uint32_t p;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "encode-int");
309*7c478bd9Sstevel@tonic-gate 	p = POP(DS);
310*7c478bd9Sstevel@tonic-gate 	ptr = add_property_buffer(env, sizeof (uint32_t));
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	memcpy(ptr, (char *)&p, sizeof (uint32_t));
313*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)ptr);
314*7c478bd9Sstevel@tonic-gate 	PUSH(DS, sizeof (uint32_t));
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate void
318*7c478bd9Sstevel@tonic-gate encode_phys(fcode_env_t *env)
319*7c478bd9Sstevel@tonic-gate {
320*7c478bd9Sstevel@tonic-gate 	uint_t ncells;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	ncells = get_number_of_parent_address_cells(env);
323*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, ncells, "encode-phys");
324*7c478bd9Sstevel@tonic-gate 	encode_int(env);
325*7c478bd9Sstevel@tonic-gate 	while (--ncells) {
326*7c478bd9Sstevel@tonic-gate 		rot(env);
327*7c478bd9Sstevel@tonic-gate 		encode_int(env);
328*7c478bd9Sstevel@tonic-gate 		encode_plus(env);
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate }
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate static fstack_t
333*7c478bd9Sstevel@tonic-gate get_decoded_int(uchar_t *dp)
334*7c478bd9Sstevel@tonic-gate {
335*7c478bd9Sstevel@tonic-gate 	uint32_t d;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	memcpy((char *)&d, dp, sizeof (uint32_t));
338*7c478bd9Sstevel@tonic-gate 	return (d);
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate int
342*7c478bd9Sstevel@tonic-gate get_default_intprop(fcode_env_t *env, char *name, device_t *d, int def)
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 	prop_t *p;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	if (!d)		/* Kludge for testing */
347*7c478bd9Sstevel@tonic-gate 		return (def);
348*7c478bd9Sstevel@tonic-gate 	p = lookup_package_property(env, name, d);
349*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
350*7c478bd9Sstevel@tonic-gate 		return (def);
351*7c478bd9Sstevel@tonic-gate 	return (get_decoded_int(p->data));
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate int
355*7c478bd9Sstevel@tonic-gate get_num_addr_cells(fcode_env_t *env, device_t *d)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	return (get_default_intprop(env, "#address-cells", d, 2));
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate int
361*7c478bd9Sstevel@tonic-gate get_num_size_cells(fcode_env_t *env, device_t *d)
362*7c478bd9Sstevel@tonic-gate {
363*7c478bd9Sstevel@tonic-gate 	return (get_default_intprop(env, "#size-cells", d, 1));
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate void
367*7c478bd9Sstevel@tonic-gate decode_phys(fcode_env_t *env)
368*7c478bd9Sstevel@tonic-gate {
369*7c478bd9Sstevel@tonic-gate 	char *ptr;
370*7c478bd9Sstevel@tonic-gate 	int len;
371*7c478bd9Sstevel@tonic-gate 	int adr_cells;
372*7c478bd9Sstevel@tonic-gate 	int offset;
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "decode-phys");
375*7c478bd9Sstevel@tonic-gate 	ptr = pop_a_string(env, &len);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	adr_cells = get_num_addr_cells(env, env->current_device->parent);
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	offset = sizeof (uint32_t) * adr_cells;
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)(ptr + offset));
382*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len + offset);
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	while (adr_cells--) {
385*7c478bd9Sstevel@tonic-gate 		fstack_t d;
386*7c478bd9Sstevel@tonic-gate 		offset -= sizeof (uint32_t);
387*7c478bd9Sstevel@tonic-gate 		d = get_decoded_int((uchar_t *)(ptr + offset));
388*7c478bd9Sstevel@tonic-gate 		PUSH(DS, d);
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate }
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate /*
393*7c478bd9Sstevel@tonic-gate  * 'reg' Fcode 0x116
394*7c478bd9Sstevel@tonic-gate  */
395*7c478bd9Sstevel@tonic-gate void
396*7c478bd9Sstevel@tonic-gate reg_prop(fcode_env_t *env)
397*7c478bd9Sstevel@tonic-gate {
398*7c478bd9Sstevel@tonic-gate 	fstack_t size;
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "reg");
401*7c478bd9Sstevel@tonic-gate 	size = POP(DS);
402*7c478bd9Sstevel@tonic-gate 	encode_phys(env);
403*7c478bd9Sstevel@tonic-gate 	PUSH(DS, size);
404*7c478bd9Sstevel@tonic-gate 	encode_int(env);
405*7c478bd9Sstevel@tonic-gate 	encode_plus(env);
406*7c478bd9Sstevel@tonic-gate 	create_prop(env, "reg");
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate void
410*7c478bd9Sstevel@tonic-gate encode_bytes(fcode_env_t *env)
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate 	char *str;
413*7c478bd9Sstevel@tonic-gate 	char *prop;
414*7c478bd9Sstevel@tonic-gate 	int len;
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "encode-bytes");
417*7c478bd9Sstevel@tonic-gate 	str = pop_a_string(env, &len);
418*7c478bd9Sstevel@tonic-gate 	prop = add_property_buffer(env, len);
419*7c478bd9Sstevel@tonic-gate 	memcpy(prop, str, len);
420*7c478bd9Sstevel@tonic-gate 	prop[len] = 0;
421*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)prop);
422*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len);
423*7c478bd9Sstevel@tonic-gate }
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate void
426*7c478bd9Sstevel@tonic-gate decode_int(fcode_env_t *env)
427*7c478bd9Sstevel@tonic-gate {
428*7c478bd9Sstevel@tonic-gate 	char *dp;
429*7c478bd9Sstevel@tonic-gate 	fstack_t d;
430*7c478bd9Sstevel@tonic-gate 	int len;
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "decode-int");
433*7c478bd9Sstevel@tonic-gate 	dp = pop_a_string(env, &len);
434*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)(dp + sizeof (uint32_t)));
435*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len - sizeof (uint32_t));
436*7c478bd9Sstevel@tonic-gate 	d = get_decoded_int((uchar_t *)dp);
437*7c478bd9Sstevel@tonic-gate 	PUSH(DS, d);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate void
441*7c478bd9Sstevel@tonic-gate decode_string(fcode_env_t *env)
442*7c478bd9Sstevel@tonic-gate {
443*7c478bd9Sstevel@tonic-gate 	int plen, len;
444*7c478bd9Sstevel@tonic-gate 	char *dp;
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "decode-string");
447*7c478bd9Sstevel@tonic-gate 	dp = pop_a_string(env, &plen);
448*7c478bd9Sstevel@tonic-gate 	len = strlen(dp) + 1;
449*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)(dp + len));
450*7c478bd9Sstevel@tonic-gate 	PUSH(DS, plen - len);
451*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)dp);
452*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len - 1);
453*7c478bd9Sstevel@tonic-gate }
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate void
456*7c478bd9Sstevel@tonic-gate encode_plus(fcode_env_t *env)
457*7c478bd9Sstevel@tonic-gate {
458*7c478bd9Sstevel@tonic-gate 	int len1, len2;
459*7c478bd9Sstevel@tonic-gate 	char *src1, *src2;
460*7c478bd9Sstevel@tonic-gate 	uchar_t *new;
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 4, "encode+");
463*7c478bd9Sstevel@tonic-gate 	src1 = pop_a_string(env, &len1);
464*7c478bd9Sstevel@tonic-gate 	src2 = pop_a_string(env, &len2);
465*7c478bd9Sstevel@tonic-gate 	new = add_property_buffer(env, len1 + len2);
466*7c478bd9Sstevel@tonic-gate 	if (src2) {
467*7c478bd9Sstevel@tonic-gate 		memcpy(new, src2, len2);
468*7c478bd9Sstevel@tonic-gate 		free_property_buffer(env, src2);
469*7c478bd9Sstevel@tonic-gate 	}
470*7c478bd9Sstevel@tonic-gate 	if (src1) {
471*7c478bd9Sstevel@tonic-gate 		memcpy(new + len2, src1, len1);
472*7c478bd9Sstevel@tonic-gate 		free_property_buffer(env, src1);
473*7c478bd9Sstevel@tonic-gate 	}
474*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)new);
475*7c478bd9Sstevel@tonic-gate 	PUSH(DS, len1 + len2);
476*7c478bd9Sstevel@tonic-gate }
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate static void
479*7c478bd9Sstevel@tonic-gate make_special_property(fcode_env_t *env, char *name)
480*7c478bd9Sstevel@tonic-gate {
481*7c478bd9Sstevel@tonic-gate 	push_a_string(env, name);
482*7c478bd9Sstevel@tonic-gate 	property(env);
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate void
486*7c478bd9Sstevel@tonic-gate device_name(fcode_env_t *env)
487*7c478bd9Sstevel@tonic-gate {
488*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "device-name");
489*7c478bd9Sstevel@tonic-gate 	encode_string(env);
490*7c478bd9Sstevel@tonic-gate 	make_special_property(env, "name");
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate void
494*7c478bd9Sstevel@tonic-gate model_prop(fcode_env_t *env)
495*7c478bd9Sstevel@tonic-gate {
496*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "model");
497*7c478bd9Sstevel@tonic-gate 	encode_string(env);
498*7c478bd9Sstevel@tonic-gate 	make_special_property(env, "model");
499*7c478bd9Sstevel@tonic-gate }
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate void
502*7c478bd9Sstevel@tonic-gate device_type(fcode_env_t *env)
503*7c478bd9Sstevel@tonic-gate {
504*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "device-type");
505*7c478bd9Sstevel@tonic-gate 	encode_string(env);
506*7c478bd9Sstevel@tonic-gate 	make_special_property(env, "device_type");
507*7c478bd9Sstevel@tonic-gate }
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate /*
510*7c478bd9Sstevel@tonic-gate  * 'next-property' Fcode implementation.
511*7c478bd9Sstevel@tonic-gate  */
512*7c478bd9Sstevel@tonic-gate void
513*7c478bd9Sstevel@tonic-gate next_property(fcode_env_t *env)
514*7c478bd9Sstevel@tonic-gate {
515*7c478bd9Sstevel@tonic-gate 	device_t *phandle;
516*7c478bd9Sstevel@tonic-gate 	char *previous;
517*7c478bd9Sstevel@tonic-gate 	prop_t *p;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "next-property");
520*7c478bd9Sstevel@tonic-gate 	phandle = (device_t *)POP(DS);
521*7c478bd9Sstevel@tonic-gate 	previous = pop_a_string(env, NULL);
522*7c478bd9Sstevel@tonic-gate 	p = phandle->properties;
523*7c478bd9Sstevel@tonic-gate 	if (previous == NULL)
524*7c478bd9Sstevel@tonic-gate 		p = phandle->properties;
525*7c478bd9Sstevel@tonic-gate 	else if (p = find_property(phandle, previous))
526*7c478bd9Sstevel@tonic-gate 		p = p->next;
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	for (; p != NULL && p->name == NULL; p = p->next)
529*7c478bd9Sstevel@tonic-gate 		;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	if (p)
532*7c478bd9Sstevel@tonic-gate 		push_a_string(env, p->name);
533*7c478bd9Sstevel@tonic-gate 	else
534*7c478bd9Sstevel@tonic-gate 		push_a_string(env, "");
535*7c478bd9Sstevel@tonic-gate 	PUSH(DS, TRUE);
536*7c478bd9Sstevel@tonic-gate }
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate void
539*7c478bd9Sstevel@tonic-gate get_property(fcode_env_t *env)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	if (MYSELF)
542*7c478bd9Sstevel@tonic-gate 		get_my_property(env);
543*7c478bd9Sstevel@tonic-gate 	else if (env->current_device) {
544*7c478bd9Sstevel@tonic-gate 		fstack_t d;
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 		REVERT_PHANDLE(env, d, env->current_device);
547*7c478bd9Sstevel@tonic-gate 		PUSH(DS, d);
548*7c478bd9Sstevel@tonic-gate 		get_package_property(env);
549*7c478bd9Sstevel@tonic-gate 	} else {
550*7c478bd9Sstevel@tonic-gate 		two_drop(env);
551*7c478bd9Sstevel@tonic-gate 		log_message(MSG_WARN, "No device context\n");
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate static void
558*7c478bd9Sstevel@tonic-gate print_indented(char *name)
559*7c478bd9Sstevel@tonic-gate {
560*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "%-28s", name);
561*7c478bd9Sstevel@tonic-gate }
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate static void
564*7c478bd9Sstevel@tonic-gate print_string(fcode_env_t *env, uchar_t *data, int len)
565*7c478bd9Sstevel@tonic-gate {
566*7c478bd9Sstevel@tonic-gate 	while (len > 0) {
567*7c478bd9Sstevel@tonic-gate 		int nlen = (strlen((char *)data)+1);
568*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "%s\n", data);
569*7c478bd9Sstevel@tonic-gate 		len -= nlen;
570*7c478bd9Sstevel@tonic-gate 		data += nlen;
571*7c478bd9Sstevel@tonic-gate 		if (len > 0)
572*7c478bd9Sstevel@tonic-gate 			print_indented("");
573*7c478bd9Sstevel@tonic-gate 	}
574*7c478bd9Sstevel@tonic-gate }
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate static void
577*7c478bd9Sstevel@tonic-gate print_ints(uchar_t *data, int len, int crlf)
578*7c478bd9Sstevel@tonic-gate {
579*7c478bd9Sstevel@tonic-gate 	uint32_t d;
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	while (len--) {
582*7c478bd9Sstevel@tonic-gate 		d = get_decoded_int(data);
583*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "%8.8lx ", d);
584*7c478bd9Sstevel@tonic-gate 		data += sizeof (uint32_t);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 	if (crlf)
587*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "\n");
588*7c478bd9Sstevel@tonic-gate }
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate static void
591*7c478bd9Sstevel@tonic-gate print_integer(fcode_env_t *env, uchar_t *data, int len)
592*7c478bd9Sstevel@tonic-gate {
593*7c478bd9Sstevel@tonic-gate 	print_ints(data, len/sizeof (uint32_t), 1);
594*7c478bd9Sstevel@tonic-gate }
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate static void
597*7c478bd9Sstevel@tonic-gate print_bytes(fcode_env_t *env, uchar_t *data, int len)
598*7c478bd9Sstevel@tonic-gate {
599*7c478bd9Sstevel@tonic-gate 	while (len--) {
600*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "%2.2x ", *data++);
601*7c478bd9Sstevel@tonic-gate 	}
602*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "\n");
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate static void
606*7c478bd9Sstevel@tonic-gate print_bytes_indented(fcode_env_t *env, uchar_t *data, int len)
607*7c478bd9Sstevel@tonic-gate {
608*7c478bd9Sstevel@tonic-gate 	int nbytes;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	for (; ; ) {
611*7c478bd9Sstevel@tonic-gate 		nbytes = min(len, 16);
612*7c478bd9Sstevel@tonic-gate 		print_bytes(env, data, nbytes);
613*7c478bd9Sstevel@tonic-gate 		len -= nbytes;
614*7c478bd9Sstevel@tonic-gate 		data += nbytes;
615*7c478bd9Sstevel@tonic-gate 		if (len == 0)
616*7c478bd9Sstevel@tonic-gate 			break;
617*7c478bd9Sstevel@tonic-gate 		print_indented("");
618*7c478bd9Sstevel@tonic-gate 	}
619*7c478bd9Sstevel@tonic-gate }
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate static void
622*7c478bd9Sstevel@tonic-gate print_reg(fcode_env_t *env, uchar_t *data, int len)
623*7c478bd9Sstevel@tonic-gate {
624*7c478bd9Sstevel@tonic-gate 	int pcells, nlen;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	if (env->current_device != NULL &&
627*7c478bd9Sstevel@tonic-gate 	    env->current_device->parent != NULL) {
628*7c478bd9Sstevel@tonic-gate 		pcells = get_num_size_cells(env, env->current_device->parent);
629*7c478bd9Sstevel@tonic-gate 		pcells +=  get_num_addr_cells(env, env->current_device->parent);
630*7c478bd9Sstevel@tonic-gate 		nlen = pcells*sizeof (uint32_t);
631*7c478bd9Sstevel@tonic-gate 		while (len > 0) {
632*7c478bd9Sstevel@tonic-gate 			print_ints(data, pcells, 1);
633*7c478bd9Sstevel@tonic-gate 			len -= nlen;
634*7c478bd9Sstevel@tonic-gate 			data += nlen;
635*7c478bd9Sstevel@tonic-gate 			if (len > 0)
636*7c478bd9Sstevel@tonic-gate 				print_indented("");
637*7c478bd9Sstevel@tonic-gate 		}
638*7c478bd9Sstevel@tonic-gate 	} else
639*7c478bd9Sstevel@tonic-gate 		print_bytes_indented(env, data, len);
640*7c478bd9Sstevel@tonic-gate }
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate static void
643*7c478bd9Sstevel@tonic-gate print_imap(fcode_env_t *env, uchar_t *dp, int len)
644*7c478bd9Sstevel@tonic-gate {
645*7c478bd9Sstevel@tonic-gate 	int n, icells;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	if (env->current_device == NULL) {
648*7c478bd9Sstevel@tonic-gate 		print_bytes_indented(env, dp, len);
649*7c478bd9Sstevel@tonic-gate 		return;
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 	n = get_num_addr_cells(env, env->current_device);
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	while (len) {
654*7c478bd9Sstevel@tonic-gate 		int offset;
655*7c478bd9Sstevel@tonic-gate 		fstack_t data;
656*7c478bd9Sstevel@tonic-gate 		device_t *node;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 		offset = 0;
659*7c478bd9Sstevel@tonic-gate 		data = get_decoded_int(dp+((n+1)*sizeof (uint32_t)));
660*7c478bd9Sstevel@tonic-gate 		CONVERT_PHANDLE(env, node, data);
661*7c478bd9Sstevel@tonic-gate 		offset += (n+2)*sizeof (uint32_t);
662*7c478bd9Sstevel@tonic-gate 		print_ints(dp, (n+2), 0);
663*7c478bd9Sstevel@tonic-gate 		icells = get_default_intprop(env, "#interrupt-cells", node, 1);
664*7c478bd9Sstevel@tonic-gate 		print_ints(dp+offset, icells, 1);
665*7c478bd9Sstevel@tonic-gate 		offset += icells*sizeof (uint32_t);
666*7c478bd9Sstevel@tonic-gate 		dp += offset;
667*7c478bd9Sstevel@tonic-gate 		len -= offset;
668*7c478bd9Sstevel@tonic-gate 		if (len)
669*7c478bd9Sstevel@tonic-gate 			print_indented("");
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate }
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate static void
674*7c478bd9Sstevel@tonic-gate print_ranges(fcode_env_t *env, uchar_t *data, int len)
675*7c478bd9Sstevel@tonic-gate {
676*7c478bd9Sstevel@tonic-gate 	int pcells, nlen;
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 	if (env->current_device != NULL &&
679*7c478bd9Sstevel@tonic-gate 	    env->current_device->parent != NULL) {
680*7c478bd9Sstevel@tonic-gate 		pcells = get_num_addr_cells(env, env->current_device);
681*7c478bd9Sstevel@tonic-gate 		pcells += get_num_addr_cells(env, env->current_device->parent);
682*7c478bd9Sstevel@tonic-gate 		pcells += get_num_size_cells(env, env->current_device);
683*7c478bd9Sstevel@tonic-gate 		nlen = pcells*sizeof (uint32_t);
684*7c478bd9Sstevel@tonic-gate 		while (len > 0) {
685*7c478bd9Sstevel@tonic-gate 			print_ints(data, pcells, 1);
686*7c478bd9Sstevel@tonic-gate 			len -= nlen;
687*7c478bd9Sstevel@tonic-gate 			data += nlen;
688*7c478bd9Sstevel@tonic-gate 			if (len > 0)
689*7c478bd9Sstevel@tonic-gate 				print_indented("");
690*7c478bd9Sstevel@tonic-gate 		}
691*7c478bd9Sstevel@tonic-gate 	} else
692*7c478bd9Sstevel@tonic-gate 		print_bytes_indented(env, data, len);
693*7c478bd9Sstevel@tonic-gate }
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate typedef struct MAGIC_PROP {
696*7c478bd9Sstevel@tonic-gate 	char *name;
697*7c478bd9Sstevel@tonic-gate 	void (*fn)(fcode_env_t *env, uchar_t *data, int len);
698*7c478bd9Sstevel@tonic-gate } magic_prop_t;
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate static magic_prop_t magic_props[] = {
701*7c478bd9Sstevel@tonic-gate 	{ "name",		print_string },
702*7c478bd9Sstevel@tonic-gate 	{ "device_type",	print_string },
703*7c478bd9Sstevel@tonic-gate 	{ "model",		print_string },
704*7c478bd9Sstevel@tonic-gate 	{ "reg",		print_reg },
705*7c478bd9Sstevel@tonic-gate 	{ "assigned-addresses",	print_reg },
706*7c478bd9Sstevel@tonic-gate 	{ "interrupt-map",	print_imap },
707*7c478bd9Sstevel@tonic-gate 	{ "#interrupt-cells",	print_integer },
708*7c478bd9Sstevel@tonic-gate 	{ "interrupt-map-mask",	print_integer },
709*7c478bd9Sstevel@tonic-gate 	{ "#size-cells",	print_integer },
710*7c478bd9Sstevel@tonic-gate 	{ "#address-cells",	print_integer },
711*7c478bd9Sstevel@tonic-gate 	{ "ranges",		print_ranges },
712*7c478bd9Sstevel@tonic-gate 	{ "device-id",		print_integer },
713*7c478bd9Sstevel@tonic-gate 	{ "vendor-id",		print_integer },
714*7c478bd9Sstevel@tonic-gate 	{ "class-code",		print_integer },
715*7c478bd9Sstevel@tonic-gate 	{ "compatible",		print_string },
716*7c478bd9Sstevel@tonic-gate 	{ "version",		print_string },
717*7c478bd9Sstevel@tonic-gate 	{ "manufacturer",	print_string },
718*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
719*7c478bd9Sstevel@tonic-gate };
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate static void
722*7c478bd9Sstevel@tonic-gate print_content(fcode_env_t *env, char *prop, uchar_t *data, int len)
723*7c478bd9Sstevel@tonic-gate {
724*7c478bd9Sstevel@tonic-gate 	magic_prop_t *p;
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 	for (p = magic_props; p->name; p++)
727*7c478bd9Sstevel@tonic-gate 		if (strcmp(prop, p->name) == 0) {
728*7c478bd9Sstevel@tonic-gate 			(*p->fn)(env, data, len);
729*7c478bd9Sstevel@tonic-gate 			return;
730*7c478bd9Sstevel@tonic-gate 		}
731*7c478bd9Sstevel@tonic-gate 	print_bytes_indented(env, data, len);
732*7c478bd9Sstevel@tonic-gate }
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate void
735*7c478bd9Sstevel@tonic-gate print_property(fcode_env_t *env, prop_t *p, char *prepend)
736*7c478bd9Sstevel@tonic-gate {
737*7c478bd9Sstevel@tonic-gate 	char buf[40];
738*7c478bd9Sstevel@tonic-gate 	char *name = (p->name ? p->name : "<noname>");
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 	if (prepend) {
741*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s %s", prepend, name);
742*7c478bd9Sstevel@tonic-gate 		name = buf;
743*7c478bd9Sstevel@tonic-gate 	}
744*7c478bd9Sstevel@tonic-gate 	print_indented(name);
745*7c478bd9Sstevel@tonic-gate 	if (p->name)
746*7c478bd9Sstevel@tonic-gate 		print_content(env, p->name, p->data, p->size);
747*7c478bd9Sstevel@tonic-gate 	else
748*7c478bd9Sstevel@tonic-gate 		print_bytes_indented(env, p->data, p->size);
749*7c478bd9Sstevel@tonic-gate }
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate void
752*7c478bd9Sstevel@tonic-gate dot_properties(fcode_env_t *env)
753*7c478bd9Sstevel@tonic-gate {
754*7c478bd9Sstevel@tonic-gate 	prop_t *p;
755*7c478bd9Sstevel@tonic-gate 	instance_t *omyself;
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate 	omyself = MYSELF;
758*7c478bd9Sstevel@tonic-gate 	MYSELF = NULL;
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate 	if (env->current_device) {
761*7c478bd9Sstevel@tonic-gate 		for (p = env->current_device->properties; p; p = p->next)
762*7c478bd9Sstevel@tonic-gate 			print_property(env, p, NULL);
763*7c478bd9Sstevel@tonic-gate 	} else {
764*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "No device context\n");
765*7c478bd9Sstevel@tonic-gate 	}
766*7c478bd9Sstevel@tonic-gate 	MYSELF = omyself;
767*7c478bd9Sstevel@tonic-gate }
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate #endif
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate #pragma init(_init)
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate static void
774*7c478bd9Sstevel@tonic-gate _init(void)
775*7c478bd9Sstevel@tonic-gate {
776*7c478bd9Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	ASSERT(env);
779*7c478bd9Sstevel@tonic-gate 	NOTICE;
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate 	P1275(0x110, 0,		"property",		property);
782*7c478bd9Sstevel@tonic-gate 	P1275(0x111, 0,		"encode-int",		encode_int);
783*7c478bd9Sstevel@tonic-gate 	P1275(0x112, 0,		"encode+",		encode_plus);
784*7c478bd9Sstevel@tonic-gate 	P1275(0x113, 0,		"encode-phys",		encode_phys);
785*7c478bd9Sstevel@tonic-gate 	P1275(0x114, 0,		"encode-string",	encode_string);
786*7c478bd9Sstevel@tonic-gate 	P1275(0x115, 0,		"encode-bytes",		encode_bytes);
787*7c478bd9Sstevel@tonic-gate 	P1275(0x116, 0,		"reg",			reg_prop);
788*7c478bd9Sstevel@tonic-gate 	FCODE(0x117, 0,		"intr",			fc_obsolete);
789*7c478bd9Sstevel@tonic-gate 	FCODE(0x118, 0,		"driver",		fc_historical);
790*7c478bd9Sstevel@tonic-gate 	P1275(0x119, 0,		"model",		model_prop);
791*7c478bd9Sstevel@tonic-gate 	P1275(0x11a, 0,		"device-type",		device_type);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	P1275(0x128, 0,		"decode-phys",		decode_phys);
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	P1275(0x201, 0,		"device-name",		device_name);
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	P1275(0x21a, 0,		"get-my-property",	get_my_property);
798*7c478bd9Sstevel@tonic-gate 	P1275(0x21b, 0,		"decode-int",		decode_int);
799*7c478bd9Sstevel@tonic-gate 	P1275(0x21c, 0,		"decode-string",	decode_string);
800*7c478bd9Sstevel@tonic-gate 	P1275(0x21d, 0,		"get-inherited-property", get_inherited_prop);
801*7c478bd9Sstevel@tonic-gate 	P1275(0x21e, 0,		"delete-property",	delete_property);
802*7c478bd9Sstevel@tonic-gate 	P1275(0x21f, 0,		"get-package-property",	get_package_property);
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	P1275(0x23d, 0,		"next-property",	next_property);
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"get-property",		get_property);
807*7c478bd9Sstevel@tonic-gate 	FORTH(0,		".properties",		dot_properties);
808*7c478bd9Sstevel@tonic-gate }
809