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

hwconfig.c

/*
 * $Id: hwconfig.c,v 1.1 2004/12/21 23:26:20 tjm Exp $
 *
 * This file is part of libconfig.
 * A library which provides a framework for managing system hardware
 * and software configuration information.
 *
 * Created by Silicon Graphics, Inc.
 *
 * Copyright (C) 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 <kl_lib.h>
#include <kl_hwconfig.h>

/*
 * alloc_hwcomponent()
 */
hwcomponent_t *
alloc_hwcomponent(hwconfig_t *hcp, int category, int type)
{
      int aflag;
        hwcomponent_t *hwcp;

        aflag = HWAFLG(hcp);
      hwcp = (hwcomponent_t *)kl_alloc_block(sizeof(hwcomponent_t), aflag);
      hwcp->hwconfig = hcp;
      hwcp->flags = hcp->flags;
      hwcp->category = category;
        hwcp->type = type;
      return(hwcp);
}

/*
 * dup_hwcomponent()
 */
hwcomponent_t *
dup_hwcomponent(hwcomponent_t *old)
{
      int aflag;
      hwconfig_t *hcp = old->hwconfig;
      hwcomponent_t *new;

      aflag = HWAFLG(hcp);
      new = (hwcomponent_t *)kl_dup_block((caddr_t *)old, aflag);

      if (old->location) {
            new->location = kl_get_string(hcp->st, old->location, aflag);
      }
      if (old->name) {
            new->name = kl_get_string(hcp->st, old->name, aflag);
      }
      if (old->serial_number) {
            new->serial_number = 
                  kl_get_string(hcp->st, old->serial_number, aflag);
      }
      if (old->part_number) {
            new->part_number = 
                  kl_get_string(hcp->st, old->part_number, aflag);
      }
      if (old->revision) {
            new->revision = kl_get_string(hcp->st, old->revision, aflag);
      }
      if (old->type_data) {
            new->type_data = kl_dup_block(old->type_data, aflag);
      }

      /* clear out some of the old links that no longer are valid
       */
      new->next = new->prev = new;
      new->cmplist = new->parent = (hwcomponent_t*)NULL;

      return(new);
}

/*
 * next_hwcmp()
 */
hwcomponent_t *
next_hwcmp(hwcomponent_t *hcp)
{
      return((hwcomponent_t *)kl_next_htnode((htnode_t *)hcp));
}

/*
 * prev_hwcmp()
 */
hwcomponent_t *
prev_hwcmp(hwcomponent_t *hcp)
{
      return((hwcomponent_t *)kl_prev_htnode((htnode_t *)hcp));
}

/*
 * hwcmp_insert_next()
 *
 * This function will add the next hardware component record to
 * a hwconfig htree. Note that in order for this function to work
 * properly, it is necessary that the level for each of the 
 * hw_component_s structs be filled in. 
 */
void
hwcmp_insert_next(hwcomponent_t *current, hwcomponent_t *next)
{
      ht_insert_next_htnode((htnode_t *)current, (htnode_t *)next);
}

/*
 * hwcmp_add_child()
 */
void
hwcmp_add_child(hwcomponent_t *cmp, hwcomponent_t *child)
{
      ht_insert_child((htnode_t *)cmp, (htnode_t *)child, HT_BEFORE);
}

/*
 * hwcmp_add_peer()
 */
void
hwcmp_add_peer(hwcomponent_t *cmp, hwcomponent_t *peer)
{
      ht_insert_peer((htnode_t *)cmp, (htnode_t *)peer, HT_AFTER);
}

/*
 * replace_hwcomponent()
 *
 * Replace an existing hwcomponent record with a new hardware
 * component record. Note that the sub-components of the existing
 * hwcomponenent are NOT switched over to the new hwcomponent. That
 * is because there is no garuantee that the sub-components are the
 * same. Also, this approach better allows the tracking of hardware 
 * component movement. It IS, however, necessary to adjust the parent 
 * pointer and possibly the component list pointer.
 */
