1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <picl.h>
30*7c478bd9Sstevel@tonic-gate #include <syslog.h>
31*7c478bd9Sstevel@tonic-gate #include <strings.h>
32*7c478bd9Sstevel@tonic-gate #include <alloca.h>
33*7c478bd9Sstevel@tonic-gate #include <pthread.h>
34*7c478bd9Sstevel@tonic-gate #include <synch.h>
35*7c478bd9Sstevel@tonic-gate #include <limits.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <picltree.h>
39*7c478bd9Sstevel@tonic-gate #include <signal.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
42*7c478bd9Sstevel@tonic-gate #include <libnvpair.h>
43*7c478bd9Sstevel@tonic-gate #include "fru_tag.h"
44*7c478bd9Sstevel@tonic-gate #include "fru_data_impl.h"
45*7c478bd9Sstevel@tonic-gate #include "fru_data.h"
46*7c478bd9Sstevel@tonic-gate #include "picld_pluginutil.h"
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #pragma	init(frudata_plugin_register) /* .init section */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate static	void		frudata_plugin_init(void);
51*7c478bd9Sstevel@tonic-gate static	void		frudata_plugin_fini(void);
52*7c478bd9Sstevel@tonic-gate static	container_tbl_t *container_table[TABLE_SIZE];
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * Locking Stragtegy :
56*7c478bd9Sstevel@tonic-gate  * calling thread should hold the cont_tbl_lock during the course
57*7c478bd9Sstevel@tonic-gate  * of container table lookup. release the cont_tbl_lock on lookup
58*7c478bd9Sstevel@tonic-gate  * failure or on the condition wait.
59*7c478bd9Sstevel@tonic-gate  *
60*7c478bd9Sstevel@tonic-gate  * thread holding the container object rwlock should release lock
61*7c478bd9Sstevel@tonic-gate  * and signal to unblock threads blocked on the condition variable
62*7c478bd9Sstevel@tonic-gate  * upon i/o completion.
63*7c478bd9Sstevel@tonic-gate  *
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate static pthread_mutex_t	cont_tbl_lock = PTHREAD_MUTEX_INITIALIZER;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate static int add_row_to_table(hash_obj_t *, picl_nodehdl_t,
69*7c478bd9Sstevel@tonic-gate 				packet_t *, container_tbl_t *);
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static picld_plugin_reg_t frudata_reg_info = {
72*7c478bd9Sstevel@tonic-gate 		PICLD_PLUGIN_VERSION_1,
73*7c478bd9Sstevel@tonic-gate 		PICLD_PLUGIN_NON_CRITICAL,
74*7c478bd9Sstevel@tonic-gate 		"SUNW_piclfrudata",
75*7c478bd9Sstevel@tonic-gate 		frudata_plugin_init,	/* init entry point */
76*7c478bd9Sstevel@tonic-gate 		frudata_plugin_fini	/* cleanup entry point */
77*7c478bd9Sstevel@tonic-gate };
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /* initialization function */
80*7c478bd9Sstevel@tonic-gate static void
81*7c478bd9Sstevel@tonic-gate frudata_plugin_register(void)
82*7c478bd9Sstevel@tonic-gate {
83*7c478bd9Sstevel@tonic-gate 	/* register plugin with daemon */
84*7c478bd9Sstevel@tonic-gate 	if (picld_plugin_register(&frudata_reg_info) != PICL_SUCCESS) {
85*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "SUNW_piclfrudata plugin registration failed");
86*7c478bd9Sstevel@tonic-gate 	}
87*7c478bd9Sstevel@tonic-gate }
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate static int
90*7c478bd9Sstevel@tonic-gate map_access_err(int err)
91*7c478bd9Sstevel@tonic-gate {
92*7c478bd9Sstevel@tonic-gate 	switch (err) {
93*7c478bd9Sstevel@tonic-gate 	case	ENFILE	:
94*7c478bd9Sstevel@tonic-gate 		return (PICL_PROPEXISTS);
95*7c478bd9Sstevel@tonic-gate 	case	EAGAIN	:
96*7c478bd9Sstevel@tonic-gate 		return (PICL_NOSPACE);
97*7c478bd9Sstevel@tonic-gate 	case	EPERM	:
98*7c478bd9Sstevel@tonic-gate 		return (PICL_PERMDENIED);
99*7c478bd9Sstevel@tonic-gate 	case	EEXIST	:
100*7c478bd9Sstevel@tonic-gate 		return (PICL_PROPEXISTS);
101*7c478bd9Sstevel@tonic-gate 	default	:
102*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
103*7c478bd9Sstevel@tonic-gate 	}
104*7c478bd9Sstevel@tonic-gate }
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate /*
107*7c478bd9Sstevel@tonic-gate  * unlock_container_lock() should be always called by the thread holding the
108*7c478bd9Sstevel@tonic-gate  * container object lock. it will signal block thread waiting on the condition
109*7c478bd9Sstevel@tonic-gate  * variable.
110*7c478bd9Sstevel@tonic-gate  */
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate static void
113*7c478bd9Sstevel@tonic-gate unlock_container_lock(container_tbl_t	*cont_hash)
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&cont_hash->rwlock);
116*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&cont_tbl_lock);
117*7c478bd9Sstevel@tonic-gate 	(void) pthread_cond_signal(&cont_hash->cond_var);
118*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&cont_tbl_lock);
119*7c478bd9Sstevel@tonic-gate }
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /* volatile callback read routine */
123*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
124*7c478bd9Sstevel@tonic-gate static int
125*7c478bd9Sstevel@tonic-gate frudata_read_callback(ptree_rarg_t *rarg, void *buf)
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate  * called to get hash object for specified node and object type from
132*7c478bd9Sstevel@tonic-gate  * hash table.
133*7c478bd9Sstevel@tonic-gate  */
134*7c478bd9Sstevel@tonic-gate static container_tbl_t *
135*7c478bd9Sstevel@tonic-gate lookup_container_table(picl_nodehdl_t nodehdl, int object_type)
136*7c478bd9Sstevel@tonic-gate {
137*7c478bd9Sstevel@tonic-gate 	int		index_to_hash;
138*7c478bd9Sstevel@tonic-gate 	int		retval = PICL_SUCCESS;
139*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*first_hash;
140*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*next_hash;
141*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	parenthdl = 0;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	switch (object_type) {
144*7c478bd9Sstevel@tonic-gate 	case	SECTION_NODE:
145*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(nodehdl, PICL_PROP_PARENT,
146*7c478bd9Sstevel@tonic-gate 			&parenthdl, sizeof (picl_nodehdl_t));
147*7c478bd9Sstevel@tonic-gate 		break;
148*7c478bd9Sstevel@tonic-gate 	case	SEGMENT_NODE:
149*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(nodehdl, PICL_PROP_PARENT,
150*7c478bd9Sstevel@tonic-gate 			&parenthdl, sizeof (picl_nodehdl_t));
151*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(parenthdl, PICL_PROP_PARENT,
152*7c478bd9Sstevel@tonic-gate 			&parenthdl, sizeof (picl_nodehdl_t));
153*7c478bd9Sstevel@tonic-gate 		break;
154*7c478bd9Sstevel@tonic-gate 	case	CONTAINER_NODE :
155*7c478bd9Sstevel@tonic-gate 		parenthdl = nodehdl;
156*7c478bd9Sstevel@tonic-gate 		break;
157*7c478bd9Sstevel@tonic-gate 	default	:
158*7c478bd9Sstevel@tonic-gate 		return (NULL);
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
162*7c478bd9Sstevel@tonic-gate 		return (NULL);
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	index_to_hash	= (parenthdl % TABLE_SIZE);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	first_hash	= container_table[index_to_hash];
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	for (next_hash = first_hash; next_hash != NULL;
170*7c478bd9Sstevel@tonic-gate 				next_hash = next_hash->next) {
171*7c478bd9Sstevel@tonic-gate 		if (parenthdl == next_hash->picl_hdl) {
172*7c478bd9Sstevel@tonic-gate 			return (next_hash);
173*7c478bd9Sstevel@tonic-gate 		}
174*7c478bd9Sstevel@tonic-gate 	}
175*7c478bd9Sstevel@tonic-gate 	return (NULL);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate static int
179*7c478bd9Sstevel@tonic-gate lock_readwrite_lock(container_tbl_t *cont_obj, int operation)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	/* if write operation */
182*7c478bd9Sstevel@tonic-gate 	if (operation == PICL_WRITE) {
183*7c478bd9Sstevel@tonic-gate 		return (pthread_rwlock_trywrlock(&cont_obj->rwlock));
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 	/* read operation */
186*7c478bd9Sstevel@tonic-gate 	return (pthread_rwlock_tryrdlock(&cont_obj->rwlock));
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * lock the container table, do lookup for the container object
191*7c478bd9Sstevel@tonic-gate  * in the container table. if container object found try to lock
192*7c478bd9Sstevel@tonic-gate  * the container object, if lock on container object is busy wait
193*7c478bd9Sstevel@tonic-gate  * on condition variable till the thread holding the container
194*7c478bd9Sstevel@tonic-gate  * object lock signal it.
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate static container_tbl_t *
198*7c478bd9Sstevel@tonic-gate lock_container_lock(picl_nodehdl_t nodehdl, int object_type, int operation)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_obj = NULL;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&cont_tbl_lock);
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	while (((cont_obj = lookup_container_table(nodehdl, object_type)) !=
205*7c478bd9Sstevel@tonic-gate 		NULL) && (lock_readwrite_lock(cont_obj, operation) == EBUSY)) {
206*7c478bd9Sstevel@tonic-gate 		pthread_cond_wait(&cont_obj->cond_var, &cont_tbl_lock);
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&cont_tbl_lock);
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	return (cont_obj);
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate static hash_obj_t *
215*7c478bd9Sstevel@tonic-gate lookup_node_object(picl_nodehdl_t nodehdl, int	object_type,
216*7c478bd9Sstevel@tonic-gate 					container_tbl_t *cont_tbl)
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	int		index_to_hash;
219*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*first_hash;
220*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_hash;
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	index_to_hash	= (nodehdl % TABLE_SIZE);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	first_hash	= &cont_tbl->hash_obj[index_to_hash];
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	for (next_hash = first_hash->next; next_hash != NULL;
228*7c478bd9Sstevel@tonic-gate 				next_hash = next_hash->next) {
229*7c478bd9Sstevel@tonic-gate 		if ((nodehdl == next_hash->picl_hdl) &&
230*7c478bd9Sstevel@tonic-gate 			(object_type == next_hash->object_type)) {
231*7c478bd9Sstevel@tonic-gate 			return (next_hash);
232*7c478bd9Sstevel@tonic-gate 		}
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 	return (NULL);
235*7c478bd9Sstevel@tonic-gate }
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate /*
238*7c478bd9Sstevel@tonic-gate  * called to add newly created container hash table into container hash table.
239*7c478bd9Sstevel@tonic-gate  *
240*7c478bd9Sstevel@tonic-gate  */
241*7c478bd9Sstevel@tonic-gate static void
242*7c478bd9Sstevel@tonic-gate add_tblobject_to_container_tbl(container_tbl_t	*cont_tbl)
243*7c478bd9Sstevel@tonic-gate {
244*7c478bd9Sstevel@tonic-gate 	int		cnt;
245*7c478bd9Sstevel@tonic-gate 	int		index_to_hash;
246*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_ptr;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	index_to_hash	= ((cont_tbl->picl_hdl) % TABLE_SIZE);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	cont_tbl->next	= container_table[index_to_hash];
251*7c478bd9Sstevel@tonic-gate 	container_table[index_to_hash] = cont_tbl;
252*7c478bd9Sstevel@tonic-gate 	hash_ptr	= cont_tbl->hash_obj;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	/* initialize the bucket of this container hash table. */
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < TABLE_SIZE; cnt++) {
257*7c478bd9Sstevel@tonic-gate 		hash_ptr->next = NULL;
258*7c478bd9Sstevel@tonic-gate 		hash_ptr->prev = NULL;
259*7c478bd9Sstevel@tonic-gate 		hash_ptr++;
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 	if (cont_tbl->next != NULL) {
262*7c478bd9Sstevel@tonic-gate 		cont_tbl->next->prev = cont_tbl;
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate static void
267*7c478bd9Sstevel@tonic-gate add_nodeobject_to_hashtable(hash_obj_t	*hash_obj, container_tbl_t *cont_tbl)
268*7c478bd9Sstevel@tonic-gate {
269*7c478bd9Sstevel@tonic-gate 	int		index_to_hash;
270*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_table;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	index_to_hash	= ((hash_obj->picl_hdl) % TABLE_SIZE);
273*7c478bd9Sstevel@tonic-gate 	hash_table	= &cont_tbl->hash_obj[index_to_hash];
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	hash_obj->next	= hash_table->next;
276*7c478bd9Sstevel@tonic-gate 	hash_table->next = hash_obj;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	if (hash_obj->next != NULL) {
279*7c478bd9Sstevel@tonic-gate 		hash_obj->next->prev = hash_obj;
280*7c478bd9Sstevel@tonic-gate 	}
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate static container_tbl_t *
284*7c478bd9Sstevel@tonic-gate alloc_container_table(picl_nodehdl_t nodehdl)
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	container_tbl_t		*cont_tbl;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	cont_tbl = malloc(sizeof (container_tbl_t));
289*7c478bd9Sstevel@tonic-gate 	if (cont_tbl == NULL) {
290*7c478bd9Sstevel@tonic-gate 		return (NULL);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	cont_tbl->picl_hdl = nodehdl;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	cont_tbl->hash_obj = malloc(sizeof (hash_obj_t[TABLE_SIZE]));
296*7c478bd9Sstevel@tonic-gate 	cont_tbl->next =	NULL;
297*7c478bd9Sstevel@tonic-gate 	cont_tbl->prev =	NULL;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	if (cont_tbl->hash_obj == NULL) {
300*7c478bd9Sstevel@tonic-gate 		(void) free(cont_tbl);
301*7c478bd9Sstevel@tonic-gate 		return (NULL);
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_init(&cont_tbl->rwlock, NULL);
305*7c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&cont_tbl->cond_var, NULL);
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	return (cont_tbl);
308*7c478bd9Sstevel@tonic-gate }
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate /*
311*7c478bd9Sstevel@tonic-gate  * called to allocate container node object for container property and a
312*7c478bd9Sstevel@tonic-gate  * container table.
313*7c478bd9Sstevel@tonic-gate  */
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate static hash_obj_t *
316*7c478bd9Sstevel@tonic-gate alloc_container_node_object(picl_nodehdl_t nodehdl)
317*7c478bd9Sstevel@tonic-gate {
318*7c478bd9Sstevel@tonic-gate 	hash_obj_t		*hash_obj;
319*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t	acc_hdl;
320*7c478bd9Sstevel@tonic-gate 	container_node_t	*cont_node;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	/* open the container (call fruaccess) */
323*7c478bd9Sstevel@tonic-gate 	acc_hdl = fru_open_container(nodehdl);
324*7c478bd9Sstevel@tonic-gate 	if (acc_hdl == (container_hdl_t)0) {
325*7c478bd9Sstevel@tonic-gate 		return (NULL);
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	/* allocate container node object */
329*7c478bd9Sstevel@tonic-gate 	cont_node	= malloc(sizeof (container_node_t));
330*7c478bd9Sstevel@tonic-gate 	if (cont_node == NULL) {
331*7c478bd9Sstevel@tonic-gate 		return (NULL);
332*7c478bd9Sstevel@tonic-gate 	}
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	/* allocate container hash object */
335*7c478bd9Sstevel@tonic-gate 	hash_obj	= malloc(sizeof (hash_obj_t));
336*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
337*7c478bd9Sstevel@tonic-gate 		(void) free(cont_node);
338*7c478bd9Sstevel@tonic-gate 		return (NULL);
339*7c478bd9Sstevel@tonic-gate 	}
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	cont_node->cont_hdl	=	acc_hdl; /* fruaccess handle */
342*7c478bd9Sstevel@tonic-gate 	cont_node->section_list	=	NULL;
343*7c478bd9Sstevel@tonic-gate 	hash_obj->picl_hdl	=	nodehdl; /* picl node handle */
344*7c478bd9Sstevel@tonic-gate 	hash_obj->object_type	=	CONTAINER_NODE;
345*7c478bd9Sstevel@tonic-gate 	hash_obj->u.cont_node	=	cont_node;
346*7c478bd9Sstevel@tonic-gate 	hash_obj->next		=	NULL;
347*7c478bd9Sstevel@tonic-gate 	hash_obj->prev		=	NULL;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	return (hash_obj);
350*7c478bd9Sstevel@tonic-gate }
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate /*
353*7c478bd9Sstevel@tonic-gate  * called to allocate node object for section node.
354*7c478bd9Sstevel@tonic-gate  */
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate static hash_obj_t *
357*7c478bd9Sstevel@tonic-gate alloc_section_node_object(picl_nodehdl_t  nodehdl, section_t  *section)
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate 	hash_obj_t		*hash_obj;
360*7c478bd9Sstevel@tonic-gate 	section_node_t		*sec_node;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	/* allocate section node object */
363*7c478bd9Sstevel@tonic-gate 	sec_node = malloc(sizeof (section_node_t));
364*7c478bd9Sstevel@tonic-gate 	if (sec_node	== NULL) {
365*7c478bd9Sstevel@tonic-gate 		return (NULL);
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	/* allocate section hash object */
369*7c478bd9Sstevel@tonic-gate 	hash_obj = malloc(sizeof (hash_obj_t));
370*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
371*7c478bd9Sstevel@tonic-gate 		(void) free(sec_node);
372*7c478bd9Sstevel@tonic-gate 		return (NULL);
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	sec_node->section_hdl	=	section->handle; /* fruaccess hdl. */
376*7c478bd9Sstevel@tonic-gate 	sec_node->segment_list	=	NULL;
377*7c478bd9Sstevel@tonic-gate 	sec_node->next		=	NULL;
378*7c478bd9Sstevel@tonic-gate 	sec_node->num_of_segment =	-1;
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	hash_obj->picl_hdl	=	nodehdl; /* picl node handle */
381*7c478bd9Sstevel@tonic-gate 	hash_obj->object_type	=	SECTION_NODE;
382*7c478bd9Sstevel@tonic-gate 	hash_obj->u.sec_node	=	sec_node;
383*7c478bd9Sstevel@tonic-gate 	hash_obj->next		=	NULL;
384*7c478bd9Sstevel@tonic-gate 	hash_obj->prev		=	NULL;
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	return (hash_obj);
387*7c478bd9Sstevel@tonic-gate }
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate /*
390*7c478bd9Sstevel@tonic-gate  * called to allocate segment node object.
391*7c478bd9Sstevel@tonic-gate  */
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate static hash_obj_t *
394*7c478bd9Sstevel@tonic-gate alloc_segment_node_object(picl_nodehdl_t nodehdl, segment_t *segment)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
397*7c478bd9Sstevel@tonic-gate 	segment_node_t	*seg_node;
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	/* allocate segment node object */
400*7c478bd9Sstevel@tonic-gate 	seg_node = malloc(sizeof (segment_node_t));
401*7c478bd9Sstevel@tonic-gate 	if (seg_node == NULL) {
402*7c478bd9Sstevel@tonic-gate 		return (NULL);
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	/* allocate segment hash object */
406*7c478bd9Sstevel@tonic-gate 	hash_obj = malloc(sizeof (hash_obj_t));
407*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
408*7c478bd9Sstevel@tonic-gate 		free(seg_node);
409*7c478bd9Sstevel@tonic-gate 		return (NULL);
410*7c478bd9Sstevel@tonic-gate 	}
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 	/* fruaccess handle */
413*7c478bd9Sstevel@tonic-gate 	seg_node->segment_hdl	= segment->handle;
414*7c478bd9Sstevel@tonic-gate 	seg_node->packet_list	= NULL;
415*7c478bd9Sstevel@tonic-gate 	seg_node->next		= NULL;
416*7c478bd9Sstevel@tonic-gate 	seg_node->num_of_pkt	= -1;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	/* picl node handle */
419*7c478bd9Sstevel@tonic-gate 	hash_obj->picl_hdl	= nodehdl;
420*7c478bd9Sstevel@tonic-gate 	hash_obj->object_type	= SEGMENT_NODE;
421*7c478bd9Sstevel@tonic-gate 	hash_obj->u.seg_node	= seg_node;
422*7c478bd9Sstevel@tonic-gate 	hash_obj->next		= NULL;
423*7c478bd9Sstevel@tonic-gate 	hash_obj->prev		= NULL;
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 	return (hash_obj);
426*7c478bd9Sstevel@tonic-gate }
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate /*
429*7c478bd9Sstevel@tonic-gate  * called to allocate node object for packet.
430*7c478bd9Sstevel@tonic-gate  */
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate static hash_obj_t *
433*7c478bd9Sstevel@tonic-gate alloc_packet_node_object(picl_nodehdl_t	nodehdl, packet_t *packet)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
436*7c478bd9Sstevel@tonic-gate 	packet_node_t	*pkt_node;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 	/* allocate packet node object */
439*7c478bd9Sstevel@tonic-gate 	pkt_node = malloc(sizeof (packet_node_t));
440*7c478bd9Sstevel@tonic-gate 	if (pkt_node == NULL) {
441*7c478bd9Sstevel@tonic-gate 		return (NULL);
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	/* allocate packet hash object */
445*7c478bd9Sstevel@tonic-gate 	hash_obj = malloc(sizeof (hash_obj_t));
446*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
447*7c478bd9Sstevel@tonic-gate 		free(pkt_node);
448*7c478bd9Sstevel@tonic-gate 		return (NULL);
449*7c478bd9Sstevel@tonic-gate 	}
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	/* fruaccess handle */
452*7c478bd9Sstevel@tonic-gate 	pkt_node->pkt_handle	= packet->handle;
453*7c478bd9Sstevel@tonic-gate 	pkt_node->next		= NULL;
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	hash_obj->picl_hdl	= nodehdl;	/* picl node handle */
456*7c478bd9Sstevel@tonic-gate 	hash_obj->object_type	= PACKET_NODE;
457*7c478bd9Sstevel@tonic-gate 	hash_obj->u.pkt_node	= pkt_node;
458*7c478bd9Sstevel@tonic-gate 	hash_obj->next		= NULL;
459*7c478bd9Sstevel@tonic-gate 	hash_obj->prev		= NULL;
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	return (hash_obj);
462*7c478bd9Sstevel@tonic-gate }
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate /* add new section hash object to the section list */
465*7c478bd9Sstevel@tonic-gate static void
466*7c478bd9Sstevel@tonic-gate add_to_section_list(hash_obj_t  *container_hash, hash_obj_t *sect_hash)
467*7c478bd9Sstevel@tonic-gate {
468*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_hash;
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 	sect_hash->u.sec_node->container_hdl = container_hash->picl_hdl;
471*7c478bd9Sstevel@tonic-gate 	if (container_hash->u.cont_node->section_list == NULL) {
472*7c478bd9Sstevel@tonic-gate 		container_hash->u.cont_node->section_list = sect_hash;
473*7c478bd9Sstevel@tonic-gate 		return;
474*7c478bd9Sstevel@tonic-gate 	}
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	for (next_hash = container_hash->u.cont_node->section_list;
477*7c478bd9Sstevel@tonic-gate 			next_hash->u.sec_node->next != NULL;
478*7c478bd9Sstevel@tonic-gate 			next_hash = next_hash->u.sec_node->next) {
479*7c478bd9Sstevel@tonic-gate 		;
480*7c478bd9Sstevel@tonic-gate 	}
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	next_hash->u.sec_node->next = sect_hash;
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate /* add new segment hash object to the existing list */
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate static void
488*7c478bd9Sstevel@tonic-gate add_to_segment_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
489*7c478bd9Sstevel@tonic-gate {
490*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_hash;
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	child_obj->u.seg_node->sec_nodehdl = parent_obj->picl_hdl;
493*7c478bd9Sstevel@tonic-gate 	if (parent_obj->u.sec_node->segment_list == NULL) {
494*7c478bd9Sstevel@tonic-gate 		parent_obj->u.sec_node->segment_list = child_obj;
495*7c478bd9Sstevel@tonic-gate 		return;
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 	for (next_hash = parent_obj->u.sec_node->segment_list;
499*7c478bd9Sstevel@tonic-gate 			next_hash->u.seg_node->next != NULL;
500*7c478bd9Sstevel@tonic-gate 			next_hash = next_hash->u.seg_node->next) {
501*7c478bd9Sstevel@tonic-gate 		;
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 	next_hash->u.seg_node->next = child_obj;
504*7c478bd9Sstevel@tonic-gate }
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate /*
507*7c478bd9Sstevel@tonic-gate  * called to add packet node object to the existing packet list.
508*7c478bd9Sstevel@tonic-gate  */
509*7c478bd9Sstevel@tonic-gate static void
510*7c478bd9Sstevel@tonic-gate add_to_packet_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
511*7c478bd9Sstevel@tonic-gate {
512*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_hash;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	if (parent_obj->u.seg_node->packet_list == NULL) {
515*7c478bd9Sstevel@tonic-gate 		parent_obj->u.seg_node->packet_list = child_obj;
516*7c478bd9Sstevel@tonic-gate 		return;
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	for (next_hash = parent_obj->u.seg_node->packet_list;
520*7c478bd9Sstevel@tonic-gate 			next_hash->u.pkt_node->next != NULL;
521*7c478bd9Sstevel@tonic-gate 			next_hash = next_hash->u.pkt_node->next) {
522*7c478bd9Sstevel@tonic-gate 		;
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 	next_hash->u.pkt_node->next = child_obj;
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate /*
528*7c478bd9Sstevel@tonic-gate  * free the packet hash list.
529*7c478bd9Sstevel@tonic-gate  */
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate static void
532*7c478bd9Sstevel@tonic-gate free_packet_list(hash_obj_t	*hash_obj, container_tbl_t *cont_tbl)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_obj;
535*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*free_obj;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	/* packet hash object list */
538*7c478bd9Sstevel@tonic-gate 	next_obj = hash_obj->u.seg_node->packet_list;
539*7c478bd9Sstevel@tonic-gate 	while (next_obj != NULL) {
540*7c478bd9Sstevel@tonic-gate 		free_obj = next_obj;
541*7c478bd9Sstevel@tonic-gate 		next_obj = next_obj->u.pkt_node->next;
542*7c478bd9Sstevel@tonic-gate 		if (free_obj->prev == NULL) { /* first node object */
543*7c478bd9Sstevel@tonic-gate 			cont_tbl->hash_obj[(free_obj->picl_hdl %
544*7c478bd9Sstevel@tonic-gate 				TABLE_SIZE)].next = free_obj->next;
545*7c478bd9Sstevel@tonic-gate 			if (free_obj->next != NULL) {
546*7c478bd9Sstevel@tonic-gate 				free_obj->next->prev = NULL;
547*7c478bd9Sstevel@tonic-gate 			}
548*7c478bd9Sstevel@tonic-gate 		} else {
549*7c478bd9Sstevel@tonic-gate 			free_obj->prev->next = free_obj->next;
550*7c478bd9Sstevel@tonic-gate 			if (free_obj->next != NULL) {
551*7c478bd9Sstevel@tonic-gate 				free_obj->next->prev = free_obj->prev;
552*7c478bd9Sstevel@tonic-gate 			}
553*7c478bd9Sstevel@tonic-gate 		}
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 		free(free_obj->u.pkt_node);
556*7c478bd9Sstevel@tonic-gate 		free(free_obj);
557*7c478bd9Sstevel@tonic-gate 	}
558*7c478bd9Sstevel@tonic-gate 	hash_obj->u.seg_node->packet_list = NULL;
559*7c478bd9Sstevel@tonic-gate }
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate /*
562*7c478bd9Sstevel@tonic-gate  * free the segment hash node object.
563*7c478bd9Sstevel@tonic-gate  */
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate static void
566*7c478bd9Sstevel@tonic-gate free_segment_node(hash_obj_t *hash_obj, picl_nodehdl_t nodehdl,
567*7c478bd9Sstevel@tonic-gate 					container_tbl_t *cont_tbl)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*prev_hash_obj;
570*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_obj;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	/* segment hash object list */
573*7c478bd9Sstevel@tonic-gate 	next_obj = hash_obj->u.sec_node->segment_list;
574*7c478bd9Sstevel@tonic-gate 	if (next_obj == NULL) {
575*7c478bd9Sstevel@tonic-gate 		return;
576*7c478bd9Sstevel@tonic-gate 	}
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	/* find the segment hash from the segment list to be deleted. */
579*7c478bd9Sstevel@tonic-gate 	if (next_obj->picl_hdl == nodehdl) {
580*7c478bd9Sstevel@tonic-gate 		hash_obj->u.sec_node->segment_list =
581*7c478bd9Sstevel@tonic-gate 					next_obj->u.seg_node->next;
582*7c478bd9Sstevel@tonic-gate 	} else {
583*7c478bd9Sstevel@tonic-gate 		while (next_obj != NULL) {
584*7c478bd9Sstevel@tonic-gate 			if (next_obj->picl_hdl != nodehdl) {
585*7c478bd9Sstevel@tonic-gate 				prev_hash_obj = next_obj;
586*7c478bd9Sstevel@tonic-gate 				next_obj = next_obj->u.seg_node->next;
587*7c478bd9Sstevel@tonic-gate 			} else {
588*7c478bd9Sstevel@tonic-gate 				prev_hash_obj->u.seg_node->next =
589*7c478bd9Sstevel@tonic-gate 						next_obj->u.seg_node->next;
590*7c478bd9Sstevel@tonic-gate 				break;
591*7c478bd9Sstevel@tonic-gate 			}
592*7c478bd9Sstevel@tonic-gate 		}
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 		if (next_obj == NULL) {
595*7c478bd9Sstevel@tonic-gate 			return;
596*7c478bd9Sstevel@tonic-gate 		}
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	}
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 	if (next_obj->prev == NULL) {
601*7c478bd9Sstevel@tonic-gate 		cont_tbl->hash_obj[(next_obj->picl_hdl % TABLE_SIZE)].next =
602*7c478bd9Sstevel@tonic-gate 							next_obj->next;
603*7c478bd9Sstevel@tonic-gate 		if (next_obj->next != NULL)
604*7c478bd9Sstevel@tonic-gate 			next_obj->next->prev = NULL;
605*7c478bd9Sstevel@tonic-gate 	} else {
606*7c478bd9Sstevel@tonic-gate 		next_obj->prev->next = next_obj->next;
607*7c478bd9Sstevel@tonic-gate 		if (next_obj->next != NULL) {
608*7c478bd9Sstevel@tonic-gate 			next_obj->next->prev = next_obj->prev;
609*7c478bd9Sstevel@tonic-gate 		}
610*7c478bd9Sstevel@tonic-gate 	}
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	free_packet_list(next_obj, cont_tbl);
613*7c478bd9Sstevel@tonic-gate 	free(next_obj->u.seg_node);
614*7c478bd9Sstevel@tonic-gate 	free(next_obj);
615*7c478bd9Sstevel@tonic-gate }
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate /*
619*7c478bd9Sstevel@tonic-gate  * Description : frudata_delete_segment is called when volatile property
620*7c478bd9Sstevel@tonic-gate  *              delete_segment under class segment is accessed.
621*7c478bd9Sstevel@tonic-gate  *
622*7c478bd9Sstevel@tonic-gate  * Arguments   : ptree_warg_t is holds node handle of segment node and property
623*7c478bd9Sstevel@tonic-gate  *              handle of delete_segment property.
624*7c478bd9Sstevel@tonic-gate  */
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
627*7c478bd9Sstevel@tonic-gate static int
628*7c478bd9Sstevel@tonic-gate frudata_delete_segment(ptree_warg_t *warg, const void *buf)
629*7c478bd9Sstevel@tonic-gate {
630*7c478bd9Sstevel@tonic-gate 	int		retval;
631*7c478bd9Sstevel@tonic-gate 	int		num_of_segment;
632*7c478bd9Sstevel@tonic-gate 	int		num_of_pkt;
633*7c478bd9Sstevel@tonic-gate 	int		pkt_cnt;
634*7c478bd9Sstevel@tonic-gate 	int		count;
635*7c478bd9Sstevel@tonic-gate 	packet_t	*pkt_buf;
636*7c478bd9Sstevel@tonic-gate 	segment_t	*seg_buffer;
637*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*seg_hash;
638*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*pkt_hash;
639*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
640*7c478bd9Sstevel@tonic-gate 	fru_segdesc_t	*desc;
641*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	sec_nodehdl;
642*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
643*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t seg_acc_hdl;
644*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t new_sec_acc_hdl;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(warg->nodeh, SEGMENT_NODE, PICL_WRITE);
647*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
648*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	/* segment hash */
652*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(warg->nodeh, SEGMENT_NODE, cont_tbl);
653*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
654*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
655*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
656*7c478bd9Sstevel@tonic-gate 	}
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	/* fruaccess segment handle */
659*7c478bd9Sstevel@tonic-gate 	seg_acc_hdl	= hash_obj->u.seg_node->segment_hdl;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	/* call fruaccess to get new section handle */
662*7c478bd9Sstevel@tonic-gate 	if (fru_delete_segment(seg_acc_hdl, &new_sec_acc_hdl, &warg->cred)
663*7c478bd9Sstevel@tonic-gate 		== -1) {
664*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
665*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
666*7c478bd9Sstevel@tonic-gate 	}
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	if (ptree_delete_node(warg->nodeh) != PICL_SUCCESS) {
669*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
670*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
671*7c478bd9Sstevel@tonic-gate 	}
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	if (ptree_destroy_node(warg->nodeh) != PICL_SUCCESS) {
674*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
675*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
676*7c478bd9Sstevel@tonic-gate 	}
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate 	/* get section node handle */
680*7c478bd9Sstevel@tonic-gate 	sec_nodehdl = hash_obj->u.seg_node->sec_nodehdl;
681*7c478bd9Sstevel@tonic-gate 	/* get section hash */
682*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(sec_nodehdl, SECTION_NODE, cont_tbl);
683*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
684*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
685*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
686*7c478bd9Sstevel@tonic-gate 	}
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 	free_segment_node(hash_obj, warg->nodeh, cont_tbl);
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 	hash_obj->u.sec_node->num_of_segment = 0;
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 	/* call fruaccess with new section handle */
693*7c478bd9Sstevel@tonic-gate 	num_of_segment = fru_get_num_segments(new_sec_acc_hdl, &warg->cred);
694*7c478bd9Sstevel@tonic-gate 	if (num_of_segment <= 0) {
695*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
696*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
697*7c478bd9Sstevel@tonic-gate 	}
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	seg_buffer = alloca(sizeof (segment_t) * num_of_segment);
700*7c478bd9Sstevel@tonic-gate 	if (seg_buffer == NULL) {
701*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
702*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
703*7c478bd9Sstevel@tonic-gate 	}
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	/* get all the segments */
706*7c478bd9Sstevel@tonic-gate 	retval = fru_get_segments(new_sec_acc_hdl, seg_buffer,
707*7c478bd9Sstevel@tonic-gate 						num_of_segment, &warg->cred);
708*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
709*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
710*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
711*7c478bd9Sstevel@tonic-gate 	}
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	seg_hash = hash_obj->u.sec_node->segment_list;
714*7c478bd9Sstevel@tonic-gate 	if (seg_hash == NULL) {
715*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
716*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
717*7c478bd9Sstevel@tonic-gate 	}
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	/* rebuild the segment list */
720*7c478bd9Sstevel@tonic-gate 	for (count = 0; count < num_of_segment; count++) {
721*7c478bd9Sstevel@tonic-gate 		desc	= (fru_segdesc_t *)&seg_buffer[count].descriptor;
722*7c478bd9Sstevel@tonic-gate 		if (!(desc->field.field_perm & SEGMENT_READ)) {
723*7c478bd9Sstevel@tonic-gate 			continue;
724*7c478bd9Sstevel@tonic-gate 		}
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 		if (desc->field.opaque) {
727*7c478bd9Sstevel@tonic-gate 			continue;
728*7c478bd9Sstevel@tonic-gate 		}
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 		hash_obj->u.sec_node->num_of_segment++;
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 		seg_hash->u.seg_node->segment_hdl = seg_buffer[count].handle;
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 		num_of_pkt =
735*7c478bd9Sstevel@tonic-gate 			fru_get_num_packets(seg_buffer[count].handle,
736*7c478bd9Sstevel@tonic-gate 						&warg->cred);
737*7c478bd9Sstevel@tonic-gate 		if (num_of_pkt <= 0) {
738*7c478bd9Sstevel@tonic-gate 			continue;
739*7c478bd9Sstevel@tonic-gate 		}
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 		pkt_buf	= alloca(sizeof (packet_t) * num_of_pkt);
742*7c478bd9Sstevel@tonic-gate 		if (pkt_buf == NULL) {
743*7c478bd9Sstevel@tonic-gate 			unlock_container_lock(cont_tbl);
744*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
745*7c478bd9Sstevel@tonic-gate 		}
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 		retval = fru_get_packets(seg_buffer[count].handle, pkt_buf,
748*7c478bd9Sstevel@tonic-gate 						num_of_pkt, &warg->cred);
749*7c478bd9Sstevel@tonic-gate 		if (retval == -1) {
750*7c478bd9Sstevel@tonic-gate 			continue;
751*7c478bd9Sstevel@tonic-gate 		}
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 		pkt_hash = seg_hash->u.seg_node->packet_list;
754*7c478bd9Sstevel@tonic-gate 		if (pkt_hash == NULL) {
755*7c478bd9Sstevel@tonic-gate 			continue;
756*7c478bd9Sstevel@tonic-gate 		}
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 		/* rebuild the packet list */
759*7c478bd9Sstevel@tonic-gate 		for (pkt_cnt = 0; pkt_cnt < num_of_pkt; pkt_cnt++) {
760*7c478bd9Sstevel@tonic-gate 			pkt_hash->u.pkt_node->pkt_handle =
761*7c478bd9Sstevel@tonic-gate 						pkt_buf[pkt_cnt].handle;
762*7c478bd9Sstevel@tonic-gate 			pkt_hash = pkt_hash->u.pkt_node->next;
763*7c478bd9Sstevel@tonic-gate 		}
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 		seg_hash = seg_hash->u.seg_node->next;
766*7c478bd9Sstevel@tonic-gate 		if (seg_hash == NULL) {
767*7c478bd9Sstevel@tonic-gate 			break;
768*7c478bd9Sstevel@tonic-gate 		}
769*7c478bd9Sstevel@tonic-gate 	}
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 	/* updated with new section handle */
772*7c478bd9Sstevel@tonic-gate 	hash_obj->u.sec_node->section_hdl = new_sec_acc_hdl;
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
777*7c478bd9Sstevel@tonic-gate }
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate /*
780*7c478bd9Sstevel@tonic-gate  * Description : frudata_read_payload is called when volatile property
781*7c478bd9Sstevel@tonic-gate  *              payload is read.
782*7c478bd9Sstevel@tonic-gate  *
783*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_rarg_t  holds node handle of the table property.
784*7c478bd9Sstevel@tonic-gate  *              and property handle of the payload cell.
785*7c478bd9Sstevel@tonic-gate  *              p_buf contains payload data when function returns.
786*7c478bd9Sstevel@tonic-gate  *
787*7c478bd9Sstevel@tonic-gate  * Returns      : PICL_SUCCESS on success.
788*7c478bd9Sstevel@tonic-gate  *              PICL_FAILURE on failure.
789*7c478bd9Sstevel@tonic-gate  */
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate static int
792*7c478bd9Sstevel@tonic-gate frudata_read_payload(ptree_rarg_t *rarg, void *buf)
793*7c478bd9Sstevel@tonic-gate {
794*7c478bd9Sstevel@tonic-gate 	int		num_bytes;
795*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
796*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t pkt_acc_hdl;
797*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(rarg->nodeh, SEGMENT_NODE, PICL_READ);
801*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
802*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
803*7c478bd9Sstevel@tonic-gate 	}
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(rarg->proph, PACKET_NODE, cont_tbl);
806*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
807*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
808*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
809*7c478bd9Sstevel@tonic-gate 	}
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate 	pkt_acc_hdl = hash_obj->u.pkt_node->pkt_handle;
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	num_bytes = fru_get_payload(pkt_acc_hdl, buf,
814*7c478bd9Sstevel@tonic-gate 			hash_obj->u.pkt_node->paylen, &rarg->cred);
815*7c478bd9Sstevel@tonic-gate 	if (num_bytes != hash_obj->u.pkt_node->paylen) {
816*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
817*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
818*7c478bd9Sstevel@tonic-gate 	}
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
823*7c478bd9Sstevel@tonic-gate }
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate /*
826*7c478bd9Sstevel@tonic-gate  * Description : frudata_write_payload is called when payload property cell
827*7c478bd9Sstevel@tonic-gate  *              is accessed.
828*7c478bd9Sstevel@tonic-gate  *
829*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_warg_t holds node handle of the packet-table.
830*7c478bd9Sstevel@tonic-gate  *              and property handle of the payload cell.
831*7c478bd9Sstevel@tonic-gate  *              p_buf contains payload data.
832*7c478bd9Sstevel@tonic-gate  *
833*7c478bd9Sstevel@tonic-gate  * Returns      : PICL_SUCCESS on success.
834*7c478bd9Sstevel@tonic-gate  *
835*7c478bd9Sstevel@tonic-gate  */
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate static int
838*7c478bd9Sstevel@tonic-gate frudata_write_payload(ptree_warg_t *warg, const void *buf)
839*7c478bd9Sstevel@tonic-gate {
840*7c478bd9Sstevel@tonic-gate 	int		retval;
841*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
842*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t pkt_acc_hdl;
843*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(warg->nodeh, SEGMENT_NODE, PICL_WRITE);
846*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
847*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
848*7c478bd9Sstevel@tonic-gate 	}
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(warg->proph, PACKET_NODE, cont_tbl);
851*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
852*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
853*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
854*7c478bd9Sstevel@tonic-gate 	}
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	pkt_acc_hdl = hash_obj->u.pkt_node->pkt_handle;
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	retval = fru_update_payload(pkt_acc_hdl, buf,
859*7c478bd9Sstevel@tonic-gate 			hash_obj->u.pkt_node->paylen,
860*7c478bd9Sstevel@tonic-gate 			&pkt_acc_hdl, &warg->cred);
861*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
862*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
863*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
864*7c478bd9Sstevel@tonic-gate 	}
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	hash_obj->u.pkt_node->pkt_handle = pkt_acc_hdl;
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
871*7c478bd9Sstevel@tonic-gate }
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate /*
874*7c478bd9Sstevel@tonic-gate  * callback volatile function is called when tag volatile property
875*7c478bd9Sstevel@tonic-gate  * is accessed. this routine holds a read lock over the hash table
876*7c478bd9Sstevel@tonic-gate  * and do a lookup over the property handle i.e property handle of
877*7c478bd9Sstevel@tonic-gate  * the tag property passed in rarg parameter.
878*7c478bd9Sstevel@tonic-gate  * tag value is copied into the buffer (void *buf).
879*7c478bd9Sstevel@tonic-gate  */
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate static int
882*7c478bd9Sstevel@tonic-gate frudata_read_tag(ptree_rarg_t	*rarg, void *buf)
883*7c478bd9Sstevel@tonic-gate {
884*7c478bd9Sstevel@tonic-gate 	int		retval;
885*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
886*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	rowproph;
887*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(rarg->nodeh, SEGMENT_NODE, PICL_READ);
890*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
891*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
892*7c478bd9Sstevel@tonic-gate 	}
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_next_by_row(rarg->proph, &rowproph);
895*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
896*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
897*7c478bd9Sstevel@tonic-gate 		return (retval);
898*7c478bd9Sstevel@tonic-gate 	}
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(rowproph, PACKET_NODE, cont_tbl);
901*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
902*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
903*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
904*7c478bd9Sstevel@tonic-gate 	}
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, &hash_obj->u.pkt_node->tag, sizeof (tag_t));
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
909*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate /*
914*7c478bd9Sstevel@tonic-gate  * Description : create_packet_table() is called by fru_delete_packet_row(),
915*7c478bd9Sstevel@tonic-gate  *              to create a packet-table volatile property. it's called after
916*7c478bd9Sstevel@tonic-gate  *              deleting the packet-table. fru_delete_packet_row() calls
917*7c478bd9Sstevel@tonic-gate  *              frudata_read_packet_table() to add rows into the table.
918*7c478bd9Sstevel@tonic-gate  */
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate static int
921*7c478bd9Sstevel@tonic-gate create_packet_table(picl_nodehdl_t seghdl, picl_prophdl_t *thdl)
922*7c478bd9Sstevel@tonic-gate {
923*7c478bd9Sstevel@tonic-gate 	int			retval;
924*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		tblhdl;
925*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		prophdl;
926*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	prop;
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	retval = ptree_create_table(&tblhdl);
929*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
930*7c478bd9Sstevel@tonic-gate 		return (retval);
931*7c478bd9Sstevel@tonic-gate 	}
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 	prop.version = PTREE_PROPINFO_VERSION;
934*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type =  PICL_PTYPE_TABLE;
935*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_READ|PICL_WRITE;
936*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = sizeof (picl_prophdl_t);
937*7c478bd9Sstevel@tonic-gate 	prop.read = NULL;
938*7c478bd9Sstevel@tonic-gate 	prop.write = NULL;
939*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_PACKET_TABLE);
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 	retval = ptree_create_and_add_prop(seghdl, &prop, &tblhdl,
942*7c478bd9Sstevel@tonic-gate 							&prophdl);
943*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
944*7c478bd9Sstevel@tonic-gate 		return (retval);
945*7c478bd9Sstevel@tonic-gate 	}
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	/* hold the table handle */
948*7c478bd9Sstevel@tonic-gate 	*thdl = tblhdl;
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
951*7c478bd9Sstevel@tonic-gate }
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate /*
954*7c478bd9Sstevel@tonic-gate  * Description : frudata_delete_packet is called when write operation is
955*7c478bd9Sstevel@tonic-gate  *		performed on tag volatile property.
956*7c478bd9Sstevel@tonic-gate  *
957*7c478bd9Sstevel@tonic-gate  *
958*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_warg_t holds node handle to the segment node.
959*7c478bd9Sstevel@tonic-gate  *              and property handle of the tag cell in the packet table to be
960*7c478bd9Sstevel@tonic-gate  *		deleted.
961*7c478bd9Sstevel@tonic-gate  *              buf contains the tag data + plus DELETE_KEY_TAG
962*7c478bd9Sstevel@tonic-gate  *
963*7c478bd9Sstevel@tonic-gate  * Returns      : PICL_SUCCESS on success
964*7c478bd9Sstevel@tonic-gate  *
965*7c478bd9Sstevel@tonic-gate  */
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate static int
968*7c478bd9Sstevel@tonic-gate frudata_delete_packet(ptree_warg_t *warg, const void *buf)
969*7c478bd9Sstevel@tonic-gate {
970*7c478bd9Sstevel@tonic-gate 	int		count = 0;
971*7c478bd9Sstevel@tonic-gate 	int		retval;
972*7c478bd9Sstevel@tonic-gate 	int		num_of_pkt;
973*7c478bd9Sstevel@tonic-gate 	uint64_t	tag;
974*7c478bd9Sstevel@tonic-gate 	packet_t	*packet;
975*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*seg_hash_obj;
976*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*pkt_hash_obj;
977*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
978*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	tblhdl;
979*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	rowproph;
980*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t new_seg_acc_hdl;
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(warg->nodeh, SEGMENT_NODE, PICL_WRITE);
983*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
984*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
985*7c478bd9Sstevel@tonic-gate 	}
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	/* get the payload property handle */
988*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_next_by_row(warg->proph, &rowproph);
989*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
990*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
991*7c478bd9Sstevel@tonic-gate 		return (retval);
992*7c478bd9Sstevel@tonic-gate 	}
993*7c478bd9Sstevel@tonic-gate 
994*7c478bd9Sstevel@tonic-gate 	/* do lookup on payload property handle */
995*7c478bd9Sstevel@tonic-gate 	pkt_hash_obj = lookup_node_object(rowproph, PACKET_NODE, cont_tbl);
996*7c478bd9Sstevel@tonic-gate 	if (pkt_hash_obj == NULL) {
997*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
998*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
999*7c478bd9Sstevel@tonic-gate 	}
1000*7c478bd9Sstevel@tonic-gate 
1001*7c478bd9Sstevel@tonic-gate 	/* verify the tag */
1002*7c478bd9Sstevel@tonic-gate 	tag = pkt_hash_obj->u.pkt_node->tag.raw_data;
1003*7c478bd9Sstevel@tonic-gate 	tag &= FRUDATA_DELETE_TAG_MASK;
1004*7c478bd9Sstevel@tonic-gate 	tag |= FRUDATA_DELETE_TAG_KEY;
1005*7c478bd9Sstevel@tonic-gate 	if (*(uint64_t *)buf != tag) {
1006*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1007*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1008*7c478bd9Sstevel@tonic-gate 	}
1009*7c478bd9Sstevel@tonic-gate 
1010*7c478bd9Sstevel@tonic-gate 	/* call fruaccess module */
1011*7c478bd9Sstevel@tonic-gate 	retval = fru_delete_packet(pkt_hash_obj->u.pkt_node->pkt_handle,
1012*7c478bd9Sstevel@tonic-gate 				&new_seg_acc_hdl, &warg->cred);
1013*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1014*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1015*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
1016*7c478bd9Sstevel@tonic-gate 	}
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate 	/* delete the packet table */
1019*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_prop_by_name(warg->nodeh, PICL_PROP_PACKET_TABLE,
1020*7c478bd9Sstevel@tonic-gate 							&tblhdl);
1021*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1022*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1023*7c478bd9Sstevel@tonic-gate 		return (retval);
1024*7c478bd9Sstevel@tonic-gate 	}
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 	retval = ptree_delete_prop(tblhdl);
1027*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1028*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1029*7c478bd9Sstevel@tonic-gate 		return (retval);
1030*7c478bd9Sstevel@tonic-gate 	}
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	retval = ptree_destroy_prop(tblhdl);
1033*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1034*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1035*7c478bd9Sstevel@tonic-gate 		return (retval);
1036*7c478bd9Sstevel@tonic-gate 	}
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 	seg_hash_obj = lookup_node_object(warg->nodeh, SEGMENT_NODE,
1040*7c478bd9Sstevel@tonic-gate 							cont_tbl);
1041*7c478bd9Sstevel@tonic-gate 	if (seg_hash_obj == NULL) {
1042*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1043*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1044*7c478bd9Sstevel@tonic-gate 	}
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate 	/* free all packet hash object */
1047*7c478bd9Sstevel@tonic-gate 	free_packet_list(seg_hash_obj, cont_tbl);
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate 	/* recreate the packet table */
1050*7c478bd9Sstevel@tonic-gate 	retval = create_packet_table(warg->nodeh, &tblhdl);
1051*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1052*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1053*7c478bd9Sstevel@tonic-gate 		return (retval);
1054*7c478bd9Sstevel@tonic-gate 	}
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 	seg_hash_obj->u.seg_node->segment_hdl = new_seg_acc_hdl;
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	seg_hash_obj->u.seg_node->num_of_pkt = 0;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	num_of_pkt = fru_get_num_packets(new_seg_acc_hdl, &warg->cred);
1061*7c478bd9Sstevel@tonic-gate 	if (num_of_pkt == -1) {
1062*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1063*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1064*7c478bd9Sstevel@tonic-gate 	}
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate 	if (num_of_pkt == 0) {
1067*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1068*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
1069*7c478bd9Sstevel@tonic-gate 	}
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 	packet = alloca(sizeof (packet_t) * num_of_pkt);
1072*7c478bd9Sstevel@tonic-gate 	if (packet == NULL) {
1073*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1074*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1075*7c478bd9Sstevel@tonic-gate 	}
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate 	retval = fru_get_packets(new_seg_acc_hdl, packet,
1078*7c478bd9Sstevel@tonic-gate 					num_of_pkt, &warg->cred);
1079*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1080*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1081*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1082*7c478bd9Sstevel@tonic-gate 	}
1083*7c478bd9Sstevel@tonic-gate 
1084*7c478bd9Sstevel@tonic-gate 	/* rebuild the packet hash object */
1085*7c478bd9Sstevel@tonic-gate 	for (count = 0; count < num_of_pkt; count++) {
1086*7c478bd9Sstevel@tonic-gate 		(void) add_row_to_table(seg_hash_obj, tblhdl, packet+count,
1087*7c478bd9Sstevel@tonic-gate 								cont_tbl);
1088*7c478bd9Sstevel@tonic-gate 	}
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate 	seg_hash_obj->u.seg_node->num_of_pkt = num_of_pkt;
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate 	(void) ptree_update_propval_by_name(warg->nodeh, PICL_PROP_NUM_TAGS,
1093*7c478bd9Sstevel@tonic-gate 				&num_of_pkt, sizeof (uint32_t));
1094*7c478bd9Sstevel@tonic-gate 
1095*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1098*7c478bd9Sstevel@tonic-gate }
1099*7c478bd9Sstevel@tonic-gate 
1100*7c478bd9Sstevel@tonic-gate /*
1101*7c478bd9Sstevel@tonic-gate  * called from frudata_delete_packet(), frudata_add_packet(),
1102*7c478bd9Sstevel@tonic-gate  * frudata_read_packet() callback routine to add packet into
1103*7c478bd9Sstevel@tonic-gate  * the packet table. it also create hash node object for each
1104*7c478bd9Sstevel@tonic-gate  * individual packet and add the object to the packet list.
1105*7c478bd9Sstevel@tonic-gate  */
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate static int
1108*7c478bd9Sstevel@tonic-gate add_row_to_table(hash_obj_t *seg_obj, picl_nodehdl_t tblhdl, packet_t *pkt,
1109*7c478bd9Sstevel@tonic-gate 					container_tbl_t *cont_tbl)
1110*7c478bd9Sstevel@tonic-gate {
1111*7c478bd9Sstevel@tonic-gate 	int			retval;
1112*7c478bd9Sstevel@tonic-gate 	int			paylen;
1113*7c478bd9Sstevel@tonic-gate 	size_t			tag_size;
1114*7c478bd9Sstevel@tonic-gate 	hash_obj_t		*hash_obj;
1115*7c478bd9Sstevel@tonic-gate 	fru_tagtype_t		tagtype;
1116*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		prophdl[NUM_OF_COL_IN_PKT_TABLE];
1117*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	prop;
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate 	prop.version = PTREE_PROPINFO_VERSION;
1120*7c478bd9Sstevel@tonic-gate 
1121*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type =  PICL_PTYPE_BYTEARRAY;
1122*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_READ|PICL_WRITE|PICL_VOLATILE;
1123*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = sizeof (fru_tag_t);
1124*7c478bd9Sstevel@tonic-gate 	prop.read = frudata_read_tag;
1125*7c478bd9Sstevel@tonic-gate 	prop.write = frudata_delete_packet;
1126*7c478bd9Sstevel@tonic-gate 
1127*7c478bd9Sstevel@tonic-gate 	/* tag property node */
1128*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_TAG);
1129*7c478bd9Sstevel@tonic-gate 
1130*7c478bd9Sstevel@tonic-gate 	paylen = get_payload_length((void *)&pkt->tag);
1131*7c478bd9Sstevel@tonic-gate 	if (paylen < 0) {
1132*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1133*7c478bd9Sstevel@tonic-gate 	}
1134*7c478bd9Sstevel@tonic-gate 
1135*7c478bd9Sstevel@tonic-gate 	retval = ptree_create_prop(&prop, NULL, &prophdl[0]);
1136*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1137*7c478bd9Sstevel@tonic-gate 		return (retval);
1138*7c478bd9Sstevel@tonic-gate 	}
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 
1141*7c478bd9Sstevel@tonic-gate 	/* payload property node */
1142*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type =  PICL_PTYPE_BYTEARRAY;
1143*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = paylen;
1144*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_PAYLOAD);
1145*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_READ|PICL_WRITE|PICL_VOLATILE;
1146*7c478bd9Sstevel@tonic-gate 	prop.read = frudata_read_payload;
1147*7c478bd9Sstevel@tonic-gate 	prop.write = frudata_write_payload;
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 	retval = ptree_create_prop(&prop, NULL, &prophdl[1]);
1150*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1151*7c478bd9Sstevel@tonic-gate 		return (retval);
1152*7c478bd9Sstevel@tonic-gate 	}
1153*7c478bd9Sstevel@tonic-gate 
1154*7c478bd9Sstevel@tonic-gate 	hash_obj = alloc_packet_node_object(prophdl[1], pkt);
1155*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1156*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1157*7c478bd9Sstevel@tonic-gate 	}
1158*7c478bd9Sstevel@tonic-gate 
1159*7c478bd9Sstevel@tonic-gate 	retval = ptree_add_row_to_table(tblhdl, NUM_OF_COL_IN_PKT_TABLE,
1160*7c478bd9Sstevel@tonic-gate 								prophdl);
1161*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1162*7c478bd9Sstevel@tonic-gate 		free(hash_obj);
1163*7c478bd9Sstevel@tonic-gate 		return (retval);
1164*7c478bd9Sstevel@tonic-gate 	}
1165*7c478bd9Sstevel@tonic-gate 
1166*7c478bd9Sstevel@tonic-gate 	tagtype = get_tag_type((fru_tag_t *)&pkt->tag);
1167*7c478bd9Sstevel@tonic-gate 	if (tagtype == -1) {
1168*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1169*7c478bd9Sstevel@tonic-gate 	}
1170*7c478bd9Sstevel@tonic-gate 
1171*7c478bd9Sstevel@tonic-gate 	tag_size = get_tag_size(tagtype);
1172*7c478bd9Sstevel@tonic-gate 	if (tag_size == (size_t)-1) {
1173*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1174*7c478bd9Sstevel@tonic-gate 	}
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 	hash_obj->u.pkt_node->paylen = paylen;
1177*7c478bd9Sstevel@tonic-gate 	hash_obj->u.pkt_node->tag.raw_data = 0;
1178*7c478bd9Sstevel@tonic-gate 	(void) memcpy(&hash_obj->u.pkt_node->tag, &pkt->tag, tag_size);
1179*7c478bd9Sstevel@tonic-gate 
1180*7c478bd9Sstevel@tonic-gate 	add_nodeobject_to_hashtable(hash_obj, cont_tbl);
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate 	add_to_packet_list(seg_obj, hash_obj);
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1185*7c478bd9Sstevel@tonic-gate }
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate /*
1188*7c478bd9Sstevel@tonic-gate  * called from frudata_read_segment() callback routine. it's called after
1189*7c478bd9Sstevel@tonic-gate  * creating the packet table under class segment. this routine reads the
1190*7c478bd9Sstevel@tonic-gate  * segment data to get total number of packets in the segments and add
1191*7c478bd9Sstevel@tonic-gate  * the tag and payload data into the table. it calls add_row_to_table
1192*7c478bd9Sstevel@tonic-gate  * routine to add individual row into the packet table.
1193*7c478bd9Sstevel@tonic-gate  */
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate static int
1196*7c478bd9Sstevel@tonic-gate frudata_read_packet(picl_nodehdl_t nodeh, picl_prophdl_t *tblhdl,
1197*7c478bd9Sstevel@tonic-gate 		container_tbl_t *cont_tbl, door_cred_t *cred)
1198*7c478bd9Sstevel@tonic-gate {
1199*7c478bd9Sstevel@tonic-gate 	int		cnt;
1200*7c478bd9Sstevel@tonic-gate 	int		retval;
1201*7c478bd9Sstevel@tonic-gate 	int		num_of_pkt;
1202*7c478bd9Sstevel@tonic-gate 	packet_t	*packet;
1203*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1204*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t seg_acc_hdl;
1205*7c478bd9Sstevel@tonic-gate 
1206*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(nodeh, SEGMENT_NODE, cont_tbl);
1207*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1208*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1209*7c478bd9Sstevel@tonic-gate 	}
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 	if (hash_obj->u.seg_node->num_of_pkt == -1) {
1212*7c478bd9Sstevel@tonic-gate 		/* get the access handle */
1213*7c478bd9Sstevel@tonic-gate 		seg_acc_hdl = hash_obj->u.seg_node->segment_hdl;
1214*7c478bd9Sstevel@tonic-gate 		/* get total number of packets */
1215*7c478bd9Sstevel@tonic-gate 		num_of_pkt = fru_get_num_packets(seg_acc_hdl, cred);
1216*7c478bd9Sstevel@tonic-gate 		if (num_of_pkt < 0) {
1217*7c478bd9Sstevel@tonic-gate 			hash_obj->u.seg_node->num_of_pkt = 0;
1218*7c478bd9Sstevel@tonic-gate 			return (map_access_err(errno));
1219*7c478bd9Sstevel@tonic-gate 		}
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 		if (num_of_pkt == 0) {
1222*7c478bd9Sstevel@tonic-gate 			hash_obj->u.seg_node->num_of_pkt = 0;
1223*7c478bd9Sstevel@tonic-gate 			return (0);
1224*7c478bd9Sstevel@tonic-gate 		}
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate 		/* allocate buffer */
1227*7c478bd9Sstevel@tonic-gate 		packet = alloca(sizeof (packet_t) * num_of_pkt);
1228*7c478bd9Sstevel@tonic-gate 		if (packet == NULL) {
1229*7c478bd9Sstevel@tonic-gate 			hash_obj->u.seg_node->num_of_pkt = 0;
1230*7c478bd9Sstevel@tonic-gate 			return (0);
1231*7c478bd9Sstevel@tonic-gate 		}
1232*7c478bd9Sstevel@tonic-gate 
1233*7c478bd9Sstevel@tonic-gate 		/* get all the packet into the packet buffer */
1234*7c478bd9Sstevel@tonic-gate 		retval = fru_get_packets(seg_acc_hdl, packet, num_of_pkt, cred);
1235*7c478bd9Sstevel@tonic-gate 		if (retval == -1) {
1236*7c478bd9Sstevel@tonic-gate 			return (0);
1237*7c478bd9Sstevel@tonic-gate 		}
1238*7c478bd9Sstevel@tonic-gate 
1239*7c478bd9Sstevel@tonic-gate 		/* add payload and tag into the table. */
1240*7c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < num_of_pkt; cnt++) {
1241*7c478bd9Sstevel@tonic-gate 			(void) add_row_to_table(hash_obj, *tblhdl, packet+cnt,
1242*7c478bd9Sstevel@tonic-gate 								cont_tbl);
1243*7c478bd9Sstevel@tonic-gate 		}
1244*7c478bd9Sstevel@tonic-gate 
1245*7c478bd9Sstevel@tonic-gate 		hash_obj->u.seg_node->num_of_pkt = num_of_pkt;
1246*7c478bd9Sstevel@tonic-gate 	}
1247*7c478bd9Sstevel@tonic-gate 	return (0);
1248*7c478bd9Sstevel@tonic-gate }
1249*7c478bd9Sstevel@tonic-gate 
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate /*
1252*7c478bd9Sstevel@tonic-gate  * Description  : frudata_add_packet is called when add-packet volatile
1253*7c478bd9Sstevel@tonic-gate  *              property is accessed.
1254*7c478bd9Sstevel@tonic-gate  *
1255*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_warg_t holds node handle of the segment node and
1256*7c478bd9Sstevel@tonic-gate  *              property handle of add-packet property.
1257*7c478bd9Sstevel@tonic-gate  *              p_buf- contains packet data to be added.
1258*7c478bd9Sstevel@tonic-gate  *
1259*7c478bd9Sstevel@tonic-gate  * Return       : PICL_SUCCESS on success.
1260*7c478bd9Sstevel@tonic-gate  *
1261*7c478bd9Sstevel@tonic-gate  */
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1264*7c478bd9Sstevel@tonic-gate static int
1265*7c478bd9Sstevel@tonic-gate frudata_add_packet(ptree_warg_t *warg, const void *buf)
1266*7c478bd9Sstevel@tonic-gate {
1267*7c478bd9Sstevel@tonic-gate 	size_t		tag_size;
1268*7c478bd9Sstevel@tonic-gate 	int		paylen;
1269*7c478bd9Sstevel@tonic-gate 	int		retval;
1270*7c478bd9Sstevel@tonic-gate 	int		num_of_pkt;
1271*7c478bd9Sstevel@tonic-gate 	int		cnt;
1272*7c478bd9Sstevel@tonic-gate 	packet_t	packet;
1273*7c478bd9Sstevel@tonic-gate 	packet_t	*pkt_buf;
1274*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1275*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*pkt_hash;
1276*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
1277*7c478bd9Sstevel@tonic-gate 	fru_tagtype_t	tagtype;
1278*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	tblhdl;
1279*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t seg_acc_hdl;
1280*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t new_seg_acc_hdl;
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(warg->nodeh, SEGMENT_NODE, PICL_WRITE);
1283*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
1284*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1285*7c478bd9Sstevel@tonic-gate 	}
1286*7c478bd9Sstevel@tonic-gate 
1287*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(warg->nodeh, SEGMENT_NODE, cont_tbl);
1288*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1289*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1290*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1291*7c478bd9Sstevel@tonic-gate 	}
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate 	seg_acc_hdl = hash_obj->u.seg_node->segment_hdl;
1294*7c478bd9Sstevel@tonic-gate 
1295*7c478bd9Sstevel@tonic-gate 	tagtype = get_tag_type((void *)buf);
1296*7c478bd9Sstevel@tonic-gate 	if (tagtype == -1) {
1297*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1298*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1299*7c478bd9Sstevel@tonic-gate 	}
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate 	tag_size = get_tag_size(tagtype);
1302*7c478bd9Sstevel@tonic-gate 	if (tag_size == (size_t)-1) {
1303*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1304*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1305*7c478bd9Sstevel@tonic-gate 	}
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 	paylen = get_payload_length((void *)buf);
1308*7c478bd9Sstevel@tonic-gate 	if (paylen == -1) {
1309*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1310*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1311*7c478bd9Sstevel@tonic-gate 	}
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 	packet.tag = 0;
1314*7c478bd9Sstevel@tonic-gate 	(void) memcpy(&packet.tag, buf, tag_size);
1315*7c478bd9Sstevel@tonic-gate 
1316*7c478bd9Sstevel@tonic-gate 	retval = fru_append_packet(seg_acc_hdl, &packet, (char *)buf + tag_size,
1317*7c478bd9Sstevel@tonic-gate 					paylen, &new_seg_acc_hdl, &warg->cred);
1318*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1319*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1320*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
1321*7c478bd9Sstevel@tonic-gate 	}
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_propval_by_name(warg->nodeh,
1324*7c478bd9Sstevel@tonic-gate 		PICL_PROP_PACKET_TABLE, &tblhdl, sizeof (picl_prophdl_t));
1325*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1326*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1327*7c478bd9Sstevel@tonic-gate 		return (retval);
1328*7c478bd9Sstevel@tonic-gate 	}
1329*7c478bd9Sstevel@tonic-gate 	retval = add_row_to_table(hash_obj, tblhdl, &packet, cont_tbl);
1330*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1331*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1332*7c478bd9Sstevel@tonic-gate 		return (retval);
1333*7c478bd9Sstevel@tonic-gate 	}
1334*7c478bd9Sstevel@tonic-gate 
1335*7c478bd9Sstevel@tonic-gate 	num_of_pkt = fru_get_num_packets(new_seg_acc_hdl, &warg->cred);
1336*7c478bd9Sstevel@tonic-gate 	if (num_of_pkt == -1) {
1337*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1338*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1339*7c478bd9Sstevel@tonic-gate 	}
1340*7c478bd9Sstevel@tonic-gate 
1341*7c478bd9Sstevel@tonic-gate 	pkt_buf = alloca(sizeof (packet_t) * num_of_pkt);
1342*7c478bd9Sstevel@tonic-gate 	if (pkt_buf == NULL) {
1343*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1344*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1345*7c478bd9Sstevel@tonic-gate 	}
1346*7c478bd9Sstevel@tonic-gate 
1347*7c478bd9Sstevel@tonic-gate 	retval = fru_get_packets(new_seg_acc_hdl, pkt_buf,
1348*7c478bd9Sstevel@tonic-gate 					num_of_pkt, &warg->cred);
1349*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1350*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1351*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1352*7c478bd9Sstevel@tonic-gate 	}
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	pkt_hash	= hash_obj->u.seg_node->packet_list;
1355*7c478bd9Sstevel@tonic-gate 	if (pkt_hash == NULL) {
1356*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1357*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1358*7c478bd9Sstevel@tonic-gate 	}
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < num_of_pkt; cnt++) {
1361*7c478bd9Sstevel@tonic-gate 		pkt_hash->u.pkt_node->pkt_handle = pkt_buf[cnt].handle;
1362*7c478bd9Sstevel@tonic-gate 		pkt_hash = pkt_hash->u.pkt_node->next;
1363*7c478bd9Sstevel@tonic-gate 	}
1364*7c478bd9Sstevel@tonic-gate 
1365*7c478bd9Sstevel@tonic-gate 	hash_obj->u.seg_node->num_of_pkt = num_of_pkt;
1366*7c478bd9Sstevel@tonic-gate 
1367*7c478bd9Sstevel@tonic-gate 	(void) ptree_update_propval_by_name(warg->nodeh, PICL_PROP_NUM_TAGS,
1368*7c478bd9Sstevel@tonic-gate 				&num_of_pkt, sizeof (uint32_t));
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
1371*7c478bd9Sstevel@tonic-gate 
1372*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1373*7c478bd9Sstevel@tonic-gate }
1374*7c478bd9Sstevel@tonic-gate 
1375*7c478bd9Sstevel@tonic-gate static void
1376*7c478bd9Sstevel@tonic-gate freeup(picl_nodehdl_t nodeh)
1377*7c478bd9Sstevel@tonic-gate {
1378*7c478bd9Sstevel@tonic-gate 	(void) ptree_delete_node(nodeh);
1379*7c478bd9Sstevel@tonic-gate 	(void) ptree_destroy_node(nodeh);
1380*7c478bd9Sstevel@tonic-gate }
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate /*
1383*7c478bd9Sstevel@tonic-gate  * called by frudata_read_segment() and fru_data_add_segment() callback routine.
1384*7c478bd9Sstevel@tonic-gate  * it's called to create a segment node and all it's property beneith the
1385*7c478bd9Sstevel@tonic-gate  * segment node in the picl tree.
1386*7c478bd9Sstevel@tonic-gate  */
1387*7c478bd9Sstevel@tonic-gate 
1388*7c478bd9Sstevel@tonic-gate static int
1389*7c478bd9Sstevel@tonic-gate create_segment_node(hash_obj_t *sec_obj, picl_nodehdl_t sec_node,
1390*7c478bd9Sstevel@tonic-gate 	segment_t *segment, container_tbl_t *cont_tbl, door_cred_t *cred)
1391*7c478bd9Sstevel@tonic-gate {
1392*7c478bd9Sstevel@tonic-gate 
1393*7c478bd9Sstevel@tonic-gate 	int			retval;
1394*7c478bd9Sstevel@tonic-gate 	char			segname[SEG_NAME_LEN + 1];
1395*7c478bd9Sstevel@tonic-gate 	uint32_t		numoftags = 0;
1396*7c478bd9Sstevel@tonic-gate 	uint32_t		protection;
1397*7c478bd9Sstevel@tonic-gate 	hash_obj_t		*hash_obj;
1398*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		nodehdl;
1399*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		prophdl;
1400*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t		tblhdl;
1401*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	prop;
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(segname, segment->name, SEG_NAME_LEN + 1);
1404*7c478bd9Sstevel@tonic-gate 	segname[SEG_NAME_LEN] = '\0';
1405*7c478bd9Sstevel@tonic-gate 
1406*7c478bd9Sstevel@tonic-gate 	if (!(isprint(segname[0]) || isprint(segname[1]))) {
1407*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1408*7c478bd9Sstevel@tonic-gate 	}
1409*7c478bd9Sstevel@tonic-gate 
1410*7c478bd9Sstevel@tonic-gate 	if (ptree_create_node(segname, PICL_CLASS_SEGMENT, &nodehdl)
1411*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1412*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1413*7c478bd9Sstevel@tonic-gate 	}
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate 	/* create property node */
1417*7c478bd9Sstevel@tonic-gate 	prop.version = PTREE_PROPINFO_VERSION;
1418*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_READ;
1419*7c478bd9Sstevel@tonic-gate 	prop.read		= NULL;
1420*7c478bd9Sstevel@tonic-gate 	prop.write		= NULL;
1421*7c478bd9Sstevel@tonic-gate 
1422*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type =  PICL_PTYPE_UNSIGNED_INT;
1423*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = sizeof (uint32_t);
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate 	/* descriptor property */
1426*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_DESCRIPTOR);
1427*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(nodehdl, &prop, &segment->descriptor,
1428*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1429*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1430*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1431*7c478bd9Sstevel@tonic-gate 	}
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 
1434*7c478bd9Sstevel@tonic-gate 	/* offset property */
1435*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_OFFSET);
1436*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(nodehdl, &prop, &segment->offset,
1437*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1438*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1439*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1440*7c478bd9Sstevel@tonic-gate 	}
1441*7c478bd9Sstevel@tonic-gate 
1442*7c478bd9Sstevel@tonic-gate 
1443*7c478bd9Sstevel@tonic-gate 	/* length property */
1444*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_LENGTH);
1445*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(nodehdl, &prop, &segment->length,
1446*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1447*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1448*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1449*7c478bd9Sstevel@tonic-gate 	}
1450*7c478bd9Sstevel@tonic-gate 
1451*7c478bd9Sstevel@tonic-gate 	/* Number of Tags */
1452*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_NUM_TAGS);
1453*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(nodehdl, &prop, &numoftags, &prophdl)
1454*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1455*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1456*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1457*7c478bd9Sstevel@tonic-gate 	}
1458*7c478bd9Sstevel@tonic-gate 
1459*7c478bd9Sstevel@tonic-gate 	if (create_packet_table(nodehdl, &tblhdl) != PICL_SUCCESS) {
1460*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1461*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1462*7c478bd9Sstevel@tonic-gate 	}
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_propval_by_name(sec_node,
1465*7c478bd9Sstevel@tonic-gate 			PICL_PROP_PROTECTED, &protection, sizeof (uint32_t));
1466*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
1467*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1468*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1469*7c478bd9Sstevel@tonic-gate 	}
1470*7c478bd9Sstevel@tonic-gate 
1471*7c478bd9Sstevel@tonic-gate 	if (protection == 0) {	/* to be added only read/write section */
1472*7c478bd9Sstevel@tonic-gate 		/* delete segment volatile property */
1473*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.type =  PICL_PTYPE_UNSIGNED_INT;
1474*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.size = sizeof (uint32_t);
1475*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.accessmode = PICL_WRITE|PICL_VOLATILE;
1476*7c478bd9Sstevel@tonic-gate 		prop.write = frudata_delete_segment;
1477*7c478bd9Sstevel@tonic-gate 		prop.read = frudata_read_callback;
1478*7c478bd9Sstevel@tonic-gate 
1479*7c478bd9Sstevel@tonic-gate 		(void) strcpy(prop.piclinfo.name, PICL_PROP_DELETE_SEGMENT);
1480*7c478bd9Sstevel@tonic-gate 		if (ptree_create_and_add_prop(nodehdl, &prop, NULL, &prophdl)
1481*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1482*7c478bd9Sstevel@tonic-gate 			freeup(nodehdl);
1483*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
1484*7c478bd9Sstevel@tonic-gate 		}
1485*7c478bd9Sstevel@tonic-gate 
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 		/* add packet volatile property */
1488*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.type =  PICL_PTYPE_BYTEARRAY;
1489*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.size = segment->length; /* segment length */
1490*7c478bd9Sstevel@tonic-gate 		prop.piclinfo.accessmode = PICL_READ|PICL_WRITE|PICL_VOLATILE;
1491*7c478bd9Sstevel@tonic-gate 		prop.read = frudata_read_callback;
1492*7c478bd9Sstevel@tonic-gate 		prop.write = frudata_add_packet;
1493*7c478bd9Sstevel@tonic-gate 
1494*7c478bd9Sstevel@tonic-gate 		(void) strcpy(prop.piclinfo.name, PICL_PROP_ADD_PACKET);
1495*7c478bd9Sstevel@tonic-gate 		if (ptree_create_and_add_prop(nodehdl, &prop, NULL, &prophdl)
1496*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1497*7c478bd9Sstevel@tonic-gate 			freeup(nodehdl);
1498*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
1499*7c478bd9Sstevel@tonic-gate 		}
1500*7c478bd9Sstevel@tonic-gate 	}
1501*7c478bd9Sstevel@tonic-gate 
1502*7c478bd9Sstevel@tonic-gate 	if (ptree_add_node(sec_node, nodehdl) != PICL_SUCCESS) {
1503*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1504*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1505*7c478bd9Sstevel@tonic-gate 	}
1506*7c478bd9Sstevel@tonic-gate 
1507*7c478bd9Sstevel@tonic-gate 	hash_obj = alloc_segment_node_object(nodehdl, segment);
1508*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1509*7c478bd9Sstevel@tonic-gate 		freeup(nodehdl);
1510*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1511*7c478bd9Sstevel@tonic-gate 	}
1512*7c478bd9Sstevel@tonic-gate 
1513*7c478bd9Sstevel@tonic-gate 	add_nodeobject_to_hashtable(hash_obj, cont_tbl);
1514*7c478bd9Sstevel@tonic-gate 
1515*7c478bd9Sstevel@tonic-gate 	add_to_segment_list(sec_obj, hash_obj);
1516*7c478bd9Sstevel@tonic-gate 
1517*7c478bd9Sstevel@tonic-gate 	retval = frudata_read_packet(nodehdl, &tblhdl, cont_tbl, cred);
1518*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1519*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
1520*7c478bd9Sstevel@tonic-gate 	}
1521*7c478bd9Sstevel@tonic-gate 
1522*7c478bd9Sstevel@tonic-gate 	(void) ptree_update_propval_by_name(nodehdl, PICL_PROP_NUM_TAGS,
1523*7c478bd9Sstevel@tonic-gate 		&hash_obj->u.seg_node->num_of_pkt, sizeof (uint32_t));
1524*7c478bd9Sstevel@tonic-gate 
1525*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1526*7c478bd9Sstevel@tonic-gate }
1527*7c478bd9Sstevel@tonic-gate 
1528*7c478bd9Sstevel@tonic-gate /*
1529*7c478bd9Sstevel@tonic-gate  * Description  :frudata_read_segment is called when num_segment volatile
1530*7c478bd9Sstevel@tonic-gate  *              property is accessed.
1531*7c478bd9Sstevel@tonic-gate  *
1532*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_rarg_t  contains node handle of the section node.
1533*7c478bd9Sstevel@tonic-gate  *                      and property node of num_segments.
1534*7c478bd9Sstevel@tonic-gate  *              void * will hold number of segment.
1535*7c478bd9Sstevel@tonic-gate  *
1536*7c478bd9Sstevel@tonic-gate  * Returns      : PICL_SUCCESS on success.
1537*7c478bd9Sstevel@tonic-gate  *              PICL_FAILURE on failure.
1538*7c478bd9Sstevel@tonic-gate  */
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate static int
1541*7c478bd9Sstevel@tonic-gate frudata_read_segment(ptree_rarg_t *rarg, void *buf)
1542*7c478bd9Sstevel@tonic-gate {
1543*7c478bd9Sstevel@tonic-gate 	int		num_of_segment;
1544*7c478bd9Sstevel@tonic-gate 	int		cnt;
1545*7c478bd9Sstevel@tonic-gate 	int		retval;
1546*7c478bd9Sstevel@tonic-gate 	segment_t	*segment;
1547*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1548*7c478bd9Sstevel@tonic-gate 	fru_segdesc_t	*desc;
1549*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t sec_acc_hdl;
1550*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
1551*7c478bd9Sstevel@tonic-gate 
1552*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(rarg->nodeh, SECTION_NODE, PICL_READ);
1553*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
1554*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1555*7c478bd9Sstevel@tonic-gate 	}
1556*7c478bd9Sstevel@tonic-gate 
1557*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(rarg->nodeh, SECTION_NODE, cont_tbl);
1558*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1559*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1560*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1561*7c478bd9Sstevel@tonic-gate 	}
1562*7c478bd9Sstevel@tonic-gate 
1563*7c478bd9Sstevel@tonic-gate 	if (hash_obj->u.sec_node->num_of_segment == -1) {
1564*7c478bd9Sstevel@tonic-gate 		sec_acc_hdl	= hash_obj->u.sec_node->section_hdl;
1565*7c478bd9Sstevel@tonic-gate 
1566*7c478bd9Sstevel@tonic-gate 		hash_obj->u.sec_node->num_of_segment = 0;
1567*7c478bd9Sstevel@tonic-gate 
1568*7c478bd9Sstevel@tonic-gate 		num_of_segment = fru_get_num_segments(sec_acc_hdl,
1569*7c478bd9Sstevel@tonic-gate 						&rarg->cred);
1570*7c478bd9Sstevel@tonic-gate 		if (num_of_segment < 0) {
1571*7c478bd9Sstevel@tonic-gate 			*(int *)buf = 0;
1572*7c478bd9Sstevel@tonic-gate 			unlock_container_lock(cont_tbl);
1573*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
1574*7c478bd9Sstevel@tonic-gate 		}
1575*7c478bd9Sstevel@tonic-gate 
1576*7c478bd9Sstevel@tonic-gate 		if (num_of_segment == 0) {
1577*7c478bd9Sstevel@tonic-gate 			*(int *)buf = 0;
1578*7c478bd9Sstevel@tonic-gate 			unlock_container_lock(cont_tbl);
1579*7c478bd9Sstevel@tonic-gate 			return (PICL_SUCCESS);
1580*7c478bd9Sstevel@tonic-gate 		}
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 		segment = alloca(sizeof (segment_t) * num_of_segment);
1583*7c478bd9Sstevel@tonic-gate 		if (segment == NULL) {
1584*7c478bd9Sstevel@tonic-gate 			*(int *)buf = 0;
1585*7c478bd9Sstevel@tonic-gate 			unlock_container_lock(cont_tbl);
1586*7c478bd9Sstevel@tonic-gate 			return (PICL_SUCCESS);
1587*7c478bd9Sstevel@tonic-gate 		}
1588*7c478bd9Sstevel@tonic-gate 
1589*7c478bd9Sstevel@tonic-gate 		retval = fru_get_segments(sec_acc_hdl, segment,
1590*7c478bd9Sstevel@tonic-gate 					num_of_segment, &rarg->cred);
1591*7c478bd9Sstevel@tonic-gate 		if (retval == -1) {
1592*7c478bd9Sstevel@tonic-gate 			*(int *)buf = 0;
1593*7c478bd9Sstevel@tonic-gate 			unlock_container_lock(cont_tbl);
1594*7c478bd9Sstevel@tonic-gate 			return (PICL_SUCCESS);
1595*7c478bd9Sstevel@tonic-gate 		}
1596*7c478bd9Sstevel@tonic-gate 
1597*7c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < num_of_segment; cnt++) {
1598*7c478bd9Sstevel@tonic-gate 
1599*7c478bd9Sstevel@tonic-gate 			desc	= (fru_segdesc_t *)&segment[cnt].descriptor;
1600*7c478bd9Sstevel@tonic-gate 			if (!(desc->field.field_perm & SEGMENT_READ)) {
1601*7c478bd9Sstevel@tonic-gate 				continue;
1602*7c478bd9Sstevel@tonic-gate 			}
1603*7c478bd9Sstevel@tonic-gate 
1604*7c478bd9Sstevel@tonic-gate 			/* if opaque segment don't create segment node */
1605*7c478bd9Sstevel@tonic-gate 			if (desc->field.opaque) {
1606*7c478bd9Sstevel@tonic-gate 				continue;
1607*7c478bd9Sstevel@tonic-gate 			}
1608*7c478bd9Sstevel@tonic-gate 			(void) create_segment_node(hash_obj, rarg->nodeh,
1609*7c478bd9Sstevel@tonic-gate 			&segment[cnt], cont_tbl, &rarg->cred);
1610*7c478bd9Sstevel@tonic-gate 			hash_obj->u.sec_node->num_of_segment++;
1611*7c478bd9Sstevel@tonic-gate 		}
1612*7c478bd9Sstevel@tonic-gate 	}
1613*7c478bd9Sstevel@tonic-gate 
1614*7c478bd9Sstevel@tonic-gate 	/* return number of segment in the section */
1615*7c478bd9Sstevel@tonic-gate 	*(int *)buf = hash_obj->u.sec_node->num_of_segment;
1616*7c478bd9Sstevel@tonic-gate 
1617*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
1618*7c478bd9Sstevel@tonic-gate 
1619*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1620*7c478bd9Sstevel@tonic-gate }
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate 
1623*7c478bd9Sstevel@tonic-gate /*
1624*7c478bd9Sstevel@tonic-gate  * Description : frudata_add_segment is called when volatile property
1625*7c478bd9Sstevel@tonic-gate  *              add_segment under class node section is accessed.
1626*7c478bd9Sstevel@tonic-gate  *
1627*7c478bd9Sstevel@tonic-gate  * Arguments    : ptree_warg_t  holds node handle for the section node.
1628*7c478bd9Sstevel@tonic-gate  *              property handle for the add_segment property.
1629*7c478bd9Sstevel@tonic-gate  *
1630*7c478bd9Sstevel@tonic-gate  * Returns      : PICL_SUCCESS on success.
1631*7c478bd9Sstevel@tonic-gate  *              PICL_FAILURE on failure.
1632*7c478bd9Sstevel@tonic-gate  */
1633*7c478bd9Sstevel@tonic-gate 
1634*7c478bd9Sstevel@tonic-gate static int
1635*7c478bd9Sstevel@tonic-gate frudata_add_segment(ptree_warg_t *warg, const void *buf)
1636*7c478bd9Sstevel@tonic-gate {
1637*7c478bd9Sstevel@tonic-gate 	int		retval;
1638*7c478bd9Sstevel@tonic-gate 	int		cnt;
1639*7c478bd9Sstevel@tonic-gate 	int		num_of_segment;
1640*7c478bd9Sstevel@tonic-gate 	segment_t	*seg_buf;
1641*7c478bd9Sstevel@tonic-gate 	segment_t	segment;
1642*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*seg_hash;
1643*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1644*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
1645*7c478bd9Sstevel@tonic-gate 	fru_segdef_t	*seg_def;
1646*7c478bd9Sstevel@tonic-gate 	fru_segdesc_t	*desc;
1647*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t new_sec_acc_hdl;
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 	seg_def	= (fru_segdef_t *)buf;
1650*7c478bd9Sstevel@tonic-gate 
1651*7c478bd9Sstevel@tonic-gate 	/* initialize segment_t */
1652*7c478bd9Sstevel@tonic-gate 	segment.handle	= 0;
1653*7c478bd9Sstevel@tonic-gate 	(void) memcpy(segment.name, seg_def->name, SEG_NAME_LEN);
1654*7c478bd9Sstevel@tonic-gate 	segment.descriptor =  seg_def->desc.raw_data;
1655*7c478bd9Sstevel@tonic-gate 	segment.length	= seg_def->size;	/* segment length */
1656*7c478bd9Sstevel@tonic-gate 	segment.offset = seg_def->address;	/* segment offset */
1657*7c478bd9Sstevel@tonic-gate 
1658*7c478bd9Sstevel@tonic-gate 	desc    = (fru_segdesc_t *)&segment.descriptor;
1659*7c478bd9Sstevel@tonic-gate 	if (!(desc->field.field_perm & SEGMENT_READ)) {
1660*7c478bd9Sstevel@tonic-gate 		return (PICL_PERMDENIED);
1661*7c478bd9Sstevel@tonic-gate 	}
1662*7c478bd9Sstevel@tonic-gate 
1663*7c478bd9Sstevel@tonic-gate 	cont_tbl = lock_container_lock(warg->nodeh, SECTION_NODE, PICL_WRITE);
1664*7c478bd9Sstevel@tonic-gate 	if (!cont_tbl) {
1665*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1666*7c478bd9Sstevel@tonic-gate 	}
1667*7c478bd9Sstevel@tonic-gate 
1668*7c478bd9Sstevel@tonic-gate 	hash_obj = lookup_node_object(warg->nodeh, SECTION_NODE, cont_tbl);
1669*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1670*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1671*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1672*7c478bd9Sstevel@tonic-gate 	}
1673*7c478bd9Sstevel@tonic-gate 
1674*7c478bd9Sstevel@tonic-gate 	/* call fruaccess module, get the new section handle. */
1675*7c478bd9Sstevel@tonic-gate 	retval = fru_add_segment(hash_obj->u.sec_node->section_hdl,
1676*7c478bd9Sstevel@tonic-gate 			&segment, &new_sec_acc_hdl, &warg->cred);
1677*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1678*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1679*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
1680*7c478bd9Sstevel@tonic-gate 	}
1681*7c478bd9Sstevel@tonic-gate 
1682*7c478bd9Sstevel@tonic-gate 	/* call access module with new section handle */
1683*7c478bd9Sstevel@tonic-gate 	num_of_segment = fru_get_num_segments(new_sec_acc_hdl, &warg->cred);
1684*7c478bd9Sstevel@tonic-gate 
1685*7c478bd9Sstevel@tonic-gate 	seg_buf	= alloca(sizeof (segment_t) * num_of_segment);
1686*7c478bd9Sstevel@tonic-gate 	if (seg_buf == NULL) {
1687*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1688*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1689*7c478bd9Sstevel@tonic-gate 	}
1690*7c478bd9Sstevel@tonic-gate 
1691*7c478bd9Sstevel@tonic-gate 	retval = fru_get_segments(new_sec_acc_hdl, seg_buf,
1692*7c478bd9Sstevel@tonic-gate 					num_of_segment, &warg->cred);
1693*7c478bd9Sstevel@tonic-gate 	if (retval ==  -1) {
1694*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1695*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1696*7c478bd9Sstevel@tonic-gate 	}
1697*7c478bd9Sstevel@tonic-gate 
1698*7c478bd9Sstevel@tonic-gate 	segment.offset	= seg_buf[(num_of_segment -1)].offset;
1699*7c478bd9Sstevel@tonic-gate 	segment.handle = seg_buf[(num_of_segment-1)].handle;
1700*7c478bd9Sstevel@tonic-gate 
1701*7c478bd9Sstevel@tonic-gate 	(void) create_segment_node(hash_obj, warg->nodeh, &segment,
1702*7c478bd9Sstevel@tonic-gate 						cont_tbl, &warg->cred);
1703*7c478bd9Sstevel@tonic-gate 
1704*7c478bd9Sstevel@tonic-gate 	/* rebuild  segment list */
1705*7c478bd9Sstevel@tonic-gate 	seg_hash = hash_obj->u.sec_node->segment_list;
1706*7c478bd9Sstevel@tonic-gate 	if (seg_hash == NULL) {
1707*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1708*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1709*7c478bd9Sstevel@tonic-gate 	}
1710*7c478bd9Sstevel@tonic-gate 
1711*7c478bd9Sstevel@tonic-gate 	hash_obj->u.sec_node->num_of_segment = 0;
1712*7c478bd9Sstevel@tonic-gate 
1713*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < num_of_segment; cnt++) {
1714*7c478bd9Sstevel@tonic-gate 		desc	= (fru_segdesc_t *)&seg_buf[cnt].descriptor;
1715*7c478bd9Sstevel@tonic-gate 		if (!(desc->field.field_perm & SEGMENT_READ)) {
1716*7c478bd9Sstevel@tonic-gate 			continue;
1717*7c478bd9Sstevel@tonic-gate 		}
1718*7c478bd9Sstevel@tonic-gate 
1719*7c478bd9Sstevel@tonic-gate 		/* if opaque segment don't create segment node */
1720*7c478bd9Sstevel@tonic-gate 		if (desc->field.opaque) {
1721*7c478bd9Sstevel@tonic-gate 			continue;
1722*7c478bd9Sstevel@tonic-gate 		}
1723*7c478bd9Sstevel@tonic-gate 
1724*7c478bd9Sstevel@tonic-gate 		seg_hash->u.seg_node->segment_hdl =
1725*7c478bd9Sstevel@tonic-gate 				seg_buf[cnt].handle;
1726*7c478bd9Sstevel@tonic-gate 		seg_hash = seg_hash->u.seg_node->next;
1727*7c478bd9Sstevel@tonic-gate 		hash_obj->u.sec_node->num_of_segment++;
1728*7c478bd9Sstevel@tonic-gate 	}
1729*7c478bd9Sstevel@tonic-gate 
1730*7c478bd9Sstevel@tonic-gate 	/* update with new section handle */
1731*7c478bd9Sstevel@tonic-gate 	hash_obj->u.sec_node->section_hdl = new_sec_acc_hdl;
1732*7c478bd9Sstevel@tonic-gate 
1733*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
1734*7c478bd9Sstevel@tonic-gate 
1735*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1736*7c478bd9Sstevel@tonic-gate }
1737*7c478bd9Sstevel@tonic-gate 
1738*7c478bd9Sstevel@tonic-gate /*
1739*7c478bd9Sstevel@tonic-gate  * called from frudata_write_section() callback routine to create
1740*7c478bd9Sstevel@tonic-gate  * section node and all the  property under class section. it also
1741*7c478bd9Sstevel@tonic-gate  * allocate hash node object for each section in the container and
1742*7c478bd9Sstevel@tonic-gate  * add the section node object in the section list.
1743*7c478bd9Sstevel@tonic-gate  */
1744*7c478bd9Sstevel@tonic-gate 
1745*7c478bd9Sstevel@tonic-gate static int
1746*7c478bd9Sstevel@tonic-gate create_section_node(picl_nodehdl_t nodehdl, int section_count,
1747*7c478bd9Sstevel@tonic-gate 				section_t *section, container_tbl_t *cont_tbl)
1748*7c478bd9Sstevel@tonic-gate {
1749*7c478bd9Sstevel@tonic-gate 	char		sec_name[SECNAMESIZE];
1750*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1751*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*cont_hash;
1752*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	chld_node;
1753*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	prophdl;
1754*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t prop;
1755*7c478bd9Sstevel@tonic-gate 
1756*7c478bd9Sstevel@tonic-gate 	(void) snprintf(sec_name, SECNAMESIZE, "section%d", section_count);
1757*7c478bd9Sstevel@tonic-gate 
1758*7c478bd9Sstevel@tonic-gate 	if (ptree_create_node(sec_name, PICL_CLASS_SECTION, &chld_node)
1759*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1760*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1761*7c478bd9Sstevel@tonic-gate 	}
1762*7c478bd9Sstevel@tonic-gate 	prop.version		= PTREE_PROPINFO_VERSION;
1763*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type	= PICL_PTYPE_UNSIGNED_INT;
1764*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_READ;
1765*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size	= sizeof (uint32_t);
1766*7c478bd9Sstevel@tonic-gate 	prop.read		= NULL;
1767*7c478bd9Sstevel@tonic-gate 	prop.write		= NULL;
1768*7c478bd9Sstevel@tonic-gate 
1769*7c478bd9Sstevel@tonic-gate 	/* offset */
1770*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_OFFSET);
1771*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(chld_node, &prop, &section->offset,
1772*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1773*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1774*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1775*7c478bd9Sstevel@tonic-gate 	}
1776*7c478bd9Sstevel@tonic-gate 
1777*7c478bd9Sstevel@tonic-gate 	/* length */
1778*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_LENGTH);
1779*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(chld_node, &prop, &section->length,
1780*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1781*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1782*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1783*7c478bd9Sstevel@tonic-gate 	}
1784*7c478bd9Sstevel@tonic-gate 
1785*7c478bd9Sstevel@tonic-gate 
1786*7c478bd9Sstevel@tonic-gate 	/* protected */
1787*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_PROTECTED);
1788*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(chld_node, &prop, &section->protection,
1789*7c478bd9Sstevel@tonic-gate 						&prophdl) != PICL_SUCCESS) {
1790*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1791*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1792*7c478bd9Sstevel@tonic-gate 	}
1793*7c478bd9Sstevel@tonic-gate 
1794*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode	= PICL_READ|PICL_VOLATILE;
1795*7c478bd9Sstevel@tonic-gate 	prop.read	= frudata_read_segment;
1796*7c478bd9Sstevel@tonic-gate 
1797*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_NUM_SEGMENTS);
1798*7c478bd9Sstevel@tonic-gate 
1799*7c478bd9Sstevel@tonic-gate 	if (ptree_create_and_add_prop(chld_node, &prop, NULL, &prophdl)
1800*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1801*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1802*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1803*7c478bd9Sstevel@tonic-gate 	}
1804*7c478bd9Sstevel@tonic-gate 
1805*7c478bd9Sstevel@tonic-gate 
1806*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type = PICL_PTYPE_BYTEARRAY;
1807*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = sizeof (fru_segdef_t);
1808*7c478bd9Sstevel@tonic-gate 
1809*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_WRITE|PICL_READ|PICL_VOLATILE;
1810*7c478bd9Sstevel@tonic-gate 	prop.write = frudata_add_segment; /* callback routine */
1811*7c478bd9Sstevel@tonic-gate 	prop.read = frudata_read_callback;
1812*7c478bd9Sstevel@tonic-gate 
1813*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_ADD_SEGMENT);
1814*7c478bd9Sstevel@tonic-gate 	/* add-segment prop if read/write section */
1815*7c478bd9Sstevel@tonic-gate 	if (section->protection == 0) {
1816*7c478bd9Sstevel@tonic-gate 		if (ptree_create_and_add_prop(chld_node, &prop, NULL, &prophdl)
1817*7c478bd9Sstevel@tonic-gate 							!= PICL_SUCCESS) {
1818*7c478bd9Sstevel@tonic-gate 			freeup(chld_node);
1819*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
1820*7c478bd9Sstevel@tonic-gate 		}
1821*7c478bd9Sstevel@tonic-gate 	}
1822*7c478bd9Sstevel@tonic-gate 
1823*7c478bd9Sstevel@tonic-gate 	if (ptree_add_node(nodehdl, chld_node) != PICL_SUCCESS) {
1824*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1825*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1826*7c478bd9Sstevel@tonic-gate 	}
1827*7c478bd9Sstevel@tonic-gate 
1828*7c478bd9Sstevel@tonic-gate 	/* lookup for container handle */
1829*7c478bd9Sstevel@tonic-gate 	cont_hash = lookup_node_object(nodehdl, CONTAINER_NODE, cont_tbl);
1830*7c478bd9Sstevel@tonic-gate 	if (cont_hash == NULL) {
1831*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1832*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1833*7c478bd9Sstevel@tonic-gate 	}
1834*7c478bd9Sstevel@tonic-gate 
1835*7c478bd9Sstevel@tonic-gate 	hash_obj = alloc_section_node_object(chld_node, section);
1836*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1837*7c478bd9Sstevel@tonic-gate 		freeup(chld_node);
1838*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1839*7c478bd9Sstevel@tonic-gate 	}
1840*7c478bd9Sstevel@tonic-gate 
1841*7c478bd9Sstevel@tonic-gate 	add_nodeobject_to_hashtable(hash_obj, cont_tbl);
1842*7c478bd9Sstevel@tonic-gate 
1843*7c478bd9Sstevel@tonic-gate 	add_to_section_list(cont_hash, hash_obj);
1844*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1845*7c478bd9Sstevel@tonic-gate }
1846*7c478bd9Sstevel@tonic-gate 
1847*7c478bd9Sstevel@tonic-gate 
1848*7c478bd9Sstevel@tonic-gate /*
1849*7c478bd9Sstevel@tonic-gate  * Description  :frudata_write_section is called when volatile container
1850*7c478bd9Sstevel@tonic-gate  *              property is accessed. it reads the section table associated
1851*7c478bd9Sstevel@tonic-gate  *              with the specified node handle(container) in ptree_rarg_t.
1852*7c478bd9Sstevel@tonic-gate  *              it calls search_root_node to search the node handle to open the
1853*7c478bd9Sstevel@tonic-gate  *              device associated with the node handle. it creates section
1854*7c478bd9Sstevel@tonic-gate  *              node and it's associated property. it also creates
1855*7c478bd9Sstevel@tonic-gate  *              volatile property num_segments.
1856*7c478bd9Sstevel@tonic-gate  *
1857*7c478bd9Sstevel@tonic-gate  * Argument     : ptree_rarg_t  : contains node handle of fru container the
1858*7c478bd9Sstevel@tonic-gate  *                                                      container.
1859*7c478bd9Sstevel@tonic-gate  *              property handle of the container.
1860*7c478bd9Sstevel@tonic-gate  *
1861*7c478bd9Sstevel@tonic-gate  * Return       : PICL_SUCCESS  on success.
1862*7c478bd9Sstevel@tonic-gate  *
1863*7c478bd9Sstevel@tonic-gate  */
1864*7c478bd9Sstevel@tonic-gate 
1865*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1866*7c478bd9Sstevel@tonic-gate 
1867*7c478bd9Sstevel@tonic-gate static int
1868*7c478bd9Sstevel@tonic-gate frudata_write_section(ptree_warg_t *warg, const void *buf)
1869*7c478bd9Sstevel@tonic-gate {
1870*7c478bd9Sstevel@tonic-gate 	int		retval;
1871*7c478bd9Sstevel@tonic-gate 	int		num_of_section;
1872*7c478bd9Sstevel@tonic-gate 	int		count;
1873*7c478bd9Sstevel@tonic-gate 	section_t	*section;
1874*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*hash_obj;
1875*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl = NULL;
1876*7c478bd9Sstevel@tonic-gate 	fru_access_hdl_t cont_acc_hdl;
1877*7c478bd9Sstevel@tonic-gate 
1878*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&cont_tbl_lock);
1879*7c478bd9Sstevel@tonic-gate 
1880*7c478bd9Sstevel@tonic-gate 	/*
1881*7c478bd9Sstevel@tonic-gate 	 * if lookup succeed return from this function with PICL_SUCCESS
1882*7c478bd9Sstevel@tonic-gate 	 * because first write operation has already occurred on this container,
1883*7c478bd9Sstevel@tonic-gate 	 * it also means that the container has been already initialzed.
1884*7c478bd9Sstevel@tonic-gate 	 */
1885*7c478bd9Sstevel@tonic-gate 
1886*7c478bd9Sstevel@tonic-gate 	cont_tbl = lookup_container_table(warg->nodeh, CONTAINER_NODE);
1887*7c478bd9Sstevel@tonic-gate 	if (cont_tbl != NULL) { /* found the hash obj in the hash table */
1888*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&cont_tbl_lock);
1889*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
1890*7c478bd9Sstevel@tonic-gate 	}
1891*7c478bd9Sstevel@tonic-gate 
1892*7c478bd9Sstevel@tonic-gate 	/*
1893*7c478bd9Sstevel@tonic-gate 	 * lookup failed that means this is first write on the
1894*7c478bd9Sstevel@tonic-gate 	 * container property. allocate a new container hash table for this
1895*7c478bd9Sstevel@tonic-gate 	 * new container and add to the cont_tbl hash table.
1896*7c478bd9Sstevel@tonic-gate 	 */
1897*7c478bd9Sstevel@tonic-gate 
1898*7c478bd9Sstevel@tonic-gate 	cont_tbl = alloc_container_table(warg->nodeh);
1899*7c478bd9Sstevel@tonic-gate 	if (cont_tbl == NULL) {
1900*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&cont_tbl_lock);
1901*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
1902*7c478bd9Sstevel@tonic-gate 	}
1903*7c478bd9Sstevel@tonic-gate 
1904*7c478bd9Sstevel@tonic-gate 	hash_obj = alloc_container_node_object(warg->nodeh);
1905*7c478bd9Sstevel@tonic-gate 	if (hash_obj == NULL) {
1906*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&cont_tbl_lock);
1907*7c478bd9Sstevel@tonic-gate 		return (map_access_err(errno));
1908*7c478bd9Sstevel@tonic-gate 	}
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate 	/* add container table object to container table */
1911*7c478bd9Sstevel@tonic-gate 	add_tblobject_to_container_tbl(cont_tbl);
1912*7c478bd9Sstevel@tonic-gate 
1913*7c478bd9Sstevel@tonic-gate 	/* add the hash object to container hash table. */
1914*7c478bd9Sstevel@tonic-gate 	add_nodeobject_to_hashtable(hash_obj, cont_tbl);
1915*7c478bd9Sstevel@tonic-gate 
1916*7c478bd9Sstevel@tonic-gate 	while (pthread_rwlock_trywrlock(&cont_tbl->rwlock) == EBUSY) {
1917*7c478bd9Sstevel@tonic-gate 		pthread_cond_wait(&cont_tbl->cond_var, &cont_tbl_lock);
1918*7c478bd9Sstevel@tonic-gate 	}
1919*7c478bd9Sstevel@tonic-gate 
1920*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&cont_tbl_lock);
1921*7c478bd9Sstevel@tonic-gate 
1922*7c478bd9Sstevel@tonic-gate 	/* fruaccess  handle */
1923*7c478bd9Sstevel@tonic-gate 	cont_acc_hdl	= hash_obj->u.cont_node->cont_hdl;
1924*7c478bd9Sstevel@tonic-gate 
1925*7c478bd9Sstevel@tonic-gate 	num_of_section = fru_get_num_sections(cont_acc_hdl, &warg->cred);
1926*7c478bd9Sstevel@tonic-gate 
1927*7c478bd9Sstevel@tonic-gate 	if (num_of_section == -1) {
1928*7c478bd9Sstevel@tonic-gate 		free(hash_obj);
1929*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1930*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1931*7c478bd9Sstevel@tonic-gate 	}
1932*7c478bd9Sstevel@tonic-gate 
1933*7c478bd9Sstevel@tonic-gate 	section	= alloca(num_of_section * sizeof (section_t));
1934*7c478bd9Sstevel@tonic-gate 
1935*7c478bd9Sstevel@tonic-gate 	retval = fru_get_sections(cont_acc_hdl, section,
1936*7c478bd9Sstevel@tonic-gate 					num_of_section, &warg->cred);
1937*7c478bd9Sstevel@tonic-gate 	if (retval == -1) {
1938*7c478bd9Sstevel@tonic-gate 		free(hash_obj);
1939*7c478bd9Sstevel@tonic-gate 		unlock_container_lock(cont_tbl);
1940*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1941*7c478bd9Sstevel@tonic-gate 	}
1942*7c478bd9Sstevel@tonic-gate 
1943*7c478bd9Sstevel@tonic-gate 	hash_obj->u.cont_node->num_of_section = num_of_section;
1944*7c478bd9Sstevel@tonic-gate 
1945*7c478bd9Sstevel@tonic-gate 	for (count = 0; count < num_of_section; count++) {
1946*7c478bd9Sstevel@tonic-gate 		(void) create_section_node(warg->nodeh, count,
1947*7c478bd9Sstevel@tonic-gate 					section + count, cont_tbl);
1948*7c478bd9Sstevel@tonic-gate 	}
1949*7c478bd9Sstevel@tonic-gate 
1950*7c478bd9Sstevel@tonic-gate 	unlock_container_lock(cont_tbl);
1951*7c478bd9Sstevel@tonic-gate 
1952*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1953*7c478bd9Sstevel@tonic-gate }
1954*7c478bd9Sstevel@tonic-gate 
1955*7c478bd9Sstevel@tonic-gate /* create container and add-segment property */
1956*7c478bd9Sstevel@tonic-gate 
1957*7c478bd9Sstevel@tonic-gate static int
1958*7c478bd9Sstevel@tonic-gate create_container_prop(picl_nodehdl_t	fruhdl)
1959*7c478bd9Sstevel@tonic-gate {
1960*7c478bd9Sstevel@tonic-gate 	int			retval;
1961*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		prophdl;
1962*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	prop;
1963*7c478bd9Sstevel@tonic-gate 
1964*7c478bd9Sstevel@tonic-gate 	prop.version = PTREE_PROPINFO_VERSION;
1965*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.type = PICL_PTYPE_UNSIGNED_INT;
1966*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.size = sizeof (uint32_t);
1967*7c478bd9Sstevel@tonic-gate 	prop.piclinfo.accessmode = PICL_WRITE|PICL_VOLATILE;
1968*7c478bd9Sstevel@tonic-gate 	(void) strcpy(prop.piclinfo.name, PICL_PROP_CONTAINER);
1969*7c478bd9Sstevel@tonic-gate 	prop.read =  frudata_read_callback;
1970*7c478bd9Sstevel@tonic-gate 	prop.write = frudata_write_section; /* callback routine */
1971*7c478bd9Sstevel@tonic-gate 
1972*7c478bd9Sstevel@tonic-gate 	/* create a property */
1973*7c478bd9Sstevel@tonic-gate 	retval = ptree_create_and_add_prop(fruhdl, &prop, NULL, &prophdl);
1974*7c478bd9Sstevel@tonic-gate 
1975*7c478bd9Sstevel@tonic-gate 	return (retval);
1976*7c478bd9Sstevel@tonic-gate }
1977*7c478bd9Sstevel@tonic-gate 
1978*7c478bd9Sstevel@tonic-gate /* search for FRUDataAvailable and create container and add segment property */
1979*7c478bd9Sstevel@tonic-gate 
1980*7c478bd9Sstevel@tonic-gate static void
1981*7c478bd9Sstevel@tonic-gate create_frudata_props(picl_prophdl_t fruhdl)
1982*7c478bd9Sstevel@tonic-gate {
1983*7c478bd9Sstevel@tonic-gate 	int		retval;
1984*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t chldhdl;
1985*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t tmphdl;
1986*7c478bd9Sstevel@tonic-gate 
1987*7c478bd9Sstevel@tonic-gate 	for (retval = ptree_get_propval_by_name(fruhdl, PICL_PROP_CHILD,
1988*7c478bd9Sstevel@tonic-gate 	&chldhdl, sizeof (picl_nodehdl_t)); retval != PICL_PROPNOTFOUND;
1989*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_propval_by_name(chldhdl, PICL_PROP_PEER,
1990*7c478bd9Sstevel@tonic-gate 		&chldhdl, sizeof (picl_nodehdl_t))) {
1991*7c478bd9Sstevel@tonic-gate 		if (retval != PICL_SUCCESS)
1992*7c478bd9Sstevel@tonic-gate 			return;
1993*7c478bd9Sstevel@tonic-gate 
1994*7c478bd9Sstevel@tonic-gate 		/* Does it have a FRUDataAvailable property */
1995*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_prop_by_name(chldhdl,
1996*7c478bd9Sstevel@tonic-gate 					PICL_PROP_FRUDATA_AVAIL, &tmphdl);
1997*7c478bd9Sstevel@tonic-gate 		if (retval == PICL_SUCCESS) {
1998*7c478bd9Sstevel@tonic-gate 			(void) create_container_prop(chldhdl);
1999*7c478bd9Sstevel@tonic-gate 		}
2000*7c478bd9Sstevel@tonic-gate 
2001*7c478bd9Sstevel@tonic-gate 		/* Traverse tree recursively */
2002*7c478bd9Sstevel@tonic-gate 		(void) create_frudata_props(chldhdl);
2003*7c478bd9Sstevel@tonic-gate 	}
2004*7c478bd9Sstevel@tonic-gate }
2005*7c478bd9Sstevel@tonic-gate 
2006*7c478bd9Sstevel@tonic-gate /*
2007*7c478bd9Sstevel@tonic-gate  * Search for the frutree config file from the platform specific
2008*7c478bd9Sstevel@tonic-gate  * directory to the common directory.
2009*7c478bd9Sstevel@tonic-gate  *
2010*7c478bd9Sstevel@tonic-gate  * The size of outfilename must be PATH_MAX
2011*7c478bd9Sstevel@tonic-gate  */
2012*7c478bd9Sstevel@tonic-gate static int
2013*7c478bd9Sstevel@tonic-gate get_config_file(char *outfilename)
2014*7c478bd9Sstevel@tonic-gate {
2015*7c478bd9Sstevel@tonic-gate 	char    nmbuf[SYS_NMLN];
2016*7c478bd9Sstevel@tonic-gate 	char    pname[PATH_MAX];
2017*7c478bd9Sstevel@tonic-gate 
2018*7c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
2019*7c478bd9Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, FRUDATA_CONFFILE_NAME, nmbuf);
2020*7c478bd9Sstevel@tonic-gate 		if (access(pname, R_OK) == 0) {
2021*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(outfilename, pname, PATH_MAX);
2022*7c478bd9Sstevel@tonic-gate 			return (0);
2023*7c478bd9Sstevel@tonic-gate 		}
2024*7c478bd9Sstevel@tonic-gate 	}
2025*7c478bd9Sstevel@tonic-gate 
2026*7c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
2027*7c478bd9Sstevel@tonic-gate 		(void) snprintf(pname, PATH_MAX, FRUDATA_CONFFILE_NAME, nmbuf);
2028*7c478bd9Sstevel@tonic-gate 		if (access(pname, R_OK) == 0) {
2029*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(outfilename, pname, PATH_MAX);
2030*7c478bd9Sstevel@tonic-gate 			return (0);
2031*7c478bd9Sstevel@tonic-gate 		}
2032*7c478bd9Sstevel@tonic-gate 	}
2033*7c478bd9Sstevel@tonic-gate 
2034*7c478bd9Sstevel@tonic-gate 	(void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
2035*7c478bd9Sstevel@tonic-gate 						FRUDATA_CONFFILE_NAME);
2036*7c478bd9Sstevel@tonic-gate 	if (access(pname, R_OK) == 0) {
2037*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(outfilename, pname, PATH_MAX);
2038*7c478bd9Sstevel@tonic-gate 		return (0);
2039*7c478bd9Sstevel@tonic-gate 	}
2040*7c478bd9Sstevel@tonic-gate 	return (-1);
2041*7c478bd9Sstevel@tonic-gate }
2042*7c478bd9Sstevel@tonic-gate 
2043*7c478bd9Sstevel@tonic-gate /*
2044*7c478bd9Sstevel@tonic-gate  * called from delete_frudata_props(), this routine delete the section node
2045*7c478bd9Sstevel@tonic-gate  * and free's the section hash object. it calls free_segment_node() to
2046*7c478bd9Sstevel@tonic-gate  * delete segment node beneath it.
2047*7c478bd9Sstevel@tonic-gate  */
2048*7c478bd9Sstevel@tonic-gate 
2049*7c478bd9Sstevel@tonic-gate static void
2050*7c478bd9Sstevel@tonic-gate free_section_node(hash_obj_t	*sec_hash, container_tbl_t *cont_tbl)
2051*7c478bd9Sstevel@tonic-gate {
2052*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*seg_hash;
2053*7c478bd9Sstevel@tonic-gate 
2054*7c478bd9Sstevel@tonic-gate 	for (seg_hash = sec_hash->u.sec_node->segment_list; seg_hash != NULL;
2055*7c478bd9Sstevel@tonic-gate 					seg_hash = seg_hash->u.seg_node->next) {
2056*7c478bd9Sstevel@tonic-gate 		free_segment_node(seg_hash, seg_hash->picl_hdl, cont_tbl);
2057*7c478bd9Sstevel@tonic-gate 	}
2058*7c478bd9Sstevel@tonic-gate 
2059*7c478bd9Sstevel@tonic-gate 	if (sec_hash->prev == NULL) {
2060*7c478bd9Sstevel@tonic-gate 		cont_tbl->hash_obj[(sec_hash->picl_hdl % TABLE_SIZE)].next =
2061*7c478bd9Sstevel@tonic-gate 						sec_hash->next;
2062*7c478bd9Sstevel@tonic-gate 		if (sec_hash->next != NULL) {
2063*7c478bd9Sstevel@tonic-gate 			sec_hash->next->prev = NULL;
2064*7c478bd9Sstevel@tonic-gate 		}
2065*7c478bd9Sstevel@tonic-gate 	} else {
2066*7c478bd9Sstevel@tonic-gate 		sec_hash->prev->next = sec_hash->next;
2067*7c478bd9Sstevel@tonic-gate 		if (sec_hash->next != NULL) {
2068*7c478bd9Sstevel@tonic-gate 			sec_hash->next->prev = sec_hash->prev;
2069*7c478bd9Sstevel@tonic-gate 		}
2070*7c478bd9Sstevel@tonic-gate 	}
2071*7c478bd9Sstevel@tonic-gate 
2072*7c478bd9Sstevel@tonic-gate 	/* delete & destroy section node */
2073*7c478bd9Sstevel@tonic-gate 	(void) ptree_delete_node(sec_hash->picl_hdl);
2074*7c478bd9Sstevel@tonic-gate 	(void) ptree_destroy_node(sec_hash->picl_hdl);
2075*7c478bd9Sstevel@tonic-gate 
2076*7c478bd9Sstevel@tonic-gate 	free(sec_hash->u.sec_node);
2077*7c478bd9Sstevel@tonic-gate 	free(sec_hash);
2078*7c478bd9Sstevel@tonic-gate }
2079*7c478bd9Sstevel@tonic-gate 
2080*7c478bd9Sstevel@tonic-gate /*
2081*7c478bd9Sstevel@tonic-gate  * called from delete_frudata_props(), this routine free's the container
2082*7c478bd9Sstevel@tonic-gate  * hash object.
2083*7c478bd9Sstevel@tonic-gate  */
2084*7c478bd9Sstevel@tonic-gate 
2085*7c478bd9Sstevel@tonic-gate static void
2086*7c478bd9Sstevel@tonic-gate unlink_container_node(container_tbl_t	*cont_hash)
2087*7c478bd9Sstevel@tonic-gate {
2088*7c478bd9Sstevel@tonic-gate 	if (cont_hash->prev == NULL) {
2089*7c478bd9Sstevel@tonic-gate 		container_table[(cont_hash->picl_hdl % TABLE_SIZE)] =
2090*7c478bd9Sstevel@tonic-gate 						cont_hash->next;
2091*7c478bd9Sstevel@tonic-gate 		if (cont_hash->next != NULL) {
2092*7c478bd9Sstevel@tonic-gate 			cont_hash->next->prev = NULL;
2093*7c478bd9Sstevel@tonic-gate 		}
2094*7c478bd9Sstevel@tonic-gate 	} else {
2095*7c478bd9Sstevel@tonic-gate 		cont_hash->prev->next = cont_hash->next;
2096*7c478bd9Sstevel@tonic-gate 		if (cont_hash->next != NULL) {
2097*7c478bd9Sstevel@tonic-gate 			cont_hash->next->prev = cont_hash->prev;
2098*7c478bd9Sstevel@tonic-gate 		}
2099*7c478bd9Sstevel@tonic-gate 	}
2100*7c478bd9Sstevel@tonic-gate }
2101*7c478bd9Sstevel@tonic-gate 
2102*7c478bd9Sstevel@tonic-gate /*
2103*7c478bd9Sstevel@tonic-gate  * called from frudata_event_handler() to free the corresponding hash object
2104*7c478bd9Sstevel@tonic-gate  * of the removed fru.
2105*7c478bd9Sstevel@tonic-gate  */
2106*7c478bd9Sstevel@tonic-gate 
2107*7c478bd9Sstevel@tonic-gate static void
2108*7c478bd9Sstevel@tonic-gate delete_frudata_props(picl_nodehdl_t	fru_hdl)
2109*7c478bd9Sstevel@tonic-gate {
2110*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*cont_hash;
2111*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*free_obj;
2112*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*sec_hash;
2113*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
2114*7c478bd9Sstevel@tonic-gate 
2115*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&cont_tbl_lock);
2116*7c478bd9Sstevel@tonic-gate 
2117*7c478bd9Sstevel@tonic-gate 	cont_tbl = lookup_container_table(fru_hdl, CONTAINER_NODE);
2118*7c478bd9Sstevel@tonic-gate 	if (cont_tbl == NULL) {
2119*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&cont_tbl_lock);
2120*7c478bd9Sstevel@tonic-gate 		return;
2121*7c478bd9Sstevel@tonic-gate 	}
2122*7c478bd9Sstevel@tonic-gate 
2123*7c478bd9Sstevel@tonic-gate 	/* remove the container object from the container table */
2124*7c478bd9Sstevel@tonic-gate 	unlink_container_node(cont_tbl);
2125*7c478bd9Sstevel@tonic-gate 
2126*7c478bd9Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&cont_tbl->cond_var);
2127*7c478bd9Sstevel@tonic-gate 
2128*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&cont_tbl_lock);
2129*7c478bd9Sstevel@tonic-gate 
2130*7c478bd9Sstevel@tonic-gate 	/*
2131*7c478bd9Sstevel@tonic-gate 	 * waiting/blocking calling thread for all I/O in
2132*7c478bd9Sstevel@tonic-gate 	 * progress to complete. don't free the container
2133*7c478bd9Sstevel@tonic-gate 	 * hash before all I/O is complete.
2134*7c478bd9Sstevel@tonic-gate 	 */
2135*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&cont_tbl->rwlock);
2136*7c478bd9Sstevel@tonic-gate 
2137*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&cont_tbl->rwlock);
2138*7c478bd9Sstevel@tonic-gate 
2139*7c478bd9Sstevel@tonic-gate 
2140*7c478bd9Sstevel@tonic-gate 	cont_hash = lookup_node_object(fru_hdl, CONTAINER_NODE, cont_tbl);
2141*7c478bd9Sstevel@tonic-gate 	if (cont_hash == NULL) {
2142*7c478bd9Sstevel@tonic-gate 		return;
2143*7c478bd9Sstevel@tonic-gate 	}
2144*7c478bd9Sstevel@tonic-gate 
2145*7c478bd9Sstevel@tonic-gate 	free_obj = cont_hash->u.cont_node->section_list;
2146*7c478bd9Sstevel@tonic-gate 	/* walk through the section list */
2147*7c478bd9Sstevel@tonic-gate 	for (sec_hash = free_obj; sec_hash != NULL; free_obj = sec_hash) {
2148*7c478bd9Sstevel@tonic-gate 		sec_hash = sec_hash->u.sec_node->next;
2149*7c478bd9Sstevel@tonic-gate 		free_section_node(free_obj, cont_tbl);
2150*7c478bd9Sstevel@tonic-gate 	}
2151*7c478bd9Sstevel@tonic-gate 	(void) fru_close_container(cont_hash->u.cont_node->cont_hdl);
2152*7c478bd9Sstevel@tonic-gate 
2153*7c478bd9Sstevel@tonic-gate 	free(cont_hash->u.cont_node);
2154*7c478bd9Sstevel@tonic-gate 	free(cont_hash);
2155*7c478bd9Sstevel@tonic-gate 
2156*7c478bd9Sstevel@tonic-gate 	free(cont_tbl->hash_obj);
2157*7c478bd9Sstevel@tonic-gate 	free(cont_tbl);
2158*7c478bd9Sstevel@tonic-gate }
2159*7c478bd9Sstevel@tonic-gate 
2160*7c478bd9Sstevel@tonic-gate /*
2161*7c478bd9Sstevel@tonic-gate  * called when there is any state-change in location, fru, port nodes.
2162*7c478bd9Sstevel@tonic-gate  * this event handler handles only location state-changes.
2163*7c478bd9Sstevel@tonic-gate  */
2164*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
2165*7c478bd9Sstevel@tonic-gate static void
2166*7c478bd9Sstevel@tonic-gate frudata_state_change_evhandler(const char *event_name, const void *event_arg,
2167*7c478bd9Sstevel@tonic-gate 	size_t size, void *cookie)
2168*7c478bd9Sstevel@tonic-gate {
2169*7c478bd9Sstevel@tonic-gate 	int rc;
2170*7c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
2171*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t prop;
2172*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	loch, fruh;
2173*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	proph, prophdl;
2174*7c478bd9Sstevel@tonic-gate 	char *present_state, *last_state;
2175*7c478bd9Sstevel@tonic-gate 	char name[PICL_PROPNAMELEN_MAX];
2176*7c478bd9Sstevel@tonic-gate 
2177*7c478bd9Sstevel@tonic-gate 	if (strcmp(event_name, PICLEVENT_STATE_CHANGE) != 0)
2178*7c478bd9Sstevel@tonic-gate 		return;
2179*7c478bd9Sstevel@tonic-gate 
2180*7c478bd9Sstevel@tonic-gate 	if (nvlist_unpack((char *)event_arg, size, &nvlp, NULL)) {
2181*7c478bd9Sstevel@tonic-gate 		return;
2182*7c478bd9Sstevel@tonic-gate 	}
2183*7c478bd9Sstevel@tonic-gate 
2184*7c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE,
2185*7c478bd9Sstevel@tonic-gate 		&loch)  == -1) {
2186*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2187*7c478bd9Sstevel@tonic-gate 		return;
2188*7c478bd9Sstevel@tonic-gate 	}
2189*7c478bd9Sstevel@tonic-gate 
2190*7c478bd9Sstevel@tonic-gate 	if (ptree_get_propval_by_name(loch, PICL_PROP_CLASSNAME, name,
2191*7c478bd9Sstevel@tonic-gate 		sizeof (name)) != PICL_SUCCESS) {
2192*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2193*7c478bd9Sstevel@tonic-gate 		return;
2194*7c478bd9Sstevel@tonic-gate 	}
2195*7c478bd9Sstevel@tonic-gate 
2196*7c478bd9Sstevel@tonic-gate 	/* handle only location events */
2197*7c478bd9Sstevel@tonic-gate 	if (strcmp(name, PICL_CLASS_LOCATION) != 0) {
2198*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2199*7c478bd9Sstevel@tonic-gate 		return;
2200*7c478bd9Sstevel@tonic-gate 	}
2201*7c478bd9Sstevel@tonic-gate 
2202*7c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_STATE,
2203*7c478bd9Sstevel@tonic-gate 		&present_state)) {
2204*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2205*7c478bd9Sstevel@tonic-gate 		return;
2206*7c478bd9Sstevel@tonic-gate 	}
2207*7c478bd9Sstevel@tonic-gate 
2208*7c478bd9Sstevel@tonic-gate 	rc = ptree_get_propval_by_name(loch, PICL_PROP_CHILD,
2209*7c478bd9Sstevel@tonic-gate 		&fruh, sizeof (picl_nodehdl_t));
2210*7c478bd9Sstevel@tonic-gate 	if (rc != PICL_SUCCESS) {
2211*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2212*7c478bd9Sstevel@tonic-gate 		return;
2213*7c478bd9Sstevel@tonic-gate 	}
2214*7c478bd9Sstevel@tonic-gate 
2215*7c478bd9Sstevel@tonic-gate 	/* fru removed */
2216*7c478bd9Sstevel@tonic-gate 	if (strcmp(present_state, PICLEVENTARGVAL_EMPTY) == 0) {
2217*7c478bd9Sstevel@tonic-gate 		delete_frudata_props(fruh);
2218*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2219*7c478bd9Sstevel@tonic-gate 		return;
2220*7c478bd9Sstevel@tonic-gate 	}
2221*7c478bd9Sstevel@tonic-gate 
2222*7c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_LAST_STATE,
2223*7c478bd9Sstevel@tonic-gate 		&last_state)) {
2224*7c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2225*7c478bd9Sstevel@tonic-gate 		return;
2226*7c478bd9Sstevel@tonic-gate 	}
2227*7c478bd9Sstevel@tonic-gate 
2228*7c478bd9Sstevel@tonic-gate 	/* fru added */
2229*7c478bd9Sstevel@tonic-gate 	if ((strcmp(last_state, PICLEVENTARGVAL_EMPTY) == 0) ||
2230*7c478bd9Sstevel@tonic-gate 		(strcmp(last_state, PICLEVENTARGVAL_UNKNOWN) == 0)) {
2231*7c478bd9Sstevel@tonic-gate 		rc = ptree_get_prop_by_name(fruh, PICL_PROP_FRUDATA_AVAIL,
2232*7c478bd9Sstevel@tonic-gate 			&proph);
2233*7c478bd9Sstevel@tonic-gate 		if (rc != PICL_SUCCESS) {
2234*7c478bd9Sstevel@tonic-gate 			if (fru_is_data_available(fruh) == 0) {
2235*7c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
2236*7c478bd9Sstevel@tonic-gate 				return;
2237*7c478bd9Sstevel@tonic-gate 			}
2238*7c478bd9Sstevel@tonic-gate 			/* create the property */
2239*7c478bd9Sstevel@tonic-gate 			prop.version = PTREE_PROPINFO_VERSION;
2240*7c478bd9Sstevel@tonic-gate 			prop.piclinfo.type =  PICL_PTYPE_VOID;
2241*7c478bd9Sstevel@tonic-gate 			prop.piclinfo.accessmode = PICL_READ;
2242*7c478bd9Sstevel@tonic-gate 			prop.piclinfo.size =  0;
2243*7c478bd9Sstevel@tonic-gate 			(void) strncpy(prop.piclinfo.name,
2244*7c478bd9Sstevel@tonic-gate 				PICL_PROP_FRUDATA_AVAIL,
2245*7c478bd9Sstevel@tonic-gate 				sizeof (prop.piclinfo.name));
2246*7c478bd9Sstevel@tonic-gate 
2247*7c478bd9Sstevel@tonic-gate 			rc = ptree_create_prop(&prop, NULL, &prophdl);
2248*7c478bd9Sstevel@tonic-gate 			if (rc != PICL_SUCCESS) {
2249*7c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
2250*7c478bd9Sstevel@tonic-gate 				return;
2251*7c478bd9Sstevel@tonic-gate 			}
2252*7c478bd9Sstevel@tonic-gate 			rc = ptree_add_prop(fruh,  prophdl);
2253*7c478bd9Sstevel@tonic-gate 			if (rc != PICL_SUCCESS) {
2254*7c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
2255*7c478bd9Sstevel@tonic-gate 				return;
2256*7c478bd9Sstevel@tonic-gate 			}
2257*7c478bd9Sstevel@tonic-gate 		}
2258*7c478bd9Sstevel@tonic-gate 		(void) create_container_prop(fruh);
2259*7c478bd9Sstevel@tonic-gate 	}
2260*7c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
2261*7c478bd9Sstevel@tonic-gate }
2262*7c478bd9Sstevel@tonic-gate 
2263*7c478bd9Sstevel@tonic-gate /*
2264*7c478bd9Sstevel@tonic-gate  * called when event is posted when is fru is either added or removed from
2265*7c478bd9Sstevel@tonic-gate  * the picltree.
2266*7c478bd9Sstevel@tonic-gate  */
2267*7c478bd9Sstevel@tonic-gate 
2268*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
2269*7c478bd9Sstevel@tonic-gate static void
2270*7c478bd9Sstevel@tonic-gate frudata_event_handler(const char *event_name, const void *event_arg,
2271*7c478bd9Sstevel@tonic-gate 						size_t size, void *cookie)
2272*7c478bd9Sstevel@tonic-gate {
2273*7c478bd9Sstevel@tonic-gate 	int		retval;
2274*7c478bd9Sstevel@tonic-gate 	char		fullfilename[PATH_MAX];
2275*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	fru_picl_hdl;
2276*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	roothdl;
2277*7c478bd9Sstevel@tonic-gate 
2278*7c478bd9Sstevel@tonic-gate 	if (strcmp(event_name, PICL_FRU_REMOVED) == 0) {
2279*7c478bd9Sstevel@tonic-gate 
2280*7c478bd9Sstevel@tonic-gate 		retval = nvlist_lookup_uint64((nvlist_t *)event_arg,
2281*7c478bd9Sstevel@tonic-gate 					PICLEVENTARG_FRUHANDLE, &fru_picl_hdl);
2282*7c478bd9Sstevel@tonic-gate 		if (retval != PICL_SUCCESS) {
2283*7c478bd9Sstevel@tonic-gate 			return;
2284*7c478bd9Sstevel@tonic-gate 		}
2285*7c478bd9Sstevel@tonic-gate 
2286*7c478bd9Sstevel@tonic-gate 		/* free the hash object */
2287*7c478bd9Sstevel@tonic-gate 		delete_frudata_props(fru_picl_hdl);
2288*7c478bd9Sstevel@tonic-gate 
2289*7c478bd9Sstevel@tonic-gate 	} else  if (strcmp(event_name, PICL_FRU_ADDED) == 0) {
2290*7c478bd9Sstevel@tonic-gate 		/*
2291*7c478bd9Sstevel@tonic-gate 		 * reparse the configuration file to create
2292*7c478bd9Sstevel@tonic-gate 		 * FRUDevicePath Prop.
2293*7c478bd9Sstevel@tonic-gate 		 */
2294*7c478bd9Sstevel@tonic-gate 		(void) get_config_file(fullfilename);
2295*7c478bd9Sstevel@tonic-gate 		retval = ptree_get_root(&roothdl);
2296*7c478bd9Sstevel@tonic-gate 		if (retval != PICL_SUCCESS) {
2297*7c478bd9Sstevel@tonic-gate 			return;
2298*7c478bd9Sstevel@tonic-gate 		}
2299*7c478bd9Sstevel@tonic-gate 
2300*7c478bd9Sstevel@tonic-gate 		(void) picld_pluginutil_parse_config_file(roothdl,
2301*7c478bd9Sstevel@tonic-gate 							fullfilename);
2302*7c478bd9Sstevel@tonic-gate 
2303*7c478bd9Sstevel@tonic-gate 		retval = nvlist_lookup_uint64((nvlist_t *)event_arg,
2304*7c478bd9Sstevel@tonic-gate 				PICLEVENTARG_PARENTHANDLE, &fru_picl_hdl);
2305*7c478bd9Sstevel@tonic-gate 		if (retval != PICL_SUCCESS) {
2306*7c478bd9Sstevel@tonic-gate 			return;
2307*7c478bd9Sstevel@tonic-gate 		}
2308*7c478bd9Sstevel@tonic-gate 
2309*7c478bd9Sstevel@tonic-gate 		/* create container property */
2310*7c478bd9Sstevel@tonic-gate 		create_frudata_props(fru_picl_hdl);
2311*7c478bd9Sstevel@tonic-gate 	}
2312*7c478bd9Sstevel@tonic-gate }
2313*7c478bd9Sstevel@tonic-gate 
2314*7c478bd9Sstevel@tonic-gate /*
2315*7c478bd9Sstevel@tonic-gate  * Function : plugin_init() is called by daemon. this routine is specified
2316*7c478bd9Sstevel@tonic-gate  * 		while registering with daemon. it performs the initialization
2317*7c478bd9Sstevel@tonic-gate  *		of plugin module.
2318*7c478bd9Sstevel@tonic-gate  */
2319*7c478bd9Sstevel@tonic-gate 
2320*7c478bd9Sstevel@tonic-gate static void
2321*7c478bd9Sstevel@tonic-gate frudata_plugin_init(void)
2322*7c478bd9Sstevel@tonic-gate {
2323*7c478bd9Sstevel@tonic-gate 	int		retval;
2324*7c478bd9Sstevel@tonic-gate 	int		count;
2325*7c478bd9Sstevel@tonic-gate 	char		fullfilename[PATH_MAX];
2326*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	fru_nodehdl;
2327*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	roothdl;
2328*7c478bd9Sstevel@tonic-gate 
2329*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_root(&roothdl);
2330*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
2331*7c478bd9Sstevel@tonic-gate 		return;
2332*7c478bd9Sstevel@tonic-gate 	}
2333*7c478bd9Sstevel@tonic-gate 
2334*7c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICL_FRU_ADDED,
2335*7c478bd9Sstevel@tonic-gate 					frudata_event_handler, NULL);
2336*7c478bd9Sstevel@tonic-gate 
2337*7c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICL_FRU_REMOVED,
2338*7c478bd9Sstevel@tonic-gate 					frudata_event_handler, NULL);
2339*7c478bd9Sstevel@tonic-gate 
2340*7c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_STATE_CHANGE,
2341*7c478bd9Sstevel@tonic-gate 				frudata_state_change_evhandler, NULL);
2342*7c478bd9Sstevel@tonic-gate 
2343*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&cont_tbl_lock);
2344*7c478bd9Sstevel@tonic-gate 	for (count = 0; count < TABLE_SIZE; count++) {
2345*7c478bd9Sstevel@tonic-gate 		container_table[count] = NULL;
2346*7c478bd9Sstevel@tonic-gate 	}
2347*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&cont_tbl_lock);
2348*7c478bd9Sstevel@tonic-gate 
2349*7c478bd9Sstevel@tonic-gate 	(void) get_config_file(fullfilename);
2350*7c478bd9Sstevel@tonic-gate 
2351*7c478bd9Sstevel@tonic-gate 	(void) picld_pluginutil_parse_config_file(roothdl, fullfilename);
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate 	retval = ptree_get_node_by_path(FRUTREE_PATH, &fru_nodehdl);
2354*7c478bd9Sstevel@tonic-gate 
2355*7c478bd9Sstevel@tonic-gate 	if (retval != PICL_SUCCESS) {
2356*7c478bd9Sstevel@tonic-gate 		return;
2357*7c478bd9Sstevel@tonic-gate 	}
2358*7c478bd9Sstevel@tonic-gate 
2359*7c478bd9Sstevel@tonic-gate 	create_frudata_props(fru_nodehdl);
2360*7c478bd9Sstevel@tonic-gate 
2361*7c478bd9Sstevel@tonic-gate }
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate static void
2364*7c478bd9Sstevel@tonic-gate free_packet_hash_object(hash_obj_t *pkt_obj)
2365*7c478bd9Sstevel@tonic-gate {
2366*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*tmp_obj;
2367*7c478bd9Sstevel@tonic-gate 
2368*7c478bd9Sstevel@tonic-gate 	while (pkt_obj != NULL) {
2369*7c478bd9Sstevel@tonic-gate 		tmp_obj = pkt_obj->u.pkt_node->next;
2370*7c478bd9Sstevel@tonic-gate 		free(pkt_obj->u.pkt_node);
2371*7c478bd9Sstevel@tonic-gate 		free(pkt_obj);
2372*7c478bd9Sstevel@tonic-gate 		pkt_obj = tmp_obj;
2373*7c478bd9Sstevel@tonic-gate 	}
2374*7c478bd9Sstevel@tonic-gate }
2375*7c478bd9Sstevel@tonic-gate 
2376*7c478bd9Sstevel@tonic-gate static void
2377*7c478bd9Sstevel@tonic-gate free_segment_hash_object(hash_obj_t *seg_obj)
2378*7c478bd9Sstevel@tonic-gate {
2379*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*tmp_obj;
2380*7c478bd9Sstevel@tonic-gate 
2381*7c478bd9Sstevel@tonic-gate 	while (seg_obj != NULL) {
2382*7c478bd9Sstevel@tonic-gate 		free_packet_hash_object(seg_obj->u.seg_node->packet_list);
2383*7c478bd9Sstevel@tonic-gate 		tmp_obj = seg_obj->u.seg_node->next;
2384*7c478bd9Sstevel@tonic-gate 		free(seg_obj->u.seg_node);
2385*7c478bd9Sstevel@tonic-gate 		free(seg_obj);
2386*7c478bd9Sstevel@tonic-gate 		seg_obj = tmp_obj;
2387*7c478bd9Sstevel@tonic-gate 	}
2388*7c478bd9Sstevel@tonic-gate }
2389*7c478bd9Sstevel@tonic-gate 
2390*7c478bd9Sstevel@tonic-gate static void
2391*7c478bd9Sstevel@tonic-gate free_hash_objects(hash_obj_t *sec_obj)
2392*7c478bd9Sstevel@tonic-gate {
2393*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*tmp_obj;
2394*7c478bd9Sstevel@tonic-gate 
2395*7c478bd9Sstevel@tonic-gate 	while (sec_obj != NULL) {
2396*7c478bd9Sstevel@tonic-gate 		free_segment_hash_object(sec_obj->u.sec_node->segment_list);
2397*7c478bd9Sstevel@tonic-gate 		tmp_obj = sec_obj->u.sec_node->next;
2398*7c478bd9Sstevel@tonic-gate 		free(sec_obj->u.sec_node);
2399*7c478bd9Sstevel@tonic-gate 		free(sec_obj);
2400*7c478bd9Sstevel@tonic-gate 		sec_obj = tmp_obj;
2401*7c478bd9Sstevel@tonic-gate 	}
2402*7c478bd9Sstevel@tonic-gate }
2403*7c478bd9Sstevel@tonic-gate 
2404*7c478bd9Sstevel@tonic-gate /*
2405*7c478bd9Sstevel@tonic-gate  * called from frudata_plugin_fini() this routine walks through
2406*7c478bd9Sstevel@tonic-gate  * the hash table to free each and very hash object in the hash table.
2407*7c478bd9Sstevel@tonic-gate  */
2408*7c478bd9Sstevel@tonic-gate 
2409*7c478bd9Sstevel@tonic-gate static void
2410*7c478bd9Sstevel@tonic-gate free_hash_table(void)
2411*7c478bd9Sstevel@tonic-gate {
2412*7c478bd9Sstevel@tonic-gate 	int		cnt;
2413*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	nodehdl;
2414*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*next_obj;
2415*7c478bd9Sstevel@tonic-gate 	hash_obj_t	*sec_obj;
2416*7c478bd9Sstevel@tonic-gate 	container_tbl_t	*cont_tbl;
2417*7c478bd9Sstevel@tonic-gate 
2418*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < TABLE_SIZE; cnt++) {
2419*7c478bd9Sstevel@tonic-gate 
2420*7c478bd9Sstevel@tonic-gate 		while (container_table[cnt]) {
2421*7c478bd9Sstevel@tonic-gate 
2422*7c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&cont_tbl_lock);
2423*7c478bd9Sstevel@tonic-gate 
2424*7c478bd9Sstevel@tonic-gate 			cont_tbl = container_table[cnt];
2425*7c478bd9Sstevel@tonic-gate 			nodehdl = cont_tbl->picl_hdl;
2426*7c478bd9Sstevel@tonic-gate 
2427*7c478bd9Sstevel@tonic-gate 			cont_tbl = lookup_container_table(nodehdl,
2428*7c478bd9Sstevel@tonic-gate 						CONTAINER_NODE);
2429*7c478bd9Sstevel@tonic-gate 			if (cont_tbl == NULL) {
2430*7c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(&cont_tbl_lock);
2431*7c478bd9Sstevel@tonic-gate 				break;
2432*7c478bd9Sstevel@tonic-gate 			}
2433*7c478bd9Sstevel@tonic-gate 
2434*7c478bd9Sstevel@tonic-gate 			unlink_container_node(cont_tbl);
2435*7c478bd9Sstevel@tonic-gate 
2436*7c478bd9Sstevel@tonic-gate 			pthread_cond_broadcast(&cont_tbl->cond_var);
2437*7c478bd9Sstevel@tonic-gate 
2438*7c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&cont_tbl_lock);
2439*7c478bd9Sstevel@tonic-gate 
2440*7c478bd9Sstevel@tonic-gate 			/*
2441*7c478bd9Sstevel@tonic-gate 			 * waiting/blocking calling thread for all I/O in
2442*7c478bd9Sstevel@tonic-gate 			 * progress to complete. don't free the container
2443*7c478bd9Sstevel@tonic-gate 			 * hash until all I/O is complete.
2444*7c478bd9Sstevel@tonic-gate 			 */
2445*7c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_wrlock(&cont_tbl->rwlock);
2446*7c478bd9Sstevel@tonic-gate 
2447*7c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(&cont_tbl->rwlock);
2448*7c478bd9Sstevel@tonic-gate 
2449*7c478bd9Sstevel@tonic-gate 			next_obj = cont_tbl->hash_obj->next;
2450*7c478bd9Sstevel@tonic-gate 			if (next_obj == NULL) {
2451*7c478bd9Sstevel@tonic-gate 				break;
2452*7c478bd9Sstevel@tonic-gate 			}
2453*7c478bd9Sstevel@tonic-gate 
2454*7c478bd9Sstevel@tonic-gate 			if (next_obj->object_type == CONTAINER_NODE) {
2455*7c478bd9Sstevel@tonic-gate 				sec_obj = next_obj->u.cont_node->section_list;
2456*7c478bd9Sstevel@tonic-gate 				free_hash_objects(sec_obj);
2457*7c478bd9Sstevel@tonic-gate 			}
2458*7c478bd9Sstevel@tonic-gate 
2459*7c478bd9Sstevel@tonic-gate 			free(next_obj->u.cont_node);
2460*7c478bd9Sstevel@tonic-gate 			free(next_obj);
2461*7c478bd9Sstevel@tonic-gate 			container_table[cnt] = cont_tbl->next;
2462*7c478bd9Sstevel@tonic-gate 
2463*7c478bd9Sstevel@tonic-gate 			free(cont_tbl);
2464*7c478bd9Sstevel@tonic-gate 		}
2465*7c478bd9Sstevel@tonic-gate 	}
2466*7c478bd9Sstevel@tonic-gate }
2467*7c478bd9Sstevel@tonic-gate 
2468*7c478bd9Sstevel@tonic-gate /*
2469*7c478bd9Sstevel@tonic-gate  * called by the daemon and perform frudata cleanup. hold the write lock
2470*7c478bd9Sstevel@tonic-gate  * over the entire hash table to free each and every hash object.
2471*7c478bd9Sstevel@tonic-gate  */
2472*7c478bd9Sstevel@tonic-gate 
2473*7c478bd9Sstevel@tonic-gate static void
2474*7c478bd9Sstevel@tonic-gate frudata_plugin_fini(void)
2475*7c478bd9Sstevel@tonic-gate {
2476*7c478bd9Sstevel@tonic-gate 
2477*7c478bd9Sstevel@tonic-gate 	free_hash_table();
2478*7c478bd9Sstevel@tonic-gate 
2479*7c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICL_FRU_ADDED,
2480*7c478bd9Sstevel@tonic-gate 				frudata_event_handler, NULL);
2481*7c478bd9Sstevel@tonic-gate 
2482*7c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICL_FRU_REMOVED,
2483*7c478bd9Sstevel@tonic-gate 				frudata_event_handler, NULL);
2484*7c478bd9Sstevel@tonic-gate 
2485*7c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE,
2486*7c478bd9Sstevel@tonic-gate 				frudata_state_change_evhandler, NULL);
2487*7c478bd9Sstevel@tonic-gate }
2488