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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This plugin creates memory configuration nodes and properties in the 31 * PICL tree for Grover/Grover+ platform. 32 * 33 * Subtree of memory-controller in the physical aspect. 34 * memory-controller --- memory-module 35 * However, there is no memory controller node on Grover. Thus we need to 36 * create it under platform. 37 * 38 * Subtree of memory in the logical aspect. 39 * memory --- memory-segment 40 * Add property _memory-module_ at memory-segment referring to the 41 * memory-module since memory-segment equals to memory-module on Grover. 42 * 43 * Undo strategy: 44 * Create all nodes and properties, or none if it fails in physical and 45 * logical memory tree respectively. It keeps on creating logical 46 * memory tree although it falis on physical logical tree, but no link to 47 * memory module. 48 * 49 * NOTE: 50 * It depends on PICL devtree plugin. 51 */ 52 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <unistd.h> 56 #include <alloca.h> 57 #include <syslog.h> 58 #include <string.h> 59 #include <libintl.h> 60 #include <picl.h> 61 #include <picltree.h> 62 #include <sys/types.h> 63 #include <sys/obpdefs.h> 64 #include "piclmemcfg.h" 65 #include "memcfg_impl.h" 66 67 static void piclmemcfg_register(void); 68 static void piclmemcfg_init(void); 69 static void piclmemcfg_fini(void); 70 71 #pragma init(piclmemcfg_register) 72 73 static picld_plugin_reg_t my_reg_info = { 74 PICLD_PLUGIN_VERSION_1, 75 PICLD_PLUGIN_NON_CRITICAL, 76 "SUNW_piclmemcfg", 77 piclmemcfg_init, 78 piclmemcfg_fini 79 }; 80 81 /* 82 * Create logical memory tree 83 * memory --- memory-segment 84 */ 85 static int 86 create_logical_tree(picl_nodehdl_t memh, mmodinfo_t *mmodinfo) 87 { 88 picl_nodehdl_t msegh; 89 picl_nodehdl_t *memsegh; 90 ptree_propinfo_t propinfo; 91 uint32_t ifactor = INTERLEAVEFACTOR; 92 int i; 93 int err = PICL_SUCCESS; 94 95 if ((memsegh = alloca(sizeof (picl_nodehdl_t) * TOTAL_MEM_SLOTS)) == 96 NULL) 97 return (PICL_FAILURE); 98 99 for (i = 0; i < TOTAL_MEM_SLOTS; i++) { 100 /* 101 * It means no segment for the slot if size is zero 102 */ 103 if (mmodinfo[i].size == 0) { 104 memsegh[i] = NULL; 105 continue; 106 } 107 108 /* 109 * Create memory-segment node under memory 110 */ 111 err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT, 112 PICL_CLASS_MEMORY_SEGMENT, &msegh); 113 if (err != PICL_SUCCESS) 114 break; 115 116 /* 117 * For undo easily later 118 */ 119 memsegh[i] = msegh; 120 121 /* 122 * Add property, Size to memory-segment node 123 */ 124 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 125 PICL_PTYPE_UNSIGNED_INT, PICL_READ, 126 sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL); 127 if (err != PICL_SUCCESS) 128 break; 129 130 err = ptree_create_and_add_prop(msegh, &propinfo, 131 &mmodinfo[i].size, NULL); 132 if (err != PICL_SUCCESS) 133 break; 134 135 /* 136 * Add property, BaseAddress to memory-segment node 137 */ 138 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 139 PICL_PTYPE_UNSIGNED_INT, PICL_READ, 140 sizeof (mmodinfo[i].base), PICL_PROP_BASEADDRESS, NULL, 141 NULL); 142 if (err != PICL_SUCCESS) 143 break; 144 145 err = ptree_create_and_add_prop(msegh, &propinfo, 146 &mmodinfo[i].base, NULL); 147 if (err != PICL_SUCCESS) 148 break; 149 150 /* 151 * Add property, InterleaveFactor to memory-segment node 152 */ 153 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 154 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (ifactor), 155 PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL); 156 if (err != PICL_SUCCESS) 157 break; 158 159 err = ptree_create_and_add_prop(msegh, &propinfo, &ifactor, 160 NULL); 161 if (err != PICL_SUCCESS) 162 break; 163 164 /* 165 * Add reference property to the memory module if memory 166 * module node handle is not NULL. 167 */ 168 if (mmodinfo[i].memmodh == NULL) 169 continue; 170 171 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 172 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t), 173 PICL_REFPROP_MEMORY_MODULE, NULL, NULL); 174 if (err != PICL_SUCCESS) 175 break; 176 177 err = ptree_create_and_add_prop(msegh, &propinfo, 178 &mmodinfo[i].memmodh, NULL); 179 if (err != PICL_SUCCESS) 180 break; 181 } 182 183 if (err != PICL_SUCCESS) { 184 /* 185 * Undo in the logical memory tree 186 */ 187 for (i = 0; i < TOTAL_MEM_SLOTS; i++) { 188 if (memsegh[i] == NULL) 189 continue; 190 191 (void) ptree_delete_node(memsegh[i]); 192 (void) ptree_destroy_node(memsegh[i]); 193 } 194 } 195 196 return (err); 197 } 198 199 /* 200 * Create physical memory tree 201 * memory-controller --- memory-module 202 */ 203 static int 204 create_physical_tree(picl_nodehdl_t plfh, mmodinfo_t *mmodinfo) 205 { 206 picl_nodehdl_t mch, memmodh; 207 ptree_propinfo_t propinfo; 208 int i; 209 int err = PICL_SUCCESS; 210 uint32_t id; 211 212 /* 213 * Create memory-controller node under platform 214 */ 215 err = ptree_create_and_add_node(plfh, PICL_NAME_MEMORY_CONTROLLER, 216 PICL_CLASS_MEMORY_CONTROLLER, &mch); 217 if (err != PICL_SUCCESS) 218 return (err); 219 220 /* 221 * Create memory-module nodes and properties 222 * Get all memory modules with dimm 223 */ 224 for (i = 0; i < TOTAL_MEM_SLOTS; i++) { 225 /* 226 * It means no dimm on the slot if size is zero 227 */ 228 if (mmodinfo[i].size == 0) 229 continue; 230 231 /* Create memory-module node under memory-controller */ 232 err = ptree_create_and_add_node(mch, PICL_NAME_MEMORY_MODULE, 233 PICL_CLASS_MEMORY_MODULE, &memmodh); 234 if (err != PICL_SUCCESS) 235 break; 236 237 /* 238 * Update memory module node handle at mmodinfo 239 */ 240 mmodinfo[i].memmodh = memmodh; 241 242 /* 243 * Add property, Size to memory-module node 244 */ 245 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 246 PICL_PTYPE_UNSIGNED_INT, PICL_READ, 247 sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL); 248 if (err != PICL_SUCCESS) 249 break; 250 251 err = ptree_create_and_add_prop(memmodh, &propinfo, 252 &mmodinfo[i].size, NULL); 253 if (err != PICL_SUCCESS) 254 break; 255 256 /* 257 * Add property, ID to memory-module node 258 */ 259 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 260 PICL_PTYPE_INT, PICL_READ, sizeof (id), PICL_PROP_ID, 261 NULL, NULL); 262 if (err != PICL_SUCCESS) 263 break; 264 265 id = i; 266 err = ptree_create_and_add_prop(memmodh, &propinfo, &id, NULL); 267 if (err != PICL_SUCCESS) 268 break; 269 } 270 271 if (err != PICL_SUCCESS) { 272 /* 273 * Clear out the saved memory module node handle so that 274 * logical memory tree won't link to memory module. 275 */ 276 for (i = 0; i < TOTAL_MEM_SLOTS; i++) 277 mmodinfo[i].memmodh = NULL; 278 279 /* 280 * Undo in the physical memory tree 281 */ 282 (void) ptree_delete_node(mch); 283 (void) ptree_destroy_node(mch); 284 } 285 286 return (err); 287 } 288 289 /* 290 * Get the memory module and memory segment information from 291 * property reg of memory node. 292 * 293 * mmodinfo will be updated. Also, the pointers to mseginfo and 294 * the number of segments will be passed to the caller. 295 */ 296 static int 297 get_reg_info(picl_nodehdl_t plfh, picl_nodehdl_t memh, 298 mmodinfo_t *mmodinfo) 299 { 300 picl_prophdl_t proph; 301 ptree_propinfo_t pinfo; 302 regspec_t *memspec; 303 int i, err; 304 int pval; 305 int nregspec; 306 307 308 /* 309 * Check if the #size-cells of the platform node is 2 310 */ 311 err = ptree_get_propval_by_name(plfh, OBP_PROP_SIZE_CELLS, &pval, 312 sizeof (pval)); 313 314 if (err == PICL_PROPNOTFOUND) 315 pval = SUPPORTED_NUM_CELL_SIZE; 316 else if (err != PICL_SUCCESS) 317 return (err); 318 319 /* 320 * don't know to handle other vals 321 */ 322 if (pval != SUPPORTED_NUM_CELL_SIZE) 323 return (PICL_FAILURE); 324 325 /* 326 * Get property reg of memory node 327 */ 328 err = ptree_get_prop_by_name(memh, OBP_REG, &proph); 329 if (err != PICL_SUCCESS) 330 return (err); 331 332 err = ptree_get_propinfo(proph, &pinfo); 333 if (err != PICL_SUCCESS) 334 return (err); 335 336 if ((memspec = alloca(pinfo.piclinfo.size)) == NULL) 337 return (PICL_FAILURE); 338 339 nregspec = pinfo.piclinfo.size / sizeof (*memspec); 340 341 if ((nregspec == 0) || (nregspec > TOTAL_MEM_SLOTS)) 342 return (PICL_FAILURE); 343 344 err = ptree_get_propval(proph, memspec, pinfo.piclinfo.size); 345 if (err != PICL_SUCCESS) 346 return (err); 347 348 349 for (i = 0; i < nregspec; i++) { 350 351 mmodinfo[i].base = memspec[i].physaddr; 352 mmodinfo[i].size = memspec[i].size; 353 354 } 355 356 return (PICL_SUCCESS); 357 } 358 359 /* 360 * executed as part of .init when the plugin is dlopen()ed 361 */ 362 static void 363 piclmemcfg_register(void) 364 { 365 (void) picld_plugin_register(&my_reg_info); 366 } 367 368 /* 369 * Init entry point of the plugin 370 * Creates the PICL nodes and properties in the physical and logical aspects. 371 */ 372 static void 373 piclmemcfg_init(void) 374 { 375 picl_nodehdl_t plfh, memh; 376 mmodinfo_t mmodinfo[TOTAL_MEM_SLOTS]; 377 378 /* 379 * Get platform node 380 */ 381 if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) { 382 syslog(LOG_ERR, EM_INIT_FAILED); 383 return; 384 } 385 386 /* 387 * Find the memory node 388 */ 389 if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) { 390 syslog(LOG_ERR, EM_INIT_FAILED); 391 return; 392 } 393 394 /* 395 * Initialize the mmodinfo and get segment information from reg 396 */ 397 (void) memset(mmodinfo, 0, sizeof (mmodinfo)); 398 399 if ((get_reg_info(plfh, memh, mmodinfo)) != PICL_SUCCESS) { 400 syslog(LOG_ERR, EM_INIT_FAILED); 401 return; 402 } 403 404 /* 405 * Create subtree of memory-controller in the physical aspect. 406 * memory-controller --- memory-module 407 */ 408 if ((create_physical_tree(plfh, mmodinfo)) != PICL_SUCCESS) 409 syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED); 410 411 /* 412 * Create subtree of memory in the logical aspect. 413 * memory --- memory-segment 414 */ 415 if ((create_logical_tree(memh, mmodinfo)) != PICL_SUCCESS) 416 syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED); 417 } 418 419 /* 420 * fini entry point of the plugin 421 */ 422 static void 423 piclmemcfg_fini(void) 424 { 425 } 426