root/usr/src/uts/sun4u/sys/opl_cfg.h
/*
 * 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 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_OPL_CFG_H
#define _SYS_OPL_CFG_H

#pragma ident   "%Z%%M% %I%     %E% SMI"

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * Hardware Descriptor.
 */

#include <sys/opl_hwdesc.h>

#define OPL_PSB_MODE    0x0
#define OPL_XSB_MODE    0x1

#define OPL_LSBID_MASK  0x1f

/*
 * CPU device portid:
 *
 *        1  0  0  0  0  0  0  0   0  0    0
 *        0  9  8  7  6  5  4  3   2  1    0
 *      ---------------------------------------
 *      | 1 |   LSB ID    | CHIP | CORE | CPU |
 *      ---------------------------------------
 */
#define OPL_CPUID_TO_LSB(devid) ((devid >> 5) & OPL_LSBID_MASK)
#define OPL_CPU_CHIP(devid)     ((devid >> 3) & 0x3)
#define OPL_CORE(devid)         ((devid >> 1) & 0x3)
#define OPL_CPU(devid)          ((devid & 0x001))

#define OPL_PORTID(board, chip)         ((1 << 10) | (board << 5) | (chip << 3))

#define OPL_CPUID(board, chip, core, cpu)                               \
                                                                        \
        ((board << 5) | (chip << 3) | (core << 1) | (cpu))

/*
 * Dummy address space for a chip.
 */
#define OPL_PROC_AS(board, chip)                                        \
                                                                        \
        ((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) |        \
                (1ULL << 33) | ((uint64_t)chip << 4))

/*
 * pseudo-mc portid:
 *
 *        1   0   0  0  0  0  0   0  0  0  0
 *        0   9   8  7  6  5  4   3  2  1  0
 *      -------------------------------------
 *      | 0 | 1 |     LSB ID    |    0      |
 *      -------------------------------------
 */
#define OPL_LSB_TO_PSEUDOMC_PORTID(board)       ((1 << 9) | (board << 4))

/*
 * Dummy address space for a pseudo memory node
 */
#define OPL_MC_AS(board)                                                \
                                                                        \
        ((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) |        \
                (1ULL << 33))

/*
 * Defines used by the Jupiter bus-specific library (lfc_jupiter.so).
 * This library gets loaded into the user-level fcode interpreter
 * and provides bus-specific methods that are used by the Oberon
 * and the CMU-channel fcode drivers.
 */
/*
 *
 * IO port id:
 *
 *        1  0  0  0  0  0  0  0   0  0    0
 *        0  9  8  7  6  5  4  3   2  1    0
 *      ---------------------------------------
 *      | 0  0 |   LSB ID    | IO CHAN | LEAF |
 *      ---------------------------------------
 */
#define OPL_PORTID_MASK                 0x7FF
#define OPL_IO_PORTID_TO_LSB(portid)    (((portid) >> 4) & OPL_LSBID_MASK)
#define OPL_PORTID_TO_CHANNEL(portid)   (((portid) >> 1) & 0x7)
#define OPL_PORTID_TO_LEAF(portid)      ((portid) & 0x1)
#define OPL_IO_PORTID(lsb, ch, leaf)    \
        (((lsb & OPL_LSBID_MASK) << 4) | ((ch & 0x7) << 1) | (leaf & 0x1))

#define OPL_ADDR_TO_LSB(hi)             (((hi) >> 8) & OPL_LSBID_MASK)
#define OPL_ADDR_TO_CHANNEL(hi)         (((hi) >> 5) & 0x7)
#define OPL_ADDR_TO_LEAF(hi, lo)        \
                (!(((hi) >> 7) & 0x1) && (((lo) >> 20) == 0x7))

#define OPL_ADDR_HI(lsb, ch)            \
                ((1 << 14) | ((lsb & OPL_LSBID_MASK) << 8) | ((ch & 0x7) << 5))

#define OPL_CMU_CHANNEL 4
#define OPL_OBERON_CHANNEL(ch)  ((ch >= 0) && (ch <= 3))
#define OPL_VALID_CHANNEL(ch)   ((ch >= 0) && (ch <= 4))
#define OPL_VALID_LEAF(leaf)    ((leaf == 0) || (leaf == 1))

#if defined(_KERNEL)

/*
 * We store the pointers to the following device nodes in this structure:
 *      "pseudo-mc"
 *      "cmp"
 *      "pci"
 *
 * These nodes represent the different branches we create in the device
 * tree for each board during probe. We store them so that when a board
 * is unprobed, we can easily locate the branches and destroy them.
 */
typedef struct {
        dev_info_t              *cfg_pseudo_mc;
        dev_info_t              *cfg_cpu_chips[HWD_CPU_CHIPS_PER_CMU];
        dev_info_t              *cfg_cmuch_leaf;
        fco_handle_t            cfg_cmuch_handle;
        char                    *cfg_cmuch_probe_str;
        dev_info_t              *cfg_pcich_leaf[HWD_PCI_CHANNELS_PER_SB]
                                                [HWD_LEAVES_PER_PCI_CHANNEL];
        fco_handle_t            cfg_pcich_handle[HWD_PCI_CHANNELS_PER_SB]
                                                [HWD_LEAVES_PER_PCI_CHANNEL];
        char                    *cfg_pcich_probe_str[HWD_PCI_CHANNELS_PER_SB]
                                                [HWD_LEAVES_PER_PCI_CHANNEL];
        void                    *cfg_hwd;
} opl_board_cfg_t;

