1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <libxml/parser.h>
  30 #include <fm/libtopo.h>
  31 #include <topo_alloc.h>
  32 #include <topo_error.h>
  33 #include <topo_parse.h>
  34 #include <topo_subr.h>
  35 
  36 tf_info_t *
  37 tf_info_new(topo_mod_t *mp, xmlDocPtr doc, xmlChar *scheme)
  38 {
  39         tf_info_t *r;
  40 
  41         if ((r = topo_mod_zalloc(mp, sizeof (tf_info_t))) == NULL)
  42                 return (NULL);
  43         r->tf_flags = TF_LIVE;
  44         if ((r->tf_scheme = topo_mod_strdup(mp, (char *)scheme)) == NULL) {
  45                 tf_info_free(mp, r);
  46                 return (NULL);
  47         }
  48         r->tf_xdoc = doc;
  49         return (r);
  50 }
  51 
  52 void
  53 tf_info_free(topo_mod_t *mp, tf_info_t *p)
  54 {
  55         if (p->tf_xdoc != NULL)
  56                 xmlFreeDoc(p->tf_xdoc);
  57         if (p->tf_scheme != NULL)
  58                 topo_mod_strfree(mp, p->tf_scheme);
  59         tf_rdata_free(mp, p->tf_rd);
  60         topo_mod_free(mp, p, sizeof (tf_info_t));
  61 }
  62 
  63 tf_rdata_t *
  64 tf_rdata_new(topo_mod_t *mp, tf_info_t *xinfo, xmlNodePtr n, tnode_t *troot)
  65 {
  66         tf_rdata_t *r;
  67         uint64_t ui;
  68         xmlChar *name = NULL;
  69 
  70         topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new rdata\n");
  71         if ((r = topo_mod_zalloc(mp, sizeof (tf_rdata_t))) == NULL) {
  72                 (void) topo_mod_seterrno(mp, ETOPO_NOMEM);
  73                 return (NULL);
  74         }
  75         r->rd_pn = troot;
  76         if ((name = xmlGetProp(n, (xmlChar *)Name)) == NULL) {
  77                 (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
  78                 goto rdata_nogood;
  79         }
  80         if ((r->rd_name = topo_mod_strdup(mp, (char *)name)) == NULL) {
  81                 (void) topo_mod_seterrno(mp, ETOPO_NOMEM);
  82                 goto rdata_nogood;
  83         }
  84         if (xmlattr_to_int(mp, n, Min, &ui) < 0)
  85                 goto rdata_nogood;
  86         r->rd_min = (int)ui;
  87         if (xmlattr_to_int(mp, n, Max, &ui) < 0)
  88                 goto rdata_nogood;
  89         r->rd_max = (int)ui;
  90         if (r->rd_min < 0 || r->rd_max < 0 || r->rd_max < r->rd_min) {
  91                 (void) topo_mod_seterrno(mp, ETOPO_PRSR_BADRNG);
  92                 goto rdata_nogood;
  93         }
  94         r->rd_finfo = xinfo;
  95         r->rd_mod = mp;
  96 
  97         if (topo_xml_range_process(mp, n, r) < 0)
  98                 goto rdata_nogood;
  99 
 100         xmlFree(name);
 101         return (r);
 102 
 103 rdata_nogood:
 104         if (name != NULL)
 105                 xmlFree(name);
 106         tf_rdata_free(mp, r);
 107         return (NULL);
 108 }
 109 
 110 void
 111 tf_rdata_free(topo_mod_t *mp, tf_rdata_t *p)
 112 {
 113         if (p == NULL)
 114                 return;
 115         tf_rdata_free(mp, p->rd_next);
 116         if (p->rd_name != NULL)
 117                 topo_mod_strfree(mp, p->rd_name);
 118         tf_edata_free(mp, p->rd_einfo);
 119         tf_idata_free(mp, p->rd_instances);
 120         tf_pad_free(mp, p->rd_pad);
 121         topo_mod_free(mp, p, sizeof (tf_rdata_t));
 122 }
 123 
 124 tf_idata_t *
 125 tf_idata_new(topo_mod_t *mp, topo_instance_t i, tnode_t *tn)
 126 {
 127         tf_idata_t *r;
 128 
 129         topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new idata %d\n", i);
 130         if ((r = topo_mod_zalloc(mp, sizeof (tf_idata_t))) == NULL)
 131                 return (NULL);
 132         r->ti_tn = tn;
 133         r->ti_i = i;
 134         return (r);
 135 }
 136 
 137 void
 138 tf_idata_free(topo_mod_t *mp, tf_idata_t *p)
 139 {
 140         if (p == NULL)
 141                 return;
 142         tf_idata_free(mp, p->ti_next);
 143         tf_pad_free(mp, p->ti_pad);
 144         topo_mod_free(mp, p, sizeof (tf_idata_t));
 145 }
 146 
 147 int
 148 tf_idata_insert(tf_idata_t **head, tf_idata_t *ni)
 149 {
 150         tf_idata_t *l, *p;
 151 
 152         p = NULL;
 153         for (l = *head; l != NULL; l = l->ti_next) {
 154                 if (ni->ti_i < l->ti_i)
 155                         break;
 156                 p = l;
 157         }
 158         ni->ti_next = l;
 159         if (p == NULL)
 160                 *head = ni;
 161         else
 162                 p->ti_next = ni;
 163         return (0);
 164 }
 165 
 166 tf_idata_t *
 167 tf_idata_lookup(tf_idata_t *head, topo_instance_t i)
 168 {
 169         tf_idata_t *f;
 170         for (f = head; f != NULL; f = f->ti_next)
 171                 if (i == f->ti_i)
 172                         break;
 173         return (f);
 174 }
 175 
 176 tf_pad_t *
 177 tf_pad_new(topo_mod_t *mp, int pcnt, int dcnt)
 178 {
 179         tf_pad_t *r;
 180 
 181         topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new pad p=%d, d=%d\n",
 182             pcnt, dcnt);
 183         if ((r = topo_mod_zalloc(mp, sizeof (tf_pad_t))) == NULL)
 184                 return (NULL);
 185         r->tpad_pgcnt = pcnt;
 186         r->tpad_dcnt = dcnt;
 187         return (r);
 188 }
 189 
 190 void
 191 tf_pad_free(topo_mod_t *mp, tf_pad_t *p)
 192 {
 193         int n;
 194         if (p == NULL)
 195                 return;
 196         if (p->tpad_pgs != NULL) {
 197                 for (n = 0; n < p->tpad_pgcnt; n++)
 198                         if (p->tpad_pgs[n] != NULL)
 199                                 nvlist_free(p->tpad_pgs[n]);
 200                 topo_mod_free(mp,
 201                     p->tpad_pgs, p->tpad_pgcnt * sizeof (nvlist_t *));
 202         }
 203         tf_rdata_free(mp, p->tpad_child);
 204         tf_rdata_free(mp, p->tpad_sibs);
 205         topo_mod_free(mp, p, sizeof (tf_pad_t));
 206 }
 207 
 208 void
 209 tf_edata_free(topo_mod_t *mp, tf_edata_t *p)
 210 {
 211         if (p == NULL)
 212                 return;
 213         if (p->te_name != NULL)
 214                 xmlFree(p->te_name);
 215         topo_mod_free(mp, p, sizeof (tf_edata_t));
 216 }