Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

sn2_hwconfig.c

/*
 * $Id: sn2_hwconfig.c,v 1.1 2004/12/21 23:26:20 tjm Exp $
 *
 * This file is part of libhwconfig.
 * A library which provides access to Linux system kernel dumps.
 *
 * Created by Silicon Graphics, Inc.
 *
 * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */
#include <klib.h>
#include <kl_config.h>
#include <kl_libhwconfig.h>

#define MODULE_CBRICK   1
#define MODULE_RBRICK   2
#define MODULE_PXBRICK  3
#define MODULE_IXBRICK  4

/* External function prototypes
 */
int init_hwgraph(int);
int kl_pci_init(void);
int init_ia64_cpuinfo(void);

/*
 * get_rack_name()
 */
static int
get_rack_name(char *modname, char *buf, int bufsz)
{
      char *c;

      if (!buf || (bufsz < 10)) {
            return(1);
      }
      c = modname;
      while (*c) {
            if (*c == 0) {
                  return(1);
            }
            if (isdigit(*c)) {
                  break;
            }
            c++;
      }
      if (*c == 0) {
            return(1);
      }
      strcpy (buf, "RACK_");
      strncat (buf, c, 3);
      return(0);
}

/*
 * get_rack()
 */
static hwcomponent_t *
get_rack(hwconfig_t *hcp, char *modname)
{
      char rack_name[10];
      hwcomponent_t *first_rackp, *rackp = (hwcomponent_t *)NULL;

      if (!modname) {
            return((hwcomponent_t *)NULL);
      }

      /* The root hwcomponent is the system record. If we don't have
       * one, there can't be any racks.
       */
      if (!hcp->hwcp_root) {
            return((hwcomponent_t *)NULL);
      }
      if (get_rack_name(modname, rack_name, 10)) {
            return((hwcomponent_t *)NULL);
      }

      if ((first_rackp = hcp->hwcp_root->cmplist)) {

            /* Cycle through the existing rack structures and
             * see if we find a match.
             */
            rackp = first_rackp;
            do {
                  if (!strcmp(rackp->name, rack_name)) {
                        break;
                  }
                  rackp = rackp->next;
            } while (rackp != first_rackp);
      }
      if (!rackp) {
            rackp = alloc_hwcomponent(hcp, HW_RACK, RACK_UNKNOWN);
            rackp->name = kl_get_string(hcp->st, rack_name, HWAFLG(hcp));
            hwcmp_add_child(hcp->hwcp_root, rackp);
      }
      return(rackp);
}

/* 
 * get_IXbrick_info()
 */
static int
get_IXbrick_info(hwcomponent_t *ixbp)
{
      char slot_name[10], *DevName;
      kaddr_t info;
      pci_dev_t *pci_dev;
      pci_vendor_t *pven;
      pci_device_t *pdev;
      hwconfig_t *hcp = ixbp->hwconfig;
      hwcomponent_t *bmp;
      vertex_t *pcixp, *busvp, *slotvp, *boardvp;

      if (!(pcixp = kl_find_vertex((vertex_t *)ixbp->arch, "pci-x"))) {
            return(1);
      }
      busvp = (vertex_t *)pcixp->v_children;
      while (busvp) {
            slotvp = (vertex_t *)busvp->v_children;
            while (slotvp) {
                  if (!strcmp(slotvp->name, "controller")) {
                              goto next;
                  }
                  if (!strcmp(slotvp->name, "direct")) {
                              goto next;
                  }
                  /* We should now have a slot number for an
                   * installed device.
                   */
                  boardvp = (vertex_t *)slotvp->v_children;
                  while(boardvp) {
                        if (!strcmp(boardvp->name, "config")) {
                              break;
                        }
                        boardvp = (vertex_t *)boardvp->v_next;
                        if (boardvp == FIRST_CHILD(boardvp)) {
                              break;
                        }
                  }
                  if (boardvp) {
                        if (!(info = kl_vertex_info_addr(boardvp))) {
                              goto next;
                        }
                        if ((pci_dev = find_pci_dev(info))) {
                              pven = find_pci_vendor(pci_dev->vendor);
                              pdev = find_pci_device(pci_dev->vendor,
                                    pci_dev->device);

                              /* If for some reason, we don't locate
                               * a pci device record, set the device
                               * name to be UNK_PCI_DEVNAME.
                               */
                              if (pdev) {
                                    DevName = pdev->DevName;
                              } else {
                                    DevName = UNK_PCI_DEVNAME;
                              }

                              bmp = alloc_hwcomponent(hcp, 
                                    HW_BOARD, BD_IO);
                              bmp->arch = (void *)boardvp;

                              bmp->name = kl_get_string(hcp->st, 
                                    DevName, HWAFLG(hcp));
                              sprintf(slot_name, "%02d.%02d.%d", 
                                    pci_dev->bus_num,
                                    pci_dev->slot_num,
                                    pci_dev->fun_num);
                              bmp->location = kl_get_string(hcp->st, 
                                    slot_name, HWAFLG(hcp));
                              hwcmp_add_child(ixbp, bmp);
                        }
                  }
next:
                  slotvp = (vertex_t *)slotvp->v_next;
                  if (slotvp == FIRST_CHILD(slotvp)) {
                        break;      
                  }
            }
                busvp = (vertex_t*)busvp->v_next;
                if (busvp == FIRST_CHILD(busvp)) {
                        break;
                }
        }
      return(0);
}

