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