/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef DEBUG_KLGRAPH #ifdef DEBUG_KLGRAPH #define DBG(x...) printk(x) #else #define DBG(x...) #endif /* DEBUG_KLGRAPH */ extern int numionodes; lboard_t *root_lboard[MAX_COMPACT_NODES]; static int hasmetarouter; char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo^34567890123456789..."; lboard_t * find_lboard_any(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { if (start->brd_type == brd_type) return start; start = KLCF_NEXT_ANY(start); } /* Didn't find it. */ return (lboard_t *)NULL; } lboard_t * find_lboard_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type) { while (start) { if ((start->brd_type == brd_type) && (start->brd_nasid == nasid)) return start; if (numionodes == numnodes) start = KLCF_NEXT_ANY(start); else start = KLCF_NEXT(start); } /* Didn't find it. */ return (lboard_t *)NULL; } lboard_t * find_lboard_class_any(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) return start; start = KLCF_NEXT_ANY(start); } /* Didn't find it. */ return (lboard_t *)NULL; } lboard_t * find_lboard_class_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { if (KLCLASS(start->brd_type) == KLCLASS(brd_type) && (start->brd_nasid == nasid)) return start; if (numionodes == numnodes) start = KLCF_NEXT_ANY(start); else start = KLCF_NEXT(start); } /* Didn't find it. */ return (lboard_t *)NULL; } klinfo_t * find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) { int index, j; if (kli == (klinfo_t *)NULL) { index = 0; } else { for (j = 0; j < KLCF_NUM_COMPS(brd); j++) { if (kli == KLCF_COMP(brd, j)) break; } index = j; if (index == KLCF_NUM_COMPS(brd)) { DBG("find_component: Bad pointer: 0x%p\n", kli); return (klinfo_t *)NULL; } index++; /* next component */ } for (; index < KLCF_NUM_COMPS(brd); index++) { kli = KLCF_COMP(brd, index); DBG("find_component: brd %p kli %p request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli)); if (KLCF_COMP_TYPE(kli) == struct_type) return kli; } /* Didn't find it. */ return (klinfo_t *)NULL; } klinfo_t * find_first_component(lboard_t *brd, unsigned char struct_type) { return find_component(brd, (klinfo_t *)NULL, struct_type); } lboard_t * find_lboard_modslot(lboard_t *start, geoid_t geoid) { /* Search all boards stored on this node. */ while (start) { if (geo_cmp(start->brd_geoid, geoid)) return start; start = KLCF_NEXT(start); } /* Didn't find it. */ return (lboard_t *)NULL; } /* * Convert a NIC name to a name for use in the hardware graph. */ void nic_name_convert(char *old_name, char *new_name) { int i; char c; char *compare_ptr; if ((old_name[0] == '\0') || (old_name[1] == '\0')) { strcpy(new_name, EDGE_LBL_XWIDGET); } else { for (i = 0; i < strlen(old_name); i++) { c = old_name[i]; if (isalpha(c)) new_name[i] = tolower(c); else if (isdigit(c)) new_name[i] = c; else new_name[i] = '_'; } new_name[i] = '\0'; } /* XXX - * Since a bunch of boards made it out with weird names like * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and * replace it with "baseio" to avoid confusion in the field. * We also have to make sure we don't report media_io instead of * baseio. */ /* Skip underscores at the beginning of the name */ for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++) ; /* * Check for some names we need to replace. Early boards * had junk following the name so check only the first * characters. */ if (!strncmp(new_name, "io6", 3) || !strncmp(new_name, "mio", 3) || !strncmp(new_name, "media_io", 8)) strcpy(new_name, "baseio"); else if (!strncmp(new_name, "divo", 4)) strcpy(new_name, "divo") ; } /* * get_actual_nasid * * Completely disabled brds have their klconfig on * some other nasid as they have no memory. But their * actual nasid is hidden in the klconfig. Use this * routine to get it. Works for normal boards too. */ nasid_t get_actual_nasid(lboard_t *brd) { klhub_t *hub ; if (!brd) return INVALID_NASID ; /* find out if we are a completely disabled brd. */ hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); if (!hub) return INVALID_NASID ; if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ return hub->hub_info.physid ; else return brd->brd_nasid ; } int xbow_port_io_enabled(nasid_t nasid, int link) { lboard_t *brd; klxbow_t *xbow_p; /* * look for boards that might contain an xbow or xbridge */ brd = find_lboard_nasid((lboard_t *)KL_CONFIG_INFO(nasid), nasid, KLTYPE_IOBRICK_XBOW); if (brd == NULL) return 0; if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) return 0; if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link)) return 0; return 1; } void board_to_path(lboard_t *brd, char *path) { moduleid_t modnum; char *board_name; char buffer[16]; ASSERT(brd); switch (KLCLASS(brd->brd_type)) { case KLCLASS_NODE: board_name = EDGE_LBL_NODE; break; case KLCLASS_ROUTER: if (brd->brd_type == KLTYPE_META_ROUTER) { board_name = EDGE_LBL_META_ROUTER; hasmetarouter++; } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) { board_name = EDGE_LBL_REPEATER_ROUTER; hasmetarouter++; } else board_name = EDGE_LBL_ROUTER; break; case KLCLASS_MIDPLANE: board_name = EDGE_LBL_MIDPLANE; break; case KLCLASS_IO: board_name = EDGE_LBL_IO; break; case KLCLASS_IOBRICK: if (brd->brd_type == KLTYPE_PXBRICK) board_name = EDGE_LBL_PXBRICK; else if (brd->brd_type == KLTYPE_IXBRICK) board_name = EDGE_LBL_IXBRICK; else if (brd->brd_type == KLTYPE_OPUSBRICK) board_name = EDGE_LBL_OPUSBRICK; else if (brd->brd_type == KLTYPE_CGBRICK) board_name = EDGE_LBL_CGBRICK; else board_name = EDGE_LBL_IOBRICK; break; default: board_name = EDGE_LBL_UNKNOWN; } modnum = geo_module(brd->brd_geoid); memset(buffer, 0, 16); format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF); sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name); } #define MHZ 1000000 /* * Get the serial number of the main component of a board * Returns 0 if a valid serial number is found * 1 otherwise. * Assumptions: Nic manufacturing string has the following format * *Serial:;* */ static int component_serial_number_get(lboard_t *board, klconf_off_t mfg_nic_offset, char *serial_number, char *key_pattern) { char *mfg_nic_string; char *serial_string,*str; int i; char *serial_pattern = "Serial:"; /* We have an error on a null mfg nic offset */ if (!mfg_nic_offset) return(1); /* Get the hub's manufacturing nic information * which is in the form of a pre-formatted string */ mfg_nic_string = (char *)NODE_OFFSET_TO_K0(NASID_GET(board), mfg_nic_offset); /* There is no manufacturing nic info */ if (!mfg_nic_string) return(1); str = mfg_nic_string; /* Look for the key pattern first (if it is specified) * and then print the serial number corresponding to that. */ if (strcmp(key_pattern,"") && !(str = strstr(mfg_nic_string,key_pattern))) return(1); /* There is no serial number info in the manufacturing * nic info */ if (!(serial_string = strstr(str,serial_pattern))) return(1); serial_string = serial_string + strlen(serial_pattern); /* Copy the serial number information from the klconfig */ i = 0; while (serial_string[i] != ';') { serial_number[i] = serial_string[i]; i++; } serial_number[i] = 0; return(0); } /* * Get the serial number of a board * Returns 0 if a valid serial number is found * 1 otherwise. */ int board_serial_number_get(lboard_t *board,char *serial_number) { ASSERT(board && serial_number); if (!board || !serial_number) return(1); strcpy(serial_number,""); switch(KLCLASS(board->brd_type)) { case KLCLASS_CPU: { /* Node board */ klhub_t *hub; /* Get the hub component information */ hub = (klhub_t *)find_first_component(board, KLSTRUCT_HUB); /* If we don't have a hub component on an IP27 * then we have a weird klconfig. */ if (!hub) return(1); /* Get the serial number information from * the hub's manufacturing nic info */ if (component_serial_number_get(board, hub->hub_mfg_nic, serial_number, "IP37")) return(1); break; } case KLCLASS_IO: { /* IO board */ klbri_t *bridge; /* Get the bridge component information */ bridge = (klbri_t *)find_first_component(board, KLSTRUCT_BRI); /* If we don't have a bridge component on an IO board * then we have a weird klconfig. */ if (!bridge) return(1); /* Get the serial number information from * the bridge's manufacturing nic info */ if (component_serial_number_get(board, bridge->bri_mfg_nic, serial_number, "")) return(1); break; } case KLCLASS_ROUTER: { /* Router board */ klrou_t *router; /* Get the router component information */ router = (klrou_t *)find_first_component(board, KLSTRUCT_ROU); /* If we don't have a router component on a router board * then we have a weird klconfig. */ if (!router) return(1); /* Get the serial number information from * the router's manufacturing nic info */ if (component_serial_number_get(board, router->rou_mfg_nic, serial_number, "")) return(1); break; } case KLCLASS_GFX: { /* Gfx board */ klgfx_t *graphics; /* Get the graphics component information */ graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX); /* If we don't have a gfx component on a gfx board * then we have a weird klconfig. */ if (!graphics) return(1); /* Get the serial number information from * the graphics's manufacturing nic info */ if (component_serial_number_get(board, graphics->gfx_mfg_nic, serial_number, "")) return(1); break; } default: strcpy(serial_number,""); break; } return(0); } /* * Format a module id for printing. * * There are three possible formats: * * MODULE_FORMAT_BRIEF is the brief 6-character format, including * the actual brick-type as recorded in the * moduleid_t, eg. 002c15 for a C-brick, or * 101#17 for a PX-brick. * * MODULE_FORMAT_LONG is the hwgraph format, eg. rack/002/bay/15 * of rack/101/bay/17 (note that the brick * type does not appear in this format). * * MODULE_FORMAT_LCD is like MODULE_FORMAT_BRIEF, except that it * ensures that the module id provided appears * exactly as it would on the LCD display of * the corresponding brick, eg. still 002c15 * for a C-brick, but 101p17 for a PX-brick. */ void format_module_id(char *buffer, moduleid_t m, int fmt) { int rack, position; unsigned char brickchar; rack = MODULE_GET_RACK(m); ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); brickchar = MODULE_GET_BTCHAR(m); if (fmt == MODULE_FORMAT_LCD) { /* Be sure we use the same brick type character as displayed * on the brick's LCD */ switch (brickchar) { case L1_BRICKTYPE_PX: brickchar = L1_BRICKTYPE_P; break; case L1_BRICKTYPE_IX: brickchar = L1_BRICKTYPE_I; break; } } position = MODULE_GET_BPOS(m); if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { /* Brief module number format, eg. 002c15 */ /* Decompress the rack number */ *buffer++ = '0' + RACK_GET_CLASS(rack); *buffer++ = '0' + RACK_GET_GROUP(rack); *buffer++ = '0' + RACK_GET_NUM(rack); /* Add the brick type */ *buffer++ = brickchar; } else if (fmt == MODULE_FORMAT_LONG) { /* Fuller hwgraph format, eg. rack/002/bay/15 */ strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer); *buffer++ = '0' + RACK_GET_CLASS(rack); *buffer++ = '0' + RACK_GET_GROUP(rack); *buffer++ = '0' + RACK_GET_NUM(rack); strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer); } /* Add the bay position, using at least two digits */ if (position < 10) *buffer++ = '0'; sprintf(buffer, "%d", position); } int cbrick_type_get_nasid(nasid_t nasid) { moduleid_t module; int t; module = iomoduleid_get(nasid); if (module < 0 ) { return MODULE_CBRICK; } t = MODULE_GET_BTYPE(module); if ((char)t == 'o') { return MODULE_OPUSBRICK; } else { return MODULE_CBRICK; } return -1; }