/* 
 * get_Rbrick_info()
 */
static int
get_Rbrick_info(hwcomponent_t *mp)
{
#ifdef NOTYET
      vertex_t *vp = (vertex_t *)mp->arch;
#endif
      return(0);
}

/*
 * get_cpu_info()
 */
static void
get_cpu_info(vertex_t *vp, hwcomponent_t *mp)
{
      int cpuid = -1;
      hwconfig_t *hcp = mp->hwconfig;
      hwcomponent_t *nmp;
      vertex_label_t *vlabelp;
      char cpuname[12];

      nmp = alloc_hwcomponent(hcp, HW_CPU, CPU_INTEL_IA64);
      nmp->arch = (void *)vp;
      if ((vlabelp = kl_vertex_label(vp, "_cpuid"))) {
            cpuid = vlabelp->info;
            kl_free_vertex_label(vlabelp);
      }
      if (cpuid >= 0) {
            sprintf(cpuname, "CPU_%d", cpuid);
      } else {
            cpuname[0] = 0;
            sprintf(cpuname, "CPU_%c", vp->name[0]);
      }
      nmp->name = kl_get_string(hcp->st, cpuname, HWAFLG(hcp));
      hwcmp_add_child(mp, nmp);
}

/*
 * get_node_info()
 */
static void
get_node_info(vertex_t *vp, hwcomponent_t *mp)
{
      int nodeid = -1;
      hwconfig_t *hcp = mp->hwconfig;
      hwcomponent_t *nmp;
      vertex_label_t *vlabelp;
      vertex_t *cpubus_vp, *cbusnum_vp, *cpu_vp;
      char nodename[12];

      nmp = alloc_hwcomponent(hcp, HW_BOARD, BD_PROCESSOR);
      nmp->arch = (void *)vp;
      if ((vlabelp = kl_vertex_label(vp, "_cnodeid"))) {
            nodeid = vlabelp->info;
            kl_free_vertex_label(vlabelp);
      }
      if (nodeid >= 0) {
            sprintf(nodename, "NODE_%d", nodeid);
      } else {
            nodename[0] = 0;
            strcat(nodename, "NODE");
      }
      nmp->name = kl_get_string(hcp->st, nodename, HWAFLG(hcp));

      /* Now get the cpu info
       */
      cpubus_vp = (vertex_t *)vp->v_children;
      while (cpubus_vp) {
            if (!strcmp(cpubus_vp->name, "cpubus")) {
                  break;
            }
            cpubus_vp = (vertex_t*)cpubus_vp->v_next;
            if (cpubus_vp == FIRST_CHILD(cpubus_vp)) {
                  /* XXX -- error message */
                  return;
            }
      }

      cbusnum_vp = (vertex_t *)cpubus_vp->v_children;
      while (cbusnum_vp) {
            /* There should only be one bus, but we
             * cycle through just in case...
             */
            cpu_vp = (vertex_t *)cbusnum_vp->v_children;
            while (cpu_vp) {
                  get_cpu_info(cpu_vp, nmp);
                  cpu_vp = (vertex_t*)cpu_vp->v_next;
                  if (cpu_vp == FIRST_CHILD(cpu_vp)) {
                        break;
                  }
            }
            cbusnum_vp = (vertex_t*)cbusnum_vp->v_next;
            if (cbusnum_vp == FIRST_CHILD(cbusnum_vp)) {
                  break;
            }
      }
      hwcmp_add_child(mp, nmp);
}

/* 
 * get_Cbrick_info()
 */
static int
get_Cbrick_info(hwcomponent_t *mp)
{
      hwconfig_t *hcp = mp->hwconfig;
      vertex_t *vp = (vertex_t *)mp->arch;
      vertex_t *cvp, *svp, *nvp;
      hwcomponent_t *nmp;
      
      /* Locate the various C-brick sub-components
       */
      cvp = (vertex_t *)vp->v_children;
      while (cvp) {
            if (!strcmp(cvp->name, "L1")) {
                  nmp = alloc_hwcomponent(hcp, HW_MODULE, MODULE_UNKNOWN);
                  nmp->name = kl_get_string(hcp->st, 
                        cvp->name, HWAFLG(hcp));
                  nmp->arch = (void *)cvp; 
                  hwcmp_add_child(mp, nmp);
            } else if (!strcmp(cvp->name, "slab")) {
                  /* Cycle through the slabs in this module and
                   * get the node information.
                   */
                  svp = (vertex_t *)cvp->v_children;
                  while (svp) {
                        nvp = (vertex_t *)svp->v_children;
                        while (nvp) {
                              if (!strcmp(nvp->name, "node")) {
                                    get_node_info(nvp, mp);
                                    break;
                              }
                              nvp = (vertex_t*)nvp->v_next;
                              if (nvp == FIRST_CHILD(nvp)) {
                                    break;
                              }
                        }
                        svp = (vertex_t*)svp->v_next;
                        if (svp == FIRST_CHILD(svp)) {
                              break;
                        }
                  }
            } else {
                  /* ??? */
            }
            cvp = (vertex_t*)cvp->v_next;
            if (cvp == FIRST_CHILD(cvp)) {
                  break;
            }     
      }
      return(0);
}