/*
 * Prototypes for the callback functions used in the DDI functions
 * used to perform device tree operations.
 *
 * init functions are used to find device nodes that are created
 * by Solaris during boot.
 *
 * create functions are used to initialize device nodes during DR.
 */
typedef int     (*opl_init_func_t)(dev_info_t *, char *, int);
typedef int     (*opl_create_func_t)(dev_info_t *, void *, uint_t);

/*
 * The following probe structure carries all the information required
 * at various points during probe. This structure serves two purposes:
 *
 *      1. It allows us to streamline functions and have them accept just
 *         a single argument.
 *
 *      2. It allows us to pass information to the DDI callbacks. DDI
 *         callbacks are allowed only one argument. It also allows
 *         us to return information from those callbacks.
 *
 * The probe structure carries a snapshot of the hardware descriptor
 * taken at the beginning of a probe.
 */
typedef struct {
        hwd_header_t            *pr_hdr;
        hwd_sb_status_t         *pr_sb_status;
        hwd_domain_info_t       *pr_dinfo;
        hwd_sb_t                *pr_sb;

        int                     pr_board;
        int                     pr_cpu_chip;
        int                     pr_core;
        int                     pr_cpu;
        int                     pr_channel;
        int                     pr_channel_status;
        int                     pr_leaf;
        int                     pr_leaf_status;

        opl_create_func_t       pr_create;
        dev_info_t              *pr_parent;
        dev_info_t              *pr_node;
        int                     pr_hold;
        unsigned                pr_cpu_impl;
} opl_probe_t;

#define OPL_STR_LEN     256

#define OPL_HI(value)   ((uint32_t)((uint64_t)(value) >> 32))
#define OPL_LO(value)   ((uint32_t)(value))

typedef struct {
        uint32_t        addr_hi;
        uint32_t        addr_lo;
} opl_addr_t;

typedef struct {
        uint32_t        rg_addr_hi;
        uint32_t        rg_addr_lo;
        uint32_t        rg_size_hi;
        uint32_t        rg_size_lo;
} opl_range_t;

typedef struct {
        int             mc_bank;
        uint32_t        mc_hi;
        uint32_t        mc_lo;
} opl_mc_addr_t;

/*
 * Convenience macros for DDI property operations. The functions that
 * DDI provides for getting and updating properties are not symmetric
 * either in their names or in the number of arguments. These macros
 * hide the gory details and provide a symmetric way to get and
 * set properties.
 */
#define opl_prop_get_string(dip, name, bufp, lenp)                      \
        ddi_getlongprop(DDI_DEV_T_ANY, dip,                             \
                        DDI_PROP_DONTPASS, name, (caddr_t)bufp, lenp)

#define opl_prop_get_int(dip, name, value, defvalue)                    \
(                                                                       \
        *(value) = ddi_getprop(DDI_DEV_T_ANY, dip,                      \
                        DDI_PROP_DONTPASS, name, defvalue),             \
        (*(value) == defvalue) ? DDI_PROP_NOT_FOUND : DDI_PROP_SUCCESS  \
)

#define opl_prop_get_int_array(dip, name, data, nelems)                 \
        ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,                   \
        DDI_PROP_DONTPASS, name, (int **)&data, (uint_t *)&nelems)

#define OPL_GET_PROP(type, dip, name, value, arg)                       \
        opl_prop_get_##type(dip, name, value, arg)

#define OPL_GET_PROP_ARRAY(type, dip, name, values, nvalues)            \
        opl_prop_get_##type##_array(dip, name, values, nvalues)

#define OPL_FREE_PROP(data)                                             \
        ddi_prop_free((void *)data)

#define OPL_UPDATE_PROP_ERR(ret, name)                                  \
        if (ret != DDI_PROP_SUCCESS) {                                  \
                cmn_err(CE_WARN, "%s (%d): %s update property error (%d)",\
                        __FILE__, __LINE__, name, ret);                 \
                return (DDI_WALK_ERROR);                                \
        }

#define OPL_UPDATE_PROP(type, dip, name, value)                         \
        ret = ndi_prop_update_##type(DDI_DEV_T_NONE, dip, name, value); \
        OPL_UPDATE_PROP_ERR(ret, name)


#define OPL_UPDATE_PROP_ARRAY(type, dip, name, values, nvalues)         \
        ret = ndi_prop_update_##type##_array(DDI_DEV_T_NONE, dip,       \
                                                name, values, nvalues); \
        OPL_UPDATE_PROP_ERR(ret, name)

/*
 * Node names for the different nodes supported in OPL.
 */
#define OPL_PSEUDO_MC_NODE      "pseudo-mc"
#define OPL_CPU_CHIP_NODE       "cmp"
#define OPL_CORE_NODE           "core"
#define OPL_CPU_NODE            "cpu"
#define OPL_PCI_LEAF_NODE       "pci"

typedef struct {
        char            *fc_service;
        fc_ops_t        *fc_op;
} opl_fc_ops_t;

/*
 * Functions used by drmach
 */
extern int      opl_probe_sb(int, unsigned *);
extern int      opl_unprobe_sb(int);
extern int      opl_read_hwd(int, hwd_header_t **, hwd_sb_status_t **,
                                hwd_domain_info_t **, hwd_sb_t **);
extern void     opl_hold_devtree(void);
extern void     opl_release_devtree(void);
extern int      oplcfg_pa_swap(int from, int to);
extern int      opl_init_cfg();

#endif /* _KERNEL */

#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_OPL_CFG_H */