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