1*12967Sgavin.maltby@oracle.com /*
2*12967Sgavin.maltby@oracle.com  * CDDL HEADER START
3*12967Sgavin.maltby@oracle.com  *
4*12967Sgavin.maltby@oracle.com  * The contents of this file are subject to the terms of the
5*12967Sgavin.maltby@oracle.com  * Common Development and Distribution License (the "License").
6*12967Sgavin.maltby@oracle.com  * You may not use this file except in compliance with the License.
7*12967Sgavin.maltby@oracle.com  *
8*12967Sgavin.maltby@oracle.com  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12967Sgavin.maltby@oracle.com  * or http://www.opensolaris.org/os/licensing.
10*12967Sgavin.maltby@oracle.com  * See the License for the specific language governing permissions
11*12967Sgavin.maltby@oracle.com  * and limitations under the License.
12*12967Sgavin.maltby@oracle.com  *
13*12967Sgavin.maltby@oracle.com  * When distributing Covered Code, include this CDDL HEADER in each
14*12967Sgavin.maltby@oracle.com  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12967Sgavin.maltby@oracle.com  * If applicable, add the following below this CDDL HEADER, with the
16*12967Sgavin.maltby@oracle.com  * fields enclosed by brackets "[]" replaced with your own identifying
17*12967Sgavin.maltby@oracle.com  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12967Sgavin.maltby@oracle.com  *
19*12967Sgavin.maltby@oracle.com  * CDDL HEADER END
20*12967Sgavin.maltby@oracle.com  */
21*12967Sgavin.maltby@oracle.com 
22*12967Sgavin.maltby@oracle.com /*
23*12967Sgavin.maltby@oracle.com  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*12967Sgavin.maltby@oracle.com  */
25*12967Sgavin.maltby@oracle.com 
26*12967Sgavin.maltby@oracle.com #include <stddef.h>
27*12967Sgavin.maltby@oracle.com #include <strings.h>
28*12967Sgavin.maltby@oracle.com 
29*12967Sgavin.maltby@oracle.com #include "../common/sw_impl.h"
30*12967Sgavin.maltby@oracle.com 
31*12967Sgavin.maltby@oracle.com /*
32*12967Sgavin.maltby@oracle.com  * We maintain a single list of all active cases across all
33*12967Sgavin.maltby@oracle.com  * subsidary diagnosis "modules".  We also offer some serialization
34*12967Sgavin.maltby@oracle.com  * services to them.
35*12967Sgavin.maltby@oracle.com  *
36*12967Sgavin.maltby@oracle.com  * To open a new case a subsidiary engine should use swde_case_open
37*12967Sgavin.maltby@oracle.com  * indicating the subsidiary id (from which we lookup the enum sw_casetype)
38*12967Sgavin.maltby@oracle.com  * and, optionally, a pointer to a structure for serialization and its size.
39*12967Sgavin.maltby@oracle.com  *
40*12967Sgavin.maltby@oracle.com  * For each case opened with swde_case_open we maintain an swde_case_t
41*12967Sgavin.maltby@oracle.com  * structure in-core.  Embedded in this is the swde_case_data_t with
42*12967Sgavin.maltby@oracle.com  * information we need to keep track of and manage this case - it's
43*12967Sgavin.maltby@oracle.com  * case type, buffer name used for the sub-de-private data (if any)
44*12967Sgavin.maltby@oracle.com  * and the size of the sub-de-private structure.  It is this
45*12967Sgavin.maltby@oracle.com  * embedded structure which is serialized as the "casedata" buffer,
46*12967Sgavin.maltby@oracle.com  * while the subsidiary-private structure is serialized into another buffer
47*12967Sgavin.maltby@oracle.com  * "casedata_<casetype-in-hex>".
48*12967Sgavin.maltby@oracle.com  *
49*12967Sgavin.maltby@oracle.com  * The subsidiary-private data structure, if any, is required to start
50*12967Sgavin.maltby@oracle.com  * with a uint32_t recording the data structure version.  This
51*12967Sgavin.maltby@oracle.com  * version is also specified as an argument to swde_case_open, and
52*12967Sgavin.maltby@oracle.com  * we note it in the "casedata" buffer we write out and require
53*12967Sgavin.maltby@oracle.com  * a match on restore.
54*12967Sgavin.maltby@oracle.com  *
55*12967Sgavin.maltby@oracle.com  * When we unserialize we restore our management structure as well as
56*12967Sgavin.maltby@oracle.com  * the sub-de-private structure.
57*12967Sgavin.maltby@oracle.com  *
58*12967Sgavin.maltby@oracle.com  * Here's how serialization works:
59*12967Sgavin.maltby@oracle.com  *
60*12967Sgavin.maltby@oracle.com  * In swde_case_open we create a case data buffer for the case named
61*12967Sgavin.maltby@oracle.com  * SW_CASE_DATA_BUFNAME.  We write the buffer out after filling in the
62*12967Sgavin.maltby@oracle.com  * structure version and recording the type of case this is, and if there
63*12967Sgavin.maltby@oracle.com  * is data for the subsidiary then we call swde_subdata to note the
64*12967Sgavin.maltby@oracle.com  * size and version of that data in the case data buf and then to create
65*12967Sgavin.maltby@oracle.com  * and write the subdata in a buffer named SW_CASE_DATA_BUFNAME_<casetype>.
66*12967Sgavin.maltby@oracle.com  *
67*12967Sgavin.maltby@oracle.com  * If the subsidiary updates its case data it is required to call
68*12967Sgavin.maltby@oracle.com  * swde_case_data_write.  This just calls fmd_buf_write for the subsidiary
69*12967Sgavin.maltby@oracle.com  * buffer name.
70*12967Sgavin.maltby@oracle.com  *
71*12967Sgavin.maltby@oracle.com  * A subsidiary can retrieve its private data buffer for a case using
72*12967Sgavin.maltby@oracle.com  * swde_case_data.  This also fills a uint32_t with the version of the
73*12967Sgavin.maltby@oracle.com  * buffer that we have for this subsidiary;  if that is an old version
74*12967Sgavin.maltby@oracle.com  * the subsidiary can cast appropriately and/or upgrade the buffer as
75*12967Sgavin.maltby@oracle.com  * below.
76*12967Sgavin.maltby@oracle.com  *
77*12967Sgavin.maltby@oracle.com  * When the host module is reloaded it calls swde_case_init to iterate
78*12967Sgavin.maltby@oracle.com  * through all cases we own.  For each we call swde_case_unserialize
79*12967Sgavin.maltby@oracle.com  * which restores our case tracking data and any subsidiary-private
80*12967Sgavin.maltby@oracle.com  * data that our case data notes.  We then call swde_case_verify which
81*12967Sgavin.maltby@oracle.com  * calls any registered verify function in the subsidiary owner, and if this
82*12967Sgavin.maltby@oracle.com  * returns 0 the case is closed.
83*12967Sgavin.maltby@oracle.com  *
84*12967Sgavin.maltby@oracle.com  * After initial write, we don't usually have to update the
85*12967Sgavin.maltby@oracle.com  * SW_CASE_DATA_BUFNAME buffer unless the subsidiary changes the size or
86*12967Sgavin.maltby@oracle.com  * version of its private buffer.  To do that the subsidiary must call
87*12967Sgavin.maltby@oracle.com  * swde_case_data_upgrade.  In that function we destroy the old subsidiary
88*12967Sgavin.maltby@oracle.com  * buffer and, if there is still a subsidiary data structure, create a
89*12967Sgavin.maltby@oracle.com  * new buffer appropriately sized and call swde_subdata to write it out
90*12967Sgavin.maltby@oracle.com  * after updating our case structure with new size etc.  Finally we write
91*12967Sgavin.maltby@oracle.com  * out our updated case data structure.
92*12967Sgavin.maltby@oracle.com  */
93*12967Sgavin.maltby@oracle.com 
94*12967Sgavin.maltby@oracle.com #define	SW_CASE_DATA_BUFNAME		"casedata"
95*12967Sgavin.maltby@oracle.com 
96*12967Sgavin.maltby@oracle.com #define	SW_CASE_DATA_VERSION_INITIAL		1
97*12967Sgavin.maltby@oracle.com #define	SW_CASE_DATA_BUFNAMELEN	18	/* 8 + 1 + 8 + 1 */
98*12967Sgavin.maltby@oracle.com typedef struct swde_case_data {
99*12967Sgavin.maltby@oracle.com 	uint32_t sc_version;		/* buffer structure version */
100*12967Sgavin.maltby@oracle.com 	int32_t sc_type;		/* enum sw_casetype */
101*12967Sgavin.maltby@oracle.com 	uint32_t sc_sub_bufvers;	/* version expected in subsidiary */
102*12967Sgavin.maltby@oracle.com 	char sc_sub_bufname[SW_CASE_DATA_BUFNAMELEN];	/* subsidiary bufname */
103*12967Sgavin.maltby@oracle.com 	int32_t sc_sub_bufsz;		/* subsidiary structure size */
104*12967Sgavin.maltby@oracle.com } swde_case_data_t;
105*12967Sgavin.maltby@oracle.com 
106*12967Sgavin.maltby@oracle.com #define	SW_CASE_DATA_VERSION		SW_CASE_DATA_VERSION_INITIAL
107*12967Sgavin.maltby@oracle.com 
108*12967Sgavin.maltby@oracle.com /*
109*12967Sgavin.maltby@oracle.com  * In-core case structure.
110*12967Sgavin.maltby@oracle.com  */
111*12967Sgavin.maltby@oracle.com typedef struct swde_case {
112*12967Sgavin.maltby@oracle.com 	fmd_case_t *swc_fmdcase;	/* fmd case handle */
113*12967Sgavin.maltby@oracle.com 	swde_case_data_t swc_data;	/* case data for serialization */
114*12967Sgavin.maltby@oracle.com 	void *swc_subdata;		/* subsidiary data for serialization */
115*12967Sgavin.maltby@oracle.com } swde_case_t;
116*12967Sgavin.maltby@oracle.com 
117*12967Sgavin.maltby@oracle.com static void
swde_case_associate(fmd_hdl_t * hdl,fmd_case_t * cp,swde_case_t * scp,void * subdata)118*12967Sgavin.maltby@oracle.com swde_case_associate(fmd_hdl_t *hdl, fmd_case_t *cp, swde_case_t *scp,
119*12967Sgavin.maltby@oracle.com     void *subdata)
120*12967Sgavin.maltby@oracle.com {
121*12967Sgavin.maltby@oracle.com 	scp->swc_fmdcase = cp;
122*12967Sgavin.maltby@oracle.com 	scp->swc_subdata = subdata;
123*12967Sgavin.maltby@oracle.com 	fmd_case_setspecific(hdl, cp, scp);
124*12967Sgavin.maltby@oracle.com }
125*12967Sgavin.maltby@oracle.com 
126*12967Sgavin.maltby@oracle.com static void
swde_case_unserialize(fmd_hdl_t * hdl,fmd_case_t * cp)127*12967Sgavin.maltby@oracle.com swde_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
128*12967Sgavin.maltby@oracle.com {
129*12967Sgavin.maltby@oracle.com 	swde_case_t *scp;
130*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap;
131*12967Sgavin.maltby@oracle.com 	void *subdata;
132*12967Sgavin.maltby@oracle.com 	size_t sz;
133*12967Sgavin.maltby@oracle.com 
134*12967Sgavin.maltby@oracle.com 	scp = fmd_hdl_zalloc(hdl, sizeof (*scp), FMD_SLEEP);
135*12967Sgavin.maltby@oracle.com 	datap = &scp->swc_data;
136*12967Sgavin.maltby@oracle.com 
137*12967Sgavin.maltby@oracle.com 	fmd_buf_read(hdl, cp, SW_CASE_DATA_BUFNAME, datap, sizeof (*datap));
138*12967Sgavin.maltby@oracle.com 
139*12967Sgavin.maltby@oracle.com 	if (datap->sc_version > SW_CASE_DATA_VERSION_INITIAL) {
140*12967Sgavin.maltby@oracle.com 		fmd_hdl_free(hdl, scp, sizeof (*scp));
141*12967Sgavin.maltby@oracle.com 		return;
142*12967Sgavin.maltby@oracle.com 	}
143*12967Sgavin.maltby@oracle.com 
144*12967Sgavin.maltby@oracle.com 	if ((sz = datap->sc_sub_bufsz) != 0) {
145*12967Sgavin.maltby@oracle.com 		subdata = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
146*12967Sgavin.maltby@oracle.com 		fmd_buf_read(hdl, cp, datap->sc_sub_bufname, subdata, sz);
147*12967Sgavin.maltby@oracle.com 
148*12967Sgavin.maltby@oracle.com 		if (*((uint32_t *)subdata) != datap->sc_sub_bufvers) {
149*12967Sgavin.maltby@oracle.com 			fmd_hdl_abort(hdl, "unserialize: expected subdata "
150*12967Sgavin.maltby@oracle.com 			    "version %u but received %u\n",
151*12967Sgavin.maltby@oracle.com 			    datap->sc_sub_bufvers, *((uint32_t *)subdata));
152*12967Sgavin.maltby@oracle.com 		}
153*12967Sgavin.maltby@oracle.com 	}
154*12967Sgavin.maltby@oracle.com 
155*12967Sgavin.maltby@oracle.com 	swde_case_associate(hdl, cp, scp, subdata);
156*12967Sgavin.maltby@oracle.com }
157*12967Sgavin.maltby@oracle.com 
158*12967Sgavin.maltby@oracle.com static void
swde_subdata(fmd_hdl_t * hdl,fmd_case_t * cp,enum sw_casetype type,swde_case_t * scp,uint32_t subdata_vers,void * subdata,size_t subdata_sz)159*12967Sgavin.maltby@oracle.com swde_subdata(fmd_hdl_t *hdl, fmd_case_t *cp, enum sw_casetype type,
160*12967Sgavin.maltby@oracle.com     swde_case_t *scp, uint32_t subdata_vers, void *subdata, size_t subdata_sz)
161*12967Sgavin.maltby@oracle.com {
162*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
163*12967Sgavin.maltby@oracle.com 
164*12967Sgavin.maltby@oracle.com 	if (*((uint32_t *)subdata) != subdata_vers)
165*12967Sgavin.maltby@oracle.com 		fmd_hdl_abort(hdl, "swde_subdata: subdata version "
166*12967Sgavin.maltby@oracle.com 		    "does not match argument\n");
167*12967Sgavin.maltby@oracle.com 
168*12967Sgavin.maltby@oracle.com 	(void) snprintf(datap->sc_sub_bufname, sizeof (datap->sc_sub_bufname),
169*12967Sgavin.maltby@oracle.com 	    "%s_%08x", SW_CASE_DATA_BUFNAME, type);
170*12967Sgavin.maltby@oracle.com 
171*12967Sgavin.maltby@oracle.com 	datap->sc_sub_bufsz = subdata_sz;
172*12967Sgavin.maltby@oracle.com 	datap->sc_sub_bufvers = subdata_vers;
173*12967Sgavin.maltby@oracle.com 	fmd_buf_create(hdl, cp, datap->sc_sub_bufname, subdata_sz);
174*12967Sgavin.maltby@oracle.com 	fmd_buf_write(hdl, cp, datap->sc_sub_bufname, subdata, subdata_sz);
175*12967Sgavin.maltby@oracle.com }
176*12967Sgavin.maltby@oracle.com 
177*12967Sgavin.maltby@oracle.com fmd_case_t *
swde_case_open(fmd_hdl_t * hdl,id_t who,char * req_uuid,uint32_t subdata_vers,void * subdata,size_t subdata_sz)178*12967Sgavin.maltby@oracle.com swde_case_open(fmd_hdl_t *hdl, id_t who, char *req_uuid,
179*12967Sgavin.maltby@oracle.com     uint32_t subdata_vers, void *subdata, size_t subdata_sz)
180*12967Sgavin.maltby@oracle.com {
181*12967Sgavin.maltby@oracle.com 	enum sw_casetype ct = sw_id_to_casetype(hdl, who);
182*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap;
183*12967Sgavin.maltby@oracle.com 	swde_case_t *scp;
184*12967Sgavin.maltby@oracle.com 	fmd_case_t *cp;
185*12967Sgavin.maltby@oracle.com 
186*12967Sgavin.maltby@oracle.com 	if (ct == SW_CASE_NONE)
187*12967Sgavin.maltby@oracle.com 		fmd_hdl_abort(hdl, "swde_case_open for type SW_CASE_NONE\n");
188*12967Sgavin.maltby@oracle.com 
189*12967Sgavin.maltby@oracle.com 	if (subdata != NULL && subdata_sz <= sizeof (uint32_t) ||
190*12967Sgavin.maltby@oracle.com 	    subdata_sz != 0 && subdata == NULL)
191*12967Sgavin.maltby@oracle.com 		fmd_hdl_abort(hdl, "swde_case_open: bad subdata\n", ct);
192*12967Sgavin.maltby@oracle.com 
193*12967Sgavin.maltby@oracle.com 	scp = fmd_hdl_zalloc(hdl, sizeof (*scp), FMD_SLEEP);
194*12967Sgavin.maltby@oracle.com 	datap = &scp->swc_data;
195*12967Sgavin.maltby@oracle.com 
196*12967Sgavin.maltby@oracle.com 	if (req_uuid == NULL) {
197*12967Sgavin.maltby@oracle.com 		cp = fmd_case_open(hdl, (void *)scp);
198*12967Sgavin.maltby@oracle.com 	} else {
199*12967Sgavin.maltby@oracle.com 		cp = fmd_case_open_uuid(hdl, req_uuid, (void *)scp);
200*12967Sgavin.maltby@oracle.com 		if (cp == NULL) {
201*12967Sgavin.maltby@oracle.com 			fmd_hdl_free(hdl, scp, sizeof (*scp));
202*12967Sgavin.maltby@oracle.com 			return (NULL);
203*12967Sgavin.maltby@oracle.com 		}
204*12967Sgavin.maltby@oracle.com 	}
205*12967Sgavin.maltby@oracle.com 
206*12967Sgavin.maltby@oracle.com 	fmd_buf_create(hdl, cp, SW_CASE_DATA_BUFNAME, sizeof (*datap));
207*12967Sgavin.maltby@oracle.com 	datap->sc_version = SW_CASE_DATA_VERSION_INITIAL;
208*12967Sgavin.maltby@oracle.com 	datap->sc_type = ct;
209*12967Sgavin.maltby@oracle.com 
210*12967Sgavin.maltby@oracle.com 	if (subdata)
211*12967Sgavin.maltby@oracle.com 		swde_subdata(hdl, cp, ct, scp, subdata_vers, subdata,
212*12967Sgavin.maltby@oracle.com 		    subdata_sz);
213*12967Sgavin.maltby@oracle.com 
214*12967Sgavin.maltby@oracle.com 	fmd_buf_write(hdl, cp, SW_CASE_DATA_BUFNAME, datap, sizeof (*datap));
215*12967Sgavin.maltby@oracle.com 	swde_case_associate(hdl, cp, scp, subdata);
216*12967Sgavin.maltby@oracle.com 
217*12967Sgavin.maltby@oracle.com 	return (cp);
218*12967Sgavin.maltby@oracle.com }
219*12967Sgavin.maltby@oracle.com 
220*12967Sgavin.maltby@oracle.com /*
221*12967Sgavin.maltby@oracle.com  * fmdo_close entry point for software-diagnosis
222*12967Sgavin.maltby@oracle.com  */
223*12967Sgavin.maltby@oracle.com void
swde_close(fmd_hdl_t * hdl,fmd_case_t * cp)224*12967Sgavin.maltby@oracle.com swde_close(fmd_hdl_t *hdl, fmd_case_t *cp)
225*12967Sgavin.maltby@oracle.com {
226*12967Sgavin.maltby@oracle.com 	swde_case_t *scp = fmd_case_getspecific(hdl, cp);
227*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
228*12967Sgavin.maltby@oracle.com 	swsub_case_close_func_t *closefunc;
229*12967Sgavin.maltby@oracle.com 
230*12967Sgavin.maltby@oracle.com 	if ((closefunc = sw_sub_case_close_func(hdl, datap->sc_type)) != NULL)
231*12967Sgavin.maltby@oracle.com 		closefunc(hdl, cp);
232*12967Sgavin.maltby@oracle.com 
233*12967Sgavin.maltby@oracle.com 	/*
234*12967Sgavin.maltby@oracle.com 	 * Now that the sub-de has had a chance to clean up, do some ourselves.
235*12967Sgavin.maltby@oracle.com 	 * Note that we free the sub-de-private subdata structure.
236*12967Sgavin.maltby@oracle.com 	 */
237*12967Sgavin.maltby@oracle.com 
238*12967Sgavin.maltby@oracle.com 	if (scp->swc_subdata) {
239*12967Sgavin.maltby@oracle.com 		fmd_hdl_free(hdl, scp->swc_subdata, datap->sc_sub_bufsz);
240*12967Sgavin.maltby@oracle.com 		fmd_buf_destroy(hdl, cp, datap->sc_sub_bufname);
241*12967Sgavin.maltby@oracle.com 	}
242*12967Sgavin.maltby@oracle.com 
243*12967Sgavin.maltby@oracle.com 	fmd_buf_destroy(hdl, cp, SW_CASE_DATA_BUFNAME);
244*12967Sgavin.maltby@oracle.com 
245*12967Sgavin.maltby@oracle.com 	fmd_hdl_free(hdl, scp, sizeof (*scp));
246*12967Sgavin.maltby@oracle.com }
247*12967Sgavin.maltby@oracle.com 
248*12967Sgavin.maltby@oracle.com fmd_case_t *
swde_case_first(fmd_hdl_t * hdl,id_t who)249*12967Sgavin.maltby@oracle.com swde_case_first(fmd_hdl_t *hdl, id_t who)
250*12967Sgavin.maltby@oracle.com {
251*12967Sgavin.maltby@oracle.com 	enum sw_casetype ct = sw_id_to_casetype(hdl, who);
252*12967Sgavin.maltby@oracle.com 	swde_case_t *scp;
253*12967Sgavin.maltby@oracle.com 	fmd_case_t *cp;
254*12967Sgavin.maltby@oracle.com 
255*12967Sgavin.maltby@oracle.com 	if (ct == SW_CASE_NONE)
256*12967Sgavin.maltby@oracle.com 		fmd_hdl_abort(hdl, "swde_case_first for type SW_CASE_NONE\n");
257*12967Sgavin.maltby@oracle.com 
258*12967Sgavin.maltby@oracle.com 	for (cp = fmd_case_next(hdl, NULL); cp; cp = fmd_case_next(hdl, cp)) {
259*12967Sgavin.maltby@oracle.com 		scp = fmd_case_getspecific(hdl, cp);
260*12967Sgavin.maltby@oracle.com 		if (scp->swc_data.sc_type == ct)
261*12967Sgavin.maltby@oracle.com 			break;
262*12967Sgavin.maltby@oracle.com 	}
263*12967Sgavin.maltby@oracle.com 
264*12967Sgavin.maltby@oracle.com 	return (cp);
265*12967Sgavin.maltby@oracle.com }
266*12967Sgavin.maltby@oracle.com 
267*12967Sgavin.maltby@oracle.com fmd_case_t *
swde_case_next(fmd_hdl_t * hdl,fmd_case_t * lastcp)268*12967Sgavin.maltby@oracle.com swde_case_next(fmd_hdl_t *hdl, fmd_case_t *lastcp)
269*12967Sgavin.maltby@oracle.com {
270*12967Sgavin.maltby@oracle.com 	swde_case_t *scp;
271*12967Sgavin.maltby@oracle.com 	fmd_case_t *cp;
272*12967Sgavin.maltby@oracle.com 	int ct;
273*12967Sgavin.maltby@oracle.com 
274*12967Sgavin.maltby@oracle.com 	if (lastcp == NULL)
275*12967Sgavin.maltby@oracle.com 		fmd_hdl_abort(hdl, "swde_case_next called for NULL lastcp\n");
276*12967Sgavin.maltby@oracle.com 
277*12967Sgavin.maltby@oracle.com 	scp = fmd_case_getspecific(hdl, lastcp);
278*12967Sgavin.maltby@oracle.com 	ct = scp->swc_data.sc_type;
279*12967Sgavin.maltby@oracle.com 
280*12967Sgavin.maltby@oracle.com 	cp = lastcp;
281*12967Sgavin.maltby@oracle.com 	while ((cp = fmd_case_next(hdl, cp)) != NULL) {
282*12967Sgavin.maltby@oracle.com 		scp = fmd_case_getspecific(hdl, cp);
283*12967Sgavin.maltby@oracle.com 		if (scp->swc_data.sc_type == ct)
284*12967Sgavin.maltby@oracle.com 			break;
285*12967Sgavin.maltby@oracle.com 	}
286*12967Sgavin.maltby@oracle.com 
287*12967Sgavin.maltby@oracle.com 	return (cp);
288*12967Sgavin.maltby@oracle.com }
289*12967Sgavin.maltby@oracle.com 
290*12967Sgavin.maltby@oracle.com void *
swde_case_data(fmd_hdl_t * hdl,fmd_case_t * cp,uint32_t * svp)291*12967Sgavin.maltby@oracle.com swde_case_data(fmd_hdl_t *hdl, fmd_case_t *cp, uint32_t *svp)
292*12967Sgavin.maltby@oracle.com {
293*12967Sgavin.maltby@oracle.com 	swde_case_t *scp = fmd_case_getspecific(hdl, cp);
294*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
295*12967Sgavin.maltby@oracle.com 
296*12967Sgavin.maltby@oracle.com 	if (svp != NULL && scp->swc_subdata)
297*12967Sgavin.maltby@oracle.com 		*svp = datap->sc_sub_bufvers;
298*12967Sgavin.maltby@oracle.com 
299*12967Sgavin.maltby@oracle.com 	return (scp->swc_subdata);
300*12967Sgavin.maltby@oracle.com }
301*12967Sgavin.maltby@oracle.com 
302*12967Sgavin.maltby@oracle.com void
swde_case_data_write(fmd_hdl_t * hdl,fmd_case_t * cp)303*12967Sgavin.maltby@oracle.com swde_case_data_write(fmd_hdl_t *hdl, fmd_case_t *cp)
304*12967Sgavin.maltby@oracle.com {
305*12967Sgavin.maltby@oracle.com 	swde_case_t *scp = fmd_case_getspecific(hdl, cp);
306*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
307*12967Sgavin.maltby@oracle.com 
308*12967Sgavin.maltby@oracle.com 	if (scp->swc_subdata == NULL)
309*12967Sgavin.maltby@oracle.com 		return;
310*12967Sgavin.maltby@oracle.com 
311*12967Sgavin.maltby@oracle.com 	fmd_buf_write(hdl, cp, scp->swc_data.sc_sub_bufname,
312*12967Sgavin.maltby@oracle.com 	    scp->swc_subdata, datap->sc_sub_bufsz);
313*12967Sgavin.maltby@oracle.com }
314*12967Sgavin.maltby@oracle.com 
315*12967Sgavin.maltby@oracle.com void
swde_case_data_upgrade(fmd_hdl_t * hdl,fmd_case_t * cp,uint32_t subdata_vers,void * subdata,size_t subdata_sz)316*12967Sgavin.maltby@oracle.com swde_case_data_upgrade(fmd_hdl_t *hdl, fmd_case_t *cp, uint32_t subdata_vers,
317*12967Sgavin.maltby@oracle.com     void *subdata, size_t subdata_sz)
318*12967Sgavin.maltby@oracle.com {
319*12967Sgavin.maltby@oracle.com 	swde_case_t *scp = fmd_case_getspecific(hdl, cp);
320*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
321*12967Sgavin.maltby@oracle.com 
322*12967Sgavin.maltby@oracle.com 	if (scp->swc_subdata) {
323*12967Sgavin.maltby@oracle.com 		fmd_buf_destroy(hdl, cp, datap->sc_sub_bufname);
324*12967Sgavin.maltby@oracle.com 		fmd_hdl_free(hdl, scp->swc_subdata, datap->sc_sub_bufsz);
325*12967Sgavin.maltby@oracle.com 		scp->swc_subdata = NULL;
326*12967Sgavin.maltby@oracle.com 		datap->sc_sub_bufsz = 0;
327*12967Sgavin.maltby@oracle.com 		datap->sc_sub_bufname[0] = '\0';
328*12967Sgavin.maltby@oracle.com 	}
329*12967Sgavin.maltby@oracle.com 
330*12967Sgavin.maltby@oracle.com 	if (subdata != NULL) {
331*12967Sgavin.maltby@oracle.com 		scp->swc_subdata = subdata;
332*12967Sgavin.maltby@oracle.com 		swde_subdata(hdl, cp, datap->sc_type, scp, subdata_vers,
333*12967Sgavin.maltby@oracle.com 		    subdata, subdata_sz);
334*12967Sgavin.maltby@oracle.com 	}
335*12967Sgavin.maltby@oracle.com 
336*12967Sgavin.maltby@oracle.com 	fmd_buf_write(hdl, scp->swc_fmdcase, SW_CASE_DATA_BUFNAME,
337*12967Sgavin.maltby@oracle.com 	    datap, sizeof (*datap));
338*12967Sgavin.maltby@oracle.com }
339*12967Sgavin.maltby@oracle.com 
340*12967Sgavin.maltby@oracle.com static void
swde_case_verify(fmd_hdl_t * hdl,fmd_case_t * cp)341*12967Sgavin.maltby@oracle.com swde_case_verify(fmd_hdl_t *hdl, fmd_case_t *cp)
342*12967Sgavin.maltby@oracle.com {
343*12967Sgavin.maltby@oracle.com 	swde_case_t *scp = fmd_case_getspecific(hdl, cp);
344*12967Sgavin.maltby@oracle.com 	swde_case_data_t *datap = &scp->swc_data;
345*12967Sgavin.maltby@oracle.com 	sw_case_vrfy_func_t *vrfy_func;
346*12967Sgavin.maltby@oracle.com 
347*12967Sgavin.maltby@oracle.com 	if ((vrfy_func = sw_sub_case_vrfy_func(hdl, datap->sc_type)) != NULL) {
348*12967Sgavin.maltby@oracle.com 		if (vrfy_func(hdl, cp) == 0)
349*12967Sgavin.maltby@oracle.com 			fmd_case_close(hdl, cp);
350*12967Sgavin.maltby@oracle.com 	}
351*12967Sgavin.maltby@oracle.com }
352*12967Sgavin.maltby@oracle.com 
353*12967Sgavin.maltby@oracle.com void
swde_case_init(fmd_hdl_t * hdl)354*12967Sgavin.maltby@oracle.com swde_case_init(fmd_hdl_t *hdl)
355*12967Sgavin.maltby@oracle.com {
356*12967Sgavin.maltby@oracle.com 	fmd_case_t *cp;
357*12967Sgavin.maltby@oracle.com 
358*12967Sgavin.maltby@oracle.com 	for (cp = fmd_case_next(hdl, NULL); cp; cp = fmd_case_next(hdl, cp)) {
359*12967Sgavin.maltby@oracle.com 		swde_case_unserialize(hdl, cp);
360*12967Sgavin.maltby@oracle.com 		swde_case_verify(hdl, cp);
361*12967Sgavin.maltby@oracle.com 	}
362*12967Sgavin.maltby@oracle.com }
363*12967Sgavin.maltby@oracle.com 
364*12967Sgavin.maltby@oracle.com /*ARGSUSED*/
365*12967Sgavin.maltby@oracle.com void
swde_case_fini(fmd_hdl_t * hdl)366*12967Sgavin.maltby@oracle.com swde_case_fini(fmd_hdl_t *hdl)
367*12967Sgavin.maltby@oracle.com {
368*12967Sgavin.maltby@oracle.com }
369