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 2000, 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Daktari Platform specific functions. 27 */ 28 29 #include <libdevinfo.h> 30 #include <alloca.h> 31 #include <inttypes.h> 32 #include <libprtdiag.h> 33 #include <sys/mc.h> 34 35 #define EXIT_MSG(msg, err) \ 36 { printf("\n%s failed with %d\n", msg, err); exit(err); } 37 38 /* we only need the 5 LSB of the portid to calculate the board number */ 39 #define DAK_SAFARI_ID_MASK 0x1F /* 5 bits */ 40 #define DAK_NODE_MASK 0x1F /* 5 bits */ 41 #define DAK_PORTID_NODE_SHIFT 5 42 #define DAK_MIN_CPU_SAFARI_ID 0 /* 0x00 */ 43 #define DAK_MAX_CPU_SAFARI_ID 23 /* 0x17 */ 44 #define DAK_MIN_IO_SAFARI_ID 24 /* 0x18 */ 45 #define DAK_MAX_IO_SAFARI_ID 31 /* 0x1F */ 46 #define NUM_MBANKS_PER_MC 4 47 48 #define DAK_CLK_FREQ_TO_MHZ(x) (((x) + 500000) / 1000000) 49 50 /* 51 * DAK_PORTID_IS_CPU_TYPE 52 * 53 * If the portid associated with a CPU board is passed in, TRUE is returned, 54 * otherwise FALSE. 55 */ 56 #define DAK_PORTID_IS_CPU_TYPE(portid) \ 57 (((((portid) & DAK_SAFARI_ID_MASK) >= DAK_MIN_CPU_SAFARI_ID) && \ 58 (((portid) & DAK_SAFARI_ID_MASK) <= DAK_MAX_CPU_SAFARI_ID)) ? \ 59 TRUE: FALSE) 60 /* 61 * DAK_CPU_BD_PORTID_TO_BD_NUM 62 * 63 * If the portid associated with a CPU board is passed in, the board number 64 * associated with this portid is returned, otherwise -1. 65 */ 66 #define DAK_CPU_BD_PORTID_TO_BD_NUM(portid) \ 67 ((DAK_PORTID_IS_CPU_TYPE(portid)) ? \ 68 (((portid) & DAK_SAFARI_ID_MASK) / 4) : (-1)) 69 70 /* 71 * DAK_PORTID_IS_IO_TYPE 72 * 73 * If the portid associated with an IO board is passed in, TRUE is returned, 74 * otherwise FALSE. 75 */ 76 #define DAK_PORTID_IS_IO_TYPE(portid) \ 77 (((((portid) & DAK_SAFARI_ID_MASK) >= DAK_MIN_IO_SAFARI_ID) && \ 78 (((portid) & DAK_SAFARI_ID_MASK) <= DAK_MAX_IO_SAFARI_ID)) ? \ 79 TRUE: FALSE) 80 81 /* 82 * DAK_IO_BD_PORTID_TO_BD_NUM 83 * 84 * If the portid associated with an IO board is passed in, the board number 85 * associated with this portid is returned, otherwise -1. 86 */ 87 #define DAK_IO_BD_PORTID_TO_BD_NUM(portid) \ 88 (DAK_PORTID_IS_IO_TYPE(portid) ? \ 89 (((((portid) & DAK_SAFARI_ID_MASK) - 24) / 2) + 6) : (-1)) 90 91 /* 92 * DAK_PORTID_TO_BOARD_NUM 93 * 94 * If a valid portid is passed in, this macro returns the board number 95 * associated with it, otherwise it returns -1. 96 */ 97 98 #define DAK_PORTID_TO_BOARD_NUM(portid) \ 99 ((DAK_PORTID_IS_CPU_TYPE(portid)) ? \ 100 (DAK_CPU_BD_PORTID_TO_BD_NUM(portid)) : \ 101 ((DAK_PORTID_IS_IO_TYPE(portid)) ? \ 102 DAK_IO_BD_PORTID_TO_BD_NUM(portid) : (-1))) 103 104 105 /* Local Functions */ 106 char *get_node_name(Prom_node *pnode); 107 char *get_node_type(Prom_node *pnode); 108 void add_node(Sys_tree *root, Prom_node *pnode); 109 Prop *find_prop(Prom_node *pnode, char *name); 110 int do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag); 111 void *get_prop_val(Prop *prop); 112 char *get_node_type(Prom_node *pnode); 113 int get_us3_mem_regs(Board_node *bnode); 114 115 void fill_pci_card_list(Prom_node *pci_instance, 116 Prom_node *pci_card_node, 117 struct io_card *pci_card, 118 struct io_card **pci_card_list, 119 char **pci_slot_name_arr); 120 121 static Prom_node *next_pci_card(Prom_node *curr_card, int *is_bridge, 122 int is_pcidev, Prom_node *curr_bridge, 123 Prom_node * parent_bridge, Prom_node *pci); 124 125 static Prom_node *dev_next_node_by_compat(Prom_node *root, char *compat); 126 static Prom_node *dev_find_node_by_compat(Prom_node *root, char *compat); 127 static Board_node *daktari_insert_board(Sys_tree *root, int board); 128 static Board_node *daktari_find_board(Sys_tree *root, int board); 129 130 static int32_t find_child_device(picl_nodehdl_t, char *, picl_nodehdl_t *); 131 static int32_t fill_device_from_id(picl_nodehdl_t, char *, picl_nodehdl_t *); 132 static int32_t fill_device_array_from_id(picl_nodehdl_t, char *, int32_t *, 133 picl_nodehdl_t **); 134 135 /* Overlaying routines */ 136 137 /* 138 * This function searches through the properties of the node passed in 139 * and returns a pointer to the value of the name property. 140 */ 141 char * 142 get_node_name(Prom_node *pnode) 143 { 144 Prop *prop; 145 146 if (pnode == NULL) 147 return (NULL); 148 149 prop = pnode->props; 150 while (prop != NULL) { 151 if (strcmp("name", (char *)prop->name.val_ptr) == 0) 152 return (prop->value.val_ptr); 153 prop = prop->next; 154 } 155 return (NULL); 156 } 157 158 /* 159 * This function searches through the properties of the node passed in 160 * and returns a pointer to the value of the name property. 161 */ 162 char * 163 get_node_type(Prom_node *pnode) 164 { 165 Prop *prop; 166 167 if (pnode == NULL) { 168 return (NULL); 169 } 170 171 prop = pnode->props; 172 while (prop != NULL) { 173 if (strcmp("device_type", (char *)prop->name.val_ptr) == 0) 174 return (prop->value.val_ptr); 175 prop = prop->next; 176 } 177 return (NULL); 178 } 179 180 /* 181 * add_node 182 * 183 * This function adds a board node to the board structure where that 184 * that node's physical component lives. 185 */ 186 void 187 add_node(Sys_tree *root, Prom_node *pnode) 188 { 189 int board = -1; 190 int portid = -1; 191 192 void *value = NULL; 193 Board_node *bnode = NULL; 194 Prom_node *p = NULL; 195 196 /* Get the board number of this board from the portid prop */ 197 value = get_prop_val(find_prop(pnode, "portid")); 198 if (value != NULL) { 199 portid = *(int *)value; 200 } 201 board = DAK_PORTID_TO_BOARD_NUM(portid); 202 /* board = DAK_GETSLOT(portid); */ 203 /* find the board node with the same board number */ 204 if ((bnode = daktari_find_board(root, board)) == NULL) { 205 bnode = daktari_insert_board(root, board); 206 } 207 208 /* now attach this prom node to the board list */ 209 /* Insert this node at the end of the list */ 210 pnode->sibling = NULL; 211 if (bnode->nodes == NULL) 212 bnode->nodes = pnode; 213 else { 214 p = bnode->nodes; 215 while (p->sibling != NULL) 216 p = p->sibling; 217 p->sibling = pnode; 218 } 219 } 220 221 /* 222 * Search a Prom node and retrieve the property with the correct 223 * name. 224 */ 225 Prop * 226 find_prop(Prom_node *pnode, char *name) 227 { 228 Prop *prop; 229 230 if (pnode == NULL) 231 return (NULL); 232 233 if (pnode->props == NULL) 234 return (NULL); 235 236 prop = pnode->props; 237 238 if (prop == NULL) 239 return (NULL); 240 241 if (prop->name.val_ptr == NULL) 242 return (NULL); 243 244 while ((prop != NULL) && (strcmp((char *)(prop->name.val_ptr), name))) { 245 prop = prop->next; 246 } 247 return (prop); 248 } 249 250 int 251 do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag) 252 { 253 return (do_devinfo(syserrlog, pgname, log_flag, prt_flag)); 254 } 255 256 257 /* 258 * return the property value for the Prop 259 * passed in. 260 */ 261 void * 262 get_prop_val(Prop *prop) 263 { 264 if (prop == NULL) 265 return (NULL); 266 267 return ((void *)(prop->value.val_ptr)); 268 } 269 270 /* Local Routines */ 271 272 /* 273 * Start from the current node and return the next node besides 274 * the current one which has the requested model property. 275 */ 276 static Prom_node * 277 dev_next_node_by_compat(Prom_node *root, char *compat) 278 { 279 Prom_node *node; 280 281 if (root == NULL) 282 return (NULL); 283 284 /* look at your children first */ 285 if ((node = dev_find_node_by_compat(root->child, compat)) != NULL) 286 return (node); 287 288 /* now look at your siblings */ 289 if ((node = dev_find_node_by_compat(root->sibling, compat)) != NULL) 290 return (node); 291 292 return (NULL); /* not found */ 293 } 294 295 /* 296 * Do a depth-first walk of a device tree and 297 * return the first node with the matching model. 298 */ 299 static Prom_node * 300 dev_find_node_by_compat(Prom_node *root, char *compat) 301 { 302 Prom_node *node; 303 char *compatible; 304 char *name; 305 306 if (root == NULL) 307 return (NULL); 308 309 if (compat == NULL) 310 return (NULL); 311 312 name = get_node_name(root); 313 if (name == NULL) 314 name = ""; 315 316 compatible = (char *)get_prop_val(find_prop(root, "compatible")); 317 318 if (compatible == NULL) 319 return (NULL); 320 321 if ((strcmp(name, "pci") == 0) && (compatible != NULL) && 322 (strcmp(compatible, compat) == 0)) { 323 return (root); /* found a match */ 324 } 325 326 /* look at your children first */ 327 if ((node = dev_find_node_by_compat(root->child, compat)) != NULL) 328 return (node); 329 330 /* now look at your siblings */ 331 if ((node = dev_find_node_by_compat(root->sibling, compat)) != NULL) 332 return (node); 333 334 return (NULL); /* not found */ 335 } 336 337 338 /* 339 * Add a board to the system list in order (sorted by board#). 340 * Initialize all pointer fields to NULL. 341 */ 342 static Board_node * 343 daktari_insert_board(Sys_tree *root, int board) 344 { 345 Board_node *bnode; 346 Board_node *temp = root->bd_list; 347 348 if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) { 349 perror("malloc"); 350 exit(1); 351 } 352 353 bnode->nodes = NULL; 354 bnode->next = NULL; 355 bnode->board_num = board; 356 bnode->board_type = UNKNOWN_BOARD; 357 358 if (temp == NULL) 359 root->bd_list = bnode; 360 361 else if (temp->board_num > board) { 362 bnode->next = temp; 363 root->bd_list = bnode; 364 365 } else { 366 while ((temp->next != NULL) && (board > temp->next->board_num)) 367 temp = temp->next; 368 369 bnode->next = temp->next; 370 temp->next = bnode; 371 } 372 root->board_cnt++; 373 374 return (bnode); 375 } 376 377 /* 378 * Find the requested board struct in the system device tree. 379 * 380 * This function overrides the functionality of the generic find_board() 381 * function in libprtdiag, but since we need to pass another parameter, 382 * we cannot simply overlay the symbol table. 383 */ 384 static Board_node * 385 daktari_find_board(Sys_tree *root, int board) 386 { 387 Board_node *bnode = root->bd_list; 388 389 while ((bnode != NULL) && (board != bnode->board_num)) { 390 bnode = bnode->next; 391 } 392 return (bnode); 393 } 394 395 396 int32_t 397 find_child_device(picl_nodehdl_t parent, char *child_name, 398 picl_nodehdl_t *child) 399 { 400 int32_t err; 401 char name[PICL_PROPNAMELEN_MAX]; 402 403 err = picl_get_propval_by_name(parent, PICL_PROP_CHILD, &(*child), 404 sizeof (picl_nodehdl_t)); 405 switch (err) { 406 case PICL_SUCCESS: 407 break; 408 case PICL_PROPNOTFOUND: 409 err = PICL_INVALIDHANDLE; 410 return (err); 411 default: 412 #ifdef WORKFILE_DEBUG 413 log_printf(dgettext(TEXT_DOMAIN, 414 "Failed picl_get_propval_by_name with %s\n"), 415 picl_strerror(err)); 416 #endif 417 return (err); 418 } 419 420 err = picl_get_propval_by_name(*child, PICL_PROP_NAME, name, 421 PICL_PROPNAMELEN_MAX); 422 423 #ifdef WORKFILE_DEBUG 424 if (err != PICL_SUCCESS) { 425 log_printf(dgettext(TEXT_DOMAIN, 426 "failed the get name for root\n"), 0); 427 log_printf(dgettext(TEXT_DOMAIN, "%s\n"), 428 picl_strerror(err), 0); 429 } 430 #endif 431 432 if (strcmp(name, child_name) == 0) 433 return (err); 434 435 while (err != PICL_PROPNOTFOUND) { 436 err = picl_get_propval_by_name(*child, PICL_PROP_PEER, 437 &(*child), sizeof (picl_nodehdl_t)); 438 switch (err) { 439 case PICL_SUCCESS: 440 err = picl_get_propval_by_name(*child, PICL_PROP_NAME, 441 name, PICL_PROPNAMELEN_MAX); 442 if (strcmp(name, child_name) == 0) 443 return (err); 444 break; 445 case PICL_PROPNOTFOUND: 446 break; 447 default: 448 #ifdef WORKFILE_DEBUG 449 log_printf(dgettext(TEXT_DOMAIN, 450 "Failed picl_get_propval_by_name with %s\n"), 451 picl_strerror(err), 0); 452 #endif 453 return (err); 454 } 455 } 456 err = PICL_INVALIDHANDLE; 457 return (err); 458 } 459 460 int32_t 461 fill_device_from_id(picl_nodehdl_t device_id, char *assoc_id, 462 picl_nodehdl_t *device) 463 { 464 int32_t err; 465 picl_prophdl_t tbl_hdl; 466 picl_prophdl_t reference_property; 467 468 err = picl_get_propval_by_name(device_id, assoc_id, &tbl_hdl, 469 sizeof (picl_prophdl_t)); 470 if (err != PICL_SUCCESS) { 471 #ifdef WORKFILE_DEBUG 472 if (err != PICL_INVALIDHANDLE) { 473 log_printf(dgettext(TEXT_DOMAIN, 474 "fill_device_from_id failure in " 475 "picl_get_propval_by_name err is %s\n"), 476 picl_strerror(err), 0); 477 } 478 #endif 479 return (err); 480 } 481 482 err = picl_get_next_by_row(tbl_hdl, &reference_property); 483 if (err != PICL_SUCCESS) { 484 #ifdef WORKFILE_DEBUG 485 log_printf(dgettext(TEXT_DOMAIN, 486 "fill_device_from_id failure in picl_get_next_by_row" 487 " err is %s\n"), picl_strerror(err), 0); 488 #endif 489 return (err); 490 } 491 492 /* get node associated with reference property */ 493 err = picl_get_propval(reference_property, &(*device), 494 sizeof (picl_nodehdl_t)); 495 496 #ifdef WORKFILE_DEBUG 497 if (err != 0) { 498 log_printf(dgettext(TEXT_DOMAIN, 499 "fill_device_from_id failure in picl_get_propval" 500 " err is %s\n"), picl_strerror(err), 0); 501 } 502 #endif 503 return (err); 504 } 505 506 int32_t 507 fill_device_array_from_id(picl_nodehdl_t device_id, char *assoc_id, 508 int32_t *number_of_devices, picl_nodehdl_t *device_array[]) 509 { 510 int32_t err; 511 int i; 512 picl_prophdl_t tbl_hdl; 513 picl_prophdl_t entry; 514 int devs = 0; 515 err = picl_get_propval_by_name(device_id, assoc_id, &tbl_hdl, 516 sizeof (picl_prophdl_t)); 517 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) { 518 #ifdef WORKFILE_DEBUG 519 log_printf(dgettext(TEXT_DOMAIN, 520 "fill_device_array_from_id failure in " 521 "picl_get_propval_by_name err is %s\n"), 522 picl_strerror(err), 0); 523 #endif 524 return (err); 525 } 526 527 entry = tbl_hdl; 528 while (picl_get_next_by_row(entry, &entry) == 0) 529 ++devs; 530 531 *device_array = calloc((devs), sizeof (picl_nodehdl_t)); 532 if (*device_array == NULL) { 533 #ifdef WORKFILE_DEBUG 534 log_printf(dgettext(TEXT_DOMAIN, 535 "fill_device_array_from_id failure getting memory" 536 " for array\n"), 0); 537 #endif 538 return (PICL_FAILURE); 539 } 540 541 entry = tbl_hdl; 542 for (i = 0; i < (devs); i++) { 543 err = picl_get_next_by_row(entry, &entry); 544 if (err != 0) { 545 #ifdef WORKFILE_DEBUG 546 log_printf(dgettext(TEXT_DOMAIN, 547 "fill_device_array_from_id failure in " 548 "picl_get_next_by_row err is %s\n"), 549 picl_strerror(err), 0); 550 #endif 551 return (err); 552 } 553 554 /* get node associated with reference property */ 555 err = picl_get_propval(entry, &((*device_array)[i]), 556 sizeof (picl_nodehdl_t)); 557 if (err != 0) { 558 #ifdef WORKFILE_DEBUG 559 log_printf(dgettext(TEXT_DOMAIN, 560 "fill_device_array_from_id failure in " 561 "picl_get_propval err is %s\n"), 562 picl_strerror(err), 0); 563 #endif 564 return (err); 565 } 566 } 567 *number_of_devices = devs; 568 return (err); 569 } 570 571 /* 572 * This function provides formatting of the memory config 573 * information that get_us3_mem_regs() and display_us3_banks() code has 574 * gathered. It overrides the generic print_us3_memory_line() code 575 * which prints an error message. 576 */ 577 void 578 print_us3_memory_line(int portid, int bank_id, uint64_t bank_size, 579 char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id) 580 { 581 int mcid; 582 mcid = portid; 583 584 log_printf(dgettext(TEXT_DOMAIN, 585 "\n %-1c %2d %2d %4lldMB %11-s %4lldMB " 586 " %2d-way %d"), 587 'A' + DAK_GETSLOT(portid), mcid, (bank_id % 4), 588 bank_size, bank_status, dimm_size, intlv, seg_id, 0); 589 } 590 591 592 /* 593 * Fills in the i/o card list to be displayed later in display_pci(); 594 */ 595 void 596 fill_pci_card_list(Prom_node * pci_instance, Prom_node * pci_card_node, 597 struct io_card *pci_card, 598 struct io_card **pci_card_list, char **slot_name_arr) 599 { 600 Prom_node *pci_bridge_node; 601 Prom_node *pci_parent_bridge; 602 int *int_val; 603 int pci_bridge = FALSE; 604 int pci_bridge_dev_no = -1; 605 int portid; 606 int pci_bus; 607 char buf[MAXSTRLEN]; 608 char *slot_name = NULL; /* info in "slot-names" prop */ 609 char *child_name; 610 char *name; 611 char *type; 612 void *value; 613 614 while (pci_card_node != NULL) { 615 int is_pci = FALSE; 616 type = NULL; 617 name = NULL; 618 /* If it doesn't have a name, skip it */ 619 name = (char *)get_prop_val( 620 find_prop(pci_card_node, "name")); 621 if (name == NULL) { 622 pci_card_node = pci_card_node->sibling; 623 continue; 624 } 625 626 /* 627 * Get the portid of the schizo that this card 628 * lives under. 629 */ 630 portid = -1; 631 value = get_prop_val(find_prop(pci_instance, "portid")); 632 if (value != NULL) { 633 portid = *(int *)value; 634 } 635 pci_card->schizo_portid = portid; 636 /* 637 * Find out whether this is PCI bus A or B 638 * using the 'reg' property. 639 */ 640 int_val = (int *)get_prop_val(find_prop(pci_instance, "reg")); 641 642 if (int_val != NULL) { 643 int_val++; /* skip over first integer */ 644 pci_bus = ((*int_val) & 0x7f0000); 645 if (pci_bus == 0x600000) 646 pci_card->pci_bus = 'A'; 647 else if (pci_bus == 0x700000) 648 pci_card->pci_bus = 'B'; 649 else 650 pci_card->pci_bus = '-'; 651 } else { 652 pci_card->pci_bus = '-'; 653 } 654 655 if ((pci_card->schizo_portid == 8) && 656 (pci_card->pci_bus == 'A')) { 657 pci_card_node = pci_card_node->sibling; 658 continue; 659 } 660 661 /* 662 * get dev# and func# for this card from the 663 * 'reg' property. 664 */ 665 int_val = (int *)get_prop_val( 666 find_prop(pci_card_node, "reg")); 667 if (int_val != NULL) { 668 pci_card->dev_no = (((*int_val) & 0xF800) >> 11); 669 pci_card->func_no = (((*int_val) & 0x700) >> 8); 670 } else { 671 pci_card->dev_no = -1; 672 pci_card->func_no = -1; 673 } 674 675 type = (char *)get_prop_val( 676 find_prop(pci_card_node, "device_type")); 677 /* 678 * If this is a pci-bridge, then store its dev# 679 * as its children nodes need this to get their slot#. 680 * We set the pci_bridge flag so that we know we are 681 * looking at a pci-bridge node. This flag gets reset 682 * every time we enter this while loop. 683 */ 684 685 /* 686 * Check for a PCI-PCI Bridge for PCI and cPCI 687 * IO Boards using the name and type properties. 688 */ 689 if ((type != NULL) && (strncmp(name, "pci", 3) == 0) && 690 (strcmp(type, "pci") == 0)) { 691 pci_bridge_node = pci_card_node; 692 is_pci = TRUE; 693 if (!pci_bridge) { 694 pci_bridge_dev_no = pci_card->dev_no; 695 pci_parent_bridge = pci_bridge_node; 696 pci_bridge = TRUE; 697 } 698 } 699 if ((pci_card->pci_bus == 'B') && (pci_card->dev_no == 1) && 700 (!pci_bridge)) { 701 pci_card_node = pci_card_node->sibling; 702 continue; 703 } 704 705 /* 706 * Get slot-names property from slot_names_arr. 707 * If we are the child of a pci_bridge we use the 708 * dev# of the pci_bridge as an index to get 709 * the slot number. We know that we are a child of 710 * a pci-bridge if our parent is the same as the last 711 * pci_bridge node found above. 712 */ 713 if (pci_card->dev_no != -1) { 714 /* 715 * We compare this cards parent node with the 716 * pci_bridge_node to see if it's a child. 717 */ 718 if (pci_card_node->parent != pci_instance && 719 pci_bridge) { 720 /* use dev_no of pci_bridge */ 721 if (pci_card->pci_bus == 'B') { 722 slot_name = 723 slot_name_arr[pci_bridge_dev_no -2]; 724 } else { 725 slot_name = 726 slot_name_arr[pci_bridge_dev_no -1]; 727 } 728 } else { 729 if (pci_card->pci_bus == 'B') { 730 slot_name = 731 slot_name_arr[pci_card->dev_no-2]; 732 } else { 733 slot_name = 734 slot_name_arr[pci_card->dev_no-1]; 735 } 736 } 737 738 if (slot_name != NULL && 739 strlen(slot_name) != 0) { 740 /* Slot num is last char in string */ 741 (void) snprintf(pci_card->slot_str, MAXSTRLEN, 742 "%c", slot_name[strlen(slot_name) - 1]); 743 } else { 744 (void) snprintf(pci_card->slot_str, MAXSTRLEN, 745 "-"); 746 } 747 748 } else { 749 (void) snprintf(pci_card->slot_str, MAXSTRLEN, 750 "%c", '-'); 751 } 752 753 /* 754 * Check for failed status. 755 */ 756 if (node_failed(pci_card_node)) 757 strcpy(pci_card->status, "fail"); 758 else 759 strcpy(pci_card->status, "ok"); 760 761 /* Get the model of this pci_card */ 762 value = get_prop_val(find_prop(pci_card_node, "model")); 763 if (value == NULL) 764 pci_card->model[0] = '\0'; 765 else { 766 (void) snprintf(pci_card->model, MAXSTRLEN, "%s", 767 (char *)value); 768 } 769 /* 770 * The card may have a "clock-frequency" but we 771 * are not interested in that. Instead we get the 772 * "clock-frequency" of the PCI Bus that the card 773 * resides on. PCI-A can operate at 33Mhz or 66Mhz 774 * depending on what card is plugged into the Bus. 775 * PCI-B always operates at 33Mhz. 776 */ 777 int_val = get_prop_val(find_prop(pci_instance, 778 "clock-frequency")); 779 if (int_val != NULL) { 780 pci_card->freq = DAK_CLK_FREQ_TO_MHZ(*int_val); 781 } else { 782 pci_card->freq = -1; 783 } 784 785 /* 786 * Figure out how we want to display the name 787 */ 788 value = get_prop_val(find_prop(pci_card_node, 789 "compatible")); 790 if (value != NULL) { 791 /* use 'name'-'compatible' */ 792 (void) snprintf(buf, MAXSTRLEN, "%s-%s", name, 793 (char *)value); 794 } else { 795 /* just use 'name' */ 796 (void) snprintf(buf, MAXSTRLEN, "%s", name); 797 } 798 name = buf; 799 800 /* 801 * If this node has children, add the device_type 802 * of the child to the name value of this pci_card-> 803 */ 804 child_name = (char *)get_node_name(pci_card_node->child); 805 if ((pci_card_node->child != NULL) && 806 (child_name != NULL)) { 807 value = get_prop_val(find_prop(pci_card_node->child, 808 "device_type")); 809 if (value != NULL) { 810 /* add device_type of child to name */ 811 (void) snprintf(pci_card->name, MAXSTRLEN, 812 "%s/%s (%s)", name, child_name, 813 (char *)value); 814 } else { 815 /* just add childs name */ 816 (void) snprintf(pci_card->name, MAXSTRLEN, 817 "%s/%s", name, child_name); 818 } 819 } else { 820 (void) snprintf(pci_card->name, MAXSTRLEN, "%s", 821 (char *)name); 822 } 823 824 /* 825 * If this is a pci-bridge, then add the word 826 * 'pci-bridge' to its model. If we can't find 827 * a model, then we just describe what the device 828 * is based on some properties. 829 */ 830 if (pci_bridge) { 831 if (strlen(pci_card->model) == 0) { 832 if (pci_card_node->parent == pci_bridge_node) 833 (void) snprintf(pci_card->model, MAXSTRLEN, 834 "%s", "device on pci-bridge"); 835 else if (pci_card_node->parent 836 == pci_parent_bridge) 837 (void) snprintf(pci_card->model, MAXSTRLEN, 838 "%s", "pci-bridge/pci-bridge"); 839 else 840 (void) snprintf(pci_card->model, MAXSTRLEN, 841 "%s", "PCI-BRIDGE"); 842 } 843 else 844 (void) snprintf(pci_card->model, MAXSTRLEN, 845 "%s/pci-bridge", pci_card->model); 846 } 847 /* insert this pci_card in the list to be displayed later */ 848 849 *pci_card_list = insert_io_card(*pci_card_list, pci_card); 850 851 /* 852 * If we are dealing with a pci-bridge, we need to move 853 * down to the children of this bridge if there are any. 854 * 855 * If we are not, we are either dealing with a regular 856 * card (in which case we move onto the sibling of this 857 * card) or we are dealing with a child of a pci-bridge 858 * (in which case we move onto the child's siblings or 859 * if there are no more siblings for this child, we 860 * move onto the parents siblings). 861 */ 862 pci_card_node = next_pci_card(pci_card_node, &pci_bridge, 863 is_pci, pci_bridge_node, 864 pci_parent_bridge, pci_instance); 865 } /* end-while */ 866 } 867 868 869 /* 870 * Helper function for fill_pci_card_list(). Indicates which 871 * card node to go to next. 872 * Parameters: 873 * ----------- 874 * Prom_node * curr_card: pointer to the current card node 875 * 876 * int * is_bridge: indicates whether or not the card (is | is on) 877 * a pci bridge 878 * 879 * int is_pcidev: indicates whether or not the current card 880 * is a pci bridge 881 * 882 * Prom_node * curr_bridge: pointer to the current pci bridge. Eg: 883 * curr_card->parent. 884 * 885 * Prom_node * parent_bridge: pointer to the first pci bridge encountered. 886 * we could have nested pci bridges, this would 887 * be the first one. 888 * 889 * Prom_node * pci: pointer to the pci instance that we are attached to. 890 * This would be parent_bridge->parent, or 891 * curr_node->parent, if curr_node is not on a pci bridge. 892 */ 893 static Prom_node * 894 next_pci_card(Prom_node *curr_card, int *is_bridge, int is_pcidev, 895 Prom_node *curr_bridge, Prom_node *parent_bridge, 896 Prom_node *pci) 897 { 898 Prom_node * curr_node = curr_card; 899 if (*is_bridge) { 900 /* 901 * is_pcidev is used to prevent us from following the 902 * children of something like a scsi device. 903 */ 904 if (curr_node->child != NULL && is_pcidev) { 905 curr_node = curr_node->child; 906 } else { 907 curr_node = curr_node->sibling; 908 if (curr_node == NULL) { 909 curr_node = curr_bridge->sibling; 910 911 while (curr_node == NULL && 912 curr_bridge != parent_bridge && 913 curr_bridge != NULL) { 914 curr_node = 915 curr_bridge->parent->sibling; 916 curr_bridge = curr_bridge->parent; 917 if (curr_node != NULL && 918 curr_node->parent == pci) { 919 break; 920 } 921 } 922 923 if (curr_bridge == NULL || 924 curr_node == NULL || 925 curr_node->parent == pci || 926 curr_bridge == parent_bridge || 927 curr_node == parent_bridge) { 928 *is_bridge = FALSE; 929 } 930 } 931 } 932 933 } else { 934 curr_node = curr_node->sibling; 935 } 936 return (curr_node); 937 } 938