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