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