void
replace_hwcomponent(hwcomponent_t *old, hwcomponent_t *new)
{
      if (old->next == old) {
            new->next = new->prev = new;
      } else {
            new->next = old->next;
            new->next->prev = new;
            new->prev = old->prev;
            new->prev->next = new;
      }

      /* Copy the parent pointer. If there was a parent and the old 
       * hwcomponent was the first item on the parent's sub-component 
       * list then we have to substitute the new pointer for the old 
       * pointer.
       */
      if ((new->parent = old->parent)) {
            if (new->parent->cmplist == old) {
                  new->parent->cmplist = new;
            }
      }
}

/*
 * insert_hwcomponent()
 */
void
insert_hwcomponent(hwcomponent_t *hwc1, hwcomponent_t *hwc2, int flag)
{
      if (flag == INSERT_AFTER) {
            hwc2->next = hwc1->next;
            hwc2->next->prev = hwc2;
            hwc1->next = hwc2;
            hwc2->prev = hwc1;
            hwc2->parent = hwc1->parent;
      } else {
            hwc2->prev = hwc1->prev;
            hwc2->prev->next = hwc2;
            hwc2->next = hwc1;
            hwc1->prev = hwc2;
            if ((hwc2->parent = hwc1->parent)) {
                  if (hwc2->parent->cmplist == hwc1) {
                        hwc2->parent->cmplist = hwc2;
                  }
            }
      }
}

/*
 * unlink_hwcomponent()
 */
void
unlink_hwcomponent(hwcomponent_t *hwc)
{
      if ((hwc->parent) && (hwc->parent->cmplist == hwc)) {
            if (hwc->next != hwc) {
                  hwc->parent->cmplist = hwc->next;
            } else {
                  hwc->parent->cmplist = (hwcomponent_t *)NULL;
            }
      }
      hwc->next->prev = hwc->prev;
      hwc->prev->next = hwc->next;
      hwc->next = hwc->prev = hwc;
}

/*
 * free_next_hwcmp()
 *
 * Recursively walk through the hwcomponent tree and free all blocks
 * of memory allocated for a hw_component_s structure, plus free any
 * private data structures associated.
 */
void
free_next_hwcmp(hwcomponent_t *hwcp)
{
      hwcomponent_t *cur, *next;


      cur = hwcp;
      do {
            if (cur->cmplist) {
                  free_next_hwcmp(cur->cmplist);
            }
            next = cur->next;

            /* Check and see if the strings in this hw_component_s 
             * struct had been allocated from a string table. If they 
             * have NOT, then they need to be freed up like all the 
             * rest of the blocks.
             */
            if (!(cur->flags & STRINGTAB_FLAG)) {
                  if (cur->location) {
                        kl_free_block(cur->location);
                  }
                  if (cur->name) {
                        kl_free_block(cur->name);
                  }
                  if (cur->serial_number) {
                        kl_free_block(cur->serial_number);
                  }
                  if (cur->part_number) {
                        kl_free_block(cur->part_number);
                  }
                  if (cur->revision) {
                        kl_free_block(cur->revision);
                  }
            }
            if (cur->type_data) {
                  kl_free_block(cur->type_data);
            }
            kl_free_block(cur);
            if (!(cur = next)) {
                  return;
            }
      } while(cur != hwcp);
}

/*
 * free_hwcomponents()
 */
void
free_hwcomponents(hwcomponent_t *hwcp)
{
      free_next_hwcmp(hwcp);
}

/*
 * hw_find_location()
 */
hwcomponent_t *
hw_find_location(hwcomponent_t *list, hwcomponent_t *hcp)
{
      hwcomponent_t *cp;

      cp = list;
      do {
            if (!compare_hwcomponents(cp, hcp)) {
                  /* The components are the same
                   */
                  return(cp);
            }
            if (kl_string_match(cp->location, hcp->location) &&
                        kl_string_match(cp->name, hcp->name)) {
                  return(cp);
            }
            cp = cp->next;
      } while (cp != list);

      return((hwcomponent_t *)NULL);
}

/*
 * hw_find_insert_point()
 */