/*
 * module_type()
 */
int
module_type(char *name)
{
      int type;

      if (!name) {
            return((char)0);
      }
      switch (name[3]) {
            case 'c': 
                  type = MODULE_CBRICK;
                  break;
            case 'r': 
                  type = MODULE_RBRICK;
                  break;
            default:
                  type = MODULE_UNKNOWN;
      }
      return(type);
}

/*
 * _get_sn2_hwconfig()
 */
static int
_get_sn2_hwconfig(hwconfig_t *hcp)
{
      vertex_t *vp, *module;
      hwcomponent_t *rp, *mp, *ixbp, *rackp;
      char modname[24];

      if (!(vp = kl_find_vertex(NULL, "module"))) {
            return(1);
      }
      hcp->hwcp_root = alloc_hwcomponent(hcp, HW_SYSTEM, 0);
      module = (vertex_t *)vp->v_children;

      /* Cycle through the modules in the hwgraph. Note that,
       * at this time, only C-bricks and R-bricks are detectable
       * this way. In order to locate PX-bricks and IX-bricks,
       * it's necessary to walk down into the node path...
       */
      while (module) {
            mp = alloc_hwcomponent(hcp, HW_MODULE, MODULE_UNKNOWN);
            modname[0] = 0;
            strcat(modname, "MODULE_");
            strcat(modname, module->name);
            mp->name = kl_get_string(hcp->st, modname, HWAFLG(hcp));
            mp->arch = (void *)module; 
            if (module_type(module->name) == MODULE_CBRICK) {
                  get_Cbrick_info(mp);
            } else if (module_type(module->name) == MODULE_RBRICK) {
                  get_Rbrick_info(mp);
            }
            rackp = get_rack(hcp, modname);
            hwcmp_add_child(rackp, mp);
            module = (vertex_t *)module->v_next;
            if (module == (vertex_t *)vp->v_children) {
                  break;
            }
      }

      /* We now need to check each of the C-brick modules to see if
       * they are attached to a PX-brick or an IX-brick. We walk 
       * through each rack, walking through each module in the rack.
       */
      rp = hcp->hwcp_root->cmplist;
      do {
            mp = rp->cmplist;
            do {
                  module = (vertex_t *)mp->arch;
                  /* XXX -- For now, check for both IXbrick, PXbrick,
                   *        and Pbrick names in the hwgraph. The Pbrick 
                   *        name will need to be removed eventually.
                   */
                  if (!(vp = kl_find_vertex(module, "IXbrick"))) {
                        if (!(vp = kl_find_vertex(module, "PXbrick"))) {
                              vp = kl_find_vertex(module, "Pbrick");
                        }
                  }
                  if (vp) {
                        /* XXX -- We need to see if this is a PXbrick
                         * or an IXbrick.
                         */
                        strcpy(modname, "MODULE_");
                        strcat(modname, vp->name);
                        ixbp = alloc_hwcomponent(hcp, HW_MODULE, MODULE_UNKNOWN);
                        ixbp->name = kl_get_string(hcp->st, 
                              modname, HWAFLG(hcp));
                        ixbp->arch = (void *)vp; 
                        get_IXbrick_info(ixbp);
                        hwcmp_add_child(rp, ixbp);
                        mp = ixbp->next;
                  } else {
                        mp = mp->next;
                  }
            } while (mp != rp->cmplist);
            rp = rp->next;
      } while (rp != hcp->hwcp_root->cmplist);

      return(0);
}

/* 
 * init_sn2_hwconfig()
 */
int
init_sn2_hwconfig(void)
{
#ifdef NOTYET
      if (init_hwgraph(0)) {
            return(1);
      }
      if (init_ia64_cpuinfo()) {
            return(1);
      }
      if (kl_pci_init()) {
            return(1);
      }
#else
      init_hwgraph(0);
      init_ia64_cpuinfo();
      kl_pci_init();
#endif
      return(0);
}

/* 
 * get_sn2_hwconfig()
 */
hwconfig_t *
get_sn2_hwconfig(int flags)
{
      hwconfig_t *hcp;

      hcp = kl_alloc_hwconfig(flags|STRINGTAB_FLAG);
      if (_get_sn2_hwconfig(hcp)) {
            kl_free_hwconfig(hcp);
            return((hwconfig_t *)NULL);
      }
      return(hcp);
}

Generated by  Doxygen 1.6.0   Back to index