linux-old/arch/ia64/sn/io/sn2/klconflib.c
<<
>>
Prefs
   1/* $Id$
   2 *
   3 * This file is subject to the terms and conditions of the GNU General Public
   4 * License.  See the file "COPYING" in the main directory of this archive
   5 * for more details.
   6 *
   7 * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
   8 */
   9
  10
  11#include <linux/types.h>
  12#include <linux/ctype.h>
  13#include <asm/sn/sgi.h>
  14#include <asm/sn/sn_sal.h>
  15#include <asm/sn/io.h>
  16#include <asm/sn/sn_cpuid.h>
  17#include <asm/sn/iograph.h>
  18#include <asm/sn/invent.h>
  19#include <asm/sn/hcl.h>
  20#include <asm/sn/labelcl.h>
  21#include <asm/sn/klconfig.h>
  22#include <asm/sn/nodepda.h>
  23#include <asm/sn/module.h>
  24#include <asm/sn/router.h>
  25#include <asm/sn/xtalk/xbow.h>
  26
  27
  28#define LDEBUG 0
  29#define NIC_UNKNOWN ((nic_t) -1)
  30
  31#undef DEBUG_KLGRAPH
  32#ifdef DEBUG_KLGRAPH
  33#define DBG(x...) printk(x)
  34#else
  35#define DBG(x...)
  36#endif /* DEBUG_KLGRAPH */
  37
  38u64 klgraph_addr[MAX_COMPACT_NODES];
  39static int hasmetarouter;
  40
  41
  42char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo2345";
  43
  44lboard_t *
  45find_lboard(lboard_t *start, unsigned char brd_type)
  46{
  47        /* Search all boards stored on this node. */
  48        while (start) {
  49                if (start->brd_type == brd_type)
  50                        return start;
  51                start = KLCF_NEXT(start);
  52        }
  53
  54        /* Didn't find it. */
  55        return (lboard_t *)NULL;
  56}
  57
  58lboard_t *
  59find_lboard_class(lboard_t *start, unsigned char brd_type)
  60{
  61        /* Search all boards stored on this node. */
  62        while (start) {
  63                if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
  64                        return start;
  65                start = KLCF_NEXT(start);
  66        }
  67
  68        /* Didn't find it. */
  69        return (lboard_t *)NULL;
  70}
  71
  72klinfo_t *
  73find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
  74{
  75        int index, j;
  76
  77        if (kli == (klinfo_t *)NULL) {
  78                index = 0;
  79        } else {
  80                for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
  81                        if (kli == KLCF_COMP(brd, j))
  82                                break;
  83                }
  84                index = j;
  85                if (index == KLCF_NUM_COMPS(brd)) {
  86                        DBG("find_component: Bad pointer: 0x%p\n", kli);
  87                        return (klinfo_t *)NULL;
  88                }
  89                index++;        /* next component */
  90        }
  91        
  92        for (; index < KLCF_NUM_COMPS(brd); index++) {          
  93                kli = KLCF_COMP(brd, index);
  94                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));
  95                if (KLCF_COMP_TYPE(kli) == struct_type)
  96                        return kli;
  97        }
  98
  99        /* Didn't find it. */
 100        return (klinfo_t *)NULL;
 101}
 102
 103klinfo_t *
 104find_first_component(lboard_t *brd, unsigned char struct_type)
 105{
 106        return find_component(brd, (klinfo_t *)NULL, struct_type);
 107}
 108
 109lboard_t *
 110find_lboard_modslot(lboard_t *start, geoid_t geoid)
 111{
 112        /* Search all boards stored on this node. */
 113        while (start) {
 114                if (geo_cmp(start->brd_geoid, geoid))
 115                        return start;
 116                start = KLCF_NEXT(start);
 117        }
 118
 119        /* Didn't find it. */
 120        return (lboard_t *)NULL;
 121}
 122
 123lboard_t *
 124find_lboard_module(lboard_t *start, geoid_t geoid)
 125{
 126        /* Search all boards stored on this node. */
 127        while (start) {
 128                if (geo_cmp(start->brd_geoid, geoid))
 129                        return start;
 130                start = KLCF_NEXT(start);
 131        }
 132
 133        /* Didn't find it. */
 134        return (lboard_t *)NULL;
 135}
 136
 137/*
 138 * Convert a NIC name to a name for use in the hardware graph.
 139 */
 140void
 141nic_name_convert(char *old_name, char *new_name)
 142{
 143        int i;
 144        char c;
 145        char *compare_ptr;
 146
 147        if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
 148                strcpy(new_name, EDGE_LBL_XWIDGET);
 149        } else {
 150                for (i = 0; i < strlen(old_name); i++) {
 151                        c = old_name[i];
 152
 153                        if (isalpha(c))
 154                                new_name[i] = tolower(c);
 155                        else if (isdigit(c))
 156                                new_name[i] = c;
 157                        else
 158                                new_name[i] = '_';
 159                }
 160                new_name[i] = '\0';
 161        }
 162
 163        /* XXX -
 164         * Since a bunch of boards made it out with weird names like
 165         * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
 166         * replace it with "baseio" to avoid confusion in the field.
 167         * We also have to make sure we don't report media_io instead of
 168         * baseio.
 169         */
 170
 171        /* Skip underscores at the beginning of the name */
 172        for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
 173                ;
 174
 175        /*
 176         * Check for some names we need to replace.  Early boards
 177         * had junk following the name so check only the first
 178         * characters.
 179         */
 180        if (!strncmp(new_name, "io6", 3) || 
 181            !strncmp(new_name, "mio", 3) || 
 182            !strncmp(new_name, "media_io", 8))
 183                strcpy(new_name, "baseio");
 184        else if (!strncmp(new_name, "divo", 4))
 185                strcpy(new_name, "divo") ;
 186
 187}
 188
 189/*
 190 * get_actual_nasid
 191 *
 192 *      Completely disabled brds have their klconfig on 
 193 *      some other nasid as they have no memory. But their
 194 *      actual nasid is hidden in the klconfig. Use this
 195 *      routine to get it. Works for normal boards too.
 196 */
 197nasid_t
 198get_actual_nasid(lboard_t *brd)
 199{
 200        klhub_t *hub ;
 201
 202        if (!brd)
 203                return INVALID_NASID ;
 204
 205        /* find out if we are a completely disabled brd. */
 206
 207        hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
 208        if (!hub)
 209                return INVALID_NASID ;
 210        if (!(hub->hub_info.flags & KLINFO_ENABLE))     /* disabled node brd */
 211                return hub->hub_info.physid ;
 212        else
 213                return brd->brd_nasid ;
 214}
 215
 216int
 217xbow_port_io_enabled(nasid_t nasid, int link)
 218{
 219        lboard_t *brd;
 220        klxbow_t *xbow_p;
 221
 222        /*
 223         * look for boards that might contain an xbow or xbridge
 224         */
 225        brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
 226        if (brd == NULL) return 0;
 227                
 228        if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
 229            == NULL)
 230            return 0;
 231
 232        if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
 233            return 0;
 234
 235        return 1;
 236}
 237
 238void
 239board_to_path(lboard_t *brd, char *path)
 240{
 241        moduleid_t modnum;
 242        char *board_name;
 243        char buffer[16];
 244
 245        ASSERT(brd);
 246
 247        switch (KLCLASS(brd->brd_type)) {
 248
 249                case KLCLASS_NODE:
 250                        board_name = EDGE_LBL_NODE;
 251                        break;
 252                case KLCLASS_ROUTER:
 253                        if (brd->brd_type == KLTYPE_META_ROUTER) {
 254                                board_name = EDGE_LBL_META_ROUTER;
 255                                hasmetarouter++;
 256                        } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
 257                                board_name = EDGE_LBL_REPEATER_ROUTER;
 258                                hasmetarouter++;
 259                        } else
 260                                board_name = EDGE_LBL_ROUTER;
 261                        break;
 262                case KLCLASS_MIDPLANE:
 263                        board_name = EDGE_LBL_MIDPLANE;
 264                        break;
 265                case KLCLASS_IO:
 266                        board_name = EDGE_LBL_IO;
 267                        break;
 268                case KLCLASS_IOBRICK:
 269                        if (brd->brd_type == KLTYPE_PXBRICK)
 270                                board_name = EDGE_LBL_PXBRICK;
 271                        else if (brd->brd_type == KLTYPE_IXBRICK)
 272                                board_name = EDGE_LBL_IXBRICK;
 273                        else if (brd->brd_type == KLTYPE_PBRICK)
 274                                board_name = EDGE_LBL_PBRICK;
 275                        else if (brd->brd_type == KLTYPE_IBRICK)
 276                                board_name = EDGE_LBL_IBRICK;
 277                        else if (brd->brd_type == KLTYPE_XBRICK)
 278                                board_name = EDGE_LBL_XBRICK;
 279                        else if (brd->brd_type == KLTYPE_PEBRICK)
 280                                board_name = EDGE_LBL_PEBRICK;
 281                        else if (brd->brd_type == KLTYPE_OPUSBRICK)
 282                                board_name = EDGE_LBL_OPUSBRICK;
 283                        else if (brd->brd_type == KLTYPE_CGBRICK)
 284                                board_name = EDGE_LBL_CGBRICK;
 285                        else
 286                                board_name = EDGE_LBL_IOBRICK;
 287                        break;
 288                default:
 289                        board_name = EDGE_LBL_UNKNOWN;
 290        }
 291                        
 292        modnum = geo_module(brd->brd_geoid);
 293        memset(buffer, 0, 16);
 294        format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
 295        sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
 296}
 297
 298#define MHZ     1000000
 299
 300
 301/* Get the canonical hardware graph name for the given pci component
 302 * on the given io board.
 303 */
 304void
 305device_component_canonical_name_get(lboard_t    *brd,
 306                                    klinfo_t    *component,
 307                                    char        *name)
 308{
 309        slotid_t        slot;
 310        char            board_name[20];
 311
 312        ASSERT(brd);
 313
 314        /* Convert the [ CLASS | TYPE ] kind of slotid
 315         * into a string
 316         */
 317        slot = brd->brd_slot;
 318
 319        /* Get the io board name  */
 320        if (!brd || (brd->brd_sversion < 2)) {
 321                strcpy(name, EDGE_LBL_XWIDGET);
 322        } else {
 323                nic_name_convert(brd->brd_name, board_name);
 324        }
 325
 326        /* Give out the canonical  name of the pci device*/
 327        sprintf(name,
 328                "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
 329                EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
 330                geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), 
 331                board_name, KLCF_BRIDGE_W_ID(component));
 332}
 333
 334/*
 335 * Get the serial number of the main  component of a board
 336 * Returns 0 if a valid serial number is found
 337 * 1 otherwise.
 338 * Assumptions: Nic manufacturing string  has the following format
 339 *                      *Serial:<serial_number>;*
 340 */
 341static int
 342component_serial_number_get(lboard_t            *board,
 343                            klconf_off_t        mfg_nic_offset,
 344                            char                *serial_number,
 345                            char                *key_pattern)
 346{
 347
 348        char    *mfg_nic_string;
 349        char    *serial_string,*str;
 350        int     i;
 351        char    *serial_pattern = "Serial:";
 352
 353        /* We have an error on a null mfg nic offset */
 354        if (!mfg_nic_offset)
 355                return(1);
 356        /* Get the hub's manufacturing nic information
 357         * which is in the form of a pre-formatted string
 358         */
 359        mfg_nic_string = 
 360                (char *)NODE_OFFSET_TO_K0(NASID_GET(board),
 361                                          mfg_nic_offset);
 362        /* There is no manufacturing nic info */
 363        if (!mfg_nic_string)
 364                return(1);
 365
 366        str = mfg_nic_string;
 367        /* Look for the key pattern first (if it is  specified)
 368         * and then print the serial number corresponding to that.
 369         */
 370        if (strcmp(key_pattern,"") && 
 371            !(str = strstr(mfg_nic_string,key_pattern)))
 372                return(1);
 373
 374        /* There is no serial number info in the manufacturing
 375         * nic info
 376         */
 377        if (!(serial_string = strstr(str,serial_pattern)))
 378                return(1);
 379
 380        serial_string = serial_string + strlen(serial_pattern);
 381        /*  Copy the serial number information from the klconfig */
 382        i = 0;
 383        while (serial_string[i] != ';') {
 384                serial_number[i] = serial_string[i];
 385                i++;
 386        }
 387        serial_number[i] = 0;
 388        
 389        return(0);
 390}
 391/*
 392 * Get the serial number of a board
 393 * Returns 0 if a valid serial number is found
 394 * 1 otherwise.
 395 */
 396
 397int
 398board_serial_number_get(lboard_t *board,char *serial_number)
 399{
 400        ASSERT(board && serial_number);
 401        if (!board || !serial_number)
 402                return(1);
 403
 404        strcpy(serial_number,"");
 405        switch(KLCLASS(board->brd_type)) {
 406        case KLCLASS_CPU: {     /* Node board */
 407                klhub_t *hub;
 408
 409                if (board->brd_type == KLTYPE_TIO) {
 410                        printk("*****board_serial_number_get: Need to support TIO.*****\n");
 411                        strcpy(serial_number,"");
 412                        return(0);
 413                }
 414                
 415                /* Get the hub component information */
 416                hub = (klhub_t *)find_first_component(board,
 417                                                      KLSTRUCT_HUB);
 418                /* If we don't have a hub component on an IP27
 419                 * then we have a weird klconfig.
 420                 */
 421                if (!hub)
 422                        return(1);
 423                /* Get the serial number information from
 424                 * the hub's manufacturing nic info
 425                 */
 426                if (component_serial_number_get(board,
 427                                                hub->hub_mfg_nic,
 428                                                serial_number,
 429                                                "IP37"))
 430                                return(1);
 431                break;
 432        }
 433        case KLCLASS_IO: {      /* IO board */
 434                if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
 435                /* Special case for TPU boards */
 436                        kltpu_t *tpu;   
 437                
 438                        /* Get the tpu component information */
 439                        tpu = (kltpu_t *)find_first_component(board,
 440                                                      KLSTRUCT_TPU);
 441                        /* If we don't have a tpu component on a tpu board
 442                         * then we have a weird klconfig.
 443                         */
 444                        if (!tpu)
 445                                return(1);
 446                        /* Get the serial number information from
 447                         * the tpu's manufacturing nic info
 448                         */
 449                        if (component_serial_number_get(board,
 450                                                tpu->tpu_mfg_nic,
 451                                                serial_number,
 452                                                ""))
 453                                return(1);
 454                        break;
 455                } else  if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
 456                            (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
 457                /* Special case for GSN boards */
 458                        klgsn_t *gsn;   
 459                
 460                        /* Get the gsn component information */
 461                        gsn = (klgsn_t *)find_first_component(board,
 462                              ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
 463                                        KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
 464                        /* If we don't have a gsn component on a gsn board
 465                         * then we have a weird klconfig.
 466                         */
 467                        if (!gsn)
 468                                return(1);
 469                        /* Get the serial number information from
 470                         * the gsn's manufacturing nic info
 471                         */
 472                        if (component_serial_number_get(board,
 473                                                gsn->gsn_mfg_nic,
 474                                                serial_number,
 475                                                ""))
 476                                return(1);
 477                        break;
 478                } else {
 479                        klbri_t *bridge;
 480                
 481                        /* Get the bridge component information */
 482                        bridge = (klbri_t *)find_first_component(board,
 483                                                         KLSTRUCT_BRI);
 484                        /* If we don't have a bridge component on an IO board
 485                         * then we have a weird klconfig.
 486                         */
 487                        if (!bridge)
 488                                return(1);
 489                        /* Get the serial number information from
 490                         * the bridge's manufacturing nic info
 491                         */
 492                        if (component_serial_number_get(board,
 493                                                bridge->bri_mfg_nic,
 494                                                serial_number,
 495                                                ""))
 496                                return(1);
 497                        break;
 498                }
 499        }
 500        case KLCLASS_ROUTER: {  /* Router board */
 501                klrou_t *router;        
 502                
 503                /* Get the router component information */
 504                router = (klrou_t *)find_first_component(board,
 505                                                         KLSTRUCT_ROU);
 506                /* If we don't have a router component on a router board
 507                 * then we have a weird klconfig.
 508                 */
 509                if (!router)
 510                        return(1);
 511                /* Get the serial number information from
 512                 * the router's manufacturing nic info
 513                 */
 514                if (component_serial_number_get(board,
 515                                                router->rou_mfg_nic,
 516                                                serial_number,
 517                                                ""))
 518                        return(1);
 519                break;
 520        }
 521        case KLCLASS_GFX: {     /* Gfx board */
 522                klgfx_t *graphics;
 523                
 524                /* Get the graphics component information */
 525                graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
 526                /* If we don't have a gfx component on a gfx board
 527                 * then we have a weird klconfig.
 528                 */
 529                if (!graphics)
 530                        return(1);
 531                /* Get the serial number information from
 532                 * the graphics's manufacturing nic info
 533                 */
 534                if (component_serial_number_get(board,
 535                                                graphics->gfx_mfg_nic,
 536                                                serial_number,
 537                                                ""))
 538                        return(1);
 539                break;
 540        }
 541        default:
 542                strcpy(serial_number,"");
 543                break;
 544        }
 545        return(0);
 546}
 547
 548#include "asm/sn/sn_private.h"
 549
 550/*
 551 * Format a module id for printing.
 552 */
 553void
 554format_module_id(char *buffer, moduleid_t m, int fmt)
 555{
 556        int rack, position;
 557        char brickchar;
 558
 559        rack = MODULE_GET_RACK(m);
 560        ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
 561        brickchar = MODULE_GET_BTCHAR(m);
 562
 563        position = MODULE_GET_BPOS(m);
 564
 565        if (fmt == MODULE_FORMAT_BRIEF) {
 566            /* Brief module number format, eg. 002c15 */
 567
 568            /* Decompress the rack number */
 569            *buffer++ = '0' + RACK_GET_CLASS(rack);
 570            *buffer++ = '0' + RACK_GET_GROUP(rack);
 571            *buffer++ = '0' + RACK_GET_NUM(rack);
 572
 573            /* Add the brick type */
 574            *buffer++ = brickchar;
 575        }
 576        else if (fmt == MODULE_FORMAT_LONG) {
 577            /* Fuller hwgraph format, eg. rack/002/bay/15 */
 578
 579            strcpy(buffer, EDGE_LBL_RACK "/");  buffer += strlen(buffer);
 580
 581            *buffer++ = '0' + RACK_GET_CLASS(rack);
 582            *buffer++ = '0' + RACK_GET_GROUP(rack);
 583            *buffer++ = '0' + RACK_GET_NUM(rack);
 584
 585            strcpy(buffer, "/" EDGE_LBL_RPOS "/");  buffer += strlen(buffer);
 586        }
 587
 588        /* Add the bay position, using at least two digits */
 589        if (position < 10)
 590            *buffer++ = '0';
 591        sprintf(buffer, "%d", position);
 592
 593}
 594
 595/*
 596 * Parse a module id, in either brief or long form.
 597 * Returns < 0 on error.
 598 * The long form does not include a brick type, so it defaults to 0 (CBrick)
 599 */
 600int
 601parse_module_id(char *buffer)
 602{
 603        unsigned int    v, rack, bay, type, form;
 604        moduleid_t      m;
 605        char            c;
 606
 607        if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
 608                form = MODULE_FORMAT_LONG;
 609                buffer += strlen(EDGE_LBL_RACK "/");
 610
 611                /* A long module ID must be exactly 5 non-template chars. */
 612                if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
 613                        return -1;
 614        }
 615        else {
 616                form = MODULE_FORMAT_BRIEF;
 617
 618                /* A brief module id must be exactly 6 characters */
 619                if (strlen(buffer) != 6)
 620                        return -2;
 621        }
 622
 623        /* The rack number must be exactly 3 digits */
 624        if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
 625                return -3;
 626
 627        rack = 0;
 628        v = *buffer++ - '0';
 629        if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
 630                return -4;
 631        RACK_ADD_CLASS(rack, v);
 632
 633        v = *buffer++ - '0';
 634        if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
 635                return -5;
 636        RACK_ADD_GROUP(rack, v);
 637
 638        v = *buffer++ - '0';
 639        /* rack numbers are 1-based */
 640        if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
 641                return -6;
 642        RACK_ADD_NUM(rack, v);
 643
 644        if (form == MODULE_FORMAT_BRIEF) {
 645                /* Next should be a module type character.  Accept ucase or lcase. */
 646                c = *buffer++;
 647                if (!isalpha(c))
 648                        return -7;
 649
 650                /* strchr() returns a pointer into brick_types[], or NULL */
 651                type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
 652                if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
 653                        return -8;
 654        }
 655        else {
 656                /* Hardcode the module type, and skip over the boilerplate */
 657                type = MODULE_CBRICK;
 658
 659                if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
 660                        return -9;
 661
 662                buffer += strlen("/" EDGE_LBL_RPOS "/");
 663        }
 664                
 665        /* The bay number is last.  Make sure it's exactly two digits */
 666
 667        if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
 668                return -10;
 669
 670        bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
 671
 672        if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
 673                return -11;
 674
 675        m = RBT_TO_MODULE(rack, bay, type);
 676
 677        /* avoid sign extending the moduleid_t */
 678        return (int)(unsigned short)m;
 679}
 680
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.