xref: /illumos-gate/usr/src/lib/efcode/engine/package.c (revision 09e6639b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.   All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Copyright 2019 Peter Tribble.
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <string.h>
33 
34 #include <fcode/private.h>
35 #include <fcode/log.h>
36 
37 #include <fcdriver/fcdriver.h>
38 
39 #define	MIN_VALUES	100
40 
41 static void
check_my_self(fcode_env_t * env,char * fn)42 check_my_self(fcode_env_t *env, char *fn)
43 {
44 	if (!MYSELF)
45 		forth_abort(env, "%s: MYSELF is NULL", fn);
46 }
47 
48 uint_t
get_number_of_parent_address_cells(fcode_env_t * env)49 get_number_of_parent_address_cells(fcode_env_t *env)
50 {
51 	uint_t ncells;
52 	device_t *d;
53 	static char func_name[] = "get_number_of_parent_address_cells";
54 
55 	if (MYSELF == NULL)	/* Kludge for testing */
56 		return (2);
57 	d = MYSELF->device;
58 	ncells = d->parent_adr_cells;
59 	if (ncells == 0) {
60 		ncells = get_default_intprop(env, "#address-cells", d->parent,
61 		    2);
62 		if (ncells > MAX_MY_ADDR) {
63 			log_message(MSG_ERROR, "%s: %s:"
64 			    " ncells (%d) > MAX_MY_ADDR (%d)\n", func_name,
65 			    get_path(env, d->parent), ncells, MAX_MY_ADDR);
66 			ncells = MAX_MY_ADDR;
67 		}
68 		d->parent_adr_cells = ncells;
69 	}
70 	return (ncells);
71 }
72 
73 instance_t *
create_ihandle(fcode_env_t * env,device_t * phandle,instance_t * parent)74 create_ihandle(fcode_env_t *env, device_t *phandle, instance_t *parent)
75 {
76 	instance_t *ihandle;
77 	int i;
78 
79 	ihandle = MALLOC(sizeof (instance_t));
80 
81 	i = max(phandle->data_size[INIT_DATA], MIN_VALUES);
82 	ihandle->data[INIT_DATA] = MALLOC(sizeof (fstack_t) * i);
83 	memcpy(ihandle->data[INIT_DATA], phandle->init_data,
84 	    (size_t) (sizeof (fstack_t) * i));
85 
86 	i = max(phandle->data_size[UINIT_DATA], MIN_VALUES);
87 	ihandle->data[UINIT_DATA] = MALLOC(sizeof (fstack_t) * i);
88 
89 	ihandle->my_space = phandle->my_space;
90 	memcpy(ihandle->my_addr, phandle->my_addr, sizeof (ihandle->my_addr));
91 	ihandle->parent = parent;
92 	ihandle->device = phandle;
93 	return (ihandle);
94 }
95 
96 device_t *
create_phandle(fcode_env_t * env,device_t * parent)97 create_phandle(fcode_env_t *env, device_t *parent)
98 {
99 	device_t *phandle;
100 
101 	phandle = MALLOC(sizeof (device_t));
102 	phandle->init_data = MALLOC(sizeof (fstack_t) * MIN_VALUES);
103 	phandle->data_size[INIT_DATA] = 0;
104 	phandle->data_size[UINIT_DATA] = 0;
105 	phandle->parent = parent;
106 	return (phandle);
107 }
108 
109 
110 static void
do_push_package(fcode_env_t * env,device_t * d)111 do_push_package(fcode_env_t *env, device_t *d)
112 {
113 	do_previous(env);
114 	do_also(env);
115 	if (d != NULL) {
116 		CONTEXT = (token_t *)(&d->vocabulary);
117 		debug_msg(DEBUG_CONTEXT, "CONTEXT:push_package: %s%d/%p/%p\n",
118 		    get_path(env, d), env->order_depth, CONTEXT, env->current);
119 	}
120 }
121 
122 static void
push_package(fcode_env_t * env)123 push_package(fcode_env_t *env)
124 {
125 	device_t *d;
126 	phandle_t ph;
127 
128 	CHECK_DEPTH(env, 1, "push-package");
129 	ph = POP(DS);
130 	CONVERT_PHANDLE(env, d, ph);
131 	do_push_package(env, d);
132 }
133 
134 static void
pop_package(fcode_env_t * env)135 pop_package(fcode_env_t *env)
136 {
137 	do_previous(env);
138 	do_definitions(env);
139 }
140 
141 static void
interpose(fcode_env_t * env)142 interpose(fcode_env_t *env)
143 {
144 	TODO;	/* interpose - not yet implemented */
145 }
146 
147 void
activate_device(fcode_env_t * env,device_t * d)148 activate_device(fcode_env_t *env, device_t *d)
149 {
150 	env->current_device = d;
151 	do_push_package(env, d);
152 	do_definitions(env);
153 }
154 
155 void
deactivate_device(fcode_env_t * env,device_t * d)156 deactivate_device(fcode_env_t *env, device_t *d)
157 {
158 	env->current_device = d;
159 	do_previous(env);
160 	if (d != NULL) {
161 		CONTEXT = (token_t *)(&d->vocabulary);
162 		debug_msg(DEBUG_CONTEXT, "CONTEXT:deactivate_device:"
163 		    " %s%d/%p/%p\n", get_path(env, d), env->order_depth,
164 		    CONTEXT, env->current);
165 	}
166 	do_definitions(env);
167 }
168 
169 void
root_node(fcode_env_t * env)170 root_node(fcode_env_t *env)
171 {
172 	do_also(env);
173 	activate_device(env, env->root_node);
174 }
175 
176 void
child_node(fcode_env_t * env)177 child_node(fcode_env_t *env)
178 {
179 	device_t *d;
180 
181 	CHECK_DEPTH(env, 1, "child");
182 	CONVERT_PHANDLE(env, d, TOS);
183 	TOS = (fstack_t)d->child;
184 	REVERT_PHANDLE(env, TOS, d->child);
185 }
186 
187 void
peer_node(fcode_env_t * env)188 peer_node(fcode_env_t *env)
189 {
190 	device_t *d;
191 
192 	CHECK_DEPTH(env, 1, "peer");
193 	CONVERT_PHANDLE(env, d, TOS);
194 	REVERT_PHANDLE(env, TOS, d->peer);
195 }
196 
197 void
new_device(fcode_env_t * env)198 new_device(fcode_env_t *env)
199 {
200 	device_t *phandle, *parent;
201 	device_t *peer;
202 
203 	check_my_self(env, "new-device");
204 
205 	parent = MYSELF->device;
206 	phandle = create_phandle(env, parent);
207 	MYSELF = create_ihandle(env, phandle, MYSELF);
208 	activate_device(env, phandle);
209 	if (parent->child) {
210 		/* Insert new child at end of peer list */
211 		for (peer = parent->child; peer->peer; peer = peer->peer)
212 			;
213 		peer->peer = phandle;
214 	} else
215 		parent->child = phandle;	/* First child */
216 	ALLOCATE_PHANDLE(env);
217 }
218 
219 void
finish_device(fcode_env_t * env)220 finish_device(fcode_env_t *env)
221 {
222 	fstack_t *mem;
223 	device_t *my_dev, *parent_dev;
224 	instance_t *parent, *myself = MYSELF;
225 	int  n;
226 
227 	check_my_self(env, "finish-device");
228 	ASSERT(myself->device);
229 	ASSERT(env->current_device);
230 	n = myself->device->data_size[INIT_DATA];
231 
232 	/*
233 	 * Paranoia.. reserve a little more instance data than we need
234 	 */
235 	mem = MALLOC(sizeof (fstack_t) * (n+8));
236 	memcpy(mem, MYSELF->device->init_data, sizeof (fstack_t) * n);
237 	FREE(myself->device->init_data);
238 	my_dev = myself->device;
239 	my_dev->init_data = mem;
240 	parent = MYSELF->parent;
241 	parent_dev = env->current_device->parent;
242 	FREE(MYSELF);
243 	MYSELF = parent;
244 	activate_device(env, parent_dev);
245 }
246 
247 static void
create_internal_value(fcode_env_t * env,char * name,int offset,int token)248 create_internal_value(fcode_env_t *env, char *name, int offset, int token)
249 {
250 	header(env, name, strlen(name), 0);
251 	COMPILE_TOKEN(&noop);
252 	EXPOSE_ACF;
253 	if (token) {
254 		SET_TOKEN(token, 0, name, LINK_TO_ACF(env->lastlink));
255 	}
256 	PUSH(DS, offset);
257 	lcomma(env);
258 	set_internal_value_actions(env);
259 }
260 
261 static void
create_my_self(fcode_env_t * env)262 create_my_self(fcode_env_t *env)
263 {
264 	int offset = offsetof(fcode_env_t, my_self);
265 
266 	create_internal_value(env, "my-self", offset, 0x203);
267 }
268 
269 static void
create_my_space(fcode_env_t * env)270 create_my_space(fcode_env_t *env)
271 {
272 	int offset = offsetof(instance_t, my_space);
273 
274 	create_internal_value(env, "my-space", -offset, 0x103);
275 }
276 
277 void
my_address(fcode_env_t * env)278 my_address(fcode_env_t *env)
279 {
280 	fstack_t *adr_ptr;
281 	uint_t ncells;
282 
283 	check_my_self(env, "my-address");
284 	ncells = get_number_of_parent_address_cells(env);
285 	adr_ptr = MYSELF->my_addr;
286 	while (--ncells) {
287 		PUSH(DS, *adr_ptr);
288 		adr_ptr++;
289 	}
290 }
291 
292 void
my_unit(fcode_env_t * env)293 my_unit(fcode_env_t *env)
294 {
295 	check_my_self(env, "my-unit");
296 	my_address(env);
297 	PUSH(DS, MYSELF->my_space);
298 }
299 
300 static void
my_args(fcode_env_t * env)301 my_args(fcode_env_t *env)
302 {
303 	check_my_self(env, "my-args");
304 	PUSH(DS, (fstack_t)MYSELF->my_args);
305 	PUSH(DS, (fstack_t)MYSELF->my_args_len);
306 }
307 
308 int
call_my_parent(fcode_env_t * env,char * method)309 call_my_parent(fcode_env_t *env, char *method)
310 {
311 	push_a_string(env, method);
312 	dollar_call_parent(env);
313 	return (env->last_error);
314 }
315 
316 void
set_args(fcode_env_t * env)317 set_args(fcode_env_t *env)
318 {
319 	int args_len;
320 	common_data_t *cdp;
321 	uint_t ncells;
322 	fstack_t *adr_ptr, *adr_ptr1, space;
323 
324 	CHECK_DEPTH(env, 4, "set-args");
325 
326 	check_my_self(env, "set-args");
327 
328 	/*
329 	 * Handle args argument of set-args.
330 	 */
331 	if (MYSELF->my_args) {
332 		FREE(MYSELF->my_args);
333 		MYSELF->my_args = NULL;
334 	}
335 	two_swap(env);
336 	MYSELF->my_args = pop_a_duped_string(env, &args_len);
337 	MYSELF->my_args_len = args_len;
338 
339 	if (call_my_parent(env, "decode-unit"))
340 		forth_abort(env, "set-args: decode-unit failed");
341 
342 	ncells = get_number_of_parent_address_cells(env);
343 
344 	/*
345 	 * Kludge: For GP2, my-space comes from decode-unit hi.address.
346 	 * for PCI, my-space from decode-unit won't have the bus#, so we need
347 	 * to get it from config_address.  Unfortunately, there is no easy
348 	 * way to figure out here which one we're looking at.  We take the
349 	 * expediant of or'ing the two values together.
350 	 */
351 	space = POP(DS);	/* pop phys.hi */
352 	if ((cdp = (common_data_t *)env->private) != NULL)
353 		space |= cdp->fc.config_address;
354 
355 	MYSELF->device->my_space = MYSELF->my_space = space;
356 
357 	adr_ptr = MYSELF->my_addr;
358 	adr_ptr1 = MYSELF->device->my_addr;
359 	while (--ncells) {
360 		*adr_ptr++ = *adr_ptr1++ = POP(DS);
361 	}
362 }
363 
364 void
my_parent(fcode_env_t * env)365 my_parent(fcode_env_t *env)
366 {
367 	check_my_self(env, "my-parent");
368 	PUSH(DS, (fstack_t)MYSELF->parent);
369 }
370 
371 instance_t *
open_instance_chain(fcode_env_t * env,device_t * phandle,int exec)372 open_instance_chain(fcode_env_t *env, device_t *phandle, int exec)
373 {
374 	instance_t *parent;
375 
376 	if (!phandle)
377 		return (NULL);
378 	parent = open_instance_chain(env, phandle->parent, exec);
379 	return (create_ihandle(env, phandle, parent));
380 }
381 
382 void
close_instance_chain(fcode_env_t * env,instance_t * ihandle,int exec)383 close_instance_chain(fcode_env_t *env, instance_t *ihandle, int exec)
384 {
385 	instance_t *parent;
386 
387 	if (ihandle) {
388 		parent = ihandle->parent;
389 		close_instance_chain(env, parent, exec);
390 		if (ihandle->my_args)
391 			FREE(ihandle->my_args);
392 		FREE(ihandle);
393 	}
394 }
395 
396 void
begin_package(fcode_env_t * env)397 begin_package(fcode_env_t *env)
398 {
399 	fstack_t ok;
400 	char *name;
401 
402 	CHECK_DEPTH(env, 6, "begin-package");
403 	two_dup(env);
404 	name = pop_a_string(env, NULL);
405 	find_package(env);
406 	ok = POP(DS);
407 	if (ok) {
408 		PUSH(DS, 0);
409 		PUSH(DS, 0);
410 		rot(env);
411 		open_package(env);
412 		MYSELF = (instance_t *)POP(DS);
413 		check_my_self(env, "begin-package");
414 		new_device(env);
415 		set_args(env);
416 	} else {
417 		log_message(MSG_INFO, "Package '%s' not found\n", name);
418 	}
419 }
420 
421 void
open_package(fcode_env_t * env)422 open_package(fcode_env_t *env)
423 {
424 	device_t *phandle;
425 	instance_t *ihandle;
426 	int len;
427 
428 	CHECK_DEPTH(env, 3, "open-package");
429 	CONVERT_PHANDLE(env, phandle, POP(DS));
430 	ihandle = open_instance_chain(env, phandle, 1);
431 	ihandle->my_args = pop_a_duped_string(env, &len);
432 	ihandle->my_args_len = len;
433 	PUSH(DS, (fstack_t)ihandle);
434 }
435 
436 void
dollar_open_package(fcode_env_t * env)437 dollar_open_package(fcode_env_t *env)
438 {
439 	fstack_t ok;
440 
441 	CHECK_DEPTH(env, 4, "$open-package");
442 	find_package(env);
443 	ok = POP(DS);
444 	if (ok) {
445 		open_package(env);
446 	} else {
447 		(void) POP(DS);
448 		(void) POP(DS);
449 		PUSH(DS, 0);
450 	}
451 }
452 
453 void
close_package(fcode_env_t * env)454 close_package(fcode_env_t *env)
455 {
456 	instance_t *ihandle;
457 
458 	CHECK_DEPTH(env, 1, "close-package");
459 	ihandle = (instance_t *)POP(DS);
460 	close_instance_chain(env, ihandle, 1);
461 }
462 
463 static void (*find_method_hook)(fcode_env_t *);
464 
465 void
set_find_method_hook(fcode_env_t * env,void (* hook)(fcode_env_t *))466 set_find_method_hook(fcode_env_t *env, void (*hook)(fcode_env_t *))
467 {
468 	find_method_hook = hook;
469 }
470 
471 void
find_method(fcode_env_t * env)472 find_method(fcode_env_t *env)
473 {
474 	fstack_t d;
475 	device_t *device;
476 	acf_t acf = 0;
477 
478 	CHECK_DEPTH(env, 3, "find-method");
479 	if (find_method_hook) {
480 		(*find_method_hook)(env);
481 		if (TOS)		/* Found it */
482 			return;
483 		POP(DS);
484 	}
485 
486 	d = POP(DS);
487 	CONVERT_PHANDLE(env, device, d);
488 	PUSH(DS, (fstack_t)&device->vocabulary);
489 	acf = voc_find(env);
490 	PUSH(DS, (fstack_t)acf);
491 	if (acf) {
492 		PUSH(DS, TRUE);
493 	}
494 }
495 
496 /*
497  * 'call-package' Fcode
498  */
499 void
call_package(fcode_env_t * env)500 call_package(fcode_env_t *env)
501 {
502 	instance_t *ihandle, *saved_myself;
503 
504 	CHECK_DEPTH(env, 2, "call-package");
505 	ihandle = (instance_t *)POP(DS);
506 	saved_myself = MYSELF;
507 	MYSELF = ihandle;
508 	execute(env);
509 	MYSELF = saved_myself;
510 }
511 
512 void
ihandle_to_phandle(fcode_env_t * env)513 ihandle_to_phandle(fcode_env_t *env)
514 {
515 	instance_t *i;
516 
517 	CHECK_DEPTH(env, 1, "ihandle>phandle");
518 	i = (instance_t *)TOS;
519 	REVERT_PHANDLE(env, TOS, i->device);
520 }
521 
522 char *
get_package_name(fcode_env_t * env,device_t * d)523 get_package_name(fcode_env_t *env, device_t *d)
524 {
525 	char *name;
526 	prop_t *prop;
527 
528 	prop = lookup_package_property(env, "name", d);
529 	if (prop == NULL) {
530 		name = "<Unnamed>";
531 	} else {
532 		name = (char *)prop->data;
533 	}
534 	return (name);
535 }
536 
537 static char *package_search_path = "/packages:/openprom";
538 
539 device_t *
match_package_path(fcode_env_t * env,char * path)540 match_package_path(fcode_env_t *env, char *path)
541 {
542 	device_t *d;
543 	char *name;
544 	int len;
545 
546 	if (*path == '/') {
547 		d = env->root_node->child;
548 		path++;
549 	} else
550 		d = env->current_device;
551 	while (*path != '\0' && d != NULL) {
552 		name = get_package_name(env, d);
553 		len = strlen(name);
554 		if (strncmp(name, path, len) == 0) {
555 			path += len;
556 			if (*path == '\0') {
557 				return (d);
558 			}
559 			/* skip the '/' */
560 			if (*path++ != '/')
561 				break;
562 			d = d->child;
563 		} else {
564 			d = d->peer;
565 		}
566 	}
567 	return (NULL);
568 }
569 
570 device_t *
locate_package(fcode_env_t * env,char * start)571 locate_package(fcode_env_t *env, char *start)
572 {
573 	device_t *d;
574 	char *p, *next_p;
575 	char *tpath, *fpath;
576 
577 	if ((d = match_package_path(env, start)) != NULL)
578 		return (d);
579 
580 	/*
581 	 * ignore starting '/'
582 	 */
583 	if (*start == '/')
584 		*start++;
585 
586 	fpath = STRDUP(package_search_path);
587 	for (p = fpath; p != NULL; p = next_p) {
588 		if ((next_p = strchr(p, ':')) != NULL)
589 			*next_p++ = '\0';
590 		tpath = MALLOC(strlen(p) + strlen(start) + 2);
591 		(void) sprintf(tpath, "%s/%s", p, start);
592 		if ((d = match_package_path(env, tpath)) != NULL) {
593 			FREE(fpath);
594 			FREE(tpath);
595 			return (d);
596 		}
597 		FREE(tpath);
598 	}
599 	FREE(fpath);
600 	return (NULL);
601 }
602 
603 void
find_package(fcode_env_t * env)604 find_package(fcode_env_t *env)
605 {
606 	char *path;
607 	device_t *package;
608 	fstack_t ph = 0;
609 
610 	CHECK_DEPTH(env, 2, "find-package");
611 	if ((path = pop_a_duped_string(env, NULL)) != NULL) {
612 		if (strcmp(path, "/") == 0)
613 			package = env->root_node;
614 		else
615 			package = locate_package(env, path);
616 		FREE(path);
617 		REVERT_PHANDLE(env, ph, package);
618 	}
619 	PUSH(DS, ph);
620 	if (package)
621 		PUSH(DS, TRUE);
622 }
623 
624 static void
encode_unit_hack(fcode_env_t * env)625 encode_unit_hack(fcode_env_t *env)
626 {
627 	int hi, i;
628 	uint_t ncells = get_number_of_parent_address_cells(env);
629 
630 	for (i = 0; i < ncells; i++)
631 		POP(DS);
632 	push_a_string(env, NULL);
633 }
634 
635 void
dollar_call_method(fcode_env_t * env)636 dollar_call_method(fcode_env_t *env)
637 {
638 	instance_t *old_myself;
639 	instance_t *myself;
640 	device_t *device;
641 	char *method;
642 
643 	CHECK_DEPTH(env, 3, "$call-method");
644 	check_my_self(env, "$call-method");
645 	old_myself = MYSELF;
646 	myself = (instance_t *)POP(DS);
647 
648 	method = (char *)DS[-1];
649 	debug_msg(DEBUG_CALL_METHOD, "$call_method %s\n", method);
650 
651 	if (old_myself && !myself) {
652 		/* We hit the root of our tree */
653 		device = old_myself->device;
654 		return;
655 	}
656 
657 	MYSELF = myself;
658 	check_my_self(env, "$call-method");
659 	device = MYSELF->device;
660 	do_push_package(env, device);
661 	PUSH(DS, (fstack_t)device);
662 	REVERT_PHANDLE(env, TOS, device);
663 	find_method(env);
664 	if (TOS) {
665 		(void) POP(DS);
666 		execute(env);
667 	} else if (strcmp(method, "encode-unit") == 0) {
668 		encode_unit_hack(env);
669 	} else {
670 		throw_from_fclib(env, 1, "Unimplemented package method: %s%s",
671 		    get_path(env, device), method);
672 	}
673 	MYSELF = old_myself;
674 	do_push_package(env, MYSELF->device);
675 }
676 
677 void
dollar_call_parent(fcode_env_t * env)678 dollar_call_parent(fcode_env_t *env)
679 {
680 	CHECK_DEPTH(env, 2, "$call-parent");
681 
682 	check_my_self(env, "$call-parent");
683 
684 	PUSH(DS, (fstack_t)MYSELF->parent);
685 	dollar_call_method(env);
686 }
687 
688 #ifdef DEBUG
689 void
current_device(fcode_env_t * env)690 current_device(fcode_env_t *env)
691 {
692 	PUSH(DS, (fstack_t)&env->current_device);
693 }
694 
695 char *
get_path(fcode_env_t * env,device_t * d)696 get_path(fcode_env_t *env, device_t *d)
697 {
698 	char *pre_path, *name, *path;
699 	int n;
700 
701 	if (d->parent)
702 		pre_path = get_path(env, d->parent);
703 	else
704 		pre_path = STRDUP("");
705 
706 	name = get_package_name(env, d);
707 	n = strlen(pre_path) + strlen(name) + 1;
708 	path = MALLOC(n);
709 	(void) strcpy(path, pre_path);
710 	(void) strcat(path, name);
711 	if (d->child && d->parent)
712 		(void) strcat(path, "/");
713 	FREE(pre_path);
714 	return (path);
715 }
716 
717 static void
pwd_dollar(fcode_env_t * env)718 pwd_dollar(fcode_env_t *env)
719 {
720 	if (env->current_device)
721 		push_a_string(env, get_path(env, env->current_device));
722 	else
723 		push_a_string(env, NULL);
724 }
725 
726 void
pwd(fcode_env_t * env)727 pwd(fcode_env_t *env)
728 {
729 	if (env->current_device) {
730 		log_message(MSG_INFO, "%s\n",
731 		    get_path(env, env->current_device));
732 	} else {
733 		log_message(MSG_INFO, "No device context\n");
734 	}
735 }
736 
737 void
do_ls(fcode_env_t * env)738 do_ls(fcode_env_t *env)
739 {
740 	device_t *d;
741 
742 	if (env->current_device == NULL) {
743 		log_message(MSG_INFO, "No device context\n");
744 		return;
745 	}
746 
747 	d = env->current_device->child;
748 	while (d) {
749 		char *name;
750 		fstack_t ph;
751 		name = get_package_name(env, d);
752 		REVERT_PHANDLE(env, ph, d);
753 		log_message(MSG_INFO, "%llx %s\n", (uint64_t)ph, name);
754 		d = d->peer;
755 	}
756 }
757 
758 void
paren_cd(fcode_env_t * env)759 paren_cd(fcode_env_t *env)
760 {
761 	char *str;
762 	device_t *p;
763 
764 	str = pop_a_string(env, NULL);
765 	if (strcmp(str, "/") == 0) {
766 		root_node(env);
767 		return;
768 	}
769 
770 	if (env->current_device == NULL) {
771 		log_message(MSG_INFO, "No device context\n");
772 		return;
773 	}
774 
775 	if (strcmp(str, "..") == 0)
776 		p = env->current_device->parent;
777 	else {
778 		device_t *n = env->current_device->child;
779 
780 		p = NULL;
781 		while (n) {
782 			char *name;
783 
784 			name = get_package_name(env, n);
785 			if (strcmp(name, str) == 0) {
786 				p = n;
787 				break;
788 			}
789 			n = n->peer;
790 		}
791 	}
792 
793 	if (p) {
794 		activate_device(env, p);
795 	} else {
796 		log_message(MSG_INFO, "No such node: %s\n", str);
797 	}
798 }
799 
800 void
do_cd(fcode_env_t * env)801 do_cd(fcode_env_t *env)
802 {
803 	parse_word(env);
804 	paren_cd(env);
805 }
806 
807 void
do_unselect_dev(fcode_env_t * env)808 do_unselect_dev(fcode_env_t *env)
809 {
810 	check_my_self(env, "unselect-dev");
811 	PUSH(DS, (fstack_t)MYSELF);
812 	close_package(env);
813 	deactivate_device(env, NULL);
814 }
815 
816 void
do_select_dev(fcode_env_t * env)817 do_select_dev(fcode_env_t *env)
818 {
819 	PUSH(DS, 0);
820 	PUSH(DS, 0);
821 	two_swap(env);
822 	dollar_open_package(env);
823 	if (TOS) {
824 		MYSELF = (instance_t *)POP(DS);
825 		check_my_self(env, "select-dev");
826 		activate_device(env, MYSELF->device);
827 	} else {
828 		drop(env);
829 		log_message(MSG_INFO, "Can't open package\n");
830 	}
831 }
832 
833 void
device_end(fcode_env_t * env)834 device_end(fcode_env_t *env)
835 {
836 	if (env->current_device) {
837 		deactivate_device(env, NULL);
838 	}
839 }
840 
841 void
end_package(fcode_env_t * env)842 end_package(fcode_env_t *env)
843 {
844 	finish_device(env);
845 	close_instance_chain(env, MYSELF, 0);
846 	device_end(env);
847 	MYSELF = NULL;
848 }
849 
850 void
exec_parent_method(fcode_env_t * env)851 exec_parent_method(fcode_env_t *env)
852 {
853 	instance_t *old_myself;
854 	instance_t *myself;
855 	device_t *device;
856 	char *method;
857 	fstack_t d;
858 
859 	check_my_self(env, "exec-parent-method");
860 	old_myself = MYSELF;
861 	MYSELF = MYSELF->parent;
862 
863 	method = (char *)DS[-1];
864 	debug_msg(DEBUG_FIND_FCODE, "exec_parent_method: '%s'\n", method);
865 
866 	check_my_self(env, "exec-parent-method");
867 	device = MYSELF->device;
868 	do_push_package(env, device);
869 	PUSH(DS, (fstack_t)device);
870 	REVERT_PHANDLE(env, TOS, device);
871 	find_method(env);
872 	d = POP(DS);
873 	if (d) {
874 		debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'/%x"
875 		    " execute\n", method, (int)TOS);
876 		execute(env);
877 		PUSH(DS, TRUE);
878 	} else {
879 		debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'"
880 		    " not found\n", method);
881 		PUSH(DS, FALSE);
882 	}
883 	MYSELF = old_myself;
884 	do_push_package(env, MYSELF->device);
885 }
886 
887 void
dump_device(fcode_env_t * env)888 dump_device(fcode_env_t *env)
889 {
890 	device_t *phandle;
891 	int i;
892 
893 	CONVERT_PHANDLE(env, phandle, POP(DS));
894 	log_message(MSG_DEBUG, "Node:      %p\n", phandle);
895 	log_message(MSG_DEBUG, "  Parent:  (%8p) %p\n",
896 	    &phandle->parent, phandle->parent);
897 	log_message(MSG_DEBUG, "  Child:   (%8p) %p\n",
898 	    &phandle->child, phandle->child);
899 	log_message(MSG_DEBUG, "  Peer:    (%8p) %p\n",
900 	    &phandle->peer, phandle->peer);
901 	log_message(MSG_DEBUG, "  Private: (%8p) %p\n",
902 	    &phandle->private, phandle->private);
903 	log_message(MSG_DEBUG, "  Props:   (%8p) %p\n",
904 	    &phandle->properties, phandle->properties);
905 	log_message(MSG_DEBUG, "  Voc:     (%8p) %p\n",
906 	    &phandle->vocabulary, phandle->vocabulary);
907 	log_message(MSG_DEBUG, "  sizes:   (%8p) %d %d\n",
908 	    &phandle->data_size,
909 	    phandle->data_size[INIT_DATA],
910 	    phandle->data_size[UINIT_DATA]);
911 	log_message(MSG_DEBUG, "  my_space: %x\n", phandle->my_space);
912 	log_message(MSG_DEBUG, "  my_addr :");
913 	for (i = 0; i < MAX_MY_ADDR; i++)
914 		log_message(MSG_DEBUG, " %x", (int)phandle->my_addr[i]);
915 	log_message(MSG_DEBUG, "\n");
916 	log_message(MSG_DEBUG, "  data:    (%8p)\n", phandle->init_data);
917 	for (i = 0; i < phandle->data_size[INIT_DATA]; i++) {
918 		log_message(MSG_DEBUG, "    %3d  -> (%8p) %x\n", i,
919 		    &phandle->init_data[i], phandle->init_data[i]);
920 	}
921 }
922 
923 void
dump_instance(fcode_env_t * env)924 dump_instance(fcode_env_t *env)
925 {
926 	int i;
927 	instance_t *ihandle;
928 
929 	ihandle = (instance_t *)POP(DS);
930 	log_message(MSG_DEBUG, "Ihandle:      %p\n", ihandle);
931 	log_message(MSG_DEBUG, "  Parent:  (%8p) %p\n",
932 	    &ihandle->parent, ihandle->parent);
933 	log_message(MSG_DEBUG, "  Device:  (%8p) %p\n",
934 	    &ihandle->device, ihandle->device);
935 	log_message(MSG_DEBUG, "  args:     '%s'\n",
936 	    ((ihandle->my_args) ? ihandle->my_args : ""));
937 	log_message(MSG_DEBUG, "  my-space: %x\n", ihandle->my_space);
938 	log_message(MSG_DEBUG, "  my_addr :");
939 	for (i = 0; i < MAX_MY_ADDR; i++)
940 		log_message(MSG_DEBUG, " %x", (int)ihandle->my_addr[i]);
941 	log_message(MSG_DEBUG, "\n");
942 	log_message(MSG_DEBUG, "  sizes:   %d %d\n",
943 	    ihandle->device->data_size[INIT_DATA],
944 	    ihandle->device->data_size[UINIT_DATA]);
945 	log_message(MSG_DEBUG, "  data:    (%8p) %x %x\n",
946 	    ihandle->data, ihandle->data[0], ihandle->data[1]);
947 	if (ihandle->device->data_size[INIT_DATA]) {
948 		log_message(MSG_DEBUG, "  Initialised:\n");
949 		for (i = 0; i < ihandle->device->data_size[INIT_DATA]; i++) {
950 			log_message(MSG_DEBUG, "    %3d  -> (%8p) %x\n", i,
951 			    &ihandle->data[INIT_DATA][i],
952 			    ihandle->data[INIT_DATA][i]);
953 		}
954 	}
955 	if (ihandle->device->data_size[INIT_DATA]) {
956 		log_message(MSG_DEBUG, "  UnInitialised:\n");
957 		for (i = 0; i < ihandle->device->data_size[UINIT_DATA]; i++) {
958 			log_message(MSG_DEBUG, "    %3d  -> (%8p) %x\n", i,
959 			    &ihandle->data[UINIT_DATA][i],
960 			    ihandle->data[UINIT_DATA][i]);
961 		}
962 	}
963 }
964 
965 #endif
966 
967 #pragma init(_init)
968 
969 #ifdef CONVERT_HANDLES
970 static device_t	*
safe_convert_phandle(fcode_env_t * env,fstack_t d)971 safe_convert_phandle(fcode_env_t *env, fstack_t d)
972 {
973 	return ((device_t *)d);
974 }
975 
976 static fstack_t
safe_revert_phandle(fcode_env_t * env,device_t * d)977 safe_revert_phandle(fcode_env_t *env, device_t *d)
978 {
979 	return ((fstack_t)d);
980 }
981 
982 static void
safe_allocate_phandle(fcode_env_t * env)983 safe_allocate_phandle(fcode_env_t *env)
984 {
985 }
986 
987 #endif
988 
989 static void
_init(void)990 _init(void)
991 {
992 	fcode_env_t *env = initial_env;
993 	char *name = "/";
994 	device_t *d;
995 
996 	ASSERT(env);
997 	NOTICE;
998 
999 #ifdef CONVERT_HANDLES
1000 	env->convert_phandle = safe_convert_phandle;
1001 	env->revert_phandle = safe_revert_phandle;
1002 	env->allocate_phandle = safe_allocate_phandle;
1003 #endif
1004 
1005 	/* build the root node */
1006 	d = create_phandle(env, NULL);
1007 	env->current_device = d;
1008 	env->root_node = d;
1009 	push_a_string(env, name);
1010 	device_name(env);
1011 	env->current_device = NULL;
1012 
1013 	create_my_self(env);
1014 	create_my_space(env);
1015 
1016 	P1275(0x102, 0,		"my-address",		my_address);
1017 	/* Fcode 0x103 "my-space" is created using create_internal_value */
1018 
1019 	P1275(0x11f, 0,		"new-device",		new_device);
1020 
1021 	P1275(0x127, 0,		"finish-device",	finish_device);
1022 
1023 	FCODE(0x129, 0,		"push-package",		push_package);
1024 	FCODE(0x12a, 0,		"pop-package",		pop_package);
1025 	FCODE(0x12b, 0,		"interpose",		interpose);
1026 
1027 	P1275(0x202, 0,		"my-args",		my_args);
1028 	/* Fcode 0x203 "my-self" is created using create_internal_value */
1029 	P1275(0x204, 0,		"find-package",		find_package);
1030 	P1275(0x205, 0,		"open-package",		open_package);
1031 	P1275(0x206, 0,		"close-package",	close_package);
1032 	P1275(0x207, 0,		"find-method",		find_method);
1033 	P1275(0x208, 0,		"call-package",		call_package);
1034 	P1275(0x209, 0,		"$call-parent",		dollar_call_parent);
1035 	P1275(0x20a, 0,		"my-parent",		my_parent);
1036 	P1275(0x20b, 0,		"ihandle>phandle",	ihandle_to_phandle);
1037 
1038 	P1275(0x20d, 0,		"my-unit",		my_unit);
1039 	P1275(0x20e, 0,		"$call-method",		dollar_call_method);
1040 	P1275(0x20f, 0,		"$open-package",	dollar_open_package);
1041 
1042 	P1275(0x23b, 0,		"child",		child_node);
1043 	P1275(0x23c, 0,		"peer",			peer_node);
1044 
1045 	P1275(0x23f, 0,		"set-args",		set_args);
1046 
1047 	FORTH(IMMEDIATE,	"root-node",		root_node);
1048 	FORTH(0,		"current-device",	current_device);
1049 	FORTH(0,		"pwd$",			pwd_dollar);
1050 	FORTH(IMMEDIATE,	"pwd",			pwd);
1051 	FORTH(IMMEDIATE,	"ls",			do_ls);
1052 	FORTH(IMMEDIATE,	"(cd)",			paren_cd);
1053 	FORTH(IMMEDIATE,	"cd",			do_cd);
1054 	FORTH(IMMEDIATE,	"device-end",		device_end);
1055 	FORTH(0,		"select-dev",		do_select_dev);
1056 	FORTH(0,		"unselect-dev",		do_unselect_dev);
1057 	FORTH(0,		"begin-package",	begin_package);
1058 	FORTH(0,		"end-package",		end_package);
1059 	FORTH(IMMEDIATE,	"dump-device",		dump_device);
1060 	FORTH(IMMEDIATE,	"dump-instance",	dump_instance);
1061 	FORTH(0,		"exec-parent-method",	exec_parent_method);
1062 }
1063