diff options
Diffstat (limited to 'arch/ia64/sn/io/klconflib.c')
-rw-r--r-- | arch/ia64/sn/io/klconflib.c | 1334 |
1 files changed, 1334 insertions, 0 deletions
diff --git a/arch/ia64/sn/io/klconflib.c b/arch/ia64/sn/io/klconflib.c new file mode 100644 index 000000000..6fd745a0b --- /dev/null +++ b/arch/ia64/sn/io/klconflib.c @@ -0,0 +1,1334 @@ +/* $Id$ + * + * 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 Silicon Graphics, Inc. + * Copyright (C) 2000 by Colin Ngam + */ + + +#include <linux/types.h> +#include <linux/config.h> +#include <linux/ctype.h> +#include <asm/sn/sgi.h> +#include <asm/sn/iograph.h> +#include <asm/sn/invent.h> +#include <asm/sn/hcl.h> +#include <asm/sn/labelcl.h> + +#include <asm/sn/agent.h> +#include <asm/sn/klconfig.h> +#include <asm/sn/nodepda.h> +#include <asm/sn/module.h> +#include <asm/sn/router.h> +#include <asm/sn/xtalk/xbow.h> + +#define printf printk +int hasmetarouter; + +#define LDEBUG 0 +#define NIC_UNKNOWN ((nic_t) -1) + +#undef DEBUG_KLGRAPH +#ifdef DEBUG_KLGRAPH +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_KLGRAPH */ + +static void sort_nic_names(lboard_t *) ; + +lboard_t * +find_lboard(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(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_class(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(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)) { + printf("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, moduleid_t mod, slotid_t slot) +{ + /* Search all boards stored on this node. */ + while (start) { + if (MODULE_MATCH(start->brd_module, mod) && + (start->brd_slot == slot)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module(lboard_t *start, moduleid_t mod) +{ + /* Search all boards stored on this node. */ + while (start) { + if (MODULE_MATCH(start->brd_module, mod)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module_class(lboard_t *start, moduleid_t mod, + unsigned char brd_type) +{ + while (start) { + + DBG("find_lboard_module_class: lboard 0x%p, start->brd_module 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_module, mod, start->brd_type, brd_type); + + if (MODULE_MATCH(start->brd_module, mod) && + (KLCLASS(start->brd_type) == KLCLASS(brd_type))) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +#ifndef CONFIG_IA64_SGI_IO +#define tolower(c) (isupper(c) ? (c) - 'A' + 'a' : (c)) +#define toupper(c) (islower(c) ? (c) - 'a' + 'A' : (c)) +#endif + + +/* + * 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"); +#if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC) + else if (!strncmp(new_name, "ip29", 4)) + strcpy(new_name,SN00_MOTHERBOARD); +#endif + else if (!strncmp(new_name, "divo", 4)) + strcpy(new_name, "divo") ; + +} + +/* Check if the given board corresponds to the global + * master io6 + */ +int +is_master_baseio(nasid_t nasid,moduleid_t module,slotid_t slot) +{ + lboard_t *board; + +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC +/* BRINGUP: If this works then look for callers of is_master_baseio() + * (e.g. iograph.c) and let them pass in a slot if they want + */ + board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), module); +#else + board = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + module, slot); +#endif + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!board && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) +#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC + board = find_lboard_module((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + module); +#else + board = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + module, slot); +#endif + } +#endif + if (!board) + return(0); + return(board->brd_flags & GLOBAL_MASTER_IO6); +} +/* + * Find the lboard structure and get the board name. + * If we can't find the structure or it's too low a revision, + * use default name. + */ +lboard_t * +get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name) +{ + lboard_t *brd; + + brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + mod, slot); + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) + brd = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + mod, slot); + } +#endif + + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, name); + } + + /* + * PV # 540860 + * If the name is not 'baseio' or SN00 MOTHERBOARD + * get the lowest of all the names in the nic string. + * This is needed for boards like divo, which can have + * a bunch of daughter cards, but would like to be called + * divo. We could do this for baseio and SN00 MOTHERBOARD + * but it has some special case names that we would not + * like to disturb at this point. + */ + + /* gfx boards don't need any of this name scrambling */ + if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) { + return(brd); + } + + if (!(!strcmp(name, "baseio") )) { + if (brd) { + sort_nic_names(brd) ; + /* Convert to small case, '-' to '_' etc */ + nic_name_convert(brd->brd_name, name) ; + } + } + + return(brd); +} + +int +get_cpu_slice(cpuid_t cpu) +{ + klcpu_t *acpu; + if ((acpu = get_cpuinfo(cpu)) == NULL) + return -1; + return acpu->cpu_info.physid; +} + + +/* + * 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 + */ +#if SN0 + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8); +#else + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_PBRICK_XBOW); +#endif + 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; + + printf("xbow_port_io_enabled: brd 0x%p xbow_p 0x%p \n", brd, xbow_p); + + return 1; +} + +void +board_to_path(lboard_t *brd, char *path) +{ + moduleid_t modnum; + char *board_name; +#if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC) + slotid_t slot; + char slot_name[SLOTNUM_MAXLENGTH]; +#endif + + 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 + 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_PBRICK) + board_name = EDGE_LBL_PBRICK; + else if (brd->brd_type == KLTYPE_IBRICK) + board_name = EDGE_LBL_IBRICK; + else if (brd->brd_type == KLTYPE_XBRICK) + board_name = EDGE_LBL_XBRICK; + else + board_name = EDGE_LBL_IOBRICK; + break; + default: + board_name = EDGE_LBL_UNKNOWN; + } + + modnum = brd->brd_module; + +#if defined(SN0) + slot = brd->brd_slot; + get_slotname(slot, slot_name); + + ASSERT(modnum >= 0); + + sprintf(path, "%H/" EDGE_LBL_SLOT "/%s/%s", + modnum, slot_name, board_name); +#else + ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE); +#ifdef BRINGUP /* fix IP35 hwgraph */ + sprintf(path, EDGE_LBL_MODULE "/%x/%s", modnum, board_name); +#else + sprintf(path, "%H/%s", modnum, board_name); +#endif +#endif +} + +/* + * Get the module number for a NASID. + */ +moduleid_t +get_module_id(nasid_t nasid) +{ + lboard_t *brd; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + + if (!brd) + return INVALID_MODULE; + else + return brd->brd_module; +} + + +#ifndef CONFIG_IA64_SGI_IO +#if 1 +/* + * find_gfxpipe(#) + * + * XXXmacko + * This is only used by graphics drivers, and should be moved + * over to gfx/kern/graphics/SN0 as soon as it's convenient. + */ +static klgfx_t *graphics_pipe_list = NULL; +static devfs_handle_t hwgraph_all_gfxids = GRAPH_VERTEX_NONE; + +void +setup_gfxpipe_link(devfs_handle_t vhdl,int pipenum) +{ + char idbuf[8]; + extern graph_hdl_t hwgraph; + + graph_info_add_LBL(hwgraph, vhdl, INFO_LBL_GFXID, INFO_DESC_EXPORT, + (arbitrary_info_t)pipenum); + if (hwgraph_all_gfxids == GRAPH_VERTEX_NONE) + hwgraph_path_add(hwgraph_root, EDGE_LBL_GFX, &hwgraph_all_gfxids); + sprintf(idbuf, "%d", pipenum); + hwgraph_edge_add(hwgraph_all_gfxids, vhdl, idbuf); + +} +#endif + +/* + * find the pipenum'th logical graphics pipe (KLCLASS_GFX) + */ +lboard_t * +find_gfxpipe(int pipenum) +{ + gda_t *gdap; + cnodeid_t cnode; + nasid_t nasid; + lboard_t *lb; + klgfx_t *kg,**pkg; + int i; + + gdap = (gda_t *)GDA_ADDR(get_nasid()); + if (gdap->g_magic != GDA_MAGIC) + return NULL; + + if (!graphics_pipe_list) { + /* for all nodes */ + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + nasid = gdap->g_nasidtable[cnode]; + if (nasid == INVALID_NASID) + continue; + lb = KL_CONFIG_INFO(nasid) ; + while (lb = find_lboard_class(lb, KLCLASS_GFX)) { + moduleid_t kgm, pkgm; + int kgs, pkgs; + +#if defined(DEBUG) && (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1 || defined(CONFIG_IA64_GENERIC))) && defined(BRINGUP) + printf("find_gfxpipe(): PIPE: %s mod %M slot %d\n",lb?lb->brd_name:"!LBRD", + lb->brd_module,lb->brd_slot); +#endif + /* insert lb into list */ + if (!(kg = (klgfx_t*)find_first_component(lb,KLSTRUCT_GFX))) { + lb = KLCF_NEXT(lb); + continue; + } + /* set moduleslot now that we have brd_module set */ + kg->moduleslot = (lb->brd_module << 8) | SLOTNUM_GETSLOT(lb->brd_slot); + /* make sure board has device flag set */ + kg->gfx_info.flags |= KLINFO_DEVICE; + if (kg->cookie < KLGFX_COOKIE) { + kg->gfx_next_pipe = NULL; + kg->cookie = KLGFX_COOKIE; + } + + kgm = kg->moduleslot>>8; + kgs = kg->moduleslot&0xff; + pkg = &graphics_pipe_list; + while (*pkg) { + pkgm = (*pkg)->moduleslot>>8; + pkgs = (*pkg)->moduleslot&0xff; + + if (!(MODULE_CMP(kgm, pkgm) > 0 || + (MODULE_CMP(kgm, pkgm) == 0 && + kgs > pkgs))) + break; + + pkg = &(*pkg)->gfx_next_pipe; + } + kg->gfx_next_pipe = *pkg; + *pkg = kg; + lb = KLCF_NEXT(lb); + } + } +#ifdef FIND_GFXPIPE_DEBUG + i = 0; + kg = graphics_pipe_list; + while (kg) { + lboard_t *lb; +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + lb = find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX); +#else +#error Need to figure out how to find graphics boards ... +#endif +#if defined(SUPPORT_PRINTING_M_FORMAT) + printf("find_gfxpipe(): %s pipe %d mod %M slot %d\n",lb?lb->brd_name:"!LBRD",i, + (kg->moduleslot>>8),(kg->moduleslot&0xff)); +#else + printf("find_gfxpipe(): %s pipe %d mod 0x%x slot %d\n",lb?lb->brd_name:"!LBRD",i, + (kg->moduleslot>>8),(kg->moduleslot&0xff)); +#endif + kg = kg->gfx_next_pipe; + i++; + } +#endif + } + + i = 0; + kg = graphics_pipe_list; + while (kg && (i < pipenum)) { + kg = kg->gfx_next_pipe; + i++; + } + + if (!kg) return NULL; + +#if defined(SN0) + return find_lboard_modslot(KL_CONFIG_INFO(kg->gfx_info.nasid), + (kg->moduleslot>>8), + SLOTNUM_XTALK_CLASS|(kg->moduleslot&0xff)); +#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + return find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX); +#else +#error Need to figure out how to find graphics boards ... +#endif +} +#endif + + +#define MHZ 1000000 + +#ifndef CONFIG_IA64_SGI_IO +uint +cpu_cycles_adjust(uint orig_cycles) +{ + klcpu_t *acpu; + uint speed; + + acpu = nasid_slice_to_cpuinfo(get_nasid(), get_slice()); + + if (acpu == NULL) return orig_cycles; + + /* + * cpu cycles seem to be half of the real value, hack and mult by 2 + * for now. + */ + speed = (orig_cycles * 2) / MHZ; + + /* + * if the cpu thinks its running at some random speed nowhere close + * the programmed speed, do nothing. + */ + if ((speed < (acpu->cpu_speed - 2)) || (speed > (acpu->cpu_speed + 2))) + return orig_cycles; + return (acpu->cpu_speed * MHZ/2); +} +#endif /* CONFIG_IA64_SGI_IO */ + +/* Get the canonical hardware graph name for the given pci component + * on the given io board. + */ +void +device_component_canonical_name_get(lboard_t *brd, + klinfo_t *component, + char *name) +{ + moduleid_t modnum; + slotid_t slot; + char board_name[20]; +#ifdef SN0 + char slot_name[SLOTNUM_MAXLENGTH]; +#endif + + ASSERT(brd); + + /* Get the module number of this board */ + modnum = brd->brd_module; + + /* Convert the [ CLASS | TYPE ] kind of slotid + * into a string + */ + slot = brd->brd_slot; +#ifdef SN0 + get_slotname(slot, slot_name); + + ASSERT(modnum >= 0); +#else + ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE); +#endif + + /* Get the io board name */ + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, board_name); + } + + /* Give out the canonical name of the pci device*/ +#ifdef SN0 + sprintf(name, + "/hw/"EDGE_LBL_MODULE "/%M/"EDGE_LBL_SLOT"/%s/%s/" + EDGE_LBL_PCI"/%d", + modnum, slot_name, board_name,KLCF_BRIDGE_W_ID(component)); +#elif defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLOT"/%s/" + EDGE_LBL_PCI"/%d", + modnum, board_name,KLCF_BRIDGE_W_ID(component)); +#endif + +} + +/* + * 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:<serial_number>;* + */ +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, +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + "IP35")) +#else + "IP27")) + /* Try with IP31 key if IP27 key fails */ + if (component_serial_number_get(board, + hub->hub_mfg_nic, + serial_number, + "IP31")) +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + return(1); + break; + } + case KLCLASS_IO: { /* IO board */ + if (KLTYPE(board->brd_type) == KLTYPE_TPU) { + /* Special case for TPU boards */ + kltpu_t *tpu; + + /* Get the tpu component information */ + tpu = (kltpu_t *)find_first_component(board, + KLSTRUCT_TPU); + /* If we don't have a tpu component on a tpu board + * then we have a weird klconfig. + */ + if (!tpu) + return(1); + /* Get the serial number information from + * the tpu's manufacturing nic info + */ + if (component_serial_number_get(board, + tpu->tpu_mfg_nic, + serial_number, + "")) + return(1); + break; + } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) || + (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) { + /* Special case for GSN boards */ + klgsn_t *gsn; + + /* Get the gsn component information */ + gsn = (klgsn_t *)find_first_component(board, + ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ? + KLSTRUCT_GSN_A : KLSTRUCT_GSN_B)); + /* If we don't have a gsn component on a gsn board + * then we have a weird klconfig. + */ + if (!gsn) + return(1); + /* Get the serial number information from + * the gsn's manufacturing nic info + */ + if (component_serial_number_get(board, + gsn->gsn_mfg_nic, + serial_number, + "")) + return(1); + break; + } else { + 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); +} + +#include "asm/sn/sn_private.h" +#ifndef CONFIG_IA64_SGI_IO +/* + * Given a physical address get the name of memory dimm bank + * in a hwgraph name format. + */ +void +membank_pathname_get(paddr_t paddr,char *name) +{ + cnodeid_t cnode; + char slotname[SLOTNUM_MAXLENGTH]; + + cnode = paddr_cnode(paddr); + /* Make sure that we have a valid name buffer */ + if (!name) + return; + + name[0] = 0; + /* Make sure that the cnode is valid */ + if ((cnode == CNODEID_NONE) || (cnode > numnodes)) + return; + /* Given a slotid(class:type) get the slotname */ +#if defined (SN0) + get_slotname(NODE_SLOTID(cnode),slotname); + sprintf(name, + "/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_SLOT"/%s/"EDGE_LBL_NODE + "/"EDGE_LBL_MEMORY"/dimm_bank/%d", + NODE_MODULEID(cnode),slotname,paddr_dimm(paddr)); +#elif defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_NODE + "/"EDGE_LBL_MEMORY"/dimm_bank/%d", + NODE_MODULEID(cnode),paddr_dimm(paddr)); +#endif +} + + + +int +membank_check_mixed_hidensity(nasid_t nasid) +{ + lboard_t *brd; + klmembnk_t *mem; + int min_size = 1024, max_size = 0; + int bank, mem_size; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + ASSERT(brd); + + mem = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); + ASSERT(mem); + + + for (mem_size = 0, bank = 0; bank < MD_MEM_BANKS; bank++) { + mem_size = KLCONFIG_MEMBNK_SIZE(mem, bank); + if (mem_size < min_size) + min_size = mem_size; + if (mem_size > max_size) + max_size = mem_size; + } + + if ((max_size == 512) && (max_size != min_size)) + return 1; + + return 0; +} + + +int +mem_mixed_hidensity_banks(void) +{ + cnodeid_t cnode; + nasid_t nasid; + + for (cnode = 0; cnode < maxnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + if (nasid == INVALID_NASID) + continue; + if (membank_check_mixed_hidensity(nasid)) + return 1; + } + return 0; + +} +#endif /* CONFIG_IA64_SGI_IO */ + +xwidgetnum_t +nodevertex_widgetnum_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + return(hubinfo_p->h_widgetid); +} + +devfs_handle_t +nodevertex_xbow_peer_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + nasid_t xbow_peer_nasid; + cnodeid_t xbow_peer; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer; + if(xbow_peer_nasid == INVALID_NASID) + return ( (devfs_handle_t)-1); + xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid); + return(NODEPDA(xbow_peer)->node_vertex); +} + +/* NIC Sorting Support */ + +#define MAX_NICS_PER_STRING 32 +#define MAX_NIC_NAME_LEN 32 + +static char * +get_nic_string(lboard_t *lb) +{ + int i; + klinfo_t *k = NULL ; + klconf_off_t mfg_off = 0 ; + char *mfg_nic = NULL ; + + for (i = 0; i < KLCF_NUM_COMPS(lb); i++) { + k = KLCF_COMP(lb, i) ; + switch(k->struct_type) { + case KLSTRUCT_BRI: + mfg_off = ((klbri_t *)k)->bri_mfg_nic ; + break ; + + case KLSTRUCT_HUB: + mfg_off = ((klhub_t *)k)->hub_mfg_nic ; + break ; + + case KLSTRUCT_ROU: + mfg_off = ((klrou_t *)k)->rou_mfg_nic ; + break ; + + case KLSTRUCT_GFX: + mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ; + break ; + + case KLSTRUCT_TPU: + mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ; + break ; + + case KLSTRUCT_GSN_A: + case KLSTRUCT_GSN_B: + mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ; + break ; + + case KLSTRUCT_XTHD: + mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ; + break; + + default: + mfg_off = 0 ; + break ; + } + if (mfg_off) + break ; + } + + if ((mfg_off) && (k)) + mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ; + + return mfg_nic ; +} + +char * +get_first_string(char **ptrs, int n) +{ + int i ; + char *tmpptr ; + + if ((ptrs == NULL) || (n == 0)) + return NULL ; + + tmpptr = ptrs[0] ; + + if (n == 1) + return tmpptr ; + + for (i = 0 ; i < n ; i++) { + if (strcmp(tmpptr, ptrs[i]) > 0) + tmpptr = ptrs[i] ; + } + + return tmpptr ; +} + +int +get_ptrs(char *idata, char **ptrs, int n, char *label) +{ + int i = 0 ; + char *tmp = idata ; + + if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0)) + return 0 ; + + while ( (tmp = strstr(tmp, label)) ){ + tmp += strlen(label) ; + /* check for empty name field, and last NULL ptr */ + if ((i < (n-1)) && (*tmp != ';')) { + ptrs[i++] = tmp ; + } + } + + ptrs[i] = NULL ; + + return i ; +} + +/* + * sort_nic_names + * + * Does not really do sorting. Find the alphabetically lowest + * name among all the nic names found in a nic string. + * + * Return: + * Nothing + * + * Side Effects: + * + * lb->brd_name gets the new name found + */ + +static void +sort_nic_names(lboard_t *lb) +{ + char *nic_str ; + char *ptrs[MAX_NICS_PER_STRING] ; + char name[MAX_NIC_NAME_LEN] ; + char *tmp, *tmp1 ; + + *name = 0 ; + + /* Get the nic pointer from the lb */ + + if ((nic_str = get_nic_string(lb)) == NULL) + return ; + + tmp = get_first_string(ptrs, + get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ; + + if (tmp == NULL) + return ; + + if ( (tmp1 = strchr(tmp, ';')) ){ + strncpy(name, tmp, tmp1-tmp) ; + name[tmp1-tmp] = 0 ; + } else { + strncpy(name, tmp, (sizeof(name) -1)) ; + name[sizeof(name)-1] = 0 ; + } + + strcpy(lb->brd_name, name) ; +} + + +#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) + +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdp789012345"; + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + int rack, position; + char brickchar; + + rack = MODULE_GET_RACK(m); + ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); + brickchar = MODULE_GET_BTCHAR(m); + position = MODULE_GET_BPOS(m); + + if (fmt == MODULE_FORMAT_BRIEF) { + /* 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); + +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + * The long form does not include a brick type, so it defaults to 0 (CBrick) + */ +int +parse_module_id(char *buffer) +{ + unsigned int v, rack, bay, type, form; + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) { + form = MODULE_FORMAT_LONG; + buffer += strlen(EDGE_LBL_RACK "/"); + + /* A long module ID must be exactly 5 non-template chars. */ + if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5) + return -1; + } + else { + form = MODULE_FORMAT_BRIEF; + + /* A brief module id must be exactly 6 characters */ + if (strlen(buffer) != 6) + return -2; + } + + /* The rack number must be exactly 3 digits */ + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2]))) + return -3; + + rack = 0; + v = *buffer++ - '0'; + if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) + return -4; + RACK_ADD_CLASS(rack, v); + + v = *buffer++ - '0'; + if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) + return -5; + RACK_ADD_GROUP(rack, v); + + v = *buffer++ - '0'; + /* rack numbers are 1-based */ + if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) + return -6; + RACK_ADD_NUM(rack, v); + + if (form == MODULE_FORMAT_BRIEF) { + /* Next should be a module type character. Accept ucase or lcase. */ + c = *buffer++; + if (!isalpha(c)) + return -7; + + /* strchr() returns a pointer into brick_types[], or NULL */ + type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types); + if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT) + return -8; + } + else { + /* Hardcode the module type, and skip over the boilerplate */ + type = MODULE_CBRICK; + + if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer) + return -9; + + buffer += strlen("/" EDGE_LBL_RPOS "/"); + } + + /* The bay number is last. Make sure it's exactly two digits */ + + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2])) + return -10; + + bay = 10 * (buffer[0] - '0') + (buffer[1] - '0'); + + if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) + return -11; + + m = RBT_TO_MODULE(rack, bay, type); + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} + +#else /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + if (fmt == MODULE_FORMAT_BRIEF) { + sprintf(buffer, "%d", m); + } + else if (fmt == MODULE_FORMAT_LONG) { + sprintf(buffer, EDGE_LBL_MODULE "/%d", m); + } +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + */ +int +parse_module_id(char *buffer) +{ + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_MODULE "/") == buffer) + buffer += strlen(EDGE_LBL_MODULE "/"); + + m = 0; + while(c = *buffer++) { + if (!isdigit(c)) + return -1; + m = 10 * m + (c - '0'); + } + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} + +#endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */ + + |