/* * add_node * * This function adds a board node to the board structure where that * that node's physical component lives. */ void add_node(Sys_tree *root, Prom_node *pnode) { int board = -1; int portid = -1; void *value = NULL; Board_node *bnode = NULL; Prom_node *p = NULL; /* Get the board number of this board from the portid prop */ value = get_prop_val(find_prop(pnode, "portid")); if (value != NULL) { portid = *(int *)value; } board = LNECK_PORTID_TO_BOARD_NUM(portid); /* find the board node with the same board number */ if ((bnode = littleneck_find_board(root, board)) == NULL) { bnode = littleneck_insert_board(root, board); } /* now attach this prom node to the board list */ /* Insert this node at the end of the list */ pnode->sibling = NULL; if (bnode->nodes == NULL) bnode->nodes = pnode; else { p = bnode->nodes; while (p->sibling != NULL) p = p->sibling; p->sibling = pnode; } }
/* * inParams - CCIMPropertyList pointer that dereferences to a list of not less * than 4 or more than 16 CCIMProperty values. Number of CCIMProperty values * must be a multiple of 4. * * The fdisk file will contain at least one line and not more than four lines * in the following format: * id:act:0:0:0:0:0:0:rsect:numsect. * Values for id, act, rsect and numsect are taken from inParams. */ static CIMBool build_fdisk_file(char *fdisk_file, CCIMPropertyList *params) { FILE *fp; int i; int error; ulong_t *vals; int cnt = 0; if (params == NULL) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (cim_false); } vals = cim_decodeUint32Array(get_prop_val(params->mDataObject), &cnt); if (cnt == 0 || cnt > 16 || (cnt % 4) != 0) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (cim_false); } (void) tmpnam(fdisk_file); /* Open the temporary file for writing */ if ((fp = util_openFile(fdisk_file, "w")) == NULL) { util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL, NULL, &error); return (cim_false); } /* * Build a fdisk_file using 4 input parameters at a time. * Check for all possible NULL parameters, parameter lists * greater than 16 or not a multiple of 4. */ for (i = 0; i < cnt; i += 4) { char line_buf[DATALEN]; (void) snprintf(line_buf, sizeof (line_buf), "%lu:%lu:0:0:0:0:0:0:%lu:%lu\n", vals[i], vals[i + 1], vals[i + 2], vals[i + 3]); /* Write the line of parameters to the fdisk_file */ if ((fputs(line_buf, fp)) == EOF) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); (void) util_closeFile(fp, fdisk_file); return (cim_false); } } if ((util_closeFile(fp, fdisk_file)) == 0) { return (cim_false); } /* Caller must delete the temporary file */ return (cim_true); }
static void display_hw_revisions(Prom_node *root, Board_node *bdlist) { Prom_node *pnode; char *value; log_printf(dgettext(TEXT_DOMAIN, "\n" "========================= HW Revisions " "=======================================\n\n")); log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n" "----------------------\n")); pnode = dev_find_node(root, "openprom"); if (pnode != NULL) { value = (char *)get_prop_val(find_prop(pnode, "version")); log_printf(value); } log_printf(dgettext(TEXT_DOMAIN, "\n\n" "IO ASIC revisions:\n" "------------------\n" " Port\n" "Model ID Status Version\n" "-------- ---- ------ -------\n")); display_schizo_revisions(bdlist); }
/* * returns the size of the given processors external cache in * bytes. If the properties required to determine this are not * present, then the function returns 0. */ int get_ecache_size(Prom_node *node) { int *cache_size_p; /* pointer to number of cache lines */ /* find the properties */ if (cache_size_p = (int *)get_prop_val(find_prop(node, "ecache-size"))) { return (*cache_size_p); } if (cache_size_p = (int *)get_prop_val(find_prop(node, "l3-cache-size"))) { return (*cache_size_p); } if (cache_size_p = (int *)get_prop_val(find_prop(node, "l2-cache-size"))) { return (*cache_size_p); } return (0); }
/* * Function: writeVolumeName * * Parameters: params - CCIMPropertyList pointer. Property list * containing the new disk label name. * op - CCIMObjectPath pointer. Object path containing * the deviceId of the disk to label. * * Returns: Returns a CCIMProperty pointer. The CCIMProperty referenced * by the pointer will contain an mValue of cim_true for * success or cim_false on failure. * * Description: Executes the fmthard -n volume_name command on the device * pointed to by 'op'. */ CCIMProperty * label_disk(CCIMPropertyList *params, CCIMObjectPath *op) { char devpath[MAXPATHLEN]; char command_line[CMDLEN]; int len; cimchar *label; int error; if (!check_rights("Solaris_Disk") || op == NULL || params == NULL) { return (create_result(PROPFALSE)); } if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (create_result(PROPFALSE)); } /* Extract the label from the input parameters */ if ((label = get_prop_val(params->mDataObject)) == NULL) { return (create_result(PROPFALSE)); } if (strlen(label) > 8) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (create_result(PROPFALSE)); } /* Build the command line to execute */ len = snprintf(command_line, sizeof (command_line), "/usr/sbin/fmthard -n '%s' %s 2> /dev/null", label, devpath); if (len < 0 || (len + 1) > sizeof (command_line)) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (create_result(PROPFALSE)); } /* Execute the command. */ if (!execute_cmd(command_line, "/dev/null")) { return (create_result(PROPFALSE)); } return (create_result(PROPTRUE)); }
/* * Return the operating frequency of a processor in Hertz. This function * requires as input a legal prom node pointer. If a NULL * is passed in or the clock-frequency property does not exist, the * function returns 0. */ uint_t get_cpu_freq(Prom_node *pnode) { Prop *prop; uint_t *value; /* find the property */ if ((prop = find_prop(pnode, "clock-frequency")) == NULL) { return (0); } if ((value = (uint_t *)get_prop_val(prop)) == NULL) { return (0); } return (*value); }
/*ARGSUSED*/ static void sun4v_display_hw_revisions(Prom_node *root, picl_nodehdl_t plafh) { Prom_node *pnode; char *value; char platbuf[MAXSTRLEN]; char *fmt = "%-20s %-40s %-30s %-9s"; log_printf(dgettext(TEXT_DOMAIN, "\n" "========================= HW Revisions " "=======================================\n\n")); log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n" "----------------------\n")); pnode = dev_find_node(root, "openprom"); if (pnode != NULL) { value = (char *)get_prop_val(find_prop(pnode, "version")); log_printf(value); } log_printf(dgettext(TEXT_DOMAIN, "\n\n" "IO ASIC revisions:\n" "------------------\n")); log_printf(fmt, "Location", "Path", "Device", "Revision\n", 0); log_printf(fmt, "--------------------", "----------------------------------------", "------------------------------", "---------\n", 0); /* Get platform name, if that fails, use montoya name by default */ if (sysinfo(SI_PLATFORM, platbuf, sizeof (platbuf)) == -1) { (void) strcpy(platbuf, MONTOYA_PLATFORM); } (void) picl_walk_tree_by_class(plafh, PCIEX, PCIEX, montoya_hw_rev_callback); (void) picl_walk_tree_by_class(plafh, PCI, PCI, montoya_hw_rev_callback); (void) picl_walk_tree_by_class(plafh, NETWORK, NETWORK, montoya_hw_rev_callback); (void) picl_walk_tree_by_class(plafh, SCSI2, SCSI2, montoya_hw_rev_callback); }
/* * Do a depth-first walk of a device tree and * return the first node with the matching model. */ static Prom_node * dev_find_node_by_compat(Prom_node *root, char *compat) { Prom_node *node; char *compatible; char *name; if (root == NULL) return (NULL); if (compat == NULL) return (NULL); name = get_node_name(root); if (name == NULL) name = ""; compatible = (char *)get_prop_val(find_prop(root, "compatible")); if (compatible == NULL) return (NULL); if ((strcmp(name, "pci") == 0) && (compatible != NULL) && (strcmp(compatible, compat) == 0)) { return (root); /* found a match */ } /* look at your children first */ if ((node = dev_find_node_by_compat(root->child, compat)) != NULL) return (node); /* now look at your siblings */ if ((node = dev_find_node_by_compat(root->sibling, compat)) != NULL) return (node); return (NULL); /* not found */ }
/* * inParams - CCIMPropertyList pointer that dereferences to a list of not less * than 5 CCIMProperty values. The number of CCIMProperty values must be a * multiple of 5. * * The file will contain at least one line in the following format: * part tag flag start_sect part_size * Values for partition, tag, flag, starting sector and partition size are * taken from inParams. */ static CIMBool build_fmt_file(char *fmt_file, CCIMPropertyList *params) { ulong_t *vals; int cnt = 0; FILE *fp; int error; int i; if (params == NULL) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (cim_false); } vals = cim_decodeUint32Array(get_prop_val(params->mDataObject), &cnt); if (cnt == 0 || (cnt % 5) != 0) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); return (cim_false); } (void) tmpnam(fmt_file); /* Open the temporary file for writing */ if ((fp = util_openFile(fmt_file, "w")) == NULL) { util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL, NULL, &error); return (cim_false); } /* * Build a data file for the fmthard command. * Each line of the file consists of: * * part_num tag flag start_sector partition_size * * The fmthard command requires the starting sector fall on * a cylinder boundry. */ for (i = 0; i < cnt; i += 5) { char line_buf[DATALEN]; char flag_buf[DATALEN]; convert_flag(vals[i + 2], flag_buf, sizeof (flag_buf)); (void) snprintf(line_buf, sizeof (line_buf), "%lu %lu %s %lu %lu\n", vals[i], vals[i + 1], flag_buf, vals[i + 3], vals[i + 4]); /* Write the line of parameters to the fdisk_file */ if ((fputs(line_buf, fp)) == EOF) { util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL, NULL, &error); (void) util_closeFile(fp, fmt_file); return (cim_false); } } if ((util_closeFile(fp, fmt_file)) == 0) { return (cim_false); } /* Caller must delete the file */ return (cim_true); }
/* * Display the CPUs present on this board. */ void display_cpus(Board_node *board) { Prom_node *cpu; /* * display the CPUs' operating frequency, cache size, impl. field * and mask revision. */ for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL; cpu = dev_next_type(cpu, "cpu")) { int freq; /* CPU clock frequency */ int ecache_size; /* External cache size */ int *mid; int *impl; int *mask, decoded_mask; mid = (int *)get_prop_val(find_prop(cpu, "upa-portid")); if (mid == NULL) { mid = (int *)get_prop_val(find_prop(cpu, "portid")); } freq = (get_cpu_freq(cpu) + 500000) / 1000000; ecache_size = get_ecache_size(cpu); impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); mask = (int *)get_prop_val(find_prop(cpu, "mask#")); /* Do not display a failed CPU node */ if ((freq != 0) && (node_failed(cpu) == 0)) { /* Board number */ display_boardnum(board->board_num); /* CPU MID */ log_printf(" %2d ", *mid, 0); /* Module number */ display_mid(*mid); /* Running frequency */ log_printf(" %3d ", freq, 0); /* Ecache size */ if (ecache_size == 0) log_printf(" %3s ", "N/A", 0); else log_printf(" %4.1f ", (float)ecache_size / (float)(1<<20), 0); /* Implementation */ if (impl == NULL) { log_printf("%6s ", "N/A", 0); } else { switch (*impl) { case SPITFIRE_IMPL: log_printf("%-6s ", "US-I", 0); break; case BLACKBIRD_IMPL: log_printf("%-6s ", "US-II", 0); break; case CHEETAH_IMPL: log_printf("%-6s ", "US-III", 0); break; case CHEETAH_PLUS_IMPL: log_printf("%-7s ", "US-III+", 0); break; case JAGUAR_IMPL: log_printf("%-6s ", "US-IV", 0); break; default: log_printf("%-6x ", *impl, 0); break; } } /* CPU Mask */ if (mask == NULL) { log_printf(" %3s", "N/A", 0); } else { if ((impl) && IS_CHEETAH(*impl)) decoded_mask = REMAP_CHEETAH_MASK(*mask); else decoded_mask = *mask; log_printf(" %d.%d", (decoded_mask >> 4) & 0xf, decoded_mask & 0xf, 0); } log_printf("\n", 0); } }
static void display_schizo_revisions(Board_node *bdlist) { Prom_node *pnode; int *int_val; int portid; int prev_portid = -1; char *status_a = NULL; char *status_b = NULL; int revision; #ifdef DEBUG uint32_t a_notes, b_notes; #endif int pci_bus; Board_node *bnode; bnode = bdlist; while (bnode != NULL) { /* * search this board node for all Schizos */ for (pnode = dev_find_node_by_compat(bnode->nodes, SCHIZO_COMPAT_PROP); pnode != NULL; pnode = dev_next_node_by_compat(pnode, SCHIZO_COMPAT_PROP)) { /* * get the reg property to determine * whether we are looking at side A or B */ int_val = (int *)get_prop_val (find_prop(pnode, "reg")); if (int_val != NULL) { int_val ++; /* second integer in array */ pci_bus = ((*int_val) & 0x7f0000); } /* get portid */ int_val = (int *)get_prop_val (find_prop(pnode, "portid")); if (int_val == NULL) continue; portid = *int_val; /* * If this is a new portid and it is PCI bus B, * we skip onto the PCI bus A. */ if ((portid != prev_portid) && (pci_bus == 0x700000)) { prev_portid = portid; /* status */ status_b = (char *)get_prop_val (find_prop(pnode, "status")); #ifdef DEBUG b_notes = pci_bus; #endif continue; /* skip to the next schizo */ } /* * This must be side A of the same Schizo. * Gather all its props and display them. */ #ifdef DEBUG a_notes = pci_bus; #endif prev_portid = portid; int_val = (int *)get_prop_val (find_prop(pnode, "version#")); if (int_val != NULL) revision = *int_val; else revision = -1; status_a = (char *)get_prop_val(find_prop (pnode, "status")); log_printf(dgettext(TEXT_DOMAIN, "Schizo ")); log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0); log_printf((status_a == NULL && status_b == NULL) ? dgettext(TEXT_DOMAIN, " ok ") : dgettext(TEXT_DOMAIN, " fail ")); log_printf(dgettext(TEXT_DOMAIN, " %4d "), revision); #ifdef DEBUG log_printf(" 0x%x 0x%x", a_notes, b_notes); #endif log_printf("\n"); } bnode = bnode->next; } }
/* * display_pci * Display all the PCI IO cards on this board. */ void display_pci(Board_node *board) { struct io_card *card_list = NULL; struct io_card card; void *value; Prom_node *pci; Prom_node *card_node; static int banner = FALSE; char *slot_name_arr[NUM_PCI_SLOTS]; int i; if (board == NULL) return; (void) memset(&card, 0, sizeof (struct io_card)); /* Initialize all the common information */ card.display = TRUE; card.board = board->board_num; /* * Search for each pci instance, then find/display all nodes under * each instance node found. */ for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP); pci != NULL; pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) { (void) snprintf(card.bus_type, MAXSTRLEN, dgettext(TEXT_DOMAIN, "PCI")); /* * Get slot-name properties from parent node and * store them in an array. */ value = (char *)get_prop_val( find_prop(pci, "slot-names")); if (value != NULL) { /* array starts after first int */ slot_name_arr[0] = (char *)value + sizeof (int); for (i = 1; i < NUM_PCI_SLOTS; i++) { slot_name_arr[i] = (char *)slot_name_arr[i - 1] + strlen(slot_name_arr[i - 1]) +1; } } /* * Search for Children of this node ie. Cards. * Note: any of these cards can be a pci-bridge * that itself has children. If we find a * pci-bridge we need to handle it specially. */ card_node = pci->child; /* Generate the list of pci cards on pci instance: pci */ fill_pci_card_list(pci, card_node, &card, &card_list, slot_name_arr); } /* end-for */ if (!banner && card_list != NULL) { log_printf(dgettext(TEXT_DOMAIN, " Bus Max\n" " IO Port Bus Freq Bus Dev,\n" "Type ID Side Slot MHz Freq Func State " "Name Model" #ifdef DEBUG " Notes" #endif "\n" "---- ---- ---- ---- ---- ---- ---- ----- " "-------------------------------- " #ifdef DEBUG "---------------------- " #endif "----------------------\n")); banner = TRUE; } display_io_cards(card_list); free_io_cards(card_list); }
void display_cpus(Board_node *board) { Prom_node *cpu; uint_t freq; int ecache_size; int *l3_shares; int *mid; int *impl; int *mask; int *coreid; char fru_prev = 'X'; /* Valid frus are 'A','B' */ int mid_prev; int ecache_size_prev = 0; char fru_name; /* * display the CPUs' operating frequency, cache size, impl. field * and mask revision. */ for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL; cpu = dev_next_type(cpu, "cpu")) { mid = (int *)get_prop_val(find_prop(cpu, "portid")); if (mid == NULL) mid = (int *)get_prop_val(find_prop(cpu, "cpuid")); freq = HZ_TO_MHZ(get_cpu_freq(cpu)); ecache_size = get_ecache_size(cpu); impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); mask = (int *)get_prop_val(find_prop(cpu, "mask#")); l3_shares = (int *)get_prop_val(find_prop(cpu, "l3-cache-sharing")); /* Do not display a failed CPU node */ if ((impl == NULL) || (freq == 0) || (node_failed(cpu))) continue; fru_name = CHERRYSTONE_GETSLOT_LABEL(*mid); if (CPU_IMPL_IS_CMP(*impl)) { coreid = (int *)get_prop_val(find_prop(cpu, "reg")); if (coreid == NULL) { continue; } if ((fru_prev == 'X') || ((fru_prev != 'X') && (fru_name != fru_prev))) { fru_prev = fru_name; mid_prev = *mid; ecache_size_prev = ecache_size; continue; } else { /* * Some CMP chips have a split E$, * so the size for both cores is added * together to get the total size for * the chip. * * Still, other CMP chips have E$ (L3) * which is logically shared, so the * total size is equal to the core size. */ if ((l3_shares == NULL) || ((l3_shares != NULL) && MULTIPLE_BITS_SET(*l3_shares))) { ecache_size += ecache_size_prev; } ecache_size_prev = 0; fru_prev = 'X'; } } log_printf(" %c", fru_name); /* CPU Module ID */ if (CPU_IMPL_IS_CMP(*impl)) { log_printf("%3d,%3d ", mid_prev, *mid, 0); } else log_printf(" %2d ", *mid); /* Running frequency */ log_printf("%4u", freq); if (ecache_size == 0) log_printf(" N/A "); else log_printf(" %4.1f ", (float)ecache_size / (float)(1<<20)); /* Implementation */ if (impl == NULL) { log_printf(dgettext(TEXT_DOMAIN, " N/A ")); } else { if (IS_CHEETAH(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-III ")); else if (IS_CHEETAH_PLUS(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-III+ ")); else if (IS_JAGUAR(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-IV ")); else if (IS_PANTHER(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-IV+ ")); else log_printf("%-6x ", *impl); } /* CPU Mask */ if (mask == NULL) { log_printf(dgettext(TEXT_DOMAIN, " N/A\n")); } else { log_printf(dgettext(TEXT_DOMAIN, " %d.%d\n"), (*mask >> 4) & 0xf, *mask & 0xf); } } }
/* * display_pci * Display all the PCI IO cards on this board. */ void display_pci(Board_node *board) { struct io_card *card_list = NULL; struct io_card card; void *value; Prom_node *pci; Prom_node *card_node; Prom_node *pci_bridge_node = NULL; char *slot_name_arr[MAX_SLOTS_PER_IO_BD] = {NULL}; char *slot_name = NULL; int slot_name_bits; int slot_name_offset = 0; char *child_name; char *name, *type; char buf[MAXSTRLEN]; int *int_val; int pci_bus; int pci_bridge = 0; int pci_bridge_dev_no; int child_dev_no; int i; int portid; int version, *pversion; if (board == NULL) return; /* Initialize all the common information */ card.display = TRUE; card.board = board->board_num; card.node_id = board->node_id; /* * Search for each schizo, then find/display all nodes under * each schizo node found. Since the model property "SUNW,schizo" * is not supported on Starcat, we must match on the compatible * property "pci108e,8001". */ for (pci = dev_find_node_by_compatible(board->nodes, SCHIZO_COMPATIBLE); pci != NULL; pci = dev_next_node_by_compatible(pci, SCHIZO_COMPATIBLE)) { /* set max freq for this board */ board_bus_max_freq = DEFAULT_MAX_FREQ; /* * Find out if this is a PCI or cPCI IO Board. * If "enum-impl" property exists in pci node => cPCI. */ value = get_prop_val(find_prop(pci, "enum-impl")); if (value == NULL) { (void) sprintf(card.bus_type, "PCI"); } else { (void) sprintf(card.bus_type, "cPCI"); } if (strstr((char *)get_prop_val( find_prop(pci, "compatible")), XMITS_COMPATIBLE)) { sprintf(card.notes, "%s", XMITS_COMPATIBLE); /* * With XMITS 3.X and PCI-X mode, the bus speed * can be higher than 66MHZ. */ value = (int *)get_prop_val (find_prop(pci, "module-revision#")); if (value) { pversion = (int *)value; version = *pversion; if (version >= 4) board_bus_max_freq = PCIX_MAX_FREQ; } } else if (strstr((char *)get_prop_val( find_prop(pci, "compatible")), SCHIZO_COMPATIBLE)) sprintf(card.notes, "%s", SCHIZO_COMPATIBLE); else sprintf(card.notes, " "); /* * Get slot-names property from parent node and * store the individual slot names in an array. * This is more general than Starcat requires, but * it is correct, according to the slot-names property. */ value = (char *)get_prop_val(find_prop(pci, "slot-names")); if (value == NULL) { /* * No slot_names property. This could be an Xmits * card, so check the child node for slot-names property */ value = (char *)get_prop_val( find_prop(pci->child, "slot-names")); } if (value != NULL) { /* Get the 4 byte bitmask and pointer to first name */ slot_name_bits = *(int *)value; if (slot_name_bits > 0) slot_name_offset = slot_name_bits - 1; slot_name = (char *)value + sizeof (int); for (i = 0; i < MAX_SLOTS_PER_IO_BD; i++) { if (! (slot_name_bits & (1 << i))) { slot_name_arr[i] = (char *)NULL; continue; } /* * Save the name pointer into the array * and advance it past the end of this * slot name */ slot_name_arr[i] = slot_name; slot_name += strlen(slot_name) + 1; } slot_name = (char *)NULL; } /* * Search for Children of this node ie. Cards. * Note: any of these cards can be a pci-bridge * that itself has children. If we find a * pci-bridge we need to handle it specially. */ card_node = pci->child; while (card_node != NULL) { pci_bridge = 0; /* If it doesn't have a name, skip it */ name = (char *)get_prop_val( find_prop(card_node, "name")); if (name == NULL) { card_node = card_node->sibling; continue; } /* * get dev# and func# for this card from the * 'reg' property. */ int_val = (int *)get_prop_val( find_prop(card_node, "reg")); if (int_val != NULL) { card.dev_no = (((*int_val) & 0xF800) >> 11); card.func_no = (((*int_val) & 0x700) >> 8); } else { card.dev_no = -1; card.func_no = -1; } /* * If this is a pci-bridge, then store it's dev# * as its children nodes need this to get their slot#. * We set the pci_bridge flag so that we know we are * looking at a pci-bridge node. This flag gets reset * every time we enter this while loop. */ /* * Check for a PCI-PCI Bridge for PCI and cPCI * IO Boards using the name and type properties. */ type = (char *)get_prop_val( find_prop(card_node, "device_type")); if ((type != NULL) && (strncmp(name, "pci", 3) == 0) && (strcmp(type, "pci") == 0)) { pci_bridge_dev_no = card.dev_no; pci_bridge_node = card_node; pci_bridge = TRUE; } /* * Get slot-names property from slot_names_arr. * If we are the child of a pci_bridge we use the * dev# of the pci_bridge as an index to get * the slot number. We know that we are a child of * a pci-bridge if our parent is the same as the last * pci_bridge node found above. */ if (card.dev_no != -1) { /* * We compare this card's parent node with the * pci_bridge_node to see if it's a child. */ if (card_node->parent == pci_bridge_node) { /* use dev_no of pci_bridge */ child_dev_no = pci_bridge_dev_no - 1; } else { /* use card's own dev_no */ child_dev_no = card.dev_no - 1; } if (child_dev_no < MAX_SLOTS_PER_IO_BD && child_dev_no >= 0 && slot_name_arr [child_dev_no + slot_name_offset] != NULL) { slot_name = slot_name_arr[ child_dev_no + slot_name_offset]; } else slot_name = (char *)NULL; if (slot_name != NULL && slot_name[0] != '\0') { (void) sprintf(card.slot_str, "%s", slot_name); } else { (void) sprintf(card.slot_str, "-"); } } else { (void) sprintf(card.slot_str, "%c", '-'); } /* * Get the portid of the schizo that this card * lives under. */ portid = -1; value = get_prop_val(find_prop(pci, "portid")); if (value != NULL) { portid = *(int *)value; } card.schizo_portid = portid; #ifdef DEBUG (void) sprintf(card.notes, "%s portid [%d]" " dev_no [%d] slot_name[%s] name_bits[%#x]", card.notes, portid, card.dev_no, ((slot_name != NULL) ? slot_name : "NULL"), slot_name_bits); #endif /* DEBUG */ /* * Find out whether this is PCI bus A or B * using the 'reg' property. */ int_val = (int *)get_prop_val (find_prop(pci, "reg")); if (int_val != NULL) { int_val ++; /* skip over first integer */ pci_bus = ((*int_val) & 0x7f0000); if (pci_bus == 0x600000) card.pci_bus = 'A'; else if (pci_bus == 0x700000) card.pci_bus = 'B'; else card.pci_bus = '-'; } else { card.pci_bus = '-'; } /* * Check for failed status. */ if (node_failed(card_node)) strcpy(card.status, "fail"); else strcpy(card.status, "ok"); /* Get the model of this card */ value = get_prop_val(find_prop(card_node, "model")); if (value == NULL) card.model[0] = '\0'; else { (void) sprintf(card.model, "%s", (char *)value); /* * If we wish to exclude onboard devices * (such as SBBC) then this is the place * and here is how to do it: * * if (strcmp(card.model, "SUNW,sbbc") == 0) { * card_node = card_node->sibling; * continue; * } */ } /* * The card may have a "clock-frequency" but we * are not interested in that. Instead we get the * "clock-frequency" of the PCI Bus that the card * resides on. PCI-A can operate at 33Mhz or 66Mhz * depending on what card is plugged into the Bus. * PCI-B always operates at 33Mhz. * */ int_val = get_prop_val(find_prop(pci, "clock-frequency")); if (int_val != NULL) { card.freq = HZ_TO_MHZ(*int_val); } else { card.freq = -1; } /* * Figure out how we want to display the name */ value = get_prop_val(find_prop(card_node, "compatible")); if (value != NULL) { /* use 'name'-'compatible' */ (void) sprintf(buf, "%s-%s", name, (char *)value); } else { /* just use 'name' */ (void) sprintf(buf, "%s", name); } name = buf; /* * If this node has children, add the device_type * of the child to the name value of this card. */ child_name = (char *)get_node_name(card_node->child); if ((card_node->child != NULL) && (child_name != NULL)) { value = get_prop_val(find_prop(card_node->child, "device_type")); if (value != NULL) { /* add device_type of child to name */ (void) sprintf(card.name, "%s/%s (%s)", name, child_name, (char *)value); } else { /* just add child's name */ (void) sprintf(card.name, "%s/%s", name, child_name); } } else { /* childless, just the card's name */ (void) sprintf(card.name, "%s", (char *)name); } /* * If this is a pci-bridge, then add the word * 'pci-bridge' to its model. */ if (pci_bridge) { if (card.model[0] == '\0') (void) sprintf(card.model, "%s", "pci-bridge"); else (void) strcat(card.model, "/pci-bridge"); } /* insert this card in the list to be displayed later */ card_list = insert_io_card(card_list, &card); /* * If we are dealing with a pci-bridge, we need to move * down to the children of this bridge, if there are * any, otherwise its siblings. * * If not a bridge, we are either dealing with a regular * card (in which case we move onto the sibling of this * card) or we are dealing with a child of a pci-bridge * (in which case we move onto the child's siblings or * if there are no more siblings for this child, we * move onto the parent's siblings). I hope you're * getting all this, there will be an exam later. */ if (pci_bridge) { if (card_node->child != NULL) card_node = card_node->child; else card_node = card_node->sibling; } else { /* * If our parent is a pci-bridge but there * are no more of its children to process we * move back up to our parent's sibling, * otherwise we move onto our own sibling. */ if ((card_node->parent == pci_bridge_node) && (card_node->sibling == NULL)) card_node = pci_bridge_node->sibling; else card_node = card_node->sibling; } } /* end while (card_node ...) loop */
/* * Fills in the i/o card list to be displayed later in display_pci(); */ void fill_pci_card_list(Prom_node * pci_instance, Prom_node * pci_card_node, struct io_card *pci_card, struct io_card **pci_card_list, char **slot_name_arr) { Prom_node *pci_bridge_node; Prom_node *pci_parent_bridge; int *int_val; int pci_bridge = FALSE; int pci_bridge_dev_no = -1; int portid; int pci_bus; char buf[MAXSTRLEN]; char *slot_name = NULL; /* info in "slot-names" prop */ char *child_name; char *name; char *type; void *value; while (pci_card_node != NULL) { int is_pci = FALSE; type = NULL; name = NULL; /* If it doesn't have a name, skip it */ name = (char *)get_prop_val( find_prop(pci_card_node, "name")); if (name == NULL) { pci_card_node = pci_card_node->sibling; continue; } /* * Get the portid of the schizo that this card * lives under. */ portid = -1; value = get_prop_val(find_prop(pci_instance, "portid")); if (value != NULL) { portid = *(int *)value; } pci_card->schizo_portid = portid; /* * Find out whether this is PCI bus A or B * using the 'reg' property. */ int_val = (int *)get_prop_val(find_prop(pci_instance, "reg")); if (int_val != NULL) { int_val++; /* skip over first integer */ pci_bus = ((*int_val) & 0x7f0000); if (pci_bus == 0x600000) pci_card->pci_bus = 'A'; else if (pci_bus == 0x700000) pci_card->pci_bus = 'B'; else pci_card->pci_bus = '-'; } else { pci_card->pci_bus = '-'; } /* * get dev# and func# for this card from the * 'reg' property. */ int_val = (int *)get_prop_val( find_prop(pci_card_node, "reg")); if (int_val != NULL) { pci_card->dev_no = (((*int_val) & 0xF800) >> 11); pci_card->func_no = (((*int_val) & 0x700) >> 8); } else {