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