2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <stddef.h>
2N/A#include <string.h>
2N/A
2N/A#include <fcode/private.h>
2N/A#include <fcode/log.h>
2N/A
2N/A#include <fcdriver/fcdriver.h>
2N/A
2N/A#define MIN_VALUES 100
2N/A
2N/Astatic void
2N/Acheck_my_self(fcode_env_t *env, char *fn)
2N/A{
2N/A if (!MYSELF)
2N/A forth_abort(env, "%s: MYSELF is NULL", fn);
2N/A}
2N/A
2N/Auint_t
2N/Aget_number_of_parent_address_cells(fcode_env_t *env)
2N/A{
2N/A uint_t ncells;
2N/A device_t *d;
2N/A static char func_name[] = "get_number_of_parent_address_cells";
2N/A
2N/A if (MYSELF == NULL) /* Kludge for testing */
2N/A return (2);
2N/A d = MYSELF->device;
2N/A ncells = d->parent_adr_cells;
2N/A if (ncells == 0) {
2N/A ncells = get_default_intprop(env, "#address-cells", d->parent,
2N/A 2);
2N/A if (ncells > MAX_MY_ADDR) {
2N/A log_message(MSG_ERROR, "%s: %s:"
2N/A " ncells (%d) > MAX_MY_ADDR (%d)\n", func_name,
2N/A get_path(env, d->parent), ncells, MAX_MY_ADDR);
2N/A ncells = MAX_MY_ADDR;
2N/A }
2N/A d->parent_adr_cells = ncells;
2N/A }
2N/A return (ncells);
2N/A}
2N/A
2N/Ainstance_t *
2N/Acreate_ihandle(fcode_env_t *env, device_t *phandle, instance_t *parent)
2N/A{
2N/A instance_t *ihandle;
2N/A int i;
2N/A
2N/A ihandle = MALLOC(sizeof (instance_t));
2N/A
2N/A i = max(phandle->data_size[INIT_DATA], MIN_VALUES);
2N/A ihandle->data[INIT_DATA] = MALLOC(sizeof (fstack_t) * i);
2N/A memcpy(ihandle->data[INIT_DATA], phandle->init_data,
2N/A (size_t) (sizeof (fstack_t) * i));
2N/A
2N/A i = max(phandle->data_size[UINIT_DATA], MIN_VALUES);
2N/A ihandle->data[UINIT_DATA] = MALLOC(sizeof (fstack_t) * i);
2N/A
2N/A ihandle->my_space = phandle->my_space;
2N/A memcpy(ihandle->my_addr, phandle->my_addr, sizeof (ihandle->my_addr));
2N/A ihandle->parent = parent;
2N/A ihandle->device = phandle;
2N/A return (ihandle);
2N/A}
2N/A
2N/Adevice_t *
2N/Acreate_phandle(fcode_env_t *env, device_t *parent)
2N/A{
2N/A device_t *phandle;
2N/A
2N/A phandle = MALLOC(sizeof (device_t));
2N/A phandle->init_data = MALLOC(sizeof (fstack_t) * MIN_VALUES);
2N/A phandle->data_size[INIT_DATA] = 0;
2N/A phandle->data_size[UINIT_DATA] = 0;
2N/A phandle->parent = parent;
2N/A return (phandle);
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Ado_push_package(fcode_env_t *env, device_t *d)
2N/A{
2N/A do_previous(env);
2N/A do_also(env);
2N/A if (d != NULL) {
2N/A CONTEXT = (token_t *)(&d->vocabulary);
2N/A debug_msg(DEBUG_CONTEXT, "CONTEXT:push_package: %s%d/%p/%p\n",
2N/A get_path(env, d), env->order_depth, CONTEXT, env->current);
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Apush_package(fcode_env_t *env)
2N/A{
2N/A device_t *d;
2N/A phandle_t ph;
2N/A
2N/A CHECK_DEPTH(env, 1, "push-package");
2N/A ph = POP(DS);
2N/A CONVERT_PHANDLE(env, d, ph);
2N/A do_push_package(env, d);
2N/A}
2N/A
2N/Astatic void
2N/Apop_package(fcode_env_t *env)
2N/A{
2N/A do_previous(env);
2N/A do_definitions(env);
2N/A}
2N/A
2N/Astatic void
2N/Ainterpose(fcode_env_t *env)
2N/A{
2N/A TODO; /* interpose - not yet implemented */
2N/A}
2N/A
2N/Avoid
2N/Aactivate_device(fcode_env_t *env, device_t *d)
2N/A{
2N/A env->current_device = d;
2N/A do_push_package(env, d);
2N/A do_definitions(env);
2N/A}
2N/A
2N/Avoid
2N/Adeactivate_device(fcode_env_t *env, device_t *d)
2N/A{
2N/A env->current_device = d;
2N/A do_previous(env);
2N/A if (d != NULL) {
2N/A CONTEXT = (token_t *)(&d->vocabulary);
2N/A debug_msg(DEBUG_CONTEXT, "CONTEXT:deactivate_device:"
2N/A " %s%d/%p/%p\n", get_path(env, d), env->order_depth,
2N/A CONTEXT, env->current);
2N/A }
2N/A do_definitions(env);
2N/A}
2N/A
2N/Avoid
2N/Aroot_node(fcode_env_t *env)
2N/A{
2N/A do_also(env);
2N/A activate_device(env, env->root_node);
2N/A}
2N/A
2N/Avoid
2N/Achild_node(fcode_env_t *env)
2N/A{
2N/A device_t *d;
2N/A
2N/A CHECK_DEPTH(env, 1, "child");
2N/A CONVERT_PHANDLE(env, d, TOS);
2N/A TOS = (fstack_t)d->child;
2N/A REVERT_PHANDLE(env, TOS, d->child);
2N/A}
2N/A
2N/Avoid
2N/Apeer_node(fcode_env_t *env)
2N/A{
2N/A device_t *d;
2N/A
2N/A CHECK_DEPTH(env, 1, "peer");
2N/A CONVERT_PHANDLE(env, d, TOS);
2N/A REVERT_PHANDLE(env, TOS, d->peer);
2N/A}
2N/A
2N/Avoid
2N/Anew_device(fcode_env_t *env)
2N/A{
2N/A device_t *phandle, *parent;
2N/A device_t *peer;
2N/A
2N/A check_my_self(env, "new-device");
2N/A
2N/A parent = MYSELF->device;
2N/A phandle = create_phandle(env, parent);
2N/A MYSELF = create_ihandle(env, phandle, MYSELF);
2N/A activate_device(env, phandle);
2N/A if (parent->child) {
2N/A /* Insert new child at end of peer list */
2N/A for (peer = parent->child; peer->peer; peer = peer->peer)
2N/A ;
2N/A peer->peer = phandle;
2N/A } else
2N/A parent->child = phandle; /* First child */
2N/A ALLOCATE_PHANDLE(env);
2N/A}
2N/A
2N/Avoid
2N/Afinish_device(fcode_env_t *env)
2N/A{
2N/A fstack_t *mem;
2N/A device_t *my_dev, *parent_dev;
2N/A instance_t *parent, *myself = MYSELF;
2N/A int n;
2N/A
2N/A check_my_self(env, "finish-device");
2N/A ASSERT(myself->device);
2N/A ASSERT(env->current_device);
2N/A n = myself->device->data_size[INIT_DATA];
2N/A
2N/A /*
2N/A * Paranoia.. reserve a little more instance data than we need
2N/A */
2N/A mem = MALLOC(sizeof (fstack_t) * (n+8));
2N/A memcpy(mem, MYSELF->device->init_data, sizeof (fstack_t) * n);
2N/A FREE(myself->device->init_data);
2N/A my_dev = myself->device;
2N/A my_dev->init_data = mem;
2N/A parent = MYSELF->parent;
2N/A parent_dev = env->current_device->parent;
2N/A FREE(MYSELF);
2N/A MYSELF = parent;
2N/A activate_device(env, parent_dev);
2N/A}
2N/A
2N/Astatic void
2N/Acreate_internal_value(fcode_env_t *env, char *name, int offset, int token)
2N/A{
2N/A header(env, name, strlen(name), 0);
2N/A COMPILE_TOKEN(&noop);
2N/A EXPOSE_ACF;
2N/A if (token) {
2N/A SET_TOKEN(token, 0, name, LINK_TO_ACF(env->lastlink));
2N/A }
2N/A PUSH(DS, offset);
2N/A lcomma(env);
2N/A set_internal_value_actions(env);
2N/A}
2N/A
2N/Astatic void
2N/Acreate_my_self(fcode_env_t *env)
2N/A{
2N/A int offset = offsetof(fcode_env_t, my_self);
2N/A
2N/A create_internal_value(env, "my-self", offset, 0x203);
2N/A}
2N/A
2N/Astatic void
2N/Acreate_my_space(fcode_env_t *env)
2N/A{
2N/A int offset = offsetof(instance_t, my_space);
2N/A
2N/A create_internal_value(env, "my-space", -offset, 0x103);
2N/A}
2N/A
2N/Avoid
2N/Amy_address(fcode_env_t *env)
2N/A{
2N/A fstack_t *adr_ptr;
2N/A uint_t ncells;
2N/A
2N/A check_my_self(env, "my-address");
2N/A ncells = get_number_of_parent_address_cells(env);
2N/A adr_ptr = MYSELF->my_addr;
2N/A while (--ncells) {
2N/A PUSH(DS, *adr_ptr);
2N/A adr_ptr++;
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Amy_unit(fcode_env_t *env)
2N/A{
2N/A check_my_self(env, "my-unit");
2N/A my_address(env);
2N/A PUSH(DS, MYSELF->my_space);
2N/A}
2N/A
2N/Astatic void
2N/Amy_args(fcode_env_t *env)
2N/A{
2N/A check_my_self(env, "my-args");
2N/A PUSH(DS, (fstack_t)MYSELF->my_args);
2N/A PUSH(DS, (fstack_t)MYSELF->my_args_len);
2N/A}
2N/A
2N/Aint
2N/Acall_my_parent(fcode_env_t *env, char *method)
2N/A{
2N/A push_a_string(env, method);
2N/A dollar_call_parent(env);
2N/A return (env->last_error);
2N/A}
2N/A
2N/Avoid
2N/Aset_args(fcode_env_t *env)
2N/A{
2N/A int args_len;
2N/A common_data_t *cdp;
2N/A uint_t ncells;
2N/A fstack_t *adr_ptr, *adr_ptr1, space;
2N/A
2N/A CHECK_DEPTH(env, 4, "set-args");
2N/A
2N/A check_my_self(env, "set-args");
2N/A
2N/A /*
2N/A * Handle args argument of set-args.
2N/A */
2N/A if (MYSELF->my_args) {
2N/A FREE(MYSELF->my_args);
2N/A MYSELF->my_args = NULL;
2N/A }
2N/A two_swap(env);
2N/A MYSELF->my_args = pop_a_duped_string(env, &args_len);
2N/A MYSELF->my_args_len = args_len;
2N/A
2N/A if (call_my_parent(env, "decode-unit"))
2N/A forth_abort(env, "set-args: decode-unit failed");
2N/A
2N/A ncells = get_number_of_parent_address_cells(env);
2N/A
2N/A /*
2N/A * Kludge: For GP2, my-space comes from decode-unit hi.address.
2N/A * for PCI, my-space from decode-unit won't have the bus#, so we need
2N/A * to get it from config_address. Unfortunately, there is no easy
2N/A * way to figure out here which one we're looking at. We take the
2N/A * expediant of or'ing the two values together.
2N/A */
2N/A space = POP(DS); /* pop phys.hi */
2N/A if ((cdp = (common_data_t *)env->private) != NULL)
2N/A space |= cdp->fc.config_address;
2N/A
2N/A MYSELF->device->my_space = MYSELF->my_space = space;
2N/A
2N/A adr_ptr = MYSELF->my_addr;
2N/A adr_ptr1 = MYSELF->device->my_addr;
2N/A while (--ncells) {
2N/A *adr_ptr++ = *adr_ptr1++ = POP(DS);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Amy_parent(fcode_env_t *env)
2N/A{
2N/A check_my_self(env, "my-parent");
2N/A PUSH(DS, (fstack_t)MYSELF->parent);
2N/A}
2N/A
2N/Ainstance_t *
2N/Aopen_instance_chain(fcode_env_t *env, device_t *phandle, int exec)
2N/A{
2N/A instance_t *parent;
2N/A
2N/A if (!phandle)
2N/A return (NULL);
2N/A parent = open_instance_chain(env, phandle->parent, exec);
2N/A return (create_ihandle(env, phandle, parent));
2N/A}
2N/A
2N/Avoid
2N/Aclose_instance_chain(fcode_env_t *env, instance_t *ihandle, int exec)
2N/A{
2N/A instance_t *parent;
2N/A
2N/A if (ihandle) {
2N/A parent = ihandle->parent;
2N/A close_instance_chain(env, parent, exec);
2N/A if (ihandle->my_args)
2N/A FREE(ihandle->my_args);
2N/A FREE(ihandle);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Abegin_package(fcode_env_t *env)
2N/A{
2N/A fstack_t ok;
2N/A char *name;
2N/A
2N/A CHECK_DEPTH(env, 6, "begin-package");
2N/A two_dup(env);
2N/A name = pop_a_string(env, NULL);
2N/A find_package(env);
2N/A ok = POP(DS);
2N/A if (ok) {
2N/A PUSH(DS, 0);
2N/A PUSH(DS, 0);
2N/A rot(env);
2N/A open_package(env);
2N/A MYSELF = (instance_t *)POP(DS);
2N/A check_my_self(env, "begin-package");
2N/A new_device(env);
2N/A set_args(env);
2N/A } else {
2N/A log_message(MSG_INFO, "Package '%s' not found\n", name);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aopen_package(fcode_env_t *env)
2N/A{
2N/A device_t *phandle;
2N/A instance_t *ihandle;
2N/A int len;
2N/A
2N/A CHECK_DEPTH(env, 3, "open-package");
2N/A CONVERT_PHANDLE(env, phandle, POP(DS));
2N/A ihandle = open_instance_chain(env, phandle, 1);
2N/A ihandle->my_args = pop_a_duped_string(env, &len);
2N/A ihandle->my_args_len = len;
2N/A PUSH(DS, (fstack_t)ihandle);
2N/A}
2N/A
2N/Avoid
2N/Adollar_open_package(fcode_env_t *env)
2N/A{
2N/A fstack_t ok;
2N/A
2N/A CHECK_DEPTH(env, 4, "$open-package");
2N/A find_package(env);
2N/A ok = POP(DS);
2N/A if (ok) {
2N/A open_package(env);
2N/A } else {
2N/A (void) POP(DS);
2N/A (void) POP(DS);
2N/A PUSH(DS, 0);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aclose_package(fcode_env_t *env)
2N/A{
2N/A instance_t *ihandle;
2N/A
2N/A CHECK_DEPTH(env, 1, "close-package");
2N/A ihandle = (instance_t *)POP(DS);
2N/A close_instance_chain(env, ihandle, 1);
2N/A}
2N/A
2N/Astatic void (*find_method_hook)(fcode_env_t *);
2N/A
2N/Avoid
2N/Aset_find_method_hook(fcode_env_t *env, void (*hook)(fcode_env_t *))
2N/A{
2N/A find_method_hook = hook;
2N/A}
2N/A
2N/Avoid
2N/Afind_method(fcode_env_t *env)
2N/A{
2N/A fstack_t d;
2N/A device_t *device;
2N/A acf_t acf = 0;
2N/A
2N/A CHECK_DEPTH(env, 3, "find-method");
2N/A if (find_method_hook) {
2N/A (*find_method_hook)(env);
2N/A if (TOS) /* Found it */
2N/A return;
2N/A POP(DS);
2N/A }
2N/A
2N/A d = POP(DS);
2N/A CONVERT_PHANDLE(env, device, d);
2N/A PUSH(DS, (fstack_t)&device->vocabulary);
2N/A acf = voc_find(env);
2N/A PUSH(DS, (fstack_t)acf);
2N/A if (acf) {
2N/A PUSH(DS, TRUE);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * 'call-package' Fcode
2N/A */
2N/Avoid
2N/Acall_package(fcode_env_t *env)
2N/A{
2N/A instance_t *ihandle, *saved_myself;
2N/A
2N/A CHECK_DEPTH(env, 2, "call-package");
2N/A ihandle = (instance_t *)POP(DS);
2N/A saved_myself = MYSELF;
2N/A MYSELF = ihandle;
2N/A execute(env);
2N/A MYSELF = saved_myself;
2N/A}
2N/A
2N/Avoid
2N/Aihandle_to_phandle(fcode_env_t *env)
2N/A{
2N/A instance_t *i;
2N/A
2N/A CHECK_DEPTH(env, 1, "ihandle>phandle");
2N/A i = (instance_t *)TOS;
2N/A REVERT_PHANDLE(env, TOS, i->device);
2N/A}
2N/A
2N/Achar *
2N/Aget_package_name(fcode_env_t *env, device_t *d)
2N/A{
2N/A char *name;
2N/A prop_t *prop;
2N/A
2N/A prop = lookup_package_property(env, "name", d);
2N/A if (prop == NULL) {
2N/A name = "<Unnamed>";
2N/A } else {
2N/A name = (char *)prop->data;
2N/A }
2N/A return (name);
2N/A}
2N/A
2N/Astatic char *package_search_path = "/packages:/openprom";
2N/A
2N/Adevice_t *
2N/Amatch_package_path(fcode_env_t *env, char *path)
2N/A{
2N/A device_t *d;
2N/A char *name;
2N/A int len;
2N/A
2N/A if (*path == '/') {
2N/A d = env->root_node->child;
2N/A path++;
2N/A } else
2N/A d = env->current_device;
2N/A while (*path != '\0' && d != NULL) {
2N/A name = get_package_name(env, d);
2N/A len = strlen(name);
2N/A if (strncmp(name, path, len) == 0) {
2N/A path += len;
2N/A if (*path == '\0') {
2N/A return (d);
2N/A }
2N/A /* skip the '/' */
2N/A if (*path++ != '/')
2N/A break;
2N/A d = d->child;
2N/A } else {
2N/A d = d->peer;
2N/A }
2N/A }
2N/A return (NULL);
2N/A}
2N/A
2N/Adevice_t *
2N/Alocate_package(fcode_env_t *env, char *start)
2N/A{
2N/A device_t *d;
2N/A char *p, *next_p;
2N/A char *tpath, *fpath;
2N/A
2N/A if ((d = match_package_path(env, start)) != NULL)
2N/A return (d);
2N/A
2N/A /*
2N/A * ignore starting '/'
2N/A */
2N/A if (*start == '/')
2N/A *start++;
2N/A
2N/A fpath = STRDUP(package_search_path);
2N/A for (p = fpath; p != NULL; p = next_p) {
2N/A if ((next_p = strchr(p, ':')) != NULL)
2N/A *next_p++ = '\0';
2N/A tpath = MALLOC(strlen(p) + strlen(start) + 2);
2N/A sprintf(tpath, "%s/%s", p, start);
2N/A if ((d = match_package_path(env, tpath)) != NULL) {
2N/A FREE(fpath);
2N/A FREE(tpath);
2N/A return (d);
2N/A }
2N/A FREE(tpath);
2N/A }
2N/A FREE(fpath);
2N/A return (NULL);
2N/A}
2N/A
2N/Avoid
2N/Afind_package(fcode_env_t *env)
2N/A{
2N/A char *path;
2N/A device_t *package;
2N/A fstack_t ph = 0;
2N/A
2N/A CHECK_DEPTH(env, 2, "find-package");
2N/A if ((path = pop_a_duped_string(env, NULL)) != NULL) {
2N/A if (strcmp(path, "/") == 0)
2N/A package = env->root_node;
2N/A else
2N/A package = locate_package(env, path);
2N/A FREE(path);
2N/A REVERT_PHANDLE(env, ph, package);
2N/A }
2N/A PUSH(DS, ph);
2N/A if (package)
2N/A PUSH(DS, TRUE);
2N/A}
2N/A
2N/Astatic void
2N/Aencode_unit_hack(fcode_env_t *env)
2N/A{
2N/A int hi, i;
2N/A uint_t ncells = get_number_of_parent_address_cells(env);
2N/A
2N/A for (i = 0; i < ncells; i++)
2N/A POP(DS);
2N/A push_a_string(env, NULL);
2N/A}
2N/A
2N/Avoid
2N/Adollar_call_method(fcode_env_t *env)
2N/A{
2N/A instance_t *old_myself;
2N/A instance_t *myself;
2N/A device_t *device;
2N/A char *method;
2N/A
2N/A CHECK_DEPTH(env, 3, "$call-method");
2N/A check_my_self(env, "$call-method");
2N/A old_myself = MYSELF;
2N/A myself = (instance_t *)POP(DS);
2N/A
2N/A method = (char *)DS[-1];
2N/A debug_msg(DEBUG_CALL_METHOD, "$call_method %s\n", method);
2N/A
2N/A if (old_myself && !myself) {
2N/A /* We hit the root of our tree */
2N/A device = old_myself->device;
2N/A return;
2N/A }
2N/A
2N/A MYSELF = myself;
2N/A check_my_self(env, "$call-method");
2N/A device = MYSELF->device;
2N/A do_push_package(env, device);
2N/A PUSH(DS, (fstack_t)device);
2N/A REVERT_PHANDLE(env, TOS, device);
2N/A find_method(env);
2N/A if (TOS) {
2N/A (void) POP(DS);
2N/A execute(env);
2N/A } else if (strcmp(method, "encode-unit") == 0) {
2N/A encode_unit_hack(env);
2N/A } else {
2N/A throw_from_fclib(env, 1, "Unimplemented package method: %s%s",
2N/A get_path(env, device), method);
2N/A }
2N/A MYSELF = old_myself;
2N/A do_push_package(env, MYSELF->device);
2N/A}
2N/A
2N/Avoid
2N/Adollar_call_parent(fcode_env_t *env)
2N/A{
2N/A CHECK_DEPTH(env, 2, "$call-parent");
2N/A
2N/A check_my_self(env, "$call-parent");
2N/A
2N/A PUSH(DS, (fstack_t)MYSELF->parent);
2N/A dollar_call_method(env);
2N/A}
2N/A
2N/A#ifdef DEBUG
2N/Avoid
2N/Acurrent_device(fcode_env_t *env)
2N/A{
2N/A PUSH(DS, (fstack_t)&env->current_device);
2N/A}
2N/A
2N/Achar *
2N/Aget_path(fcode_env_t *env, device_t *d)
2N/A{
2N/A char *pre_path, *name, *path;
2N/A int n;
2N/A
2N/A if (d->parent)
2N/A pre_path = get_path(env, d->parent);
2N/A else
2N/A pre_path = STRDUP("");
2N/A
2N/A name = get_package_name(env, d);
2N/A n = strlen(pre_path) + strlen(name) + 1;
2N/A path = MALLOC(n);
2N/A strcpy(path, pre_path);
2N/A strcat(path, name);
2N/A if (d->child && d->parent)
2N/A strcat(path, "/");
2N/A FREE(pre_path);
2N/A return (path);
2N/A}
2N/A
2N/Astatic void
2N/Apwd_dollar(fcode_env_t *env)
2N/A{
2N/A if (env->current_device)
2N/A push_a_string(env, get_path(env, env->current_device));
2N/A else
2N/A push_a_string(env, NULL);
2N/A}
2N/A
2N/Avoid
2N/Apwd(fcode_env_t *env)
2N/A{
2N/A if (env->current_device) {
2N/A log_message(MSG_INFO, "%s\n",
2N/A get_path(env, env->current_device));
2N/A } else {
2N/A log_message(MSG_INFO, "No device context\n");
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Ado_ls(fcode_env_t *env)
2N/A{
2N/A device_t *d;
2N/A
2N/A if (env->current_device == NULL) {
2N/A log_message(MSG_INFO, "No device context\n");
2N/A return;
2N/A }
2N/A
2N/A d = env->current_device->child;
2N/A while (d) {
2N/A char *name;
2N/A fstack_t ph;
2N/A name = get_package_name(env, d);
2N/A REVERT_PHANDLE(env, ph, d);
2N/A log_message(MSG_INFO, "%llx %s\n", (uint64_t)ph, name);
2N/A d = d->peer;
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aparen_cd(fcode_env_t *env)
2N/A{
2N/A char *str;
2N/A device_t *p;
2N/A
2N/A str = pop_a_string(env, NULL);
2N/A if (strcmp(str, "/") == 0) {
2N/A root_node(env);
2N/A return;
2N/A }
2N/A
2N/A if (env->current_device == NULL) {
2N/A log_message(MSG_INFO, "No device context\n");
2N/A return;
2N/A }
2N/A
2N/A if (strcmp(str, "..") == 0)
2N/A p = env->current_device->parent;
2N/A else {
2N/A device_t *n = env->current_device->child;
2N/A
2N/A p = NULL;
2N/A while (n) {
2N/A char *name;
2N/A
2N/A name = get_package_name(env, n);
2N/A if (strcmp(name, str) == 0) {
2N/A p = n;
2N/A break;
2N/A }
2N/A n = n->peer;
2N/A }
2N/A }
2N/A
2N/A if (p) {
2N/A activate_device(env, p);
2N/A } else {
2N/A log_message(MSG_INFO, "No such node: %s\n", str);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Ado_cd(fcode_env_t *env)
2N/A{
2N/A parse_word(env);
2N/A paren_cd(env);
2N/A}
2N/A
2N/Avoid
2N/Ado_unselect_dev(fcode_env_t *env)
2N/A{
2N/A check_my_self(env, "unselect-dev");
2N/A PUSH(DS, (fstack_t)MYSELF);
2N/A close_package(env);
2N/A deactivate_device(env, NULL);
2N/A}
2N/A
2N/Avoid
2N/Ado_select_dev(fcode_env_t *env)
2N/A{
2N/A PUSH(DS, 0);
2N/A PUSH(DS, 0);
2N/A two_swap(env);
2N/A dollar_open_package(env);
2N/A if (TOS) {
2N/A MYSELF = (instance_t *)POP(DS);
2N/A check_my_self(env, "select-dev");
2N/A activate_device(env, MYSELF->device);
2N/A } else {
2N/A drop(env);
2N/A log_message(MSG_INFO, "Can't open package\n");
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Adevice_end(fcode_env_t *env)
2N/A{
2N/A if (env->current_device) {
2N/A deactivate_device(env, NULL);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aend_package(fcode_env_t *env)
2N/A{
2N/A finish_device(env);
2N/A close_instance_chain(env, MYSELF, 0);
2N/A device_end(env);
2N/A MYSELF = NULL;
2N/A}
2N/A
2N/Avoid
2N/Aexec_parent_method(fcode_env_t *env)
2N/A{
2N/A instance_t *old_myself;
2N/A instance_t *myself;
2N/A device_t *device;
2N/A char *method;
2N/A fstack_t d;
2N/A
2N/A check_my_self(env, "exec-parent-method");
2N/A old_myself = MYSELF;
2N/A MYSELF = MYSELF->parent;
2N/A
2N/A method = (char *)DS[-1];
2N/A debug_msg(DEBUG_FIND_FCODE, "exec_parent_method: '%s'\n", method);
2N/A
2N/A check_my_self(env, "exec-parent-method");
2N/A device = MYSELF->device;
2N/A do_push_package(env, device);
2N/A PUSH(DS, (fstack_t)device);
2N/A REVERT_PHANDLE(env, TOS, device);
2N/A find_method(env);
2N/A d = POP(DS);
2N/A if (d) {
2N/A debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'/%x"
2N/A " execute\n", method, (int)TOS);
2N/A execute(env);
2N/A PUSH(DS, TRUE);
2N/A } else {
2N/A debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'"
2N/A " not found\n", method);
2N/A PUSH(DS, FALSE);
2N/A }
2N/A MYSELF = old_myself;
2N/A do_push_package(env, MYSELF->device);
2N/A}
2N/A
2N/Avoid
2N/Adump_device(fcode_env_t *env)
2N/A{
2N/A device_t *phandle;
2N/A int i;
2N/A
2N/A CONVERT_PHANDLE(env, phandle, POP(DS));
2N/A log_message(MSG_DEBUG, "Node: %p\n", phandle);
2N/A log_message(MSG_DEBUG, " Parent: (%8p) %p\n",
2N/A &phandle->parent, phandle->parent);
2N/A log_message(MSG_DEBUG, " Child: (%8p) %p\n",
2N/A &phandle->child, phandle->child);
2N/A log_message(MSG_DEBUG, " Peer: (%8p) %p\n",
2N/A &phandle->peer, phandle->peer);
2N/A log_message(MSG_DEBUG, " Private: (%8p) %p\n",
2N/A &phandle->private, phandle->private);
2N/A log_message(MSG_DEBUG, " Props: (%8p) %p\n",
2N/A &phandle->properties, phandle->properties);
2N/A log_message(MSG_DEBUG, " Voc: (%8p) %p\n",
2N/A &phandle->vocabulary, phandle->vocabulary);
2N/A log_message(MSG_DEBUG, " sizes: (%8p) %d %d\n",
2N/A &phandle->data_size,
2N/A phandle->data_size[INIT_DATA],
2N/A phandle->data_size[UINIT_DATA]);
2N/A log_message(MSG_DEBUG, " my_space: %x\n", phandle->my_space);
2N/A log_message(MSG_DEBUG, " my_addr :");
2N/A for (i = 0; i < MAX_MY_ADDR; i++)
2N/A log_message(MSG_DEBUG, " %x", (int)phandle->my_addr[i]);
2N/A log_message(MSG_DEBUG, "\n");
2N/A log_message(MSG_DEBUG, " data: (%8p)\n", phandle->init_data);
2N/A for (i = 0; i < phandle->data_size[INIT_DATA]; i++) {
2N/A log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
2N/A &phandle->init_data[i], phandle->init_data[i]);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Adump_instance(fcode_env_t *env)
2N/A{
2N/A int i;
2N/A instance_t *ihandle;
2N/A
2N/A ihandle = (instance_t *)POP(DS);
2N/A log_message(MSG_DEBUG, "Ihandle: %p\n", ihandle);
2N/A log_message(MSG_DEBUG, " Parent: (%8p) %p\n",
2N/A &ihandle->parent, ihandle->parent);
2N/A log_message(MSG_DEBUG, " Device: (%8p) %p\n",
2N/A &ihandle->device, ihandle->device);
2N/A log_message(MSG_DEBUG, " args: '%s'\n",
2N/A ((ihandle->my_args) ? ihandle->my_args : ""));
2N/A log_message(MSG_DEBUG, " my-space: %x\n", ihandle->my_space);
2N/A log_message(MSG_DEBUG, " my_addr :");
2N/A for (i = 0; i < MAX_MY_ADDR; i++)
2N/A log_message(MSG_DEBUG, " %x", (int)ihandle->my_addr[i]);
2N/A log_message(MSG_DEBUG, "\n");
2N/A log_message(MSG_DEBUG, " sizes: %d %d\n",
2N/A ihandle->device->data_size[INIT_DATA],
2N/A ihandle->device->data_size[UINIT_DATA]);
2N/A log_message(MSG_DEBUG, " data: (%8p) %x %x\n",
2N/A ihandle->data, ihandle->data[0], ihandle->data[1]);
2N/A if (ihandle->device->data_size[INIT_DATA]) {
2N/A log_message(MSG_DEBUG, " Initialised:\n");
2N/A for (i = 0; i < ihandle->device->data_size[INIT_DATA]; i++) {
2N/A log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
2N/A &ihandle->data[INIT_DATA][i],
2N/A ihandle->data[INIT_DATA][i]);
2N/A }
2N/A }
2N/A if (ihandle->device->data_size[INIT_DATA]) {
2N/A log_message(MSG_DEBUG, " UnInitialised:\n");
2N/A for (i = 0; i < ihandle->device->data_size[UINIT_DATA]; i++) {
2N/A log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
2N/A &ihandle->data[UINIT_DATA][i],
2N/A ihandle->data[UINIT_DATA][i]);
2N/A }
2N/A }
2N/A}
2N/A
2N/A#endif
2N/A
2N/A#pragma init(_init)
2N/A
2N/A#ifdef CONVERT_HANDLES
2N/Astatic device_t *
2N/Asafe_convert_phandle(fcode_env_t *env, fstack_t d)
2N/A{
2N/A return ((device_t *)d);
2N/A}
2N/A
2N/Astatic fstack_t
2N/Asafe_revert_phandle(fcode_env_t *env, device_t *d)
2N/A{
2N/A return ((fstack_t)d);
2N/A}
2N/A
2N/Astatic void
2N/Asafe_allocate_phandle(fcode_env_t *env)
2N/A{
2N/A}
2N/A
2N/A#endif
2N/A
2N/Astatic void
2N/A_init(void)
2N/A{
2N/A fcode_env_t *env = initial_env;
2N/A char *name = "/";
2N/A device_t *d;
2N/A
2N/A ASSERT(env);
2N/A NOTICE;
2N/A
2N/A#ifdef CONVERT_HANDLES
2N/A env->convert_phandle = safe_convert_phandle;
2N/A env->revert_phandle = safe_revert_phandle;
2N/A env->allocate_phandle = safe_allocate_phandle;
2N/A#endif
2N/A
2N/A /* build the root node */
2N/A d = create_phandle(env, NULL);
2N/A env->current_device = d;
2N/A env->root_node = d;
2N/A push_a_string(env, name);
2N/A device_name(env);
2N/A env->current_device = NULL;
2N/A
2N/A create_my_self(env);
2N/A create_my_space(env);
2N/A
2N/A P1275(0x102, 0, "my-address", my_address);
2N/A /* Fcode 0x103 "my-space" is created using create_internal_value */
2N/A
2N/A P1275(0x11f, 0, "new-device", new_device);
2N/A
2N/A P1275(0x127, 0, "finish-device", finish_device);
2N/A
2N/A FCODE(0x129, 0, "push-package", push_package);
2N/A FCODE(0x12a, 0, "pop-package", pop_package);
2N/A FCODE(0x12b, 0, "interpose", interpose);
2N/A
2N/A P1275(0x202, 0, "my-args", my_args);
2N/A /* Fcode 0x203 "my-self" is created using create_internal_value */
2N/A P1275(0x204, 0, "find-package", find_package);
2N/A P1275(0x205, 0, "open-package", open_package);
2N/A P1275(0x206, 0, "close-package", close_package);
2N/A P1275(0x207, 0, "find-method", find_method);
2N/A P1275(0x208, 0, "call-package", call_package);
2N/A P1275(0x209, 0, "$call-parent", dollar_call_parent);
2N/A P1275(0x20a, 0, "my-parent", my_parent);
2N/A P1275(0x20b, 0, "ihandle>phandle", ihandle_to_phandle);
2N/A
2N/A P1275(0x20d, 0, "my-unit", my_unit);
2N/A P1275(0x20e, 0, "$call-method", dollar_call_method);
2N/A P1275(0x20f, 0, "$open-package", dollar_open_package);
2N/A
2N/A P1275(0x23b, 0, "child", child_node);
2N/A P1275(0x23c, 0, "peer", peer_node);
2N/A
2N/A P1275(0x23f, 0, "set-args", set_args);
2N/A
2N/A FORTH(IMMEDIATE, "root-node", root_node);
2N/A FORTH(0, "current-device", current_device);
2N/A FORTH(0, "pwd$", pwd_dollar);
2N/A FORTH(IMMEDIATE, "pwd", pwd);
2N/A FORTH(IMMEDIATE, "ls", do_ls);
2N/A FORTH(IMMEDIATE, "(cd)", paren_cd);
2N/A FORTH(IMMEDIATE, "cd", do_cd);
2N/A FORTH(IMMEDIATE, "device-end", device_end);
2N/A FORTH(0, "select-dev", do_select_dev);
2N/A FORTH(0, "unselect-dev", do_unselect_dev);
2N/A FORTH(0, "begin-package", begin_package);
2N/A FORTH(0, "end-package", end_package);
2N/A FORTH(IMMEDIATE, "dump-device", dump_device);
2N/A FORTH(IMMEDIATE, "dump-instance", dump_instance);
2N/A FORTH(0, "exec-parent-method", exec_parent_method);
2N/A}