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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Sun4v Platform specific functions. 28 * 29 * called when : 30 * machine_type == huron 31 * 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <kstat.h> 38 #include <fcntl.h> 39 #include <string.h> 40 #include <assert.h> 41 #include <libintl.h> 42 #include <note.h> 43 #include <sys/systeminfo.h> 44 #include <sys/openpromio.h> 45 #include <sys/sysmacros.h> 46 #include <picl.h> 47 #include "picldefs.h" 48 #include <pdevinfo.h> 49 #include <display.h> 50 #include <display_sun4v.h> 51 #include <libprtdiag.h> 52 #include "huron.h" 53 54 #if !defined(TEXT_DOMAIN) 55 #define TEXT_DOMAIN "SYS_TEST" 56 #endif 57 58 static void 59 huron_get_bus_type(char *path, struct io_card *card) 60 { 61 if (strcmp(path, HURON_NIU) == 0) { 62 (void) strcpy(card->bus_type, "NIU"); 63 } else { 64 (void) strcpy(card->bus_type, "PCIE"); 65 } 66 } 67 68 void 69 huron_get_slot_number(char *path, struct io_card *card) 70 { 71 if (strcmp(path, HURON_N2_XAUI0) == 0) { 72 (void) strcpy(card->slot_str, "0"); 73 card->slot = 0; 74 } else if (strcmp(path, HURON_N2_XAUI1) == 0) { 75 (void) strcpy(card->slot_str, "1"); 76 card->slot = 1; 77 } else if (strncmp(path, HURON_PCIE_SLOT0, 78 strlen(HURON_PCIE_SLOT0)) == 0) { 79 (void) strcpy(card->slot_str, "0"); 80 card->slot = 0; 81 } else if (strncmp(path, HURON_PCIE_SLOT1, 82 strlen(HURON_PCIE_SLOT1)) == 0) { 83 (void) strcpy(card->slot_str, "1"); 84 card->slot = 1; 85 } else if (strncmp(path, HURON_PCIE_SLOT2, 86 strlen(HURON_PCIE_SLOT2)) == 0) { 87 (void) strcpy(card->slot_str, "2"); 88 card->slot = 2; 89 } else if (strncmp(path, HURON_PCIE_SLOT3, 90 strlen(HURON_PCIE_SLOT3)) == 0) { 91 (void) strcpy(card->slot_str, "3"); 92 card->slot = 3; 93 } else if (strncmp(path, HURON_PCIE_SLOT4, 94 strlen(HURON_PCIE_SLOT4)) == 0) { 95 (void) strcpy(card->slot_str, "4"); 96 card->slot = 4; 97 } else if (strncmp(path, HURON_PCIE_SLOT5, 98 strlen(HURON_PCIE_SLOT5)) == 0) { 99 (void) strcpy(card->slot_str, "5"); 100 card->slot = 5; 101 } else { 102 (void) strcpy(card->slot_str, MOTHERBOARD); 103 card->slot = NO_SLOT; 104 } 105 } 106 107 int 108 huron_get_network_instance(char *path) 109 { 110 if (strcmp(path, HURON_NETWORK_0) == 0) { 111 return (0); 112 } else if (strcmp(path, HURON_NETWORK_1) == 0) { 113 return (1); 114 } else if (strcmp(path, HURON_NETWORK_2) == 0) { 115 return (2); 116 } else if (strcmp(path, HURON_NETWORK_3) == 0) { 117 return (3); 118 } else if (strcmp(path, HURON_N2_XAUI0) == 0) { 119 return (0); 120 } else if (strcmp(path, HURON_N2_XAUI1) == 0) { 121 return (1); 122 } else { 123 return (-1); 124 } 125 } 126 /* 127 * add all io devices under pci in io list 128 */ 129 /* ARGSUSED */ 130 int 131 huron_pci_callback(picl_nodehdl_t pcih, void *args) 132 { 133 int err = PICL_SUCCESS; 134 picl_nodehdl_t nodeh; 135 char path[MAXSTRLEN]; 136 char parent_path[MAXSTRLEN]; 137 char piclclass[PICL_CLASSNAMELEN_MAX]; 138 char name[MAXSTRLEN]; 139 char model[MAXSTRLEN]; 140 char *compatible; 141 char binding_name[MAXSTRLEN]; 142 struct io_card pci_card; 143 int32_t instance; 144 145 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path, 146 sizeof (parent_path)); 147 if (err != PICL_SUCCESS) { 148 return (err); 149 } 150 151 /* Walk through the children */ 152 err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 153 sizeof (picl_nodehdl_t)); 154 155 while (err == PICL_SUCCESS) { 156 err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 157 piclclass, sizeof (piclclass)); 158 if (err != PICL_SUCCESS) 159 return (err); 160 161 if (strcmp(piclclass, "pciex") == 0) { 162 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, 163 &nodeh, sizeof (picl_nodehdl_t)); 164 continue; 165 } 166 167 if (strcmp(piclclass, "sun4v") == 0) { 168 err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, 169 &nodeh, sizeof (picl_nodehdl_t)); 170 continue; 171 } 172 173 err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, 174 path, sizeof (path)); 175 if (err != PICL_SUCCESS) { 176 return (err); 177 } 178 179 (void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes)); 180 181 huron_get_bus_type(parent_path, &pci_card); 182 183 err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, &name, 184 sizeof (name)); 185 if (err == PICL_PROPNOTFOUND) 186 (void) strcpy(name, ""); 187 else if (err != PICL_SUCCESS) 188 return (err); 189 190 if (strcmp(parent_path, HURON_NIU) == 0) 191 huron_get_slot_number(path, &pci_card); 192 else 193 huron_get_slot_number(parent_path, &pci_card); 194 195 /* Figure NAC name */ 196 if ((strcmp(name, NETWORK) == 0) && 197 (strcmp(pci_card.slot_str, MOTHERBOARD) == 0)) { 198 instance = huron_get_network_instance(path); 199 (void) snprintf(pci_card.status, 200 sizeof (pci_card.status), "%s/%s%d", MOTHERBOARD, 201 "NET", instance); 202 } else { 203 if (pci_card.slot != NO_SLOT) { 204 (void) snprintf(pci_card.status, 205 sizeof (pci_card.status), "%s/%s%d", 206 MOTHERBOARD, pci_card.bus_type, 207 pci_card.slot); 208 } else { 209 (void) snprintf(pci_card.status, 210 sizeof (pci_card.status), "%s/%s", 211 MOTHERBOARD, pci_card.bus_type); 212 } 213 } 214 215 /* 216 * Get the name of this card. Iif binding_name is found, 217 * name will be <nodename>-<binding_name> 218 */ 219 220 err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME, 221 &binding_name, sizeof (binding_name)); 222 if (err == PICL_PROPNOTFOUND) { 223 /* 224 * if compatible prop is found, name will be 225 * <nodename>-<compatible> 226 */ 227 err = huron_get_first_compatible_value(nodeh, 228 &compatible); 229 if (err == PICL_SUCCESS) { 230 (void) strlcat(name, "-", MAXSTRLEN); 231 (void) strlcat(name, compatible, MAXSTRLEN); 232 free(compatible); 233 } else if (err != PICL_PROPNOTFOUND) { 234 return (err); 235 } 236 } else if (err != PICL_SUCCESS) { 237 return (err); 238 } else if (strcmp(name, binding_name) != 0) { 239 (void) strlcat(name, "-", MAXSTRLEN); 240 (void) strlcat(name, binding_name, MAXSTRLEN); 241 } 242 243 (void) strlcpy(pci_card.name, name, sizeof (pci_card.name)); 244 245 /* Get the model of this card */ 246 247 err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL, 248 &model, sizeof (model)); 249 if (err == PICL_PROPNOTFOUND) 250 (void) strcpy(model, ""); 251 else if (err != PICL_SUCCESS) 252 return (err); 253 (void) strlcpy(pci_card.model, model, sizeof (pci_card.model)); 254 255 /* Print NAC name */ 256 log_printf("%-11s", pci_card.status); 257 /* Print IO Type */ 258 log_printf("%6s", pci_card.bus_type); 259 /* Print Slot # */ 260 log_printf("%5s", pci_card.slot_str); 261 /* Print Parent Path */ 262 log_printf("%46.45s", pci_card.notes); 263 /* Printf Card Name */ 264 if (strlen(pci_card.name) > 24) 265 log_printf("%25.24s+", pci_card.name); 266 else 267 log_printf("%26s", pci_card.name); 268 /* Print Card Model */ 269 if (strlen(pci_card.model) > 10) 270 log_printf("%10.9s+", pci_card.model); 271 else 272 log_printf("%10s", pci_card.model); 273 log_printf("\n"); 274 275 err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 276 sizeof (picl_nodehdl_t)); 277 278 } 279 280 return (PICL_WALK_CONTINUE); 281 } 282 283 /* 284 * local functions 285 */ 286 /* 287 * add all io devices under pci in io list 288 */ 289 /* ARGSUSED */ 290 int 291 huron_hw_rev_callback(picl_nodehdl_t pcih, void *args) 292 { 293 int err = PICL_SUCCESS; 294 char path[MAXSTRLEN] = ""; 295 char device_path[MAXSTRLEN]; 296 char NAC[MAXSTRLEN]; 297 char *compatible; 298 int32_t revision; 299 int device_found = 0; 300 301 err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, path, 302 sizeof (path)); 303 if (err != PICL_SUCCESS) { 304 return (err); 305 } 306 307 if ((strcmp(path, HURON_NETWORK_0) == 0) || 308 (strcmp(path, HURON_NETWORK_1) == 0)) { 309 device_found = 1; 310 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", 311 MOTHERBOARD, OPHIR, 0); 312 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 313 &err); 314 } 315 316 if ((strcmp(path, HURON_NETWORK_2) == 0) || 317 (strcmp(path, HURON_NETWORK_3) == 0)) { 318 device_found = 1; 319 (void) snprintf(NAC, sizeof (NAC), "%s/%s%d", MOTHERBOARD, 320 OPHIR, 1); 321 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 322 &err); 323 } 324 325 if (strcmp(path, HURON_SWITCH_A_PATH) == 0) { 326 device_found = 1; 327 (void) snprintf(NAC, sizeof (NAC), "%s/%s", 328 MOTHERBOARD, HURON_SWITCH_A); 329 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 330 &err); 331 } 332 333 if (strcmp(path, HURON_SWITCH_B_PATH) == 0) { 334 device_found = 1; 335 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD, 336 HURON_SWITCH_B); 337 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 338 &err); 339 } 340 341 if (strcmp(path, HURON_SWITCH_C_PATH) == 0) { 342 device_found = 1; 343 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD, 344 HURON_SWITCH_C); 345 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 346 &err); 347 } 348 349 if (strcmp(path, HURON_LSI_PATH) == 0) { 350 device_found = 1; 351 (void) snprintf(NAC, sizeof (NAC), "%s/%s", MOTHERBOARD, 352 SAS_SATA_HBA); 353 revision = huron_get_int_propval(pcih, OBP_PROP_REVISION_ID, 354 &err); 355 } 356 if (device_found == 1) { 357 (void) strcpy(device_path, path); 358 err = huron_get_first_compatible_value(pcih, &compatible); 359 360 /* Print NAC name */ 361 log_printf("%-20s", NAC); 362 /* Print Device Path */ 363 if (strlen(device_path) > 45) 364 log_printf("%45.44s+", device_path); 365 else 366 log_printf("%46s", device_path); 367 /* Print Compatible # */ 368 if (err == PICL_SUCCESS) { 369 log_printf("%31s", compatible); 370 free(compatible); 371 } else 372 log_printf("%31s", " "); 373 /* Print Revision */ 374 log_printf("%6d", revision); 375 log_printf("\n"); 376 } 377 378 return (PICL_WALK_CONTINUE); 379 } 380 381 /* 382 * return the first compatible value 383 */ 384 int 385 huron_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf) 386 { 387 int err; 388 picl_prophdl_t proph; 389 picl_propinfo_t pinfo; 390 picl_prophdl_t tblh; 391 picl_prophdl_t rowproph; 392 char *pval; 393 394 err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE, 395 &pinfo, &proph); 396 if (err != PICL_SUCCESS) 397 return (err); 398 399 if (pinfo.type == PICL_PTYPE_CHARSTRING) { 400 pval = malloc(pinfo.size); 401 if (pval == NULL) 402 return (PICL_FAILURE); 403 err = picl_get_propval(proph, pval, pinfo.size); 404 if (err != PICL_SUCCESS) { 405 free(pval); 406 return (err); 407 } 408 *outbuf = pval; 409 return (PICL_SUCCESS); 410 } 411 412 if (pinfo.type != PICL_PTYPE_TABLE) 413 return (PICL_FAILURE); 414 415 /* get first string from table */ 416 err = picl_get_propval(proph, &tblh, pinfo.size); 417 if (err != PICL_SUCCESS) 418 return (err); 419 420 err = picl_get_next_by_row(tblh, &rowproph); 421 if (err != PICL_SUCCESS) 422 return (err); 423 424 err = picl_get_propinfo(rowproph, &pinfo); 425 if (err != PICL_SUCCESS) 426 return (err); 427 428 pval = malloc(pinfo.size); 429 if (pval == NULL) 430 return (PICL_FAILURE); 431 432 err = picl_get_propval(rowproph, pval, pinfo.size); 433 if (err != PICL_SUCCESS) { 434 free(pval); 435 return (err); 436 } 437 438 *outbuf = pval; 439 return (PICL_SUCCESS); 440 } 441 442 int64_t 443 huron_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret) 444 { 445 int err; 446 picl_prophdl_t proph; 447 picl_propinfo_t pinfo; 448 int8_t int8v; 449 int16_t int16v; 450 int32_t int32v; 451 int64_t int64v; 452 453 err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); 454 if (err != PICL_SUCCESS) { 455 *ret = err; 456 return (0); 457 } 458 459 /* 460 * If it is not an int, uint or byte array prop, return failure 461 */ 462 if ((pinfo.type != PICL_PTYPE_INT) && 463 (pinfo.type != PICL_PTYPE_UNSIGNED_INT) && 464 (pinfo.type != PICL_PTYPE_BYTEARRAY)) { 465 *ret = PICL_FAILURE; 466 return (0); 467 } 468 469 switch (pinfo.size) { 470 case sizeof (int8_t): 471 err = picl_get_propval(proph, &int8v, sizeof (int8v)); 472 *ret = err; 473 return (int8v); 474 case sizeof (int16_t): 475 err = picl_get_propval(proph, &int16v, sizeof (int16v)); 476 *ret = err; 477 return (int16v); 478 case sizeof (int32_t): 479 err = picl_get_propval(proph, &int32v, sizeof (int32v)); 480 *ret = err; 481 return (int32v); 482 case sizeof (int64_t): 483 err = picl_get_propval(proph, &int64v, sizeof (int64v)); 484 *ret = err; 485 return (int64v); 486 default: /* not supported size */ 487 *ret = PICL_FAILURE; 488 return (0); 489 } 490 } 491