summaryrefslogtreecommitdiff
path: root/usr/src/lib/efcode/jupiter/jupiter.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/efcode/jupiter/jupiter.c')
-rw-r--r--usr/src/lib/efcode/jupiter/jupiter.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/usr/src/lib/efcode/jupiter/jupiter.c b/usr/src/lib/efcode/jupiter/jupiter.c
new file mode 100644
index 0000000000..2fc159bc20
--- /dev/null
+++ b/usr/src/lib/efcode/jupiter/jupiter.c
@@ -0,0 +1,437 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (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 2006 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>
+
+#include <sys/opl_cfg.h>
+
+/* VA for HardWare Descriptor */
+static hwd_cmu_chan_t hwd_va_cmu;
+static hwd_leaf_t hwd_va_pci;
+
+/* Macro to get I/O portid */
+#define DO_GET_IO_PORTID(env, lo, hi, portid) \
+ PUSH(DS, lo); \
+ PUSH(DS, hi); \
+ do_get_io_portid(env); \
+ portid = (uint32_t)POP(DS)
+
+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, "jupiter:%s: failed\n", service);
+
+ mcookie = mapping_to_mcookie(virt, len, NULL, NULL);
+
+ if (mcookie == NULL)
+ throw_from_fclib(env, 1,
+ "jupiter:%s: mapping_to_mcookie failed\n", service);
+
+ mcookie += offset;
+
+ debug_msg(DEBUG_REG_ACCESS, "jupiter:%s: %llx -> %x\n", service,
+ (long long)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, "jupiter:%s: %x not an mcookie!\n",
+ service, (int)mcookie);
+ virt = mcookie;
+ } else {
+ virt = mcookie_to_addr(mcookie);
+ debug_msg(DEBUG_REG_ACCESS, "jupiter:%s: %x -> %llx\n",
+ service, (int)mcookie, (long long)virt);
+ delete_mapping(mcookie);
+ }
+
+ error = fc_run_priv(pdp->common, service, 2, 0,
+ fc_size2cell(len), virt);
+ if (error)
+ log_message(MSG_ERROR, "jupiter:%s: failed\n", service);
+}
+
+static void
+do_map_in(fcode_env_t *env)
+{
+ fstack_t phi, plo, len, addr;
+
+ CHECK_DEPTH(env, 3, "jupiter: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, "jupiter:map-out");
+ len = POP(DS);
+ addr = POP(DS);
+ mem_map_out(env, addr, len);
+}
+
+static void
+do_get_io_portid(fcode_env_t *env)
+{
+ fstack_t phi, plo;
+ unsigned int portid, lsb, ch, leaf;
+
+ CHECK_DEPTH(env, 2, "jupiter:get-portid");
+
+ phi = POP(DS);
+ plo = POP(DS);
+
+ lsb = OPL_ADDR_TO_LSB(phi);
+ ch = OPL_ADDR_TO_CHANNEL(phi);
+ leaf = OPL_ADDR_TO_LEAF(phi, plo);
+
+ portid = OPL_IO_PORTID(lsb, ch, leaf);
+
+ debug_msg(DEBUG_REG_ACCESS, "jupiter:get-portid ( %x %x ) -> %x\n",
+ (int)phi, (int)plo, (int)portid);
+ PUSH(DS, portid);
+}
+
+static void
+do_encode_unit(fcode_env_t *env)
+{
+ char enc_buf[64];
+ fstack_t hi, lo;
+ uint32_t id;
+ long long off;
+
+ CHECK_DEPTH(env, 2, "jupiter:encode-unit");
+
+ hi = POP(DS);
+ lo = POP(DS);
+ off = (long long)(((hi & 0x1F) << 32) | lo);
+
+ /* Convert physical address to portid */
+ DO_GET_IO_PORTID(env, lo, hi, id);
+
+ if (off) {
+ (void) sprintf(enc_buf, "%x,%llx", id, off);
+ } else {
+ (void) sprintf(enc_buf, "%x", id);
+ }
+
+ debug_msg(DEBUG_REG_ACCESS, "jupiter:encode_unit ( %x %x ) -> '%s'\n",
+ (uint32_t)hi, (uint32_t)lo, enc_buf);
+
+ push_a_string(env, STRDUP(enc_buf));
+}
+
+static void
+do_decode_unit(fcode_env_t *env)
+{
+ uint32_t hi;
+ long long lo;
+ unsigned int portid, lsb, ch;
+ char *buf;
+
+ CHECK_DEPTH(env, 2, "jupiter:decode-unit");
+
+ buf = pop_a_string(env, NULL);
+ if (sscanf(buf, "%x,%llx", &portid, &lo) != 2) {
+ if (sscanf(buf, "%x", &portid) != 1) {
+ throw_from_fclib(env, 1, "jupiter:decode_unit:%s",
+ buf);
+ }
+ lo = 0;
+ }
+
+ lsb = OPL_IO_PORTID_TO_LSB(portid);
+ ch = OPL_PORTID_TO_CHANNEL(portid);
+ hi = OPL_ADDR_HI(lsb, ch);
+
+ debug_msg(DEBUG_REG_ACCESS,
+ "jupiter:decode_unit ( '%s' ) -> %x %llx\n", buf, hi, lo);
+
+ PUSH(DS, (fstack_t)lo);
+ PUSH(DS, (fstack_t)hi);
+}
+
+static void
+do_device_id(fcode_env_t *env)
+{
+ common_data_t *cdp = COMMON_PRIVATE(env);
+ char *buf = NULL;
+ uint32_t hi;
+ long long lo;
+ uint32_t portid, ch, leaf;
+
+ CHECK_DEPTH(env, 2, "jupiter:device-id");
+
+ hi = POP(DS);
+ lo = POP(DS);
+
+ portid = 0;
+ if (cdp && cdp->fc.unit_address &&
+ ((buf = strdup(cdp->fc.unit_address)) != NULL)) {
+ /*
+ * Get portid number from unit_address
+ * Because of no leaf information in physical address
+ */
+ if (sscanf(buf, "%x,%llx", &portid, &lo) != 2) {
+ if (sscanf(buf, "%x", &portid) != 1) {
+ throw_from_fclib(env, 1,
+ "jupiter:do_device_id: invalid %s", buf);
+ }
+ }
+ } else {
+ /*
+ * Non existence unit_address case.
+ * Convert physical address to portid.
+ */
+ throw_from_fclib(env, 1,
+ "jupiter:do_device_id: failed unit address");
+ DO_GET_IO_PORTID(env, lo, hi, portid);
+ }
+
+ debug_msg(DEBUG_FIND_FCODE,
+ "jupiter:do_device_id:(%x,%llx)\n", portid, lo);
+
+ /* Pick up each ID from portid */
+ ch = OPL_PORTID_TO_CHANNEL(portid);
+ leaf = OPL_PORTID_TO_LEAF(portid);
+
+ if (ch == OPL_CMU_CHANNEL) {
+ /*
+ * CMU-CH: PCICMU CHANNEL
+ */
+ debug_msg(DEBUG_FIND_FCODE,
+ "jupiter:do_device_id:cmu-ch\n");
+ push_a_string(env, "cmu-ch");
+ } else if (OPL_OBERON_CHANNEL(ch) && OPL_VALID_LEAF(leaf)) {
+ /*
+ * PCI-CH: Oberon Leaves CHANNEL
+ */
+ if (leaf) {
+ /* Leaf B */
+ debug_msg(DEBUG_FIND_FCODE,
+ "jupiter:do_device_id:jup-oberon-pci1\n");
+ push_a_string(env, "jup-oberon-pci1");
+ } else {
+ /* Leaf A */
+ debug_msg(DEBUG_FIND_FCODE,
+ "jupiter:do_device_id:jup-oberon-pci0\n");
+ push_a_string(env, "jup-oberon-pci0");
+ }
+ } else {
+ /* Not matched to any channels */
+ throw_from_fclib(env, 1,
+ "jupiter:do_device_id: invalid portid %x", portid);
+ push_a_string(env, "");
+ }
+
+ /* Free the duplicated buf */
+ if (buf != NULL)
+ free(buf);
+}
+
+static void
+do_get_hwd_va(fcode_env_t *env)
+{
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+ char *service = "get-hwd-va";
+ char *buf;
+ uint32_t portid = 0;
+ int ch;
+ int error;
+ fc_cell_t status;
+ void *hwd_va;
+
+ CHECK_DEPTH(env, 2, "jupiter:get-hwd-va");
+
+ /* Get a portid with string format */
+ buf = pop_a_string(env, NULL);
+
+ /* Convert to the integer from the string */
+ if (sscanf(buf, "%x", &portid) != 1) {
+ throw_from_fclib(env, 1, "jupiter:%s: invalid portid",
+ service);
+ }
+
+ ch = OPL_PORTID_TO_CHANNEL(portid);
+ if (!OPL_VALID_CHANNEL(ch)) {
+ throw_from_fclib(env, 1, "jupiter:%s: invalid poritd",
+ service);
+ hwd_va = 0;
+ goto out;
+ }
+
+ if (ch == OPL_CMU_CHANNEL) {
+ hwd_va = (void *)&hwd_va_cmu;
+ } else {
+ hwd_va = (void *)&hwd_va_pci;
+ }
+
+ /*
+ * Get the virtual address of hwd specified with portid.
+ */
+ error = fc_run_priv(pdp->common, service, 2, 1,
+ fc_uint32_t2cell(portid), fc_ptr2cell(hwd_va), &status);
+
+ if (error || !status)
+ throw_from_fclib(env, 1, "jupiter:%s: failed\n", service);
+
+out:
+ PUSH(DS, (fstack_t)hwd_va);
+}
+
+static void
+do_get_intrp_name(fcode_env_t *env)
+{
+ /*
+ * Just pass the "eFCode" string.
+ */
+
+ debug_msg(DEBUG_FIND_FCODE,
+ "jupiter: do_get_intrp_name: eFCode\n");
+
+ push_a_string(env, "eFCode");
+}
+
+static void
+do_master_interrupt(fcode_env_t *env)
+{
+ int portid;
+ token_t xt;
+
+ CHECK_DEPTH(env, 2, "jupiter:master-interrput");
+ portid = POP(DS);
+ xt = POP(DS);
+
+ PUSH(DS, FALSE);
+ debug_msg(DEBUG_REG_ACCESS,
+ "jupiter:master-interrupt ( %x %x ) -> %x\n",
+ portid, xt, (int)FALSE);
+}
+
+static void
+do_register_vector_entry(fcode_env_t *env)
+{
+ int ign, ino, level;
+
+ CHECK_DEPTH(env, 3, "jupiter:register-vector-entry");
+ ign = POP(DS);
+ ino = POP(DS);
+ level = POP(DS);
+
+ PUSH(DS, FALSE);
+ debug_msg(DEBUG_REG_ACCESS,
+ "jupiter: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 = -1;
+
+ PUSH(DS, mid);
+ debug_msg(DEBUG_REG_ACCESS,
+ "jupiter:get-interrupt-target ( ) -> %x\n", mid);
+}
+
+
+#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, "map-out", do_map_out);
+ FORTH(0, "get-portid", do_get_io_portid);
+ FORTH(0, "decode-unit", do_decode_unit);
+ FORTH(0, "encode-unit", do_encode_unit);
+ FORTH(0, "device-id", do_device_id);
+ FORTH(0, "get-hwd-va", do_get_hwd_va);
+ FORTH(0, "get-fcinterp-name", do_get_intrp_name);
+ FORTH(0, "master-interrupt", do_master_interrupt);
+ FORTH(0, "register-vector-entry", do_register_vector_entry);
+ FORTH(0, "get-interrupt-target", do_get_interrupt_target);
+}