diff options
Diffstat (limited to 'usr/src/lib/efcode')
100 files changed, 20313 insertions, 0 deletions
diff --git a/usr/src/lib/efcode/Makefile b/usr/src/lib/efcode/Makefile new file mode 100644 index 0000000000..4806e7a9bc --- /dev/null +++ b/usr/src/lib/efcode/Makefile @@ -0,0 +1,71 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.lib + +SUBDIRS = engine fcdriver extend packages pci gp2 upa interpreter efdaemon +TESTDIRS = fcode_test + +EFCODEDIRS= $(ROOTLIBDIR)/efcode $(ROOTLIBDIR)/efcode/$(MACH64) + +all:= TARGET= all +install:= TARGET= install +clean:= TARGET= clean +clobber:= TARGET= clobber +lint:= TARGET= lint + +.PARALLEL: $(SUBDIRS) +.KEEP_STATE: + +all clean clobber lint: $(SUBDIRS) + +$(EFCODEDIRS): + $(INS.dir) + +install: $(EFCODEDIRS) .WAIT $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +$(TESTDIRS): FRC + @cd $@; pwd; $(MAKE) all + +FRC: + +# +# Interdependencies between shared objects follow. +# + +extend fcdriver packages pci gp2 upa interpreter efdaemon: engine + +fcdriver: packages + +gp2 pci interpreter: fcdriver + +interpreter: packages extend diff --git a/usr/src/lib/efcode/Makefile.efcode b/usr/src/lib/efcode/Makefile.efcode new file mode 100644 index 0000000000..748c0294c2 --- /dev/null +++ b/usr/src/lib/efcode/Makefile.efcode @@ -0,0 +1,71 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# Common build rules for efcode shared objects. +# +# For historical reasons, these shared objects aren't explicitly versioned, so +# turn off VERS and LIBLINKS (VERS must be cleared before the inclusion of +# Makefile.lib, and LIBLINKS must be cleared afterwards). Also, because of +# the weird alternate naming scheme, we must define our own symlink macros. +# + +VERS = + +include $(SRC)/lib/Makefile.lib + +LIBS = $(DYNLIB) +LDLIBS += -lc +LIBLINKS = + +CPPFLAGS += -DDEBUG -DFCODE_INTERNAL +CPPFLAGS += -I $(SRC)/lib/efcode/include -I $(ROOT)/usr/platform/sun4u/include +DYNFLAGS += -R\$$ORIGIN + +SRCDIR = .. +EFCODE64DIR = /usr/lib/efcode/$(MACH64) +ROOTLIBDIR = $(ROOT)/usr/lib/efcode +ROOTLIBDIR64 = $(ROOT)/usr/lib/efcode/$(MACH64) +ROOTSYMLINKS64 = $(SYMLINKS:%=$(ROOTLIBDIR64)/%) + +# +# Since a number of efcode shared objects depend on fcode.so, fcdriver.so, and +# fcpackage.so, provide macros that expand to their full paths. +# +FCODE64 = $(ROOTLIBDIR64)/fcode.so +FCDRIVER64 = $(ROOTLIBDIR64)/fcdriver.so +FCPACKAGE64 = $(ROOTLIBDIR64)/fcpackage.so + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +$(ROOTSYMLINKS64): $(ROOTLIBDIR64)/$(DYNLIB) + -$(RM) $@; $(SYMLINK) $(DYNLIB) $@ + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/efcode/Makefile.subdirs b/usr/src/lib/efcode/Makefile.subdirs new file mode 100644 index 0000000000..3dd1a71017 --- /dev/null +++ b/usr/src/lib/efcode/Makefile.subdirs @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/lib/Makefile.lib + +# +# No need for 32-bit versions of these shared objects. +# +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +msg := TARGET= _msg + +.KEEP_STATE: + +all clean clobber install lint _msg: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/efcode/efdaemon/Makefile b/usr/src/lib/efcode/efdaemon/Makefile new file mode 100644 index 0000000000..30c27a7953 --- /dev/null +++ b/usr/src/lib/efcode/efdaemon/Makefile @@ -0,0 +1,69 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/efcode/efdaemon/Makefile + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 + +EFCODEDIR = $(ROOT)/usr/lib/efcode +EFCODEDIR64 = $(EFCODEDIR)/$(MACH64) + +CPPFLAGS += -DDEBUG -DFCODE_INTERNAL +CPPFLAGS += -I ../include -I $(ROOT)/usr/platform/sun4u/include + +PROG = efdaemon +EFTARGETS += $(EFCODEDIR64)/$(PROG) +EFTARGETS += $(EFCODEDIR)/efcode.sh + +MFSTDIR = $(ROOT)/var/svc/manifest/platform/sun4u +MANIFEST = efdaemon.xml +EFTARGETS += $(MFSTDIR)/$(MANIFEST) + +$(MFSTDIR)/$(MANIFEST) := FILEMODE = 0444 + +all: $(PROG) + +clean: + -$(RM) $(PROG) + +$(EFCODEDIR64)/%: % + $(INS.file) + +$(EFCODEDIR)/%.sh: %.sh + $(INS.file) + +$(MFSTDIR)/%: % + $(INS.file) + +install: all .WAIT $(EFTARGETS) + +lint: lint_PROG + +.KEEP_STATE: + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/lib/efcode/efdaemon/efcode.sh b/usr/src/lib/efcode/efdaemon/efcode.sh new file mode 100644 index 0000000000..914279b876 --- /dev/null +++ b/usr/src/lib/efcode/efdaemon/efcode.sh @@ -0,0 +1,33 @@ +#!/sbin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +# +# The open /dev/fcode file descriptor is passed by efdaemon in file +# descriptor 0, so redirecting stdin in this script is strongly discouraged. +# +/usr/lib/efcode/sparcv9/interpreter diff --git a/usr/src/lib/efcode/efdaemon/efdaemon.c b/usr/src/lib/efcode/efdaemon/efdaemon.c new file mode 100644 index 0000000000..7aba030848 --- /dev/null +++ b/usr/src/lib/efcode/efdaemon/efdaemon.c @@ -0,0 +1,185 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * efdaemon - Emebbed Fcode Interpreter daemon. + * + * Opens /dev/fcode, detaches from tty and reads a request. Upon successful + * return, invokes the Fcode interpreter via the shell script: + * /usr/lib/efcode/efcode.sh Waits for completion of the interpreter. + */ + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <strings.h> +#include <syslog.h> +#include <errno.h> +#include <sys/wait.h> + +char efcode_sh_file[] = "/usr/lib/efcode/efcode.sh"; +char dev_fcode_file[] = "/dev/fcode"; + +int debug = 0; + +int +main(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int c, fd, nbytes, status; + char tc; + pid_t pid, tpid; + long nerr = 0; + + openlog("efdaemon", LOG_PID|LOG_CONS, LOG_DAEMON); + + while ((c = getopt(argc, argv, "d")) != EOF) { + switch (c) { + + case 'd': + debug++; + break; + + case '?': + syslog(LOG_ERR, "Usage: efdaemon [ -d ]\n"); + exit(1); + } + } + + /* + * Ensure we can open /dev/fcode + */ + if ((fd = open(dev_fcode_file, O_RDONLY)) < 0) { + /* + * Only output message if debug is on. On most systems, + * /dev/fcode will not exist, so this message would pollute the + * console. + */ + if (debug) + syslog(LOG_ERR, "Can't open %s: %s\n", dev_fcode_file, + strerror(errno)); + exit(1); + } + close(fd); + + /* + * Ensure that /usr/lib/efcode/efcode.sh exists and is executable. + */ + if (access(efcode_sh_file, X_OK | R_OK)) { + syslog(LOG_ERR, "%s: %s\n", efcode_sh_file, strerror(errno)); + exit(1); + } + + /* + * Fork a child then parent exits so we're a child of initd. + */ + if ((pid = fork()) < 0) { + syslog(LOG_ERR, "Fork failed: %s\n", strerror(errno)); + exit(1); + } + if (pid) + exit(0); + + + /* + * detach from tty here. + */ + setpgrp(); + close(0); + close(1); + close(2); + (void) open("/dev/null", O_RDWR); + (void) dup(0); + (void) dup(0); + + for (;;) { + while ((fd = open(dev_fcode_file, O_RDONLY)) < 0) { + nerr++; + if (nerr == 1) + syslog(LOG_ERR, "Can't open %s: %s\n", + dev_fcode_file, strerror(errno)); + sleep(1); + } + if (nerr > 1) { + syslog(LOG_ERR, "Open on %s failed %d times\n", + dev_fcode_file, nerr); + } + nerr = 0; + nbytes = read(fd, &tc, sizeof (tc)); + if (nbytes < 0) { + syslog(LOG_ERR, "Read of %s: %s\n", dev_fcode_file, + strerror(errno)); + close(fd); + continue; + } + if (debug) + syslog(LOG_DEBUG, "Got request\n"); + while ((pid = fork()) < 0) { + nerr++; + if (nerr == 1) + syslog(LOG_ERR, "Fork failed: %s\n", + strerror(errno)); + sleep(1); + } + if ((nerr > 1) && pid) { + syslog(LOG_ERR, "Fork failed %d times\n", nerr); + } + nerr = 0; + if (pid) { + tpid = wait(&status); + if (tpid < 0) + syslog(LOG_ERR, "Wait error: %s\n", + strerror(errno)); + else if (pid != tpid) + syslog(LOG_ERR, "Wait error, expect pid: %d" + " got %d, status: %x\n", pid, tpid, status); + else if (status) + syslog(LOG_ERR, "Wait pid: %d status: %x\n", + pid, status); + else if (debug) + syslog(LOG_DEBUG, "Wait: pid: %d\n", pid); + close(fd); + continue; + } + if (debug) + syslog(LOG_DEBUG, "Child: %d processing request\n", + getpid()); + fcntl(fd, F_DUP2FD, 0); + while (execl("/bin/sh", "sh", efcode_sh_file, NULL)) { + nerr++; + if (nerr == 1) + syslog(LOG_ERR, "execl(/bin/sh) failed: %s\n", + strerror(errno)); + sleep(1); + } + } + + return (0); +} diff --git a/usr/src/lib/efcode/efdaemon/efdaemon.xml b/usr/src/lib/efcode/efdaemon/efdaemon.xml new file mode 100644 index 0000000000..415d692b88 --- /dev/null +++ b/usr/src/lib/efcode/efdaemon/efdaemon.xml @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (the "License"). You may not use this file except in compliance + with the License. + + You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + or http://www.opensolaris.org/os/licensing. + See the License for the specific language governing permissions + and limitations under the License. + + When distributing Covered Code, include this CDDL HEADER in each + file and include the License file at usr/src/OPENSOLARIS.LICENSE. + If applicable, add the following below this CDDL HEADER, with the + fields enclosed by brackets "[]" replaced with your own identifying + information: Portions Copyright [yyyy] [name of copyright owner] + + CDDL HEADER END + + ident "%Z%%M% %I% %E% SMI" + + NOTE: This service manifest is not editable; its contents will + be overwritten by package or patch operations, including + operating system upgrade. Make customizations in a different + file. +--> + +<service_bundle type='manifest' name='SUNWefcr:efdaemon'> + +<service + name='platform/sun4u/efdaemon' + type='service' + version='1'> + + <single_instance /> + + <dependency + name='single-user' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri + value='svc:/milestone/single-user:default' /> + </dependency> + + <exec_method + type='method' + name='start' + exec='/usr/lib/efcode/sparcv9/efdaemon' + timeout_seconds='30' /> + + <exec_method + type='method' + name='stop' + exec=':kill' + timeout_seconds='30' /> + + <instance name='default' enabled='false' /> + + <stability value='Unstable' /> + + <template> + <common_name> + <loctext xml:lang='C'> + embedded FCode interpreter + </loctext> + </common_name> + <documentation> + <manpage title='efdaemon' section='1M' manpath='/usr/share/man' /> + </documentation> + </template> + +</service> + +</service_bundle> diff --git a/usr/src/lib/efcode/engine/Makefile b/usr/src/lib/efcode/engine/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/engine/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/engine/Makefile.com b/usr/src/lib/efcode/engine/Makefile.com new file mode 100644 index 0000000000..fc8c6135b5 --- /dev/null +++ b/usr/src/lib/efcode/engine/Makefile.com @@ -0,0 +1,38 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = init.o interface.o signal.o forth.o fcode.o interp.o debug.o \ + env.o print.o properties.o actions.o package.o instance.o \ + alarm.o interactive.o framebuffer.o font.o fb8.o extend.o tracing.o \ + resource.o prims64.o mcookie.o log.o cleanup.o + +LIBRARY = fcode.a + +include ../../Makefile.efcode + +LDLIBS += -lrt diff --git a/usr/src/lib/efcode/engine/actions.c b/usr/src/lib/efcode/engine/actions.c new file mode 100644 index 0000000000..11fb96c363 --- /dev/null +++ b/usr/src/lib/efcode/engine/actions.c @@ -0,0 +1,399 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#define NUM_DEFAULT_ACTIONS 7 + +/* + * value_fetch and value_store are the same as "fetch" and "store", but + * we'll leave them implemented here for now. + */ +static void +value_fetch(fcode_env_t *env) +{ + variable_t *addr; + + CHECK_DEPTH(env, 1, "value_fetch"); + addr = (variable_t *)POP(DS); + PUSH(DS, (variable_t)*addr); +} + +static void +value_store(fcode_env_t *env) +{ + variable_t *addr; + + CHECK_DEPTH(env, 1, "value_store"); + addr = (variable_t *)POP(DS); + *addr = (variable_t)POP(DS); +} + +void * +get_internal_address(fcode_env_t *env) +{ + int *ptr; + + CHECK_DEPTH(env, 1, "get_internal_address"); + ptr = (int *)POP(DS); + if (*ptr > 0) + return ((uchar_t *)env + *ptr); + return ((uchar_t *)MYSELF - *ptr); +} + +void +internal_env_fetch(fcode_env_t *env) +{ + instance_t **iptr; + + CHECK_DEPTH(env, 1, "internal_env_fetch"); + iptr = (instance_t **)get_internal_address(env); + PUSH(DS, (fstack_t)(*iptr)); +} + +void +internal_env_store(fcode_env_t *env) +{ + instance_t **iptr; + + CHECK_DEPTH(env, 2, "internal_env_store"); + iptr = (instance_t **)get_internal_address(env); + *iptr = (instance_t *)POP(DS); +} + +void +internal_env_addr(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 1, "internal_env_addr"); + d = (fstack_t)get_internal_address(env); + PUSH(DS, d); +} + +void +do_buffer_data(fcode_env_t *env, token_t *d, int instance) +{ + if (!*d) { /* check if buffer not alloc'ed yet */ + token_t *buf; + + if (instance) { + int n, off; + + n = TOKEN_ROUNDUP(d[1]); + buf = alloc_instance_data(env, UINIT_DATA, n, &off); + memset(buf, 0, d[1]); + } else { + buf = (token_t *)HERE; + set_here(env, HERE + d[1], "do_buffer_data"); + } + *d = (token_t)buf; + } + PUSH(DS, *d); +} + +void +ibuffer_init(fcode_env_t *env) +{ + token_t *d; + + d = get_instance_address(env); + do_buffer_data(env, d, 1); +} + +void +buffer_init(fcode_env_t *env) +{ + token_t *d; + + CHECK_DEPTH(env, 1, "buffer_init"); + d = (token_t *)POP(DS); + do_buffer_data(env, d, 0); +} + +void +do_defer(fcode_env_t *env) +{ + fetch(env); + execute(env); +} + +token_t *value_actions[NUM_DEFAULT_ACTIONS]; +token_t value_defines[NUM_DEFAULT_ACTIONS][3] = { + { (token_t)&value_fetch, (token_t)&value_store, (token_t)&noop }, + { (token_t)&fetch_instance_data, (token_t)&set_instance_data, + (token_t)&address_instance_data }, + { (token_t)&internal_env_fetch, (token_t)&internal_env_store, + (token_t)&internal_env_addr }, + { (token_t)&do_defer, (token_t)&store, (token_t)&noop }, + { (token_t)&idefer_exec, (token_t)&set_instance_data, + (token_t)&address_instance_data }, + { (token_t)&buffer_init, (token_t)&two_drop, (token_t)&noop, }, + { (token_t)&ibuffer_init, (token_t)&two_drop, + (token_t)&address_instance_data } +}; + +int +run_action(fcode_env_t *env, acf_t acf, int action) +{ + token_t *p = (token_t *)acf; + + if ((p[0] & 1) == 0) { + log_message(MSG_WARN, "run_action: acf: %p @acf: %p not" + " indirect\n", acf, p[0]); + return (1); + } + + p = (token_t *)(p[0] & ~1); + + if (action >= p[1] || action < 0) { + log_message(MSG_WARN, "run_action: acf: %p action: %d" + " out of range: 0-%d\n", acf, action, (int)p[1]); + return (1); + } + + if (p[0] == (token_t)&do_default_action) { + fstack_t d; + + d = (fstack_t)p[action+2]; + PUSH(DS, d); + execute(env); + return (0); + } + log_message(MSG_WARN, "run_action: acf: %p/%p not default action\n", + acf, p[0]); + return (1); +} + +void +do_default_action(fcode_env_t *env) +{ + acf_t a; + + CHECK_DEPTH(env, 1, "do_default_action"); + a = (acf_t)TOS; + (void) run_action(env, (a-1), 0); +} + +void +do_set_action(fcode_env_t *env) +{ + acf_t a = (acf_t)TOS; + + CHECK_DEPTH(env, 1, "do_set_action"); + TOS += sizeof (acf_t); + (void) run_action(env, a, 1); +} + +void +action_colon(fcode_env_t *env) +{ + token_roundup(env, "action_colon"); + env->action_ptr[env->action_count] = (token_t)HERE; + COMPILE_TOKEN(&do_colon); + env->action_count++; + env->state |= 1; +} + +void +actions(fcode_env_t *env) +{ + int n; + token_t *d; + + token_roundup(env, "actions"); + d = (token_t *)HERE; + *d++ = (token_t)&do_default_action; + n = (int)POP(DS); + *d++ = n; + env->num_actions = n; + env->action_count = 0; + env->action_ptr = d; + d += n; + set_here(env, (uchar_t *)d, "actions"); +} + +void +install_actions(fcode_env_t *env, token_t *table) +{ + acf_t *dptr; + token_t p; + + dptr = (acf_t *)LINK_TO_ACF(env->lastlink); + p = (token_t)table; + p -= (sizeof (token_t) + sizeof (acf_t)); + *dptr = (acf_t)(p | 1); +} + +void +use_actions(fcode_env_t *env) +{ + if (env->state) { + TODO; /* use-actions in compile state. */ + } else { + install_actions(env, env->action_ptr); + } +} + +void +perform_action(fcode_env_t *env) +{ + int n; + acf_t a; + + CHECK_DEPTH(env, 2, "perform_action"); + n = POP(DS); + a = (acf_t)POP(DS); + PUSH(DS, (fstack_t)ACF_TO_BODY(a)); + + if (run_action(env, a, n)) { + system_message(env, "Bad Object action"); + } +} + +void +define_actions(fcode_env_t *env, int n, token_t *array) +{ + int a; + + PUSH(DS, (fstack_t)n); + actions(env); + + a = 0; + while (n--) { + action_colon(env); + COMPILE_TOKEN(&array[a]); + env->state |= 8; + semi(env); + a++; + } +} + +/* + * This is for things like my-self which have meaning to the + * forth engine but I don't want to turn them into standard forth values + * that would make the 'C' variables hard to understand, instead these + * 'global' state variables will act directly upon the native 'C' structures. + */ + +void +set_internal_value_actions(fcode_env_t *env) +{ + ASSERT(value_actions[2]); + install_actions(env, value_actions[2]); +} + +void +set_value_actions(fcode_env_t *env, int which) +{ + ASSERT((which == 0) || (which == 1)); + ASSERT(value_actions[which]); + install_actions(env, value_actions[which]); +} + +void +set_defer_actions(fcode_env_t *env, int which) +{ + ASSERT((which == 0) || (which == 1)); + ASSERT(value_actions[which+3]); + install_actions(env, value_actions[which+3]); +} + +void +set_buffer_actions(fcode_env_t *env, int which) +{ + ASSERT((which == 0) || (which == 1)); + ASSERT(value_actions[which+5]); + install_actions(env, value_actions[which+5]); +} + +#if defined(DEBUG) + +void +do_get(fcode_env_t *env) +{ + PUSH(DS, 0); + perform_action(env); +} + +void +do_set(fcode_env_t *env) +{ + PUSH(DS, 1); + perform_action(env); +} + +void +do_addr(fcode_env_t *env) +{ + PUSH(DS, 2); + perform_action(env); +} + +void +dump_actions(fcode_env_t *env) +{ + int i; + for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) { + log_message(MSG_INFO, "Action Set: %d = %p\n", i, + value_actions[i]); + } +} +#endif /* DEBUG */ + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + int i; + + ASSERT(env); + NOTICE; + + for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) { + define_actions(env, 3, value_defines[i]); + value_actions[i] = env->action_ptr; + } + +#if defined(DEBUG) + FORTH(0, "get", do_get); + FORTH(0, "set", do_set); + FORTH(0, "addr", do_addr); + FORTH(0, "dump-actions", dump_actions); + FORTH(IMMEDIATE, "actions", actions); + FORTH(IMMEDIATE, "use-actions", use_actions); + FORTH(IMMEDIATE, "action:", action_colon); + FORTH(0, "perform-action", perform_action); +#endif /* DEBUG */ +} diff --git a/usr/src/lib/efcode/engine/alarm.c b/usr/src/lib/efcode/engine/alarm.c new file mode 100644 index 0000000000..c9d4550a9d --- /dev/null +++ b/usr/src/lib/efcode/engine/alarm.c @@ -0,0 +1,101 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <fcode/private.h> + +/* + * 'user-abort' Fcode + */ +void +user_abort(fcode_env_t *env) +{ + forth_abort(env, "user-abort called"); +} + +static fstack_t alarm_xt; +static fstack_t alarm_ms; +static fcode_env_t *alarm_env; + +static void +catch_alarm(int signo) +{ + fcode_env_t *env = alarm_env; + + if (env && alarm_xt && alarm_ms) { + PUSH(DS, alarm_xt); + execute(env); + signal(SIGALRM, catch_alarm); + alarm((alarm_ms + 999)/1000); + } +} + +/* + * 'alarm' Fcode + */ +void +do_alarm(fcode_env_t *env) +{ + fstack_t ms, xt; + + CHECK_DEPTH(env, 2, "alarm"); + ms = POP(DS); + xt = POP(DS); + if (ms == 0) { + alarm(0); + signal(SIGALRM, SIG_DFL); + alarm_xt = 0; + alarm_ms = 0; + alarm_env = 0; + } else { + signal(SIGALRM, catch_alarm); + alarm_xt = xt; + alarm_ms = ms; + alarm_env = env; + alarm((ms + 999)/1000); + } +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + P1275(0x213, 0, "alarm", do_alarm); + + P1275(0x219, 0, "user-abort", user_abort); +} diff --git a/usr/src/lib/efcode/engine/cleanup.c b/usr/src/lib/efcode/engine/cleanup.c new file mode 100644 index 0000000000..898924f33a --- /dev/null +++ b/usr/src/lib/efcode/engine/cleanup.c @@ -0,0 +1,52 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#pragma fini(_fini) + +static void +_fini(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + + debug_msg(DEBUG_EXIT_WORDS|DEBUG_TOKEN_USAGE, + "Dumping interpretter state\n"); + + DEBUGF(EXIT_WORDS, dump_words(env)); + DEBUGF(TOKEN_USAGE, verify_usage(env)); + + destroy_environment(env); +} diff --git a/usr/src/lib/efcode/engine/debug.c b/usr/src/lib/efcode/engine/debug.c new file mode 100644 index 0000000000..bcdd238b94 --- /dev/null +++ b/usr/src/lib/efcode/engine/debug.c @@ -0,0 +1,1601 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#ifndef DEBUG_LVL +#define DEBUG_LVL 0 +#endif + +struct bitab { + token_t bi_ptr; + char *bi_name; + int bi_type; +}; + +struct bitab *lookup_builtin(token_t); + +static int debug_level = DEBUG_LVL; + +void +set_interpreter_debug_level(long lvl) +{ + debug_level = lvl; +} + +long +get_interpreter_debug_level(void) +{ + return (debug_level); +} + +void +output_data_stack(fcode_env_t *env, int msglevel) +{ + int i; + + log_message(msglevel, "( "); + if (DS > env->ds0) { + for (i = 0; i < (DS - env->ds0); i++) + log_message(msglevel, "%llx ", + (uint64_t)(env->ds0[i + 1])); + } else + log_message(msglevel, "<empty> "); + log_message(msglevel, ") "); +} + +void +output_return_stack(fcode_env_t *env, int show_wa, int msglevel) +{ + int i; + int anyout = 0; + + log_message(msglevel, "R:( "); + if (show_wa) { + log_message(msglevel, "%s ", + acf_backup_search(env, (acf_t)WA)); + anyout++; + } + if (IP) { + anyout++; + log_message(msglevel, "%s ", acf_backup_search(env, IP)); + } + for (i = (RS - env->rs0) - 1; i > 0; i--) { + anyout++; + log_message(msglevel, "%s ", + acf_backup_search(env, (acf_t)env->rs0[i+1])); + } + if (!anyout) + log_message(msglevel, "<empty> "); + log_message(msglevel, ") "); +} + +void +dump_comma(fcode_env_t *env, char *type) +{ + xforth_t d; + + if (strcmp(type, "x,") == 0) + d = peek_xforth(env); + else + d = TOS; + log_message(MSG_FC_DEBUG, "%s %p, %llx\n", type, HERE, (uint64_t)d); +} + +static int ndebug_names; +#define MAXDEBUG_NAMES 10 +static char *debug_names[MAXDEBUG_NAMES]; + +static int ndebug_acfs; +#define MAXDEBUG_ACFS 10 +static acf_t debug_acfs[MAXDEBUG_ACFS]; + +void +add_debug_acf(fcode_env_t *env, acf_t acf) +{ + int i; + + for (i = 0; i < ndebug_acfs; i++) + if (acf == debug_acfs[i]) + return; + + if (!within_dictionary(env, acf)) + log_message(MSG_ERROR, "Can't debug builtin\n"); + else if (ndebug_acfs >= MAXDEBUG_ACFS) + log_message(MSG_ERROR, "Too many debug ACF's\n"); + else { + debug_acfs[ndebug_acfs++] = acf; + *LINK_TO_FLAGS(ACF_TO_LINK(acf)) |= FLAG_DEBUG; + } +} + +static void +paren_debug(fcode_env_t *env) +{ + acf_t acf; + + acf = (acf_t)POP(DS); + if (!within_dictionary(env, acf)) { + log_message(MSG_INFO, "acf: %llx not in dictionary\n", + (uint64_t)acf); + return; + } + if ((acf_t)_ALIGN(acf, token_t) != acf) { + log_message(MSG_INFO, "acf: %llx not aligned\n", + (uint64_t)acf); + return; + } + if (*acf != (token_t)(&do_colon)) { + log_message(MSG_INFO, "acf: %llx not a colon-def\n", + (uint64_t)acf); + return; + } + add_debug_acf(env, acf); +} + +static void +debug(fcode_env_t *env) +{ + fstack_t d; + char *word; + acf_t acf; + + parse_word(env); + dollar_find(env); + d = POP(DS); + if (d) { + acf = (acf_t)POP(DS); + add_debug_acf(env, acf); + } else if (ndebug_names >= MAXDEBUG_NAMES) { + log_message(MSG_ERROR, "Too many forward debug words\n"); + two_drop(env); + } else { + word = pop_a_duped_string(env, NULL); + log_message(MSG_INFO, "Forward defined word: %s\n", word); + debug_names[ndebug_names++] = word; + } +} + +/* + * Eliminate dups and add vocabulary forth to end if not already on list. + */ +static void +order_to_dict_list(fcode_env_t *env, token_t *order[]) +{ + int i, j, norder = 0; + + if (env->current) + order[norder++] = env->current; + for (i = env->order_depth; i >= 0; i--) { + for (j = 0; j < norder && order[j] != env->order[i]; j++) + ; + if (j == norder) + order[norder++] = env->order[i]; + } + for (j = 0; j < norder && order[j] != (token_t *)&env->forth_voc_link; + j++) + ; + if (j == norder) + order[norder++] = (token_t *)&env->forth_voc_link; + order[norder] = NULL; +} + +static acf_t +search_all_dictionaries(fcode_env_t *env, + acf_t (*fn)(fcode_env_t *, acf_t, void *), + void *arg) +{ + token_t *order[MAX_ORDER+1]; + int i; + token_t *dptr; + acf_t acf; + + order_to_dict_list(env, order); + for (i = 0; (dptr = order[i]) != NULL; i++) { + for (dptr = (token_t *)(*dptr); dptr; + dptr = (token_t *)(*dptr)) + if ((acf = (*fn)(env, LINK_TO_ACF(dptr), arg)) != NULL) + return (acf); + } + return (NULL); +} + +char * +acf_to_str(acf_t acf) +{ + static char msg[(sizeof (acf) * 2) + 3]; + + sprintf(msg, "(%08p)", acf); + return (msg); +} + +char * +get_name_or_acf(token_t *dptr) +{ + char *name; + + if ((name = get_name(dptr)) != NULL) + return (name); + return (acf_to_str(LINK_TO_ACF(dptr))); +} + +static void +output_acf_name(acf_t acf) +{ + char *name; + token_t *dptr; + static int acf_count = 0; + + if (acf == NULL) { + if (acf_count) + log_message(MSG_INFO, "\n"); + acf_count = 0; + return; + } + dptr = ACF_TO_LINK(acf); + if ((name = get_name(dptr)) == NULL) + name = "<noname>"; + + log_message(MSG_INFO, "%24s (%08p)", name, acf); + if (++acf_count >= 2) { + log_message(MSG_INFO, "\n"); + acf_count = 0; + } else + log_message(MSG_INFO, " "); +} + +static void +dot_debug(fcode_env_t *env) +{ + int i; + token_t *dptr; + + if (ndebug_names == 0) + log_message(MSG_INFO, "No forward debug words\n"); + else { + for (i = 0; i < ndebug_names; i++) + log_message(MSG_INFO, "%s Forward\n", debug_names[i]); + } + if (ndebug_acfs == 0) + log_message(MSG_INFO, "No debug words\n"); + else { + for (i = 0; i < ndebug_acfs; i++) + log_message(MSG_INFO, "%s\n", + get_name_or_acf(ACF_TO_LINK(debug_acfs[i]))); + } +} + +static void +do_undebug(fcode_env_t *env, char *name) +{ + int i; + + for (i = 0; i < ndebug_names; i++) { + if (strcmp(debug_names[i], name) == 0) { + log_message(MSG_INFO, "Undebugging forward word %s\n", + name); + FREE(debug_names[i]); + for (i++; i < ndebug_names; i++) + debug_names[i - 1] = debug_names[i]; + ndebug_names--; + break; + } + } +} + +static void +undebug(fcode_env_t *env) +{ + fstack_t d; + acf_t acf; + flag_t *flagp; + char *name; + int i, j; + + parse_word(env); + two_dup(env); + dollar_find(env); + d = POP(DS); + if (d) { + acf = (acf_t)POP(DS); + flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf)); + if ((*flagp & FLAG_DEBUG) == 0) + log_message(MSG_WARN, "Word not debugged?\n"); + else { + log_message(MSG_INFO, "Undebugging acf: %p\n", acf); + *flagp &= ~FLAG_DEBUG; + for (i = 0; i < ndebug_acfs; i++) { + if (debug_acfs[i] == acf) { + for (j = i + 1; j < ndebug_acfs; j++) + debug_acfs[j-1] = debug_acfs[j]; + ndebug_acfs--; + break; + } + } + } + } else + two_drop(env); + name = pop_a_string(env, NULL); + do_undebug(env, name); +} + +int +name_is_debugged(fcode_env_t *env, char *name) +{ + int i; + + if (ndebug_names <= 0) + return (0); + for (i = 0; i < ndebug_names; i++) + if (strcmp(debug_names[i], name) == 0) + return (1); + return (0); +} + +/* + * This is complicated by being given ACF's to temporary compile words which + * don't have a header. + */ +int +is_debug_word(fcode_env_t *env, acf_t acf) +{ + flag_t *flagp; + int i; + + /* check to see if any words are being debugged */ + if (ndebug_acfs == 0) + return (0); + + /* only words in dictionary can be debugged */ + if (!within_dictionary(env, acf)) + return (0); + + /* check that word has "FLAG_DEBUG" on */ + flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf)); + if ((*flagp & FLAG_DEBUG) == 0) + return (0); + + /* look in table of debug acf's */ + for (i = 0; i < ndebug_acfs; i++) + if (debug_acfs[i] == acf) + return (1); + return (0); +} + +#define MAX_DEBUG_STACK 100 +token_t debug_low[MAX_DEBUG_STACK], debug_high[MAX_DEBUG_STACK]; +int debug_prev_level[MAX_DEBUG_STACK]; +int debug_curr_level[MAX_DEBUG_STACK]; +int ndebug_stack = 0; + +void +debug_set_level(fcode_env_t *env, int level) +{ + debug_curr_level[ndebug_stack - 1] = level; + set_interpreter_debug_level(level); +} + +token_t +find_semi_in_colon_def(fcode_env_t *env, acf_t acf) +{ + for (; within_dictionary(env, acf); acf++) + if (*acf == (token_t)(&semi_ptr)) + return ((token_t)acf); + return (0); +} + +void +check_for_debug_entry(fcode_env_t *env) +{ + int top; + + if (is_debug_word(env, WA) && ndebug_stack < MAX_DEBUG_STACK) { + top = ndebug_stack++; + debug_prev_level[top] = get_interpreter_debug_level(); + debug_low[top] = (token_t)WA; + if (*WA == (token_t)(&do_colon)) { + debug_high[top] = + find_semi_in_colon_def(env, WA); + } else { + debug_high[top] = 0; /* marker... */ + } + debug_set_level(env, DEBUG_STEPPING); + output_step_message(env); + } +} + +void +check_for_debug_exit(fcode_env_t *env) +{ + if (ndebug_stack) { + int top = ndebug_stack - 1; + + if (debug_high[top] == 0) { + set_interpreter_debug_level(debug_prev_level[top]); + ndebug_stack--; + } else if ((token_t)IP >= debug_low[top] && + (token_t)IP <= debug_high[top]) { + set_interpreter_debug_level(debug_curr_level[top]); + } else { + set_interpreter_debug_level(debug_prev_level[top]); + } + } +} + +void +check_semi_debug_exit(fcode_env_t *env) +{ + if (ndebug_stack) { + int top = ndebug_stack - 1; + + if ((token_t)(IP - 1) == debug_high[top]) { + set_interpreter_debug_level(debug_prev_level[top]); + ndebug_stack--; + } + } +} + +/* + * Really entering do_run, since this may be a recursive entry to do_run, + * we need to set the debug level to what it was previously. + */ +int +current_debug_state(fcode_env_t *env) +{ + if (ndebug_stack) { + int top = ndebug_stack - 1; + set_interpreter_debug_level(debug_prev_level[top]); + } + return (ndebug_stack); +} + +void +clear_debug_state(fcode_env_t *env, int oldstate) +{ + if (ndebug_stack && oldstate <= ndebug_stack) { + set_interpreter_debug_level(debug_prev_level[oldstate]); + ndebug_stack = oldstate; + } +} + +void +unbug(fcode_env_t *env) +{ + int i; + token_t *link; + flag_t *flag; + + for (i = ndebug_stack - 1; i >= 0; i--) { + link = ACF_TO_LINK(debug_low[i]); + flag = LINK_TO_FLAGS(link); + *flag &= ~FLAG_DEBUG; + } + clear_debug_state(env, 0); +} + +void +output_vitals(fcode_env_t *env) +{ + log_message(MSG_FC_DEBUG, "IP=%p, *IP=%p, WA=%p, *WA=%p ", IP, + (IP ? *IP : 0), WA, (WA ? *WA : 0)); +} + +int +do_exec_debug(fcode_env_t *env, void *fn) +{ + int dl = debug_level; + int show_wa = 1; + + if ((dl & (DEBUG_EXEC_DUMP_DS | DEBUG_EXEC_DUMP_RS | + DEBUG_EXEC_SHOW_VITALS | DEBUG_EXEC_TRACE | DEBUG_TRACING | + DEBUG_STEPPING)) == 0) + return (0); + + if (dl & DEBUG_STEPPING) { + dl |= DEBUG_EXEC_DUMP_DS; + } + if (dl & (DEBUG_STEPPING | DEBUG_EXEC_TRACE)) { + log_message(MSG_FC_DEBUG, "%-15s ", acf_to_name(env, WA)); + show_wa = 0; + } + if (dl & DEBUG_EXEC_DUMP_DS) + output_data_stack(env, MSG_FC_DEBUG); + if (dl & DEBUG_EXEC_DUMP_RS) + output_return_stack(env, show_wa, MSG_FC_DEBUG); + if (dl & DEBUG_EXEC_SHOW_VITALS) + output_vitals(env); + if (dl & DEBUG_TRACING) + do_fclib_trace(env, (void *) fn); + log_message(MSG_FC_DEBUG, "\n"); + if (dl & DEBUG_STEPPING) + return (do_fclib_step(env)); + return (0); +} + +static void +smatch(fcode_env_t *env) +{ + int len; + char *str, *p; + + if ((str = parse_a_string(env, &len)) == NULL) + log_message(MSG_INFO, "smatch: no string\n"); + else { + for (p = (char *)env->base; p < (char *)HERE; p++) + if (memcmp(p, str, len) == 0) + log_message(MSG_DEBUG, "%p\n", p); + } +} + +void +check_vitals(fcode_env_t *env) +{ + int i; + token_t *dptr; + + dptr = env->current; + if (*dptr && !within_dictionary(env, (uchar_t *)*dptr)) + log_message(MSG_ERROR, "Current: %p outside dictionary\n", + *dptr); + for (i = env->order_depth; i >= 0; i--) { + dptr = env->order[i]; + if (!dptr) + continue; + if (*dptr && !within_dictionary(env, (uchar_t *)*dptr)) + log_message(MSG_ERROR, "Order%d: %p outside" + " dictionary\n", i, *dptr); + } + if (HERE < env->base || HERE >= env->base + dict_size) { + log_message(MSG_ERROR, "HERE: %p outside range\n", HERE); + } + if (DS < env->ds0 || DS >= &env->ds0[stack_size]) { + forth_abort(env, "DS: %p outside range\n", DS); + } + if (RS < env->rs0 || RS >= &env->rs0[stack_size]) { + log_message(MSG_ERROR, "RS: %p outside range\n", RS); + RS = env->rs0; + } + if (IP && !within_dictionary(env, IP)) + log_message(MSG_ERROR, "IP: %p outside dictionary\n", IP); + if (!within_dictionary(env, (void *)env->forth_voc_link)) + log_message(MSG_ERROR, "forth_voc_link: %p outside" + " dictionary\n", env->forth_voc_link); +} + +static void +dump_table(fcode_env_t *env) +{ + int i; + + for (i = 0; i < MAX_FCODE; i++) { + if (*(env->table[i].apf) != (token_t)(&f_error)) { + log_message(MSG_DEBUG, "Token: %4x %32s acf = %8p," + " %8p\n", i, env->table[i].name, env->table[i].apf, + *(env->table[i].apf)); + } + } + log_message(MSG_DEBUG, "%d FCODES implemented\n", fcode_impl_count); +} + +void +verify_usage(fcode_env_t *env) +{ + int i, untested = 0; + + for (i = 0; i < MAX_FCODE; i++) { + int verify; + + verify = env->table[i].flags & (ANSI_WORD|P1275_WORD); + if ((verify) && +#ifdef DEBUG + (env->table[i].usage == 0) && +#endif + (env->table[i].apf)) { + log_message(MSG_DEBUG, + "Untested: %4x %32s acf = %8p, %8p\n", i, + env->table[i].name, env->table[i].apf, + *(env->table[i].apf)); + untested++; + } + } + if (untested) + log_message(MSG_DEBUG, "%d untested tokens\n", untested); +} + +static void +debugf(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&debug_level); +} + +static void +control(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&env->control); +} + +struct bittab { + int b_bitval; + char *b_bitname; +} bittab[] = { + DEBUG_CONTEXT, "context", + DEBUG_BYTELOAD_DS, "byteload-ds", + DEBUG_BYTELOAD_RS, "byteload-rs", + DEBUG_BYTELOAD_TOKENS, "byteload-tokens", + DEBUG_NEW_TOKEN, "new-token", + DEBUG_EXEC_TRACE, "exec-trace", + DEBUG_EXEC_SHOW_VITALS, "exec-show-vitals", + DEBUG_EXEC_DUMP_DS, "exec-dump-ds", + DEBUG_EXEC_DUMP_RS, "exec-dump-rs", + DEBUG_COMMA, "comma", + DEBUG_HEADER, "header", + DEBUG_EXIT_WORDS, "exit-words", + DEBUG_EXIT_DUMP, "exit-dump", + DEBUG_DUMP_TOKENS, "dump-tokens", + DEBUG_COLON, "colon", + DEBUG_NEXT_VITALS, "next-vitals", + DEBUG_VOC_FIND, "voc-find", + DEBUG_DUMP_DICT_TOKENS, "dump-dict-tokens", + DEBUG_TOKEN_USAGE, "token-usage", + DEBUG_DUMP_TOKEN_TABLE, "dump-token-table", + DEBUG_SHOW_STACK, "show-stack", + DEBUG_SHOW_RS, "show-rs", + DEBUG_TRACING, "tracing", + DEBUG_TRACE_STACK, "trace-stack", + DEBUG_CALL_METHOD, "call-method", + DEBUG_ACTIONS, "actions", + DEBUG_STEPPING, "stepping", + DEBUG_REG_ACCESS, "reg-access", + DEBUG_ADDR_ABUSE, "addr-abuse", + DEBUG_FIND_FCODE, "find-fcode", + DEBUG_UPLOAD, "upload", + 0 +}; + +void +debug_flags_to_output(fcode_env_t *env, int flags) +{ + int first = 1, i; + + for (i = 0; bittab[i].b_bitval != 0; i++) + if (bittab[i].b_bitval & flags) { + if (!first) + log_message(MSG_INFO, ","); + first = 0; + log_message(MSG_INFO, bittab[i].b_bitname); + } + if (first) + log_message(MSG_INFO, "<empty>"); + log_message(MSG_INFO, "\n"); +} + +static void +dot_debugf(fcode_env_t *env) +{ + debug_flags_to_output(env, debug_level); +} + +static void +debugf_qmark(fcode_env_t *env) +{ + debug_flags_to_output(env, 0xffffffff); +} + +int +debug_flags_to_mask(char *str) +{ + int flags = 0; + char *p; + int i; + + if (isdigit(*str)) { + if (*str == '0') { + str++; + if (*str == 'x' || *str == 'X') { + sscanf(str + 1, "%x", &flags); + } else + sscanf(str, "%o", &flags); + } else + sscanf(str, "%d", &flags); + return (flags); + } + if (strcmp(str, "clear") == 0) + return (0); + if (strcmp(str, "all") == 0) + return (0xffffffff & ~DEBUG_STEPPING); + if (*str) { + do { + if (p = strchr(str, ',')) + *p++ = '\0'; + for (i = 0; bittab[i].b_bitname != 0; i++) + if (strcmp(str, bittab[i].b_bitname) == 0) { + flags |= bittab[i].b_bitval; + break; + } + if (bittab[i].b_bitname == 0) + log_message(MSG_WARN, + "Unknown debug flag: '%s'\n", str); + str = p; + } while (p); + } + return (flags); +} + +static void +set_debugf(fcode_env_t *env) +{ + char *str; + + str = parse_a_string(env, NULL); + debug_level = debug_flags_to_mask(str); +} + +static acf_t +show_a_word(fcode_env_t *env, acf_t acf, void *arg) +{ + static int nshow_words = 0; + + if (acf == NULL) { + if (nshow_words > 0) { + log_message(MSG_DEBUG, "\n"); + nshow_words = 0; + } + return (NULL); + } + log_message(MSG_DEBUG, "%15s ", get_name_or_acf(ACF_TO_LINK(acf))); + nshow_words++; + if (nshow_words >= 4) { + log_message(MSG_DEBUG, "\n"); + nshow_words = 0; + } + return (NULL); +} + +void +words(fcode_env_t *env) +{ + (void) search_all_dictionaries(env, show_a_word, NULL); + (void) show_a_word(env, NULL, NULL); +} + +static acf_t +dump_a_word(fcode_env_t *env, acf_t acf, void *arg) +{ + output_acf_name(acf); + return (NULL); +} + +void +dump_words(fcode_env_t *env) +{ + (void) search_all_dictionaries(env, dump_a_word, NULL); + output_acf_name(NULL); +} + +static void +dump_line(uchar_t *ptr) +{ + uchar_t *byte; + int i; + + log_message(MSG_INFO, "%p ", (uint32_t)ptr); + for (i = 0, byte = ptr; i < 16; i++) { + if (i == 8) + log_message(MSG_INFO, " "); + log_message(MSG_INFO, "%02.2x ", *byte++); + } + log_message(MSG_INFO, " "); + for (i = 0, byte = ptr; i < 16; i++, byte++) { + log_message(MSG_INFO, "%c", + ((*byte < 0x20) || (*byte > 0x7f)) ? '.' : *byte); + } + log_message(MSG_INFO, "\n"); +} + +void +dump_dictionary(fcode_env_t *env) +{ + uchar_t *ptr; + + log_message(MSG_INFO, "Dictionary dump: base: %p\n", env->base); + for (ptr = (uchar_t *)(((long)(env->base)) & ~0xf); ptr < HERE; + ptr += 16) + dump_line(ptr); +} + +static char * +acf_to_fcode_name(fcode_env_t *env, acf_t acf) +{ + int i; + + for (i = 0; i < MAX_FCODE; i++) + if (env->table[i].apf == acf) + return (env->table[i].name); + return (NULL); +} + +static acf_t +acf_match(fcode_env_t *env, acf_t sacf, void *macf) +{ + if (sacf == (acf_t)macf) + return (sacf); + return (NULL); +} + +/* + * Given an ACF, return ptr to name or "unknown" string. + */ +char * +acf_to_name(fcode_env_t *env, acf_t acf) +{ + struct bitab *bip; + static char name_buf[256]; + uchar_t *p, *np; + int i, n; + + if (!within_dictionary(env, acf)) { + if ((bip = lookup_builtin((token_t)acf)) != NULL) + return (bip->bi_name); + return (NULL); + } + return (get_name_or_acf(ACF_TO_LINK(acf))); +} + +int +within_dictionary(fcode_env_t *env, void *addr) +{ + return ((uchar_t *)addr >= env->base && + (uchar_t *)addr < env->base + dict_size); +} + +static int +within_word(fcode_env_t *env, acf_t acf, acf_t wacf) +{ + if (acf == wacf || acf + 1 == wacf) + return (1); + if (*acf == (token_t)(&do_colon)) { + do { + if (acf == wacf) + return (1); + } while (*acf++ != (token_t)(&semi_ptr)); + } + return (0); +} + +/* + * Given an ACF in the middle of a colon definition, search dictionary towards + * beginning for "colon" acf. If we find a "semi" acf first, we're not in + * the middle of a colon-def (temporary execute?). + */ +char * +acf_backup_search(fcode_env_t *env, acf_t acf) +{ + acf_t nacf; + char *name; + + if ((acf_t)_ALIGN(acf, token_t) == acf && within_dictionary(env, acf)) { + for (nacf = acf; nacf >= (acf_t)env->base; nacf--) + if (*nacf == (token_t)(&do_colon) || + *nacf == (token_t)(&semi_ptr)) + break; + if (nacf >= (acf_t)env->base && *nacf == (token_t)(&do_colon) && + (name = get_name(ACF_TO_LINK(nacf))) != NULL) + return (name); + } + return (acf_to_str(acf)); +} + +/* + * Print out current process's C stack using /usr/proc/bin/pstack + */ +void +ctrace(fcode_env_t *env) +{ + char buf[256]; + FILE *fd; + + log_message(MSG_DEBUG, "Interpreter C Stack:\n"); + sprintf(buf, "/usr/proc/bin/pstack %d", getpid()); + if ((fd = popen(buf, "r")) == NULL) + log_perror(MSG_ERROR, "Can't run: %s", buf); + else { + while (fgets(buf, sizeof (buf), fd)) + log_message(MSG_DEBUG, buf); + fclose(fd); + } +} + +/* + * Dump data, return stacks, try to unthread forth calling stack. + */ +void +ftrace(fcode_env_t *env) +{ + log_message(MSG_DEBUG, "Forth Interpreter Stacks:\n"); + output_data_stack(env, MSG_DEBUG); + output_return_stack(env, 1, MSG_DEBUG); + log_message(MSG_DEBUG, "\n"); +} + +int in_forth_abort; + +/* + * Handle fatal error, if interactive mode, return to ok prompt. + */ +void +forth_abort(fcode_env_t *env, char *fmt, ...) +{ + va_list ap; + char msg[256]; + + if (in_forth_abort) { + log_message(MSG_FATAL, "ABORT: abort within forth_abort\n"); + abort(); + } + in_forth_abort++; + + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + log_message(MSG_ERROR, "ABORT: %s\n", msg); + + if (env) { + ctrace(env); + ftrace(env); + } + + return_to_interact(env); + /* + * If not in interactive mode, return_to_interact just returns. + */ + exit(1); +} + +/* + * Handle fatal system call error + */ +void +forth_perror(fcode_env_t *env, char *fmt, ...) +{ + va_list ap; + char msg[256]; + int save_errno = errno; /* just in case... */ + + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + + forth_abort(env, "%s: %s", msg, strerror(save_errno)); +} + +static void +show_stack(fcode_env_t *env) +{ +#ifdef DEBUG + debug_level ^= DEBUG_SHOW_STACK; +#else + /*EMPTY*/ +#endif +} + +static void +print_bytes_header(int width, int offset) +{ + int i; + + for (i = 0; i < width; i++) + log_message(MSG_INFO, " "); + log_message(MSG_INFO, " "); + for (i = 0; i < 16; i++) { + if (i == 8) + log_message(MSG_INFO, " "); + if (i == offset) + log_message(MSG_INFO, "\\/ "); + else + log_message(MSG_INFO, "%2x ", i); + } + log_message(MSG_INFO, " "); + for (i = 0; i < 16; i++) { + if (i == offset) + log_message(MSG_INFO, "v"); + else + log_message(MSG_INFO, "%x", i); + } + log_message(MSG_INFO, "\n"); +} + +static void +dump(fcode_env_t *env) +{ + uchar_t *data; + int len, offset; + char buf[20]; + + len = POP(DS); + data = (uchar_t *)POP(DS); + offset = ((long)data) & 0xf; + len += offset; + data = (uchar_t *)((long)data & ~0xf); + sprintf(buf, "%p", (uint32_t)data); + print_bytes_header(strlen(buf), offset); + for (len += offset; len > 0; len -= 16, data += 16) + dump_line(data); +} + +static acf_t +do_sifting(fcode_env_t *env, acf_t acf, void *pat) +{ + char *name; + + if ((name = get_name(ACF_TO_LINK(acf))) != NULL && strstr(name, pat)) + output_acf_name(acf); + return (NULL); +} + +static void +sifting(fcode_env_t *env) +{ + char *pat; + + if ((pat = parse_a_string(env, NULL)) != NULL) { + (void) search_all_dictionaries(env, do_sifting, pat); + output_acf_name(NULL); + } +} + +void +print_level(int level, int *doprint) +{ + int i; + + if (*doprint) { + log_message(MSG_DEBUG, "\n "); + for (i = 0; i < level; i++) + log_message(MSG_DEBUG, " "); + *doprint = 0; + } +} + +#define BI_QUOTE 1 +#define BI_BLIT 2 +#define BI_BDO 3 +#define BI_QDO 4 +#define BI_BR 5 +#define BI_QBR 6 +#define BI_BOF 7 +#define BI_LOOP 8 +#define BI_PLOOP 9 +#define BI_TO 10 +#define BI_SEMI 11 +#define BI_COLON 12 +#define BI_NOOP 13 +#define BI_NOTYET 14 /* unimplented in "see" */ + +struct bitab bitab[] = { + (token_t)("e_ptr), "\"", BI_QUOTE, + (token_t)(&blit_ptr), "blit", BI_BLIT, + (token_t)(&do_bdo_ptr), "do", BI_BDO, + (token_t)(&do_bqdo_ptr), "?do", BI_QDO, + (token_t)(&bbranch_ptrs[0]), "br", BI_BR, + (token_t)(&bbranch_ptrs[1]), "qbr", BI_QBR, + (token_t)(&bbranch_ptrs[2]), "bof", BI_BOF, + (token_t)(&do_loop_ptr), "loop", BI_LOOP, + (token_t)(&do_ploop_ptr), "+loop", BI_PLOOP, + (token_t)(&to_ptr), "to", BI_NOOP, + (token_t)(&semi_ptr), ";", BI_SEMI, + (token_t)(&do_colon), ":", BI_COLON, + (token_t)(&tlit_ptr), "[']", BI_NOOP, + (token_t)(&do_leave_ptr), "leave", BI_NOTYET, + (token_t)(&create_ptr), "create", BI_NOTYET, + (token_t)(&does_ptr), "does>", BI_NOTYET, + (token_t)(&value_defines[0][0]), "a.@", BI_NOTYET, + (token_t)(&value_defines[0][1]), "a.!", BI_NOTYET, + (token_t)(&value_defines[0][2]), "a.nop", BI_NOTYET, + (token_t)(&value_defines[1][0]), "a.i@", BI_NOTYET, + (token_t)(&value_defines[1][1]), "a.i!", BI_NOTYET, + (token_t)(&value_defines[1][2]), "a.iad", BI_NOTYET, + (token_t)(&value_defines[2][0]), "a.defer", BI_NOTYET, + (token_t)(&value_defines[2][1]), "a.@", BI_NOTYET, + (token_t)(&value_defines[2][2]), "a.nop", BI_NOTYET, + (token_t)(&value_defines[3][0]), "a.defexec", BI_NOTYET, + (token_t)(&value_defines[3][1]), "a.iset", BI_NOTYET, + (token_t)(&value_defines[3][2]), "a.iad", BI_NOTYET, + (token_t)(&value_defines[4][0]), "a.binit", BI_NOTYET, + (token_t)(&value_defines[4][1]), "a.2drop", BI_NOTYET, + (token_t)(&value_defines[4][2]), "a.nop", BI_NOTYET, + (token_t)(&value_defines[5][0]), "a.ibinit", BI_NOTYET, + (token_t)(&value_defines[5][1]), "a.2drop", BI_NOTYET, + (token_t)(&value_defines[5][2]), "a.iad", BI_NOTYET, + 0 +}; + +struct bitab * +lookup_builtin(token_t builtin) +{ + int i; + + for (i = 0; bitab[i].bi_ptr; i++) + if (bitab[i].bi_ptr == builtin) + return (&bitab[i]); + return (NULL); +} + +static void +paren_see(fcode_env_t *env) +{ + acf_t save_acf = (acf_t)POP(DS); + acf_t acf = save_acf; + int i, n, pass; + token_t brtab[30], thentab[30], brstk[30]; + int nbrtab = 0, nthentab = 0, nbrstk = 0; + uchar_t *p; + int level = 0, doprintlevel = 1, nthen; + struct bitab *bip; + token_t last_lit = 0, case_lit = 0, endof_loc = 0, endcase_loc = 0; + + if ((bip = lookup_builtin(*acf)) == NULL || + bip->bi_type != BI_COLON) { + if (bip = lookup_builtin((token_t)acf)) + log_message(MSG_INFO, "%s: builtin\n", bip->bi_name); + else + log_message(MSG_INFO, "%s: builtin\n", + acf_to_name(env, acf)); + return; + } + log_message(MSG_INFO, ": %s", acf_to_name(env, acf)); + for (pass = 0; pass < 2; pass++) { + acf = save_acf; + for (acf++; ; acf++) { + if (pass) { + print_level(level, &doprintlevel); + for (nthen = 0; nthentab > 0 && + thentab[nthentab-1] == (token_t)acf; + nthentab--) + nthen++; + if (nthen) { + level -= nthen; + doprintlevel = 1; + print_level(level, &doprintlevel); + for (i = 0; i < nthen; i++) + log_message(MSG_INFO, "then "); + } + print_level(level, &doprintlevel); + for (i = 0; i < nbrtab; i += 2) + if ((token_t)acf == brtab[i]) { + log_message(MSG_INFO, "begin "); + brstk[nbrstk++] = brtab[i+1]; + level++; + doprintlevel = 1; + } + print_level(level, &doprintlevel); + if (case_lit == (token_t)acf) { + log_message(MSG_INFO, "case "); + doprintlevel = 1; + print_level(level, &doprintlevel); + } + if (endof_loc == (token_t)acf) { + log_message(MSG_INFO, "endof "); + doprintlevel = 1; + print_level(level, &doprintlevel); + } + if (endcase_loc == (token_t)acf) { + doprintlevel = 1; + print_level(level, &doprintlevel); + log_message(MSG_INFO, "endcase "); + } + } + if ((bip = lookup_builtin((token_t)*acf)) == 0) { + last_lit = (token_t)acf; + if (pass) + log_message(MSG_INFO, "%s ", + acf_to_name(env, (acf_t)*acf)); + continue; + } + if (bip->bi_type == BI_SEMI) { + if (pass) { + log_message(MSG_INFO, "\n"); + log_message(MSG_INFO, "%s\n", + bip->bi_name); + } + break; + } + switch (bip->bi_type) { + + case BI_NOOP: + case BI_NOTYET: + if (pass) + log_message(MSG_INFO, "%s ", + bip->bi_name); + break; + + case BI_QUOTE: + if (pass) + log_message(MSG_INFO, "\" "); + acf++; + p = (uchar_t *)acf; + n = *p++; + if (pass) + log_message(MSG_INFO, "%s\" ", p); + p += n + 1; + for (; ((token_t)(p)) & (sizeof (token_t) - 1); + p++) + ; + acf = (acf_t)p; + acf--; + break; + + case BI_BLIT: + acf++; + if (pass) + log_message(MSG_INFO, "%x ", *acf); + break; + + case BI_BDO: + case BI_QDO: + if (pass) { + log_message(MSG_INFO, "%s ", + bip->bi_name); + doprintlevel = 1; + level++; + } + acf++; + break; + + case BI_BR: + acf++; + if (pass) { + if (*acf < (token_t)acf) { + if (nbrstk) { + doprintlevel = 1; + level--; + print_level(level, + &doprintlevel); + log_message(MSG_INFO, + "repeat "); + nbrstk--; + } else + log_message(MSG_INFO, + "[br back?]"); + } else if (nthentab) { + doprintlevel = 1; + print_level(level - 1, + &doprintlevel); + log_message(MSG_INFO, "else "); + doprintlevel = 1; + thentab[nthentab - 1] = *acf; + } + } else { + if (*acf < (token_t)acf) { + brtab[nbrtab++] = *acf; + brtab[nbrtab++] = (token_t)acf; + } + if (endcase_loc == 0 && + case_lit) { + endcase_loc = *acf; + } + } + break; + + case BI_QBR: + acf++; + if (pass) { + if (*acf < (token_t)acf) { + if (nbrstk) { + doprintlevel = 1; + level--; + print_level(level, + &doprintlevel); + log_message(MSG_INFO, + "until "); + nbrstk--; + } else + log_message(MSG_INFO, + "[br back?]"); + } else if (nbrstk > 0 && + *acf >= brstk[nbrstk - 1]) { + doprintlevel = 1; + print_level(level - 1, + &doprintlevel); + log_message(MSG_INFO, + "while "); + doprintlevel = 1; + } else { + log_message(MSG_INFO, "if "); + doprintlevel = 1; + level++; + thentab[nthentab++] = *acf; + } + } else if (*acf < (token_t)acf) { + brtab[nbrtab++] = *acf; + brtab[nbrtab++] = (token_t)acf; + } + break; + + case BI_BOF: + acf++; + if (pass) { + log_message(MSG_INFO, "of "); + endof_loc = *acf; + } else if (case_lit == 0) { + case_lit = last_lit; + } + break; + + case BI_LOOP: + case BI_PLOOP: + if (pass) { + level--; + doprintlevel = 1; + print_level(level, &doprintlevel); + log_message(MSG_INFO, "%s ", + bip->bi_name); + } + acf++; + break; + + default: + log_message(MSG_ERROR, "Invalid builtin %s\n", + bip->bi_name); + } + } + } +} + +static void +see(fcode_env_t *env) +{ + fstack_t d; + + parse_word(env); + dollar_find(env); + d = POP(DS); + if (d) + paren_see(env); + else { + log_message(MSG_WARN, "?"); + two_drop(env); + } +} + +static acf_t +do_dot_calls(fcode_env_t *env, acf_t acf, void *cacf) +{ + token_t *dptr = ACF_TO_LINK(acf); + token_t *wptr = acf; + + if (*wptr == (token_t)(&do_colon)) { + do { + if ((acf_t)(*wptr) == (acf_t)cacf) + output_acf_name(acf); + } while (*wptr++ != (token_t)(&semi_ptr)); + } else if ((acf_t)(*wptr) == cacf) + output_acf_name(acf); + else if (wptr == (token_t *)cacf) + output_acf_name(acf); + return (NULL); +} + +static void +dot_calls(fcode_env_t *env) +{ + acf_t acf = (acf_t)POP(DS); + + search_all_dictionaries(env, do_dot_calls, acf); + output_acf_name(NULL); +} + +static void +dot_pci_space(fcode_env_t *env) +{ + fstack_t d = POP(DS); + + switch ((d >> 24) & 0x3) { + case 0: log_message(MSG_INFO, "Config,"); break; + case 1: log_message(MSG_INFO, "IO,"); break; + case 2: log_message(MSG_INFO, "Memory32,"); break; + case 3: log_message(MSG_INFO, "Memory64,"); break; + } + if (d & 0x80000000) + log_message(MSG_INFO, "Not_reloc,"); + if (d & 0x400000000) + log_message(MSG_INFO, "Prefetch,"); + if (d & 0x200000000) + log_message(MSG_INFO, "Alias,"); + log_message(MSG_INFO, "Bus%d,", (d >> 16) & 0xff); + log_message(MSG_INFO, "Dev%d,", (d >> 11) & 0x1f); + log_message(MSG_INFO, "Func%d,", (d >> 8) & 0x7); + log_message(MSG_INFO, "Reg%x", d & 0xff); + log_message(MSG_INFO, "\n"); +} + +void +fcode_debug(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)(&env->fcode_debug)); +} + +static void +base_addr(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)env->base); +} + +static int mw_valid; +static int mw_size; +static void *mw_addr; +static fstack_t mw_value; +static fstack_t mw_lastvalue; + +static fstack_t +mw_fetch(void) +{ + switch (mw_size) { + case 1: return (*((uint8_t *)mw_addr)); + case 2: return (*((uint16_t *)mw_addr)); + case 4: return (*((uint32_t *)mw_addr)); + case 8: return (*((uint64_t *)mw_addr)); + } + return (0); +} + +void +do_memory_watch(fcode_env_t *env) +{ + fstack_t value; + + if (!mw_valid) + return; + value = mw_fetch(); + if (value != mw_lastvalue) { + if (mw_valid == 1 || mw_value == value) { + log_message(MSG_INFO, + "memory-watch: %p/%d: %llx -> %llx\n", + mw_addr, mw_size, (uint64_t)mw_lastvalue, + (uint64_t)value); + do_fclib_step(env); + } + mw_lastvalue = value; + } +} + +static void +set_memory_watch(fcode_env_t *env, int type, int size, void *addr, + fstack_t value) +{ + switch (size) { + case 1: case 2: case 4: case 8: + break; + default: + log_message(MSG_ERROR, "set_memory_watch: invalid size: %d\n", + size); + return; + } + mw_valid = type; + mw_size = size; + mw_addr = addr; + mw_value = value; + mw_lastvalue = mw_fetch(); +} + +static void +memory_watch(fcode_env_t *env) +{ + int size = POP(DS); + void *addr = (void *)POP(DS); + + set_memory_watch(env, 1, size, addr, 0); +} + +static void +memory_watch_value(fcode_env_t *env) +{ + int size = POP(DS); + void *addr = (void *)POP(DS); + fstack_t value = POP(DS); + + set_memory_watch(env, 2, size, addr, value); +} + +static void +memory_watch_clear(fcode_env_t *env) +{ + mw_valid = 0; +} + +static void +vsearch(fcode_env_t *env) +{ + fstack_t value; + int size = POP(DS); + fstack_t match_value = POP(DS); + uchar_t *toaddr = (uchar_t *)POP(DS); + uchar_t *fromaddr = (uchar_t *)POP(DS); + + log_message(MSG_INFO, "%p to %p by %d looking for %llx\n", fromaddr, + toaddr, size, (uint64_t)match_value); + for (; fromaddr < toaddr; fromaddr += size) { + switch (size) { + case 1: value = *((uint8_t *)fromaddr); break; + case 2: value = *((uint16_t *)fromaddr); break; + case 4: value = *((uint32_t *)fromaddr); break; + case 8: value = *((uint64_t *)fromaddr); break; + default: + log_message(MSG_INFO, "Invalid size: %d\n", size); + return; + } + if (value == match_value) + log_message(MSG_INFO, "%p\n", fromaddr); + } +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(IMMEDIATE, "words", words); + FORTH(IMMEDIATE, "dump-words", dump_words); + FORTH(IMMEDIATE, "dump-dict", dump_dictionary); + FORTH(IMMEDIATE, "dump-table", dump_table); + FORTH(0, "debugf", debugf); + FORTH(0, ".debugf", dot_debugf); + FORTH(0, "set-debugf", set_debugf); + FORTH(0, "debugf?", debugf_qmark); + FORTH(0, "control", control); + FORTH(0, "dump", dump); + FORTH(IMMEDIATE, "showstack", show_stack); + FORTH(IMMEDIATE, "sifting", sifting); + FORTH(IMMEDIATE, "ctrace", ctrace); + FORTH(IMMEDIATE, "ftrace", ftrace); + FORTH(0, "see", see); + FORTH(0, "(see)", paren_see); + FORTH(0, "base-addr", base_addr); + FORTH(0, "smatch", smatch); + FORTH(0, ".calls", dot_calls); + FORTH(0, ".pci-space", dot_pci_space); + FORTH(0, "(debug)", paren_debug); + FORTH(0, "debug", debug); + FORTH(0, ".debug", dot_debug); + FORTH(0, "undebug", undebug); + FORTH(0, "memory-watch", memory_watch); + FORTH(0, "memory-watch-value", memory_watch_value); + FORTH(0, "memory-watch-clear", memory_watch_clear); + FORTH(0, "vsearch", vsearch); +} diff --git a/usr/src/lib/efcode/engine/env.c b/usr/src/lib/efcode/engine/env.c new file mode 100644 index 0000000000..e5d20ec882 --- /dev/null +++ b/usr/src/lib/efcode/engine/env.c @@ -0,0 +1,863 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <ctype.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <fcode/private.h> +#include <fcode/log.h> + + +static variable_t verbose_emit; + +void +do_verbose_emit(fcode_env_t *env) +{ + verbose_emit ^= 1; +} + +/* + * Internal "emit". + * Note log_emit gathers up characters and issues a syslog or write to + * error log file if enabled. + */ +void +do_emit(fcode_env_t *env, uchar_t c) +{ + if (verbose_emit) + log_message(MSG_ERROR, "emit(%x)\n", c); + + if (c == '\n') { + env->output_column = 0; + env->output_line++; + } else if (c == '\r') + env->output_column = 0; + else + env->output_column++; + if (isatty(fileno(stdout))) { + if ((c >= 0x20 && c <= 0x7f) || c == '\n' || c == '\r' || + c == '\b') + putchar(c); + else if (c >= 0 && c < 0x20) + printf("@%c", c + '@'); + else + printf("\\%x", c); + fflush(stdout); + } + log_emit(c); +} + +void +system_message(fcode_env_t *env, char *msg) +{ + throw_from_fclib(env, 1, msg); +} + +void +emit(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 1, "emit"); + d = POP(DS); + do_emit(env, d); +} + +#include <sys/time.h> + +/* + * 'key?' - abort if stdin is not a tty. + */ +void +keyquestion(fcode_env_t *env) +{ + struct timeval timeval; + fd_set readfds; + int ret; + + if (isatty(fileno(stdin))) { + FD_ZERO(&readfds); + FD_SET(fileno(stdin), &readfds); + timeval.tv_sec = 0; + timeval.tv_usec = 1000; + ret = select(fileno(stdin) + 1, &readfds, NULL, NULL, &timeval); + if (FD_ISSET(fileno(stdin), &readfds)) + PUSH(DS, TRUE); + else + PUSH(DS, FALSE); + } else + forth_abort(env, "'key?' called in non-interactive mode"); +} + +/* + * 'key' - abort if stdin is not a tty, will block on read if char not avail. + */ +void +key(fcode_env_t *env) +{ + uchar_t c; + + if (isatty(fileno(stdin))) { + read(fileno(stdin), &c, 1); + PUSH(DS, c); + } else + forth_abort(env, "'key' called in non-interactive mode"); +} + +void +type(fcode_env_t *env) +{ + int len; + char *ptr; + + CHECK_DEPTH(env, 2, "type"); + ptr = pop_a_string(env, &len); + while (len--) + do_emit(env, *ptr++); +} + +void +paren_cr(fcode_env_t *env) +{ + do_emit(env, '\r'); +} + +void +fc_crlf(fcode_env_t *env) +{ + do_emit(env, '\n'); +} + +void +fc_num_out(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)(&env->output_column)); +} + +void +fc_num_line(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)(&env->output_line)); +} + +void +expect(fcode_env_t *env) +{ + char *buf, *rbuf; + int len; + + CHECK_DEPTH(env, 2, "expect"); + buf = pop_a_string(env, &len); + read_line(env); + rbuf = pop_a_string(env, NULL); + if (rbuf) { + strcpy(buf, rbuf); + env->span = strlen(buf); + } else + env->span = 0; +} + +void +span(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&env->span); +} + +void +do_ms(fcode_env_t *env) +{ + fstack_t d; + timespec_t rqtp; + + CHECK_DEPTH(env, 1, "ms"); + d = POP(DS); + if (d) { + rqtp.tv_sec = 0; + rqtp.tv_nsec = d*1000*1000; + nanosleep(&rqtp, 0); + } +} + +void +do_get_msecs(fcode_env_t *env) +{ + struct timeval tp; + long ms; + timespec_t rqtp; + + gettimeofday(&tp, NULL); + ms = (tp.tv_usec/1000) + (tp.tv_sec * 1000); + PUSH(DS, (fstack_t)ms); + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000*1000; + nanosleep(&rqtp, 0); +} + +#define CMN_MSG_SIZE 256 +#define CMN_MAX_DIGITS 3 + +typedef struct CMN_MSG_T cmn_msg_t; + +struct CMN_MSG_T { + char buf[CMN_MSG_SIZE]; + int level; + int len; + cmn_msg_t *prev; + cmn_msg_t *next; +}; + +typedef struct CMN_FMT_T cmn_fmt_t; + +struct CMN_FMT_T { + int fwidth; /* format field width */ + int cwidth; /* column width specified in format */ + char format; /* format type */ +}; + +static cmn_msg_t *root = NULL; +static int cmn_msg_level = 0; + +/* + * validfmt() + * + * Called by fmt_str() function to validate and extract formatting + * information from the supplied input buffer. + * + * Supported formats are: + * %c - character + * %d - signed decimal + * %x - unsigned hex + * %s - string + * %ld - signed 64 bit data + * %lx - unsigned 64 bit data + * %p - unsigned 64 bit data(pointer) + * %% - print as single "%" character + * + * Return values are: + * 0 - valid formatting + * 1 - invalid formatting found in the input buffer + * -1 - NULL pointer passed in for caller's receptacle + * + * + * For valid formatting, caller's supplied cmn_fmt_t elements are + * filled in: + * fwidth: + * > 0 - returned value is the field width + * < 0 - returned value is negation of field width for + * 64 bit data formats + * cwidth: + * formatted column width(if specified), otherwise 0 + * + * format: + * contains the formatting(single) character + */ +static int +validfmt(char *fmt, cmn_fmt_t *cfstr) +{ + int isll = 0; + int *fwidth, *cwidth; + char *format; + char *dig1, *dig2; + char cdigs[CMN_MAX_DIGITS+1]; + + if (cfstr == NULL) + return (-1); + + fwidth = &cfstr->fwidth; + cwidth = &cfstr->cwidth; + format = &cfstr->format; + *fwidth = *cwidth = 0; + *format = NULL; + dig1 = dig2 = NULL; + + /* check for left justification character */ + if (*fmt == '-') { + fmt++; + (*fwidth)++; + + /* check for column width specification */ + if (isdigit(*fmt)) + dig1 = fmt; /* save ptr to first digit */ + while (isdigit(*fmt)) { + fmt++; + (*fwidth)++; + } + /* if ljust specified w/o size, return format error */ + if (*fwidth == 1) { + return (1); + } + dig2 = fmt; /* save ptr to last digit + 1 */ + } else { + /* check for column width specification */ + if (isdigit(*fmt)) { + dig1 = fmt; /* save ptr to first digit */ + while (isdigit(*fmt)) { + fmt++; + (*fwidth)++; + } + dig2 = fmt; /* save ptr to last digit + 1 */ + } + } + + /* if a column width was specified, save it in caller's struct */ + if (dig1) { + int nbytes; + + nbytes = dig2 - dig1; + /* if too many digits in the width return error */ + if (nbytes > CMN_MAX_DIGITS) + return (1); + strncpy(cdigs, dig1, nbytes); + cdigs[nbytes] = 0; + *cwidth = atoi(cdigs); + } + + /* check for long format specifier */ + if (*fmt == 'l') { + fmt++; + (*fwidth)++; + isll = 1; + } + + /* process by specific format type */ + switch (*fmt) { + case 'c': + case 's': + case '%': + if (isll) + return (1); + case 'd': + case 'x': + *format = *fmt; + (*fwidth)++; + break; + case 'p': + isll = 1; /* uses 64 bit format */ + *format = *fmt; + (*fwidth)++; + break; + default: + return (1); /* unknown format type */ + } + if (isll) { + *fwidth *= -1; + } + return (0); +} + +/* + * fmt_args() + * + * Called by fmt_str() to setup arguments for subsequent snprintf() + * calls. For cases not involving column width limitations, processing + * simply POPs the data stack as required to setup caller's arg(or + * llarg, as appropriate). When a column width is specified for output, + * a temporary buffer is constructed to contain snprintf() generated + * output for the argument. Testing is then performed to determine if + * the specified column width will require truncation of the output. + * If so, truncation of least significant digits is performed as + * necessary, and caller's arg(or llarg) is adjusted to obtain the + * specified column width. + * + */ + +static void +fmt_args(fcode_env_t *env, int cw, int fw, char format, long *arg, + long long *llarg) +{ + char *cbuf; + char snf[3]; + int cbsize; + int cnv = 10, ndigits = 0; + + if (fw > 0) { /* check for normal (not long) formats */ + + /* initialize format string for snprintf call */ + snf[0] = '%'; + snf[1] = format; + snf[2] = 0; + + /* process by format type */ + switch (format) { + case 'x': + cnv = 16; + case 'd': + case 'c': + case 'p': + *arg = POP(DS); + break; + case 's': + POP(DS); + *arg = POP(DS); + break; + case '%': + return; + default: + log_message(MSG_ERROR, + "fmt_args:invalid format type! (%s)\n", + &format); + return; + } + + /* check if a column width was specified */ + if (cw) { + /* allocate a scratch buffer */ + cbsize = 2*(sizeof (long long)) + 1; + cbuf = MALLOC(cbsize); + + if (snprintf(cbuf, cbsize, snf, *arg) < 0) + log_message(MSG_ERROR, + "fmt_args: snprintf output error\n"); + while ((cbuf[ndigits] != NULL) && + (ndigits < cbsize)) + ndigits++; + + /* if truncation is necessary, do it */ + if (ndigits > cw) { + cbuf[cw] = 0; + if (format == 's') { + char *str; + str = (char *)*arg; + str[cw] = 0; + } else + *arg = strtol(cbuf, + (char **)NULL, cnv); + } + free(cbuf); + } + + } else { /* process long formats */ + + *llarg = POP(DS); + + /* check if a column width was specified */ + if (cw) { + /* allocate a scratch buffer */ + cbsize = 2*(sizeof (long long)) + 1; + cbuf = MALLOC(cbsize); + + switch (format) { + case 'p': + cnv = 16; + if (snprintf(cbuf, cbsize, "%p", *llarg) < 0) + log_message(MSG_ERROR, + "fmt_args: snprintf error\n"); + break; + case 'x': + cnv = 16; + if (snprintf(cbuf, cbsize, "%lx", *llarg) < 0) + log_message(MSG_ERROR, + "fmt_args: snprintf error\n"); + break; + case 'd': + if (snprintf(cbuf, cbsize, "%ld", *llarg) < 0) + log_message(MSG_ERROR, + "fmt_args: snprintf error\n"); + break; + default: + log_message(MSG_ERROR, + "invalid long format type! (l%s)\n", + &format); + free(cbuf); + return; + } + while ((cbuf[ndigits] != NULL) && + (ndigits < cbsize)) { + ndigits++; + } + /* if truncation is necessary, do it */ + if (ndigits > cw) { + cbuf[cw] = 0; + *llarg = strtoll(cbuf, (char **)NULL, cnv); + } + free(cbuf); + } + } +} + +/* + * fmt_str() + * + * Extracts text from caller's input buffer, processes explicit + * formatting as necessary, and outputs formatted text to caller's + * receptacle. + * + * env - pointer to caller's fcode environment + * fmt - pointer to caller's input buffr + * fmtbuf - ponter to caller's receptacle buffer + * bsize - size of caller's fmtbuf buffer + * + * This function performs an initial test to determine if caller's + * input buffer contains formatting(specified by presence of "%") + * in the buffer. If so, validfmt() function is called to verify + * the formatting, after which the buffer is processed according + * to the field width specified by validfmt() output. Special + * processing is required when caller's buffer contains a double + * "%" ("%%"), in which case the second "%" is accepted as normal + * text. + */ + +static void +fmt_str(fcode_env_t *env, char *fmt, char *fmtbuf, int bsize) +{ + char tbuf[CMN_MSG_SIZE]; + char *fmptr, *pct; + int l, cw, fw, bytes; + long arg; + long long llarg; + + *fmtbuf = 0; + if ((pct = strchr(fmt, '%')) != 0) { + cmn_fmt_t cfstr; + int vferr; + + l = strlen(pct++); + vferr = validfmt(pct, &cfstr); + if (!vferr) { + fw = cfstr.fwidth; + cw = cfstr.cwidth; + fmptr = &cfstr.format; + } else { + if (vferr < 0) { + log_message(MSG_ERROR, + "fmt_str: NULL ptr supplied to validfmt()\n"); + return; + } + + bytes = pct - fmt; + strncpy(tbuf, fmt, bytes); + strncpy(tbuf+bytes, "%", 1); + strncpy(tbuf+bytes+1, fmt+bytes, 1); + bytes += 2; + tbuf[bytes] = 0; + + log_message(MSG_ERROR, + "fmt_str: invalid format type! (%s)\n", + tbuf+bytes-3); + + strncpy(fmtbuf, tbuf, bsize); + return; + } + + if (fw > 0) { /* process normal (not long) formats */ + bytes = pct - fmt + fw; + strncpy(tbuf, fmt, bytes); + tbuf[bytes] = 0; + } else { + /* if here, fw must be a long format */ + if (*fmptr == 'p') { + bytes = pct - fmt - fw; + strncpy(tbuf, fmt, bytes); + tbuf[bytes] = 0; + } else { + bytes = pct - fmt - fw - 2; + strncpy(tbuf, fmt, bytes); + tbuf[bytes] = 'l'; + strncpy(tbuf+bytes+1, fmt+bytes, 2); + tbuf[bytes+1+2] = 0; + } + } + + /* if more input buffer to process, recurse */ + if ((l - abs(fw)) != 0) { + fmt_str(env, pct+abs(fw), (tbuf + strlen(tbuf)), + CMN_MSG_SIZE - strlen(tbuf)); + } + + /* call to extract args for snprintf() calls below */ + fmt_args(env, cw, fw, *fmptr, &arg, &llarg); + + if (fw > 0) { /* process normal (not long) formats */ + switch (*fmptr) { + case 'd': + case 'x': + case 'c': + case 's': + case 'p': + (void) snprintf(fmtbuf, bsize, tbuf, arg); + break; + case '%': + (void) snprintf(fmtbuf, bsize, tbuf); + break; + default: + log_message(MSG_ERROR, + "fmt_str: invalid format (%s)\n", + fmptr); + return; + } + + } else /* process long formats */ + (void) snprintf(fmtbuf, bsize, tbuf, llarg); + + } else + strncpy(fmtbuf, fmt, bsize); +} + +/* + * fc_cmn_append() + * + * Pops data stack to obtain message text, and calls fmt_str() + * function to perform any message formatting necessary. + * + * This function is called from fc_cmn_end() or directly in + * processing a cmn-append token. Since a pre-existing message + * context is assumed, initial checking is performed to verify + * its existence. + */ + +void +fc_cmn_append(fcode_env_t *env) +{ + int len; + char *str; + + if (root == NULL) { + log_message(MSG_ERROR, + "fc_cmn_append: no message context for append\n"); + return; + } + + len = POP(DS); + str = (char *)POP(DS); + + if ((root->len + len) < CMN_MSG_SIZE) { + fmt_str(env, str, root->buf+root->len, CMN_MSG_SIZE - + root->len); + root->len += len; + } else + log_message(MSG_ERROR, + "fc_cmn_append: append exceeds max msg size\n"); +} + +/* + * fc_cmn_end() + * + * Process ]cmn-end token to log the message initiated by a preceeding + * fc_cmn_start() call. + * + * Since nested cmn-xxx[ calls are supported, a test is made to determine + * if this is the final cmn-end of a nested sequence. If so, or if + * there was no nesting, log_message() is called with the appropriate + * text buffer. Otherwise, the root variable is adjusted to point to + * the preceeding message in the sequence and links in the list are + * updated. No logging is performed until the final ]cmn-end of the + * sequence is processed; then, messages are logged in FIFO order. + */ +void +fc_cmn_end(fcode_env_t *env) +{ + cmn_msg_t *old; + + if (root == 0) { + log_message(MSG_ERROR, "]cmn-end call w/o buffer\n"); + return; + } + + fc_cmn_append(env); + + if (root->prev == 0) { + cmn_msg_t *next; + do { + log_message(root->level, "%s\n", root->buf); + next = root->next; + free(root); + root = next; + } while (root); + } else { + old = root->prev; + old->next = root; + root = old; + } +} + +/* + * fc_cmn_start() + * + * Generic function to begin a common message. + * + * Allocates a new cmn_msg_t to associate with the message, and sets + * up initial text as specified by callers' inputs: + * + * env - pointer to caller's fcode environment + * head - pointer to initial text portion of the message + * path - flag to indicate if a device path is to be generated + */ +static void +fc_cmn_start(fcode_env_t *env, char *head, int path) +{ + cmn_msg_t *new; + char *dpath; + + new = MALLOC(sizeof (cmn_msg_t)); + new->prev = root; + if (root != 0) + root->next = new; + strcpy(new->buf, head); + new->len = strlen(head); + if (path && env->current_device) { + dpath = get_path(env, env->current_device); + strcpy(new->buf+new->len, dpath); + new->len += strlen(dpath); + strncpy(new->buf+new->len++, ": ", 2); + ++new->len; + free(dpath); + } + new->level = cmn_msg_level; + new->next = NULL; + root = new; +} + +/* + * fc_cmn_type() + * + * Process cmn-type[ token. + * + * Invokes fc_cmn_start() to create a message containing blank + * header and no device path information. + */ +void +fc_cmn_type(fcode_env_t *env) +{ + cmn_msg_level = MSG_INFO; + fc_cmn_start(env, "", 0); +} + +/* + * fc_cmn_msg() + * + * Process cmn-msg[ token. + * + * Invokes fc_cmn_start() to create a message containing blank + * header but specifying device path information. + */ +void +fc_cmn_msg(fcode_env_t *env) +{ + + cmn_msg_level = MSG_INFO; + fc_cmn_start(env, "", 1); +} + +/* + * fc_cmn_note() + * + * Process cmn-note[ token. + * + * Invokes fc_cmn_start() to create a message with NOTICE stamping in + * the header and specification of device path information. + */ +void +fc_cmn_note(fcode_env_t *env) +{ + cmn_msg_level = MSG_NOTE; + fc_cmn_start(env, "NOTICE: ", 1); +} + +/* + * fc_cmn_warn() + * + * Process cmn-warn[ token. + * + * Invokes fc_cmn_start() to create a message with WARNING stamping in + * the header and specification of device path information. + */ +void +fc_cmn_warn(fcode_env_t *env) +{ + cmn_msg_level = MSG_WARN; + fc_cmn_start(env, "WARNING: ", 1); +} + +/* + * fc_cmn_error() + * + * Process cmn-error[ token. + * + * Invokes fc_cmn_start() to create a message with ERROR stamping in + * the header and specification of device path information. + */ +void +fc_cmn_error(fcode_env_t *env) +{ + cmn_msg_level = MSG_ERROR; + fc_cmn_start(env, "ERROR: ", 1); +} + +/* + * fc_cmn_fatal() + * + * Process cmn-fatal[ token. + * + * Invokes fc_cmn_start() to create a message with FATAL stamping in + * the header and specification of device path information. + */ +void +fc_cmn_fatal(fcode_env_t *env) +{ + cmn_msg_level = MSG_FATAL; + fc_cmn_start(env, "FATAL: ", 1); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + ASSERT(env); + NOTICE; + + ANSI(0x088, 0, "span", span); + ANSI(0x08a, 0, "expect", expect); + + ANSI(0x08d, 0, "key?", keyquestion); + ANSI(0x08e, 0, "key", key); + ANSI(0x08f, 0, "emit", emit); + ANSI(0x090, 0, "type", type); + ANSI(0x091, 0, "(cr", paren_cr); + ANSI(0x092, 0, "cr", fc_crlf); + ANSI(0x093, 0, "#out", fc_num_out); + ANSI(0x094, 0, "#line", fc_num_line); + + FCODE(0x125, 0, "get-msecs", do_get_msecs); + FCODE(0x126, 0, "ms", do_ms); + + FORTH(0, "verbose-emit", do_verbose_emit); + FCODE(0x7e9, 0, "cmn-fatal[", fc_cmn_fatal); + FCODE(0x7ea, 0, "cmn-error[", fc_cmn_error); + FCODE(0x7eb, 0, "cmn-warn[", fc_cmn_warn); + FCODE(0x7ec, 0, "cmn-note[", fc_cmn_note); + FCODE(0x7ed, 0, "cmn-type[", fc_cmn_type); + FCODE(0x7ee, 0, "cmn-append", fc_cmn_append); + FCODE(0x7ef, 0, "]cmn-end", fc_cmn_end); + FCODE(0x7f0, 0, "cmn-msg[", fc_cmn_msg); +} diff --git a/usr/src/lib/efcode/engine/extend.c b/usr/src/lib/efcode/engine/extend.c new file mode 100644 index 0000000000..9e631012b2 --- /dev/null +++ b/usr/src/lib/efcode/engine/extend.c @@ -0,0 +1,147 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <sys/shm.h> +#include <dlfcn.h> +#include <fcode/private.h> + +static void +do_dlopen(fcode_env_t *env) +{ + char *name; + int mode; + void *pl; + + mode = POP(DS); + name = pop_a_string(env, NULL); + pl = dlopen(name, mode); + PUSH(DS, (fstack_t)pl); +} + +static void +do_extend(fcode_env_t *env) +{ + parse_word(env); + PUSH(DS, (fstack_t)RTLD_NOW); + do_dlopen(env); + drop(env); +} + +static void +do_dlclose(fcode_env_t *env) +{ + void *pl = (void *)POP(DS); + dlclose(pl); +} + +static void +do_dlsym(fcode_env_t *env) +{ + char *name; + fstack_t d; + + name = pop_a_string(env, NULL); + d = POP(DS); + d = (fstack_t)dlsym((void *) d, name); + PUSH(DS, d); +} + +static void +do_dlexec(fcode_env_t *env) +{ + int args; + fstack_t a, b, c, d; + fstack_t (*fn0)(void); + fstack_t (*fn1)(fstack_t); + fstack_t (*fn2)(fstack_t, fstack_t); + fstack_t (*fn3)(fstack_t, fstack_t, fstack_t); + fstack_t (*fn4)(fstack_t, fstack_t, fstack_t, fstack_t); + + args = POP(DS); + a = POP(DS); + switch (args) { + + case 0: + fn0 = (fstack_t (*)(void)) a; + a = fn0(); + PUSH(DS, a); + break; + + case 1: + fn1 = (fstack_t (*)(fstack_t)) a; + a = POP(DS); + a = fn1(a); + PUSH(DS, a); + break; + + case 2: + fn2 = (fstack_t (*)(fstack_t, fstack_t))a; + a = POP(DS); + b = POP(DS); + a = fn2(a, b); + PUSH(DS, a); + break; + + case 3: + fn3 = (fstack_t (*)(fstack_t, fstack_t, fstack_t))a; + a = POP(DS); + b = POP(DS); + c = POP(DS); + a = fn3(a, b, c); + PUSH(DS, a); + break; + + case 4: + fn4 = (fstack_t (*)(fstack_t, fstack_t, fstack_t, fstack_t))a; + a = POP(DS); + b = POP(DS); + c = POP(DS); + d = POP(DS); + a = fn4(a, b, c, d); + PUSH(DS, a); + break; + } +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "dl-open", do_dlopen); + FORTH(0, "dl-close", do_dlclose); + FORTH(0, "dl-sym", do_dlsym); + FORTH(0, "dl-exec", do_dlexec); + FORTH(IMMEDIATE, "extend-from", do_extend); +} diff --git a/usr/src/lib/efcode/engine/fb8.c b/usr/src/lib/efcode/engine/fb8.c new file mode 100644 index 0000000000..777b9d0713 --- /dev/null +++ b/usr/src/lib/efcode/engine/fb8.c @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <fcode/private.h> + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FCODE(0x180, 0, "fb8-draw-character", fc_unimplemented); + FCODE(0x181, 0, "fb8-reset-screen", fc_unimplemented); + FCODE(0x182, 0, "fb8-toggle-cursor", fc_unimplemented); + FCODE(0x183, 0, "fb8-erase-screen", fc_unimplemented); + FCODE(0x184, 0, "fb8-blink-screen", fc_unimplemented); + FCODE(0x185, 0, "fb8-invert-screen", fc_unimplemented); + FCODE(0x186, 0, "fb8-insert-characters", fc_unimplemented); + FCODE(0x187, 0, "fb8-delete-characters", fc_unimplemented); + FCODE(0x188, 0, "fb8-insert-lines", fc_unimplemented); + FCODE(0x189, 0, "fb8-delete-lines", fc_unimplemented); + FCODE(0x18a, 0, "fb8-draw-logo", fc_unimplemented); + FCODE(0x18b, 0, "fb8-install", fc_unimplemented); +} diff --git a/usr/src/lib/efcode/engine/fcode.c b/usr/src/lib/efcode/engine/fcode.c new file mode 100644 index 0000000000..e8cedb3816 --- /dev/null +++ b/usr/src/lib/efcode/engine/fcode.c @@ -0,0 +1,1031 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +int fcode_impl_count = 0; + +void (*crash_ptr)(fcode_env_t *env) = do_crash; + +uchar_t +next_bytecode(fcode_env_t *env) +{ + uchar_t byte; + + byte = *env->fcode_ptr; + env->fcode_ptr += env->fcode_incr; + return (byte); +} + +ushort_t +get_next_token(fcode_env_t *env) +{ + ushort_t token = next_bytecode(env); + if ((token) && (token < 0x10)) { + token = (token << 8) | next_bytecode(env); + } + env->last_fcode = token; + return (token); +} + +ushort_t +get_short(fcode_env_t *env) +{ + ushort_t u; + + /* + * Logical or DOES NOT guarantee left to right evaluation... + */ + u = next_bytecode(env) << 8; + return (u | next_bytecode(env)); +} + +uint_t +get_int(fcode_env_t *env) +{ + uint_t u; + + /* + * Logical or DOES NOT guarantee left to right evaluation... + */ + u = get_short(env) << 16; + return (u | get_short(env)); +} + +void +expose_acf(fcode_env_t *env, char *name) +{ + if (name == NULL) + name = "<unknown>"; + EXPOSE_ACF; + debug_msg(DEBUG_CONTEXT, "CONTEXT:expose_acf: acf: %p/'%s' %p\n", + LINK_TO_ACF(env->lastlink), name, env->current); +} + +void +do_code(fcode_env_t *env, int token, char *name, void (*fn)(fcode_env_t *)) +{ + env->table[token].name = name; + if (fn == NULL) { + env->table[token].apf = NULL; + env->table[token].name = name; + } else { + header(env, name, strlen(name), 0); + env->table[token].apf = (acf_t)HERE; + COMPILE_TOKEN(fn); + expose_acf(env, name); + } +} + +void +define_word(fcode_env_t *env, int flag, char *name, void (*fn)(fcode_env_t *)) +{ + header(env, name, strlen(name), flag); + COMPILE_TOKEN(fn); + expose_acf(env, name); +} + +void +end0(fcode_env_t *env) +{ + env->interpretting = 0; +} + +static void +end1(fcode_env_t *env) +{ + env->interpretting = 0; +} + +void +blit(fcode_env_t *env) +{ + fstack_t d = (int)get_int(env); + PUSH(DS, d); + literal(env); +} + +void (*bbranch_ptrs[3])(fcode_env_t *env) = { + do_bbranch, + do_bqbranch, + do_bofbranch +}; + +void +branch_common(fcode_env_t *env, short direction, fstack_t which, int doswap) +{ + fstack_t *sp; + token_t *branch_loc; + + ASSERT((which < 3) && (which >= 0)); + which = (fstack_t)&bbranch_ptrs[which]; + set_temporary_compile(env); + COMPILE_TOKEN(which); + if (direction >= 0) { + bmark(env); + if (doswap) + swap(env); + PUSH(DS, 0); + compile_comma(env); + } else { + + /* + * We look down the stack for a branch location + * that isn't pointing to zero (i.e. a forward branch label). + * We move the first one we find to the top of the stack, + * which is what gets compiled in with 'compile_comma'. + * Not finding a valid branch label is bad. + */ + for (sp = env->ds; sp >= env->ds0; sp--) { + branch_loc = (token_t *)*sp; + if (branch_loc && *branch_loc) { + break; + } + } + if (sp < env->ds0) + log_message(MSG_ERROR, "branch_common: back: " + "no branch loc on stack\n"); + else { + /* Move branch_loc to top of data stack */ + for (; sp < env->ds; sp++) + *sp = sp[1]; + *sp = (fstack_t)branch_loc; + } + env->level--; + compile_comma(env); + temporary_execute(env); + } +} + +void +bbranch(fcode_env_t *env) +{ + short offset = (short)get_short(env); + + branch_common(env, offset, 0, 1); +} + +void +bqbranch(fcode_env_t *env) +{ + short offset = (short)get_short(env); + + branch_common(env, offset, 1, 0); +} + +void +do_quote(fcode_env_t *env) +{ + int len; + uchar_t *strptr; + + strptr = (uchar_t *)IP; + len = *strptr; + PUSH(DS, (fstack_t)strptr+1); + PUSH(DS, len); + strptr += TOKEN_ROUNDUP(len+2); + IP = (token_t *)strptr; +} + +void +bquote(fcode_env_t *env) +{ + char stringbuff[256]; + int len, count; + char *strptr; + + count = len = next_bytecode(env); + if (env->state) { + COMPILE_TOKEN("e_ptr); + strptr = (char *)HERE; + *strptr++ = len; + while (count--) + *strptr++ = next_bytecode(env); + *strptr++ = 0; + set_here(env, (uchar_t *)strptr, "bquote"); + token_roundup(env, "bquote"); + } else { + strptr = stringbuff; + while (count--) + *strptr++ = next_bytecode(env); + *strptr = 0; + push_string(env, stringbuff, len); + } +} + +char * +get_name(token_t *linkp) +{ + char *name, *p; + flag_t *fptr = LINK_TO_FLAGS(linkp); + int len; + char *cptr; + + if (*fptr & FLAG_NONAME) + return (NULL); + + cptr = (char *)fptr; + len = cptr[-1]; + if (len <= 0 || len > 64 || cptr[-2] != '\0') + return (NULL); + + name = cptr - (len+2); + + for (p = name; *p != '\0'; p++) + if (!isprint(*p)) + return (NULL); + + if ((p - name) != len) + return (NULL); + + return (name); +} + +void +header(fcode_env_t *env, char *name, int len, flag_t flag) +{ + char *strptr; + flag_t *fptr; + acf_t dptr; + extern void add_debug_acf(fcode_env_t *, acf_t); + + /* Now form the entry in the dictionary */ + token_roundup(env, "header"); + dptr = (acf_t)HERE; + if (len) { + int bytes = len+2+sizeof (flag_t); + dptr = (acf_t)(TOKEN_ROUNDUP(HERE+bytes)); + fptr = LINK_TO_FLAGS(dptr); + strptr = (char *)fptr - 1; + *strptr-- = len; + *strptr-- = 0; + while (len) + *strptr-- = name[--len]; + } else { + dptr++; + fptr = LINK_TO_FLAGS(dptr); + flag |= FLAG_NONAME; + } + *fptr = flag; + *dptr = *((acf_t)env->current); + env->lastlink = dptr++; + set_here(env, (uchar_t *)dptr, "header"); + + if (name_is_debugged(env, name)) { + log_message(MSG_INFO, "Turning debug on for %s\n", name); + add_debug_acf(env, LINK_TO_ACF(env->lastlink)); + } + debug_msg(DEBUG_HEADER, "Define: '%s' @ %p\n", name, HERE); +} + +void +token_common(fcode_env_t *env, int headered, int visible) +{ + char namebuff[32]; + int len, count, token; + char *strptr, c; + + strptr = namebuff; + if (headered) { + len = next_bytecode(env); + for (count = 0; count < len; count++) { + c = next_bytecode(env); + if (count < sizeof (namebuff)) + *strptr++ = c; + } + } + + if (!visible) + len = 0; + *strptr = 0; + token = get_short(env); + env->last_token = token; + + debug_msg(DEBUG_NEW_TOKEN, "Define %s token: '%s' (%x)\n", + (visible ? "named" : "headerless"), namebuff, token); + + header(env, namebuff, len, 0); + env->table[token].flags = 0; + if (len) { + env->table[token].name = MALLOC(len+1); + strncpy(env->table[token].name, namebuff, len); + } else { + env->table[token].name = NULL; + } + env->last_token = token; +} + +void +named_token(fcode_env_t *env) +{ + token_common(env, 1, env->fcode_debug); +} + +void +external_token(fcode_env_t *env) +{ + token_common(env, 1, 1); +} + +void +new_token(fcode_env_t *env) +{ + token_common(env, 0, 0); +} + +void +offset16(fcode_env_t *env) +{ + env->offset_incr = 2; +} + +void +minus_one(fcode_env_t *env) +{ + PUSH(DS, -1); +} + +void +zero(fcode_env_t *env) +{ + PUSH(DS, 0); +} + +void +one(fcode_env_t *env) +{ + PUSH(DS, 1); +} + +void +two(fcode_env_t *env) +{ + PUSH(DS, 2); +} + +void +three(fcode_env_t *env) +{ + PUSH(DS, 3); +} + +void +version1(fcode_env_t *env) +{ + env->fcode_incr = 1; +} + +static void +start0(fcode_env_t *env) +{ + env->fcode_incr = 1; +} + +static void +start1(fcode_env_t *env) +{ + env->fcode_incr = 1; +} + +void +start2(fcode_env_t *env) +{ + env->fcode_incr = 2; +} + +static void +start4(fcode_env_t *env) +{ + env->fcode_incr = 4; +} + +int +check_fcode_header(char *fname, uchar_t *header, int len) +{ + uint32_t length; + static char func_name[] = "check_fcode_header"; + + if (len <= 8) { + log_message(MSG_ERROR, "%s: '%s' fcode size (%d) <= 8\n", + func_name, fname, len); + return (0); + } + if (header[0] != 0xf1 && header[0] != 0xfd) { + log_message(MSG_ERROR, "%s: '%s' header[0] is 0x%02x not" + " 0xf1/0xfd\n", func_name, fname, header[0]); + return (0); + } + length = (header[4] << 24) | (header[5] << 16) | (header[6] << 8) | + header[7]; + if (length > len) { + log_message(MSG_ERROR, "%s: '%s' length (%d) >" + " fcode size (%d)\n", func_name, fname, length, len); + return (0); + } + if (length < len) { + log_message(MSG_WARN, "%s: '%s' length (%d) <" + " fcode size (%d)\n", func_name, fname, length, len); + } + return (1); +} + +void +byte_load(fcode_env_t *env) +{ + uchar_t *fcode_buffer; + uchar_t *fcode_ptr; + int fcode_incr; + int offset_incr; + int fcode_xt; + int interpretting; + int depth; + int length; + int past_eob = 0; + int db; + + /* save any existing interpret state */ + fcode_buffer = env->fcode_buffer; + fcode_ptr = env->fcode_ptr; + fcode_incr = env->fcode_incr; + offset_incr = env->offset_incr; + interpretting = env->interpretting; + depth = DEPTH-2; + + /* Now init them */ + CHECK_DEPTH(env, 2, "byte-load"); + fcode_xt = POP(DS); + env->fcode_ptr = env->fcode_buffer = (uchar_t *)POP(DS); + if (fcode_xt != 1) { + log_message(MSG_WARN, "byte-load: ignoring xt\n"); + } + + length = (env->fcode_buffer[4] << 24) | (env->fcode_buffer[5] << 16) | + (env->fcode_buffer[6] << 8) | env->fcode_buffer[7]; + if (!check_fcode_header("byte-load", env->fcode_ptr, length)) + log_message(MSG_WARN, "byte-load: header NOT OK\n"); + + env->fcode_incr = 1; + env->offset_incr = 1; + env->interpretting = 1; + env->level = 0; + + db = get_interpreter_debug_level() & + (DEBUG_BYTELOAD_DS|DEBUG_BYTELOAD_RS|DEBUG_BYTELOAD_TOKENS); + debug_msg(db, "byte_load: %p, %d\n", env->fcode_buffer, fcode_xt); + debug_msg(db, " header: %x, %x\n", + env->fcode_buffer[0], env->fcode_buffer[1]); + debug_msg(db, " crc: %x\n", + (env->fcode_buffer[2]<<8)|(env->fcode_buffer[3])); + debug_msg(db, " length: %x\n", length); + env->fcode_ptr += 8; + + debug_msg(db, "Interpretting: %d\n", env->interpretting); + + while (env->interpretting) { + int token; + fcode_token *entry; + acf_t apf; + + if (!past_eob && env->fcode_ptr >= env->fcode_buffer + length) { + log_message(MSG_WARN, "byte-load: past EOB\n"); + past_eob = 1; + } + + env->last_fcode_ptr = env->fcode_ptr; + token = get_next_token(env); + + entry = &env->table[token]; + apf = entry->apf; + + DEBUGF(BYTELOAD_DS, output_data_stack(env, MSG_FC_DEBUG)); + DEBUGF(BYTELOAD_RS, output_return_stack(env, 1, MSG_FC_DEBUG)); + DEBUGF(BYTELOAD_TOKENS, log_message(MSG_FC_DEBUG, + "%s: %04x %03x %s (%x)", + ((env->state && (entry->flags & IMMEDIATE) == 0)) ? + "Compile" : "Execute", + env->last_fcode_ptr - env->fcode_buffer, token, + entry->name ? entry->name : "???", entry->flags)); + if (db) + log_message(MSG_FC_DEBUG, "\n"); + if (apf) { + DEBUGF(TOKEN_USAGE, entry->usage++); + PUSH(DS, (fstack_t)apf); + if ((env->state) && + ((entry->flags & IMMEDIATE) == 0)) { + /* Compile in references */ + compile_comma(env); + } else { + execute(env); + } + } + } + if (DEPTH != depth) { + log_message(MSG_ERROR, "FCODE has net stack change of %d\n", + DEPTH-depth); + } + /* restore old state */ + env->fcode_ptr = fcode_ptr; + env->fcode_buffer = fcode_buffer; + env->fcode_incr = fcode_incr; + env->offset_incr = offset_incr; + env->interpretting = interpretting; +} + +void +btick(fcode_env_t *env) +{ + int token = get_next_token(env); + + PUSH(DS, (fstack_t)env->table[token].apf); + tick_literal(env); +} + +static void +show_fcode_def(fcode_env_t *env, char *type) +{ + int i = env->last_token; + + if (get_interpreter_debug_level() & DEBUG_DUMP_TOKENS) { + if (env->table[i].name) + log_message(MSG_INFO, "%s: %s %03x %p\n", type, + env->table[i].name, i, env->table[i].apf); + else + log_message(MSG_INFO, "%s: <noname> %03x %p\n", type, i, + env->table[i].apf); + } +} + +void +bcolon(fcode_env_t *env) +{ + if (env->state == 0) { + env->table[env->last_token].apf = (acf_t)HERE; + env->table[env->last_token].flags = 0; + show_fcode_def(env, "bcolon"); + } + env->state |= 1; + COMPILE_TOKEN(&do_colon); +} + +void +bcreate(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bcreate"); + COMPILE_TOKEN(&do_create); + expose_acf(env, "<bcreate>"); +} + +void +get_token_name(fcode_env_t *env, int token, char **name, int *len) +{ + *name = env->table[token].name; + if (*name) { + *len = strlen(*name); + } else + *len = 0; +} + +void +bvalue(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bvalue"); + make_common_access(env, 0, 0, 1, + env->instance_mode, &noop, &noop, &set_value_actions); +} + +void +bvariable(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bvariable"); + PUSH(DS, 0); + make_common_access(env, 0, 0, 1, + env->instance_mode, &instance_variable, &do_create, NULL); +} + +void +bconstant(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bconstant"); + make_common_access(env, 0, 0, 1, + env->instance_mode, &do_constant, &do_constant, NULL); +} + +void +bdefer(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bdefer"); + + PUSH(DS, (fstack_t)&crash_ptr); + make_common_access(env, 0, 0, 1, env->instance_mode, + &noop, &noop, &set_defer_actions); +} + +void +bbuffer_colon(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "buffer:"); + PUSH(DS, 0); + make_common_access(env, 0, 0, 2, env->instance_mode, + &noop, &noop, &set_buffer_actions); +} + +void +do_field(fcode_env_t *env) +{ + fstack_t *d; + + d = (fstack_t *)WA; + TOS += *d; +} + +void +bfield(fcode_env_t *env) +{ + env->table[env->last_token].apf = (acf_t)HERE; + show_fcode_def(env, "bfield"); + COMPILE_TOKEN(&do_field); + over(env); + compile_comma(env); + add(env); + expose_acf(env, "<bfield>"); +} + +void +bto(fcode_env_t *env) +{ + btick(env); + + if (env->state) { + COMPILE_TOKEN(&to_ptr); + } else { + do_set_action(env); + } +} + +void +get_token(fcode_env_t *env) +{ + fstack_t tok; + fstack_t immediate = 0; + + CHECK_DEPTH(env, 1, "get-token"); + tok = POP(DS); + tok &= MAX_FCODE; + PUSH(DS, (fstack_t)env->table[tok].apf); + if (env->table[tok].flags & IMMEDIATE) immediate = 1; + PUSH(DS, immediate); +} + +void +set_token(fcode_env_t *env) +{ + fstack_t tok; + fstack_t immediate; + acf_t acf; + + CHECK_DEPTH(env, 3, "set-token"); + tok = POP(DS); + tok &= MAX_FCODE; + immediate = POP(DS); + acf = (acf_t)POP(DS); + if (immediate) + env->table[tok].flags |= IMMEDIATE; + else + env->table[tok].flags &= ~IMMEDIATE; + env->table[tok].apf = acf; + immediate = env->last_token; + env->last_token = tok; + show_fcode_def(env, "set_token"); + env->last_token = immediate; +} + +void +bof(fcode_env_t *env) +{ + short offset = get_short(env); + branch_common(env, offset, 2, 0); +} + +void +bcase(fcode_env_t *env) +{ + env->level++; + set_temporary_compile(env); + PUSH(DS, 0); +} + +void +bendcase(fcode_env_t *env) +{ + COMPILE_TOKEN(env->table[0x46].apf); /* Hack for now... */ + while (TOS) { + bresolve(env); + } + (void) POP(DS); + env->level--; + temporary_execute(env); +} + +void +bendof(fcode_env_t *env) +{ + short offset = get_short(env); + branch_common(env, offset, 0, 1); + bresolve(env); +} + +void +fcode_revision(fcode_env_t *env) +{ + /* We are Version 3.0 */ + PUSH(DS, 0x30000); +} + +void +alloc_mem(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "alloc-mem"); + TOS = (fstack_t)MALLOC((size_t)TOS); + if (!TOS) { + throw_from_fclib(env, 1, "alloc-mem failed"); + } +} + +void +free_mem(fcode_env_t *env) +{ + void *p; + + CHECK_DEPTH(env, 2, "free-mem"); + (void) POP(DS); + p = (void *) POP(DS); + FREE(p); +} + +void +parse_two_int(fcode_env_t *env) +{ + uint_t lo, hi; + char *str; + int len; + + CHECK_DEPTH(env, 2, "parse-2int"); + lo = 0; + hi = 0; + str = pop_a_string(env, &len); + if (len) { + if (sscanf(str, "%x,%x", &hi, &lo) != 2) { + throw_from_fclib(env, 1, "parse_2int"); + } + } + PUSH(DS, lo); + PUSH(DS, hi); +} + +void +left_parse_string(fcode_env_t *env) +{ + char sep, *cptr, *lstr, *rstr; + int len, llen, rlen; + + CHECK_DEPTH(env, 3, "left-parse-string"); + sep = (char)POP(DS); + if (TOS == 0) { + two_dup(env); + return; + } + lstr = pop_a_string(env, &llen); + len = 0; + cptr = NULL; + while (len < llen) { + if (lstr[len] == sep) { + cptr = lstr+len; + break; + } + len++; + } + if (cptr != NULL) { + rstr = cptr+1; + rlen = lstr + llen - rstr; + llen = len; + } else { + rlen = 0; + rstr = lstr; + } + PUSH(DS, (fstack_t)rstr); + PUSH(DS, rlen); + PUSH(DS, (fstack_t)lstr); + PUSH(DS, llen); +} + +/* + * (is-user-word) ( name-str name-len xt -- ) + */ +void +is_user_word(fcode_env_t *env) +{ + fstack_t xt; + char *name; + int len; + + CHECK_DEPTH(env, 3, "(is-user-word)"); + xt = POP(DS); + name = pop_a_string(env, &len); + header(env, name, len, 0); + COMPILE_TOKEN(&do_alias); + COMPILE_TOKEN(xt); + expose_acf(env, name); +} + +void +f_error(fcode_env_t *env) +{ +#if 0 + env->interpretting = 0; + log_message(MSG_ERROR, "Uniplemented FCODE token encountered %x\n", + env->last_fcode); +#else + forth_abort(env, "Unimplemented FCODE token: 0x%x\n", env->last_fcode); +#endif +} + +static void +fcode_buffer_addr(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)(env->fcode_buffer)); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + P1275(0x000, DEFINER, "end0", end0); + P1275(0x010, DEFINER, "b(lit)", blit); + P1275(0x011, DEFINER, "b(')", btick); + P1275(0x012, DEFINER, "b(\")", bquote); + P1275(0x013, DEFINER, "bbranch", bbranch); + P1275(0x014, DEFINER, "b?branch", bqbranch); + P1275(0x015, DEFINER, "b(loop)", bloop); + P1275(0x016, DEFINER, "b(+loop)", bplusloop); + P1275(0x017, DEFINER, "b(do)", bdo); + P1275(0x018, DEFINER, "b(?do)", bqdo); + P1275(0x01b, DEFINER, "b(leave)", bleave); + P1275(0x01c, DEFINER, "b(of)", bof); + + P1275(0x087, 0, "fcode-revision", fcode_revision); + + P1275(0x08b, 0, "alloc-mem", alloc_mem); + P1275(0x08c, 0, "free-mem", free_mem); + + P1275(0x0a4, 0, "-1", minus_one); + P1275(0x0a5, 0, "0", zero); + P1275(0x0a6, 0, "1", one); + P1275(0x0a7, 0, "2", two); + P1275(0x0a8, 0, "3", three); + + P1275(0x0ae, 0, "aligned", aligned); + P1275(0x0b1, DEFINER, "b(<mark)", bmark); + P1275(0x0b2, DEFINER, "b(>resolve)", bresolve); + FCODE(0x0b3, 0, "set-token-table", fc_historical); + FCODE(0x0b4, 0, "set-table", fc_historical); + P1275(0x0b5, 0, "new-token", new_token); + P1275(0x0b6, 0, "named-token", named_token); + P1275(0x0b7, DEFINER, "b(:)", bcolon); + P1275(0x0b8, DEFINER, "b(value)", bvalue); + P1275(0x0b9, DEFINER, "b(variable)", bvariable); + P1275(0x0ba, DEFINER, "b(constant)", bconstant); + P1275(0x0bb, DEFINER, "b(create)", bcreate); + P1275(0x0bc, DEFINER, "b(defer)", bdefer); + P1275(0x0bd, 0, "b(buffer:)", bbuffer_colon); + P1275(0x0be, 0, "b(field)", bfield); + FCODE(0x0bf, 0, "b(code)", fc_historical); + P1275(0x0c0, IMMEDIATE, "instance", instance); + + P1275(0x0c2, DEFINER, "b(;)", semi); + P1275(0x0c3, DEFINER, "b(to)", bto); + P1275(0x0c4, DEFINER, "b(case)", bcase); + P1275(0x0c5, DEFINER, "b(endcase)", bendcase); + P1275(0x0c6, DEFINER, "b(endof)", bendof); + + P1275(0x0ca, 0, "external-token", external_token); + P1275(0x0cc, 0, "offset16", offset16); + P1275(0x0cd, 0, "evaluate", evaluate); + + P1275(0x0da, 0, "get-token", get_token); + P1275(0x0db, 0, "set-token", set_token); + + P1275(0x0f0, 0, "start0", start0); + P1275(0x0f1, 0, "start1", start1); + P1275(0x0f2, 0, "start2", start2); + P1275(0x0f3, 0, "start4", start4); + + P1275(0x0fd, 0, "version1", version1); + FCODE(0x0fe, 0, "4-byte-id", fc_historical); + + P1275(0x0ff, 0, "end1", end1); + + /* Call it "old-dma-alloc" so no one gets confused */ + FCODE(0x101, 0, "old-dma-alloc", fc_historical); + + FCODE(0x104, 0, "memmap", fc_historical); + FCODE(0x105, 0, "free-virtual", fc_unimplemented); + + FCODE(0x106, 0, ">physical", fc_historical); + + FCODE(0x10f, 0, "my-params", fc_historical); + + P1275(0x11b, 0, "parse-2int", parse_two_int); + + FCODE(0x122, 0, "memory-test-suite", fc_unimplemented); + FCODE(0x123, 0, "group-code", fc_historical); + FCODE(0x124, 0, "mask", fc_unimplemented); + + FCODE(0x130, 0, "map-low", fc_unimplemented); + FCODE(0x131, 0, "sbus-intr>cpu", fc_unimplemented); + + FCODE(0x170, 0, "fb1-draw-character", fc_historical); + FCODE(0x171, 0, "fb1-reset-screen", fc_historical); + FCODE(0x172, 0, "fb1-toggle-cursor", fc_historical); + FCODE(0x173, 0, "fb1-erase-screen", fc_historical); + FCODE(0x174, 0, "fb1-blink-screen", fc_historical); + FCODE(0x175, 0, "fb1-invert-screen", fc_historical); + FCODE(0x176, 0, "fb1-insert-characters", fc_historical); + FCODE(0x177, 0, "fb1-delete-characters", fc_historical); + FCODE(0x178, 0, "fb1-insert-lines", fc_historical); + FCODE(0x179, 0, "fb1-delete-lines", fc_historical); + FCODE(0x17a, 0, "fb1-draw-logo", fc_historical); + FCODE(0x17b, 0, "fb1-install", fc_historical); + FCODE(0x17c, 0, "fb1-slide-up", fc_historical); + + FCODE(0x190, 0, "VME-bus Support", fc_obsolete); + FCODE(0x191, 0, "VME-bus Support", fc_obsolete); + FCODE(0x192, 0, "VME-bus Support", fc_obsolete); + FCODE(0x193, 0, "VME-bus Support", fc_obsolete); + FCODE(0x194, 0, "VME-bus Support", fc_obsolete); + FCODE(0x195, 0, "VME-bus Support", fc_obsolete); + FCODE(0x196, 0, "VME-bus Support", fc_obsolete); + + FCODE(0x1a0, 0, "return-buffer", fc_historical); + FCODE(0x1a1, 0, "xmit-packet", fc_historical); + FCODE(0x1a2, 0, "poll-packet", fc_historical); + + FCODE(0x210, 0, "processor-type", fc_historical); + FCODE(0x211, 0, "firmware-version", fc_historical); + FCODE(0x212, 0, "fcode-version", fc_historical); + + FCODE(0x214, 0, "(is-user-word)", is_user_word); + FCODE(0x215, 0, "suspend-fcode", fc_unimplemented); + + FCODE(0x229, 0, "adr-mask", fc_historical); + + FCODE(0x238, 0, "probe", fc_historical); + FCODE(0x239, 0, "probe-virtual", fc_historical); + + P1275(0x23e, 0, "byte-load", byte_load); + + P1275(0x240, 0, "left-parse-string", left_parse_string); + FORTH(0, "fcode-buffer", fcode_buffer_addr); +} diff --git a/usr/src/lib/efcode/engine/font.c b/usr/src/lib/efcode/engine/font.c new file mode 100644 index 0000000000..a38307480f --- /dev/null +++ b/usr/src/lib/efcode/engine/font.c @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <fcode/private.h> + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + P1275(0x16a, 0, "default-font", fc_unimplemented); + P1275(0x16b, 0, "set-font", fc_unimplemented); + P1275(0x16c, 0, "char-height", fc_unimplemented); + P1275(0x16d, 0, "char-width", fc_unimplemented); + P1275(0x16e, 0, ">font", fc_unimplemented); + P1275(0x16f, 0, "fontbytes", fc_unimplemented); +} diff --git a/usr/src/lib/efcode/engine/forth.c b/usr/src/lib/efcode/engine/forth.c new file mode 100644 index 0000000000..b0b8005342 --- /dev/null +++ b/usr/src/lib/efcode/engine/forth.c @@ -0,0 +1,2675 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +void (*semi_ptr)(fcode_env_t *env) = do_semi; +void (*does_ptr)(fcode_env_t *env) = install_does; +void (*quote_ptr)(fcode_env_t *env) = do_quote; +void (*blit_ptr)(fcode_env_t *env) = do_literal; +void (*tlit_ptr)(fcode_env_t *env) = do_literal; +void (*do_bdo_ptr)(fcode_env_t *env) = do_bdo; +void (*do_bqdo_ptr)(fcode_env_t *env) = do_bqdo; +void (*create_ptr)(fcode_env_t *env) = do_creator; +void (*do_leave_ptr)(fcode_env_t *env) = do_bleave; +void (*do_loop_ptr)(fcode_env_t *env) = do_bloop; +void (*do_ploop_ptr)(fcode_env_t *env) = do_bploop; + +void unaligned_lstore(fcode_env_t *); +void unaligned_wstore(fcode_env_t *); +void unaligned_lfetch(fcode_env_t *); +void unaligned_wfetch(fcode_env_t *); + +/* start with the simple maths functions */ + + +void +add(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "+"); + d = POP(DS); + TOS += d; +} + +void +subtract(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "-"); + d = POP(DS); + TOS -= d; +} + +void +multiply(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "*"); + d = POP(DS); + TOS *= d; +} + +void +slash_mod(fcode_env_t *env) +{ + fstack_t d, o, t, rem; + int sign = 1; + + CHECK_DEPTH(env, 2, "/mod"); + d = POP(DS); + o = t = POP(DS); + + if (d == 0) { + throw_from_fclib(env, 1, "/mod divide by zero"); + } + sign = ((d ^ t) < 0); + if (d < 0) { + d = -d; + if (sign) { + t += (d-1); + } + } + if (t < 0) { + if (sign) { + t -= (d-1); + } + t = -t; + } + t = t / d; + if ((o ^ sign) < 0) { + rem = (t * d) + o; + } else { + rem = o - (t*d); + } + if (sign) { + t = -t; + } + PUSH(DS, rem); + PUSH(DS, t); +} + +/* + * 'u/mod' Fcode implementation. + */ +void +uslash_mod(fcode_env_t *env) +{ + u_lforth_t u1, u2; + + CHECK_DEPTH(env, 2, "u/mod"); + u2 = POP(DS); + u1 = POP(DS); + + if (u2 == 0) + forth_abort(env, "u/mod: divide by zero"); + PUSH(DS, u1 % u2); + PUSH(DS, u1 / u2); +} + +void +divide(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "/"); + slash_mod(env); + nip(env); +} + +void +mod(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "mod"); + slash_mod(env); + drop(env); +} + +void +and(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "and"); + d = POP(DS); + TOS &= d; +} + +void +or(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "or"); + d = POP(DS); + TOS |= d; +} + +void +xor(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "xor"); + d = POP(DS); + TOS ^= d; +} + +void +invert(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "invert"); + TOS = ~TOS; +} + +void +lshift(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "lshift"); + d = POP(DS); + TOS = TOS << d; +} + +void +rshift(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "rshift"); + d = POP(DS); + TOS = ((ufstack_t)TOS) >> d; +} + +void +rshifta(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, ">>a"); + d = POP(DS); + TOS = ((s_lforth_t)TOS) >> d; +} + +void +negate(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "negate"); + TOS = -TOS; +} + +void +f_abs(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "abs"); + if (TOS < 0) TOS = -TOS; +} + +void +f_min(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "min"); + d = POP(DS); + if (d < TOS) TOS = d; +} + +void +f_max(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "max"); + d = POP(DS); + if (d > TOS) TOS = d; +} + +void +to_r(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, ">r"); + PUSH(RS, POP(DS)); +} + +void +from_r(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 1, "r>"); + PUSH(DS, POP(RS)); +} + +void +rfetch(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 1, "r@"); + PUSH(DS, *RS); +} + +void +f_exit(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 1, "exit"); + IP = (token_t *)POP(RS); +} + +#define COMPARE(cmp, rhs) ((((s_lforth_t)TOS) cmp((s_lforth_t)(rhs))) ? \ + TRUE : FALSE) +#define UCOMPARE(cmp, rhs) ((((u_lforth_t)TOS) cmp((u_lforth_t)(rhs))) ? \ + TRUE : FALSE) +#define EQUALS == +#define NOTEQUALS != +#define LESSTHAN < +#define LESSEQUALS <= +#define GREATERTHAN > +#define GREATEREQUALS >= + +void +zero_equals(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0="); + TOS = COMPARE(EQUALS, 0); +} + +void +zero_not_equals(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0<>"); + TOS = COMPARE(NOTEQUALS, 0); +} + +void +zero_less(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0<"); + TOS = COMPARE(LESSTHAN, 0); +} + +void +zero_less_equals(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0<="); + TOS = COMPARE(LESSEQUALS, 0); +} + +void +zero_greater(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0>"); + TOS = COMPARE(GREATERTHAN, 0); +} + +void +zero_greater_equals(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "0>="); + TOS = COMPARE(GREATEREQUALS, 0); +} + +void +less(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "<"); + d = POP(DS); + TOS = COMPARE(LESSTHAN, d); +} + +void +greater(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, ">"); + d = POP(DS); + TOS = COMPARE(GREATERTHAN, d); +} + +void +equals(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "="); + d = POP(DS); + TOS = COMPARE(EQUALS, d); +} + +void +not_equals(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "<>"); + d = POP(DS); + TOS = COMPARE(NOTEQUALS, d); +} + + +void +unsign_greater(fcode_env_t *env) +{ + ufstack_t d; + + CHECK_DEPTH(env, 2, "u>"); + d = POP(DS); + TOS = UCOMPARE(GREATERTHAN, d); +} + +void +unsign_less_equals(fcode_env_t *env) +{ + ufstack_t d; + + CHECK_DEPTH(env, 2, "u<="); + d = POP(DS); + TOS = UCOMPARE(LESSEQUALS, d); +} + +void +unsign_less(fcode_env_t *env) +{ + ufstack_t d; + + CHECK_DEPTH(env, 2, "u<"); + d = POP(DS); + TOS = UCOMPARE(LESSTHAN, d); +} + +void +unsign_greater_equals(fcode_env_t *env) +{ + ufstack_t d; + + CHECK_DEPTH(env, 2, "u>="); + d = POP(DS); + TOS = UCOMPARE(GREATEREQUALS, d); +} + +void +greater_equals(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, ">="); + d = POP(DS); + TOS = COMPARE(GREATEREQUALS, d); +} + +void +less_equals(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "<="); + d = POP(DS); + TOS = COMPARE(LESSEQUALS, d); +} + +void +between(fcode_env_t *env) +{ + s_lforth_t hi, lo; + + CHECK_DEPTH(env, 3, "between"); + hi = (s_lforth_t)POP(DS); + lo = (s_lforth_t)POP(DS); + TOS = (((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS <= hi) ? -1 : 0); +} + +void +within(fcode_env_t *env) +{ + s_lforth_t lo, hi; + + CHECK_DEPTH(env, 3, "within"); + hi = (s_lforth_t)POP(DS); + lo = (s_lforth_t)POP(DS); + TOS = ((((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS < hi)) ? -1 : 0); +} + +void +do_literal(fcode_env_t *env) +{ + PUSH(DS, *IP); + IP++; +} + +void +literal(fcode_env_t *env) +{ + if (env->state) { + COMPILE_TOKEN(&blit_ptr); + compile_comma(env); + } +} + +void +do_also(fcode_env_t *env) +{ + token_t *d = *ORDER; + + if (env->order_depth < (MAX_ORDER - 1)) { + env->order[++env->order_depth] = d; + debug_msg(DEBUG_CONTEXT, "CONTEXT:also: %d/%p/%p\n", + env->order_depth, CONTEXT, env->current); + } else + log_message(MSG_WARN, "Vocabulary search order exceeds: %d\n", + MAX_ORDER); +} + +void +do_previous(fcode_env_t *env) +{ + if (env->order_depth) { + env->order_depth--; + debug_msg(DEBUG_CONTEXT, "CONTEXT:previous: %d/%p/%p\n", + env->order_depth, CONTEXT, env->current); + } +} + +#ifdef DEBUG +void +do_order(fcode_env_t *env) +{ + int i; + + log_message(MSG_INFO, "Order: Depth: %ld: ", env->order_depth); + for (i = env->order_depth; i >= 0 && env->order[i]; i--) + log_message(MSG_INFO, "%p ", (void *)env->order[i]); + log_message(MSG_INFO, "\n"); +} +#endif + +void +noop(fcode_env_t *env) +{ + /* what a waste of cycles */ +} + + +#define FW_PER_FL (sizeof (lforth_t)/sizeof (wforth_t)) + +void +lwsplit(fcode_env_t *env) +{ + union { + u_wforth_t l_wf[FW_PER_FL]; + u_lforth_t l_lf; + } d; + int i; + + CHECK_DEPTH(env, 1, "lwsplit"); + d.l_lf = POP(DS); + for (i = 0; i < FW_PER_FL; i++) + PUSH(DS, d.l_wf[(FW_PER_FL - 1) - i]); +} + +void +wljoin(fcode_env_t *env) +{ + union { + u_wforth_t l_wf[FW_PER_FL]; + u_lforth_t l_lf; + } d; + int i; + + CHECK_DEPTH(env, FW_PER_FL, "wljoin"); + for (i = 0; i < FW_PER_FL; i++) + d.l_wf[i] = POP(DS); + PUSH(DS, d.l_lf); +} + +void +lwflip(fcode_env_t *env) +{ + union { + u_wforth_t l_wf[FW_PER_FL]; + u_lforth_t l_lf; + } d, c; + int i; + + CHECK_DEPTH(env, 1, "lwflip"); + d.l_lf = POP(DS); + for (i = 0; i < FW_PER_FL; i++) + c.l_wf[i] = d.l_wf[(FW_PER_FL - 1) - i]; + PUSH(DS, c.l_lf); +} + +void +lbsplit(fcode_env_t *env) +{ + union { + uchar_t l_bytes[sizeof (lforth_t)]; + u_lforth_t l_lf; + } d; + int i; + + CHECK_DEPTH(env, 1, "lbsplit"); + d.l_lf = POP(DS); + for (i = 0; i < sizeof (lforth_t); i++) + PUSH(DS, d.l_bytes[(sizeof (lforth_t) - 1) - i]); +} + +void +bljoin(fcode_env_t *env) +{ + union { + uchar_t l_bytes[sizeof (lforth_t)]; + u_lforth_t l_lf; + } d; + int i; + + CHECK_DEPTH(env, sizeof (lforth_t), "bljoin"); + for (i = 0; i < sizeof (lforth_t); i++) + d.l_bytes[i] = POP(DS); + PUSH(DS, (fstack_t)d.l_lf); +} + +void +lbflip(fcode_env_t *env) +{ + union { + uchar_t l_bytes[sizeof (lforth_t)]; + u_lforth_t l_lf; + } d, c; + int i; + + CHECK_DEPTH(env, 1, "lbflip"); + d.l_lf = POP(DS); + for (i = 0; i < sizeof (lforth_t); i++) + c.l_bytes[i] = d.l_bytes[(sizeof (lforth_t) - 1) - i]; + PUSH(DS, c.l_lf); +} + +void +wbsplit(fcode_env_t *env) +{ + union { + uchar_t w_bytes[sizeof (wforth_t)]; + u_wforth_t w_wf; + } d; + int i; + + CHECK_DEPTH(env, 1, "wbsplit"); + d.w_wf = POP(DS); + for (i = 0; i < sizeof (wforth_t); i++) + PUSH(DS, d.w_bytes[(sizeof (wforth_t) - 1) - i]); +} + +void +bwjoin(fcode_env_t *env) +{ + union { + uchar_t w_bytes[sizeof (wforth_t)]; + u_wforth_t w_wf; + } d; + int i; + + CHECK_DEPTH(env, sizeof (wforth_t), "bwjoin"); + for (i = 0; i < sizeof (wforth_t); i++) + d.w_bytes[i] = POP(DS); + PUSH(DS, d.w_wf); +} + +void +wbflip(fcode_env_t *env) +{ + union { + uchar_t w_bytes[sizeof (wforth_t)]; + u_wforth_t w_wf; + } c, d; + int i; + + CHECK_DEPTH(env, 1, "wbflip"); + d.w_wf = POP(DS); + for (i = 0; i < sizeof (wforth_t); i++) + c.w_bytes[i] = d.w_bytes[(sizeof (wforth_t) - 1) - i]; + PUSH(DS, c.w_wf); +} + +void +upper_case(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "upc"); + TOS = toupper(TOS); +} + +void +lower_case(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "lcc"); + TOS = tolower(TOS); +} + +void +pack_str(fcode_env_t *env) +{ + char *buf; + size_t len; + char *str; + + CHECK_DEPTH(env, 3, "pack"); + buf = (char *)POP(DS); + len = (size_t)POP(DS); + str = (char *)TOS; + TOS = (fstack_t)buf; + *buf++ = (uchar_t)len; + strncpy(buf, str, (len&0xff)); +} + +void +count_str(fcode_env_t *env) +{ + uchar_t *len; + + CHECK_DEPTH(env, 1, "count"); + len = (uchar_t *)TOS; + TOS += 1; + PUSH(DS, *len); +} + +void +to_body(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, ">body"); + TOS = (fstack_t)(((acf_t)TOS)+1); +} + +void +to_acf(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "body>"); + TOS = (fstack_t)(((acf_t)TOS)-1); +} + +/* + * 'unloop' Fcode implementation, drop 3 loop ctrl elements off return stack. + */ +static void +unloop(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 3, "unloop"); + RS -= 3; +} + +/* + * 'um*' Fcode implementation. + */ +static void +um_multiply(fcode_env_t *env) +{ + ufstack_t u1, u2; + dforth_t d; + + CHECK_DEPTH(env, 2, "um*"); + u1 = POP(DS); + u2 = POP(DS); + d = u1 * u2; + push_double(env, d); +} + +/* + * um/mod (d.lo d.hi u -- urem uquot) + */ +static void +um_slash_mod(fcode_env_t *env) +{ + u_dforth_t d; + uint32_t u, urem, uquot; + + CHECK_DEPTH(env, 3, "um/mod"); + u = (uint32_t)POP(DS); + d = pop_double(env); + urem = d % u; + uquot = d / u; + PUSH(DS, urem); + PUSH(DS, uquot); +} + +/* + * d+ (d1.lo d1.hi d2.lo d2.hi -- dsum.lo dsum.hi) + */ +static void +d_plus(fcode_env_t *env) +{ + dforth_t d1, d2; + + CHECK_DEPTH(env, 4, "d+"); + d2 = pop_double(env); + d1 = pop_double(env); + d1 += d2; + push_double(env, d1); +} + +/* + * d- (d1.lo d1.hi d2.lo d2.hi -- ddif.lo ddif.hi) + */ +static void +d_minus(fcode_env_t *env) +{ + dforth_t d1, d2; + + CHECK_DEPTH(env, 4, "d-"); + d2 = pop_double(env); + d1 = pop_double(env); + d1 -= d2; + push_double(env, d1); +} + +void +set_here(fcode_env_t *env, uchar_t *new_here, char *where) +{ + if (new_here < HERE) { + if (strcmp(where, "temporary_execute")) { + /* + * Other than temporary_execute, no one should set + * here backwards. + */ + log_message(MSG_WARN, "Warning: set_here(%s) back: old:" + " %p new: %p\n", where, HERE, new_here); + } + } + if (new_here >= env->base + dict_size) + forth_abort(env, "Here (%p) set past dictionary end (%p)", + new_here, env->base + dict_size); + HERE = new_here; +} + +static void +unaligned_store(fcode_env_t *env) +{ + extern void unaligned_xstore(fcode_env_t *); + + if (sizeof (fstack_t) == sizeof (lforth_t)) + unaligned_lstore(env); + else + unaligned_xstore(env); +} + +static void +unaligned_fetch(fcode_env_t *env) +{ + extern void unaligned_xfetch(fcode_env_t *); + + if (sizeof (fstack_t) == sizeof (lforth_t)) + unaligned_lfetch(env); + else + unaligned_xfetch(env); +} + +void +comma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, ","); + DEBUGF(COMMA, dump_comma(env, ",")); + PUSH(DS, (fstack_t)HERE); + unaligned_store(env); + set_here(env, HERE + sizeof (fstack_t), "comma"); +} + +void +lcomma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "l,"); + DEBUGF(COMMA, dump_comma(env, "l,")); + PUSH(DS, (fstack_t)HERE); + unaligned_lstore(env); + set_here(env, HERE + sizeof (u_lforth_t), "lcomma"); +} + +void +wcomma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "w,"); + DEBUGF(COMMA, dump_comma(env, "w,")); + PUSH(DS, (fstack_t)HERE); + unaligned_wstore(env); + set_here(env, HERE + sizeof (u_wforth_t), "wcomma"); +} + +void +ccomma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "c,"); + DEBUGF(COMMA, dump_comma(env, "c,")); + PUSH(DS, (fstack_t)HERE); + cstore(env); + set_here(env, HERE + sizeof (uchar_t), "ccomma"); +} + +void +token_roundup(fcode_env_t *env, char *where) +{ + if ((((token_t)HERE) & (sizeof (token_t) - 1)) != 0) { + set_here(env, (uchar_t *)TOKEN_ROUNDUP(HERE), where); + } +} + +void +compile_comma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "compile,"); + DEBUGF(COMMA, dump_comma(env, "compile,")); + token_roundup(env, "compile,"); + PUSH(DS, (fstack_t)HERE); + unaligned_store(env); + set_here(env, HERE + sizeof (fstack_t), "compile,"); +} + +void +unaligned_lfetch(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 1, "unaligned-l@"); + addr = POP(DS); + for (i = 0; i < sizeof (lforth_t); i++, addr++) { + PUSH(DS, addr); + cfetch(env); + } + bljoin(env); + lbflip(env); +} + +void +unaligned_lstore(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 2, "unaligned-l!"); + addr = POP(DS); + lbsplit(env); + for (i = 0; i < sizeof (lforth_t); i++, addr++) { + PUSH(DS, addr); + cstore(env); + } +} + +void +unaligned_wfetch(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 1, "unaligned-w@"); + addr = POP(DS); + for (i = 0; i < sizeof (wforth_t); i++, addr++) { + PUSH(DS, addr); + cfetch(env); + } + bwjoin(env); + wbflip(env); +} + +void +unaligned_wstore(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 2, "unaligned-w!"); + addr = POP(DS); + wbsplit(env); + for (i = 0; i < sizeof (wforth_t); i++, addr++) { + PUSH(DS, addr); + cstore(env); + } +} + +/* + * 'lbflips' Fcode implementation. + */ +static void +lbflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "lbflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (lforth_t), + addr += sizeof (lforth_t)) { + PUSH(DS, addr); + unaligned_lfetch(env); + lbflip(env); + PUSH(DS, addr); + unaligned_lstore(env); + } +} + +/* + * 'wbflips' Fcode implementation. + */ +static void +wbflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "wbflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (wforth_t), + addr += sizeof (wforth_t)) { + PUSH(DS, addr); + unaligned_wfetch(env); + wbflip(env); + PUSH(DS, addr); + unaligned_wstore(env); + } +} + +/* + * 'lwflips' Fcode implementation. + */ +static void +lwflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "lwflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (lforth_t), + addr += sizeof (lforth_t)) { + PUSH(DS, addr); + unaligned_lfetch(env); + lwflip(env); + PUSH(DS, addr); + unaligned_lstore(env); + } +} + +void +base(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&env->num_base); +} + +void +dot_s(fcode_env_t *env) +{ + output_data_stack(env, MSG_INFO); +} + +void +state(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&env->state); +} + +int +is_digit(char digit, int num_base, fstack_t *dptr) +{ + int error = 0; + char base; + + if (num_base < 10) { + base = '0' + (num_base-1); + } else { + base = 'a' + (num_base - 10); + } + + *dptr = 0; + if (digit > '9') digit |= 0x20; + if (((digit < '0') || (digit > base)) || + ((digit > '9') && (digit < 'a') && (num_base > 10))) + error = 1; + else { + if (digit <= '9') + digit -= '0'; + else + digit = digit - 'a' + 10; + *dptr = digit; + } + return (error); +} + +void +dollar_number(fcode_env_t *env) +{ + char *buf; + fstack_t value; + int len, sign = 1, error = 0; + + CHECK_DEPTH(env, 2, "$number"); + buf = pop_a_string(env, &len); + if (*buf == '-') { + sign = -1; + buf++; + len--; + } + value = 0; + while (len-- && !error) { + fstack_t digit; + + if (*buf == '.') { + buf++; + continue; + } + value *= env->num_base; + error = is_digit(*buf++, env->num_base, &digit); + value += digit; + } + if (error) { + PUSH(DS, -1); + } else { + value *= sign; + PUSH(DS, value); + PUSH(DS, 0); + } +} + +void +digit(fcode_env_t *env) +{ + fstack_t base; + fstack_t value; + + CHECK_DEPTH(env, 2, "digit"); + base = POP(DS); + if (is_digit(TOS, base, &value)) + PUSH(DS, 0); + else { + TOS = value; + PUSH(DS, -1); + } +} + +void +space(fcode_env_t *env) +{ + PUSH(DS, ' '); +} + +void +backspace(fcode_env_t *env) +{ + PUSH(DS, '\b'); +} + +void +bell(fcode_env_t *env) +{ + PUSH(DS, '\a'); +} + +void +fc_bounds(fcode_env_t *env) +{ + fstack_t lo, hi; + + CHECK_DEPTH(env, 2, "bounds"); + lo = DS[-1]; + hi = TOS; + DS[-1] = lo+hi; + TOS = lo; +} + +void +here(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)HERE); +} + +void +aligned(fcode_env_t *env) +{ + ufstack_t a; + + CHECK_DEPTH(env, 1, "aligned"); + a = (TOS & (sizeof (lforth_t) - 1)); + if (a) + TOS += (sizeof (lforth_t) - a); +} + +void +instance(fcode_env_t *env) +{ + env->instance_mode |= 1; +} + +void +semi(fcode_env_t *env) +{ + + env->state &= ~1; + COMPILE_TOKEN(&semi_ptr); + + /* + * check if we need to supress expose action; + * If so this is an internal word and has no link field + * or it is a temporary compile + */ + + if (env->state == 0) { + expose_acf(env, "<semi>"); + } + if (env->state & 8) { + env->state ^= 8; + } +} + +void +do_create(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)WA); +} + +void +drop(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "drop"); + (void) POP(DS); +} + +void +f_dup(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 1, "dup"); + d = TOS; + PUSH(DS, d); +} + +void +over(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "over"); + d = DS[-1]; + PUSH(DS, d); +} + +void +swap(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "swap"); + d = DS[-1]; + DS[-1] = DS[0]; + DS[0] = d; +} + + +void +rot(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 3, "rot"); + d = DS[-2]; + DS[-2] = DS[-1]; + DS[-1] = TOS; + TOS = d; +} + +void +minus_rot(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 3, "-rot"); + d = TOS; + TOS = DS[-1]; + DS[-1] = DS[-2]; + DS[-2] = d; +} + +void +tuck(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "tuck"); + d = TOS; + swap(env); + PUSH(DS, d); +} + +void +nip(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "nip"); + swap(env); + drop(env); +} + +void +qdup(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 1, "?dup"); + d = TOS; + if (d) + PUSH(DS, d); +} + +void +depth(fcode_env_t *env) +{ + fstack_t d; + + d = DS - env->ds0; + PUSH(DS, d); +} + +void +pick(fcode_env_t *env) +{ + fstack_t p; + + CHECK_DEPTH(env, 1, "pick"); + p = POP(DS); + if (p < 0 || p >= (env->ds - env->ds0)) + forth_abort(env, "pick: invalid pick value: %d\n", (int)p); + p = DS[-p]; + PUSH(DS, p); +} + +void +roll(fcode_env_t *env) +{ + fstack_t d, r; + + CHECK_DEPTH(env, 1, "roll"); + r = POP(DS); + if (r <= 0 || r >= (env->ds - env->ds0)) + forth_abort(env, "roll: invalid roll value: %d\n", (int)r); + + d = DS[-r]; + while (r) { + DS[-r] = DS[ -(r-1) ]; + r--; + } + TOS = d; +} + +void +two_drop(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "2drop"); + DS -= 2; +} + +void +two_dup(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "2dup"); + DS[1] = DS[-1]; + DS[2] = TOS; + DS += 2; +} + +void +two_over(fcode_env_t *env) +{ + fstack_t a, b; + + CHECK_DEPTH(env, 4, "2over"); + a = DS[-3]; + b = DS[-2]; + PUSH(DS, a); + PUSH(DS, b); +} + +void +two_swap(fcode_env_t *env) +{ + fstack_t a, b; + + CHECK_DEPTH(env, 4, "2swap"); + a = DS[-3]; + b = DS[-2]; + DS[-3] = DS[-1]; + DS[-2] = TOS; + DS[-1] = a; + TOS = b; +} + +void +two_rot(fcode_env_t *env) +{ + fstack_t a, b; + + CHECK_DEPTH(env, 6, "2rot"); + a = DS[-5]; + b = DS[-4]; + DS[-5] = DS[-3]; + DS[-4] = DS[-2]; + DS[-3] = DS[-1]; + DS[-2] = TOS; + DS[-1] = a; + TOS = b; +} + +void +two_slash(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "2/"); + TOS = TOS >> 1; +} + +void +utwo_slash(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "u2/"); + TOS = (ufstack_t)((ufstack_t)TOS) >> 1; +} + +void +two_times(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "2*"); + TOS = (ufstack_t)((ufstack_t)TOS) << 1; +} + +void +slash_c(fcode_env_t *env) +{ + PUSH(DS, sizeof (char)); +} + +void +slash_w(fcode_env_t *env) +{ + PUSH(DS, sizeof (wforth_t)); +} + +void +slash_l(fcode_env_t *env) +{ + PUSH(DS, sizeof (lforth_t)); +} + +void +slash_n(fcode_env_t *env) +{ + PUSH(DS, sizeof (fstack_t)); +} + +void +ca_plus(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "ca+"); + d = POP(DS); + TOS += d * sizeof (char); +} + +void +wa_plus(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "wa+"); + d = POP(DS); + TOS += d * sizeof (wforth_t); +} + +void +la_plus(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "la+"); + d = POP(DS); + TOS += d * sizeof (lforth_t); +} + +void +na_plus(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "na+"); + d = POP(DS); + TOS += d * sizeof (fstack_t); +} + +void +char_plus(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "char+"); + TOS += sizeof (char); +} + +void +wa1_plus(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "wa1+"); + TOS += sizeof (wforth_t); +} + +void +la1_plus(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "la1+"); + TOS += sizeof (lforth_t); +} + +void +cell_plus(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "cell+"); + TOS += sizeof (fstack_t); +} + +void +do_chars(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "chars"); +} + +void +slash_w_times(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "/w*"); + TOS *= sizeof (wforth_t); +} + +void +slash_l_times(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "/l*"); + TOS *= sizeof (lforth_t); +} + +void +cells(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "cells"); + TOS *= sizeof (fstack_t); +} + +void +do_on(fcode_env_t *env) +{ + variable_t *d; + + CHECK_DEPTH(env, 1, "on"); + d = (variable_t *)POP(DS); + *d = -1; +} + +void +do_off(fcode_env_t *env) +{ + variable_t *d; + + CHECK_DEPTH(env, 1, "off"); + d = (variable_t *)POP(DS); + *d = 0; +} + +void +fetch(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "@"); + TOS = *((variable_t *)TOS); +} + +void +lfetch(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "l@"); + TOS = *((lforth_t *)TOS); +} + +void +wfetch(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "w@"); + TOS = *((wforth_t *)TOS); +} + +void +swfetch(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "<w@"); + TOS = *((s_wforth_t *)TOS); +} + +void +cfetch(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "c@"); + TOS = *((uchar_t *)TOS); +} + +void +store(fcode_env_t *env) +{ + variable_t *dptr; + + CHECK_DEPTH(env, 2, "!"); + dptr = (variable_t *)POP(DS); + *dptr = POP(DS); +} + +void +addstore(fcode_env_t *env) +{ + variable_t *dptr; + + CHECK_DEPTH(env, 2, "+!"); + dptr = (variable_t *)POP(DS); + *dptr = POP(DS) + *dptr; +} + +void +lstore(fcode_env_t *env) +{ + lforth_t *dptr; + + CHECK_DEPTH(env, 2, "l!"); + dptr = (lforth_t *)POP(DS); + *dptr = (lforth_t)POP(DS); +} + +void +wstore(fcode_env_t *env) +{ + wforth_t *dptr; + + CHECK_DEPTH(env, 2, "w!"); + dptr = (wforth_t *)POP(DS); + *dptr = (wforth_t)POP(DS); +} + +void +cstore(fcode_env_t *env) +{ + uchar_t *dptr; + + CHECK_DEPTH(env, 2, "c!"); + dptr = (uchar_t *)POP(DS); + *dptr = (uchar_t)POP(DS); +} + +void +two_fetch(fcode_env_t *env) +{ + variable_t *d; + + CHECK_DEPTH(env, 1, "2@"); + d = (variable_t *)POP(DS); + PUSH(DS, (fstack_t)(d + 1)); + unaligned_fetch(env); + PUSH(DS, (fstack_t)d); + unaligned_fetch(env); +} + +void +two_store(fcode_env_t *env) +{ + variable_t *d; + + CHECK_DEPTH(env, 3, "2!"); + d = (variable_t *)POP(DS); + PUSH(DS, (fstack_t)d); + unaligned_store(env); + PUSH(DS, (fstack_t)(d + 1)); + unaligned_store(env); +} + +/* + * 'move' Fcode reimplemented in fcdriver to check for mapped addresses. + */ +void +fc_move(fcode_env_t *env) +{ + void *dest, *src; + size_t len; + + CHECK_DEPTH(env, 3, "move"); + len = (size_t)POP(DS); + dest = (void *)POP(DS); + src = (void *)POP(DS); + + memmove(dest, src, len); +} + +void +fc_fill(fcode_env_t *env) +{ + void *dest; + uchar_t val; + size_t len; + + CHECK_DEPTH(env, 3, "fill"); + val = (uchar_t)POP(DS); + len = (size_t)POP(DS); + dest = (void *)POP(DS); + memset(dest, val, len); +} + +void +fc_comp(fcode_env_t *env) +{ + char *str1, *str2; + size_t len; + int res; + + CHECK_DEPTH(env, 3, "comp"); + len = (size_t)POP(DS); + str1 = (char *)POP(DS); + str2 = (char *)POP(DS); + res = memcmp(str2, str1, len); + if (res > 0) + res = 1; + else if (res < 0) + res = -1; + PUSH(DS, res); +} + +void +set_temporary_compile(fcode_env_t *env) +{ + if (!env->state) { + token_roundup(env, "set_temporary_compile"); + PUSH(RS, (fstack_t)HERE); + env->state = 3; + COMPILE_TOKEN(&do_colon); + } +} + +void +bmark(fcode_env_t *env) +{ + set_temporary_compile(env); + env->level++; + PUSH(DS, (fstack_t)HERE); +} + +void +temporary_execute(fcode_env_t *env) +{ + uchar_t *saved_here; + + if ((env->level == 0) && (env->state & 2)) { + fstack_t d = POP(RS); + + semi(env); + + saved_here = HERE; + /* execute the temporary definition */ + env->state &= ~2; + PUSH(DS, d); + execute(env); + + /* now wind the dictionary back! */ + if (saved_here != HERE) { + debug_msg(DEBUG_COMMA, "Ignoring set_here in" + " temporary_execute\n"); + } else + set_here(env, (uchar_t *)d, "temporary_execute"); + } +} + +void +bresolve(fcode_env_t *env) +{ + token_t *prev = (token_t *)POP(DS); + + env->level--; + *prev = (token_t)HERE; + temporary_execute(env); +} + +#define BRANCH_IP(ipp) ((token_t *)(*((token_t *)(ipp)))) + +void +do_bbranch(fcode_env_t *env) +{ + IP = BRANCH_IP(IP); +} + +void +do_bqbranch(fcode_env_t *env) +{ + fstack_t flag; + + CHECK_DEPTH(env, 1, "b?branch"); + flag = POP(DS); + if (flag) { + IP++; + } else { + IP = BRANCH_IP(IP); + } +} + +void +do_bofbranch(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "bofbranch"); + d = POP(DS); + if (d == TOS) { + (void) POP(DS); + IP++; + } else { + IP = BRANCH_IP(IP); + } +} + +void +do_bleave(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 3, "do_bleave"); + (void) POP(RS); + (void) POP(RS); + IP = (token_t *)POP(RS); +} + +void +loop_inc(fcode_env_t *env, fstack_t inc) +{ + ufstack_t a; + + CHECK_RETURN_DEPTH(env, 2, "loop_inc"); + + /* + * Note: end condition is when the sign bit of R[0] changes. + */ + a = RS[0]; + RS[0] += inc; + if (((a ^ RS[0]) & SIGN_BIT) == 0) { + IP = BRANCH_IP(IP); + } else { + do_bleave(env); + } +} + +void +do_bloop(fcode_env_t *env) +{ + loop_inc(env, 1); +} + +void +do_bploop(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 1, "+loop"); + d = POP(DS); + loop_inc(env, d); +} + +void +loop_common(fcode_env_t *env, fstack_t ptr) +{ + short offset = get_short(env); + + COMPILE_TOKEN(ptr); + env->level--; + compile_comma(env); + bresolve(env); +} + +void +bloop(fcode_env_t *env) +{ + loop_common(env, (fstack_t)&do_loop_ptr); +} + +void +bplusloop(fcode_env_t *env) +{ + loop_common(env, (fstack_t)&do_ploop_ptr); +} + +void +common_do(fcode_env_t *env, fstack_t endpt, fstack_t start, fstack_t limit) +{ + ufstack_t i, l; + + /* + * Same computation as OBP, sets up so that loop_inc will terminate + * when the sign bit of RS[0] changes. + */ + i = (start - limit) - SIGN_BIT; + l = limit + SIGN_BIT; + PUSH(RS, endpt); + PUSH(RS, l); + PUSH(RS, i); +} + +void +do_bdo(fcode_env_t *env) +{ + fstack_t lo, hi; + fstack_t endpt; + + CHECK_DEPTH(env, 2, "bdo"); + endpt = (fstack_t)BRANCH_IP(IP); + IP++; + lo = POP(DS); + hi = POP(DS); + common_do(env, endpt, lo, hi); +} + +void +do_bqdo(fcode_env_t *env) +{ + fstack_t lo, hi; + fstack_t endpt; + + CHECK_DEPTH(env, 2, "b?do"); + endpt = (fstack_t)BRANCH_IP(IP); + IP++; + lo = POP(DS); + hi = POP(DS); + if (lo == hi) { + IP = (token_t *)endpt; + } else { + common_do(env, endpt, lo, hi); + } +} + +void +compile_do_common(fcode_env_t *env, fstack_t ptr) +{ + set_temporary_compile(env); + COMPILE_TOKEN(ptr); + bmark(env); + COMPILE_TOKEN(0); + bmark(env); +} + +void +bdo(fcode_env_t *env) +{ + short offset = (short)get_short(env); + compile_do_common(env, (fstack_t)&do_bdo_ptr); +} + +void +bqdo(fcode_env_t *env) +{ + short offset = (short)get_short(env); + compile_do_common(env, (fstack_t)&do_bqdo_ptr); +} + +void +loop_i(fcode_env_t *env) +{ + fstack_t i; + + CHECK_RETURN_DEPTH(env, 2, "i"); + i = RS[0] + RS[-1]; + PUSH(DS, i); +} + +void +loop_j(fcode_env_t *env) +{ + fstack_t j; + + CHECK_RETURN_DEPTH(env, 5, "j"); + j = RS[-3] + RS[-4]; + PUSH(DS, j); +} + +void +bleave(fcode_env_t *env) +{ + + if (env->state) { + COMPILE_TOKEN(&do_leave_ptr); + } +} + +void +push_string(fcode_env_t *env, char *str, int len) +{ +#define NSTRINGS 16 + static int string_count = 0; + static int buflen[NSTRINGS]; + static char *buffer[NSTRINGS]; + char *dest; + + if (!len) { + PUSH(DS, 0); + PUSH(DS, 0); + return; + } + if (len != buflen[string_count]) { + if (buffer[string_count]) FREE(buffer[string_count]); + buffer[ string_count ] = (char *)MALLOC(len+1); + buflen[ string_count ] = len; + } + dest = buffer[ string_count++ ]; + string_count = string_count%NSTRINGS; + memcpy(dest, str, len); + *(dest+len) = 0; + PUSH(DS, (fstack_t)dest); + PUSH(DS, len); +#undef NSTRINGS +} + +void +parse_word(fcode_env_t *env) +{ + int len = 0; + char *next, *dest, *here = ""; + + if (env->input) { + here = env->input->scanptr; + while (*here == env->input->separator) here++; + next = strchr(here, env->input->separator); + if (next) { + len = next - here; + while (*next == env->input->separator) next++; + } else { + len = strlen(here); + next = here + len; + } + env->input->scanptr = next; + } + push_string(env, here, len); +} + +void +install_does(fcode_env_t *env) +{ + token_t *dptr; + + dptr = (token_t *)LINK_TO_ACF(env->lastlink); + + log_message(MSG_WARN, "install_does: Last acf at: %p\n", (void *)dptr); + + *dptr = ((token_t)(IP+1)) | 1; +} + +void +does(fcode_env_t *env) +{ + token_t *dptr; + + token_roundup(env, "does"); + + if (env->state) { + COMPILE_TOKEN(&does_ptr); + COMPILE_TOKEN(&semi_ptr); + } else { + dptr = (token_t *)LINK_TO_ACF(env->lastlink); + log_message(MSG_WARN, "does: Last acf at: %p\n", (void *)dptr); + *dptr = ((token_t)(HERE)) | 1; + env->state |= 1; + } + COMPILE_TOKEN(&do_colon); +} + +void +do_current(fcode_env_t *env) +{ + debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CURRENT\n"); + PUSH(DS, (fstack_t)&env->current); +} + +void +do_context(fcode_env_t *env) +{ + debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CONTEXT\n"); + PUSH(DS, (fstack_t)&CONTEXT); +} + +void +do_definitions(fcode_env_t *env) +{ + env->current = CONTEXT; + debug_msg(DEBUG_CONTEXT, "CONTEXT:definitions: %d/%p/%p\n", + env->order_depth, CONTEXT, env->current); +} + +void +make_header(fcode_env_t *env, int flags) +{ + int len; + char *name; + + name = parse_a_string(env, &len); + header(env, name, len, flags); +} + +void +do_creator(fcode_env_t *env) +{ + make_header(env, 0); + COMPILE_TOKEN(&do_create); + expose_acf(env, "<create>"); +} + +void +create(fcode_env_t *env) +{ + if (env->state) { + COMPILE_TOKEN(&create_ptr); + } else + do_creator(env); +} + +void +colon(fcode_env_t *env) +{ + make_header(env, 0); + env->state |= 1; + COMPILE_TOKEN(&do_colon); +} + +void +recursive(fcode_env_t *env) +{ + expose_acf(env, "<recursive>"); +} + +void +compile_string(fcode_env_t *env) +{ + int len; + uchar_t *str, *tostr; + + COMPILE_TOKEN("e_ptr); + len = POP(DS); + str = (uchar_t *)POP(DS); + tostr = HERE; + *tostr++ = len; + while (len--) + *tostr++ = *str++; + *tostr++ = '\0'; + set_here(env, tostr, "compile_string"); + token_roundup(env, "compile_string"); +} + +void +run_quote(fcode_env_t *env) +{ + char osep; + + osep = env->input->separator; + env->input->separator = '"'; + parse_word(env); + env->input->separator = osep; + + if (env->state) { + compile_string(env); + } +} + +void +does_vocabulary(fcode_env_t *env) +{ + CONTEXT = WA; + debug_msg(DEBUG_CONTEXT, "CONTEXT:vocabulary: %d/%p/%p\n", + env->order_depth, CONTEXT, env->current); +} + +void +do_vocab(fcode_env_t *env) +{ + make_header(env, 0); + COMPILE_TOKEN(does_vocabulary); + PUSH(DS, 0); + compile_comma(env); + expose_acf(env, "<vocabulary>"); +} + +void +do_forth(fcode_env_t *env) +{ + CONTEXT = (token_t *)(&env->forth_voc_link); + debug_msg(DEBUG_CONTEXT, "CONTEXT:forth: %d/%p/%p\n", + env->order_depth, CONTEXT, env->current); +} + +acf_t +voc_find(fcode_env_t *env) +{ + token_t *voc; + token_t *dptr; + char *find_name, *name; + + voc = (token_t *)POP(DS); + find_name = pop_a_string(env, NULL); + + for (dptr = (token_t *)(*voc); dptr; dptr = (token_t *)(*dptr)) { + if ((name = get_name(dptr)) == NULL) + continue; + if (strcmp(find_name, name) == 0) { + debug_msg(DEBUG_VOC_FIND, "%s -> %p\n", find_name, + LINK_TO_ACF(dptr)); + return (LINK_TO_ACF(dptr)); + } + } + debug_msg(DEBUG_VOC_FIND, "%s not found\n", find_name); + return (NULL); +} + +void +dollar_find(fcode_env_t *env) +{ + acf_t acf = NULL; + int i; + + CHECK_DEPTH(env, 2, "$find"); + for (i = env->order_depth; i >= 0 && env->order[i] && !acf; i--) { + two_dup(env); + PUSH(DS, (fstack_t)env->order[i]); + acf = voc_find(env); + } + if (acf) { + two_drop(env); + PUSH(DS, (fstack_t)acf); + PUSH(DS, TRUE); + } else + PUSH(DS, FALSE); +} + +void +interpret(fcode_env_t *env) +{ + char *name; + + parse_word(env); + while (TOS) { + two_dup(env); + dollar_find(env); + if (TOS) { + flag_t *flags; + + drop(env); + nip(env); + nip(env); + flags = LINK_TO_FLAGS(ACF_TO_LINK(TOS)); + + if ((env->state) && + ((*flags & IMMEDIATE) == 0)) { + /* Compile in references */ + compile_comma(env); + } else { + execute(env); + } + } else { + int bad; + drop(env); + dollar_number(env); + bad = POP(DS); + if (bad) { + two_dup(env); + name = pop_a_string(env, NULL); + log_message(MSG_INFO, "%s?\n", name); + break; + } else { + nip(env); + nip(env); + literal(env); + } + } + parse_word(env); + } + two_drop(env); +} + +void +evaluate(fcode_env_t *env) +{ + input_typ *old_input = env->input; + input_typ *eval_bufp = MALLOC(sizeof (input_typ)); + + CHECK_DEPTH(env, 2, "evaluate"); + eval_bufp->separator = ' '; + eval_bufp->maxlen = POP(DS); + eval_bufp->buffer = (char *)POP(DS); + eval_bufp->scanptr = eval_bufp->buffer; + env->input = eval_bufp; + interpret(env); + FREE(eval_bufp); + env->input = old_input; +} + +void +make_common_access(fcode_env_t *env, + char *name, int len, + int ncells, + int instance_mode, + void (*acf_instance)(fcode_env_t *env), + void (*acf_static)(fcode_env_t *env), + void (*set_action)(fcode_env_t *env, int)) +{ + if (instance_mode && !MYSELF) { + system_message(env, "No instance context"); + } + + debug_msg(DEBUG_ACTIONS, "make_common_access:%s '%s', %d\n", + (instance_mode ? "instance" : ""), + (name ? name : ""), ncells); + + if (len) + header(env, name, len, 0); + if (instance_mode) { + token_t *dptr; + int offset; + + COMPILE_TOKEN(acf_instance); + dptr = alloc_instance_data(env, INIT_DATA, ncells, &offset); + debug_msg(DEBUG_ACTIONS, "Data: %p, offset %d\n", (char *)dptr, + offset); + PUSH(DS, offset); + compile_comma(env); + while (ncells--) + *dptr++ = MYSELF->data[INIT_DATA][offset++] = POP(DS); + env->instance_mode = 0; + } else { + COMPILE_TOKEN(acf_static); + while (ncells--) + compile_comma(env); + } + expose_acf(env, name); + if (set_action) + set_action(env, instance_mode); +} + +void +do_constant(fcode_env_t *env) +{ + PUSH(DS, (variable_t)(*WA)); +} + +void +do_crash(fcode_env_t *env) +{ + forth_abort(env, "Unitialized defer"); +} + +/* + * 'behavior' Fcode retrieve execution behavior for a defer word. + */ +static void +behavior(fcode_env_t *env) +{ + acf_t defer_xt; + token_t token; + acf_t contents_xt; + + CHECK_DEPTH(env, 1, "behavior"); + defer_xt = (acf_t)POP(DS); + token = *defer_xt; + contents_xt = (token_t *)(token & ~1); + if ((token & 1) == 0 || *contents_xt != (token_t)&do_default_action) + forth_abort(env, "behavior: bad xt: %p indir: %x/%p\n", + defer_xt, token & 1, *contents_xt); + defer_xt++; + PUSH(DS, *((variable_t *)defer_xt)); +} + +void +fc_abort(fcode_env_t *env, char *type) +{ + forth_abort(env, "%s Fcode '%s' Executed", type, + acf_to_name(env, WA - 1)); +} + +void +f_abort(fcode_env_t *env) +{ + fc_abort(env, "Abort"); +} + +/* + * Fcodes chosen not to support. + */ +void +fc_unimplemented(fcode_env_t *env) +{ + fc_abort(env, "Unimplemented"); +} + +/* + * Fcodes that are Obsolete per P1275-1994. + */ +void +fc_obsolete(fcode_env_t *env) +{ + fc_abort(env, "Obsolete"); +} + +/* + * Fcodes that are Historical per P1275-1994 + */ +void +fc_historical(fcode_env_t *env) +{ + fc_abort(env, "Historical"); +} + +void +catch(fcode_env_t *env) +{ + error_frame *new; + + CHECK_DEPTH(env, 1, "catch"); + new = MALLOC(sizeof (error_frame)); + new->ds = DS-1; + new->rs = RS; + new->myself = MYSELF; + new->next = env->catch_frame; + new->code = 0; + env->catch_frame = new; + execute(env); + PUSH(DS, new->code); + env->catch_frame = new->next; + FREE(new); +} + +void +throw_from_fclib(fcode_env_t *env, fstack_t errcode, char *fmt, ...) +{ + error_frame *efp; + va_list ap; + char msg[256]; + + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + + if (errcode) { + + env->last_error = errcode; + + /* + * No catch frame set => fatal error + */ + efp = env->catch_frame; + if (!efp) + forth_abort(env, "%s: No catch frame", msg); + + debug_msg(DEBUG_TRACING, "throw_from_fclib: throw: %s\n", msg); + + /* + * Setting IP=0 will force the unwinding of the calls + * (see execute) which is how we will return (eventually) + * to the test in catch that follows 'execute'. + */ + DS = efp->ds; + RS = efp->rs; + MYSELF = efp->myself; + IP = 0; + efp->code = errcode; + } +} + +void +throw(fcode_env_t *env) +{ + fstack_t t; + + CHECK_DEPTH(env, 1, "throw"); + t = POP(DS); + if (t >= -20 && t <= 20) + throw_from_fclib(env, t, "throw Fcode errcode: 0x%x", (int)t); + else { + if (t) + log_message(MSG_ERROR, "throw: errcode: 0x%x\n", + (int)t); + throw_from_fclib(env, t, "throw Fcode err: %s", (char *)t); + } +} + +void +tick_literal(fcode_env_t *env) +{ + if (env->state) { + COMPILE_TOKEN(&tlit_ptr); + compile_comma(env); + } +} + +void +do_tick(fcode_env_t *env) +{ + parse_word(env); + dollar_find(env); + invert(env); + throw(env); + tick_literal(env); +} + +void +bracket_tick(fcode_env_t *env) +{ + do_tick(env); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + NOTICE; + ASSERT(env); + + ANSI(0x019, 0, "i", loop_i); + ANSI(0x01a, 0, "j", loop_j); + ANSI(0x01d, 0, "execute", execute); + ANSI(0x01e, 0, "+", add); + ANSI(0x01f, 0, "-", subtract); + ANSI(0x020, 0, "*", multiply); + ANSI(0x021, 0, "/", divide); + ANSI(0x022, 0, "mod", mod); + FORTH(0, "/mod", slash_mod); + ANSI(0x023, 0, "and", and); + ANSI(0x024, 0, "or", or); + ANSI(0x025, 0, "xor", xor); + ANSI(0x026, 0, "invert", invert); + ANSI(0x027, 0, "lshift", lshift); + ANSI(0x028, 0, "rshift", rshift); + ANSI(0x029, 0, ">>a", rshifta); + ANSI(0x02a, 0, "/mod", slash_mod); + ANSI(0x02b, 0, "u/mod", uslash_mod); + ANSI(0x02c, 0, "negate", negate); + ANSI(0x02d, 0, "abs", f_abs); + ANSI(0x02e, 0, "min", f_min); + ANSI(0x02f, 0, "max", f_max); + ANSI(0x030, 0, ">r", to_r); + ANSI(0x031, 0, "r>", from_r); + ANSI(0x032, 0, "r@", rfetch); + ANSI(0x033, 0, "exit", f_exit); + ANSI(0x034, 0, "0=", zero_equals); + ANSI(0x035, 0, "0<>", zero_not_equals); + ANSI(0x036, 0, "0<", zero_less); + ANSI(0x037, 0, "0<=", zero_less_equals); + ANSI(0x038, 0, "0>", zero_greater); + ANSI(0x039, 0, "0>=", zero_greater_equals); + ANSI(0x03a, 0, "<", less); + ANSI(0x03b, 0, ">", greater); + ANSI(0x03c, 0, "=", equals); + ANSI(0x03d, 0, "<>", not_equals); + ANSI(0x03e, 0, "u>", unsign_greater); + ANSI(0x03f, 0, "u<=", unsign_less_equals); + ANSI(0x040, 0, "u<", unsign_less); + ANSI(0x041, 0, "u>=", unsign_greater_equals); + ANSI(0x042, 0, ">=", greater_equals); + ANSI(0x043, 0, "<=", less_equals); + ANSI(0x044, 0, "between", between); + ANSI(0x045, 0, "within", within); + ANSI(0x046, 0, "drop", drop); + ANSI(0x047, 0, "dup", f_dup); + ANSI(0x048, 0, "over", over); + ANSI(0x049, 0, "swap", swap); + ANSI(0x04a, 0, "rot", rot); + ANSI(0x04b, 0, "-rot", minus_rot); + ANSI(0x04c, 0, "tuck", tuck); + ANSI(0x04d, 0, "nip", nip); + ANSI(0x04e, 0, "pick", pick); + ANSI(0x04f, 0, "roll", roll); + ANSI(0x050, 0, "?dup", qdup); + ANSI(0x051, 0, "depth", depth); + ANSI(0x052, 0, "2drop", two_drop); + ANSI(0x053, 0, "2dup", two_dup); + ANSI(0x054, 0, "2over", two_over); + ANSI(0x055, 0, "2swap", two_swap); + ANSI(0x056, 0, "2rot", two_rot); + ANSI(0x057, 0, "2/", two_slash); + ANSI(0x058, 0, "u2/", utwo_slash); + ANSI(0x059, 0, "2*", two_times); + ANSI(0x05a, 0, "/c", slash_c); + ANSI(0x05b, 0, "/w", slash_w); + ANSI(0x05c, 0, "/l", slash_l); + ANSI(0x05d, 0, "/n", slash_n); + ANSI(0x05e, 0, "ca+", ca_plus); + ANSI(0x05f, 0, "wa+", wa_plus); + ANSI(0x060, 0, "la+", la_plus); + ANSI(0x061, 0, "na+", na_plus); + ANSI(0x062, 0, "char+", char_plus); + ANSI(0x063, 0, "wa1+", wa1_plus); + ANSI(0x064, 0, "la1+", la1_plus); + ANSI(0x065, 0, "cell+", cell_plus); + ANSI(0x066, 0, "chars", do_chars); + ANSI(0x067, 0, "/w*", slash_w_times); + ANSI(0x068, 0, "/l*", slash_l_times); + ANSI(0x069, 0, "cells", cells); + ANSI(0x06a, 0, "on", do_on); + ANSI(0x06b, 0, "off", do_off); + ANSI(0x06c, 0, "+!", addstore); + ANSI(0x06d, 0, "@", fetch); + ANSI(0x06e, 0, "l@", lfetch); + ANSI(0x06f, 0, "w@", wfetch); + ANSI(0x070, 0, "<w@", swfetch); + ANSI(0x071, 0, "c@", cfetch); + ANSI(0x072, 0, "!", store); + ANSI(0x073, 0, "l!", lstore); + ANSI(0x074, 0, "w!", wstore); + ANSI(0x075, 0, "c!", cstore); + ANSI(0x076, 0, "2@", two_fetch); + ANSI(0x077, 0, "2!", two_store); + ANSI(0x078, 0, "move", fc_move); + ANSI(0x079, 0, "fill", fc_fill); + ANSI(0x07a, 0, "comp", fc_comp); + ANSI(0x07b, 0, "noop", noop); + ANSI(0x07c, 0, "lwsplit", lwsplit); + ANSI(0x07d, 0, "wljoin", wljoin); + ANSI(0x07e, 0, "lbsplit", lbsplit); + ANSI(0x07f, 0, "bljoin", bljoin); + ANSI(0x080, 0, "wbflip", wbflip); + ANSI(0x081, 0, "upc", upper_case); + ANSI(0x082, 0, "lcc", lower_case); + ANSI(0x083, 0, "pack", pack_str); + ANSI(0x084, 0, "count", count_str); + ANSI(0x085, 0, "body>", to_acf); + ANSI(0x086, 0, ">body", to_body); + + ANSI(0x089, 0, "unloop", unloop); + + ANSI(0x09f, 0, ".s", dot_s); + ANSI(0x0a0, 0, "base", base); + FCODE(0x0a1, 0, "convert", fc_historical); + ANSI(0x0a2, 0, "$number", dollar_number); + ANSI(0x0a3, 0, "digit", digit); + + ANSI(0x0a9, 0, "bl", space); + ANSI(0x0aa, 0, "bs", backspace); + ANSI(0x0ab, 0, "bell", bell); + ANSI(0x0ac, 0, "bounds", fc_bounds); + ANSI(0x0ad, 0, "here", here); + + ANSI(0x0af, 0, "wbsplit", wbsplit); + ANSI(0x0b0, 0, "bwjoin", bwjoin); + + P1275(0x0cb, 0, "$find", dollar_find); + + ANSI(0x0d0, 0, "c,", ccomma); + ANSI(0x0d1, 0, "w,", wcomma); + ANSI(0x0d2, 0, "l,", lcomma); + ANSI(0x0d3, 0, ",", comma); + ANSI(0x0d4, 0, "um*", um_multiply); + ANSI(0x0d5, 0, "um/mod", um_slash_mod); + + ANSI(0x0d8, 0, "d+", d_plus); + ANSI(0x0d9, 0, "d-", d_minus); + + ANSI(0x0dc, 0, "state", state); + ANSI(0x0de, 0, "behavior", behavior); + ANSI(0x0dd, 0, "compile,", compile_comma); + + ANSI(0x216, 0, "abort", f_abort); + ANSI(0x217, 0, "catch", catch); + ANSI(0x218, 0, "throw", throw); + + ANSI(0x226, 0, "lwflip", lwflip); + ANSI(0x227, 0, "lbflip", lbflip); + ANSI(0x228, 0, "lbflips", lbflips); + + ANSI(0x236, 0, "wbflips", wbflips); + ANSI(0x237, 0, "lwflips", lwflips); + + FORTH(0, "forth", do_forth); + FORTH(0, "current", do_current); + FORTH(0, "context", do_context); + FORTH(0, "definitions", do_definitions); + FORTH(0, "vocabulary", do_vocab); + FORTH(IMMEDIATE, ":", colon); + FORTH(IMMEDIATE, ";", semi); + FORTH(IMMEDIATE, "create", create); + FORTH(IMMEDIATE, "does>", does); + FORTH(IMMEDIATE, "recursive", recursive); + FORTH(0, "parse-word", parse_word); + FORTH(IMMEDIATE, "\"", run_quote); + FORTH(IMMEDIATE, "order", do_order); + FORTH(IMMEDIATE, "also", do_also); + FORTH(IMMEDIATE, "previous", do_previous); + FORTH(IMMEDIATE, "'", do_tick); + FORTH(IMMEDIATE, "[']", bracket_tick); + FORTH(0, "unaligned-l@", unaligned_lfetch); + FORTH(0, "unaligned-l!", unaligned_lstore); + FORTH(0, "unaligned-w@", unaligned_wfetch); + FORTH(0, "unaligned-w!", unaligned_wstore); +} diff --git a/usr/src/lib/efcode/engine/framebuffer.c b/usr/src/lib/efcode/engine/framebuffer.c new file mode 100644 index 0000000000..aaf3a44f53 --- /dev/null +++ b/usr/src/lib/efcode/engine/framebuffer.c @@ -0,0 +1,71 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <fcode/private.h> + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FCODE(0x11c, 0, "is-install", fc_unimplemented); + FCODE(0x11d, 0, "is-remove", fc_unimplemented); + FCODE(0x11e, 0, "is-selftest", fc_unimplemented); + + FCODE(0x121, 0, "display-status", fc_unimplemented); + + FCODE(0x150, 0, "#lines", fc_unimplemented); + FCODE(0x151, 0, "#columns", fc_unimplemented); + FCODE(0x152, 0, "line#", fc_unimplemented); + FCODE(0x153, 0, "column#", fc_unimplemented); + FCODE(0x154, 0, "inverse?", fc_unimplemented); + FCODE(0x155, 0, "inverse-screen?", fc_unimplemented); + FCODE(0x156, 0, "frame-buffer-busy?", fc_historical); + FCODE(0x157, 0, "draw-character", fc_unimplemented); + FCODE(0x158, 0, "reset-screen", fc_unimplemented); + FCODE(0x159, 0, "toggle-cursor", fc_unimplemented); + FCODE(0x15a, 0, "erase-screen", fc_unimplemented); + FCODE(0x15b, 0, "blink-screen", fc_unimplemented); + FCODE(0x15c, 0, "invert-screen", fc_unimplemented); + FCODE(0x15d, 0, "insert-characters", fc_unimplemented); + FCODE(0x15e, 0, "delete-characters", fc_unimplemented); + FCODE(0x15f, 0, "insert-lines", fc_unimplemented); + FCODE(0x160, 0, "delete-lines", fc_unimplemented); + FCODE(0x161, 0, "draw-logo", fc_unimplemented); + FCODE(0x162, 0, "frame-buffer-adr", fc_unimplemented); + FCODE(0x163, 0, "screen-height", fc_unimplemented); + FCODE(0x164, 0, "screen-width", fc_unimplemented); + FCODE(0x165, 0, "window-top", fc_unimplemented); + FCODE(0x166, 0, "window-left", fc_unimplemented); +} diff --git a/usr/src/lib/efcode/engine/init.c b/usr/src/lib/efcode/engine/init.c new file mode 100644 index 0000000000..128476cf4e --- /dev/null +++ b/usr/src/lib/efcode/engine/init.c @@ -0,0 +1,139 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +fcode_env_t *initial_env = 0; +int dict_size = 0x100000; /* 1Mb, hopefully big enough... */ +int stack_size = 0x200; + +void * +safe_malloc(size_t n, char *f, int l) +{ + void *p; + + p = malloc((size_t) n); +#if defined(__sparcv9) + /* + * For Ultrasparc, we must force addresses to be less than 4Gb, + * since Fcode assumes that addresses can be stored in 32 bits. + * To get around this would require turning all addresses into + * cookies, which is a lot of work. + */ + if (((uint64_t)p) >= 0x100000000) { + log_message(MSG_WARN, "Malloc returned address > 4Gb\n"); + } +#endif /* __sparcv9 */ + if (p) { + memset(p, 0, (size_t) n); + } else + log_message(MSG_ERROR, "%s:%d:Malloc(%llx) failed\n", f, l, + (uint64_t)n); + return (p); +} + +void * +safe_realloc(void *p, size_t n, char *f, int l) +{ + void *newp; + + if ((newp = safe_malloc(n, f, l)) == NULL) { + log_message(MSG_ERROR, "%s:%d:realloc(%p, %x) failed\n", f, l, + p, n); + safe_free(p, f, l); + return (NULL); + } + if (p) { + memcpy(newp, p, n); + safe_free(p, f, l); + } + return (newp); +} + +void +safe_free(void *p, char *f, int l) +{ + if (p) { + free(p); + } +} + +char * +safe_strdup(char *s, char *f, int l) +{ + char *p = strdup(s); + + return (p); +} + +#pragma init(_init) + +static void +_init(void) +{ + int i; + acf_t f_error_addr; + fcode_env_t *env; + + NOTICE; + + fcode_impl_count = 0; + env = MALLOC(sizeof (fcode_env_t)); + env->table = MALLOC((MAX_FCODE + 1) * sizeof (fcode_token)); + env->base = MALLOC(dict_size); + env->here = env->base; + env->ds = env->ds0 = MALLOC(stack_size * sizeof (fstack_t)); + env->rs = env->rs0 = MALLOC(stack_size * sizeof (fstack_t)); + env->order = MALLOC(MAX_ORDER * sizeof (token_t)); + env->input = MALLOC(sizeof (input_typ)); + env->num_base = 0x10; + + /* Setup the initial forth environment */ + do_forth(env); + do_definitions(env); + install_handlers(env); + + initial_env = env; + + /* + * Need to define this early because it is the default for + * all unimpl, FCODE functions + */ + P1275(0x0fc, IMMEDIATE, "ferror", f_error); + f_error_addr = LINK_TO_ACF(env->lastlink); + for (i = 0; i <= MAX_FCODE; i++) { + DEBUGF(ANY, env->table[i].usage = 0); + SET_TOKEN(i, IMMEDIATE, "ferror", f_error_addr); + } + fcode_impl_count = 0; +} diff --git a/usr/src/lib/efcode/engine/instance.c b/usr/src/lib/efcode/engine/instance.c new file mode 100644 index 0000000000..380d1d6297 --- /dev/null +++ b/usr/src/lib/efcode/engine/instance.c @@ -0,0 +1,117 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> + +#include <fcode/private.h> + +/* + * Return a pointer to the allocated instance data. + * If the data was initialised then return a pointer to the initialisation + * buffer otherwise return a pointer to the un-init data. + */ +token_t * +alloc_instance_data(fcode_env_t *env, int init, int n, int *offset) +{ + int ptr; + + *offset = ptr = MYSELF->device->data_size[init]; + MYSELF->device->data_size[init] += n; + if (init == INIT_DATA) + return (&MYSELF->device->init_data[ptr]); + else + return (&MYSELF->data[init][ptr]); +} + +token_t * +get_instance_address(fcode_env_t *env) +{ + int which; + token_t *ptr; + token_t offset; + + CHECK_DEPTH(env, 1, "get_instance_address"); + ptr = (token_t *) POP(DS); + offset = *ptr; + if (offset < 0) { + offset = -offset; + which = UINIT_DATA; + } else { + which = INIT_DATA; + } + return (&MYSELF->data[which][offset]); +} + +void +fetch_instance_data(fcode_env_t *env) +{ + token_t *ptr; + + CHECK_DEPTH(env, 1, "get_instance_data"); + ptr = get_instance_address(env); + PUSH(DS, *ptr); +} + +void +set_instance_data(fcode_env_t *env) +{ + token_t *ptr; + + CHECK_DEPTH(env, 2, "set_instance_data"); + ptr = get_instance_address(env); + *ptr = POP(DS); +} + +void +address_instance_data(fcode_env_t *env) +{ + token_t *ptr; + + CHECK_DEPTH(env, 1, "address_instance_data"); + ptr = get_instance_address(env); + PUSH(DS, (fstack_t) ptr); +} + +void +instance_variable(fcode_env_t *env) +{ + token_t *ptr; + + PUSH(DS, (fstack_t) WA); + ptr = get_instance_address(env); + PUSH(DS, (fstack_t) ptr); +} + +void +idefer_exec(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "idefer_exec"); + fetch_instance_data(env); + execute(env); +} diff --git a/usr/src/lib/efcode/engine/interactive.c b/usr/src/lib/efcode/engine/interactive.c new file mode 100644 index 0000000000..398f52a686 --- /dev/null +++ b/usr/src/lib/efcode/engine/interactive.c @@ -0,0 +1,808 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <setjmp.h> +#include <sys/stat.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +void (*to_ptr)(fcode_env_t *env) = do_set_action; +jmp_buf *jmp_buf_ptr = NULL; + +char * +parse_a_string(fcode_env_t *env, int *lenp) +{ + parse_word(env); + return (pop_a_string(env, lenp)); +} + +void +constant(fcode_env_t *env) +{ + char *name; + int len; + + name = parse_a_string(env, &len); + env->instance_mode = 0; + make_common_access(env, name, len, 1, 0, + &do_constant, &do_constant, NULL); +} + +void +buffer_colon(fcode_env_t *env) +{ + char *name; + int len; + + PUSH(DS, 0); + name = parse_a_string(env, &len); + make_common_access(env, name, len, 2, + env->instance_mode, &noop, &noop, &set_buffer_actions); +} + +void +value(fcode_env_t *env) +{ + char *name; + int len; + + name = parse_a_string(env, &len); + make_common_access(env, name, len, 1, + env->instance_mode, &noop, &noop, &set_value_actions); +} + +void +variable(fcode_env_t *env) +{ + char *name; + int len; + + PUSH(DS, 0); + name = parse_a_string(env, &len); + make_common_access(env, name, len, 1, + env->instance_mode, &instance_variable, &do_create, NULL); +} + +void +defer(fcode_env_t *env) +{ + static void (*crash_ptr)(fcode_env_t *env) = do_crash; + char *name; + int len; + + PUSH(DS, (fstack_t)&crash_ptr); + name = parse_a_string(env, &len); + make_common_access(env, name, len, 1, + env->instance_mode, &noop, &noop, &set_defer_actions); +} + +void +field(fcode_env_t *env) +{ + char *name; + int len; + + over(env); + name = parse_a_string(env, &len); + make_common_access(env, name, len, 1, 0, &do_field, &do_field, NULL); + add(env); +} + +void +bye(fcode_env_t *env) +{ + exit(0); +} + +void +do_resume(fcode_env_t *env) +{ + if (env->interactive) env->interactive--; + COMPLETE_INTERRUPT; +} + +/* + * In interactive mode, jmp_buf_ptr should be non-null. + */ +void +return_to_interact(fcode_env_t *env) +{ + if (jmp_buf_ptr) + longjmp(*jmp_buf_ptr, 1); +} + +void +do_interact(fcode_env_t *env) +{ + int level; + jmp_buf jmp_env; + jmp_buf *ojmp_ptr; + error_frame new; + input_typ *old_input = env->input; + + log_message(MSG_INFO, "Type resume to return\n"); + env->interactive++; + level = env->interactive; + + ojmp_ptr = jmp_buf_ptr; + jmp_buf_ptr = &jmp_env; + env->input->separator = ' '; + env->input->maxlen = 256; + env->input->buffer = MALLOC(env->input->maxlen); + env->input->scanptr = env->input->buffer; + + if (setjmp(jmp_env)) { + if (in_forth_abort > 1) { + RS = env->rs0; + DS = env->ds0; + MYSELF = 0; + IP = 0; + env->input = old_input; + env->order_depth = 0; + } else { + RS = new.rs; + DS = new.ds; + MYSELF = new.myself; + IP = new.ip; + env->input = old_input; + } + do_forth(env); + do_definitions(env); + in_forth_abort = 0; + } else { + new.rs = RS; + new.ds = DS; + new.myself = MYSELF; + new.ip = IP; + } + + while (env->interactive == level) { + int wlen; + char *p; + + DEBUGF(SHOW_RS, output_return_stack(env, 0, MSG_FC_DEBUG)); + DEBUGF(SHOW_STACK, output_data_stack(env, MSG_FC_DEBUG)); + +#define USE_READLINE +#ifdef USE_READLINE + { + char *line; + void read_line(fcode_env_t *); + + read_line(env); + if ((line = pop_a_string(env, NULL)) == NULL) + continue; + + env->input->scanptr = strcpy(env->input->buffer, line); + } +#else + if (isatty(fileno(stdin))) + printf("ok "); + + env->input->scanptr = fgets(env->input->buffer, + env->input->maxlen, stdin); + + if (feof(stdin)) + break; + + if (env->input->scanptr == NULL) + continue; +#endif + + if ((p = strpbrk(env->input->scanptr, "\n\r")) != NULL) + *p = '\0'; + + if ((wlen = strlen(env->input->scanptr)) == 0) + continue; + + PUSH(DS, (fstack_t)env->input->buffer); + PUSH(DS, wlen); + evaluate(env); + } + + jmp_buf_ptr = ojmp_ptr; + FREE(env->input->buffer); +} + +static void +temp_base(fcode_env_t *env, fstack_t base) +{ + fstack_t obase; + + obase = env->num_base; + env->num_base = base; + parse_word(env); + evaluate(env); + env->num_base = obase; +} + +static void +temp_decimal(fcode_env_t *env) +{ + temp_base(env, 10); +} + +static void +temp_hex(fcode_env_t *env) +{ + temp_base(env, 0x10); +} + +static void +temp_binary(fcode_env_t *env) +{ + temp_base(env, 2); +} + +static void +do_hex(fcode_env_t *env) +{ + env->num_base = 0x10; +} + +static void +do_decimal(fcode_env_t *env) +{ + env->num_base = 10; +} + +static void +do_binary(fcode_env_t *env) +{ + env->num_base = 2; +} + +static void +do_clear(fcode_env_t *env) +{ + DS = env->ds0; +} + +static void +action_one(fcode_env_t *env) +{ + + do_tick(env); + if (env->state) { + COMPILE_TOKEN(&to_ptr); + } else { + PUSH(DS, 1); + perform_action(env); + } +} + +void +do_if(fcode_env_t *env) +{ + branch_common(env, 1, 1, 0); +} + +void +do_else(fcode_env_t *env) +{ + branch_common(env, 1, 0, 1); + bresolve(env); +} + +void +do_then(fcode_env_t *env) +{ + bresolve(env); +} + +void +do_of(fcode_env_t *env) +{ + branch_common(env, 0, 2, 0); +} + +void +load_file(fcode_env_t *env) +{ + int fd; + int len, n; + char *name; + char *buffer; + struct stat buf; + + CHECK_DEPTH(env, 2, "load-file"); + name = pop_a_string(env, &len); + log_message(MSG_INFO, "load_file: '%s'\n", name); + fd = open(name, O_RDONLY); + if (fd < 0) { + forth_perror(env, "Can't open '%s'", name); + } + fstat(fd, &buf); + len = buf.st_size; + buffer = MALLOC(len); + if (buffer == 0) + forth_perror(env, "load_file: MALLOC(%d)", len); + + if ((n = read(fd, buffer, len)) < 0) + forth_perror(env, "read error '%s'", name); + + close(fd); + PUSH(DS, (fstack_t)buffer); + PUSH(DS, (fstack_t)n); +} + +void +load(fcode_env_t *env) +{ + parse_word(env); + if (TOS > 0) + load_file(env); +} + +void +fevaluate(fcode_env_t *env) +{ + char *buffer; + int bytes, len; + + two_dup(env); + buffer = pop_a_string(env, &len); + for (bytes = 0; bytes < len; bytes++) { + if ((buffer[bytes] == '\n') || (buffer[bytes] == '\r')) + buffer[bytes] = ' '; + } + evaluate(env); +} + +void +fload(fcode_env_t *env) +{ + char *buffer; + + load(env); + two_dup(env); + buffer = pop_a_string(env, NULL); + fevaluate(env); + FREE(buffer); +} + +#include <sys/termio.h> + +#define MAX_LINE_BUF 20 + +static char *history_lines[MAX_LINE_BUF]; +int num_lines = 0; + +static void +add_line_to_history(fcode_env_t *env, char *line) +{ + int i; + + if (num_lines < MAX_LINE_BUF) + history_lines[num_lines++] = STRDUP(line); + else { + FREE(history_lines[0]); + for (i = 0; i < MAX_LINE_BUF - 1; i++) + history_lines[i] = history_lines[i + 1]; + history_lines[MAX_LINE_BUF - 1] = STRDUP(line); + } +} + +static void +do_emit_chars(fcode_env_t *env, char c, int n) +{ + int i; + + for (i = 0; i < n; i++) + do_emit(env, c); +} + +static void +do_emit_str(fcode_env_t *env, char *str, int n) +{ + int i; + + for (i = 0; i < n; i++) + do_emit(env, *str++); +} + +static char * +find_next_word(char *cursor, char *eol) +{ + while (cursor < eol && *cursor != ' ') + cursor++; + while (cursor < eol && *cursor == ' ') + cursor++; + return (cursor); +} + +static char * +find_prev_word(char *buf, char *cursor) +{ + int skippedword = 0; + + if (cursor == buf) + return (cursor); + cursor--; + while (cursor > buf && *cursor == ' ') + cursor--; + while (cursor > buf && *cursor != ' ') { + skippedword++; + cursor--; + } + if (skippedword && *cursor == ' ') + cursor++; + return (cursor); +} + +void +redraw_line(fcode_env_t *env, char *prev_l, char *prev_cursor, char *prev_eol, + char *new_l, char *new_cursor, char *new_eol) +{ + int len; + + /* backup to beginning of previous line */ + do_emit_chars(env, '\b', prev_cursor - prev_l); + + /* overwrite new line */ + do_emit_str(env, new_l, new_eol - new_l); + + /* Output blanks to erase previous line chars if old line was longer */ + len = max(0, (prev_eol - prev_l) - (new_eol - new_l)); + do_emit_chars(env, ' ', len); + + /* Backup cursor for new line */ + do_emit_chars(env, '\b', len + (new_eol - new_cursor)); +} + +#define MAX_LINE_SIZE 256 + +static void +do_save_buf(char *save_buf, char *buf, int n) +{ + n = max(0, min(n, MAX_LINE_SIZE)); + memcpy(save_buf, buf, n); + save_buf[n] = '\0'; +} + +char prompt_string[80] = "ok "; + +void +read_line(fcode_env_t *env) +{ + char buf[MAX_LINE_SIZE+1], save_buf[MAX_LINE_SIZE+1]; + char save_line[MAX_LINE_SIZE+1]; + char *p, *cursor, *eol, *tp, *cp; + fstack_t d; + int saw_esc = 0, do_quote = 0, i, cur_line, len, my_line, save_cursor; + struct termio termio, savetermio; + + if (!isatty(fileno(stdin))) { + fgets(buf, sizeof (buf), stdin); + push_string(env, buf, strlen(buf)); + return; + } + printf(prompt_string); + fflush(stdout); + ioctl(fileno(stdin), TCGETA, &termio); + savetermio = termio; + termio.c_lflag &= ~(ICANON|ECHO|ECHOE|IEXTEN); + termio.c_cc[VTIME] = 0; + termio.c_cc[VMIN] = 1; + ioctl(fileno(stdin), TCSETA, &termio); + my_line = cur_line = num_lines; + save_buf[0] = '\0'; + for (cursor = eol = buf; ; ) { + for (d = FALSE; d == FALSE; d = POP(DS)) + keyquestion(env); + key(env); + d = POP(DS); + if (do_quote) { + do_quote = 0; + if ((cursor - buf) < MAX_LINE_SIZE) { + *cursor++ = d; + if (cursor > eol) + eol = cursor; + do_emit(env, d); + } + continue; + } + if (saw_esc) { + saw_esc = 0; + switch (d) { + + default: /* Ignore anything else */ + continue; + + case 'b': /* Move backward one word */ + case 'B': + tp = find_prev_word(buf, cursor); + if (tp < cursor) { + do_emit_chars(env, '\b', cursor - tp); + cursor = tp; + } + continue; + + case 'f': /* Move forward one word */ + case 'F': + tp = find_next_word(cursor, eol); + if (tp > cursor) { + do_emit_str(env, tp, tp - cursor); + cursor = tp; + } + continue; + + case 'h': /* Erase from beginning of word to */ + case 'H': /* just before cursor, saving chars */ + d = CTRL('w'); + break; + + case 'd': + case 'D': + tp = find_next_word(cursor, eol); + if (tp <= cursor) + continue; + len = tp - cursor; + do_save_buf(save_buf, cursor, len); + memmove(cursor, tp, eol - tp); + redraw_line(env, buf, cursor, eol, buf, cursor, + eol - len); + eol -= len; + continue; + } + } + switch (d) { + + default: + if ((cursor - buf) < MAX_LINE_SIZE) { + *cursor++ = d; + if (cursor > eol) + eol = cursor; + do_emit(env, d); + } + continue; + + case CTRL('['): /* saw esc. character */ + saw_esc = 1; + continue; + + case CTRL('f'): /* move forward one char */ + if (cursor < eol) + do_emit(env, *cursor++); + continue; + + case CTRL('a'): /* cursor to beginning of line */ + do_emit_chars(env, '\b', cursor - buf); + cursor = buf; + continue; + + case CTRL('e'): /* cursor to end of line */ + do_emit_str(env, cursor, eol - cursor); + cursor = eol; + continue; + + + case CTRL('n'): /* Move to next line in buffer */ + case CTRL('p'): /* Move to previous line in buffer */ + if (d == CTRL('p')) { + if (cur_line <= 0) + continue; + if (my_line == cur_line) { + do_save_buf(save_line, buf, eol - buf); + save_cursor = cursor - buf; + } + cur_line--; + } else { + if (cur_line >= num_lines) + continue; + cur_line++; + if (cur_line == num_lines) { + len = strlen(save_line); + redraw_line(env, buf, cursor, eol, + save_line, save_line + save_cursor, + save_line + len); + strcpy(buf, save_line); + eol = buf + len; + cursor = buf + save_cursor; + continue; + } + } + p = history_lines[cur_line]; + len = strlen(p); + redraw_line(env, buf, cursor, eol, p, p, p + len); + strcpy(buf, history_lines[cur_line]); + cursor = buf; + eol = buf + len; + continue; + + case CTRL('o'): /* Insert newline */ + continue; + + case CTRL('k'): /* Erase from cursor to eol, saving */ + /* chars, at eol, joins two lines */ + if (cursor == eol) { + if (cur_line >= num_lines) + continue; + if (cur_line == num_lines - 1) { + p = save_line; + len = strlen(save_line); + num_lines -= 1; + my_line = num_lines; + } else { + cur_line++; + p = history_lines[cur_line]; + len = strlen(p); + } + len = min(len, MAX_LINE_SIZE - (eol - buf)); + memcpy(eol, p, len); + redraw_line(env, buf, cursor, eol, buf, cursor, + eol + len); + eol += len; + continue; + } + do_save_buf(save_buf, cursor, eol - cursor); + redraw_line(env, buf, cursor, eol, buf, cursor, + cursor); + eol = cursor; + continue; + + case CTRL('w'): /* Erase word */ + tp = find_prev_word(buf, cursor); + if (tp == cursor) + continue; + len = cursor - tp; + do_save_buf(save_buf, tp, len); + memmove(tp, cursor, eol - cursor); + redraw_line(env, buf, cursor, eol, buf, cursor - len, + eol - len); + eol -= len; + cursor -= len; + continue; + + case CTRL('u'): /* Erases line, saving chars */ + do_save_buf(save_buf, buf, eol - buf); + redraw_line(env, buf, cursor, eol, buf, buf, buf); + cursor = buf; + eol = buf; + continue; + + case CTRL('y'): /* Insert save buffer before cursor */ + len = min(strlen(save_buf), + MAX_LINE_SIZE - (eol - buf)); + if (len == 0) + continue; + memmove(cursor + len, cursor, eol - cursor); + memcpy(cursor, save_buf, len); + redraw_line(env, buf, cursor, eol, buf, cursor + len, + eol + len); + cursor += len; + eol += len; + continue; + + case CTRL('q'): /* Quote next char */ + do_quote = 1; + continue; + + case CTRL('l'): /* Display edit buffer */ + do_emit(env, '\n'); + for (i = 0; i < num_lines; i++) { + do_emit_str(env, history_lines[i], + strlen(history_lines[i])); + do_emit(env, '\n'); + } + redraw_line(env, buf, buf, buf, buf, cursor, eol); + continue; + + case CTRL('r'): /* redraw line */ + redraw_line(env, buf, cursor, eol, buf, cursor, eol); + continue; + + case CTRL('c'): /* Exit script editor */ + continue; + + case CTRL('b'): /* backup cursor */ + if (cursor <= buf) + continue; + cursor--; + do_emit(env, '\b'); + continue; + + case CTRL('h'): /* Backspace */ + case 0x7f: /* DEL */ + if (cursor <= buf) + continue; + memmove(cursor - 1, cursor, eol - cursor); + redraw_line(env, buf, cursor, eol, buf, cursor - 1, + eol - 1); + cursor--; + eol--; + continue; + + case '\r': + case '\n': + *eol = '\0'; + do_emit(env, '\n'); + break; + } + break; + } + add_line_to_history(env, buf); + ioctl(fileno(stdin), TCSETA, &savetermio); + push_string(env, buf, strlen(buf)); +} + +static void +set_prompt(fcode_env_t *env) +{ + char *prompt; + + if ((prompt = parse_a_string(env, NULL)) != NULL) + strncpy(prompt_string, prompt, sizeof (prompt_string)); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(IMMEDIATE, "if", do_if); + FORTH(IMMEDIATE, "else", do_else); + FORTH(IMMEDIATE, "then", do_then); + FORTH(IMMEDIATE, "case", bcase); + FORTH(IMMEDIATE, "of", do_of); + FORTH(IMMEDIATE, "endof", do_else); + FORTH(IMMEDIATE, "endcase", bendcase); + FORTH(IMMEDIATE, "value", value); + FORTH(IMMEDIATE, "variable", variable); + FORTH(IMMEDIATE, "constant", constant); + FORTH(IMMEDIATE, "defer", defer); + FORTH(IMMEDIATE, "buffer:", buffer_colon); + FORTH(IMMEDIATE, "field", field); + FORTH(IMMEDIATE, "struct", zero); + FORTH(IMMEDIATE, "to", action_one); + FORTH(IMMEDIATE, "d#", temp_decimal); + FORTH(IMMEDIATE, "h#", temp_hex); + FORTH(IMMEDIATE, "b#", temp_binary); + FORTH(0, "decimal", do_decimal); + FORTH(0, "hex", do_hex); + FORTH(0, "binary", do_binary); + FORTH(0, "clear", do_clear); + FORTH(IMMEDIATE, "bye", bye); + FORTH(0, "interact", do_interact); + FORTH(IMMEDIATE, "resume", do_resume); + FORTH(0, "fload", fload); + FORTH(0, "load", load); + FORTH(0, "read-line", read_line); + FORTH(0, "set-prompt", set_prompt); +} diff --git a/usr/src/lib/efcode/engine/interface.c b/usr/src/lib/efcode/engine/interface.c new file mode 100644 index 0000000000..31f0cc9e91 --- /dev/null +++ b/usr/src/lib/efcode/engine/interface.c @@ -0,0 +1,273 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +/* + * the external start point for this goo + */ + +void +push_ds(fcode_env_t *env, fstack_t d) +{ + PUSH(DS, d); +} + +fstack_t +pop_ds(fcode_env_t *env) +{ + return (POP(DS)); +} + +void +push_rs(fcode_env_t *env, fstack_t d) +{ + PUSH(RS, d); +} + +fstack_t +pop_rs(fcode_env_t *env) +{ + return (POP(RS)); +} + +/* + * Pushes a C string on the stack. + */ +void +push_a_string(fcode_env_t *env, char *str) +{ + if (str) { + PUSH(DS, (fstack_t)str); + PUSH(DS, strlen(str)); + } else { + PUSH(DS, 0); + PUSH(DS, 0); + } +} + +/* + * Pops a (potentially null) string off the stack. + */ +char * +pop_a_string(fcode_env_t *env, int *lenp) +{ + int len; + char *str; + + len = POP(DS); + str = (char *)POP(DS); + if (len == 0) + str = NULL; + else if (str == NULL) + len = 0; + if (lenp) + *lenp = len; + return (str); +} + +/* + * Pops & strdup's a string off the stack, handles NULL strings. + */ +char * +pop_a_duped_string(fcode_env_t *env, int *lenp) +{ + char *str; + + str = pop_a_string(env, lenp); + if (str) + return (STRDUP(str)); + return (NULL); +} + +/* + * Push Forth Double type. + */ +void +push_double(fcode_env_t *env, dforth_t d) +{ + fstack_t lo, hi; + + lo = DFORTH_LO(d); + hi = DFORTH_HI(d); + PUSH(DS, lo); + PUSH(DS, hi); +} + +/* + * Pop Forth Double type. + */ +dforth_t +pop_double(fcode_env_t *env) +{ + fstack_t lo, hi; + + hi = POP(DS); + lo = POP(DS); + return (MAKE_DFORTH(hi, lo)); +} + +/* + * Peek at top of stack Forth Double type. + */ +dforth_t +peek_double(fcode_env_t *env) +{ + dforth_t a; + + a = pop_double(env); + push_double(env, a); + return (a); +} + +void +run_fcode(fcode_env_t *env, uchar_t *buff, int len) +{ + int i; + + /* + * Really just checking to see if buff is all ascii characters. + * Fcode normally starts with 0xfd, so for fcode, this should be + * a fast check. + */ + for (i = 0; i < len; i++) + if (buff[i] >= 0x80) + break; + PUSH(DS, (fstack_t)buff); + if (i < len) { + /* Non-ascii found, probably Fcode */ + PUSH(DS, (fstack_t)1); + byte_load(env); + } else { + /* All ascii found, probably ascii */ + PUSH(DS, len); + fevaluate(env); + } +} + +void +run_fcode_from_file(fcode_env_t *env, char *fname, int aout_flag) +{ + uchar_t *p; + int len; + + push_a_string(env, fname); + load_file(env); + len = POP(DS); + p = (uchar_t *)POP(DS); + if (aout_flag) { + p += 0x20; + len -= 0x20; + } + run_fcode(env, p, len); +} + +fcode_env_t * +clone_environment(fcode_env_t *src, void *private) +{ + fcode_env_t *env; + + if (!src) { + src = initial_env; + src->private = private; + return (src); + } + +#if 0 + src->private = private; + if (src->my_self || src->state) { + log_message(MSG_WARN, "Can't clone an active instance or" + " compile state!\n"); + return (NULL); + } + + log_message(MSG_WARN, "Warning: Device-tree state is shared!\n"); +#endif + + env = MALLOC(sizeof (fcode_env_t)); + memcpy(env, src, sizeof (fcode_env_t)); + +#if 0 + env->table = MALLOC((MAX_FCODE + 1) * sizeof (fcode_token)); + memcpy(env->table, src->table, (MAX_FCODE + 1) * sizeof (fcode_token)); + + /* + * Note that cloning the dictionary doesn't make sense unless the + * ptrs + XT's in the dictionary are relative to BASE. + */ + env->base = MALLOC(dict_size); + memcpy(env->base, src->base, dict_size); + + env->here = src->base - (uchar_t *)src + env->base; +#endif + + env->ds0 = MALLOC(stack_size * sizeof (fstack_t)); + memcpy(env->ds0, src->ds0, stack_size * sizeof (fstack_t)); + env->ds = src->ds - src->ds0 + env->ds0; + + env->rs0 = MALLOC(stack_size * sizeof (fstack_t)); + memcpy(env->rs0, src->rs0, stack_size * sizeof (fstack_t)); + env->rs = src->rs - src->rs0 + env->rs0; + + env->order = MALLOC(MAX_ORDER * sizeof (token_t)); + memcpy(env->order, src->order, MAX_ORDER * sizeof (token_t)); + + env->input = MALLOC(sizeof (input_typ)); + + env->catch_frame = 0; + + IP = 0; + + return (env); +} + +void +destroy_environment(fcode_env_t *env) +{ + FREE(env->input); + FREE(env->order); + FREE(env->ds0); + FREE(env->rs0); +#if 0 + FREE(env->base); + FREE(env->table); +#endif + FREE(env); + + if (env == initial_env) { + /* This call only happens internally */ + + initial_env = NULL; + /* You had better not exercise the engine anymore! */ + } +} diff --git a/usr/src/lib/efcode/engine/interp.c b/usr/src/lib/efcode/engine/interp.c new file mode 100644 index 0000000000..e0e41dba01 --- /dev/null +++ b/usr/src/lib/efcode/engine/interp.c @@ -0,0 +1,121 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +void +do_run(fcode_env_t *env, int next) +{ + token_t target, indirect; + void (*fn)(fcode_env_t *env); + int debug_state = current_debug_state(env); + extern void do_memory_watch(fcode_env_t *env); + + for (; ; ) { + if (next) { + DEBUGF(NEXT_VITALS, output_vitals(env); + log_message(MSG_FC_DEBUG, "\n")); + CHECK_INTERRUPT; + if (IP == NULL) + break; + WA = (token_t *) *IP; + IP++; + } + check_for_debug_entry(env); + indirect = *WA; + if (indirect & 1) { + target = indirect & ~1; + target = *((token_t *)target); + } else + target = indirect; + fn = (void (*)(fcode_env_t *)) target; + if (do_exec_debug(env, (void *)fn)) + break; + if (indirect & 1) { + PUSH(DS, (fstack_t) (WA+1)); + WA = (token_t *) target; + } + WA++; + fn(env); + check_vitals(env); + check_for_debug_exit(env); + do_memory_watch(env); + next = 1; + } + clear_debug_state(env, debug_state); +} + +void +do_semi(fcode_env_t *env) +{ + CHECK_RETURN_DEPTH(env, 1, ";"); + check_semi_debug_exit(env); + IP = (token_t *) POP(RS); +} + +void +do_colon(fcode_env_t *env) +{ + PUSH(RS, (fstack_t) IP); + IP = WA; +} + +void +do_alias(fcode_env_t *env) +{ + token_t *ip; + + ip = IP; + IP = 0; + WA = (token_t *) *WA; + do_run(env, 0); + IP = ip; +} + +void +execute(fcode_env_t *env) +{ + token_t *ip, *wa; + + /* + * In order to ensure that only this token executes we + * force IP to zero after stashing it, then when the stack + * unwinds (do_run returns) we can restore the old value. + */ + CHECK_DEPTH(env, 1, "execute"); + ip = IP; + wa = WA; + IP = 0; + WA = (token_t *) POP(DS); + do_run(env, 0); + IP = ip; + WA = wa; +} diff --git a/usr/src/lib/efcode/engine/log.c b/usr/src/lib/efcode/engine/log.c new file mode 100644 index 0000000000..b17f38b8c4 --- /dev/null +++ b/usr/src/lib/efcode/engine/log.c @@ -0,0 +1,361 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Daemon log message. This can direct log messages to either stdout, + * an error log file or syslog (or any combination). + */ + +#include <stdarg.h> +#include <stdio.h> +#include <syslog.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#define LOG_LINESIZE 256 +#define LOG_EMIT_BUFSIZE LOG_LINESIZE + +static FILE *error_log_fp = NULL; +static int syslog_opened = 0; +static int error_log_flags; +static int syslog_log_flags; +static int do_emit_flag = -1; +static int daemon_log_flag; +static int min_syslog_level = LOG_ERR; + +static int log_to_stdout(int); +static int log_to_error_log(int); +static int log_to_syslog(int); +static int msg_level_to_syslog(int); + +/* + * Complicated by not wanting to do any emit processing if no one's actually + * going to see it. + */ +void +log_emit(char c) +{ + static char emit_buf[LOG_EMIT_BUFSIZE]; + static char *emit_p = emit_buf; + static int lastnl = 1; + + /* + * No one has set the do_emit_flag, go ahead and figure it out. + */ + if (do_emit_flag < 0) { + do_emit_flag = (log_to_stdout(MSG_EMIT) | + log_to_error_log(MSG_EMIT) | log_to_syslog(MSG_EMIT)); + } + + if (!do_emit_flag) + return; + + /* + * Check for buffer overflow. + */ + if (emit_p >= &emit_buf[LOG_EMIT_BUFSIZE - 1]) { + *emit_p = '\0'; + log_message(MSG_EMIT, "emit: %s\n", emit_buf); + emit_p = emit_buf; + lastnl = 1; + } + + /* + * Fcode emit's may output both CR/LF, we go ahead and eat multiple + * ones in succession. + */ + if (c == '\n' || c == '\r') { + if (!lastnl) { + *emit_p = '\0'; + log_message(MSG_EMIT, "emit: %s\n", emit_buf); + emit_p = emit_buf; + } + lastnl = 1; + } else { + lastnl = 0; + *emit_p++ = c; + } +} + +/* + * If stdout is a tty and this is MSG_EMIT, we should have alredy output it. + * If running as daemon, output to stdout is a waste of time. + */ +static int +log_to_stdout(int msg_level) +{ + if (isatty(fileno(stdin)) && (msg_level & MSG_EMIT) != 0) + return (0); + return (daemon_log_flag == 0); +} + +/* + * Can't turn off FATAL or ERROR messages to error log file. + */ +static int +log_to_error_log(int msg_level) +{ + if (!error_log_fp) + return (0); + if (msg_level & (MSG_FATAL|MSG_ERROR)) + return (1); + return (msg_level & error_log_flags); +} + +/* + * Can't turn off FATAL or ERROR messages to syslog. + */ +static int +log_to_syslog(int msg_level) +{ + if (!syslog_opened) + return (0); + if (msg_level & (MSG_FATAL|MSG_ERROR)) + return (1); + return (msg_level & syslog_log_flags); +} + +/* + * Turn internal MSG level to syslog msg level. Don't return a msg level + * lower priority than min_syslog_level. + */ +static int +msg_level_to_syslog(int msg_level) +{ + if (min_syslog_level <= LOG_ERR) + return (min_syslog_level); + if (msg_level & (MSG_FATAL|MSG_ERROR)) + return (LOG_ERR); + if (min_syslog_level <= LOG_WARNING) + return (min_syslog_level); + if (msg_level & MSG_WARN) + return (LOG_WARNING); + if (min_syslog_level <= LOG_NOTICE) + return (min_syslog_level); + if (msg_level & MSG_NOTE) + return (LOG_NOTICE); + if (min_syslog_level <= LOG_INFO) + return (min_syslog_level); + if (msg_level & MSG_INFO) + return (LOG_INFO); + return (min(min_syslog_level, LOG_DEBUG)); +} + +/* + * Log a message to the appropriate places. + */ +void +log_message(int msg_level, char *fmt, ...) +{ + va_list ap; + char msg[LOG_LINESIZE], *p; + static char log_msg[LOG_LINESIZE]; + + va_start(ap, fmt); + + vsprintf(msg, fmt, ap); + + if (log_to_stdout(msg_level)) { + printf(msg); + fflush(stdout); + } + if (log_to_error_log(msg_level)) { + fprintf(error_log_fp, msg); + fflush(error_log_fp); + } + if (log_to_syslog(msg_level)) { + if (strlen(log_msg) + strlen(msg) > LOG_LINESIZE - 1) { + syslog(msg_level_to_syslog(msg_level), log_msg); + log_msg[0] = '\0'; + } + strcat(log_msg, msg); + if ((p = strchr(log_msg, '\n')) != NULL) { + *p = '\0'; + syslog(msg_level_to_syslog(msg_level), log_msg); + log_msg[0] = '\0'; + } + } +} + +/* + * Output debug message + */ +void +debug_msg(int debug_level, char *fmt, ...) +{ + va_list ap; + char msg[LOG_LINESIZE]; + + if ((debug_level & get_interpreter_debug_level()) == 0) + return; + + va_start(ap, fmt); + + vsprintf(msg, fmt, ap); + + log_message(MSG_DEBUG, msg); +} + +/* + * Log a perror message to the appropriate places. + */ +void +log_perror(int msg_level, char *fmt, ...) +{ + va_list ap; + char msg[LOG_LINESIZE], tmp[LOG_LINESIZE]; + + va_start(ap, fmt); + + vsprintf(msg, fmt, ap); + sprintf(tmp, "%s: %s\n", msg, strerror(errno)); + log_message(msg_level, tmp); +} + +void +set_min_syslog_level(int level) +{ + min_syslog_level = level; +} + +char *error_log_name; + +void +open_error_log(char *fname, int errflags) +{ + if ((error_log_fp = fopen(fname, "a")) == NULL) { + log_perror(MSG_FATAL, fname); + exit(1); + } + error_log_name = STRDUP(fname); + error_log_flags = errflags; + do_emit_flag = (log_to_stdout(MSG_EMIT) | log_to_error_log(MSG_EMIT) | + log_to_syslog(MSG_EMIT)); +} + +void +open_syslog_log(char *logname, int logflags) +{ + openlog(logname, LOG_PID, LOG_DAEMON); + syslog_log_flags = logflags; + do_emit_flag = (log_to_stdout(MSG_EMIT) | log_to_error_log(MSG_EMIT) | + log_to_syslog(MSG_EMIT)); + syslog_opened = 1; +} + +/* + * Turn on/off syslog LOG_DAEMON flag to syslog messages. Also controls + * outputting to stdout, which is a waste of time when we're running as a + * daemon. + */ +void +set_daemon_log_flag(int flag) +{ + if (flag) + daemon_log_flag = LOG_DAEMON; + else + daemon_log_flag = 0; +} + +int +parse_msg_flags(char *flags) +{ + int msgflags = 0; + char c; + + while ((c = *flags++) != '\0') { + switch (c) { + case 'f': msgflags |= MSG_FATAL; break; + case 'e': msgflags |= MSG_ERROR; break; + case 'w': msgflags |= MSG_WARN; break; + case 'i': msgflags |= MSG_INFO; break; + case 'd': msgflags |= MSG_DEBUG; break; + case 'D': msgflags |= MSG_FC_DEBUG; break; + + default: + log_message(MSG_ERROR, "Invalid msglvl flag: %c\n", c); + break; + } + } + return (msgflags); +} + +#define MAXERRBUF 256 +char error_buffer[MAXERRBUF]; + +static void +dot_error_buffer(fcode_env_t *env) +{ + log_message(MSG_INFO, "%s\n", error_buffer); +} + +static void +set_error_log(fcode_env_t *env) +{ + char *fname; + FILE *fp; + + parse_word(env); + fname = pop_a_string(env, NULL); + if (fname != NULL) { + if ((fp = fopen(fname, "a")) == NULL) { + log_perror(MSG_ERROR, "Can't open '%s'\n", fname); + return; + } + if (error_log_fp) + fclose(error_log_fp); + if (error_log_name) + FREE(error_log_name); + error_log_fp = fp; + error_log_name = STRDUP(fname); + error_log_flags = MSG_FATAL|MSG_ERROR|MSG_WARN|MSG_INFO| + MSG_DEBUG|MSG_FC_DEBUG; + } else if (error_log_name) + log_message(MSG_INFO, "%s\n", error_log_name); + else + log_message(MSG_INFO, "NULL\n"); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, ".error-buffer", dot_error_buffer); + FORTH(0, "set-error-log", set_error_log); +} diff --git a/usr/src/lib/efcode/engine/mcookie.c b/usr/src/lib/efcode/engine/mcookie.c new file mode 100644 index 0000000000..8a12bf547a --- /dev/null +++ b/usr/src/lib/efcode/engine/mcookie.c @@ -0,0 +1,237 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +#define MAX_MAPS 16 + +#define MAP_IS_VALID 0x01 + +struct map_table { + int map_flags; + uint64_t map_add; + size_t map_size; + uint64_t adj_virt; + size_t adj_length; +} map_table[MAX_MAPS]; + +/* + * Originally, this code translated kernel supplied virtual addresses into + * "memory cookies", which was a 32-bit number with ascii-M in the upper 8 + * bits, a 4-bit index and a 20-bit offset. However, this caused two + * problems: 1) the 20-bit offset was too small for some devices, esp. some + * with frame-buffers; 2) if the fcode used the cookie to program the + * hardware, there was no easy way for the software to detect that a + * translation needed to be done. + * + * For that reason, "memory cookies" are now just the kernel-supplied + * virtual address, and we now check each memory access to see if it's + * attempting to access kernel-supplied memory. The only important thing + * now is that "is_mcookie" returns 1 (or true) if the tested mcookie + * is a kernel virtual address. + * + * There is a potential bug if the kernel virtual address happens to + * conflict with a user virtual address. However, the current implementation + * of Solaris avoids this conflict. + */ + +fstack_t +mapping_to_mcookie(uint64_t req_add, size_t req_size, uint64_t adj_virt, + size_t adj_length) +{ + int i; + struct map_table *mp; + + for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) + if ((mp->map_flags & MAP_IS_VALID) == 0) + break; + if (i == MAX_MAPS) { + log_message(MSG_WARN, "Warning: too many mappings\n"); + return (0); + } + debug_msg(DEBUG_REG_ACCESS, "Allocating mapping: %d add: 0x%llx" + " size: 0x%x\n", i, req_add, req_size); + mp->map_flags |= MAP_IS_VALID; + mp->map_add = req_add; + mp->map_size = req_size; + mp->adj_virt = adj_virt; + mp->adj_length = adj_length; + if (mp->adj_length != 0) + return (adj_virt); + else + return (req_add); +} + +void +delete_mapping(fstack_t mcookie) +{ + int i; + struct map_table *mp; + + for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) { + if ((mp->map_flags & MAP_IS_VALID) && + mcookie >= mp->map_add && + mcookie < mp->map_add + mp->map_size) { + debug_msg(DEBUG_REG_ACCESS, "Deallocating mapping: %d" + " add: 0x%llx size: 0x%x\n", i, mp->map_add, + mp->map_size); + mp->map_flags &= ~MAP_IS_VALID; + mp->map_add = 0; + mp->map_size = 0; + mp->adj_virt = 0; + mp->adj_length = 0; + return; + } + } + log_message(MSG_WARN, "Warning: delete_mapping: invalid" + " mcookie: %llx\n", (uint64_t)mcookie); +} + +int +is_mcookie(fstack_t mcookie) +{ + struct map_table *mp; + int i; + + for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) + if ((mp->map_flags & MAP_IS_VALID) && + mcookie >= mp->map_add && + mcookie < mp->map_add + mp->map_size) + return (1); + return (0); +} + +uint64_t +mcookie_to_addr(fstack_t mcookie) +{ + return (mcookie); +} + +fstack_t +mcookie_to_rlen(fstack_t mcookie) +{ + int i; + struct map_table *mp; + + for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) { + if ((mp->map_flags & MAP_IS_VALID) && + mcookie >= mp->map_add && + mcookie < mp->map_add + mp->map_size) { + return (mp->map_size); + } + } + log_message(MSG_WARN, "Warning: mcookie_to_rlen: invalid" + " mcookie: %llx\n", (uint64_t)mcookie); +} + +fstack_t +mcookie_to_rvirt(fstack_t mcookie) +{ + int i; + struct map_table *mp; + + for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) { + if ((mp->map_flags & MAP_IS_VALID) && + mcookie >= mp->map_add && + mcookie < mp->map_add + mp->map_size) { + return (mp->map_add); + } + } + log_message(MSG_WARN, "Warning: mcookie_to_rvirt: invalid" + " mcookie: %llx\n", (uint64_t)mcookie); +} + +static void +dot_maps(fcode_env_t *env) +{ + int i; + + log_message(MSG_DEBUG, "idx base-addr size\n"); + for (i = 0; i < MAX_MAPS; i++) { + if (map_table[i].map_flags & MAP_IS_VALID) + log_message(MSG_DEBUG, "%3d %016llx %8x\n", i, + map_table[i].map_add, map_table[i].map_size); + } +} + +static void +map_qmark(fcode_env_t *env) +{ + fstack_t d = POP(DS); + + if (!is_mcookie(d)) + log_message(MSG_INFO, "%llx: not mcookie\n", (uint64_t)d); + else + log_message(MSG_INFO, "%llx -> %llx\n", (uint64_t)d, + mcookie_to_addr(d)); +} + +static void +add_map(fcode_env_t *env) +{ + fstack_t size, addr; + + size = POP(DS); + addr = POP(DS); + addr = mapping_to_mcookie(addr, size, NULL, NULL); + PUSH(DS, addr); +} + +static void +del_map(fcode_env_t *env) +{ + fstack_t addr; + + addr = POP(DS); + delete_mapping(addr); +} + + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, ".maps", dot_maps); + FORTH(0, "map?", map_qmark); + FORTH(0, "add-map", add_map); + FORTH(0, "del-map", del_map); +} diff --git a/usr/src/lib/efcode/engine/package.c b/usr/src/lib/efcode/engine/package.c new file mode 100644 index 0000000000..b32773f45d --- /dev/null +++ b/usr/src/lib/efcode/engine/package.c @@ -0,0 +1,1077 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +#define MIN_VALUES 100 + +static void +check_my_self(fcode_env_t *env, char *fn) +{ + if (!MYSELF) + forth_abort(env, "%s: MYSELF is NULL", fn); +} + +uint_t +get_number_of_parent_address_cells(fcode_env_t *env) +{ + uint_t ncells; + device_t *d; + static char func_name[] = "get_number_of_parent_address_cells"; + + if (MYSELF == NULL) /* Kludge for testing */ + return (2); + d = MYSELF->device; + ncells = d->parent_adr_cells; + if (ncells == 0) { + ncells = get_default_intprop(env, "#address-cells", d->parent, + 2); + if (ncells > MAX_MY_ADDR) { + log_message(MSG_ERROR, "%s: %s:" + " ncells (%d) > MAX_MY_ADDR (%d)\n", func_name, + get_path(env, d->parent), ncells, MAX_MY_ADDR); + ncells = MAX_MY_ADDR; + } + d->parent_adr_cells = ncells; + } + return (ncells); +} + +instance_t * +create_ihandle(fcode_env_t *env, device_t *phandle, instance_t *parent) +{ + instance_t *ihandle; + int i; + + ihandle = MALLOC(sizeof (instance_t)); + + i = max(phandle->data_size[INIT_DATA], MIN_VALUES); + ihandle->data[INIT_DATA] = MALLOC(sizeof (fstack_t) * i); + memcpy(ihandle->data[INIT_DATA], phandle->init_data, + (size_t) (sizeof (fstack_t) * i)); + + i = max(phandle->data_size[UINIT_DATA], MIN_VALUES); + ihandle->data[UINIT_DATA] = MALLOC(sizeof (fstack_t) * i); + + ihandle->my_space = phandle->my_space; + memcpy(ihandle->my_addr, phandle->my_addr, sizeof (ihandle->my_addr)); + ihandle->parent = parent; + ihandle->device = phandle; + return (ihandle); +} + +device_t * +create_phandle(fcode_env_t *env, device_t *parent) +{ + device_t *phandle; + + phandle = MALLOC(sizeof (device_t)); + phandle->init_data = MALLOC(sizeof (fstack_t) * MIN_VALUES); + phandle->data_size[INIT_DATA] = 0; + phandle->data_size[UINIT_DATA] = 0; + phandle->parent = parent; + return (phandle); +} + + +static void +do_push_package(fcode_env_t *env, device_t *d) +{ + do_previous(env); + do_also(env); + if (d != NULL) { + CONTEXT = (token_t *)(&d->vocabulary); + debug_msg(DEBUG_CONTEXT, "CONTEXT:push_package: %s%d/%p/%p\n", + get_path(env, d), env->order_depth, CONTEXT, env->current); + } +} + +static void +push_package(fcode_env_t *env) +{ + device_t *d; + phandle_t ph; + + CHECK_DEPTH(env, 1, "push-package"); + ph = POP(DS); + CONVERT_PHANDLE(env, d, ph); + do_push_package(env, d); +} + +static void +pop_package(fcode_env_t *env) +{ + do_previous(env); + do_definitions(env); +} + +static void +interpose(fcode_env_t *env) +{ + TODO; /* interpose - not yet implemented */ +} + +void +activate_device(fcode_env_t *env, device_t *d) +{ + env->current_device = d; + do_push_package(env, d); + do_definitions(env); +} + +void +deactivate_device(fcode_env_t *env, device_t *d) +{ + env->current_device = d; + do_previous(env); + if (d != NULL) { + CONTEXT = (token_t *)(&d->vocabulary); + debug_msg(DEBUG_CONTEXT, "CONTEXT:deactivate_device:" + " %s%d/%p/%p\n", get_path(env, d), env->order_depth, + CONTEXT, env->current); + } + do_definitions(env); +} + +/* + * Starfire hack to set '/' device_type to 'upa' + */ +#include <sys/systeminfo.h> +static void +starfire_hack(fcode_env_t *env) +{ + char platform[100]; + + sysinfo(SI_PLATFORM, platform, sizeof (platform)); + if (strcmp(platform, "SUNW,Ultra-Enterprise-10000") == 0 && + find_property(env->root_node, "device_type") == NULL) { + create_string_prop(env, "device_type", "upa"); + } +} + +void +root_node(fcode_env_t *env) +{ + do_also(env); + activate_device(env, env->root_node); + starfire_hack(env); +} + +void +child_node(fcode_env_t *env) +{ + device_t *d; + + CHECK_DEPTH(env, 1, "child"); + CONVERT_PHANDLE(env, d, TOS); + TOS = (fstack_t)d->child; + REVERT_PHANDLE(env, TOS, d->child); +} + +void +peer_node(fcode_env_t *env) +{ + device_t *d; + + CHECK_DEPTH(env, 1, "peer"); + CONVERT_PHANDLE(env, d, TOS); + REVERT_PHANDLE(env, TOS, d->peer); +} + +void +new_device(fcode_env_t *env) +{ + device_t *phandle, *parent; + device_t *peer; + + check_my_self(env, "new-device"); + + parent = MYSELF->device; + phandle = create_phandle(env, parent); + MYSELF = create_ihandle(env, phandle, MYSELF); + activate_device(env, phandle); + if (parent->child) { + /* Insert new child at end of peer list */ + for (peer = parent->child; peer->peer; peer = peer->peer) + ; + peer->peer = phandle; + } else + parent->child = phandle; /* First child */ + ALLOCATE_PHANDLE(env); +} + +void +finish_device(fcode_env_t *env) +{ + fstack_t *mem; + device_t *my_dev, *parent_dev; + instance_t *parent, *myself = MYSELF; + int n; + + check_my_self(env, "finish-device"); + ASSERT(myself->device); + ASSERT(env->current_device); + n = myself->device->data_size[INIT_DATA]; + + /* + * Paranoia.. reserve a little more instance data than we need + */ + mem = MALLOC(sizeof (fstack_t) * (n+8)); + memcpy(mem, MYSELF->device->init_data, sizeof (fstack_t) * n); + FREE(myself->device->init_data); + my_dev = myself->device; + my_dev->init_data = mem; + parent = MYSELF->parent; + parent_dev = env->current_device->parent; + FREE(MYSELF); + MYSELF = parent; + activate_device(env, parent_dev); +} + +static void +create_internal_value(fcode_env_t *env, char *name, int offset, int token) +{ + header(env, name, strlen(name), 0); + COMPILE_TOKEN(&noop); + EXPOSE_ACF; + if (token) { + SET_TOKEN(token, 0, name, LINK_TO_ACF(env->lastlink)); + } + PUSH(DS, offset); + lcomma(env); + set_internal_value_actions(env); +} + +static void +create_my_self(fcode_env_t *env) +{ + int offset = offsetof(fcode_env_t, my_self); + + create_internal_value(env, "my-self", offset, 0x203); +} + +static void +create_my_space(fcode_env_t *env) +{ + int offset = offsetof(instance_t, my_space); + + create_internal_value(env, "my-space", -offset, 0x103); +} + +void +my_address(fcode_env_t *env) +{ + fstack_t *adr_ptr; + uint_t ncells; + + check_my_self(env, "my-address"); + ncells = get_number_of_parent_address_cells(env); + adr_ptr = MYSELF->my_addr; + while (--ncells) { + PUSH(DS, *adr_ptr); + adr_ptr++; + } +} + +void +my_unit(fcode_env_t *env) +{ + check_my_self(env, "my-unit"); + my_address(env); + PUSH(DS, MYSELF->my_space); +} + +static void +my_args(fcode_env_t *env) +{ + check_my_self(env, "my-args"); + PUSH(DS, (fstack_t)MYSELF->my_args); + PUSH(DS, (fstack_t)MYSELF->my_args_len); +} + +int +call_my_parent(fcode_env_t *env, char *method) +{ + push_a_string(env, method); + dollar_call_parent(env); + return (env->last_error); +} + +void +set_args(fcode_env_t *env) +{ + int args_len; + common_data_t *cdp; + uint_t ncells; + fstack_t *adr_ptr, *adr_ptr1, space; + + CHECK_DEPTH(env, 4, "set-args"); + + check_my_self(env, "set-args"); + + /* + * Handle args argument of set-args. + */ + if (MYSELF->my_args) { + FREE(MYSELF->my_args); + MYSELF->my_args = NULL; + } + two_swap(env); + MYSELF->my_args = pop_a_duped_string(env, &args_len); + MYSELF->my_args_len = args_len; + + if (call_my_parent(env, "decode-unit")) + forth_abort(env, "set-args: decode-unit failed"); + + ncells = get_number_of_parent_address_cells(env); + + /* + * Kludge: For GP2, my-space comes from decode-unit hi.address. + * for PCI, my-space from decode-unit won't have the bus#, so we need + * to get it from config_address. Unfortunately, there is no easy + * way to figure out here which one we're looking at. We take the + * expediant of or'ing the two values together. + */ + space = POP(DS); /* pop phys.hi */ + if ((cdp = (common_data_t *)env->private) != NULL) + space |= cdp->fc.config_address; + + MYSELF->device->my_space = MYSELF->my_space = space; + + adr_ptr = MYSELF->my_addr; + adr_ptr1 = MYSELF->device->my_addr; + while (--ncells) { + *adr_ptr++ = *adr_ptr1++ = POP(DS); + } +} + +void +my_parent(fcode_env_t *env) +{ + check_my_self(env, "my-parent"); + PUSH(DS, (fstack_t)MYSELF->parent); +} + +instance_t * +open_instance_chain(fcode_env_t *env, device_t *phandle, int exec) +{ + instance_t *parent; + + if (!phandle) + return (NULL); + parent = open_instance_chain(env, phandle->parent, exec); + return (create_ihandle(env, phandle, parent)); +} + +void +close_instance_chain(fcode_env_t *env, instance_t *ihandle, int exec) +{ + instance_t *parent; + + if (ihandle) { + parent = ihandle->parent; + close_instance_chain(env, parent, exec); + if (ihandle->my_args) + FREE(ihandle->my_args); + FREE(ihandle); + } +} + +void +begin_package(fcode_env_t *env) +{ + fstack_t ok; + char *name; + + CHECK_DEPTH(env, 6, "begin-package"); + two_dup(env); + name = pop_a_string(env, NULL); + find_package(env); + ok = POP(DS); + if (ok) { + PUSH(DS, 0); + PUSH(DS, 0); + rot(env); + open_package(env); + MYSELF = (instance_t *)POP(DS); + check_my_self(env, "begin-package"); + new_device(env); + set_args(env); + } else { + log_message(MSG_INFO, "Package '%s' not found\n", name); + } +} + +void +open_package(fcode_env_t *env) +{ + device_t *phandle; + instance_t *ihandle; + int len; + + CHECK_DEPTH(env, 3, "open-package"); + CONVERT_PHANDLE(env, phandle, POP(DS)); + ihandle = open_instance_chain(env, phandle, 1); + ihandle->my_args = pop_a_duped_string(env, &len); + ihandle->my_args_len = len; + PUSH(DS, (fstack_t)ihandle); +} + +void +dollar_open_package(fcode_env_t *env) +{ + fstack_t ok; + + CHECK_DEPTH(env, 4, "$open-package"); + find_package(env); + ok = POP(DS); + if (ok) { + open_package(env); + } else { + PUSH(DS, 0); + } +} + +void +close_package(fcode_env_t *env) +{ + instance_t *ihandle; + + CHECK_DEPTH(env, 1, "close-package"); + ihandle = (instance_t *)POP(DS); + close_instance_chain(env, ihandle, 1); +} + +static void (*find_method_hook)(fcode_env_t *); + +void +set_find_method_hook(fcode_env_t *env, void (*hook)(fcode_env_t *)) +{ + find_method_hook = hook; +} + +void +find_method(fcode_env_t *env) +{ + fstack_t d; + device_t *device; + acf_t acf = 0; + + CHECK_DEPTH(env, 3, "find-method"); + if (find_method_hook) { + (*find_method_hook)(env); + if (TOS) /* Found it */ + return; + POP(DS); + } + + d = POP(DS); + CONVERT_PHANDLE(env, device, d); + PUSH(DS, (fstack_t)&device->vocabulary); + acf = voc_find(env); + PUSH(DS, (fstack_t)acf); + if (acf) { + PUSH(DS, TRUE); + } +} + +/* + * 'call-package' Fcode + */ +void +call_package(fcode_env_t *env) +{ + instance_t *ihandle, *saved_myself; + + CHECK_DEPTH(env, 2, "call-package"); + ihandle = (instance_t *)POP(DS); + saved_myself = MYSELF; + MYSELF = ihandle; + execute(env); + MYSELF = saved_myself; +} + +void +ihandle_to_phandle(fcode_env_t *env) +{ + instance_t *i; + + CHECK_DEPTH(env, 1, "ihandle>phandle"); + i = (instance_t *)TOS; + REVERT_PHANDLE(env, TOS, i->device); +} + +char * +get_package_name(fcode_env_t *env, device_t *d) +{ + char *name; + prop_t *prop; + + prop = lookup_package_property(env, "name", d); + if (prop == NULL) { + name = "<Unnamed>"; + } else { + name = (char *)prop->data; + } + return (name); +} + +static char *package_search_path = "/packages:/openprom"; + +device_t * +match_package_path(fcode_env_t *env, char *path) +{ + device_t *d; + char *name; + int len; + + if (*path == '/') { + d = env->root_node->child; + path++; + } else + d = env->current_device; + while (*path != '\0' && d != NULL) { + name = get_package_name(env, d); + len = strlen(name); + if (strncmp(name, path, len) == 0) { + path += len; + if (*path == '\0') { + return (d); + } + /* skip the '/' */ + if (*path++ != '/') + break; + d = d->child; + } else { + d = d->peer; + } + } + return (NULL); +} + +device_t * +locate_package(fcode_env_t *env, char *start) +{ + device_t *d; + char *p, *next_p; + char *tpath, *fpath; + + if ((d = match_package_path(env, start)) != NULL) + return (d); + + /* + * ignore starting '/' + */ + if (*start == '/') + *start++; + + fpath = STRDUP(package_search_path); + for (p = fpath; p != NULL; p = next_p) { + if ((next_p = strchr(p, ':')) != NULL) + *next_p++ = '\0'; + tpath = MALLOC(strlen(p) + strlen(start) + 2); + sprintf(tpath, "%s/%s", p, start); + if ((d = match_package_path(env, tpath)) != NULL) { + FREE(fpath); + FREE(tpath); + return (d); + } + FREE(tpath); + } + FREE(fpath); + return (NULL); +} + +void +find_package(fcode_env_t *env) +{ + char *path; + device_t *package; + fstack_t ph = 0; + + CHECK_DEPTH(env, 2, "find-package"); + if ((path = pop_a_duped_string(env, NULL)) != NULL) { + if (strcmp(path, "/") == 0) + package = env->root_node; + else + package = locate_package(env, path); + FREE(path); + REVERT_PHANDLE(env, ph, package); + } + PUSH(DS, ph); + if (package) + PUSH(DS, TRUE); +} + +static void +encode_unit_hack(fcode_env_t *env) +{ + int hi, i; + uint_t ncells = get_number_of_parent_address_cells(env); + + for (i = 0; i < ncells; i++) + POP(DS); + push_a_string(env, NULL); +} + +void +dollar_call_method(fcode_env_t *env) +{ + instance_t *old_myself; + instance_t *myself; + device_t *device; + char *method; + + CHECK_DEPTH(env, 3, "$call-method"); + check_my_self(env, "$call-method"); + old_myself = MYSELF; + myself = (instance_t *)POP(DS); + + method = (char *)DS[-1]; + debug_msg(DEBUG_CALL_METHOD, "$call_method %s\n", method); + + if (old_myself && !myself) { + /* We hit the root of our tree */ + device = old_myself->device; + return; + } + + MYSELF = myself; + check_my_self(env, "$call-method"); + device = MYSELF->device; + do_push_package(env, device); + PUSH(DS, (fstack_t)device); + REVERT_PHANDLE(env, TOS, device); + find_method(env); + if (TOS) { + (void) POP(DS); + execute(env); + } else if (strcmp(method, "encode-unit") == 0) { + encode_unit_hack(env); + } else { + throw_from_fclib(env, 1, "Unimplemented package method: %s%s", + get_path(env, device), method); + } + MYSELF = old_myself; + do_push_package(env, MYSELF->device); +} + +void +dollar_call_parent(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "$call-parent"); + + check_my_self(env, "$call-parent"); + + PUSH(DS, (fstack_t)MYSELF->parent); + dollar_call_method(env); +} + +#ifdef DEBUG +void +current_device(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)&env->current_device); +} + +char * +get_path(fcode_env_t *env, device_t *d) +{ + char *pre_path, *name, *path; + int n; + + if (d->parent) + pre_path = get_path(env, d->parent); + else + pre_path = STRDUP(""); + + name = get_package_name(env, d); + n = strlen(pre_path) + strlen(name) + 1; + path = MALLOC(n); + strcpy(path, pre_path); + strcat(path, name); + if (d->child && d->parent) + strcat(path, "/"); + FREE(pre_path); + return (path); +} + +static void +pwd_dollar(fcode_env_t *env) +{ + if (env->current_device) + push_a_string(env, get_path(env, env->current_device)); + else + push_a_string(env, NULL); +} + +void +pwd(fcode_env_t *env) +{ + if (env->current_device) { + log_message(MSG_INFO, "%s\n", + get_path(env, env->current_device)); + } else { + log_message(MSG_INFO, "No device context\n"); + } +} + +void +do_ls(fcode_env_t *env) +{ + device_t *d; + + if (env->current_device == NULL) { + log_message(MSG_INFO, "No device context\n"); + return; + } + + d = env->current_device->child; + while (d) { + char *name; + fstack_t ph; + name = get_package_name(env, d); + REVERT_PHANDLE(env, ph, d); + log_message(MSG_INFO, "%llx %s\n", (uint64_t)ph, name); + d = d->peer; + } +} + +void +paren_cd(fcode_env_t *env) +{ + char *str; + device_t *p; + + str = pop_a_string(env, NULL); + if (strcmp(str, "/") == 0) { + root_node(env); + return; + } + + if (env->current_device == NULL) { + log_message(MSG_INFO, "No device context\n"); + return; + } + + if (strcmp(str, "..") == 0) + p = env->current_device->parent; + else { + device_t *n = env->current_device->child; + + p = NULL; + while (n) { + char *name; + + name = get_package_name(env, n); + if (strcmp(name, str) == 0) { + p = n; + break; + } + n = n->peer; + } + } + + if (p) { + activate_device(env, p); + } else { + log_message(MSG_INFO, "No such node: %s\n", str); + } +} + +void +do_cd(fcode_env_t *env) +{ + parse_word(env); + paren_cd(env); +} + +void +do_unselect_dev(fcode_env_t *env) +{ + check_my_self(env, "unselect-dev"); + PUSH(DS, (fstack_t)MYSELF); + close_package(env); + deactivate_device(env, NULL); +} + +void +do_select_dev(fcode_env_t *env) +{ + PUSH(DS, 0); + PUSH(DS, 0); + two_swap(env); + dollar_open_package(env); + if (TOS) { + MYSELF = (instance_t *)POP(DS); + check_my_self(env, "select-dev"); + activate_device(env, MYSELF->device); + } else { + drop(env); + log_message(MSG_INFO, "Can't open package\n"); + } +} + +void +device_end(fcode_env_t *env) +{ + if (env->current_device) { + deactivate_device(env, NULL); + } +} + +void +end_package(fcode_env_t *env) +{ + finish_device(env); + close_instance_chain(env, MYSELF, 0); + device_end(env); + MYSELF = NULL; +} + +void +exec_parent_method(fcode_env_t *env) +{ + instance_t *old_myself; + instance_t *myself; + device_t *device; + char *method; + fstack_t d; + + check_my_self(env, "exec-parent-method"); + old_myself = MYSELF; + MYSELF = MYSELF->parent; + + method = (char *)DS[-1]; + debug_msg(DEBUG_FIND_FCODE, "exec_parent_method: '%s'\n", method); + + check_my_self(env, "exec-parent-method"); + device = MYSELF->device; + do_push_package(env, device); + PUSH(DS, (fstack_t)device); + REVERT_PHANDLE(env, TOS, device); + find_method(env); + d = POP(DS); + if (d) { + debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'/%x" + " execute\n", method, (int)TOS); + execute(env); + PUSH(DS, TRUE); + } else { + debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'" + " not found\n", method); + PUSH(DS, FALSE); + } + MYSELF = old_myself; + do_push_package(env, MYSELF->device); +} + +void +dump_device(fcode_env_t *env) +{ + device_t *phandle; + int i; + + CONVERT_PHANDLE(env, phandle, POP(DS)); + log_message(MSG_DEBUG, "Node: %p\n", phandle); + log_message(MSG_DEBUG, " Parent: (%8p) %p\n", + &phandle->parent, phandle->parent); + log_message(MSG_DEBUG, " Child: (%8p) %p\n", + &phandle->child, phandle->child); + log_message(MSG_DEBUG, " Peer: (%8p) %p\n", + &phandle->peer, phandle->peer); + log_message(MSG_DEBUG, " Private: (%8p) %p\n", + &phandle->private, phandle->private); + log_message(MSG_DEBUG, " Props: (%8p) %p\n", + &phandle->properties, phandle->properties); + log_message(MSG_DEBUG, " Voc: (%8p) %p\n", + &phandle->vocabulary, phandle->vocabulary); + log_message(MSG_DEBUG, " sizes: (%8p) %d %d\n", + &phandle->data_size, + phandle->data_size[INIT_DATA], + phandle->data_size[UINIT_DATA]); + log_message(MSG_DEBUG, " my_space: %x\n", phandle->my_space); + log_message(MSG_DEBUG, " my_addr :"); + for (i = 0; i < MAX_MY_ADDR; i++) + log_message(MSG_DEBUG, " %x", (int)phandle->my_addr[i]); + log_message(MSG_DEBUG, "\n"); + log_message(MSG_DEBUG, " data: (%8p)\n", phandle->init_data); + for (i = 0; i < phandle->data_size[INIT_DATA]; i++) { + log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i, + &phandle->init_data[i], phandle->init_data[i]); + } +} + +void +dump_instance(fcode_env_t *env) +{ + int i; + instance_t *ihandle; + + ihandle = (instance_t *)POP(DS); + log_message(MSG_DEBUG, "Ihandle: %p\n", ihandle); + log_message(MSG_DEBUG, " Parent: (%8p) %p\n", + &ihandle->parent, ihandle->parent); + log_message(MSG_DEBUG, " Device: (%8p) %p\n", + &ihandle->device, ihandle->device); + log_message(MSG_DEBUG, " args: '%s'\n", + ((ihandle->my_args) ? ihandle->my_args : "")); + log_message(MSG_DEBUG, " my-space: %x\n", ihandle->my_space); + log_message(MSG_DEBUG, " my_addr :"); + for (i = 0; i < MAX_MY_ADDR; i++) + log_message(MSG_DEBUG, " %x", (int)ihandle->my_addr[i]); + log_message(MSG_DEBUG, "\n"); + log_message(MSG_DEBUG, " sizes: %d %d\n", + ihandle->device->data_size[INIT_DATA], + ihandle->device->data_size[UINIT_DATA]); + log_message(MSG_DEBUG, " data: (%8p) %x %x\n", + ihandle->data, ihandle->data[0], ihandle->data[1]); + if (ihandle->device->data_size[INIT_DATA]) { + log_message(MSG_DEBUG, " Initialised:\n"); + for (i = 0; i < ihandle->device->data_size[INIT_DATA]; i++) { + log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i, + &ihandle->data[INIT_DATA][i], + ihandle->data[INIT_DATA][i]); + } + } + if (ihandle->device->data_size[INIT_DATA]) { + log_message(MSG_DEBUG, " UnInitialised:\n"); + for (i = 0; i < ihandle->device->data_size[UINIT_DATA]; i++) { + log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i, + &ihandle->data[UINIT_DATA][i], + ihandle->data[UINIT_DATA][i]); + } + } +} + +#endif + +#pragma init(_init) + +#ifdef CONVERT_HANDLES +static device_t * +safe_convert_phandle(fcode_env_t *env, fstack_t d) +{ + return ((device_t *)d); +} + +static fstack_t +safe_revert_phandle(fcode_env_t *env, device_t *d) +{ + return ((fstack_t)d); +} + +static void +safe_allocate_phandle(fcode_env_t *env) +{ +} + +#endif + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + char *name = "/"; + device_t *d; + + ASSERT(env); + NOTICE; + +#ifdef CONVERT_HANDLES + env->convert_phandle = safe_convert_phandle; + env->revert_phandle = safe_revert_phandle; + env->allocate_phandle = safe_allocate_phandle; +#endif + + /* build the root node */ + d = create_phandle(env, NULL); + env->current_device = d; + env->root_node = d; + push_a_string(env, name); + device_name(env); + env->current_device = NULL; + + create_my_self(env); + create_my_space(env); + + P1275(0x102, 0, "my-address", my_address); + /* Fcode 0x103 "my-space" is created using create_internal_value */ + + P1275(0x11f, 0, "new-device", new_device); + + P1275(0x127, 0, "finish-device", finish_device); + + FCODE(0x129, 0, "push-package", push_package); + FCODE(0x12a, 0, "pop-package", pop_package); + FCODE(0x12b, 0, "interpose", interpose); + + P1275(0x202, 0, "my-args", my_args); + /* Fcode 0x203 "my-self" is created using create_internal_value */ + P1275(0x204, 0, "find-package", find_package); + P1275(0x205, 0, "open-package", open_package); + P1275(0x206, 0, "close-package", close_package); + P1275(0x207, 0, "find-method", find_method); + P1275(0x208, 0, "call-package", call_package); + P1275(0x209, 0, "$call-parent", dollar_call_parent); + P1275(0x20a, 0, "my-parent", my_parent); + P1275(0x20b, 0, "ihandle>phandle", ihandle_to_phandle); + + P1275(0x20d, 0, "my-unit", my_unit); + P1275(0x20e, 0, "$call-method", dollar_call_method); + P1275(0x20f, 0, "$open-package", dollar_open_package); + + P1275(0x23b, 0, "child", child_node); + P1275(0x23c, 0, "peer", peer_node); + + P1275(0x23f, 0, "set-args", set_args); + + FORTH(IMMEDIATE, "root-node", root_node); + FORTH(0, "current-device", current_device); + FORTH(0, "pwd$", pwd_dollar); + FORTH(IMMEDIATE, "pwd", pwd); + FORTH(IMMEDIATE, "ls", do_ls); + FORTH(IMMEDIATE, "(cd)", paren_cd); + FORTH(IMMEDIATE, "cd", do_cd); + FORTH(IMMEDIATE, "device-end", device_end); + FORTH(0, "select-dev", do_select_dev); + FORTH(0, "unselect-dev", do_unselect_dev); + FORTH(0, "begin-package", begin_package); + FORTH(0, "end-package", end_package); + FORTH(IMMEDIATE, "dump-device", dump_device); + FORTH(IMMEDIATE, "dump-instance", dump_instance); + FORTH(0, "exec-parent-method", exec_parent_method); +} diff --git a/usr/src/lib/efcode/engine/prims64.c b/usr/src/lib/efcode/engine/prims64.c new file mode 100644 index 0000000000..7a4f7fa9d1 --- /dev/null +++ b/usr/src/lib/efcode/engine/prims64.c @@ -0,0 +1,464 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcode/private.h> +#include <fcdriver/fcdriver.h> + +#define LF_PER_XF (sizeof (xforth_t)/sizeof (lforth_t)) +#define WF_PER_XF (sizeof (xforth_t)/sizeof (wforth_t)) + +void unaligned_xfetch(fcode_env_t *); +void unaligned_xstore(fcode_env_t *); +static void xbsplit(fcode_env_t *); + +xforth_t +pop_xforth(fcode_env_t *env) +{ + if (sizeof (xforth_t) == sizeof (fstack_t)) + return (POP(DS)); + return ((xforth_t)pop_double(env)); +} + +xforth_t +peek_xforth(fcode_env_t *env) +{ + xforth_t d; + + d = pop_xforth(env); + push_xforth(env, d); + return (d); +} + +void +push_xforth(fcode_env_t *env, xforth_t a) +{ + if (sizeof (xforth_t) == sizeof (fstack_t)) + PUSH(DS, a); + else + push_double(env, (dforth_t)a); +} + +/* + * bxjoin ( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o ) + */ +static void +bxjoin(fcode_env_t *env) +{ + union { + uchar_t b_bytes[sizeof (xforth_t)]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, sizeof (xforth_t), "bxjoin"); + for (i = 0; i < sizeof (xforth_t); i++) + b.b_bytes[i] = POP(DS); + push_xforth(env, b.b_xf); +} + +/* + * <l@ ( qaddr -- n ) + */ +static void +lsfetch(fcode_env_t *env) +{ + s_lforth_t *addr; + xforth_t a; + + CHECK_DEPTH(env, 1, "<l@"); + addr = (s_lforth_t *)POP(DS); + a = *addr; + push_xforth(env, a); +} + +/* + * lxjoin ( quad.lo quad.hi -- o ) + */ +static void +lxjoin(fcode_env_t *env) +{ + union { + lforth_t b_lf[LF_PER_XF]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, LF_PER_XF, "lxjoin"); + for (i = 0; i < LF_PER_XF; i++) + b.b_lf[i] = POP(DS); + push_xforth(env, b.b_xf); +} + +/* + * wxjoin ( w.lo w.2 w.3 w.hi -- o ) + */ +static void +wxjoin(fcode_env_t *env) +{ + union { + wforth_t b_wf[WF_PER_XF]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, WF_PER_XF, "wxjoin"); + for (i = 0; i < WF_PER_XF; i++) + b.b_wf[i] = POP(DS); + push_xforth(env, b.b_xf); +} + +/* + * x, ( o -- ) + */ +static void +xcomma(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "x,"); + DEBUGF(COMMA, dump_comma(env, "x,")); + PUSH(DS, (fstack_t)HERE); + unaligned_xstore(env); + set_here(env, HERE + sizeof (xforth_t), "xcomma"); +} + +/* + * x@ ( xaddr -- o ) + */ +void +xfetch(fcode_env_t *env) +{ + xforth_t *addr; + xforth_t a; + + CHECK_DEPTH(env, 1, "x@"); + addr = (xforth_t *)POP(DS); + a = *addr; + push_xforth(env, a); +} + +/* + * x! ( o xaddr -- ) + */ +void +xstore(fcode_env_t *env) +{ + xforth_t *addr; + xforth_t a; + + CHECK_DEPTH(env, 2, "x!"); + addr = (xforth_t *)POP(DS); + a = pop_xforth(env); + *addr = a; +} + +/* + * /x ( -- n ) + */ +static void +slash_x(fcode_env_t *env) +{ + PUSH(DS, sizeof (xforth_t)); +} + +/* + * /x* ( nu1 -- nu2 ) + */ +static void +slash_x_times(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "/x*"); + TOS *= sizeof (xforth_t); +} + +/* + * xa+ ( addr1 index -- addr2 ) + */ +static void +xa_plus(fcode_env_t *env) +{ + fstack_t index; + + CHECK_DEPTH(env, 2, "xa+"); + index = POP(DS); + TOS += index * sizeof (xforth_t); +} + +/* + * xa1+ ( addr1 -- addr2 ) + */ +static void +xa_one_plus(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "xa1+"); + TOS += sizeof (xforth_t); +} + +/* + * xbflip ( oct1 -- oct2 ) + */ +void +xbflip(fcode_env_t *env) +{ + union { + uchar_t b_bytes[sizeof (xforth_t)]; + xforth_t b_xf; + } b, c; + int i; + + CHECK_DEPTH(env, 1, "xbflip"); + b.b_xf = pop_xforth(env); + for (i = 0; i < sizeof (xforth_t); i++) + c.b_bytes[i] = b.b_bytes[(sizeof (xforth_t) - 1) - i]; + push_xforth(env, c.b_xf); +} + +void +unaligned_xfetch(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 1, "unaligned-x@"); + addr = POP(DS); + for (i = 0; i < sizeof (xforth_t); i++, addr++) { + PUSH(DS, addr); + cfetch(env); + } + bxjoin(env); + xbflip(env); +} + +void +unaligned_xstore(fcode_env_t *env) +{ + fstack_t addr; + int i; + + CHECK_DEPTH(env, 2, "unaligned-x!"); + addr = POP(DS); + xbsplit(env); + for (i = 0; i < sizeof (xforth_t); i++, addr++) { + PUSH(DS, addr); + cstore(env); + } +} + +/* + * xbflips ( xaddr len -- ) + */ +static void +xbflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "xbflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (xforth_t), + addr += sizeof (xforth_t)) { + PUSH(DS, addr); + unaligned_xfetch(env); + xbflip(env); + PUSH(DS, addr); + unaligned_xstore(env); + } +} + +/* + * xbsplit ( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi ) + */ +static void +xbsplit(fcode_env_t *env) +{ + union { + uchar_t b_bytes[sizeof (xforth_t)]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, 1, "xbsplit"); + b.b_xf = pop_xforth(env); + for (i = 0; i < sizeof (xforth_t); i++) + PUSH(DS, b.b_bytes[(sizeof (xforth_t) - 1) - i]); +} + +/* + * xlflip ( oct1 -- oct2 ) + */ +void +xlflip(fcode_env_t *env) +{ + union { + lforth_t b_lf[LF_PER_XF]; + xforth_t b_xf; + } b, c; + int i; + + CHECK_DEPTH(env, 1, "xlflip"); + b.b_xf = pop_xforth(env); + for (i = 0; i < LF_PER_XF; i++) + c.b_lf[i] = b.b_lf[(LF_PER_XF - 1) - i]; + push_xforth(env, c.b_xf); +} + +/* + * xlflips ( xaddr len -- ) + */ +static void +xlflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "xlflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (xforth_t), + addr += sizeof (xforth_t)) { + PUSH(DS, addr); + unaligned_xfetch(env); + xlflip(env); + PUSH(DS, addr); + unaligned_xstore(env); + } +} + +/* + * xlsplit ( o -- quad.lo quad.hi ) + */ +static void +xlsplit(fcode_env_t *env) +{ + union { + lforth_t b_lf[LF_PER_XF]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, 1, "xlsplit"); + b.b_xf = pop_xforth(env); + for (i = 0; i < LF_PER_XF; i++) + PUSH(DS, b.b_lf[(LF_PER_XF - 1) - i]); +} + + +/* + * xwflip ( oct1 -- oct2 ) + */ +static void +xwflip(fcode_env_t *env) +{ + union { + wforth_t b_wf[WF_PER_XF]; + xforth_t b_xf; + } b, c; + int i; + + CHECK_DEPTH(env, 1, "xwflip"); + b.b_xf = pop_xforth(env); + for (i = 0; i < WF_PER_XF; i++) + c.b_wf[i] = b.b_wf[(WF_PER_XF - 1) - i]; + push_xforth(env, c.b_xf); +} + +/* + * xwflips ( xaddr len -- ) + */ +static void +xwflips(fcode_env_t *env) +{ + fstack_t len, addr; + int i; + + CHECK_DEPTH(env, 2, "xwflips"); + len = POP(DS); + addr = POP(DS); + for (i = 0; i < len; i += sizeof (xforth_t), + addr += sizeof (xforth_t)) { + PUSH(DS, addr); + unaligned_xfetch(env); + xwflip(env); + PUSH(DS, addr); + unaligned_xstore(env); + } +} + +/* + * xwsplit ( o -- w.lo w.2 w.3 w.hi ) + */ +static void +xwsplit(fcode_env_t *env) +{ + union { + wforth_t b_wf[WF_PER_XF]; + xforth_t b_xf; + } b; + int i; + + CHECK_DEPTH(env, 1, "xwsplit"); + b.b_xf = pop_xforth(env); + for (i = 0; i < WF_PER_XF; i++) + PUSH(DS, b.b_wf[(WF_PER_XF - 1) - i]); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + P1275(0x241, 0, "bxjoin", bxjoin); + P1275(0x242, 0, "<l@", lsfetch); + P1275(0x243, 0, "lxjoin", lxjoin); + P1275(0x244, 0, "wxjoin", wxjoin); + P1275(0x245, 0, "x,", xcomma); + P1275(0x246, 0, "x@", xfetch); + P1275(0x247, 0, "x!", xstore); + P1275(0x248, 0, "/x", slash_x); + P1275(0x249, 0, "/x*", slash_x_times); + P1275(0x24a, 0, "xa+", xa_plus); + P1275(0x24b, 0, "xa1+", xa_one_plus); + P1275(0x24c, 0, "xbflip", xbflip); + P1275(0x24d, 0, "xbflips", xbflips); + P1275(0x24e, 0, "xbsplit", xbsplit); + P1275(0x24f, 0, "xlflip", xlflip); + P1275(0x250, 0, "xlflips", xlflips); + P1275(0x251, 0, "xlsplit", xlsplit); + P1275(0x252, 0, "xwflip", xwflip); + P1275(0x253, 0, "xwflips", xwflips); + P1275(0x254, 0, "xwsplit", xwsplit); + + FORTH(0, "unaligned-x@", unaligned_xfetch); + FORTH(0, "unaligned-x!", unaligned_xstore); +} diff --git a/usr/src/lib/efcode/engine/print.c b/usr/src/lib/efcode/engine/print.c new file mode 100644 index 0000000000..0db6d6bf49 --- /dev/null +++ b/usr/src/lib/efcode/engine/print.c @@ -0,0 +1,265 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcode/private.h> + +#define DIGIT(x) (((x) > 9) ? ((x) + 'a' - 10) : ((x) + '0')) + +void +to_digit(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, ">digit"); + TOS = DIGIT(TOS); +} + +void +pic_hold(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "hold"); + *(--env->picturebufpos) = (char) POP(DS); +} + +void +pic_start(fcode_env_t *env) +{ + env->picturebufpos = env->picturebuf + env->picturebuflen - 1; + *env->picturebufpos = 0; +} + +void +pic_ustop(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "u#>"); + (void) POP(DS); + push_string(env, env->picturebufpos, strlen(env->picturebufpos)); +} + +void +pic_unsigned(fcode_env_t *env) +{ + ufstack_t a, b; + + CHECK_DEPTH(env, 1, "u#"); + a = (ufstack_t) TOS; + b = a % env->num_base; + TOS = (fstack_t) (a / env->num_base); + *(--env->picturebufpos) = DIGIT(b); +} + +void +pic_sign(fcode_env_t *env) +{ + fstack_t s; + + CHECK_DEPTH(env, 1, "sign"); + s = POP(DS); + if (s < 0) { + PUSH(DS, '-'); + pic_hold(env); + } +} + +static void +pic_uremainder(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "u#s"); + do { + pic_unsigned(env); + } while (TOS); +} + +void +format_number(fcode_env_t *env, int neg, int width) +{ + pic_start(env); + if (width == 0) { + PUSH(DS, ' '); + pic_hold(env); + } + pic_uremainder(env); + if (env->num_base == 10 && neg) { + PUSH(DS, '-'); + pic_hold(env); + } + width -= strlen(env->picturebufpos); + while (width > 0) { + PUSH(DS, ' '); + pic_hold(env); + width--; + } + pic_ustop(env); +} + +static void +convert_num(fcode_env_t *env) +{ + int n; + + CHECK_DEPTH(env, 1, "(.)"); + n = 0; + if (env->num_base == 10 && TOS < 0) { + TOS = -TOS; + n = 1; + } + format_number(env, n, 0); +} + +void +do_dot_r(fcode_env_t *env) +{ + int w, n; + + CHECK_DEPTH(env, 2, ".r"); + n = 0; + w = (int) POP(DS); + if (env->num_base == 10 && TOS < 0) { + TOS = -TOS; + n = 1; + } + format_number(env, n, w); + type(env); +} + +void +do_udot_r(fcode_env_t *env) +{ + int w; + + CHECK_DEPTH(env, 2, "u.r"); + w = (int) POP(DS); + format_number(env, 0, w); + type(env); +} + +void +do_dot(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "."); + PUSH(DS, 0); + do_dot_r(env); +} + +void +do_dot_d(fcode_env_t *env) +{ + int base; + + CHECK_DEPTH(env, 1, ".d"); + base = env->num_base; + env->num_base = 10; + do_dot(env); + env->num_base = base; +} + +void +do_dot_x(fcode_env_t *env) +{ + int base; + + CHECK_DEPTH(env, 1, ".x"); + base = env->num_base; + env->num_base = 16; + do_dot(env); + env->num_base = base; +} + +void +do_udot(fcode_env_t *env) +{ + CHECK_DEPTH(env, 1, "u."); + PUSH(DS, 0); + do_udot_r(env); +} + +void +pic_dunsigned(fcode_env_t *env) +{ + ufstack_t b; + u_dforth_t a; + + CHECK_DEPTH(env, 2, "#"); + a = pop_double(env); + b = a % env->num_base; + a /= env->num_base; + push_double(env, a); + *(--env->picturebufpos) = DIGIT(b); +} + +void +pic_dremainder(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "#s"); + do { + pic_dunsigned(env); + } while (peek_double(env)); +} + +void +pic_dstop(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "#>"); + (void) pop_double(env); + push_string(env, env->picturebufpos, strlen(env->picturebufpos)); +} + + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + ASSERT(env); + NOTICE; + + env->picturebuflen = 0x100; + env->picturebuf = MALLOC(env->picturebuflen); + + ANSI(0x095, 0, "hold", pic_hold); + ANSI(0x096, 0, "<#", pic_start); + ANSI(0x097, 0, "u#>", pic_ustop); + ANSI(0x098, 0, "sign", pic_sign); + ANSI(0x099, 0, "u#", pic_unsigned); + ANSI(0x09a, 0, "u#s", pic_uremainder); + ANSI(0x09b, 0, "u.", do_udot); + P1275(0x09c, 0, "u.r", do_udot_r); + P1275(0x09d, 0, ".", do_dot); + ANSI(0x09e, 0, ".r", do_dot_r); + + ANSI(0x0c7, 0, "#", pic_dunsigned); + ANSI(0x0c8, 0, "#s", pic_dremainder); + ANSI(0x0c9, 0, "#>", pic_dstop); + + FORTH(0, ">digit", to_digit); + FORTH(0, "(.)", convert_num); + FORTH(0, ".d", do_dot_d); + FORTH(0, ".x", do_dot_x); +} diff --git a/usr/src/lib/efcode/engine/properties.c b/usr/src/lib/efcode/engine/properties.c new file mode 100644 index 0000000000..ff14c1f03c --- /dev/null +++ b/usr/src/lib/efcode/engine/properties.c @@ -0,0 +1,808 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +void +create_prop(fcode_env_t *env, char *name) +{ + push_a_string(env, name); + property(env); +} + +void +create_int_prop(fcode_env_t *env, char *name, int val) +{ + PUSH(DS, val); + encode_int(env); + create_prop(env, name); +} + +void +create_string_prop(fcode_env_t *env, char *name, char *val) +{ + push_a_string(env, val); + encode_string(env); + create_prop(env, name); +} + +static int +addr_cmp(void *a, void *b) +{ + return ((uchar_t *)a == (uchar_t *)b); +} + +static void * +add_property_buffer(fcode_env_t *env, int len) +{ + void *data = MALLOC(len+1); + return (add_resource(&env->propbufs, data, addr_cmp)); +} + +static void +free_property_buffer(fcode_env_t *env, void *buffer) +{ + free_resource(&env->propbufs, buffer, addr_cmp); + FREE(buffer); +} + +/* + * Golden Rule: + * DO NOT cache the value of the head of the property list *before* + * looking up a property. + * This routine is also responsible for purging dead properties + * and that *can* affect the head pointer. + * you have been warned! + */ +prop_t * +find_property(device_t *d, char *name) +{ + prop_t *p = d->properties, *prev; + prop_t *found = NULL; + + prev = NULL; + while (p && !found) { + if (p->name) { + if (strcmp(name, p->name) == 0) { + found = p; + } + prev = p; + p = p->next; + } else { + prop_t *dead; + + if (prev) + prev->next = p->next; + else { + /* last prop in chain */ + d->properties = p->next; + } + dead = p; + p = p->next; + FREE(dead->name); + FREE(dead->data); + FREE(dead); + } + } + return (found); +} + +static prop_t * +stack_find_property(fcode_env_t *env, device_t *d) +{ + char *propname; + + propname = pop_a_string(env, NULL); + return (find_property(d, propname)); +} + +void +property(fcode_env_t *env) +{ + int datalen; + char *propname, *srcptr; + prop_t *p; + device_t *d; + + CHECK_DEPTH(env, 4, "property"); + if (MYSELF) { + d = MYSELF->device; + } else { + d = env->current_device; + if (!d) { + void *buffer; + + two_drop(env); + if ((buffer = pop_a_string(env, NULL)) != NULL) + free_property_buffer(env, buffer); + return; + } + } + propname = pop_a_string(env, NULL); + p = find_property(d, propname); + if (p == NULL) { + p = MALLOC(sizeof (prop_t)); + p->next = d->properties; + d->properties = p; + p->name = STRDUP(propname); + } else if (p->data) + FREE(p->data); /* release old resources */ + srcptr = pop_a_string(env, &datalen); + p->data = MALLOC(datalen+1); + p->size = datalen; + memcpy(p->data, srcptr, datalen); + p->data[datalen] = 0; + if (srcptr) + free_property_buffer(env, srcptr); +} + +prop_t * +lookup_package_property(fcode_env_t *env, char *propname, device_t *d) +{ + prop_t *p; + + p = find_property(d, propname); + if (p) { + return (p); + } + if (d->vectors.get_package_prop) { + static prop_t sp; + fstack_t fail, n; + + /* recreate the FORTH environment for the remote call */ + push_a_string(env, propname); + REVERT_PHANDLE(env, n, d); + PUSH(DS, n); + d->vectors.get_package_prop(env); + fail = POP(DS); + if (fail) + return (NULL); + sp.size = POP(DS); + sp.data = (uchar_t *)POP(DS); + sp.name = propname; + sp.next = NULL; + return (&sp); + } + return (NULL); +} + +void +get_package_property(fcode_env_t *env) +{ + prop_t *p; + device_t *d; + char *propname; + + CHECK_DEPTH(env, 3, "get-package-property"); + CONVERT_PHANDLE(env, d, POP(DS)); + propname = pop_a_string(env, NULL); + p = lookup_package_property(env, propname, d); + if (p) { + PUSH(DS, (fstack_t)p->data); + PUSH(DS, p->size); + PUSH(DS, FALSE); + } else + PUSH(DS, TRUE); +} + +void +get_inherited_prop(fcode_env_t *env) +{ + instance_t *ih; + device_t *dev; + prop_t *prop; + char *pname; + int plen; + + /* + * First, we look thru the in-memory device tree for the property. + * If we don't find it, we call get_inherited_prop, which "knows" it's + * not going to find the property below the attachment point. + */ + + CHECK_DEPTH(env, 2, "get-inherited-property"); + pname = pop_a_string(env, &plen); + ih = MYSELF; + if (ih) { + for (; ih; ih = ih->parent) { + dev = ih->device; + prop = find_property(dev, pname); + if (prop) { + PUSH(DS, (fstack_t)prop->data); + PUSH(DS, (fstack_t)prop->size); + PUSH(DS, FALSE); + return; + } + } + if (dev->vectors.get_inherited_prop) { + push_a_string(env, pname); + dev->vectors.get_inherited_prop(env); + return; + } + } + PUSH(DS, TRUE); +} + +void +delete_property(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "delete-property"); + if (MYSELF) { + prop_t *p; + + p = stack_find_property(env, MYSELF->device); + if (p) { + /* + * write the name as NULL; the space will be free'd + * the next time a property lookup passes this node + */ + p->name = NULL; + } + } else { + two_drop(env); + } +} + +void +get_my_property(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "get-my-property"); + PUSH(DS, (fstack_t)MYSELF); + ihandle_to_phandle(env); + get_package_property(env); +} + +void +encode_string(fcode_env_t *env) +{ + char *str; + char *prop; + int len; + + CHECK_DEPTH(env, 2, "encode-string"); + str = pop_a_string(env, &len); + + prop = add_property_buffer(env, len); + memcpy(prop, str, len); + prop[len] = 0; + PUSH(DS, (fstack_t)prop); + PUSH(DS, len + 1); +} + +void +encode_int(fcode_env_t *env) +{ + uchar_t *ptr; + uint32_t p; + + CHECK_DEPTH(env, 1, "encode-int"); + p = POP(DS); + ptr = add_property_buffer(env, sizeof (uint32_t)); + + memcpy(ptr, (char *)&p, sizeof (uint32_t)); + PUSH(DS, (fstack_t)ptr); + PUSH(DS, sizeof (uint32_t)); +} + +void +encode_phys(fcode_env_t *env) +{ + uint_t ncells; + + ncells = get_number_of_parent_address_cells(env); + CHECK_DEPTH(env, ncells, "encode-phys"); + encode_int(env); + while (--ncells) { + rot(env); + encode_int(env); + encode_plus(env); + } +} + +static fstack_t +get_decoded_int(uchar_t *dp) +{ + uint32_t d; + + memcpy((char *)&d, dp, sizeof (uint32_t)); + return (d); +} + +int +get_default_intprop(fcode_env_t *env, char *name, device_t *d, int def) +{ + prop_t *p; + + if (!d) /* Kludge for testing */ + return (def); + p = lookup_package_property(env, name, d); + if (p == NULL) + return (def); + return (get_decoded_int(p->data)); +} + +int +get_num_addr_cells(fcode_env_t *env, device_t *d) +{ + return (get_default_intprop(env, "#address-cells", d, 2)); +} + +int +get_num_size_cells(fcode_env_t *env, device_t *d) +{ + return (get_default_intprop(env, "#size-cells", d, 1)); +} + +void +decode_phys(fcode_env_t *env) +{ + char *ptr; + int len; + int adr_cells; + int offset; + + CHECK_DEPTH(env, 2, "decode-phys"); + ptr = pop_a_string(env, &len); + + adr_cells = get_num_addr_cells(env, env->current_device->parent); + + offset = sizeof (uint32_t) * adr_cells; + + PUSH(DS, (fstack_t)(ptr + offset)); + PUSH(DS, len + offset); + + while (adr_cells--) { + fstack_t d; + offset -= sizeof (uint32_t); + d = get_decoded_int((uchar_t *)(ptr + offset)); + PUSH(DS, d); + } +} + +/* + * 'reg' Fcode 0x116 + */ +void +reg_prop(fcode_env_t *env) +{ + fstack_t size; + + CHECK_DEPTH(env, 1, "reg"); + size = POP(DS); + encode_phys(env); + PUSH(DS, size); + encode_int(env); + encode_plus(env); + create_prop(env, "reg"); +} + +void +encode_bytes(fcode_env_t *env) +{ + char *str; + char *prop; + int len; + + CHECK_DEPTH(env, 2, "encode-bytes"); + str = pop_a_string(env, &len); + prop = add_property_buffer(env, len); + memcpy(prop, str, len); + prop[len] = 0; + PUSH(DS, (fstack_t)prop); + PUSH(DS, len); +} + +void +decode_int(fcode_env_t *env) +{ + char *dp; + fstack_t d; + int len; + + CHECK_DEPTH(env, 2, "decode-int"); + dp = pop_a_string(env, &len); + PUSH(DS, (fstack_t)(dp + sizeof (uint32_t))); + PUSH(DS, len - sizeof (uint32_t)); + d = get_decoded_int((uchar_t *)dp); + PUSH(DS, d); +} + +void +decode_string(fcode_env_t *env) +{ + int plen, len; + char *dp; + + CHECK_DEPTH(env, 2, "decode-string"); + dp = pop_a_string(env, &plen); + len = strlen(dp) + 1; + PUSH(DS, (fstack_t)(dp + len)); + PUSH(DS, plen - len); + PUSH(DS, (fstack_t)dp); + PUSH(DS, len - 1); +} + +void +encode_plus(fcode_env_t *env) +{ + int len1, len2; + char *src1, *src2; + uchar_t *new; + + CHECK_DEPTH(env, 4, "encode+"); + src1 = pop_a_string(env, &len1); + src2 = pop_a_string(env, &len2); + new = add_property_buffer(env, len1 + len2); + if (src2) { + memcpy(new, src2, len2); + free_property_buffer(env, src2); + } + if (src1) { + memcpy(new + len2, src1, len1); + free_property_buffer(env, src1); + } + PUSH(DS, (fstack_t)new); + PUSH(DS, len1 + len2); +} + +static void +make_special_property(fcode_env_t *env, char *name) +{ + push_a_string(env, name); + property(env); +} + +void +device_name(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "device-name"); + encode_string(env); + make_special_property(env, "name"); +} + +void +model_prop(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "model"); + encode_string(env); + make_special_property(env, "model"); +} + +void +device_type(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "device-type"); + encode_string(env); + make_special_property(env, "device_type"); +} + +/* + * 'next-property' Fcode implementation. + */ +void +next_property(fcode_env_t *env) +{ + device_t *phandle; + char *previous; + prop_t *p; + + CHECK_DEPTH(env, 3, "next-property"); + phandle = (device_t *)POP(DS); + previous = pop_a_string(env, NULL); + p = phandle->properties; + if (previous == NULL) + p = phandle->properties; + else if (p = find_property(phandle, previous)) + p = p->next; + + for (; p != NULL && p->name == NULL; p = p->next) + ; + + if (p) + push_a_string(env, p->name); + else + push_a_string(env, ""); + PUSH(DS, TRUE); +} + +void +get_property(fcode_env_t *env) +{ + if (MYSELF) + get_my_property(env); + else if (env->current_device) { + fstack_t d; + + REVERT_PHANDLE(env, d, env->current_device); + PUSH(DS, d); + get_package_property(env); + } else { + two_drop(env); + log_message(MSG_WARN, "No device context\n"); + } +} + +#ifdef DEBUG + +static void +print_indented(char *name) +{ + log_message(MSG_INFO, "%-28s", name); +} + +static void +print_string(fcode_env_t *env, uchar_t *data, int len) +{ + while (len > 0) { + int nlen = (strlen((char *)data)+1); + log_message(MSG_INFO, "%s\n", data); + len -= nlen; + data += nlen; + if (len > 0) + print_indented(""); + } +} + +static void +print_ints(uchar_t *data, int len, int crlf) +{ + uint32_t d; + + while (len--) { + d = get_decoded_int(data); + log_message(MSG_INFO, "%8.8lx ", d); + data += sizeof (uint32_t); + } + if (crlf) + log_message(MSG_INFO, "\n"); +} + +static void +print_integer(fcode_env_t *env, uchar_t *data, int len) +{ + print_ints(data, len/sizeof (uint32_t), 1); +} + +static void +print_bytes(fcode_env_t *env, uchar_t *data, int len) +{ + while (len--) { + log_message(MSG_INFO, "%2.2x ", *data++); + } + log_message(MSG_INFO, "\n"); +} + +static void +print_bytes_indented(fcode_env_t *env, uchar_t *data, int len) +{ + int nbytes; + + for (; ; ) { + nbytes = min(len, 16); + print_bytes(env, data, nbytes); + len -= nbytes; + data += nbytes; + if (len == 0) + break; + print_indented(""); + } +} + +static void +print_reg(fcode_env_t *env, uchar_t *data, int len) +{ + int pcells, nlen; + + if (env->current_device != NULL && + env->current_device->parent != NULL) { + pcells = get_num_size_cells(env, env->current_device->parent); + pcells += get_num_addr_cells(env, env->current_device->parent); + nlen = pcells*sizeof (uint32_t); + while (len > 0) { + print_ints(data, pcells, 1); + len -= nlen; + data += nlen; + if (len > 0) + print_indented(""); + } + } else + print_bytes_indented(env, data, len); +} + +static void +print_imap(fcode_env_t *env, uchar_t *dp, int len) +{ + int n, icells; + + if (env->current_device == NULL) { + print_bytes_indented(env, dp, len); + return; + } + n = get_num_addr_cells(env, env->current_device); + + while (len) { + int offset; + fstack_t data; + device_t *node; + + offset = 0; + data = get_decoded_int(dp+((n+1)*sizeof (uint32_t))); + CONVERT_PHANDLE(env, node, data); + offset += (n+2)*sizeof (uint32_t); + print_ints(dp, (n+2), 0); + icells = get_default_intprop(env, "#interrupt-cells", node, 1); + print_ints(dp+offset, icells, 1); + offset += icells*sizeof (uint32_t); + dp += offset; + len -= offset; + if (len) + print_indented(""); + } +} + +static void +print_ranges(fcode_env_t *env, uchar_t *data, int len) +{ + int pcells, nlen; + + if (env->current_device != NULL && + env->current_device->parent != NULL) { + pcells = get_num_addr_cells(env, env->current_device); + pcells += get_num_addr_cells(env, env->current_device->parent); + pcells += get_num_size_cells(env, env->current_device); + nlen = pcells*sizeof (uint32_t); + while (len > 0) { + print_ints(data, pcells, 1); + len -= nlen; + data += nlen; + if (len > 0) + print_indented(""); + } + } else + print_bytes_indented(env, data, len); +} + +typedef struct MAGIC_PROP { + char *name; + void (*fn)(fcode_env_t *env, uchar_t *data, int len); +} magic_prop_t; + +static magic_prop_t magic_props[] = { + { "name", print_string }, + { "device_type", print_string }, + { "model", print_string }, + { "reg", print_reg }, + { "assigned-addresses", print_reg }, + { "interrupt-map", print_imap }, + { "#interrupt-cells", print_integer }, + { "interrupt-map-mask", print_integer }, + { "#size-cells", print_integer }, + { "#address-cells", print_integer }, + { "ranges", print_ranges }, + { "device-id", print_integer }, + { "vendor-id", print_integer }, + { "class-code", print_integer }, + { "compatible", print_string }, + { "version", print_string }, + { "manufacturer", print_string }, + { NULL, NULL } +}; + +static void +print_content(fcode_env_t *env, char *prop, uchar_t *data, int len) +{ + magic_prop_t *p; + + for (p = magic_props; p->name; p++) + if (strcmp(prop, p->name) == 0) { + (*p->fn)(env, data, len); + return; + } + print_bytes_indented(env, data, len); +} + +void +print_property(fcode_env_t *env, prop_t *p, char *prepend) +{ + char buf[40]; + char *name = (p->name ? p->name : "<noname>"); + + if (prepend) { + sprintf(buf, "%s %s", prepend, name); + name = buf; + } + print_indented(name); + if (p->name) + print_content(env, p->name, p->data, p->size); + else + print_bytes_indented(env, p->data, p->size); +} + +void +dot_properties(fcode_env_t *env) +{ + prop_t *p; + instance_t *omyself; + + omyself = MYSELF; + MYSELF = NULL; + + if (env->current_device) { + for (p = env->current_device->properties; p; p = p->next) + print_property(env, p, NULL); + } else { + log_message(MSG_INFO, "No device context\n"); + } + MYSELF = omyself; +} + +#endif + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + P1275(0x110, 0, "property", property); + P1275(0x111, 0, "encode-int", encode_int); + P1275(0x112, 0, "encode+", encode_plus); + P1275(0x113, 0, "encode-phys", encode_phys); + P1275(0x114, 0, "encode-string", encode_string); + P1275(0x115, 0, "encode-bytes", encode_bytes); + P1275(0x116, 0, "reg", reg_prop); + FCODE(0x117, 0, "intr", fc_obsolete); + FCODE(0x118, 0, "driver", fc_historical); + P1275(0x119, 0, "model", model_prop); + P1275(0x11a, 0, "device-type", device_type); + + P1275(0x128, 0, "decode-phys", decode_phys); + + P1275(0x201, 0, "device-name", device_name); + + P1275(0x21a, 0, "get-my-property", get_my_property); + P1275(0x21b, 0, "decode-int", decode_int); + P1275(0x21c, 0, "decode-string", decode_string); + P1275(0x21d, 0, "get-inherited-property", get_inherited_prop); + P1275(0x21e, 0, "delete-property", delete_property); + P1275(0x21f, 0, "get-package-property", get_package_property); + + P1275(0x23d, 0, "next-property", next_property); + + FORTH(0, "get-property", get_property); + FORTH(0, ".properties", dot_properties); +} diff --git a/usr/src/lib/efcode/engine/resource.c b/usr/src/lib/efcode/engine/resource.c new file mode 100644 index 0000000000..5ede6eea74 --- /dev/null +++ b/usr/src/lib/efcode/engine/resource.c @@ -0,0 +1,134 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +fc_resource_t * +find_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *)) +{ + fc_resource_t *f, *prev, *r = *head; + + f = NULL; + prev = NULL; + while (r) { + if (r->data == NULL) { + fc_resource_t *dead; + + if (prev) + prev->next = r->next; + else { + *head = r->next; + } + dead = r; + r = r->next; + FREE(dead); + } else { + if (cmp(ptr, r->data)) { + f = r; + break; + } + prev = r; + r = r->next; + } + } + return (f); +} + +void * +add_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *)) +{ + fc_resource_t *r; + + r = find_resource(head, ptr, cmp); + if (r == NULL) { + r = MALLOC(sizeof (fc_resource_t)); + r->data = ptr; + r->next = *head; + *head = r; + return (r->data); + } + log_message(MSG_ERROR, "add_resource: Duplicate entry: %p\n", ptr); + return (NULL); +} + +void +free_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *)) +{ + fc_resource_t *r; + + if ((r = find_resource(head, ptr, cmp)) != NULL) + r->data = NULL; + else + log_message(MSG_ERROR, "free_resource: No such Entry: %p\n", + ptr); +} + +#ifdef DEBUG + +static int +dump_print(void *s, void *d) +{ + log_message(MSG_DEBUG, "Buffer: %p\n", d); + return (0); +} + +void +dump_resources(fcode_env_t *env) +{ + fc_resource_t **head; + + head = (fc_resource_t **) POP(DS); + (void) find_resource(head, NULL, dump_print); +} + +void +propbufs(fcode_env_t *env) +{ + PUSH(DS, (fstack_t) &env->propbufs); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + NOTICE; + ASSERT(env); + + FORTH(0, "propbufs", propbufs); + FORTH(0, "dump-resource", dump_resources); +} + +#endif diff --git a/usr/src/lib/efcode/engine/signal.c b/usr/src/lib/efcode/engine/signal.c new file mode 100644 index 0000000000..a023bfd857 --- /dev/null +++ b/usr/src/lib/efcode/engine/signal.c @@ -0,0 +1,91 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> + +#include <sys/time.h> +#include <sys/termio.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +static fcode_env_t *saved_envp; +static struct termio saved_termio; + +static void +process_signal(int sig, siginfo_t *sip, void *addr) +{ + /* + * Format appropriate error message, want fault addr if Bus Error + * or Segmentation Violation. + */ + switch (sig) { + case SIGSEGV: + case SIGBUS: + case SIGILL: + case SIGFPE: + forth_abort(saved_envp, "%s: Fault Addr: 0x%08x", + strsignal(sig), sip->si_addr); + + case SIGQUIT: + ioctl(fileno(stdin), TCSETA, &saved_termio); + log_message(MSG_FATAL, "SIGQUIT\n"); + abort(); + + case SIGINT: + ioctl(fileno(stdin), TCSETA, &saved_termio); + break; + } + forth_abort(saved_envp, strsignal(sig)); +} + +void +install_handlers(fcode_env_t *env) +{ + struct sigaction sa; + + saved_envp = env; + + ioctl(fileno(stdin), TCGETA, &saved_termio); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO|SA_NODEFER; + sa.sa_handler = 0; + sa.sa_sigaction = process_signal; + + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); +} diff --git a/usr/src/lib/efcode/engine/sparcv9/Makefile b/usr/src/lib/efcode/engine/sparcv9/Makefile new file mode 100644 index 0000000000..af568ee0b3 --- /dev/null +++ b/usr/src/lib/efcode/engine/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +sparcv9_C_PICFLAGS = -KPIC + +install: all $(ROOTLIBS64) diff --git a/usr/src/lib/efcode/engine/tracing.c b/usr/src/lib/efcode/engine/tracing.c new file mode 100644 index 0000000000..43ade86faa --- /dev/null +++ b/usr/src/lib/efcode/engine/tracing.c @@ -0,0 +1,223 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <dlfcn.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#ifdef DEBUG + +static void (*trace_fn)(fcode_env_t *); + +void +set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *)) +{ + trace_fn = tracer; +} + +void +set_level(long lvl) +{ + long debug; + + debug = get_interpreter_debug_level(); + set_interpreter_debug_level(debug | lvl); +} + +void +unset_level(long lvl) +{ + long debug; + + debug = get_interpreter_debug_level(); + set_interpreter_debug_level(debug & ~lvl); +} + +void +enable_trace(fcode_env_t *env) +{ + set_level(DEBUG_TRACING); +} + +void +enable_stack_trace(fcode_env_t *env) +{ + set_level(DEBUG_TRACE_STACK); +} + +void +disable_stack_trace(fcode_env_t *env) +{ + unset_level(DEBUG_TRACE_STACK); +} + +void +disable_trace(fcode_env_t *env) +{ + unset_level(DEBUG_TRACING); +} + +void +call_trace(fcode_env_t *env) +{ + set_level(DEBUG_CALL_METHOD); +} + +void +no_call_trace(fcode_env_t *env) +{ + unset_level(DEBUG_CALL_METHOD); +} + +void +do_fclib_trace(fcode_env_t *env, void *fn) +{ + void *address; + Dl_info dlip; + static char buf[80]; + + if (dladdr((void *) fn, &dlip)) { + int offset; + + address = dlsym(RTLD_DEFAULT, dlip.dli_sname); + offset = ((char *) fn) - ((char *) address); + if (offset == 0) { + log_message(MSG_FC_DEBUG, "%s: tracing %s()\n", + dlip.dli_fname, dlip.dli_sname); + } else { + log_message(MSG_FC_DEBUG, "%s: tracing %s%s0x%x()\n", + dlip.dli_fname, dlip.dli_sname, + ((offset < 0) ? "-" : "+"), + ((offset < 0) ? -offset : offset)); + } + } else { + log_message(MSG_FC_DEBUG, "do_fclib_trace: <Unknown> %p\n", fn); + } + if (trace_fn) + trace_fn(env); +} + +void +output_step_message(fcode_env_t *env) +{ + log_message(MSG_INFO, "Step keys: <space>, Continue, Forth, Go," + " Help, Step, Quit\n"); +} + +void +enable_step(fcode_env_t *env) +{ + output_step_message(env); + set_level(DEBUG_STEPPING); +} + + +void +disable_step(fcode_env_t *env) +{ + unset_level(DEBUG_STEPPING); +} + +/* + * Output of state info is done elsewhere + */ +int +do_fclib_step(fcode_env_t *env) +{ + int c; + fcode_env_t *new_env; + + for (; ; ) { + c = getchar(); + if (c != '\n') { + while (getchar() != '\n') + ; + } + switch (c) { + case EOF: + case 'q': + unbug(env); + IP = 0; + return (1); + + case 'c': + debug_set_level(env, + DEBUG_EXEC_TRACE|DEBUG_EXEC_DUMP_DS); + break; + + case 'g': + unbug(env); + break; + + case 'f': + unset_level(DEBUG_STEPPING); + new_env = clone_environment(env, NULL); + do_interact(new_env); + destroy_environment(new_env); + set_level(DEBUG_STEPPING); + continue; + + case ' ': + case '\n': + break; + + case 'd': /* Unimplemented */ + case 'u': /* Unimplemented */ + default: + output_step_message(env); + continue; + } + break; + } + return (0); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + + FORTH(0, "stack-trace", enable_stack_trace); + FORTH(0, "no-stack-trace", disable_stack_trace); + FORTH(0, "trace-on", enable_trace); + FORTH(0, "trace-off", disable_trace); + FORTH(0, "call-trace", call_trace); + FORTH(0, "no-call-trace", no_call_trace); + FORTH(0, "step-on", enable_step); + FORTH(0, "step-off", disable_step); +} + +#endif diff --git a/usr/src/lib/efcode/extend/Makefile b/usr/src/lib/efcode/extend/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/extend/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/extend/Makefile.com b/usr/src/lib/efcode/extend/Makefile.com new file mode 100644 index 0000000000..7b25d08906 --- /dev/null +++ b/usr/src/lib/efcode/extend/Makefile.com @@ -0,0 +1,38 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = fthread.o +LIBRARY = fcthread.a + +include ../../Makefile.efcode + +# +# One of our symbols, `env', comes from the fcode interpreter itself, +# so turn off symbol checking. Yuck. +# +ZDEFS = diff --git a/usr/src/lib/efcode/extend/fthread.c b/usr/src/lib/efcode/extend/fthread.c new file mode 100644 index 0000000000..4c2c698a4e --- /dev/null +++ b/usr/src/lib/efcode/extend/fthread.c @@ -0,0 +1,96 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <fcode/private.h> +#include <fcode/log.h> + +static int envp; +static int envc; +static fcode_env_t *envs[4]; + +static void +do_clone(fcode_env_t *cenv) +{ + fcode_env_t *new; + + if (envc < 4) { + envs[envc] = env; + envc++; + new = clone_environment(cenv, NULL); + if (new) { + envs[envc] = new; + env = new; + return; + } + } + system_message(cenv, "clone failed"); +} + +static void +do_switch(fcode_env_t *cenv) +{ + int bail = 4; + do { + envp = (envp+1)%4; + env = envs[envp]; + bail--; + } while ((env == NULL) && (!bail)); + log_message(MSG_INFO, "Env: %x\n", env); +} + +static void +do_release(fcode_env_t *cenv) +{ + int bail = 4; + destroy_environment(envs[envp]); + envs[envp] = NULL; + do { + envp = (envp+1)%4; + env = envs[envp]; + bail--; + } while ((env == NULL) && (!bail)); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + envp = 0; + envc = 0; + + FORTH(0, "clone", do_clone); + FORTH(0, "switch", do_switch); + FORTH(0, "release", do_release); +} diff --git a/usr/src/lib/efcode/extend/sparcv9/Makefile b/usr/src/lib/efcode/extend/sparcv9/Makefile new file mode 100644 index 0000000000..1c13ef5f37 --- /dev/null +++ b/usr/src/lib/efcode/extend/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) + +install: all $(ROOTLIBS64) diff --git a/usr/src/lib/efcode/fcdriver/Makefile b/usr/src/lib/efcode/fcdriver/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/fcdriver/Makefile.com b/usr/src/lib/efcode/fcdriver/Makefile.com new file mode 100644 index 0000000000..48cbb283fb --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/Makefile.com @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = ioctl.o misc.o dma.o property.o fcdebug.o phandle.o build_tree.o \ + load_node.o upload.o get_req.o +LIBRARY = fcdriver.a + +include ../../Makefile.efcode diff --git a/usr/src/lib/efcode/fcdriver/build_tree.c b/usr/src/lib/efcode/fcdriver/build_tree.c new file mode 100644 index 0000000000..9abcbe9fbc --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/build_tree.c @@ -0,0 +1,250 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> +#include <fcntl.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static fc_phandle_t +fc_nodeop(common_data_t *cdp, fc_phandle_t node, char *svc) +{ + fc_cell_t hcell; + int error; + + error = fc_run_priv(cdp, svc, 1, 1, fc_phandle2cell(node), &hcell); + if (error) + return (NULL); + return (fc_cell2phandle(hcell)); +} + +void +recurse_tree(fcode_env_t *env, device_t *d, + void (*fn)(fcode_env_t *, device_t *)) +{ + if (d != NULL) { + device_t *p; + + fn(env, d); + recurse_tree(env, d->child, fn); + recurse_tree(env, d->peer, fn); + } +} + +static void +get_prom_nodeid(fcode_env_t *env, device_t *d) +{ + common_data_t *cdp = env->private; + private_data_t *pd = d->private; + char *name; + int namelen; + char *namebuf; + + if ((pd != NULL) && (pd->node)) { + if (os_get_prop_common(cdp, pd->node, "name", + 0, &namebuf, &namelen)) + namebuf = "<unknown>"; + debug_msg(DEBUG_UPLOAD, "Populated: %s = %p\n", namebuf, + pd->node); + return; + } + + name = get_package_name(env, d); + debug_msg(DEBUG_UPLOAD, "Node %s: %p (%p)\n", name, d, pd); + if (d->parent) { + private_data_t *ppd = (private_data_t *) d->parent->private; + fc_phandle_t thisnode; + + if (os_get_prop_common(cdp, ppd->node, "name", + 0, &namebuf, &namelen)) + namebuf = "<unknown>"; + debug_msg(DEBUG_UPLOAD, "Parent: %p (%p) %s = %p\n", d->parent, + ppd, namebuf, ppd->node); + for (thisnode = fc_nodeop(cdp, ppd->node, FC_CHILD_FCODE); + thisnode != NULL; + thisnode = fc_nodeop(cdp, thisnode, FC_PEER_FCODE)) { + int status; + + namebuf = ""; + namelen = 0; + status = os_get_prop_common(cdp, thisnode, "name", + 0, &namebuf, &namelen); + debug_msg(DEBUG_UPLOAD, "Lookup: %p name '%s'\n" + " status: %d", thisnode, namebuf, status); + if (status == 0 && strcmp(name, namebuf) == 0) + break; + } + if (thisnode) { + pd = MALLOC(sizeof (private_data_t)); + pd->common = cdp; + pd->node = thisnode; + pd->upload = 0; + d->private = pd; + add_my_handle(env, pd->node, d); + install_property_vectors(env, d); + debug_msg(DEBUG_UPLOAD, "Found: %p\n", thisnode); + } + } +} + +static void +update_nodeids(fcode_env_t *env) +{ + /* + * We scan through the tree looking for nodes that don't have + * one of my structures attached, and for each of those nodes + * I attempt to match it with a real firmware node + */ + recurse_tree(env, env->root_node, get_prom_nodeid); +} + +static void +build_nodes(fcode_env_t *env, common_data_t *cdp, fc_phandle_t h) +{ + char *name; + int len; + int n, allocd, depth; + fc_phandle_t p; + device_t *current, *attach; + private_data_t *pd; + private_data_t **node_array; + + /* + * This is not nice; new_device calls the allocate_phandle + * routine without exception, we need to disable the allocation + * while we are building the tree to the attachment point + * which is why the init_done variable exists. + */ + cdp->init_done = 0; + node_array = NULL; + depth = 0; + allocd = sizeof (private_data_t *); + do { + node_array = REALLOC(node_array, allocd*(depth+1)); + pd = MALLOC(sizeof (private_data_t)); + pd->node = h; + node_array[depth] = pd; + name = NULL; + (void) os_get_prop_common(cdp, pd->node, "name", 0, &name, + &len); + if (name) + debug_msg(DEBUG_UPLOAD, "Node: %p name: '%s'\n", h, + name); + else + log_message(MSG_ERROR, "Node: %p Unnamed node!!\n", h); + depth++; + h = fc_nodeop(cdp, h, FC_PARENT); + } while (h); + + for (n = 0; n < (depth-1); n++) { + new_device(env); + } + + env->attachment_pt = current = attach = env->current_device; + + for (n = 0; n < depth; n++) { + pd = node_array[n]; + pd->common = cdp; + current->private = pd; + add_my_handle(env, pd->node, current); + install_property_vectors(env, current); + current = current->parent; + } + + for (current = attach; current != NULL; current = current->parent) { + install_node_data(env, current); + if (current->parent) + finish_device(env); + } + + FREE(node_array); + cdp->init_done = 2; + update_nodeids(env); + cdp->init_done = 1; + cdp->first_node = 1; +} + +void +build_tree(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + instance_t *ih; + + root_node(env); + ih = open_instance_chain(env, env->current_device, 0); + MYSELF = ih; + build_nodes(env, cdp, cdp->attach); + close_instance_chain(env, ih, 0); + MYSELF = 0; + device_end(env); +} + +/* + * Installs /openprom and /packages nodes and sub-nodes. + */ +void +install_builtin_nodes(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + int saved_first_node; + int saved_init_done; + + if (cdp) { + saved_first_node = cdp->first_node; + saved_init_done = cdp->init_done; + cdp->first_node = 0; + cdp->init_done = 2; + install_openprom_nodes(env); + install_package_nodes(env); + cdp->first_node = saved_first_node; + cdp->init_done = saved_init_done; + } +} + + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "update-nodes", update_nodeids); + FORTH(0, "build-tree", build_tree); +} diff --git a/usr/src/lib/efcode/fcdriver/dma.c b/usr/src/lib/efcode/fcdriver/dma.c new file mode 100644 index 0000000000..669a681905 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/dma.c @@ -0,0 +1,123 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + + +static void +do_dma_alloc(fcode_env_t *env) +{ + size_t size; + void *p; + + CHECK_DEPTH(env, 1, "dma-alloc"); + size = (size_t) POP(DS); + p = valloc(size); + debug_msg(DEBUG_REG_ACCESS, "dma-alloc ( %x ) -> %p\n", (int)size, p); + throw_from_fclib(env, (p == 0), "dma-alloc failed"); + PUSH(DS, (fstack_t) p); +} + +static void +do_dma_free(fcode_env_t *env) +{ + void *p; + size_t size; + + CHECK_DEPTH(env, 2, "dma-free"); + size = POP(DS); + p = (void *) POP(DS); + debug_msg(DEBUG_REG_ACCESS, "dma-free ( %p %x )\n", p, (int)size); + + free(p); +} + +static void +do_dma_map_in(fcode_env_t *env) +{ + fc_cell_t data; + fstack_t va, len, cacheable; + private_data_t *pd = DEVICE_PRIVATE(env); + int error; + + CHECK_DEPTH(env, 3, "dma-map-in"); + cacheable = POP(DS); + len = POP(DS); + va = POP(DS); + + error = fc_run_priv(pd->common, "dma-map-in", 3, 1, + fc_int2cell(cacheable), fc_size2cell(len), fc_ptr2cell(va), + &data); + + throw_from_fclib(env, error, "dma-map-in failed"); + + PUSH(DS, (fstack_t)data); +} + +static void +do_dma_map_out(fcode_env_t *env) +{ + fstack_t va, dva, len; + private_data_t *pd = DEVICE_PRIVATE(env); + int error; + + CHECK_DEPTH(env, 3, "dma-map-out"); + len = POP(DS); + dva = POP(DS); + va = POP(DS); + + error = fc_run_priv(pd->common, "dma-map-out", 3, 0, fc_size2cell(len), + fc_ptr2cell(dva), fc_ptr2cell(va)); + + throw_from_fclib(env, error, "dma-map-out failed"); +} + +static void +do_dma_sync(fcode_env_t *env) +{ + CHECK_DEPTH(env, 3, "dma-sync"); + /* 3drop */ + DS -= 3; +} + +void +install_dma_methods(fcode_env_t *env) +{ + FORTH(0, "dma-alloc", do_dma_alloc); + FORTH(0, "dma-free", do_dma_free); + FORTH(0, "dma-map-in", do_dma_map_in); + FORTH(0, "dma-map-out", do_dma_map_out); + FORTH(0, "dma-sync", do_dma_sync); + +} diff --git a/usr/src/lib/efcode/fcdriver/fcdebug.c b/usr/src/lib/efcode/fcdriver/fcdebug.c new file mode 100644 index 0000000000..fee58574eb --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/fcdebug.c @@ -0,0 +1,116 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static void +dump_private(fcode_env_t *env) +{ + common_data_t *cdp; + private_data_t *p; + + if (env->current_device) { + p = env->current_device->private; + if (p) { + cdp = p->common; + } else + cdp = NULL; + } else { + cdp = env->private; + p = NULL; + } + + if (cdp == NULL) { + log_message(MSG_ERROR, "dump_private: NULL private ptr!\n"); + return; + } + + log_message(MSG_DEBUG, "Private Data:\n"); + log_message(MSG_DEBUG, "Progname: %s\n", cdp->Progname); + log_message(MSG_DEBUG, "fcode_fd: %8p\n", cdp->fcode_fd); + log_message(MSG_DEBUG, "attach: %llx\n", cdp->attach); + log_message(MSG_DEBUG, "Params: (%8p)\n", &cdp->fc); + log_message(MSG_DEBUG, " size: %d\n", cdp->fc.fcode_size); + log_message(MSG_DEBUG, " unit: %s\n", cdp->fc.unit_address); + if (p != NULL) { + log_message(MSG_DEBUG, "Node: %p\n", p->node); + log_message(MSG_DEBUG, "Parent: %p\n", p->parent); + log_message(MSG_DEBUG, "upload: %d\n", p->upload); + log_message(MSG_DEBUG, "debug: %8x\n", p->debug); + } +} + +static void +trigger(fcode_env_t *env) +{ + common_data_t *cdp = (common_data_t *)env->private; + + ASSERT(cdp); + + cdp->fcode_fd = open("/dev/fcode", O_RDONLY); + if (cdp->fcode_fd >= 0) { + log_message(MSG_INFO, "Trigger..."); + if (!fc_get_request(cdp)) + log_message(MSG_ERROR, "fc_get_request failed\n"); + else + log_message(MSG_INFO, "\n"); + } else + forth_abort(env, "Can't open /dev/fcode\n"); +} + +static void +do_trigger(fcode_env_t *env) +{ + trigger(env); + build_tree(env); + install_builtin_nodes(env); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "dump-private", dump_private); + FORTH(0, "trigger", do_trigger); +} diff --git a/usr/src/lib/efcode/fcdriver/get_req.c b/usr/src/lib/efcode/fcdriver/get_req.c new file mode 100644 index 0000000000..6a87b375d5 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/get_req.c @@ -0,0 +1,466 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> +#include <errno.h> + +#include <sys/mman.h> +#include <sys/pci.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static char *pkg_my_args; +static char fcode_dev[] = "/dev/fcode"; + +static void +dot_request(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + + log_message(MSG_INFO, "request: cfgadd: %x fc_size: %x unitadd: %s" + " attach: %x args: '%s'\n", cdp->fc.config_address, + cdp->fc.fcode_size, cdp->fc.unit_address, cdp->attach, + pkg_my_args ? pkg_my_args : "<null>"); +} + +/* + * Get next request from /dev/fcode. + */ +int +fc_get_request(common_data_t *cdp) +{ + char c; + int nbytes; + + if (cdp->fcode_fd < 0) { + log_message(MSG_FATAL, "fc_get_request: fcode_fd not open\n"); + return (0); + } + + if ((nbytes = read(cdp->fcode_fd, &c, sizeof (c))) < 0) { + log_perror(MSG_FATAL, "read(%s) failed", fcode_dev); + return (0); + } + + if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) { + log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed"); + return (0); + } + + if ((cdp->attach = fc_get_ap(cdp)) == NULL) + return (0); + + return (1); +} + +static void +get_my_args(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + char buffer[BUFSIZ]; + + /* + * Don't get if already set. + */ + if (pkg_my_args) + return; + + if (ioctl(cdp->fcode_fd, FC_GET_MY_ARGS, buffer) < 0) { + return; + } + pkg_my_args = STRDUP(buffer); +} + +static void +set_my_args(fcode_env_t *env) +{ + if (pkg_my_args) + FREE(pkg_my_args); + + parse_word(env); + pkg_my_args = pop_a_duped_string(env, NULL); +} + +static void +dot_my_args(fcode_env_t *env) +{ + if (pkg_my_args) + log_message(MSG_INFO, "%s\n", pkg_my_args); + else + log_message(MSG_INFO, "NULL\n"); +} + +void +push_my_args(fcode_env_t *env) +{ + push_a_string(env, pkg_my_args); +} + +void +get_fcode_from_device(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + char *p, *buf; + static char func_name[] = "get_fcode_from_device"; + fc_fcode_info_t fcode_info; + + if (!cdp->fc.fcode_size) { + debug_msg(DEBUG_FIND_FCODE, "%s: Fcode zero length\n", + func_name); + push_a_string(env, NULL); + return; + } + fcode_info.fcode_size = cdp->fc.fcode_size; + fcode_info.fcode_ptr = MALLOC(cdp->fc.fcode_size); + if (ioctl(cdp->fcode_fd, FC_GET_FCODE_DATA, &fcode_info) < 0) { + log_perror(MSG_FATAL, "ioctl(FC_GET_FCODE_DATA) failed"); + push_a_string(env, NULL); + } else { + debug_msg(DEBUG_FIND_FCODE, + "%s: Fcode from device: len: 0x%x\n", func_name, + (int)cdp->fc.fcode_size); + PUSH(DS, (fstack_t)fcode_info.fcode_ptr); + PUSH(DS, (fstack_t)cdp->fc.fcode_size); + } +} + +static void +save_fcode_to_file(fcode_env_t *env) +{ + char *buf, *fname; + int len; + FILE *fd; + + CHECK_DEPTH(env, 4, "save-fcode-to-file"); + if ((fname = pop_a_string(env, NULL)) == NULL) { + log_message(MSG_DEBUG, "fname?\n"); + return; + } + if ((buf = pop_a_string(env, &len)) == NULL) { + log_message(MSG_INFO, "buf?\n"); + return; + } + if ((fd = fopen(fname, "w")) == NULL) { + log_perror(MSG_DEBUG, "Save_fcode_to_file: Can't open '%s'", + fname); + return; + } + log_message(MSG_INFO, "Fcode %p,%x to file '%s'\n", buf, len, fname); + fwrite(buf, len, sizeof (char), fd); + fclose(fd); +} + +void +exec_fcode_builtin_method(fcode_env_t *env) +{ + fstack_t d; + char *method; + extern void exec_parent_method(fcode_env_t *); + extern void exec_builtin_driver(fcode_env_t *); + + method = (char *)DS[-1]; + exec_parent_method(env); + d = POP(DS); + if (d) { + debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s -> %s found\n", + method, (char *)DS[-1]); + exec_builtin_driver(env); + debug_msg(DEBUG_FIND_FCODE, "builtin-driver-exec: %p %x\n", + (char *)DS[-1], (int)TOS); + } else { + debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s not found\n", + method); + PUSH(DS, FALSE); + } +} + +void +get_fcode_from_filesystem(fcode_env_t *env) +{ + fstack_t d; + char *method, *fc_name, *path; + extern void exec_parent_method(fcode_env_t *); + static char fname[] = "get-fcode-from-filesystem"; + + method = (char *)DS[-1]; + exec_parent_method(env); + d = POP(DS); + if (d) { + fc_name = pop_a_string(env, NULL); + debug_msg(DEBUG_FIND_FCODE, "%s: %s -> %s found\n", fname, + method, fc_name); + if ((path = search_for_fcode_file(env, fc_name)) != NULL) { + debug_msg(DEBUG_FIND_FCODE, "%s: file: %s FOUND\n", + fname, path); + push_a_string(env, path); + load_file(env); + } else { + debug_msg(DEBUG_FIND_FCODE, "%s: file '%s' not found\n", + fname, fc_name); + PUSH(DS, FALSE); + } + } else { + debug_msg(DEBUG_FIND_FCODE, "%s: method '%s' not found\n", + fname, method); + PUSH(DS, FALSE); + } +} + +/* + * Looks for "device-id" and "class-id" methods in parent, if there, + * executes them to get "builtin drivers" file name or method name, then + * executes the builtin-driver method. If both those fail, try getting the + * fcode from the device. Note that we sleaze resetting the data stack. + * This would be cleaner if we had a way to do the equivalent of "catch/throw" + * from within C code. + */ +void +find_fcode(fcode_env_t *env) +{ + fstack_t *dp = env->ds; + static char func_name[] = "find_fcode"; + + my_unit(env); + push_a_string(env, "device-id"); + get_fcode_from_filesystem(env); + if (TOS) { + debug_msg(DEBUG_FIND_FCODE, "%s: FS dev-id: len: 0x%x\n", + func_name, TOS); + return; + } + + env->ds = dp; + my_unit(env); + push_a_string(env, "class-id"); + get_fcode_from_filesystem(env); + if (TOS) { + debug_msg(DEBUG_FIND_FCODE, "%s: FS cls-id len: 0x%x\n", + func_name, TOS); + return; + } + + env->ds = dp; + get_fcode_from_device(env); + if (TOS) { + debug_msg(DEBUG_FIND_FCODE, "%s: DEV fcode len: 0x%x\n", + func_name, TOS); + return; + } + + env->ds = dp; + my_unit(env); + push_a_string(env, "device-id"); + exec_fcode_builtin_method(env); + if (TOS) { + debug_msg(DEBUG_FIND_FCODE, "%s: dropin dev-id len: 0x%x\n", + func_name, TOS); + return; + } + + env->ds = dp; + my_unit(env); + push_a_string(env, "class-id"); + exec_fcode_builtin_method(env); + if (TOS) { + debug_msg(DEBUG_FIND_FCODE, "%s: dropin cls-id len: 0x%x\n", + func_name, TOS); + return; + } + debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name); +} + +int +open_fcode_dev(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + + if ((cdp->fcode_fd = open(fcode_dev, O_RDONLY)) < 0) + log_perror(MSG_ERROR, "Can't open '%s'", fcode_dev); + return (cdp->fcode_fd >= 0); +} + +static void +get_request(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + + if (cdp->fcode_fd >= 0) + close(cdp->fcode_fd); + if (!open_fcode_dev(env)) + exit(1); + if (!fc_get_request(cdp)) { + log_message(MSG_FATAL, "fc_get_request failed\n"); + exit(1); + } + + get_my_args(env); + + DEBUGF(UPLOAD, dot_request(env)); +} + +/* + * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened + * file descriptor is fd 0. + */ +static void +get_efdaemon_request(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + + cdp->fcode_fd = 0; + if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) { + log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed"); + exit(1); + } + + if ((cdp->attach = fc_get_ap(cdp)) == NULL) + exit(1); + + get_my_args(env); + + DEBUGF(UPLOAD, dot_request(env)); +} + +static void +process_request(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + fstack_t fcode_len; + char *path; + + build_tree(env); + install_builtin_nodes(env); + push_my_args(env); + push_a_string(env, cdp->fc.unit_address); + if ((path = get_path(env, env->attachment_pt)) == NULL) { + log_message(MSG_FATAL, "Can't get_path of" + " attachment_pt %p\n", env->attachment_pt); + exit(1); + } + debug_msg(DEBUG_UPLOAD, "Attach Point: %s\n", path); + + push_a_string(env, path); + begin_package(env); + find_fcode(env); + fcode_len = POP(DS); + if (!fcode_len) { + (void) POP(DS); + debug_msg(DEBUG_UPLOAD, "Zero length Fcode\n"); + return; + } + + debug_msg(DEBUG_UPLOAD, "byte-load fcode_len: %x\n", + fcode_len); + + PUSH(DS, 1); + byte_load(env); + end_package(env); + upload_nodes(env); + validate_nodes(env); + debug_msg(DEBUG_UPLOAD, "Upload Done\n"); +} + +static void +finish_request(fcode_env_t *env) +{ + common_data_t *cdp = env->private; + + close(cdp->fcode_fd); +} + +/* + * Non-daemon "do-request", for debugging + */ +static void +do_request(fcode_env_t *env) +{ + get_request(env); + process_request(env); + finish_request(env); +} + +/* + * This process one request from efdaemon, we know that /dev/fcode is already + * open and passed in fd0 (stdin). If it's not, we throw up our hands. + */ +void +run_one_efdaemon_request(fcode_env_t *env) +{ + get_efdaemon_request(env); + process_request(env); + finish_request(env); + exit(0); +} + +void +probe_space(fcode_env_t *env) +{ + fc_cell_t cfg = 0; + int error; + + error = fc_run_priv(env->private, FC_PROBE_SPACE, 0, 1, &cfg); + if (error) + throw_from_fclib(env, 1, "FC_PROBE_SPACE failed\n"); + PUSH(DS, fc_cell2uint32_t(cfg)); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "get-fcode-from-device", get_fcode_from_device); + FORTH(0, "save-fcode-to-file", save_fcode_to_file); + FORTH(0, "get-my-args", get_my_args); + FORTH(0, "set-my-args", set_my_args); + FORTH(0, ".my-args", dot_my_args); + FORTH(0, ".request", dot_request); + FORTH(0, "get-request", get_request); + FORTH(0, "process-request", process_request); + FORTH(0, "finish-request", finish_request); + FORTH(0, "do-request", do_request); + FORTH(0, "find-fcode", find_fcode); + FORTH(0, "exec-fcode-builtin-method", exec_fcode_builtin_method); + FORTH(0, "run-one-efdaemon-request", run_one_efdaemon_request); + FORTH(0, "get-efdaemon-request", get_efdaemon_request); + FORTH(0, "probe-space", probe_space); +} diff --git a/usr/src/lib/efcode/fcdriver/ioctl.c b/usr/src/lib/efcode/fcdriver/ioctl.c new file mode 100644 index 0000000000..218ceb88db --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/ioctl.c @@ -0,0 +1,110 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> +#include <fcntl.h> +#include <stdarg.h> +#include <errno.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +#define FCC_MAX_CELLS 10 + +int +fc_run_priv(common_data_t *cdp, char *service, int nin, int nout, ...) +{ + va_list ap; + int i, error, no_err; + fc_cell_t fc_req[FCC_FIXED_CELLS+FCC_MAX_CELLS]; + struct fc_client_interface *cip = (struct fc_client_interface *)fc_req; + fc_cell_t *fcp; + char *error_msg; + + no_err = nin & FCRP_NOERROR; + nin &= ~FCRP_NOERROR; + + bzero(fc_req, sizeof (fc_req)); + if (nin + nout > FCC_MAX_CELLS) { + log_message(MSG_ERROR, "%s: too many ins (%d) and outs (%d)\n", + service, nin, nout); + nin = min(nin, FCC_MAX_CELLS); + nout = FCC_MAX_CELLS - nin; + } + va_start(ap, nout); + cip->svc_name = fc_ptr2cell(service); + cip->nargs = fc_int2cell(nin); + cip->nresults = fc_int2cell(nout); + for (i = 0; i < nin; i++) + fc_arg(cip, i) = va_arg(ap, fc_cell_t); + error = ioctl(cdp->fcode_fd, FC_RUN_PRIV, cip); + for (i = 0; i < nout; i++) { + fcp = va_arg(ap, fc_cell_t *); + *fcp = fc_result(cip, i); + } + va_end(ap); + + if (error) + error_msg = strerror(errno); + else if (cip->priv_error) { + error_msg = "Priv violation"; + error = 1; + } else if (cip->error) { + error_msg = "Error"; + error = 1; + } + if ((error & !no_err) || + (get_interpreter_debug_level() & DEBUG_REG_ACCESS)) { + if (error) + log_message(MSG_ERROR, "%s: FC_RUN_PRIV: %s: ", + cdp->Progname, error_msg); + log_message(MSG_ERROR, "%s ( ", service); + for (i = 0; i < nin; i++) + log_message(MSG_ERROR, "%llx ", + (uint64_t)fc_arg(cip, i)); + log_message(MSG_ERROR, ")"); + if (error) + ; + else if (nout) { + log_message(MSG_ERROR, " ->"); + for (i = 0; i < nout; i++) + log_message(MSG_ERROR, " %llx", + (uint64_t)fc_result(cip, i)); + } else + log_message(MSG_ERROR, " OK"); + log_message(MSG_ERROR, "\n"); + } + return (error); +} diff --git a/usr/src/lib/efcode/fcdriver/load_node.c b/usr/src/lib/efcode/fcdriver/load_node.c new file mode 100644 index 0000000000..613a1f94f6 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/load_node.c @@ -0,0 +1,289 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <fcntl.h> +#include <sys/shm.h> +#include <dlfcn.h> +#include <sys/systeminfo.h> +#include <sys/utsname.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static char *default_search_path; +static char search_proto[] = + "/usr/platform/%s/lib/efcode%s:" + "/usr/platform/%s/lib/efcode%s:" + "/usr/lib/efcode%s"; + +/* + * Build the library/drop-in fcode search path. If there's no architecture + * passed, we build the search path (per the PSARC decision): + * /usr/platform/`uname -i`/lib/efcode + * /usr/platform/`uname -m`/lib/efcode + * /usr/lib/efcode + * If there is an architecture passed, we prepend the following search path to + * the above: + * /usr/platform/`uname -i`/lib/efcode/{architecture} + * /usr/platform/`uname -m`/lib/efcode/{architecture} + * /usr/lib/efcode/{architecture} + * This allows FCode drop-in searches to find FCode in the non-architecture + * directories. + */ +static void +build_default_search_path(char *arch) +{ + char platform[100], *p; + struct stat statb; + struct utsname utsname; + int len; + + sysinfo(SI_PLATFORM, platform, sizeof (platform)); + uname(&utsname); + len = strlen(search_proto) + strlen(platform) + strlen(utsname.machine); + if (*arch != '\0') { + len += len + (3 * strlen(arch)) + 1; + } + default_search_path = MALLOC(len); + if (*arch != '\0') { + sprintf(default_search_path, search_proto, platform, arch, + utsname.machine, arch, arch); + p = default_search_path + strlen(default_search_path); + *p++ = ':'; + } else + p = default_search_path; + + sprintf(p, search_proto, platform, "", utsname.machine, "", ""); +} + +static void +set_default_search_path(fcode_env_t *env) +{ + if (default_search_path) + FREE(default_search_path); + + parse_word(env); + default_search_path = pop_a_duped_string(env, NULL); +} + +static void +get_default_search_path(fcode_env_t *env) +{ + push_a_string(env, default_search_path); +} + +/* + * Complicated by fact that a library (e.g. a 32-bit library) can match the + * file name. But if we're running as 64-bit, dlopen on that library will + * fail. + */ +static char * +search_path(char *name, char *search, int (*fn)(char *)) +{ + char *p, *next_p; + char *tpath, *fpath; + + fpath = STRDUP(search); + for (p = fpath; p != NULL; p = next_p) { + if ((next_p = strchr(p, ':')) != NULL) + *next_p++ = '\0'; + tpath = MALLOC(strlen(p) + strlen(name) + 2); + sprintf(tpath, "%s/%s", p, name); + if ((*fn)(tpath)) { + FREE(fpath); + return (tpath); + } + FREE(tpath); + } + FREE(fpath); + return (NULL); +} + +static int +load_lib_file(char *path) +{ + struct stat buf; + + debug_msg(DEBUG_FIND_FCODE, "load_lib_file: '%s' -> ", path); + if (stat(path, &buf)) { + debug_msg(DEBUG_FIND_FCODE, "stat failed\n"); + return (0); + } + if (dlopen(path, RTLD_NOW) != NULL) { + debug_msg(DEBUG_FIND_FCODE, "OK\n"); + return (1); + } + debug_msg(DEBUG_FIND_FCODE, "dlopen failed\n"); + return (0); +} + +static int +is_fcode_file(char *path) +{ + struct stat statb; + int fd; + uchar_t header[8]; + int status; + static char func_name[] = "is_fcode_file"; + extern int check_fcode_header(char *, uchar_t *, int); + + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' -> ", func_name, path); + if ((fd = open(path, 0)) < 0) { + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' can't open\n", func_name, + path); + return (0); + } + if (fstat(fd, &statb) != 0 || read(fd, header, sizeof (header)) < 0) { + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' can't fstat/read\n", + func_name, path); + close(fd); + return (0); + } + status = check_fcode_header(path, header, statb.st_size); + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' format %s\n", func_name, path, + status ? "OK" : "NOT OK"); + close(fd); + return (status); +} + +static char * +find_lib_file(fcode_env_t *env, char *prefix, char *name, char *suffix, + int (*fn)(char *)) +{ + char *search, *fname; + char *lib_name; + common_data_t *cdp = env->private; + + if ((search = cdp->search_path) == NULL && + (search = default_search_path) == NULL) { + log_message(MSG_ERROR, "find_lib_file: no search path\n"); + return (NULL); + } + + lib_name = MALLOC(strlen(name) + strlen(prefix) + strlen(suffix) + 1); + sprintf(lib_name, "%s%s%s", prefix, name, suffix); + fname = search_path(lib_name, search, fn); + FREE(lib_name); + return (fname); +} + +char * +search_for_fcode_file(fcode_env_t *env, char *basename) +{ + return (find_lib_file(env, "", basename, ".fc", is_fcode_file)); +} + +static void +load_appropriate_file(fcode_env_t *env, char *name, device_t *d) +{ + char *fname; + + if ((fname = find_lib_file(env, "lfc_", name, ".so", load_lib_file)) + != NULL) { + debug_msg(DEBUG_FIND_FCODE, "Loading Library: %s\n", fname); + FREE(fname); + } else if ((fname = search_for_fcode_file(env, name)) != NULL) { + debug_msg(DEBUG_FIND_FCODE, "Loading Fcode: %s\n", fname); + run_fcode_from_file(env, fname, 0); + FREE(fname); + } else { + throw_from_fclib(env, 1, + "Can't find 'lfc_%s.so' or '%s.fc'\n", name, name); + } +} + +void +install_node_data(fcode_env_t *env, device_t *d) +{ + prop_t *p; + device_t *cd; + char libname[512]; + static char func_name[] = "install_node_data"; + + if (d->parent) { + if ((p = lookup_package_property(env, "device_type", + d->parent)) == NULL) { + log_message(MSG_ERROR, "%s: no 'device_type' property" + " for '%s'\n", func_name, get_path(env, d->parent)); + return; + } + /* + * Warning: lookup_package_property uses a static data area to + * build the property node returned, so we have to grab a copy + * of the data. + */ + strcpy(libname, (char *)p->data); + strcat(libname, "_"); + } else + libname[0] = '\0'; + + if ((p = lookup_package_property(env, "device_type", d)) == NULL) { + log_message(MSG_ERROR, "%s: no 'device_type' property for" + " '%s'\n", func_name, get_path(env, d)); + return; + } + + /* + * Warning: lookup_package_property uses a static data area to build + * the property node returned, so we have to grab a copy of the + * data. + */ + strcat(libname, (char *)p->data); + + debug_msg(DEBUG_FIND_FCODE, "%s: `%s` lname: '%s'\n", func_name, + get_path(env, d), libname); + + load_appropriate_file(env, libname, d); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + +#if defined(__sparcv9) + build_default_search_path("/sparcv9"); +#else + build_default_search_path(""); +#endif + FORTH(0, "set-default-search-path", set_default_search_path); + FORTH(0, "get-default-search-path", get_default_search_path); +} diff --git a/usr/src/lib/efcode/fcdriver/misc.c b/usr/src/lib/efcode/fcdriver/misc.c new file mode 100644 index 0000000000..4e62b11e03 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/misc.c @@ -0,0 +1,659 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static fc_cell_t +fc_reg_read(fcode_env_t *env, char *service, fstack_t virt, int *errp) +{ + fc_cell_t virtaddr, data; + int error, nin; + + if (!is_mcookie(virt)) + forth_abort(env, "fc_reg_read: bad mcookie: 0x%x\n", virt); + + virtaddr = mcookie_to_addr(virt); + + /* Supress fc_run_priv error msgs on peeks */ + nin = ((errp == NULL) ? 1 : (1 | FCRP_NOERROR)); + + error = fc_run_priv(env->private, service, nin, 1, virtaddr, &data); + if (errp) + /* Don't report error on peeks */ + *errp = error; + else if (error) { + log_message(MSG_ERROR, "fc_read_reg: ERROR: cookie: %llx" + " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr); + data = 0; + } + return (data); +} + +static void +fc_reg_write(fcode_env_t *env, char *service, fstack_t virt, fc_cell_t data, + int *errp) +{ + fc_cell_t virtaddr; + int error, nin; + + if (!is_mcookie(virt)) + forth_abort(env, "fc_reg_write: bad mcookie: 0x%x\n", virt); + + virtaddr = mcookie_to_addr(virt); + + /* Supress fc_run_priv error msgs on pokes */ + nin = ((errp == NULL) ? 2 : (2 | FCRP_NOERROR)); + + error = fc_run_priv(env->private, service, nin, 0, virtaddr, data); + if (errp) + /* Don't report error on pokes */ + *errp = error; + else if (error) { + log_message(MSG_ERROR, "fc_write_reg: ERROR: cookie: %llx" + " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr); + } +} + +static int +check_address_abuse(fcode_env_t *env, fstack_t addr, char *type, + int want_mcookie, void (*alt)(fcode_env_t *)) +{ + if (is_mcookie(addr) != want_mcookie) { + debug_msg(DEBUG_ADDR_ABUSE, "Warning: %s to %s address: %llx\n", + type, want_mcookie ? "unmapped" : "mapped", + (uint64_t)addr); + (*alt)(env); + return (1); + } + return (0); +} + +static void +rlfetch(fcode_env_t *env) +{ + fstack_t p; + + CHECK_DEPTH(env, 1, "rl@"); + p = TOS; + if (!check_address_abuse(env, p, "rl@", 1, lfetch)) + TOS = (lforth_t)fc_reg_read(env, "rl@", p, NULL); +} + +static void +rlstore(fcode_env_t *env) +{ + fstack_t p, d; + + CHECK_DEPTH(env, 2, "rl!"); + p = TOS; + if (!check_address_abuse(env, p, "rl!", 1, lstore)) { + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rl!", p, d, NULL); + } +} + +static void +rwfetch(fcode_env_t *env) +{ + fstack_t p; + + CHECK_DEPTH(env, 1, "rw@"); + p = TOS; + if (!check_address_abuse(env, p, "rw@", 1, wfetch)) + TOS = (wforth_t)fc_reg_read(env, "rw@", p, NULL); +} + +static void +rwstore(fcode_env_t *env) +{ + fstack_t p, d; + + CHECK_DEPTH(env, 2, "rw!"); + p = TOS; + if (!check_address_abuse(env, p, "rw!", 1, wstore)) { + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rw!", p, d, NULL); + } +} + +void +rbfetch(fcode_env_t *env) +{ + fstack_t p; + + CHECK_DEPTH(env, 1, "rb@"); + p = TOS; + if (!check_address_abuse(env, p, "rb@", 1, cfetch)) { + TOS = (uchar_t)fc_reg_read(env, "rb@", p, NULL); + } +} + +static void +rbstore(fcode_env_t *env) +{ + fstack_t p, d; + + CHECK_DEPTH(env, 2, "rb!"); + p = TOS; + if (!check_address_abuse(env, p, "rb!", 1, cstore)) { + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rb!", p, d, NULL); + } +} + +/* + * rx@ ( xa -- xv ) + */ +static void +rxfetch(fcode_env_t *env) +{ + fstack_t p; + xforth_t x; + + CHECK_DEPTH(env, 1, "rx@"); + p = TOS; + if (!check_address_abuse(env, p, "rx@", 1, xfetch)) { + p = POP(DS); + push_xforth(env, (xforth_t)fc_reg_read(env, "rx@", p, NULL)); + } +} + +/* + * rx! ( xv xa -- ) + */ +static void +rxstore(fcode_env_t *env) +{ + fstack_t p; + xforth_t d; + + CHECK_DEPTH(env, 2, "rx!"); + p = TOS; + if (!check_address_abuse(env, p, "rx!", 1, xstore)) { + p = POP(DS); + d = pop_xforth(env); + fc_reg_write(env, "rx!", p, d, NULL); + } +} + +static void +lpeek(fcode_env_t *env) +{ + fstack_t p; + lforth_t r; + int error; + + CHECK_DEPTH(env, 1, "lpeek"); + p = POP(DS); + r = (lforth_t)fc_reg_read(env, "rl@", p, &error); + if (error) + PUSH(DS, FALSE); + else { + PUSH(DS, r); + PUSH(DS, TRUE); + } +} + +static void +lpoke(fcode_env_t *env) +{ + fstack_t p, d; + int error; + + CHECK_DEPTH(env, 2, "lpoke"); + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rl!", p, d, &error); + PUSH(DS, error ? FALSE : TRUE); +} + +static void +wpeek(fcode_env_t *env) +{ + fstack_t p; + int error; + wforth_t r; + + CHECK_DEPTH(env, 1, "wpeek"); + p = POP(DS); + r = (wforth_t)fc_reg_read(env, "rw@", p, &error); + if (error) + PUSH(DS, FALSE); + else { + PUSH(DS, r); + PUSH(DS, TRUE); + } +} + +static void +wpoke(fcode_env_t *env) +{ + fstack_t p, d; + int error; + + CHECK_DEPTH(env, 2, "wpoke"); + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rw!", p, d, &error); + PUSH(DS, error ? FALSE : TRUE); +} + +static void +cpeek(fcode_env_t *env) +{ + fstack_t p; + uchar_t r; + int error; + + CHECK_DEPTH(env, 1, "cpeek"); + p = POP(DS); + r = (uchar_t)fc_reg_read(env, "rb@", p, &error); + if (error) + PUSH(DS, FALSE); + else { + PUSH(DS, r); + PUSH(DS, TRUE); + } +} + +static void +cpoke(fcode_env_t *env) +{ + fstack_t p, d; + int error; + + CHECK_DEPTH(env, 2, "cpoke"); + p = POP(DS); + d = POP(DS); + fc_reg_write(env, "rb!", p, d, &error); + PUSH(DS, error ? FALSE : TRUE); +} + +/* + * fcdriver version of cfetch, replaces base 'c@' + */ +static void +fcd_cfetch(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 1, "c@"); + if (!check_address_abuse(env, addr, "c@", 0, rbfetch)) + cfetch(env); +} + +/* + * fcdriver version of cstore, replaces base 'c!' + */ +static void +fcd_cstore(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 2, "c!"); + if (!check_address_abuse(env, addr, "c!", 0, rbstore)) + cstore(env); +} + +/* + * fcdriver version of wfetch, replaces base 'w@' + */ +static void +fcd_wfetch(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 1, "w@"); + if (!check_address_abuse(env, addr, "w@", 0, rwfetch)) + wfetch(env); +} + +/* + * fcdriver version of wstore, replaces base 'w!' + */ +static void +fcd_wstore(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 2, "w!"); + if (!check_address_abuse(env, addr, "w!", 0, rwstore)) + wstore(env); +} + +/* + * fcdriver version of lfetch, replaces base 'l@' + */ +static void +fcd_lfetch(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 1, "l@"); + if (!check_address_abuse(env, addr, "l@", 0, rlfetch)) + lfetch(env); +} + +/* + * fcdriver version of lstore, replaces base 'l!' + */ +static void +fcd_lstore(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 2, "l!"); + if (!check_address_abuse(env, addr, "l!", 0, rlstore)) + lstore(env); +} + +/* + * fcdriver version of xfetch, replaces base 'x@' + */ +static void +fcd_xfetch(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 1, "x@"); + if (!check_address_abuse(env, addr, "x@", 0, rxfetch)) + xfetch(env); +} + +/* + * fcdriver version of xstore, replaces base 'x!' + */ +static void +fcd_xstore(fcode_env_t *env) +{ + fstack_t addr = TOS; + + CHECK_DEPTH(env, 2, "x!"); + if (!check_address_abuse(env, addr, "x!", 0, rxstore)) + xstore(env); +} + +/* + * fcdriver version of move, replaces base 'move' + */ +static void +fcd_move(fcode_env_t *env) +{ + size_t len; + uchar_t *destaddr, *srcaddr; + + CHECK_DEPTH(env, 3, "move"); + len = POP(DS); + destaddr = ((uchar_t *)POP(DS)); + srcaddr = ((uchar_t *)POP(DS)); + for (; len > 0; len--, srcaddr++, destaddr++) { + PUSH(DS, (fstack_t)srcaddr); + fcd_cfetch(env); + PUSH(DS, (fstack_t)destaddr); + fcd_cstore(env); + } +} + +static void +fcd_comp(fcode_env_t *env) +{ + char *str1, *str2, byte1, byte2; + size_t len; + + CHECK_DEPTH(env, 3, "comp"); + len = (size_t)POP(DS); + str1 = (char *)POP(DS); + str2 = (char *)POP(DS); + for (; len > 0; len--, str1++, str2++) { + PUSH(DS, (fstack_t)str1); + fcd_cfetch(env); + byte1 = POP(DS); + PUSH(DS, (fstack_t)str2); + fcd_cfetch(env); + byte2 = POP(DS); + if (byte1 > byte2) { + PUSH(DS, -1); + return; + } + if (byte1 < byte2) { + PUSH(DS, 1); + return; + } + } + PUSH(DS, 0); +} + +char * +get_eeprom_value(fcode_env_t *env, char *name) +{ + FILE *fd; + char buf[80], *p; + + sprintf(buf, "eeprom '%s'", name); + if ((fd = popen(buf, "r")) == NULL) + return (NULL); + fgets(buf, sizeof (buf), fd); + pclose(fd); + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + if ((p = strchr(buf, '=')) != NULL) + return (p + 1); + return (NULL); +} + +static void +local_mac_address(fcode_env_t *env) +{ + char *mac_str; + int mac_value; + + mac_str = get_eeprom_value(env, "local-mac-address?"); + if (mac_str != NULL && strcmp(mac_str, "true") == 0) + mac_value = TRUE; + else + mac_value = FALSE; + PUSH(DS, mac_value); +} + +/* + * Allow for programmatic over-ride of 'mac-address' + */ +#define MAC_ADDR_SIZE 6 +static char *mac_addr; +static int mac_addr_is_valid; + +void +set_mac_address(char *macaddr) +{ + mac_addr_is_valid = 1; + memcpy(mac_addr, macaddr, MAC_ADDR_SIZE); +} + +void +push_mac_address(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)mac_addr); + PUSH(DS, MAC_ADDR_SIZE); +} + +/* + * Does driver call to get this. + */ +static void +local_ether_addr(fcode_env_t *env) +{ + static fc_cell_t *mac_add; + int error; + + mac_add = MALLOC(sizeof (fc_cell_t) * 2); + error = fc_run_priv(env->private, "local-ether-addr", 0, 2, &mac_add[0], + &mac_add[1]); + if (error) { + bzero(mac_add, sizeof (mac_add)); + } + + PUSH(DS, (fstack_t)&mac_add[0]); + PUSH(DS, 6); +} + +/* + * 'mac-address' - complicated by 'local-mac-address' stuff. + */ +static void +mac_address(fcode_env_t *env) +{ + fstack_t d; + + if (mac_addr_is_valid) { + push_mac_address(env); + return; + } + + /* + * From here, we essentially re-implement OBP's 'mac-address' word. + * on some platforms, this may need to be re-implemented. + */ + local_mac_address(env); + d = POP(DS); + if (d) { + push_a_string(env, "local-mac-address"); + get_inherited_prop(env); + d = POP(DS); + if (d == FALSE && TOS == 6) + return; + two_drop(env); + } + local_ether_addr(env); +} + +/* + * Allow for the programmatic setting of diagnostic-mode? + */ +static int diag_mode_is_valid = 0; +static int diag_mode = 0; + +void +set_diagnostic_mode(fcode_env_t *env) +{ + fstack_t d = POP(DS); + + diag_mode = d; + diag_mode_is_valid = 1; +} + +void +push_diagnostic_mode(fcode_env_t *env) +{ + PUSH(DS, (fstack_t)diag_mode); +} + +/* + * 'diagnostic-mode?' - diagnostic-mode? is equivalent to NVRAM 'diag-switch?' + */ +static void +diagnostic_mode(fcode_env_t *env) +{ + char *diag_str; + int diag_value; + + if (!diag_mode_is_valid) { + diag_str = get_eeprom_value(env, "diag-switch?"); + if (diag_str != NULL && strcmp(diag_str, "false") == 0) + diag_value = FALSE; + else + diag_value = TRUE; + PUSH(DS, diag_value); + set_diagnostic_mode(env); + } + + push_diagnostic_mode(env); +} + +/* + * May need to implement other memory-access Fcodes here (depending upon + * abuse), like fill, comp, +!, etc., etc. + */ + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + mac_addr = MALLOC(MAC_ADDR_SIZE); + + ASSERT(env); + NOTICE; + + ANSI(0x06e, 0, "l@", fcd_lfetch); + ANSI(0x06f, 0, "w@", fcd_wfetch); + ANSI(0x071, 0, "c@", fcd_cfetch); + ANSI(0x073, 0, "l!", fcd_lstore); + ANSI(0x074, 0, "w!", fcd_wstore); + ANSI(0x075, 0, "c!", fcd_cstore); + ANSI(0x078, 0, "move", fcd_move); + ANSI(0x07a, 0, "comp", fcd_comp); + + ANSI(0x120, 0, "diagnostic-mode?", diagnostic_mode); + + ANSI(0x1a4, 0, "mac-address", mac_address); + + P1275(0x220, 0, "cpeek", cpeek); + P1275(0x221, 0, "wpeek", wpeek); + P1275(0x222, 0, "lpeek", lpeek); + P1275(0x223, 0, "cpoke", cpoke); + P1275(0x224, 0, "wpoke", wpoke); + P1275(0x225, 0, "lpoke", lpoke); + + P1275(0x230, 0, "rb@", rbfetch); + P1275(0x231, 0, "rb!", rbstore); + P1275(0x232, 0, "rw@", rwfetch); + P1275(0x233, 0, "rw!", rwstore); + P1275(0x234, 0, "rl@", rlfetch); + P1275(0x235, 0, "rl!", rlstore); + + P1275(0x246, 0, "x@", fcd_xfetch); + P1275(0x247, 0, "x!", fcd_xstore); + + P1275(0x22e, 0, "rx@", rxfetch); + P1275(0x22f, 0, "rx!", rxstore); + FORTH(0, "set-diagnostic-mode", set_diagnostic_mode); + FORTH(0, "local-mac-address?", local_mac_address); + FORTH(0, "local-ether-addr", local_ether_addr); +} diff --git a/usr/src/lib/efcode/fcdriver/phandle.c b/usr/src/lib/efcode/fcdriver/phandle.c new file mode 100644 index 0000000000..79a202da4e --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/phandle.c @@ -0,0 +1,204 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + + +static int use_os_handle = 1; + +void +do_use_os_handles(fcode_env_t *env) +{ + use_os_handle = 1; +} + +void +do_use_fake_handles(fcode_env_t *env) +{ + log_message(MSG_ERROR, "WARNING: using fake phandles, test only\n"); + use_os_handle = 0; +} + +static int +match_nodeid(void *s, void *d) +{ + my_nodeid_t *src = s; + my_nodeid_t *dest = d; + return ((src->node) == (dest->node)); +} + +static int +match_handle(void *s, void *d) +{ + my_nodeid_t *src = s; + my_nodeid_t *dest = d; + return ((src->my_handle) == (dest->my_handle)); +} + +/* + * Convert from an OS phandle to an interpreter phandle + */ +device_t * +convert_phandle(fcode_env_t *env, fstack_t d) +{ + fc_resource_t *t; + common_data_t *cdp = env->private; + device_t *r; + + if (use_os_handle) { + my_nodeid_t nh; + nh.my_handle = (fc_phandle_t) d; + t = find_resource(&cdp->nodeids, &nh, match_handle); + if (t == NULL) { + r = 0; + } else { + my_nodeid_t *p = (my_nodeid_t *) t->data; + r = (device_t *) p->node; + } + } else + r = (device_t *)d; + return (r); +} + +/* + * Interpreter phandle to OS phandle + */ +fstack_t +revert_phandle(fcode_env_t *env, device_t *d) +{ + fc_resource_t *t; + common_data_t *cdp = env->private; + fstack_t r; + + if (use_os_handle) { + my_nodeid_t nh; + nh.node = d; + t = find_resource(&cdp->nodeids, &nh, match_nodeid); + if (t == NULL) { + r = 0; + } else { + my_nodeid_t *p = (my_nodeid_t *) t->data; + r = (fstack_t) p->my_handle; + } + } else + r = (fstack_t) d; + return (r); +} + +void +add_my_handle(fcode_env_t *env, fc_phandle_t mh, device_t *d) +{ + my_nodeid_t *nh; + common_data_t *cdp = env->private; + + nh = MALLOC(sizeof (my_nodeid_t)); + nh->my_handle = mh; + nh->node = d; + if (add_resource(&cdp->nodeids, nh, match_handle) == NULL) { + log_message(MSG_ERROR, "add_my_handle: add_resource failed\n"); + } +} + +void +allocate_phandle(fcode_env_t *env) +{ + private_data_t *pd; + common_data_t *cdp; + int error; + char *service; + device_t *current; + fc_cell_t hcell; + + if ((cdp = env->private) == NULL) { + log_message(MSG_ERROR, "allocate_phandle: NULL common\n"); + return; + } + + if (!cdp->init_done) + return; + + current = MYSELF->device; + ASSERT(current); + + if (cdp->first_node) { + service = FC_CONFIG_CHILD; + cdp->first_node = 0; + } else { + service = FC_ALLOC_PHANDLE; + } + + pd = MALLOC(sizeof (private_data_t)); + pd->common = cdp; + pd->parent = (fc_phandle_t) revert_phandle(env, current->parent); + pd->upload = (cdp->init_done == 1); + current->private = pd; + + error = fc_run_priv(cdp, service, 0, 1, &hcell); + + pd->node = fc_cell2phandle(hcell); + + add_my_handle(env, pd->node, current); +} + +fc_phandle_t +fc_get_ap(common_data_t *cdp) +{ + fc_cell_t hcell; + int error; + + error = fc_run_priv(cdp, FC_AP_PHANDLE, 0, 1, &hcell); + + if (error) + exit(1); + + return (fc_cell2phandle(hcell)); +} + + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + env->convert_phandle = convert_phandle; + env->revert_phandle = revert_phandle; + env->allocate_phandle = allocate_phandle; + FORTH(0, "use-os-handles", do_use_os_handles); + FORTH(0, "use-fake-handles", do_use_fake_handles); +} diff --git a/usr/src/lib/efcode/fcdriver/property.c b/usr/src/lib/efcode/fcdriver/property.c new file mode 100644 index 0000000000..5634d1407d --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/property.c @@ -0,0 +1,180 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + + +static char *prop_buf; + +static int +getproplen(common_data_t *cdp, fc_phandle_t node, char *propname, int inherit) +{ + fc_cell_t len; + char *service; + int error; + + service = inherit ? FC_GET_IN_PROPLEN : FC_GET_PKG_PROPLEN; + + error = fc_run_priv(cdp, service, 2, 1, fc_phandle2cell(node), + fc_ptr2cell(propname), &len); + if (error) + return (-1); + + return (fc_cell2int(len)); +} + +static int +getprop(common_data_t *cdp, fc_phandle_t node, char *propname, char *buf, + int inherit) +{ + fc_cell_t len; + char *service; + int error; + + service = inherit ? FC_GET_IN_PROP : FC_GET_PKG_PROP; + + error = fc_run_priv(cdp, service, 3, 1, fc_phandle2cell(node), + fc_ptr2cell(buf), fc_ptr2cell(propname), &len); + if (error) + return (-1); + + return (fc_cell2int(len)); +} + +int +os_get_prop_common(common_data_t *cdp, fc_phandle_t node, char *name, + int inherit, char **buf, int *len) +{ + int i, j; + char *bp; + + i = getproplen(cdp, node, name, inherit); + if (i <= 0) { + /* + * OK for properties to be undefined, suppress error message + * unless some debug is on. + */ + if (get_interpreter_debug_level()) + log_message(MSG_ERROR, "os_get_prop_common:" + " getproplen(%s) returned %d\n", name, i); + return (-1); + } + bp = MALLOC(i); + + j = getprop(cdp, node, name, bp, inherit); + if (i != j) { + /* + * It's an error if getproplen succeeded but getprop didn't + * return a matching length. + */ + log_message(MSG_ERROR, "os_get_prop_common: getprop(%s)" + " return %d, getproplen returned %d\n", name, j, i); + FREE(bp); + return (-2); + } + memcpy(prop_buf, bp, i); + *buf = prop_buf; + *len = i; + FREE(bp); + return (0); +} + +static void +os_get_prop(fcode_env_t *env, int inherit, device_t *dev) +{ + fc_phandle_t node; + char *name; + char *prop; + int len; + private_data_t *pd; + + ASSERT(dev); + + pd = dev->private; + ASSERT(pd); + + name = pop_a_string(env, &len); + + node = pd->node; + if (node == NULL) { + log_message(MSG_ERROR, "os_get_prop: NULL node: %s\n", + get_path(env, dev)); + PUSH(DS, TRUE); + } else if (os_get_prop_common(pd->common, node, name, inherit, &prop, + &len)) { + PUSH(DS, TRUE); + } else { + PUSH(DS, (fstack_t)prop); + PUSH(DS, len); + PUSH(DS, FALSE); + } +} + +static void +os_get_package_prop(fcode_env_t *env) +{ + device_t *dev; + + CONVERT_PHANDLE(env, dev, POP(DS)); + os_get_prop(env, 0, dev); +} + +static void +os_get_inherited_prop(fcode_env_t *env) +{ + os_get_prop(env, 1, env->attachment_pt); +} + +void +install_property_vectors(fcode_env_t *env, device_t *d) +{ + d->vectors.get_package_prop = os_get_package_prop; + d->vectors.get_inherited_prop = os_get_inherited_prop; +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + prop_buf = MALLOC(4096); + +} diff --git a/usr/src/lib/efcode/fcdriver/sparcv9/Makefile b/usr/src/lib/efcode/fcdriver/sparcv9/Makefile new file mode 100644 index 0000000000..ec8b9d5c96 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) $(FCPACKAGE64) + +install: all $(ROOTLIBS64) diff --git a/usr/src/lib/efcode/fcdriver/upload.c b/usr/src/lib/efcode/fcdriver/upload.c new file mode 100644 index 0000000000..14b8989295 --- /dev/null +++ b/usr/src/lib/efcode/fcdriver/upload.c @@ -0,0 +1,178 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> +#include <fcntl.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static void +create_node(fcode_env_t *env, device_t *d) +{ + int error; + prop_t *p; + instance_t *ih; + char *service = FC_NEW_DEVICE; + private_data_t *pd, *ppd; + char *unit_str; + + pd = (private_data_t *)d->private; + ppd = (private_data_t *)d->parent->private; + + ih = MYSELF; + MYSELF = open_instance_chain(env, d, 0); + p = lookup_package_property(env, "name", d); + if (p == NULL) { + forth_abort(env, "create_node: '%s' name prop not found\n", + get_path(env, d)); + } + + debug_msg(DEBUG_UPLOAD, "Create Node: %p\n", pd->node); + debug_msg(DEBUG_UPLOAD, " Device Name: '%s'\n", p->data); + debug_msg(DEBUG_UPLOAD, " Parent : %p\n", ppd->node); + + my_unit(env); + (void) call_my_parent(env, "encode-unit"); + unit_str = pop_a_duped_string(env, NULL); + if (unit_str == NULL) { + unit_str = STRDUP(""); + } + + debug_msg(DEBUG_UPLOAD, " Unit Addr : '%s'\n", unit_str); + + error = fc_run_priv(pd->common, FC_NEW_DEVICE, 4, 0, + fc_phandle2cell(pd->node), fc_phandle2cell(ppd->node), + fc_ptr2cell(unit_str), fc_ptr2cell(p->data)); + + FREE(unit_str); + close_instance_chain(env, MYSELF, 0); + MYSELF = ih; + + if (error) + log_message(MSG_ERROR, "%s: parent: '%s' new: '%s'\n", service, + get_path(env, d->parent), p->data); +} + +static void +finish_node(fcode_env_t *env, device_t *d) +{ + private_data_t *pd; + int error; + + pd = (private_data_t *)d->private; + + debug_msg(DEBUG_UPLOAD, "Finish Node: %p\n", pd->node); + + error = fc_run_priv(pd->common, FC_FINISH_DEVICE, 1, 0, + fc_phandle2cell(pd->node)); + if (error) + log_message(MSG_ERROR, "%s: failed\n", FC_FINISH_DEVICE); +} + +static void +upload_properties(fcode_env_t *env, device_t *d) +{ + prop_t *p; + private_data_t *pd; + int error; + + pd = (private_data_t *)d->private; + debug_msg(DEBUG_UPLOAD, "Upload Properties: node %p upload: %d\n", + pd->node, pd->upload); + + if (!pd->upload) + return; + + for (p = d->properties; p; p = p->next) { + DEBUGF(UPLOAD, print_property(env, p, " Upload: ")); + + error = fc_run_priv(pd->common, FC_CREATE_PROPERTY, 4, 0, + fc_phandle2cell(pd->node), fc_int2cell(p->size), + fc_ptr2cell(p->data), fc_ptr2cell(p->name)); + + if (error) + log_message(MSG_ERROR, "%s: '%s' failed\n", + FC_CREATE_PROPERTY, p->name); + } +} + +static void +upload_node(fcode_env_t *env, device_t *d) +{ + private_data_t *pd = (private_data_t *)d->private; + + if (pd) { + debug_msg(DEBUG_UPLOAD, "Upload Node: dev: %p node: %p" + " upload: %d\n", d, pd->node, pd->upload); + if (pd->upload) { + create_node(env, d); + upload_properties(env, d); + finish_node(env, d); + } + } else + debug_msg(DEBUG_UPLOAD, "Upload Node: dev: %p NULL private\n", + d); +} + +void +upload_nodes(fcode_env_t *env) +{ + debug_msg(DEBUG_UPLOAD, "Upload Nodes: Recursing Tree\n"); + recurse_tree(env, env->root_node, upload_node); +} + +void +validate_nodes(fcode_env_t *env) +{ + int error; + common_data_t *cdp = env->private; + + error = ioctl(cdp->fcode_fd, FC_VALIDATE); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "upload-nodes", upload_nodes); + FORTH(0, "validate-nodes", validate_nodes); +} diff --git a/usr/src/lib/efcode/fcode_test/Makefile b/usr/src/lib/efcode/fcode_test/Makefile new file mode 100644 index 0000000000..e45ef0b706 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/Makefile @@ -0,0 +1,56 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/efcode/fcode_test/Makefile +# + +include ../../../Makefile.master + +TESTSRCS = test.fth calling.fth iftest.fth arithmetic.fth create.fth \ + stack.fth bytemanipulate.fth loop.fth find.fth values.fth \ + instance.fth catch.fth storage.fth case.fth access.fth misc.fth \ + parse.fth + +PROGS = test.fcode test64.fcode + +TOKENIZE = $(ONBLD_TOOLS)/bin/sparc/tokenize + +.SUFFIXES: .fcode .fth $(SUFFIXES) + +install all: $(PROGS) + +.fth.fcode: + $(TOKENIZE) $< + +test.fcode: $(TESTSRCS) + +clean: + $(RM) $(PROGS) + +clobber: clean + +install_h: diff --git a/usr/src/lib/efcode/fcode_test/access.fth b/usr/src/lib/efcode/fcode_test/access.fth new file mode 100644 index 0000000000..9f441d83b4 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/access.fth @@ -0,0 +1,70 @@ +\ #pragma ident "%Z%%M% %I% %E% SMI" +\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License, Version 1.0 only +\ (the "License"). You may not use this file except in compliance +\ with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + +." Access test: " +0 value word-test +0 value char-test +0 value end-test +0 value end-test2 +variable var-test +create access-test + h# 80004000 l, + here to word-test + h# 8000 w, h# 4000 w, + here to char-test + h# 1 c, h# 2 c, h# 3 c, h# 4 c, + here to end-test + h# a55aa55a , + here to end-test2 + + + " l,+" access-test la1+ word-test = .passed? + " w,+" word-test 2 wa+ char-test = .passed? + " c,+" char-test 4 ca+ end-test = .passed? + " ,+" end-test cell+ end-test2 = .passed? + " c@.1" char-test c@ h# 1 = .passed? + " c@.2" char-test char+ c@ h# 2 = .passed? + " c@.3" char-test 2 ca+ c@ h# 3 = .passed? + " c@.4" char-test 3 ca+ c@ h# 4 = .passed? + " w@.1" access-test w@ h# 8000 = .passed? + " w@.2" access-test wa1+ w@ h# 4000 = .passed? + " w@.3" word-test w@ h# 8000 = .passed? + " w@.4" word-test wa1+ w@ h# 4000 = .passed? + " w@.5" char-test w@ h# 0102 = .passed? + " w@.6" char-test wa1+ w@ h# 0304 = .passed? + " <w@" access-test <w@ h# ffff8000 = .passed? + " l@.1" access-test l@ h# 80004000 = .passed? + " l@.2" word-test l@ h# 80004000 = .passed? + " l@.3" char-test l@ h# 01020304 = .passed? + " @!.1" h# 5a5aa5a5 var-test ! var-test @ h# 5a5aa5a5 = .passed? + " c@c!.1" h# 55 var-test c! var-test c@ h# 55 = .passed? + " w@w!.1" h# aa55 var-test w! var-test w@ h# aa55 = .passed? + " l@l!.1" h# 5555aaaa var-test l! var-test l@ h# 5555aaaa = .passed? + " @!.1" h# aaaa5555 var-test ! var-test @ h# aaaa5555 = .passed? + " +!.1" 2 var-test ! 3 var-test +! var-test @ 5 = .passed? + " 2!.1" 1 2 access-test 2! access-test @ 2 = + access-test cell+ @ 1 = and .passed? + " 2@.1" access-test 2@ 2 = swap 1 = and .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/arithmetic.fth b/usr/src/lib/efcode/fcode_test/arithmetic.fth new file mode 100644 index 0000000000..8a91e7d88d --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/arithmetic.fth @@ -0,0 +1,174 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Simple 0 Logic Tests: " + " 0 invert" 0 invert .passed? + " 0 0=" 0 0= .passed? + " -1 invert" -1 invert 0= .passed? + " 1 0<>" 1 0<> .passed? + " 1 0=" 1 0= invert .passed? + " 1 0<>" 1 0<> .passed? + " 0 0>=" 0 0>= .passed? + " 1 0>=" 1 0>= .passed? + " -1 0>=" -1 0>= invert .passed? + " 1 0>" 1 0> .passed? + " 0 0>" 0 0> invert .passed? + " -1 0<" -1 0< .passed? + " 0 0<" 0 0< invert .passed? + " 0 0<=" 0 0<= .passed? + " -1 0<=" -1 0<= .passed? + " 1 0<=" 1 0<= invert .passed? +cr + +." Positive Arithmetic Comparision Tests: " + " 1 0 >" 1 0 > .passed? + " 1 1 >=" 1 1 >= .passed? + " 1 1 >" 1 1 > invert .passed? + " 0 1 <" 0 1 < .passed? + " 0 0 <=" 0 0 <= .passed? + " 1 0 <" 1 0 < invert .passed? + " 0 0 =" 0 0 = .passed? + " 0 1 =" 0 1 = invert .passed? + " 0 1 <>" 0 1 <> .passed? + " 1 1 <>" 1 1 <> invert .passed? +cr + +." Signed Comparison Tests: " + " -1 1 >" -1 1 > invert .passed? + " -1 -2 >" -1 -2 > .passed? + " -1 0 <" -1 0 < .passed? + " -2 -1 <" -2 -1 < .passed? +cr + +." Unsigned Comparison Tests: " + " -1 0 u>" -1 0 u> .passed? + " -1 0 u>=" 1 1 u>= .passed? + " 1 -1 <" 2 1 >= .passed? + " 0 1 >=" 0 1 >= invert .passed? + " 0 -1 u<" 0 -1 u< .passed? + " 0 -1 u<=" 0 -1 u<= .passed? + " 2 -2 u<=" 2 -2 u<= .passed? +cr + +." Arithmetic Tests: " + " 1 1 +" 1 1 + 2 = .passed? + " 1 1 -" 1 1 - 0 = .passed? + " 1 negate " 1 negate 1+ 0= .passed? + " 0 1 -" 0 1 - -1 = .passed? + " -1 abs" -1 abs 1 = .passed? + " -1 2 min" -1 2 min 1+ 0= .passed? + " 2 -1 min" 2 -1 min 1+ 0= .passed? + " 3 2 max" 3 2 max 3 = .passed? + " 2 3 max" 2 3 max 3 = .passed? +cr + +." Binary Logic: " + " 3 1 and" 3 1 and 1 = .passed? + " 2 1 and" 2 1 and 0= .passed? + " 1 1 or" 1 1 or 1 = .passed? + " 3 1 xor" 3 1 xor 2 = .passed? +cr + +." Shifting: " + " (short) lshift" h# 11 8 lshift h# 1100 = .passed? + " (short) rshift" h# 1122 8 rshift h# 11 = .passed? + " (long) lshift" h# 1 d# 31 lshift 1- h# 7fffffff = .passed? + " (long) rshift" h# 80 d# 24 lshift d# 31 rshift 1 = .passed? + " >>a" -4 1 >>a -2 = .passed? +cr + +." Sized Arithmetic Tests: " + " u2/" 0 0 0 h# 80 bljoin u2/ h# 4000.0000 = .passed? + " 2/" -4 2/ -2 = .passed? + " 2*" h# 4000.0000 dup 1 lshift swap 2* = .passed? + " /c" 1 /c = .passed? + " /w" 2 /w = .passed? + " /l" 4 /l = .passed? + " /n" 4 /n = 8 /n = or .passed? + " ca+" h# 4000 3 ca+ h# 4003 = .passed? + " wa+" h# 4000 3 wa+ h# 4006 = .passed? + " la+" h# 4000 3 la+ h# 400c = .passed? + " na+" h# 4000 3 na+ h# 4000 3 /n * + = .passed? + " char+" h# 4000 char+ h# 4001 = .passed? + " wa1+" h# 4000 wa1+ h# 4002 = .passed? + " la1+" h# 4000 la1+ h# 4004 = .passed? + " cell+" h# 4000 cell+ h# 4000 /n + = .passed? + " chars" 4 chars 4 = .passed? + " /w*" 8 /w* h# 10 = .passed? + " /l*" 4 /l* h# 10 = .passed? + " cells" 4 cells 4 /n * = .passed? +cr + +." Division related Tests: " + " /mod (+ +)" 5 2 /mod 2 = swap 1 = and .passed? + " /mod (- -)" -5 -2 /mod 2 = swap -1 = and .passed? + " /mod (+ -)" 5 -2 /mod -3 = swap -1 = and .passed? + " /mod (- +)" -5 2 /mod -3 = swap 1 = and .passed? + " / (+ +)" 5 2 / 2 = .passed? + " / (- -)" -5 -2 / 2 = .passed? + " / (+ -)" 5 -2 / -3 = .passed? + " / (- +)" -5 2 / -3 = .passed? + " mod (+ +)" 5 2 mod 1 = .passed? + " mod (- -)" -5 -2 mod -1 = .passed? + " mod (+ -)" 5 -2 mod -1 = .passed? + " mod (- +)" -5 2 mod 1 = .passed? +cr + +." Signed Multiply/Divide Tests:" + " * (+ +)" 2 3 * 6 = .passed? + " * (- +)" -3 3 * -9 = .passed? + " * (+ -)" 4 -2 * -8 = .passed? + " * (- -)" -4 -3 * 12 = .passed? +cr + +." Unsigned Multiply/Divide Tests: " + " um*" 1 2 um* 0= swap 2 = and .passed? + " um/mod" 5 0 2 um/mod 2 = swap 1 = and .passed? + " u/mod" 5 2 u/mod 2 = swap 1 = and .passed? +cr + +." Ranged Tests: " + " within (!0)" 2 1 3 within .passed? + " within (0 hi)" 3 1 3 within 0= .passed? + " within (!0 lo)" 1 1 3 within .passed? + " within (0 >)" 0 1 3 within 0= .passed? + " within (0 <)" 4 1 3 within 0= .passed? + " within (-ve)" 0 -5 5 within .passed? + " within (- -)" -7 -10 -5 within .passed? + " between (!0)" 2 1 3 between .passed? + " between (!0 lo)" 1 1 3 between .passed? + " between (!0 hi)" 3 1 3 between .passed? + " between (0 >)" 4 1 3 between 0= .passed? + " between (0 <)" 0 1 3 between 0= .passed? + " between (-ve)" 0 -5 5 between .passed? + " between (- -)" -7 -10 -5 between .passed? + " bounds" -1 3 bounds -1 = swap 2 = and .passed? +cr + +." Double Arithmetic: " + " d+" 1 2 3 4 d+ 6 = swap 4 = and .passed? + " d-" 3 4 2 1 d- 3 = swap 1 = and .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/bytemanipulate.fth b/usr/src/lib/efcode/fcode_test/bytemanipulate.fth new file mode 100644 index 0000000000..772e07f6f1 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/bytemanipulate.fth @@ -0,0 +1,56 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Byte Split tests: " + " lbsplit" h# 11223344 lbsplit + h# 11 = swap h# 22 = and swap + h# 33 = and swap h# 44 = and .passed? + " lwsplit" h# 11223344 lwsplit + h# 1122 = swap h# 3344 = and .passed? + " wbsplit" h# 31122 wbsplit + h# 11 = swap h# 22 = and .passed? + " wljoin" h# beef h# dead wljoin h# deadbeef = .passed? + " bljoin" h# 111 h# 222 h# 333 h# 444 bljoin + h# 44332211 = .passed? + " bwjoin" h# 111 h# 222 bwjoin h# 2211 = .passed? + " lbflip" h# 11223344 lbflip h# 44332211 = .passed? + " lwflip" h# 11223344 lwflip h# 33441122 = .passed? + " wbflip" h# 31122 wbflip h# 2211 = .passed? +create flip-area + h# 01020304 l, + " wbflips" flip-area /l wbflips flip-area l@ h# 02010403 = .passed? + " lwflips" flip-area /l lwflips flip-area l@ h# 04030201 = .passed? + " lbflips" flip-area /l lbflips flip-area l@ h# 01020304 = .passed? +cr + +." Memory ops: " + " comp +" " abcde" drop " abcd" drop 5 comp 1 = .passed? + " comp -" " abcd" drop " abcde" comp -1 = .passed? + " comp =" " abcdef" drop " abcdef" comp 0= .passed? + " alloc-mem" h# 100 dup alloc-mem ?dup + if 2swap -1 else drop false then .passed? + " free-mem" 2swap swap free-mem 1 .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/calling.fth b/usr/src/lib/efcode/fcode_test/calling.fth new file mode 100644 index 0000000000..85eedc7f8b --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/calling.fth @@ -0,0 +1,36 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +: t1 ascii W emit ; +: t2 ascii L emit ; +: t3 t2 ascii D emit ; +: t4 t1 ascii O emit ; +: t5 t4 ascii R emit ; +: t6 t5 t3 space ; +: t7 ." hello " t6 ; +: t8 t7 ." and everyone" ; + +cr ." > " t8 cr diff --git a/usr/src/lib/efcode/fcode_test/case.fth b/usr/src/lib/efcode/fcode_test/case.fth new file mode 100644 index 0000000000..58b7dcbc52 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/case.fth @@ -0,0 +1,42 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Case: " +: case1 ( n -- str ) + case + 0 of " zero" >r >r endof + 1 of " one" >r >r endof + 2 of " two" >r >r endof + dup <# u#s u#> >r >r + endcase + r> r> +; + " case.1" 0 case1 drop " zero" comp invert .passed? + " case.2" 1 case1 drop " one" comp invert .passed? + " case.3" 2 case1 drop " two" comp invert .passed? + " case.4" 3 case1 drop " 3" comp invert .passed? + " case.5" 4 case1 drop " 4" comp invert .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/catch.fth b/usr/src/lib/efcode/fcode_test/catch.fth new file mode 100644 index 0000000000..c3493bcf41 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/catch.fth @@ -0,0 +1,33 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." catch/throw: " + : ttest ( n -- ) throw 0 ; + : ttest1 ( -- ) 0 ['] ttest catch 0= swap 0= and ; + : ttest2 ( -- ) 1 1 ['] ttest catch nip 1 = swap 1 = and ; + " 0 throw" ttest1 .passed? + " 1 throw" ttest2 .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/create.fth b/usr/src/lib/efcode/fcode_test/create.fth new file mode 100644 index 0000000000..be83cd7d5a --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/create.fth @@ -0,0 +1,40 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Create Test: " +create table + ascii p c, + ascii a c, + ascii s c, + ascii s c, + ascii e c, + ascii d c, + +here table - create table-len c, + +: table-test ( -- ) table table-len c@ ; + " create.1" " passed" drop table-test comp invert .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/find.fth b/usr/src/lib/efcode/fcode_test/find.fth new file mode 100644 index 0000000000..443bb60fa3 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/find.fth @@ -0,0 +1,35 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License, Version 1.0 only +\ (the "License"). You may not use this file except in compliance +\ with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + +." Execute test: " + : etest ['] 1 dup dup execute swap execute + swap execute + ; + " " etest 3 = .passed? + " evaluate.1" " 1 2 +" evaluate 3 = .passed? +cr + +." $find testing: " +" $find.1" 0 1 " drop" $find if execute then 0= .passed? +" $find.2" " qwerty" $find if false else " qwerty" $= then .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/iftest.fth b/usr/src/lib/efcode/fcode_test/iftest.fth new file mode 100644 index 0000000000..b087cff1d1 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/iftest.fth @@ -0,0 +1,118 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License, Version 1.0 only +\ (the "License"). You may not use this file except in compliance +\ with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + +cr ." Simple interpreted IF THEN test: " +1 if .passed then space +0 if .failed then space +cr + +." Simple interpreted IF ELSE THEN test: " +0 if .failed else .passed then space +1 if .passed else .failed then space +cr + +." Nested interpreted IF test: " +1 1 1 0 0 1 0 0 +if if .failed else .failed then space +else if .failed else .passed then space +then +if if .failed else .passed then space +else if .failed else .failed then space +then +if if .failed else .failed then space +else if .passed else .failed then space +then +if if .passed else .failed then space +else if .failed else .failed then space +then +cr + +." Compiled single IF tests:" space +: if-true? if .passed space 0 exit then .failed space 0 ; 1 if-true? +: if-false? if .failed space 1 exit then .passed space 1 ; if-false? +: true? if .passed else .failed then space 0 ; true? +: false? if .failed else .passed then space ; false? + +cr + +." Nested compiled IF test: " +: if-test1 ( -- ) + 0 1 0 if + .failed + else + if + dup if .failed then + if .failed else .passed then + else + .failed + then + then +; if-test1 space + +: .passed? ( str,len flag ) + if if then if then .passed space else cr type space .failed cr then +; + +: if-test2 ( x x x -- ) + if + if + if + 7 + else + 6 + then + else + if + 5 + else + 4 + then + then + else + if + if + 3 + else + 2 + then + else + if + 1 + else + 0 + then + then + then +; + + " if-test2.0" 0 0 0 if-test2 0 = .passed? + " if-test2.1" 1 0 0 if-test2 1 = .passed? + " if-test2.2" 0 1 0 if-test2 2 = .passed? + " if-test2.3" 1 1 0 if-test2 3 = .passed? + " if-test2.4" 0 0 1 if-test2 4 = .passed? + " if-test2.5" 1 0 1 if-test2 5 = .passed? + " if-test2.6" 0 1 1 if-test2 6 = .passed? + " if-test2.7" 1 1 1 if-test2 7 = .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/instance.fth b/usr/src/lib/efcode/fcode_test/instance.fth new file mode 100644 index 0000000000..c37f08a5a1 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/instance.fth @@ -0,0 +1,28 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +3 instance value ivar-foo +4 instance value ivar-bar diff --git a/usr/src/lib/efcode/fcode_test/loop.fth b/usr/src/lib/efcode/fcode_test/loop.fth new file mode 100644 index 0000000000..72f860ea9e --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/loop.fth @@ -0,0 +1,97 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License, Version 1.0 only +\ (the "License"). You may not use this file except in compliance +\ with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + +." Interactive begin .. while .. repeat: " + " no loop (1) " 1 begin 0 while 1- repeat .passed? + " loop to 0 (1)" 9 begin dup while 1- repeat 0= .passed? +cr +." Compiled begin .. while .. repeat: " + : btest1 1 begin 0 while 1- repeat .passed? ; + : btest2 9 begin dup while 1- repeat 0= .passed? ; + " no loop (2) " btest1 + " loop to 0 (2)" btest2 +cr +." Interactive begin..until: " + " no loop (3)" 1 begin dup until .passed? + " loop to 0 (3)" 9 begin 1- dup 0= until 0= .passed? +cr +." Compiled begin..until: " + : btest3 1 begin dup until .passed? ; + : btest4 9 begin 1- dup 0= until 0= .passed? ; + " no loop (4)" btest3 + " loop to 0 (4)" btest4 +cr +." Interactive do .. loop: " + " loop (1)" 0 h# 10 0 do drop i loop h# f = .passed? + " no loop (1)" 1 0 0 ?do 1- loop .passed? + " leave (1)" h# 10 0 do i 5 = if 1 leave drop 0 then loop .passed? +cr +." Compiled do .. loop: " + : loop1 do drop i loop h# f = .passed? ; + : loop2 ?do 1- loop .passed? ; + : loop3 do i 3 = if drop i leave 0 then loop ; + : loop7 do i 4 = if drop i unloop exit then loop ; + " loop (2)" 0 h# 10 0 loop1 + " no loop (2)" 1 0 0 loop2 + " leave (2)" 3 4 0 loop3 3 = .passed? + " unloop" 5 6 0 loop7 4 = .passed? +cr +." Interactive do .. +loop: " + " loop by 2" 0 h# 10 0 do drop i 2 +loop h# e = .passed? + " loop down by 2" 0 -2 h# 10 do drop i -2 +loop h# -2 = .passed? +cr +." Compiled do .. +loop: " + : loop4 0 h# 10 0 do drop i 2 +loop h# e = .passed? ; + : loop5 0 -2 h# 10 do drop i -2 +loop -2 = .passed? ; + " loop (4)" loop4 + " loop (5)" loop5 +cr +." Nested loops: " + : loop6 0 h# 4 0 do 8 0 do 1 j 3 lshift i + lshift xor loop loop ; + " i,j sum" loop6 lwsplit over = swap h# ffff = and .passed? +cr +." Negative Limit Loops: " + " loop.7" h# 10 -37 8 bounds do drop i loop -30 = .passed? + " loop.8" h# 10 -37 -30 do drop i -1 +loop -37 = .passed? +cr +." Compiled begin...again: " + : loop9 begin true exit again false ; loop9 " loop9" rot .passed? + 0 value in-count + 0 value out-count + : loop10 + begin + out-count 1+ to out-count + begin + in-count 10 >= if + exit + then in-count 1+ to in-count + again + -1 to in-count + exit + again + -2 to in-count + ; + " loop.10" loop10 in-count 10 = out-count 1 = and .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/misc.fth b/usr/src/lib/efcode/fcode_test/misc.fth new file mode 100644 index 0000000000..20dee7aabd --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/misc.fth @@ -0,0 +1,188 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Buffer: " + h# 20 buffer: my-unit-str + " abcd" my-unit-str pack drop + " pack.1" my-unit-str c@ 4 = .passed? + " pack.2" my-unit-str 1 + c@ ascii a = .passed? + " pack.3" my-unit-str 2 + c@ ascii b = .passed? + " pack.4" my-unit-str 3 + c@ ascii c = .passed? + " pack.5" my-unit-str 4 + c@ ascii d = .passed? + " count.1" my-unit-str count " abcd" $= .passed? +cr + +." Formatting: " + " fmt.1" 1 h# 23 <# #s #> " 2300000001" $= .passed? + " fmt.2" 1 h# 23 <# # # #> " 01" $= .passed? + " fmt.3" h# 123 <# u#s u#> " 123" $= .passed? + " fmt.4" h# 123 <# u# ascii X hold u# u#> " 2X3" $= .passed? + d# 10 base ! + " fmt.5" d# -123 <# dup abs u#s swap sign u#> " -123" $= .passed? + " fmt.6" d# 123 <# dup abs u#s swap sign u#> " 123" $= .passed? + " fmt.7" " -123" $number invert swap d# -123 = and .passed? + d# 16 base ! + " fmt.8" " 32a" $number invert swap h# 32a = and .passed? + " fmt.9" " xyzzy" $number .passed? + : dnumber ( n -- str len ) + base @ >r d# 10 base ! + <# dup abs u#s swap sign u#> + r> base ! + ; + " fmt.10" d# 12345678 dnumber " 12345678" $= .passed? + " fmt.11" d# -87654321 dnumber " -87654321" $= .passed? + " fmt.12" #out @ space #out @ 1 - = .passed? + " fmt.13" #line @ cr #out @ #line @ rot 1 + = swap 0= and .passed? + " fmt.14" #line @ (cr #out @ #line @ rot = swap 0= and .passed? + " fmt.15" bs h# 8 = .passed? + " fmt.16" bell h# 7 = .passed? + " fmt.17" bl h# 20 = .passed? + " fmt.18" ascii 5 d# 10 digit swap 5 = and .passed? + " fmt.19" ascii x d# 16 digit invert swap ascii x = and .passed? +cr + +." (is-user-word): " + : xyzzy 1 2 3 ; + " xx" ' xyzzy (is-user-word) + " xx" $find if .passed space execute else .failed then + " iuw.1" 2 pick 3 = .passed? + " iuw.2" 3 pick 2 = .passed? + " iuw.3" 4 pick 1 = .passed? + drop drop drop +cr + +." Move/Fill/Upper/Lower:" + " xyzzy" my-unit-str swap move + " move.1" my-unit-str " xyzzy" comp 0= .passed? + my-unit-str 9 ascii A fill + my-unit-str 6 ascii X fill + " fill.1" my-unit-str " XXXXXXAAA" comp 0= .passed? + 9 0 do my-unit-str i + dup c@ lcc swap c! loop + " lcc.1" my-unit-str " xxxxxxaaa" comp 0= .passed? + 9 0 do my-unit-str i + dup c@ upc swap c! loop + " upc.1" my-unit-str " XXXXXXAAA" comp 0= .passed? +cr + +." >body/body>: " +external + : xx 1 2 3 ; +headers + " >body" ' xx >body ' xx /n + = .passed? + " body>" ' xx dup >body body> = .passed? +cr + +." Fcode-revision: " + " Fcode-revision" fcode-revision h# 30000 = .passed? +cr + +." Defer/Behavior: " + defer defer-word + ' xx to defer-word + " defer.1" defer-word 3 = swap 2 = and swap 1 = and .passed? + " behavior.1" ' defer-word behavior ' xx = .passed? +cr + +." Aligned: " + variable alvar + " align.1" alvar aligned alvar = .passed? + " align.2" alvar /c - aligned alvar = .passed? + " align.3" alvar char+ aligned alvar la1+ = .passed? +cr + +." Field: " +struct + /n field >x1 + /l field >x2 + /w field >x3 + /c field >x4 +constant /field-test + " field.1" /field-test /n /l /w /c + + + = .passed? + " field.2" 0 >x1 0 = .passed? + " field.3" 0 >x2 /n = .passed? + " field.4" 0 >x3 /n /l + = .passed? + " field.5" 0 >x4 /n /l /w + + = .passed? +cr + + +." Properties: " + 0 value root-phandle + " use-fake-handles" $find if execute else 2drop then + " /" " (cd)" $find if execute else 2drop then + " /" find-package if to root-phandle then + 1 encode-int " int-prop" property + 1 2 encode-phys " phys-prop" property + 1 2 3 reg + " XYZZY" model + 1 encode-int 2 encode-int encode+ " 2int-prop" property + " abcd" encode-string " string-prop" property + " wxyz" encode-bytes " bytes-prop" property + " prop.1" " bytes-prop" root-phandle get-package-property if + .failed + else + " wxyz" $= .passed? + then + " prop.2" " string-prop" root-phandle get-package-property if + .failed + else + decode-string " abcd" $= nip nip .passed? + then + " prop.3" " int-prop" root-phandle get-package-property if + .failed + else + decode-int 1 = nip nip .passed? + then + " prop.4" " phys-prop" root-phandle get-package-property if + .failed + else + decode-phys 2 = swap 1 = and nip nip .passed? + then + " prop.5" 0 0 root-phandle next-property if + " bytes-prop" $= .passed? + else + .failed + then + " prop.6" " string-prop" root-phandle next-property if + " 2int-prop" $= .passed? + else + .failed + then +cr + " .properties" $find if execute else 2drop then +cr + +." Timing/Alarm: " + " ms.1" get-msecs h# 100 ms get-msecs swap - h# 80 h# 150 between .passed? +\ 0 value alarm-happened +\ : alarm-word 1 to alarm-happened ." OK " ; +\ ' alarm-word 10 alarm +\ 0 +\ begin +\ 1 + dup 1000000 > alarm-happened 0<> or +\ until +\ drop +\ 0 0 alarm +\ " alarm.1" alarm-happened .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/parse.fth b/usr/src/lib/efcode/fcode_test/parse.fth new file mode 100644 index 0000000000..121cfdb3a1 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/parse.fth @@ -0,0 +1,56 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + + ." parse:" + : $= ( str1 len1 str2 len2 -- true/false ) + 2 pick <> if + 3drop false + else + swap dup 0= if + 3drop true + else + true swap 0 do + 2 pick i + c@ + 2 pick i + c@ + = and + loop nip nip + then + then + ; + : parse-test + " $= test.1" " abcd" " abcd" $= .passed? + " $= test.2" " abdc" " abcd" $= invert .passed? + " $= test.3" " abc" " abcd" $= invert .passed? + " 9600,8,n,1,-" + ascii , left-parse-string " 9600" $= " left-parse.1" rot .passed? + ascii , left-parse-string " 8" $= " left-parse.2" rot .passed? + ascii , left-parse-string " n" $= " left-parse.3" rot .passed? + ascii , left-parse-string " 1" $= " left-parse.4" rot .passed? + ascii , left-parse-string " -" $= " left-parse.5" rot .passed? + 2drop + ; + parse-test + cr diff --git a/usr/src/lib/efcode/fcode_test/stack.fth b/usr/src/lib/efcode/fcode_test/stack.fth new file mode 100644 index 0000000000..b0f4c2eb07 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/stack.fth @@ -0,0 +1,56 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Stack Manipulation: " + " drop" 1 0 drop .passed? + " swap" 1 2 1 swap drop = .passed? + " nip" 1 0 1 nip - 0= .passed? + " over" 1 2 over 1 = nip nip .passed? + " dup" 1 dup = .passed? + " tuck" 2 1 tuck nip = .passed? + " rot" 3 2 1 rot 3 = nip nip .passed? + " -rot" 3 2 1 -rot 2 = nip nip .passed? + " 2rot" 1 2 3 4 5 6 2rot 2 = swap 1 = and swap 6 = and swap + 5 = and swap 4 = and swap 3 = and .passed? + " 2dup" 1 -1 2dup + 0= nip nip .passed? + " ?dup" 0 1 ?dup = nip .passed? + " 2swap" 1 1 0 0 2swap and nip nip .passed? + " 2drop" 1 1 0 0 2drop and .passed? + " 2over" 1 2 0 0 2over 2swap 2drop rot = -rot = = .passed? + " roll" 1 2 3 4 3 roll 1 = nip nip nip .passed? + " depth" 0 0 depth 4 = nip nip .passed? +cr + +." Return Stack: " +: test-rs + " >r" 3 1 >r 2 >r 3 = .passed? + " r@" 3 r@ 2 = nip .passed? + " r>" 3 r> 2 = r> 1 = and nip .passed? +; test-rs +: bail-test ( -- ) r> drop ; +: bail ( -- ) 1 bail-test drop 0 ; + " Manipulate" bail .passed? +cr diff --git a/usr/src/lib/efcode/fcode_test/storage.fth b/usr/src/lib/efcode/fcode_test/storage.fth new file mode 100644 index 0000000000..1ffa4f79fb --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/storage.fth @@ -0,0 +1,46 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +." Runtime storage access: " + variable var-1 var-1 off + 4 constant const-1 + 5 value val-1 + " variable (off) (get)" var-1 @ 0= .passed? + " variable (on) (set)" var-1 on var-1 @ -1 = .passed? + " variable (set)" 2 var-1 ! var-1 @ 2 = .passed? + " constant.1" const-1 4 = .passed? + " value (get)" val-1 5 = .passed? + " value (set)" 2 to val-1 val-1 2 = .passed? +cr + +." Compile time storage access: " + " variable (get)" : vtest1 var-1 @ = .passed? ; 2 vtest1 + " variable (set)" : vtest2 1 var-1 ! 1 vtest1 ; vtest2 + " constant.2" : ctest const-1 const-1 + 8 = .passed? ; ctest + " value (get)" : vtest3 val-1 = .passed? ; 2 vtest3 + " value (set)" : vtest4 1 to val-1 1 vtest3 ; vtest4 +cr + diff --git a/usr/src/lib/efcode/fcode_test/test.fth b/usr/src/lib/efcode/fcode_test/test.fth new file mode 100644 index 0000000000..86e27b33f7 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/test.fth @@ -0,0 +1,70 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Use is subject to license terms. +\ +\ CDDL HEADER START +\ +\ The contents of this file are subject to the terms of the +\ Common Development and Distribution License, Version 1.0 only +\ (the "License"). You may not use this file except in compliance +\ with the License. +\ +\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ or http://www.opensolaris.org/os/licensing. +\ See the License for the specific language governing permissions +\ and limitations under the License. +\ +\ When distributing Covered Code, include this CDDL HEADER in each +\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ If applicable, add the following below this CDDL HEADER, with the +\ fields enclosed by brackets "[]" replaced with your own identifying +\ information: Portions Copyright [yyyy] [name of copyright owner] +\ +\ CDDL HEADER END +\ + +fcode-version1 + +alias headerless headers + + fload calling.fth + noop + : .noop noop noop ; + + : .failed ." failed!" ; + + : .passed ." OK" ; + + fload iftest.fth + + : .chkstk depth if ." Stack Changed: " .s cr then ; + + .chkstk + fload arithmetic.fth + .chkstk + fload stack.fth + .chkstk + fload create.fth + .chkstk + fload bytemanipulate.fth + .chkstk + fload loop.fth + .chkstk + fload storage.fth + .chkstk + fload access.fth + .chkstk + fload case.fth + .chkstk + fload catch.fth + .chkstk + fload parse.fth + .chkstk + fload find.fth + .chkstk + fload misc.fth + .chkstk + cr ." End of Tests" cr + +end0 + diff --git a/usr/src/lib/efcode/fcode_test/test64.fth b/usr/src/lib/efcode/fcode_test/test64.fth new file mode 100644 index 0000000000..56088018a5 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/test64.fth @@ -0,0 +1,126 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +fcode-version1 +." 64-bit Fcode operation tests" cr + + : .failed ." failed!" ; + + : .passed ." OK" ; + + : .chkstk depth if ." Stack Changed: " .s cr then ; + + : .passed? ( str,len flag ) + if if then if then .passed space else cr type space .failed cr then + ; + +\ comparisons only 32-bit... +: xl= ( xv lh ll -- flag ) + swap rot xlsplit rot = -rot = and +; + +: x= ( xv1 xv2 -- flag ) + xlsplit rot xlsplit rot = -rot = and +; +create test-64 + h# 01020304 l, + h# 05060708 l, + h# 81121314 l, + h# 85161718 l, + h# ffffffff l, + h# 80000000 l, + +." 64-bit access tests: " + " /x.1" /x 8 = .passed? + " xa1+.1" test-64 xa1+ test-64 /x + = .passed? + " xa+.1" test-64 2 xa+ test-64 /x 2 * + = .passed? + " x@.1" test-64 x@ h# 01020304 h# 05060708 xl= .passed? + " x@.2" test-64 xa1+ x@ h# 81121314 h# 85161718 xl= .passed? + " <l@.1" test-64 2 xa+ dup la1+ <l@ swap x@ x= .passed? + " bxjoin.1" 8 7 6 5 4 3 2 1 bxjoin test-64 x@ x= .passed? + " wxjoin.1" h# 0708 h# 0506 h# 0304 h# 0102 wxjoin test-64 x@ x= .passed? + " lxjoin.1" h# 05060708 h# 01020304 lxjoin test-64 x@ x= .passed? + " x!.1" h# 85161718 h# 81121314 lxjoin test-64 x! + test-64 x@ h# 81121314 h# 85161718 xl= .passed? + " x!.2" h# 05060708 h# 01020304 lxjoin test-64 x! + test-64 x@ h# 01020304 h# 05060708 xl= .passed? +cr +." 64-bit flips: " + " xbflip.1" test-64 x@ xbflip h# 08070605 h# 04030201 xl= .passed? + " xwflip.1" test-64 x@ xwflip h# 07080506 h# 03040102 xl= .passed? + " xlflip.1" test-64 x@ xlflip h# 05060708 h# 01020304 xl= .passed? + " xbsplit.1" test-64 x@ xbsplit bxjoin test-64 x@ x= .passed? + " xwsplit.1" test-64 x@ xwsplit wxjoin test-64 x@ x= .passed? + " xlsplit.1" test-64 x@ xlsplit lxjoin test-64 x@ x= .passed? + " xbflips.1" test-64 /x xbflips test-64 x@ + h# 08070605 h# 04030201 xl= .passed? + " xbflips.2" test-64 /x xbflips test-64 x@ + h# 01020304 h# 05060708 xl= .passed? + " xwflips.1" test-64 /x xwflips test-64 x@ + h# 07080506 h# 03040102 xl= .passed? + " xwflips.2" test-64 /x xwflips test-64 x@ + h# 01020304 h# 05060708 xl= .passed? + " xlflips.1" test-64 /x xlflips test-64 x@ + h# 05060708 h# 01020304 xl= .passed? + " xlflips.2" test-64 /x xlflips test-64 x@ + h# 01020304 h# 05060708 xl= .passed? +cr + + +0 value commatest-64-end +create commatest-64 + h# 01020304 h# 05060708 swap lxjoin x, + h# 81121314 h# 85161718 swap lxjoin x, + h# ffffffff h# 80000000 swap lxjoin x, + here to commatest-64-end + +." 64-bit xcomma: " + " x,.1" commatest-64 3 xa+ commatest-64-end = .passed? + " x,.2" test-64 x@ commatest-64 x@ x= .passed? + " x,.3" test-64 xa1+ x@ commatest-64 xa1+ x@ x= .passed? + " x,.4" test-64 2 xa+ x@ commatest-64 2 xa+ x@ x= .passed? +cr + +." 64-bit constant/value/variable: " +1 2 lxjoin constant const-64 +1 2 lxjoin value value-64 +variable var-64 + " const.1" const-64 2 1 xl= .passed? + " value.1" value-64 2 1 xl= .passed? + " value.2" 3 4 lxjoin to value-64 value-64 4 3 xl= .passed? + " var.1" const-64 var-64 ! var-64 @ 2 1 xl= .passed? +cr + +." 64-bit comparisions: " + \ FCode comparators are 32-bit only, upper 32-bits are ignored. + " 64comp.1" 1 2 lxjoin 1 = .passed? + " 64comp.2" 1 2 lxjoin 2 < .passed? + " 64comp.3" 2 1 2 lxjoin > .passed? + " 64comp.4" 0 2 lxjoin 0= .passed? + " 64comp.5" 1 2 lxjoin 0> .passed? +cr + +end0 diff --git a/usr/src/lib/efcode/fcode_test/values.fth b/usr/src/lib/efcode/fcode_test/values.fth new file mode 100644 index 0000000000..296f0e0387 --- /dev/null +++ b/usr/src/lib/efcode/fcode_test/values.fth @@ -0,0 +1,29 @@ +\ #ident "%Z%%M% %I% %E% SMI" +\ purpose: +\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ copyright: Use is subject to license terms. +\ copyright: +\ copyright: CDDL HEADER START +\ copyright: +\ copyright: The contents of this file are subject to the terms of the +\ copyright: Common Development and Distribution License, Version 1.0 only +\ copyright: (the "License"). You may not use this file except in compliance +\ copyright: with the License. +\ copyright: +\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +\ copyright: or http://www.opensolaris.org/os/licensing. +\ copyright: See the License for the specific language governing permissions +\ copyright: and limitations under the License. +\ copyright: +\ copyright: When distributing Covered Code, include this CDDL HEADER in each +\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE. +\ copyright: If applicable, add the following below this CDDL HEADER, with the +\ copyright: fields enclosed by brackets "[]" replaced with your own identifying +\ copyright: information: Portions Copyright [yyyy] [name of copyright owner] +\ copyright: +\ copyright: CDDL HEADER END +\ copyright: + +external +1 value var-foo +2 value var-bar diff --git a/usr/src/lib/efcode/gp2/Makefile b/usr/src/lib/efcode/gp2/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/gp2/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/gp2/Makefile.com b/usr/src/lib/efcode/gp2/Makefile.com new file mode 100644 index 0000000000..87d58209a9 --- /dev/null +++ b/usr/src/lib/efcode/gp2/Makefile.com @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = gp2.o +LIBRARY = lfc_gptwo.a +SYMLINKS = lfc_gptwo_gptwo.so + +include ../../Makefile.efcode diff --git a/usr/src/lib/efcode/gp2/gp2.c b/usr/src/lib/efcode/gp2/gp2.c new file mode 100644 index 0000000000..8832230f76 --- /dev/null +++ b/usr/src/lib/efcode/gp2/gp2.c @@ -0,0 +1,341 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +fstack_t +mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t lo, fstack_t len) +{ + private_data_t *pdp = DEVICE_PRIVATE(env); + fc_cell_t virt; + fstack_t mcookie = NULL; + char *service = "map-in"; + int error; + int offset = 0; + + /* + * The calculation of the offset, lo and len are left here + * due to historical precedence. + */ + + offset = lo & PAGEOFFSET; + lo &= PAGEMASK; + len = (len + offset + PAGEOFFSET) & PAGEMASK; + + error = fc_run_priv(pdp->common, service, 3, 1, fc_size2cell(len), + fc_uint32_t2cell(hi), fc_uint32_t2cell(lo), &virt); + + if (error) + throw_from_fclib(env, 1, "gp2:%s: failed\n", service); + + mcookie = mapping_to_mcookie(virt, len, NULL, NULL); + + if (mcookie == NULL) + throw_from_fclib(env, 1, "gp2:%s: mapping_to_mcookie failed\n", + service); + + mcookie += offset; + + debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %llx -> %x\n", service, + (uint64_t)virt, (uint32_t)mcookie); + + return (mcookie); +} + +static void +mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t len) +{ + private_data_t *pdp = DEVICE_PRIVATE(env); + fc_cell_t virt; + char *service = "map-out"; + int error; + int offset; + + /* + * The calculation of the offset, lo and len are left here + * due to historical precedence. + */ + + offset = mcookie & PAGEOFFSET; + mcookie &= PAGEMASK; + len = (len + offset + PAGEOFFSET) & PAGEMASK; + + if (!is_mcookie(mcookie)) { + log_message(MSG_ERROR, "gp2:%s: %x not an mcookie!\n", + service, (int)mcookie); + virt = mcookie; + } else { + virt = mcookie_to_addr(mcookie); + debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %x -> %llx\n", service, + (int)mcookie, (uint64_t)virt); + delete_mapping(mcookie); + } + + error = fc_run_priv(pdp->common, service, 2, 0, fc_size2cell(len), + virt); + if (error) + log_message(MSG_ERROR, "gp2:%s: failed\n", service); +} + +static void +do_get_portid(fcode_env_t *env) +{ + fstack_t phi, plo, portid; + private_data_t *pdp = DEVICE_PRIVATE(env); + + CHECK_DEPTH(env, 2, "gp2:get-portid"); + phi = POP(DS); + plo = POP(DS); + + portid = ((plo & 0xff800000) >> 23) | ((phi & 1) << 9); + debug_msg(DEBUG_REG_ACCESS, "gp2:get-portid ( %x %x ) -> %x\n", + (int)phi, (int)plo, (int)portid); + PUSH(DS, portid); +} + +static void +do_map_in(fcode_env_t *env) +{ + fstack_t phi, pmid, plo, len, addr; + + CHECK_DEPTH(env, 3, "gp2:map-in"); + len = POP(DS); + phi = POP(DS); + plo = POP(DS); + addr = mem_map_in(env, phi, plo, len); + PUSH(DS, addr); +} + +static void +do_map_out(fcode_env_t *env) +{ + fstack_t addr, len; + + CHECK_DEPTH(env, 2, "gp2:map-out"); + len = POP(DS); + addr = POP(DS); + mem_map_out(env, addr, len); +} + +static void +do_encode_unit(fcode_env_t *env) +{ + char enc_buf[64]; + fstack_t hi, mid, lo; + int id, off; + + CHECK_DEPTH(env, 2, "gp2:encode-unit"); + hi = POP(DS); + lo = POP(DS); + + hi = (hi & 0x00000001); /* get high order agent id bit */ + id = (hi << 9) | (lo >> 23); /* build extended agent id */ + off = lo & 0x7fffff; /* build config offset */ + + if (off) { + sprintf(enc_buf, "%x,%x", id, off); + } else { + sprintf(enc_buf, "%x", id); + } + debug_msg(DEBUG_REG_ACCESS, "gp2:encode_unit ( %x %x ) -> '%s'\n", + (int)hi, (int)lo, enc_buf); + push_a_string(env, STRDUP(enc_buf)); +} + +static void +do_decode_unit(fcode_env_t *env) +{ + uint32_t lo, hi; + int agent, offset; + char *buf; + + CHECK_DEPTH(env, 2, "gp2:decode-unit"); + buf = pop_a_string(env, NULL); + if (sscanf(buf, "%x,%x", &agent, &offset) != 2) { + if (sscanf(buf, "%x", &agent) != 1) { + throw_from_fclib(env, 1, "gp2:decode_unit:%s", buf); + } + offset = 0; + } + lo = offset | (agent << 23); + hi = (agent >> 9) | 0x400; + debug_msg(DEBUG_REG_ACCESS, "gp2:decode_unit ( '%s' ) -> %x %x\n", buf, + hi, lo); + PUSH(DS, lo); + PUSH(DS, hi); +} + +static void +do_claim_addr(fcode_env_t *env) +{ + fstack_t portid, bar, align, type, size_hi, size_lo; + fc_cell_t lo, hi; + private_data_t *pdp = DEVICE_PRIVATE(env); + char *service = "claim-address"; + int error; + + CHECK_DEPTH(env, 6, "gp2:claim-address"); + portid = POP(DS); + bar = POP(DS); + align = POP(DS); + type = POP(DS); + size_hi = POP(DS); + size_lo = POP(DS); + + error = fc_run_priv(pdp->common, service, 6, 2, + fc_int2cell(portid), fc_int2cell(bar), fc_int2cell(align), + fc_int2cell(type), fc_int2cell(size_hi), fc_int2cell(size_lo), + &lo, &hi); + + if (error) + throw_from_fclib(env, 1, "gp2:%s: failed\n", service); + + debug_msg(DEBUG_REG_ACCESS, + "gp2:%s ( %x %x %x %x %x %x ) -> %x %x\n", service, (int)portid, + (int)bar, (int)align, (int)type, (int)size_hi, (int)size_lo, + (uint32_t)hi, (uint32_t)lo); + + PUSH(DS, (uint32_t)lo); + PUSH(DS, (uint32_t)hi); +} + +static void +do_master_interrupt(fcode_env_t *env) +{ + int portid; + token_t xt; + + CHECK_DEPTH(env, 2, "gp2:master-interrput"); + portid = POP(DS); + xt = POP(DS); + PUSH(DS, FALSE); + debug_msg(DEBUG_REG_ACCESS, "gp2:master-interrupt ( %x %x ) -> %x\n", + portid, xt, (int)FALSE); +} + +static void +do_register_vectory_entry(fcode_env_t *env) +{ + int ign, ino, level; + + CHECK_DEPTH(env, 3, "gp2:register-vector-entry"); + ign = POP(DS); + ino = POP(DS); + level = POP(DS); + PUSH(DS, FALSE); + debug_msg(DEBUG_REG_ACCESS, "gp2:register-vector-entry ( %x %x %x ) ->" + " %x\n", ign, ino, level, (int)FALSE); +} + +static void +do_get_interrupt_target(fcode_env_t *env) +{ + int mid = 0; + + PUSH(DS, mid); + debug_msg(DEBUG_REG_ACCESS, "gp2:get-interrupt-target ( ) -> %x\n", + mid); +} + +static void +do_device_id(fcode_env_t *env) +{ + fstack_t phi, plo, addr; + fc_cell_t virtaddr; + private_data_t *pdp = DEVICE_PRIVATE(env); + uint64_t wci_id_reg; + int rc, parid; + + CHECK_DEPTH(env, 2, "gp2:device-id"); + phi = POP(DS); + plo = POP(DS); + + PUSH(DS, plo); + PUSH(DS, phi); + PUSH(DS, 0x100); + + do_map_in(env); + + addr = POP(DS); + + virtaddr = mcookie_to_addr(addr); + + /* Try to read the wci_id register */ + rc = fc_run_priv(pdp->common, "rx@", 1, 1, virtaddr + 0xe0, + &wci_id_reg); + + mem_map_out(env, addr, 0x100); + + /* + * Get the part id from the jtag ID register + */ + parid = ((wci_id_reg >> 12) & 0xffff); + + if (!rc && parid == 0x4478) { + debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-wci\n"); + push_a_string(env, "SUNW,wci"); + } else { + debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-pci\n"); + push_a_string(env, "gp2-pci"); + } +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + ASSERT(env->current_device); + NOTICE; + + create_int_prop(env, "#address-cells", 2); + + FORTH(0, "map-in", do_map_in); + FORTH(0, "get-portid", do_get_portid); + FORTH(0, "map-out", do_map_out); + FORTH(0, "decode-unit", do_decode_unit); + FORTH(0, "encode-unit", do_encode_unit); + FORTH(0, "claim-address", do_claim_addr); + FORTH(0, "master-interrupt", do_master_interrupt); + FORTH(0, "register-vector-entry", do_register_vectory_entry); + FORTH(0, "get-interrupt-target", do_get_interrupt_target); + FORTH(0, "device-id", do_device_id); + + install_dma_methods(env); + +} diff --git a/usr/src/lib/efcode/gp2/sparcv9/Makefile b/usr/src/lib/efcode/gp2/sparcv9/Makefile new file mode 100644 index 0000000000..6656b54ad3 --- /dev/null +++ b/usr/src/lib/efcode/gp2/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) $(FCDRIVER64) + +install: all $(ROOTLIBS64) $(ROOTSYMLINKS64) diff --git a/usr/src/lib/efcode/include/fcdriver/fcdriver.h b/usr/src/lib/efcode/include/fcdriver/fcdriver.h new file mode 100644 index 0000000000..d40ca79cd4 --- /dev/null +++ b/usr/src/lib/efcode/include/fcdriver/fcdriver.h @@ -0,0 +1,75 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCDRIVER_FCDRIVER_H +#define _FCDRIVER_FCDRIVER_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/fcode.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NODEIDs { + fc_phandle_t my_handle; + device_t *node; +} my_nodeid_t; + +typedef struct MY_GLOBAL_DATA { + int fcode_fd; + char *path; + char *Progname; + struct fc_parameters fc; + fc_phandle_t attach; + fc_resource_t *nodeids; + char *search_path; + int init_done; + int first_node; +} common_data_t; + +typedef struct MY_PRIVATE_DATA { + common_data_t *common; + fc_phandle_t node; + fc_phandle_t parent; + struct fc_parameters fc; + void *debug; + int upload; +} private_data_t; + +#ifdef FCODE_INTERNAL +#include <fcdriver/proto.h> +#endif + +void upload_nodes(fcode_env_t *); +void validate_nodes(fcode_env_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCDRIVER_FCDRIVER_H */ diff --git a/usr/src/lib/efcode/include/fcdriver/proto.h b/usr/src/lib/efcode/include/fcdriver/proto.h new file mode 100644 index 0000000000..2cab34e4d2 --- /dev/null +++ b/usr/src/lib/efcode/include/fcdriver/proto.h @@ -0,0 +1,61 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCDRIVER_PROTO_H +#define _FCDRIVER_PROTO_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CURRENT_DEVICE(e) (e)->current_device +#define COMMON_PRIVATE(e) (common_data_t *)((e)->private) +#define DEVICE_PRIVATE(e) (private_data_t *)(MYSELF->device->private) + +void install_pci_methods(fcode_env_t *); +void install_property_vectors(fcode_env_t *, device_t *); +void install_node_data(fcode_env_t *, device_t *); +void build_tree(fcode_env_t *); +void install_dma_methods(fcode_env_t *); +void add_my_handle(fcode_env_t *, fc_phandle_t, device_t *); +void recurse_tree(fcode_env_t *, device_t *, + void (*)(fcode_env_t *, device_t *)); + +int do_run_priv(common_data_t *, struct fc_client_interface *, int); +int fc_run_priv(common_data_t *, char *, int, int, ...); +int os_get_prop_common(common_data_t *, fc_phandle_t, char *, int, char **, + int *); +fc_phandle_t fc_get_ap(common_data_t *); +int fc_get_request(common_data_t *); +void set_debug_level(common_data_t *, uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCDRIVER_PROTO_H */ diff --git a/usr/src/lib/efcode/include/fcode/debug.h b/usr/src/lib/efcode/include/fcode/debug.h new file mode 100644 index 0000000000..450844618c --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/debug.h @@ -0,0 +1,75 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCODE_DEBUG_H +#define _FCODE_DEBUG_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_CONTEXT 0x00000001 +#define DEBUG_BYTELOAD_DS 0x00000002 +#define DEBUG_BYTELOAD_RS 0x00000004 +#define DEBUG_BYTELOAD_TOKENS 0x00000008 +#define DEBUG_NEW_TOKEN 0x00000010 +#define DEBUG_EXEC_TRACE 0x00000020 +#define DEBUG_EXEC_SHOW_VITALS 0x00000040 +#define DEBUG_EXEC_DUMP_DS 0x00000080 +#define DEBUG_EXEC_DUMP_RS 0x00000100 +#define DEBUG_COMMA 0x00000200 +#define DEBUG_HEADER 0x00000400 +#define DEBUG_EXIT_WORDS 0x00000800 +#define DEBUG_EXIT_DUMP 0x00001000 +#define DEBUG_DUMP_TOKENS 0x00002000 +#define DEBUG_COLON 0x00004000 +#define DEBUG_NEXT_VITALS 0x00008000 +#define DEBUG_UPLOAD 0x00010000 +#define DEBUG_VOC_FIND 0x00020000 +#define DEBUG_DUMP_DICT_TOKENS 0x00040000 +#define DEBUG_TOKEN_USAGE 0x00080000 +#define DEBUG_DUMP_TOKEN_TABLE 0x00100000 +#define DEBUG_SHOW_STACK 0x00200000 +#define DEBUG_SHOW_RS 0x00400000 +#define DEBUG_TRACING 0x00800000 +#define DEBUG_TRACE_STACK 0x01000000 +#define DEBUG_CALL_METHOD 0x02000000 +#define DEBUG_ACTIONS 0x04000000 +#define DEBUG_STEPPING 0x08000000 +#define DEBUG_REG_ACCESS 0x10000000 +#define DEBUG_ADDR_ABUSE 0x20000000 +#define DEBUG_FIND_FCODE 0x40000000 + +#define DEBUG_ANY 0xffffffff + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_DEBUG_H */ diff --git a/usr/src/lib/efcode/include/fcode/engine.h b/usr/src/lib/efcode/include/fcode/engine.h new file mode 100644 index 0000000000..06e5ef2767 --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/engine.h @@ -0,0 +1,331 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCODE_ENGINE_H +#define _FCODE_ENGINE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_ORDER 32 +#define CONVERT_HANDLES + +#ifdef BIGSTACK +typedef long long fstack_t; +typedef unsigned long long ufstack_t; +#else +typedef long fstack_t; +typedef unsigned long ufstack_t; +#endif +typedef long *acf_t; /* pointer to execution token */ +typedef long token_t; /* sizeof a forth token */ + +/* x@, x! type */ +typedef uint64_t u_xforth_t; +typedef int64_t s_xforth_t; +typedef uint64_t xforth_t; + +/* l@, l! type */ +typedef uint32_t u_lforth_t; +typedef int32_t s_lforth_t; +typedef uint32_t lforth_t; + +/* w@, w! type */ +typedef uint16_t u_wforth_t; +typedef int16_t s_wforth_t; +typedef uint16_t wforth_t; + +/* Double type */ +typedef uint64_t u_dforth_t; +typedef int64_t s_dforth_t; +typedef uint64_t dforth_t; + +/* Variable/Value/Constant type */ +typedef token_t variable_t; + +typedef struct PROPERTY { + char *name; + uchar_t *data; + int size; + struct PROPERTY *next; +} prop_t; + +typedef struct RESOURCE { + struct RESOURCE *next; + void *data; +} fc_resource_t; + +#define INIT_DATA 0 +#define UINIT_DATA 1 + +typedef struct FCODE_ENV fcode_env_t; + +typedef struct DEVICE_VECTOR { + /* + * If there is private data associated with a node this vector + * table contains the routines that will be called to augment the + * device. + * These two routines allow the interpreter to use a different + * + * Interface Note: + * Any routine installed here is assumed to have the standard forth + * call state. It must be a void function call taking a forth execution + * environment, returning any data on the stack. In general the + * vector call should have the same semantics as the original routine + * it is replacing. (see get_prop as an example). + * + * The caller has the responsibility of converting the resulting data + * back to a form it requires. + * + */ + void (*get_package_prop)(fcode_env_t *); + void (*get_inherited_prop)(fcode_env_t *); +} device_vector_t; + +typedef struct DEVICE device_t; + +#define MAX_MY_ADDR 4 + +struct DEVICE { + device_t *parent; + device_t *child; + device_t *peer; + prop_t *properties; + token_t *vocabulary; + fstack_t parent_adr_cells; + fstack_t my_space; + fstack_t my_addr[MAX_MY_ADDR]; + fstack_t frame_buffer_adr; + int data_size[2]; + token_t *init_data; /* initialised instance data */ + void *private; /* app private data */ + device_vector_t vectors; +}; + +typedef struct INSTANCE { + struct INSTANCE *parent; + device_t *device; + /* + * These are copies of the same structures from the device definition + * however changes here will be thrown away when the instance is + * destroyed. + */ + char *my_args; + int my_args_len; + fstack_t my_space; + fstack_t my_addr[MAX_MY_ADDR]; + fstack_t frame_buffer_adr; + token_t *data[2]; +} instance_t; + +typedef struct FCODE_TOKEN { + ulong_t flags; + char *name; + acf_t apf; /* pointer to acf in dictionary */ +#ifdef DEBUG + int usage; +#endif +} fcode_token; + +typedef struct { + char *buffer; + char *scanptr; + int maxlen; + int separator; +} input_typ; + +typedef struct ERROR_FRAME { + struct ERROR_FRAME *next; + fstack_t *ds; + fstack_t *rs; + instance_t *myself; + token_t *ip; + fstack_t code; +} error_frame; + +struct FCODE_ENV { + fcode_token *table; /* token table */ + uchar_t *base; /* dictionary base */ + uchar_t *here; /* current dp */ + char *name; /* last name */ + long level; /* level */ + token_t *ip; /* instruction pointer */ + token_t *wa; /* word address */ + fstack_t *ds0; /* base of dats stack */ + fstack_t *rs0; /* base of return stack */ + fstack_t *ds; /* data stack base */ + fstack_t *rs; /* return stack base */ + variable_t num_base; /* current base */ + token_t *current; /* current voc */ + long order_depth; + token_t **order; /* Voc. search order */ + token_t *lastlink; /* last forth def */ + token_t *forth_voc_link; /* Storage location for 'forth' voc */ + int last_token; /* last defined token */ + device_t *root_node; /* root node */ + device_t *attachment_pt; + device_t *current_device; /* */ + instance_t *my_self; /* pointer to my data */ + int offset_incr; /* size of FCODE token offsets */ + error_frame *catch_frame; + uchar_t *fcode_buffer; /* pointer to fcode buffer */ + uchar_t *fcode_ptr; /* pointer into fcode buffer */ + uchar_t *last_fcode_ptr; /* pointer to last fcode fetched */ + fstack_t last_fcode; /* last fcode# executed */ + fstack_t last_error; /* last throw code executed */ + int fcode_incr; /* space between bytecodes */ + int interpretting; + variable_t state; /* compile or run? */ + int fcode_debug; + int diagnostic_mode; + fstack_t instance_mode; + int interactive; /* DEBUG, interact variable */ + int num_actions; + int action_count; + token_t *action_ptr; + int strict_fcode; + fstack_t control; /* control VM behaviour */ + input_typ *input; /* input buffer pointer */ + variable_t span; + char *picturebufpos; /* pictured string buffer position */ + char *picturebuf; /* pictured string buffer */ + int picturebuflen; /* pictured string buffer length */ + variable_t output_column; /* output column# (#out) */ + variable_t output_line; /* output line# (#line) */ +#ifdef CONVERT_HANDLES + device_t *(*convert_phandle)(fcode_env_t *, fstack_t); + fstack_t (*revert_phandle)(fcode_env_t *, device_t *); + void (*allocate_phandle)(fcode_env_t *); +#endif + fc_resource_t *propbufs; + void *private; /* private data ptr for app use. */ +}; + +#define MAX_FCODE 0xfff /* max no. of Fcode entries in table */ + + +typedef unsigned char flag_t; + +#define DS (env->ds) +#define RS (env->rs) +#define TOS *DS +#define IP (env->ip) +#define WA (env->wa) +#define DEPTH (DS-env->ds0) +#define CURRENT (env->current) +#define ORDER (env->order) +#define BASE (env->base) +#define HERE (env->here) +#define CONTEXT env->order[env->order_depth] +#define MYSELF (env->my_self) + +#ifdef FCODE_INTERNAL +#include <fcode/proto.h> +#endif +#include <fcode/public.h> + +#define SIGN_SHIFT ((8*(sizeof (fstack_t)))-1) +#define SIGN_BIT (((ufstack_t)1)<<SIGN_SHIFT) + +/* + * Note that sizeof (token_t) MUST equal sizeof (token_t *). If it doesn't, + * many things will break. + */ +#define _ALIGN(x, y) (((long)(x)) & ~(sizeof (y)-1)) +#define TOKEN_ROUNDUP(x) _ALIGN((x + ((sizeof (token_t)-1))), token_t) + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +/* values for flag_t */ +#define ANSI_WORD 0x01 +#define P1275_WORD 0x02 +#define FLAG_NONAME 0x04 +#define IMMEDIATE 0x08 +#define FLAG_VALUE 0x10 +#define FLAG_DEBUG 0x20 +#define DEFINER (FLAG_NONAME|IMMEDIATE) + +#define FORTH(fl, nm, fnc) define_word(env, fl, nm, fnc); + +#define LINK_TO_ACF(x) (((token_t *)(x))+1) +#define LINK_TO_FLAGS(x) (((flag_t *)(x))-1) +#define ACF_TO_LINK(x) (((token_t *)(x))-1) +#define ACF_TO_BODY(x) (((acf_t)(x))+1) +#define BODY_TO_LINK(x) (((acf_t)(x))-1) +#define BODY_TO_FLAGS(x) (((flag_t *)(BODY_TO_LINK(x))) - 1) +#define EXPOSE_ACF *((acf_t)env->current) = \ + (token_t)(env->lastlink) + +#define COMPILE_TOKEN(x) PUSH(DS, (fstack_t)(x)); compile_comma(env); +#define CHECK_DEPTH(env, x, w) if ((x) > (env->ds - env->ds0)) \ + forth_abort(env, "%s: stack underflow\n", w); +#define CHECK_RETURN_DEPTH(env, x, w) if ((x) > (env->rs - env->rs0)) \ + forth_abort(env, "%s: return stack underflow\n", w); + +#define FCRP_NOERROR 0x80000000 /* fc_run_priv: no err msg. */ + +#ifdef CONVERT_HANDLES +#define CONVERT_PHANDLE(e, x, y) x = env->convert_phandle(e, y) +#define REVERT_PHANDLE(e, x, y) x = env->revert_phandle(e, y) +#define ALLOCATE_PHANDLE(e) env->allocate_phandle(e) +#else +#define CONVERT_PHANDLE(e, x, y) x = (device_t *)(y) +#define REVERT_PHANDLE(e, x, y) x = (fstack_t)(y) +#define ALLOCATE_PHANDLE(e) +#endif + +extern fcode_env_t *env; +extern int dict_size; +extern int in_forth_abort; +extern int stack_size; +extern token_t value_defines[][3]; +extern void (*bbranch_ptrs[3])(fcode_env_t *); +extern void (*blit_ptr)(fcode_env_t *); +extern void (*create_ptr)(fcode_env_t *); +extern void (*do_bdo_ptr)(fcode_env_t *); +extern void (*do_bqdo_ptr)(fcode_env_t *); +extern void (*do_leave_ptr)(fcode_env_t *); +extern void (*do_loop_ptr)(fcode_env_t *); +extern void (*do_ploop_ptr)(fcode_env_t *); +extern void (*does_ptr)(fcode_env_t *); +extern void (*quote_ptr)(fcode_env_t *); +extern void (*quote_ptr)(fcode_env_t *); +extern void (*semi_ptr)(fcode_env_t *); +extern void (*tlit_ptr)(fcode_env_t *); +extern void (*to_ptr)(fcode_env_t *); +extern void (*to_ptr)(fcode_env_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_ENGINE_H */ diff --git a/usr/src/lib/efcode/include/fcode/log.h b/usr/src/lib/efcode/include/fcode/log.h new file mode 100644 index 0000000000..866739fb1c --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/log.h @@ -0,0 +1,60 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _FCODE_LOG_H +#define _FCODE_LOG_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal Message Levels */ +#define MSG_FATAL 0x01 /* Fatal Error -> LOG_ERR */ +#define MSG_ERROR 0x02 /* Error -> LOG_ERR */ +#define MSG_WARN 0x04 /* Warning -> LOG_WARN */ +#define MSG_NOTE 0x08 /* Notice -> LOG_NOTICE */ +#define MSG_INFO 0x10 /* Informational -> LOG_INFO */ +#define MSG_DEBUG 0x20 /* Debug -> LOG_DEBUG */ +#define MSG_FC_DEBUG 0x40 /* Fcode (Noisy) Debug -> LOG_DEBUG */ +#define MSG_EMIT 0x80 /* Fcode Emit -> LOG_DEBUG */ + +void log_message(int, char *, ...); +void log_perror(int, char *, ...); +void debug_msg(int, char *, ...); +void open_syslog_log(char *, int); +void open_error_log(char *, int); +void log_emit(char); +void set_daemon_log_flag(int); +void set_min_syslog_level(int); +int parse_msg_flags(char *); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_LOG_H */ diff --git a/usr/src/lib/efcode/include/fcode/private.h b/usr/src/lib/efcode/include/fcode/private.h new file mode 100644 index 0000000000..1a5834483b --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/private.h @@ -0,0 +1,147 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCODE_PRIVATE_H +#define _FCODE_PRIVATE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef DEBUG +#include <fcode/debug.h> + +#ifdef __cplusplus +extern "C" { +#endif + +long get_interpreter_debug_level(void); +void set_interpreter_debug_level(long lvl); + +#define DPRINTF(x, y) if (get_interpreter_debug_level() & (DEBUG_##x))\ + printf y +#define DEBUGF(x, y) if (get_interpreter_debug_level() & (DEBUG_##x))\ + { y; } +#else + +#ifdef __cplusplus +extern "C" { +#endif + +#define DPRINTF(x, y) +#define DEBUGF(x, y) +#endif + +#define PUSH(sp, n) *(++sp) = (n) +#define POP(sp) *(sp--) + +#define ERROR(x) printf x + +#define MALLOC(x) safe_malloc((x), __FILE__, __LINE__) +#define REALLOC(x, n) safe_realloc((x), (n), __FILE__, __LINE__) +#define STRDUP(x) safe_strdup((x), __FILE__, __LINE__) +#define FREE(x) safe_free((x), __FILE__, __LINE__) + +#include <fcode/engine.h> + +extern fcode_env_t *initial_env; +extern int fcode_impl_count; + +#define SET_TOKEN(t, f, n, a) \ + env->table[t].flags = f; \ + env->table[t].name = n; \ + env->table[t].apf = a; + +#define FCODE(token, fl, nm, fnc) \ + fcode_impl_count++; \ + env->table[token].flags = fl; \ + do_code(env, token, nm, fnc); + +#define ANSI(tk, t, nm, fnc) FCODE(tk, (ANSI_WORD|P1275_WORD|t), nm, fnc) +#define P1275(tk, t, nm, fnc) FCODE(tk, (P1275_WORD|t), nm, fnc) + +#ifdef DEBUG +#define ASSERT(x) if (!(x)) printf("%s:%d: ASSERT FAILED!!\n",\ + __FILE__, __LINE__); +#ifdef NOTICE +#undef NOTICE +#define NOTICE printf("%s:%d: _init called\n", __FILE__, __LINE__) +#else +#define NOTICE +#endif +#else +#define ASSERT(x) +#define NOTICE +#endif + +void fc_abort(fcode_env_t *, char *type); + +#define TODO fc_abort(env, "TODO") +#define FATAL ERROR(("%s:%d: MANGLED FCODE!! Fatal Error\n",\ + __FILE__, __LINE__))) + +#ifndef USE_INTERRUPTS +#define CHECK_INTERRUPT +#define COMPLETE_INTERRUPT +#else +#define CHECK_INTERRUPT check_interrupt() +#define COMPLETE_INTERRUPT complete_interrupt() +#endif + +/* dforth_t manimpulations */ +#define MAKE_DFORTH(hi, lo) ((((u_dforth_t)(hi) << 32)) | \ + (((u_dforth_t)(lo)) & 0xffffffff)) +#define DFORTH_LO(df) (((u_dforth_t)(df)) & 0xffffffff) +#define DFORTH_HI(df) ((((u_dforth_t)(df)) >> 32) & 0xffffffff) + +#define TRUE (-1) +#define FALSE (0) + + +instance_t *open_instance_chain(fcode_env_t *, device_t *, int); +void close_instance_chain(fcode_env_t *, instance_t *, int); +void activate_device(fcode_env_t *, device_t *); +void deactivate_device(fcode_env_t *, device_t *); + +void install_handlers(fcode_env_t *); +void set_defer_actions(fcode_env_t *, int); +void throw_from_fclib(fcode_env_t *, fstack_t, char *, ...); +int get_default_intprop(fcode_env_t *, char *, device_t *, int); +uint_t get_number_of_parent_address_cells(fcode_env_t *); +char *get_package_name(fcode_env_t *, device_t *); + +token_t *get_instance_address(fcode_env_t *); +fc_resource_t *find_resource(fc_resource_t **, void *, + int (c)(void *, void *)); +void *add_resource(fc_resource_t **, void *, int (c)(void *, void *)); +void free_resource(fc_resource_t **, void *, int (c)(void *, void *)); +void set_temporary_compile(fcode_env_t *); +void temporary_execute(fcode_env_t *); +prop_t *lookup_package_property(fcode_env_t *, char *, device_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_PRIVATE_H */ diff --git a/usr/src/lib/efcode/include/fcode/proto.h b/usr/src/lib/efcode/include/fcode/proto.h new file mode 100644 index 0000000000..84a7490cf4 --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/proto.h @@ -0,0 +1,448 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _FCODE_PROTO_H +#define _FCODE_PROTO_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FNPROTO(x) void x(fcode_env_t *) + +FNPROTO(bdo); +FNPROTO(bqdo); + +FNPROTO(literal); +void branch_common(fcode_env_t *, short, fstack_t, int); +FNPROTO(zero); +FNPROTO(bloop); +FNPROTO(bplusloop); +FNPROTO(loop_i); +FNPROTO(loop_j); +FNPROTO(bleave); +FNPROTO(execute); +FNPROTO(add); +FNPROTO(subtract); +FNPROTO(multiply); +FNPROTO(slash_mod); +FNPROTO(uslash_mod); +FNPROTO(divide); +FNPROTO(mod); +FNPROTO(and); +FNPROTO(or); +FNPROTO(xor); +FNPROTO(invert); +FNPROTO(lshift); +FNPROTO(rshift); +FNPROTO(rshifta); +FNPROTO(negate); +FNPROTO(f_abs); +FNPROTO(f_min); +FNPROTO(f_max); +FNPROTO(to_r); +FNPROTO(from_r); +FNPROTO(rfetch); +FNPROTO(f_exit); +FNPROTO(zero_equals); +FNPROTO(zero_not_equals); +FNPROTO(zero_less); +FNPROTO(zero_less_equals); +FNPROTO(zero_greater); +FNPROTO(zero_greater_equals); +FNPROTO(less); +FNPROTO(greater); +FNPROTO(equals); +FNPROTO(not_equals); +FNPROTO(unsign_greater); +FNPROTO(unsign_less_equals); +FNPROTO(unsign_less); +FNPROTO(unsign_greater_equals); +FNPROTO(greater_equals); +FNPROTO(less_equals); +FNPROTO(between); +FNPROTO(within); +FNPROTO(drop); +FNPROTO(f_dup); +FNPROTO(over); +FNPROTO(swap); +FNPROTO(rot); +FNPROTO(minus_rot); +FNPROTO(tuck); +FNPROTO(nip); +FNPROTO(pick); +FNPROTO(roll); +FNPROTO(qdup); +FNPROTO(depth); +FNPROTO(two_drop); +FNPROTO(two_dup); +FNPROTO(two_over); +FNPROTO(two_swap); +FNPROTO(two_rot); +FNPROTO(two_slash); +FNPROTO(utwo_slash); +FNPROTO(two_times); +FNPROTO(slash_c); +FNPROTO(slash_w); +FNPROTO(slash_l); +FNPROTO(slash_n); +FNPROTO(ca_plus); +FNPROTO(wa_plus); +FNPROTO(la_plus); +FNPROTO(na_plus); +FNPROTO(c1_plus); +FNPROTO(w1_plus); +FNPROTO(l1_plus); +FNPROTO(cell_plus); +FNPROTO(do_chars); +FNPROTO(slash_w_times); +FNPROTO(slash_l_times); +FNPROTO(cells); +FNPROTO(do_off); +FNPROTO(do_on); +FNPROTO(fetch); +FNPROTO(lfetch); +FNPROTO(wfetch); +FNPROTO(swfetch); +FNPROTO(cfetch); +FNPROTO(store); +FNPROTO(lstore); +FNPROTO(wstore); +FNPROTO(cstore); + +FNPROTO(noop); +FNPROTO(lwsplit); +FNPROTO(wljoin); +FNPROTO(lbsplit); +FNPROTO(bljoin); +FNPROTO(wbflip); +FNPROTO(upper_case); +FNPROTO(lower_case); +FNPROTO(pack_str); +FNPROTO(count_str); +FNPROTO(to_body); +FNPROTO(to_acf); +FNPROTO(bcase); +FNPROTO(bendcase); + +FNPROTO(span); + +FNPROTO(expect); + +FNPROTO(emit); +FNPROTO(type); + +FNPROTO(fc_crlf); + +FNPROTO(base); +FNPROTO(dollar_number); +FNPROTO(digit); + +FNPROTO(do_constant); +FNPROTO(do_defer); +FNPROTO(do_crash); +FNPROTO(do_field); +FNPROTO(idefer_exec); + +FNPROTO(set_args); + +void make_common_access(fcode_env_t *, char *, int, int, int, + void (*acf_i)(fcode_env_t *), void (*acf_s)(fcode_env_t *), + void (*set_a)(fcode_env_t *, int)); + +FNPROTO(do_create); + +FNPROTO(instance); +FNPROTO(semi); + +FNPROTO(dollar_find); +acf_t voc_find(fcode_env_t *env); + +FNPROTO(evaluate); + +FNPROTO(ccomma); +FNPROTO(wcomma); +FNPROTO(lcomma); +FNPROTO(comma); +FNPROTO(state); +FNPROTO(compile_comma); + +FNPROTO(here); +FNPROTO(aligned); +FNPROTO(wbsplit); +FNPROTO(bwjoin); +FNPROTO(bmark); +FNPROTO(bresolve); + +FNPROTO(f_error); +FNPROTO(fc_unimplemented); +FNPROTO(fc_obsolete); +FNPROTO(fc_historical); + +FNPROTO(myspace); +FNPROTO(property); +FNPROTO(encode_int); +FNPROTO(encode_plus); +FNPROTO(encode_phys); +FNPROTO(encode_string); +FNPROTO(encode_bytes); +FNPROTO(model_prop); +FNPROTO(device_type); +FNPROTO(new_device); + +FNPROTO(finish_device); + +FNPROTO(device_name); + +FNPROTO(lwflip); +FNPROTO(lbflip); + +FNPROTO(child_node); +FNPROTO(peer_node); + +FNPROTO(byte_load); + +uchar_t next_bytecode(fcode_env_t *); +ushort_t get_short(fcode_env_t *); +uint_t get_int(fcode_env_t *); + +char *get_name(long *); +FNPROTO(words); +void header(fcode_env_t *, char *, int, flag_t); +void do_code(fcode_env_t *, int, char *, FNPROTO((*))); +void push_string(fcode_env_t *, char *, int); + +FNPROTO(verify_usage); +FNPROTO(dump_dictionary); +void print_stack_element(fcode_env_t *, fstack_t); +void dump_data_stack(fcode_env_t *, int); +void dump_return_stack(fcode_env_t *, int); +char *acf_lookup(fcode_env_t *, acf_t); +char *acf_to_name(fcode_env_t *, acf_t); +int within_dictionary(fcode_env_t *, void *); +char *acf_backup_search(fcode_env_t *, acf_t); +void dump_forth_environment(fcode_env_t *); +void forth_abort(fcode_env_t *, char *, ...); +void forth_perror(fcode_env_t *, char *, ...); +void return_to_interact(fcode_env_t *); +char *get_path(fcode_env_t *, device_t *); +char *search_for_fcode_file(fcode_env_t *, char *); +int current_debug_state(fcode_env_t *); +int debug_flags_to_mask(char *); +int do_exec_debug(fcode_env_t *, void *); +int name_is_debugged(fcode_env_t *, char *); +prop_t *find_property(device_t *, char *); +void buffer_init(fcode_env_t *env); +void check_for_debug_entry(fcode_env_t *); +void check_for_debug_exit(fcode_env_t *); +void check_semi_debug_exit(fcode_env_t *); +void check_vitals(fcode_env_t *); +void clear_debug_state(fcode_env_t *, int); +void debug_set_level(fcode_env_t *, int); +void define_actions(fcode_env_t *env, int n, token_t *array); +void do_alias(fcode_env_t *); +void do_bbranch(fcode_env_t *env); +void do_bdo(fcode_env_t *); +void do_bleave(fcode_env_t *env); +void do_bloop(fcode_env_t *env); +void do_bofbranch(fcode_env_t *env); +void do_bploop(fcode_env_t *env); +void do_bqbranch(fcode_env_t *env); +void do_bqdo(fcode_env_t *env); +void do_creator(fcode_env_t *env); +void do_default_action(fcode_env_t *env); +void do_emit(fcode_env_t *, uchar_t); +void do_literal(fcode_env_t *); +void dump_comma(fcode_env_t *, char *); +void dump_words(fcode_env_t *); +void fevaluate(fcode_env_t *); +void ibuffer_init(fcode_env_t *env); +void install_builtin_nodes(fcode_env_t *); +void install_does(fcode_env_t *); +void install_openprom_nodes(fcode_env_t *); +void install_package_nodes(fcode_env_t *); +void internal_env_addr(fcode_env_t *env); +void internal_env_fetch(fcode_env_t *env); +void internal_env_store(fcode_env_t *env); +void key(fcode_env_t *); +void keyquestion(fcode_env_t *); +void make_a_node(fcode_env_t *, char *, int); +void output_data_stack(fcode_env_t *, int); +void output_return_stack(fcode_env_t *, int, int); +void output_step_message(fcode_env_t *); +void output_vitals(fcode_env_t *); +void print_property(fcode_env_t *, prop_t *, char *); +void read_line(fcode_env_t *); +void run_daemon(fcode_env_t *); +void run_fcode_from_file(fcode_env_t *, char *, int); +void tick_literal(fcode_env_t *); +void unbug(fcode_env_t *); +void xbflip(fcode_env_t *); +void xfetch(fcode_env_t *); +void xlflip(fcode_env_t *); +void xstore(fcode_env_t *); +void expose_acf(fcode_env_t *, char *); + +FNPROTO(do_semi); +FNPROTO(do_colon); +FNPROTO(do_next); +void do_run(fcode_env_t *, int); + +void *safe_malloc(size_t, char *, int); +void *safe_realloc(void *, size_t, char *, int); +char *safe_strdup(char *, char *, int); +void safe_free(void *, char *, int); + +FNPROTO(do_forth); +FNPROTO(do_current); +FNPROTO(do_context); +FNPROTO(do_definitions); +FNPROTO(do_interact); +FNPROTO(do_resume); +FNPROTO(do_vocab); +FNPROTO(create); +FNPROTO(colon); +FNPROTO(does); +FNPROTO(recursive); +FNPROTO(do_if); +FNPROTO(do_else); +FNPROTO(do_then); +FNPROTO(parse_word); +FNPROTO(do_quote); +FNPROTO(run_quote); + +FNPROTO(do_order); +FNPROTO(do_also); +FNPROTO(do_previous); + +FNPROTO(find_package); +FNPROTO(open_package); +FNPROTO(close_package); +FNPROTO(find_method); +FNPROTO(dollar_call_parent); +FNPROTO(my_parent); +FNPROTO(my_unit); +FNPROTO(ihandle_to_phandle); +FNPROTO(dollar_call_method); +FNPROTO(dollar_open_package); + +FNPROTO(call_environment_method); + +FNPROTO(f_abort); +FNPROTO(catch); +FNPROTO(throw); + +FNPROTO(get_my_property); +FNPROTO(decode_int); +FNPROTO(decode_string); +FNPROTO(get_inherited_prop); +FNPROTO(delete_property); +FNPROTO(get_package_property); +void get_environment_property(fcode_env_t *env, int); + +FNPROTO(root_node); +FNPROTO(current_device); +FNPROTO(dot_properties); +FNPROTO(pwd); +FNPROTO(do_ls); +FNPROTO(do_cd); +FNPROTO(do_select_dev); +FNPROTO(do_unselect_dev); +FNPROTO(device_end); +FNPROTO(value); +FNPROTO(buffer_colon); +FNPROTO(variable); +FNPROTO(constant); +FNPROTO(actions); +FNPROTO(use_actions); +FNPROTO(action_colon); +FNPROTO(perform_action); +FNPROTO(do_tick); +FNPROTO(bracket_tick); +FNPROTO(defer); +FNPROTO(bye); +FNPROTO(dump_device); +FNPROTO(dump_instance); +FNPROTO(compile_string); +FNPROTO(parse_two_int); + +token_t *alloc_instance_data(fcode_env_t *, int, int, int *); +FNPROTO(fetch_instance_data); +FNPROTO(set_instance_data); +FNPROTO(address_instance_data); +FNPROTO(instance_variable); +FNPROTO(decode_phys); + +void install_actions(fcode_env_t *env, token_t *table); +void set_value_actions(fcode_env_t *env, int); +void set_internal_value_actions(fcode_env_t *env); +void set_buffer_actions(fcode_env_t *env, int); + +void system_message(fcode_env_t *env, char *msg); + +void check_interrupt(void); +void complete_interrupt(void); + +FNPROTO(do_set_action); +void push_a_string(fcode_env_t *, char *); +char *pop_a_string(fcode_env_t *, int *); +char *pop_a_duped_string(fcode_env_t *, int *); +char *parse_a_string(fcode_env_t *, int *); +void push_double(fcode_env_t *, dforth_t); +dforth_t pop_double(fcode_env_t *); +dforth_t peek_double(fcode_env_t *); +void push_xforth(fcode_env_t *, xforth_t); +xforth_t pop_xforth(fcode_env_t *); +xforth_t peek_xforth(fcode_env_t *); +void create_prop(fcode_env_t *, char *); +void create_int_prop(fcode_env_t *, char *, int); +void create_string_prop(fcode_env_t *, char *, char *); +void make_builtin_hooks(fcode_env_t *, char *); +fstack_t mapping_to_mcookie(uint64_t, size_t, uint64_t, size_t); +void delete_mapping(fstack_t); +int is_mcookie(fstack_t); +uint64_t mcookie_to_addr(fstack_t); +fstack_t mcookie_to_rlen(fstack_t); +fstack_t mcookie_to_rvirt(fstack_t); +void set_here(fcode_env_t *, uchar_t *, char *); +int call_my_parent(fcode_env_t *, char *); +FILE *get_dump_fd(fcode_env_t *); + +void load_file(fcode_env_t *); +void token_roundup(fcode_env_t *, char *); + +#ifdef DEBUG +void do_fclib_trace(fcode_env_t *, void *); +int do_fclib_step(fcode_env_t *); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_PROTO_H */ diff --git a/usr/src/lib/efcode/include/fcode/public.h b/usr/src/lib/efcode/include/fcode/public.h new file mode 100644 index 0000000000..98ec6b2219 --- /dev/null +++ b/usr/src/lib/efcode/include/fcode/public.h @@ -0,0 +1,59 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _FCODE_PUBLIC_H +#define _FCODE_PUBLIC_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * these are the public interfaces to the fcode interpretter + */ + +void define_word(fcode_env_t *, int, char *, void (*)(fcode_env_t *)); +void push_ds(fcode_env_t *, fstack_t); +void push_rs(fcode_env_t *, fstack_t); +fstack_t pop_ds(fcode_env_t *); +fstack_t pop_rs(fcode_env_t *); + +void run_fcode(fcode_env_t *, uchar_t *, int); +void destroy_environment(fcode_env_t *); +void begin_package(fcode_env_t *); +void end_package(fcode_env_t *); +fcode_env_t *clone_environment(fcode_env_t *, void *); + +void set_interpreter_debug_level(long); +long get_interpreter_debug_level(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCODE_PUBLIC_H */ diff --git a/usr/src/lib/efcode/interpreter/Makefile b/usr/src/lib/efcode/interpreter/Makefile new file mode 100644 index 0000000000..b8c56e1542 --- /dev/null +++ b/usr/src/lib/efcode/interpreter/Makefile @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 + +PROG = interpreter + +EFCODEDIR64 = $(ROOT)/usr/lib/efcode/$(MACH64) +ROOTCMDDIR = $(EFCODEDIR64) + +CPPFLAGS += -DDEBUG -DFCODE_INTERNAL +CPPFLAGS += -I ../include -I $(ROOT)/usr/platform/sun4u/include +LDFLAGS += -R/usr/lib/efcode/$(MACH64) -M mapfile64 + +LIBS = fcode.so fcdriver.so +$(PROG) := LDLIBS += -L/usr/lib/efcode/$(MACH64) $(LIBS:%=$(EFCODEDIR64)/%) + +all: $(PROG) + +clean: + -$(RM) $(PROG) + +install: all .WAIT $(ROOTCMD) + +lint: lint_PROG + +.KEEP_STATE: + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/lib/efcode/interpreter/interpreter.c b/usr/src/lib/efcode/interpreter/interpreter.c new file mode 100644 index 0000000000..73383e5704 --- /dev/null +++ b/usr/src/lib/efcode/interpreter/interpreter.c @@ -0,0 +1,198 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Embedded Fcode Interpreter + * + * Process cmd line args and invoke Fcode engine. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <stropts.h> +#include <ctype.h> + +#include <fcode/engine.h> +#include <fcode/log.h> +#include <fcode/debug.h> + +#include <fcdriver/fcdriver.h> + +#define MSG_ERRLOG_DEFAULT (MSG_FATAL|MSG_ERROR|MSG_WARN|MSG_INFO|\ + MSG_DEBUG|MSG_FC_DEBUG) +#define MSG_SYSLOG_DEFAULT (MSG_FATAL|MSG_ERROR|MSG_WARN) +#define DEBUG_FC_LIST (DEBUG_COMMA|DEBUG_EXEC_TRACE|\ + DEBUG_EXEC_DUMP_RS|DEBUG_EXEC_DUMP_RS|\ + DEBUG_EXEC_SHOW_VITALS|DEBUG_TRACING|\ + DEBUG_BYTELOAD_DS|DEBUG_BYTELOAD_RS|\ + DEBUG_BYTELOAD_TOKENS|DEBUG_SHOW_RS|\ + DEBUG_SHOW_STACK) + +common_data_t common; + +void *fc_env; + +void +usage(char *argv[]) +{ + log_message(MSG_ERROR, "Usage: %s <flags>\n", argv[0]); + log_message(MSG_ERROR, + " -D fcode_debug = true\n"); + log_message(MSG_ERROR, + " -d <level> set debug level\n"); + log_message(MSG_ERROR, + " -f <file> interpret fcode/source <file>\n"); + log_message(MSG_ERROR, + " -i go 'interactive'\n"); + log_message(MSG_ERROR, + " -s <string> interpret <string> as forth\n"); + log_message(MSG_ERROR, + " -a FCODE image has a.out header\n"); + log_message(MSG_ERROR, + " -e [<msglvl>:]<errorlog> Set error log file\n"); + log_message(MSG_ERROR, + " -l <msglvl> Set syslog message level\n"); + log_message(MSG_ERROR, + " -k Toggle OBP page kludge\n"); +} + +fcode_env_t *env; + +int +main(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int c, aout = 0; + char *fcode_file = NULL; + char *forthstr = NULL; + int debug = 0; + int syslog_flags = MSG_SYSLOG_DEFAULT; + int lflag = 0; + int error_log_flags; + char *errlog = NULL; + extern void run_one_efdaemon_request(fcode_env_t *); + + common.Progname = argv[0]; + common.search_path = getenv("FC_SEARCH_PATH"); + common.fcode_fd = -1; + env = fc_env = clone_environment(NULL, &common); + + while ((c = getopt(argc, argv, "ad:e:f:l:iDs:k")) != EOF) { + switch (c) { + case 'a': + aout = 1; + break; + + case 'd': + debug = debug_flags_to_mask(optarg); + set_interpreter_debug_level(debug); + if (debug) + env->fcode_debug = 1; + break; + + case 'e': + if ((errlog = strchr(optarg, ':')) != NULL) { + *errlog++ = '\0'; + error_log_flags = parse_msg_flags(optarg); + } else { + errlog = optarg; + error_log_flags = MSG_ERRLOG_DEFAULT; + } + open_error_log(errlog, error_log_flags); + break; + + case 'l': + syslog_flags = parse_msg_flags(optarg); + lflag++; + break; + + case 'D': + env->fcode_debug = 1; + break; + + case 'f': + fcode_file = optarg; + break; + + case 'i': + forthstr = "interact"; + env->fcode_debug = 1; + break; + + case 's': + forthstr = optarg; + break; + + case '?': + usage(argv); + exit(1); + } + } + + if (forthstr) { + run_fcode(env, (uchar_t *)forthstr, strlen(forthstr)); + } else if (fcode_file) { + run_fcode_from_file(env, fcode_file, aout); + } else { + if ((debug & DEBUG_FC_LIST) != 0 && + ((error_log_flags | syslog_flags) & MSG_FC_DEBUG) == 0) { + log_message(MSG_WARN, "Warning, verbose debug flag(s)" + " on, but syslog/errlog not enabled for verbose" + " debug\n"); + if (errlog) + error_log_flags |= MSG_FC_DEBUG; + else + syslog_flags |= MSG_FC_DEBUG; + } + if ((debug & ~DEBUG_FC_LIST) != 0 && + ((error_log_flags | syslog_flags) & MSG_DEBUG) == 0) { + log_message(MSG_WARN, "Warning, debug flag(s) on, but" + " syslog/errlog not enabled for debug\n"); + if (errlog) + error_log_flags |= MSG_DEBUG; + else + syslog_flags |= MSG_DEBUG; + } + + if (errlog == NULL || lflag) { + if (syslog_flags & MSG_FC_DEBUG) + log_message(MSG_WARN, "Warning, verbose debug" + " not recommended for syslog\n"); + open_syslog_log("interpreter", syslog_flags); + } + run_one_efdaemon_request(env); + } + + return (0); +} diff --git a/usr/src/lib/efcode/interpreter/mapfile64 b/usr/src/lib/efcode/interpreter/mapfile64 new file mode 100644 index 0000000000..1e1367557c --- /dev/null +++ b/usr/src/lib/efcode/interpreter/mapfile64 @@ -0,0 +1,32 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +#ident "%Z%%M% %I% %E% SMI" +# +# identical to /usr/lib/ld/sparcv9/map.below4G +# We need this because malloc may return addresses which are bigger than +# 32 bits, but the Fcode interpreter assumes addresses can fit in 32 bits. +# This forces addresses to be in 32 bits. +# +text = V0x80000000; diff --git a/usr/src/lib/efcode/packages/Makefile b/usr/src/lib/efcode/packages/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/packages/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/packages/Makefile.com b/usr/src/lib/efcode/packages/Makefile.com new file mode 100644 index 0000000000..d481808477 --- /dev/null +++ b/usr/src/lib/efcode/packages/Makefile.com @@ -0,0 +1,39 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = populate.o parse.o memalloc.o +LIBRARY = fcpackage.a + +include ../../Makefile.efcode + +# +# Unfortunately, there's a circular dependency between fcdriver and fcpackage, +# and we have to compile one of them first. Since no one other than fcdriver +# directly links with fcpackage, this is the simplest way out. +# +ZDEFS = diff --git a/usr/src/lib/efcode/packages/memalloc.c b/usr/src/lib/efcode/packages/memalloc.c new file mode 100644 index 0000000000..3bb4a928ff --- /dev/null +++ b/usr/src/lib/efcode/packages/memalloc.c @@ -0,0 +1,131 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static void schizo_vtop(fcode_env_t *, fc_cell_t, fstack_t *, fstack_t *); + +/* + * claim under /openprom/client-services is only used by schizo Fcode, we + * call "schizo,claim-memory" service. + */ +void +claim(fcode_env_t *env) +{ + size_t size; + void *hint; + int align; + fc_cell_t vaddr; + int error; + + CHECK_DEPTH(env, 3, "schizo,claim-memory"); + hint = (void *)POP(DS); + size = POP(DS); + align = POP(DS); + error = fc_run_priv(env->private, "schizo,claim-memory", 3, 1, + fc_int2cell(align), fc_size2cell(size), fc_ptr2cell(hint), &vaddr); + if (error) + throw_from_fclib(env, 1, "client-services/claim failed\n"); + vaddr = mapping_to_mcookie(vaddr, size, NULL, NULL); + PUSH(DS, (fstack_t)vaddr); +} + +void +release(fcode_env_t *env) +{ + size_t size; + void *addr; + int error; + + CHECK_DEPTH(env, 2, "schizo,release-memory"); + addr = (void *)POP(DS); + size = POP(DS); + error = fc_run_priv(env->private, "schizo,release-memory", 2, 0, + fc_size2cell(size), fc_ptr2cell(addr)); + if (error) + throw_from_fclib(env, 1, "client-services/release failed\n"); + delete_mapping((fstack_t)addr); +} + +static void +fc_vtop(fcode_env_t *env) +{ + void *vaddr; + fc_cell_t physlo, physhi; + int error; + + CHECK_DEPTH(env, 1, "schizo,vtop"); + vaddr = (void *)POP(DS); + error = fc_run_priv(env->private, "schizo,vtop", 1, 2, + fc_ptr2cell(vaddr), &physlo, &physhi); + if (error) + throw_from_fclib(env, 1, "fc_vtop: '>physical' failed\n"); + + PUSH(DS, physlo); + PUSH(DS, physhi); +} + +void +install_openprom_nodes(fcode_env_t *env) +{ + MYSELF = open_instance_chain(env, env->root_node, 0); + if (MYSELF != NULL) { + make_a_node(env, "openprom", 0); + make_a_node(env, "client-services", 0); + FORTH(0, "claim", claim); + FORTH(0, "release", release); + finish_device(env); + finish_device(env); + close_instance_chain(env, MYSELF, 0); + device_end(env); + MYSELF = 0; + } +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + FORTH(0, "install-openprom-nodes", install_openprom_nodes); + FORTH(0, "claim", claim); + FORTH(0, "release", release); + P1275(0x106, 0, ">physical", fc_vtop); +} diff --git a/usr/src/lib/efcode/packages/parse.c b/usr/src/lib/efcode/packages/parse.c new file mode 100644 index 0000000000..b75dd73ee5 --- /dev/null +++ b/usr/src/lib/efcode/packages/parse.c @@ -0,0 +1,135 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +void +byte_loadfile(fcode_env_t *env) +{ + int len; + + load_file(env); + len = (int) POP(DS); + if (len) { + void *ptr = (void *) TOS; + PUSH(DS, 1); + byte_load(env); + FREE(ptr); + } else { + drop(env); + } +} + +void +define_hook(fcode_env_t *env, char *name, int len, char *fcimage) +{ + static void (*byteload_ptr)(fcode_env_t *env) = byte_loadfile; + + header(env, name, len, 0); + COMPILE_TOKEN(&do_colon); + env->state |= 1; + PUSH(DS, (fstack_t) fcimage); + PUSH(DS, strlen(fcimage)); + compile_string(env); + COMPILE_TOKEN(&byteload_ptr); + semi(env); +} + +/* + * simple parser for builtin-driver matching. + * + * Consists of alias:target<CR> + * where alias is: + * <Key>[;<key>[;<key>]] + * + * and target is: + * <path to fcode image> + */ + +#define PARSE_LINE 256 + +static void +line_error(char *where, int line, char *msg) +{ + log_message(MSG_ERROR, "%s:%d: %s\n", where, line, msg); +} + +void +make_builtin_hooks(fcode_env_t *env, char *where) +{ + FILE *fd; + int lnum = 0, len; + char *buffer, *line, *target, *next; + + if (where == NULL) + where = "/fcode/aliases"; + + if ((fd = fopen(where, "r")) == NULL) { + return; + } + + buffer = MALLOC(PARSE_LINE+1); + + while ((line = fgets(buffer, PARSE_LINE, fd)) != NULL) { + lnum++; + if ((next = strpbrk(line, " \t#\n")) != NULL) + *next = '\0'; + if (strlen(line) == 0) + continue; + if ((target = strchr(line, ':')) == NULL) { + line_error(where, lnum, "Badly formed line"); + continue; + } + *target++ = 0; + if (strlen(line) == 0) { + line_error(where, lnum, "Badly formed alias"); + continue; + } + if (strlen(target) == 0) { + line_error(where, lnum, "Badly formed target"); + continue; + } + for (; line; line = next) { + if ((next = strchr(line, ';')) != NULL) + *next++ = '\0'; + if (strlen(line) == 0) + line_error(where, lnum, "Null key in alias"); + else + define_hook(env, line, strlen(line), target); + } + } + FREE(buffer); + fclose(fd); +} diff --git a/usr/src/lib/efcode/packages/populate.c b/usr/src/lib/efcode/packages/populate.c new file mode 100644 index 0000000000..6d9cc7501e --- /dev/null +++ b/usr/src/lib/efcode/packages/populate.c @@ -0,0 +1,310 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static device_t *builtin_driver_device; + +static int +is_device_builtin_package(fcode_env_t *env, device_t *d) +{ + return (d == builtin_driver_device); +} + +static char *dropin_name; + +/* + * do-builtin-dropin ( -- ) + * Convoluted name just in case someone has "do-dropin" word in Fcode. + * Somewhat different from do-dropin in OBP, as we just load the Fcode, we + * don't do a byte-load. + */ +static void +do_builtin_dropin(fcode_env_t *env) +{ + fc_cell_t len, result; + char *buf; + int error; + static char func_name[] = "do-builtin-dropin"; + extern int check_fcode_header(char *, uchar_t *, int); + + if (dropin_name == NULL) { + log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name); + return; + } + debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name); + error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, + fc_ptr2cell(dropin_name), &len); + if (error) + return; + if (len == 0) { + log_message(MSG_WARN, "%s: '%s' zero length Fcode\n", + func_name, dropin_name); + return; + } + buf = MALLOC(len); + error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1, + fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result); + if (error) { + FREE(buf); + return; + } + + if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0) + log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n", + func_name, dropin_name); + + debug_msg(DEBUG_FIND_FCODE, + "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name, + (int)len); + PUSH(DS, (fstack_t)buf); + PUSH(DS, 1); + byte_load(env); +} + +static void +do_builtin_file(fcode_env_t *env) +{ + char *fname; + static char func_name[] = "do-builtin-file"; + fstack_t d; + + if (dropin_name == NULL) { + log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name); + return; + } + debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name); + push_a_string(env, dropin_name); + load_file(env); + d = POP(DS); + if (d) { + debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name, + dropin_name); + PUSH(DS, 1); + byte_load(env); + } else + debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n", + func_name, dropin_name); +} + +/* + * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure + * the builtin exists. If it exists, then we need to leave the xt of + * do-builtin-dropin on the stack and remember the name for do-dropin. This is + * extremely convoluted because we can't a priori populate + * SUNW,builtin-drivers. + */ +static void +builtin_driver_method_hook(fcode_env_t *env) +{ + device_t *device; + char *method, *path; + fc_cell_t len; + fstack_t d; + int error; + static char func_name[] = "builtin-driver-method-hook"; + + d = POP(DS); + CONVERT_PHANDLE(env, device, d); + if (!is_device_builtin_package(env, device)) { + PUSH(DS, d); + PUSH(DS, FALSE); + return; + } + + method = pop_a_string(env, NULL); + + /* + * Check for file in filesystem. If it exists, we'll just try to do + * a do-dropin-file. + */ + if ((path = search_for_fcode_file(env, method)) != NULL) { + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name, + method, path); + if (dropin_name) { + FREE(dropin_name); + } + dropin_name = STRDUP(path); + push_a_string(env, "do-builtin-file"); + dollar_find(env); + return; + } + + error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, + fc_ptr2cell(method), &len); + if (error || len == 0) { + if (len == 0) + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n", + func_name, method); + push_a_string(env, method); + PUSH(DS, d); + PUSH(DS, FALSE); + } else { + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n", + func_name, method, (int)len); + if (dropin_name) { + FREE(dropin_name); + } + dropin_name = STRDUP(method); + push_a_string(env, "do-builtin-dropin"); + dollar_find(env); + } +} + +void +make_a_node(fcode_env_t *env, char *name, int finish) +{ + new_device(env); + push_a_string(env, name); + device_name(env); + if (finish) + finish_device(env); +} + +void +install_package_nodes(fcode_env_t *env) +{ + MYSELF = open_instance_chain(env, env->root_node, 0); + if (MYSELF != NULL) { + make_a_node(env, "packages", 0); + make_a_node(env, "disk-label", 0); + finish_device(env); + make_a_node(env, "SUNW,builtin-drivers", 0); + builtin_driver_device = env->current_device; + finish_device(env); + finish_device(env); + close_instance_chain(env, MYSELF, 0); + device_end(env); + MYSELF = 0; + } +} + +/* + * find-builtin-driver ( str len -- xt true | false ) + */ +void +find_builtin_driver(fcode_env_t *env) +{ + fstack_t d; + + CHECK_DEPTH(env, 2, "find-builtin-driver"); + push_a_string(env, "SUNW,builtin-drivers"); + find_package(env); + d = POP(DS); + if (d) { + find_method(env); + } else { + two_drop(env); + PUSH(DS, FALSE); + } +} + +void +exec_builtin_driver(fcode_env_t *env) +{ + fstack_t d; + char *method, *path, *buf; + fc_cell_t len, result; + int error; + static char func_name[] = "exec-builtin-driver"; + extern int check_fcode_header(char *, uchar_t *, int); + + CHECK_DEPTH(env, 2, func_name); + method = pop_a_string(env, NULL); + + /* + * Check for file in filesystem. If it exists, we'll just try to do + * a do-dropin-file. + */ + if ((path = search_for_fcode_file(env, method)) != NULL) { + push_a_string(env, path); + load_file(env); + return; + } + + error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1, + fc_ptr2cell(method), &len); + if (error || len == 0) { + if (len == 0) + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n", + func_name, method); + PUSH(DS, 0); + return; + } + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n", + func_name, method, (int)len); + buf = MALLOC(len); + error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1, + fc_ptr2cell(method), fc_ptr2cell(buf), len, &result); + if (error) { + FREE(buf); + PUSH(DS, 0); + return; + } + + if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0) + log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n", + func_name, method); + + debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n", + func_name, method, buf, (int)len); + PUSH(DS, (fstack_t)buf); + PUSH(DS, len); +} + +#pragma init(_init) + +static void +_init(void) +{ + extern void set_find_method_hook(fcode_env_t *, + void (*)(fcode_env_t *)); + fcode_env_t *env = initial_env; + fstack_t d; + + ASSERT(env); + NOTICE; + + set_find_method_hook(env, builtin_driver_method_hook); + + FORTH(0, "install-package-nodes", install_package_nodes); + FORTH(0, "find-builtin-driver", find_builtin_driver); + FORTH(0, "exec-builtin-driver", exec_builtin_driver); + FORTH(0, "builtin-driver-method-hook", + builtin_driver_method_hook); + FORTH(0, "do-builtin-dropin", do_builtin_dropin); + FORTH(0, "do-builtin-file", do_builtin_file); +} diff --git a/usr/src/lib/efcode/packages/sparcv9/Makefile b/usr/src/lib/efcode/packages/sparcv9/Makefile new file mode 100644 index 0000000000..1c13ef5f37 --- /dev/null +++ b/usr/src/lib/efcode/packages/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) + +install: all $(ROOTLIBS64) diff --git a/usr/src/lib/efcode/pci/Makefile b/usr/src/lib/efcode/pci/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/pci/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/pci/Makefile.com b/usr/src/lib/efcode/pci/Makefile.com new file mode 100644 index 0000000000..759b03e7e9 --- /dev/null +++ b/usr/src/lib/efcode/pci/Makefile.com @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = pci.o +LIBRARY = lfc_upa_pci.a + +SYMLINKS = lfc_pci_pci.so lfc_gptwo_pci.so + +include ../../Makefile.efcode diff --git a/usr/src/lib/efcode/pci/pci.c b/usr/src/lib/efcode/pci/pci.c new file mode 100644 index 0000000000..53aa22cdf9 --- /dev/null +++ b/usr/src/lib/efcode/pci/pci.c @@ -0,0 +1,345 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#include <fcode/private.h> +#include <fcode/log.h> + +#include <fcdriver/fcdriver.h> + +static fstack_t +mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t mid, fstack_t lo, + fstack_t requested_len) +{ + private_data_t *cdp = DEVICE_PRIVATE(env); + int error; + fc_cell_t requested_virt, adjusted_virt; + char *service = "map-in"; + fstack_t mcookie = NULL; + int pa_offset = 0, va_offset = 0; + fstack_t adjusted_len = 0; + + pa_offset = lo & PAGEOFFSET; + lo &= PAGEMASK; + + /* adjust the requested_len to a multiple of a pagesize */ + requested_len = (requested_len + pa_offset + PAGEOFFSET) & PAGEMASK; + + error = fc_run_priv(cdp->common, service, 4, 1, + fc_size2cell(requested_len), fc_uint32_t2cell(hi), + fc_uint32_t2cell(mid), fc_uint32_t2cell(lo), &requested_virt); + + if (error) + throw_from_fclib(env, 1, "pci:%s: failed\n", service); + + /* + * Check the requested_virt address and ensure that + * it starts at a page boundary. + */ + + va_offset = requested_virt & PAGEOFFSET; + + if (va_offset != 0) { + + /* + * Align the virtual address to a page boundary + * before mapping it to a mcookie. Recalcuate the + * length and round it up to the next multiple of a pagesize. + */ + + adjusted_virt = requested_virt & PAGEMASK; + adjusted_len = (requested_len + va_offset + PAGEOFFSET) + & PAGEMASK; + } + + mcookie = mapping_to_mcookie(requested_virt, requested_len, + adjusted_virt, adjusted_len); + + if (mcookie == NULL) + throw_from_fclib(env, 1, "pci-mapin-> pci:%s:" + " mapping_to_mcookie failed\n", service); + /* + * Recalculate the address of the mcookie. + */ + + mcookie += va_offset + pa_offset; + + debug_msg(DEBUG_REG_ACCESS, "pci:map-in: %llx -> %x\n", + (uint64_t)requested_virt, (uint32_t)mcookie); + + return (mcookie); +} + +static void +mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t requested_len) +{ + private_data_t *cdp = DEVICE_PRIVATE(env); + char *service = "map-out"; + fc_cell_t requested_virt; + int error; + + if (!is_mcookie(mcookie)) { + log_message(MSG_ERROR, "pci:%s: %x not mcookie!\n", service, + (uint32_t)mcookie); + requested_virt = mcookie; + } else { + requested_virt = mcookie_to_rvirt(mcookie); + requested_len = mcookie_to_rlen(mcookie); + delete_mapping(mcookie); + debug_msg(DEBUG_REG_ACCESS, "pci:%s: %x -> %llx\n", service, + (uint32_t)mcookie, (uint64_t)requested_virt); + } + + error = fc_run_priv(cdp->common, service, 2, 0, + fc_size2cell(requested_len), requested_virt); + + if (error) + log_message(MSG_ERROR, "pci:%s: failed\n", service); +} + +static void +pci_config_fetch(fcode_env_t *env, char *service) +{ + uint32_t cfgadd; + fc_cell_t value; + private_data_t *h = DEVICE_PRIVATE(env); + int error; + + ASSERT(h); + CHECK_DEPTH(env, 1, service); + cfgadd = POP(DS); + error = fc_run_priv(h->common, service, 1, 1, fc_uint32_t2cell(cfgadd), + &value); + + if (error) + throw_from_fclib(env, 1, "pci:%s ( %x ) FAIL\n", service, + cfgadd); + + PUSH(DS, value); +} + +static void +pci_config_store(fcode_env_t *env, char *service) +{ + uint32_t cfgadd; + fc_cell_t value; + private_data_t *h = DEVICE_PRIVATE(env); + int error; + + ASSERT(h); + CHECK_DEPTH(env, 2, service); + cfgadd = POP(DS); + value = POP(DS); + error = fc_run_priv(h->common, service, 2, 0, fc_uint32_t2cell(cfgadd), + fc_uint32_t2cell(value)); + + if (error) + throw_from_fclib(env, 1, "pci:%s ( %x %x ) FAIL\n", service, + cfgadd, value); +} + +static void +config_lfetch(fcode_env_t *env) +{ + pci_config_fetch(env, "config-l@"); +} + +static void +config_lstore(fcode_env_t *env) +{ + pci_config_store(env, "config-l!"); +} + +static void +config_wfetch(fcode_env_t *env) +{ + pci_config_fetch(env, "config-w@"); +} + +static void +config_wstore(fcode_env_t *env) +{ + pci_config_store(env, "config-w!"); +} + +static void +config_bfetch(fcode_env_t *env) +{ + pci_config_fetch(env, "config-b@"); +} + +static void +config_bstore(fcode_env_t *env) +{ + pci_config_store(env, "config-b!"); +} + +static void +do_map_in(fcode_env_t *env) +{ + fstack_t phi, pmid, plo, len, addr; + + CHECK_DEPTH(env, 4, "pci:map-in"); + len = POP(DS); + phi = POP(DS); + pmid = POP(DS); + plo = POP(DS); + addr = mem_map_in(env, phi, pmid, plo, len); + PUSH(DS, addr); +} + +static void +do_map_out(fcode_env_t *env) +{ + fstack_t addr, len; + + CHECK_DEPTH(env, 2, "pci:map-out"); + len = POP(DS); + addr = POP(DS); + mem_map_out(env, addr, len); +} + +static void +do_encode_unit(fcode_env_t *env) +{ + char enc_buf[64]; + uint32_t hi; + int dev, fn; + + CHECK_DEPTH(env, 3, "pci:encode-unit"); + hi = POP(DS); + (void) POP(DS); + (void) POP(DS); + + fn = ((hi >> 8) & 0x7); + dev = ((hi >> 11) & 0x1f); + + if (fn) { + sprintf(enc_buf, "%x,%x", dev, fn); + } else { + sprintf(enc_buf, "%x", dev); + } + debug_msg(DEBUG_REG_ACCESS, "pci:encode-unit ( %x ) -> %s\n", + hi, enc_buf); + push_a_string(env, STRDUP(enc_buf)); +} + +static void +do_decode_unit(fcode_env_t *env) +{ + int lo, hi, unit; + char *buf; + + CHECK_DEPTH(env, 2, "pci:decode-unit"); + buf = pop_a_string(env, NULL); + if (sscanf(buf, "%x,%x", &hi, &lo) != 2) { + throw_from_fclib(env, 1, "pci:decode-unit: '%s'", buf); + } + unit = ((hi & 0x1f) << 11); + unit |= ((lo & 0x7) << 8); + debug_msg(DEBUG_REG_ACCESS, "pci:decode-unit ( '%s' ) -> 0 0 %x\n", + buf, unit); + PUSH(DS, 0); + PUSH(DS, 0); + PUSH(DS, unit); +} + +static void +do_device_id(fcode_env_t *env) +{ + uint32_t cfgadd; + uint16_t ven_id, dev_id; + char buf[40]; + + CHECK_DEPTH(env, 3, "pci:device-id"); + cfgadd = POP(DS); + (void) POP(DS); + (void) POP(DS); + PUSH(DS, cfgadd + PCI_CONF_VENID); + config_wfetch(env); + ven_id = POP(DS); + PUSH(DS, cfgadd + PCI_CONF_DEVID); + config_wfetch(env); + dev_id = POP(DS); + sprintf(buf, "pci%x,%x", ven_id, dev_id); + push_a_string(env, STRDUP(buf)); +} + +static void +do_class_id(fcode_env_t *env) +{ + uint32_t cfgadd; + uint8_t basclass, subclass, progclass; + char buf[40]; + + CHECK_DEPTH(env, 3, "pci:class-id"); + cfgadd = POP(DS); + (void) POP(DS); + (void) POP(DS); + PUSH(DS, cfgadd + PCI_CONF_BASCLASS); + config_bfetch(env); + basclass = POP(DS); + PUSH(DS, cfgadd + PCI_CONF_SUBCLASS); + config_bfetch(env); + subclass = POP(DS); + PUSH(DS, cfgadd + PCI_CONF_PROGCLASS); + config_bfetch(env); + progclass = POP(DS); + sprintf(buf, "pciclass%02x%02x%02x", basclass, subclass, progclass); + push_a_string(env, STRDUP(buf)); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + ASSERT(env->current_device); + NOTICE; + + FORTH(0, "config-l@", config_lfetch); + FORTH(0, "config-l!", config_lstore); + FORTH(0, "config-w@", config_wfetch); + FORTH(0, "config-w!", config_wstore); + FORTH(0, "config-b@", config_bfetch); + FORTH(0, "config-b!", config_bstore); + FORTH(0, "map-in", do_map_in); + FORTH(0, "map-out", do_map_out); + FORTH(0, "decode-unit", do_decode_unit); + FORTH(0, "encode-unit", do_encode_unit); + FORTH(0, "device-id", do_device_id); + FORTH(0, "class-id", do_class_id); + + install_dma_methods(env); +} diff --git a/usr/src/lib/efcode/pci/sparcv9/Makefile b/usr/src/lib/efcode/pci/sparcv9/Makefile new file mode 100644 index 0000000000..6656b54ad3 --- /dev/null +++ b/usr/src/lib/efcode/pci/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) $(FCDRIVER64) + +install: all $(ROOTLIBS64) $(ROOTSYMLINKS64) diff --git a/usr/src/lib/efcode/upa/Makefile b/usr/src/lib/efcode/upa/Makefile new file mode 100644 index 0000000000..29132d88a1 --- /dev/null +++ b/usr/src/lib/efcode/upa/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.subdirs diff --git a/usr/src/lib/efcode/upa/Makefile.com b/usr/src/lib/efcode/upa/Makefile.com new file mode 100644 index 0000000000..c3edf9eb42 --- /dev/null +++ b/usr/src/lib/efcode/upa/Makefile.com @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +OBJECTS = upa.o +LIBRARY = lfc_upa.a + +include ../../Makefile.efcode diff --git a/usr/src/lib/efcode/upa/sparcv9/Makefile b/usr/src/lib/efcode/upa/sparcv9/Makefile new file mode 100644 index 0000000000..c545bf4255 --- /dev/null +++ b/usr/src/lib/efcode/upa/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +DYNFLAGS += $(FCODE64) + +install: all $(ROOTLIBS64) $(ROOTSYMLINKS64) diff --git a/usr/src/lib/efcode/upa/upa.c b/usr/src/lib/efcode/upa/upa.c new file mode 100644 index 0000000000..251dd5183d --- /dev/null +++ b/usr/src/lib/efcode/upa/upa.c @@ -0,0 +1,74 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <string.h> +#include <fcode/private.h> + +static void +do_decode_unit(fcode_env_t *env) +{ + CHECK_DEPTH(env, 2, "upa:decode-unit"); + parse_two_int(env); + if ((TOS & 0x1c0) == 0) { + TOS = ((TOS << 1) | 0x1c0); + } +} + +static void +do_encode_unit(fcode_env_t *env) +{ + static char buf[8]; + fstack_t hi, mid, lo; + int dev, fn, len; + + CHECK_DEPTH(env, 2, "upa:encode-unit"); + hi = POP(DS); + lo = POP(DS); + hi = ((hi >> 1) & 0x1f); + sprintf(buf, "%x,%x", hi, lo); + push_a_string(env, buf); +} + +#pragma init(_init) + +static void +_init(void) +{ + fcode_env_t *env = initial_env; + + ASSERT(env); + NOTICE; + + create_int_prop(env, "#address-cells", 2); + create_int_prop(env, "#size-cells", 2); + + FORTH(0, "decode-unit", do_decode_unit); + FORTH(0, "encode-unit", do_encode_unit); + +} |