diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/efcode/fcdriver | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/efcode/fcdriver')
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/Makefile | 29 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/Makefile.com | 33 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/build_tree.c | 250 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/dma.c | 123 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/fcdebug.c | 116 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/get_req.c | 466 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/ioctl.c | 110 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/load_node.c | 289 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/misc.c | 659 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/phandle.c | 204 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/property.c | 180 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/sparcv9/Makefile | 34 | ||||
| -rw-r--r-- | usr/src/lib/efcode/fcdriver/upload.c | 178 |
13 files changed, 2671 insertions, 0 deletions
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); +} |
