1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_OPL_CFG_H 27 #define _SYS_OPL_CFG_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 /* 36 * Hardware Descriptor. 37 */ 38 39 #include <sys/opl_hwdesc.h> 40 41 #define OPL_PSB_MODE 0x0 42 #define OPL_XSB_MODE 0x1 43 44 #define OPL_LSBID_MASK 0x1f 45 46 /* 47 * CPU device portid: 48 * 49 * 1 0 0 0 0 0 0 0 0 0 0 50 * 0 9 8 7 6 5 4 3 2 1 0 51 * --------------------------------------- 52 * | 1 | LSB ID | CHIP | CORE | CPU | 53 * --------------------------------------- 54 */ 55 #define OPL_CPUID_TO_LSB(devid) ((devid >> 5) & OPL_LSBID_MASK) 56 #define OPL_CPU_CHIP(devid) ((devid >> 3) & 0x3) 57 #define OPL_CORE(devid) ((devid >> 1) & 0x3) 58 #define OPL_CPU(devid) ((devid & 0x001)) 59 60 #define OPL_PORTID(board, chip) ((1 << 10) | (board << 5) | (chip << 3)) 61 62 #define OPL_CPUID(board, chip, core, cpu) \ 63 \ 64 ((board << 5) | (chip << 3) | (core << 1) | (cpu)) 65 66 /* 67 * Dummy address space for a chip. 68 */ 69 #define OPL_PROC_AS(board, chip) \ 70 \ 71 ((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) | \ 72 (1ULL << 33) | ((uint64_t)chip << 4)) 73 74 /* 75 * pseudo-mc portid: 76 * 77 * 1 0 0 0 0 0 0 0 0 0 0 78 * 0 9 8 7 6 5 4 3 2 1 0 79 * ------------------------------------- 80 * | 0 | 1 | LSB ID | 0 | 81 * ------------------------------------- 82 */ 83 #define OPL_LSB_TO_PSEUDOMC_PORTID(board) ((1 << 9) | (board << 4)) 84 85 /* 86 * Dummy address space for a pseudo memory node 87 */ 88 #define OPL_MC_AS(board) \ 89 \ 90 ((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) | \ 91 (1ULL << 33)) 92 93 /* 94 * Defines used by the Jupiter bus-specific library (lfc_jupiter.so). 95 * This library gets loaded into the user-level fcode interpreter 96 * and provides bus-specific methods that are used by the Oberon 97 * and the CMU-channel fcode drivers. 98 */ 99 /* 100 * 101 * IO port id: 102 * 103 * 1 0 0 0 0 0 0 0 0 0 0 104 * 0 9 8 7 6 5 4 3 2 1 0 105 * --------------------------------------- 106 * | 0 0 | LSB ID | IO CHAN | LEAF | 107 * --------------------------------------- 108 */ 109 #define OPL_PORTID_MASK 0x7FF 110 #define OPL_IO_PORTID_TO_LSB(portid) (((portid) >> 4) & OPL_LSBID_MASK) 111 #define OPL_PORTID_TO_CHANNEL(portid) (((portid) >> 1) & 0x7) 112 #define OPL_PORTID_TO_LEAF(portid) ((portid) & 0x1) 113 #define OPL_IO_PORTID(lsb, ch, leaf) \ 114 (((lsb & OPL_LSBID_MASK) << 4) | ((ch & 0x7) << 1) | (leaf & 0x1)) 115 116 #define OPL_ADDR_TO_LSB(hi) (((hi) >> 8) & OPL_LSBID_MASK) 117 #define OPL_ADDR_TO_CHANNEL(hi) (((hi) >> 5) & 0x7) 118 #define OPL_ADDR_TO_LEAF(hi, lo) \ 119 (!(((hi) >> 7) & 0x1) && (((lo) >> 20) == 0x7)) 120 121 #define OPL_ADDR_HI(lsb, ch) \ 122 ((1 << 14) | ((lsb & OPL_LSBID_MASK) << 8) | ((ch & 0x7) << 5)) 123 124 #define OPL_CMU_CHANNEL 4 125 #define OPL_OBERON_CHANNEL(ch) ((ch >= 0) && (ch <= 3)) 126 #define OPL_VALID_CHANNEL(ch) ((ch >= 0) && (ch <= 4)) 127 #define OPL_VALID_LEAF(leaf) ((leaf == 0) || (leaf == 1)) 128 129 #if defined(_KERNEL) 130 131 /* 132 * We store the pointers to the following device nodes in this structure: 133 * "pseudo-mc" 134 * "cmp" 135 * "pci" 136 * 137 * These nodes represent the different branches we create in the device 138 * tree for each board during probe. We store them so that when a board 139 * is unprobed, we can easily locate the branches and destroy them. 140 */ 141 typedef struct { 142 dev_info_t *cfg_pseudo_mc; 143 dev_info_t *cfg_cpu_chips[HWD_CPU_CHIPS_PER_CMU]; 144 dev_info_t *cfg_cmuch_leaf; 145 fco_handle_t cfg_cmuch_handle; 146 char *cfg_cmuch_probe_str; 147 dev_info_t *cfg_pcich_leaf[HWD_PCI_CHANNELS_PER_SB] 148 [HWD_LEAVES_PER_PCI_CHANNEL]; 149 fco_handle_t cfg_pcich_handle[HWD_PCI_CHANNELS_PER_SB] 150 [HWD_LEAVES_PER_PCI_CHANNEL]; 151 char *cfg_pcich_probe_str[HWD_PCI_CHANNELS_PER_SB] 152 [HWD_LEAVES_PER_PCI_CHANNEL]; 153 void *cfg_hwd; 154 } opl_board_cfg_t; 155 156 /* 157 * Prototypes for the callback functions used in the DDI functions 158 * used to perform device tree operations. 159 * 160 * init functions are used to find device nodes that are created 161 * by Solaris during boot. 162 * 163 * create functions are used to initialize device nodes during DR. 164 */ 165 typedef int (*opl_init_func_t)(dev_info_t *, char *, int); 166 typedef int (*opl_create_func_t)(dev_info_t *, void *, uint_t); 167 168 /* 169 * The following probe structure carries all the information required 170 * at various points during probe. This structure serves two purposes: 171 * 172 * 1. It allows us to streamline functions and have them accept just 173 * a single argument. 174 * 175 * 2. It allows us to pass information to the DDI callbacks. DDI 176 * callbacks are allowed only one argument. It also allows 177 * us to return information from those callbacks. 178 * 179 * The probe structure carries a snapshot of the hardware descriptor 180 * taken at the beginning of a probe. 181 */ 182 typedef struct { 183 hwd_header_t *pr_hdr; 184 hwd_sb_status_t *pr_sb_status; 185 hwd_domain_info_t *pr_dinfo; 186 hwd_sb_t *pr_sb; 187 188 int pr_board; 189 int pr_cpu_chip; 190 int pr_core; 191 int pr_cpu; 192 int pr_channel; 193 int pr_channel_status; 194 int pr_leaf; 195 int pr_leaf_status; 196 197 opl_create_func_t pr_create; 198 dev_info_t *pr_parent; 199 dev_info_t *pr_node; 200 int pr_hold; 201 unsigned pr_cpu_impl; 202 } opl_probe_t; 203 204 #define OPL_STR_LEN 256 205 206 #define OPL_HI(value) ((uint32_t)((uint64_t)(value) >> 32)) 207 #define OPL_LO(value) ((uint32_t)(value)) 208 209 typedef struct { 210 uint32_t addr_hi; 211 uint32_t addr_lo; 212 } opl_addr_t; 213 214 typedef struct { 215 uint32_t rg_addr_hi; 216 uint32_t rg_addr_lo; 217 uint32_t rg_size_hi; 218 uint32_t rg_size_lo; 219 } opl_range_t; 220 221 typedef struct { 222 int mc_bank; 223 uint32_t mc_hi; 224 uint32_t mc_lo; 225 } opl_mc_addr_t; 226 227 /* 228 * Convenience macros for DDI property operations. The functions that 229 * DDI provides for getting and updating properties are not symmetric 230 * either in their names or in the number of arguments. These macros 231 * hide the gory details and provide a symmetric way to get and 232 * set properties. 233 */ 234 #define opl_prop_get_string(dip, name, bufp, lenp) \ 235 ddi_getlongprop(DDI_DEV_T_ANY, dip, \ 236 DDI_PROP_DONTPASS, name, (caddr_t)bufp, lenp) 237 238 #define opl_prop_get_int(dip, name, value, defvalue) \ 239 ( \ 240 *(value) = ddi_getprop(DDI_DEV_T_ANY, dip, \ 241 DDI_PROP_DONTPASS, name, defvalue), \ 242 (*(value) == defvalue) ? DDI_PROP_NOT_FOUND : DDI_PROP_SUCCESS \ 243 ) 244 245 #define opl_prop_get_int_array(dip, name, data, nelems) \ 246 ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, \ 247 DDI_PROP_DONTPASS, name, (int **)&data, (uint_t *)&nelems) 248 249 #define OPL_GET_PROP(type, dip, name, value, arg) \ 250 opl_prop_get_##type(dip, name, value, arg) 251 252 #define OPL_GET_PROP_ARRAY(type, dip, name, values, nvalues) \ 253 opl_prop_get_##type##_array(dip, name, values, nvalues) 254 255 #define OPL_FREE_PROP(data) \ 256 ddi_prop_free((void *)data) 257 258 #define OPL_UPDATE_PROP_ERR(ret, name) \ 259 if (ret != DDI_PROP_SUCCESS) { \ 260 cmn_err(CE_WARN, "%s (%d): %s update property error (%d)",\ 261 __FILE__, __LINE__, name, ret); \ 262 return (DDI_WALK_ERROR); \ 263 } 264 265 #define OPL_UPDATE_PROP(type, dip, name, value) \ 266 ret = ndi_prop_update_##type(DDI_DEV_T_NONE, dip, name, value); \ 267 OPL_UPDATE_PROP_ERR(ret, name) 268 269 270 #define OPL_UPDATE_PROP_ARRAY(type, dip, name, values, nvalues) \ 271 ret = ndi_prop_update_##type##_array(DDI_DEV_T_NONE, dip, \ 272 name, values, nvalues); \ 273 OPL_UPDATE_PROP_ERR(ret, name) 274 275 /* 276 * Node names for the different nodes supported in OPL. 277 */ 278 #define OPL_PSEUDO_MC_NODE "pseudo-mc" 279 #define OPL_CPU_CHIP_NODE "cmp" 280 #define OPL_CORE_NODE "core" 281 #define OPL_CPU_NODE "cpu" 282 #define OPL_PCI_LEAF_NODE "pci" 283 284 typedef struct { 285 char *fc_service; 286 fc_ops_t *fc_op; 287 } opl_fc_ops_t; 288 289 /* 290 * Functions used by drmach 291 */ 292 extern int opl_probe_sb(int, unsigned *); 293 extern int opl_unprobe_sb(int); 294 extern int opl_read_hwd(int, hwd_header_t **, hwd_sb_status_t **, 295 hwd_domain_info_t **, hwd_sb_t **); 296 extern void opl_hold_devtree(void); 297 extern void opl_release_devtree(void); 298 extern int oplcfg_pa_swap(int from, int to); 299 extern int opl_init_cfg(); 300 301 #endif /* _KERNEL */ 302 303 #ifdef __cplusplus 304 } 305 #endif 306 307 #endif /* _SYS_OPL_CFG_H */ 308