hwcomponent_t *
hw_find_insert_point(hwcomponent_t *list, hwcomponent_t *hcp, int *flag)
{
      hwcomponent_t *cp;

      if (flag) {
            *flag = 0;
      }

      cp = list;
      do {
            if (hcp->location) {
                  if (!cp->location) {
                        cp = cp->next;
                        continue;
                  }
                  if (kl_string_compare(cp->location, 
                              hcp->location) > 0) {
                        if (cp != list) {
                              return(cp);
                        } else {
                              return(list);
                        }
                  }
            } else if (hcp->name) {
                  if (!cp->name) {
                        cp = cp->next;
                        continue;
                  }
                  if (kl_string_compare(cp->name, hcp->name) > 0) {
                        if (cp != list) {
                              return(cp);
                        } else {
                              return(list);
                        }
                  }
            }
            cp = cp->next;
      } while (cp != list);

      /* If we didn't find anyting, return the list pointer (the item
       * will be inserted at the end of the list).
       */
      if (flag) {
            *flag = INSERT_AFTER;
      }
      return(list->prev);
}

/*
 * compare_hwcomponents()
 */
int
compare_hwcomponents(hwcomponent_t *hwcp1, hwcomponent_t *hwcp2)
{
      /* We have to assuem that level is the same for each hw_component
       */

      if (!kl_string_match(hwcp1->location, hwcp2->location)) {
            return(1);
      }

      if (hwcp1->category != hwcp2->category) {
            return(1);
      }

      if (hwcp1->type != hwcp2->type) {
            return(1);
      }

      /* If we get to here, we prety much have the same type of
       * hw_component located in the same location. Now all we have to
       * do is compare serial_number, revision, etc. Note that if
       * a particular hw_component_s struct does not contain any of
       * this data, we don't consider it a failure (as long as
       * it is the same for both components).
       */
      if (!kl_string_match(hwcp1->serial_number, hwcp2->serial_number)) {
            return(1);
      }
      if (!kl_string_match(hwcp1->revision, hwcp2->revision)) {
            return(1);
      }
      if (!kl_string_match(hwcp1->part_number, hwcp2->part_number)) {
            return(1);
      }
      if (!kl_string_match(hwcp1->name, hwcp2->name)) {
            return(1);
      }

      /* If we get to here, then it either is the same component, or there
       * is not enough information in the record (e.g., serial number) to
       * tell if it is the same component or not. In such cases, we will
       * consider that it is the same.
       */
      return(0);
}

/*
 * kl_alloc_hwconfig()
 */
hwconfig_t *
kl_alloc_hwconfig(int flags)
{
      int flag = ((flags & K_PERM) ? K_PERM : K_TEMP);
      hwconfig_t *hcp;

      hcp = (hwconfig_t *)kl_alloc_block(sizeof(hwconfig_t), flag);
      if (flags & STRINGTAB_FLAG) {
            hcp->st = kl_init_string_table(flags);
      }
      hcp->flags = flags;
      return(hcp);
}

/*
 * kl_update_hwcomponent()
 *
 * Recursively walk through the hwcomponent tree and update all the
 * hw_component_s structs (set the node level).
 */
void
kl_update_hwcomponent(hwcomponent_t *hwcp)
{
      hwcomponent_t *cur;

      cur = hwcp;
      do {
            if (cur->parent) {
                  cur->level = cur->parent->level + 1;
            }
            if (cur->cmplist) {
                  kl_update_hwcomponent(cur->cmplist);
            }
            cur = cur->next;
      } while(cur != hwcp);
}

/*
 * kl_update_hwconfig()
 */
int
kl_update_hwconfig(hwconfig_t *hcp)
{
      hwcomponent_t *hwcp;

      if (hcp && (hwcp = hcp->hwcp_root)) {

            /* Set the level for each node
             */
            kl_update_hwcomponent(hwcp);

            /* Make sure that the sys_id for each hw_component matches the
             * one in the hwconfig_s struct. Also, update the count of
             * hw_component_s structs (after skipping over the root).
             */
            hcp->hwcp_count = 0;
            while ((hwcp = next_hwcmp(hwcp))) {
                  hwcp->sys_id = hcp->sys_id;
                  hcp->hwcp_count++;
            }
            return(0);
      }
      return(1);
}

/*
 * kl_free_hwconfig()
 */
void
kl_free_hwconfig(hwconfig_t *hcp)
{
      if (hcp) {
            if (hcp->hwcp_root) {
                  free_next_hwcmp(hcp->hwcp_root);
            }
            if (hcp->st) {
                  /* Free the string table
                   */
                  kl_free_string_table(hcp->st);
            }
            kl_free_block(hcp);
      }
}

Generated by  Doxygen 1.6.0   Back to index