xref: /onnv-gate/usr/src/uts/common/avs/ns/unistat/spcs_s_k.c (revision 9093:cd587b0bd19c)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9093SRamana.Srikanth@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM /*
277836SJohn.Forte@Sun.COM  *	The SPCS status support kernel utilities
287836SJohn.Forte@Sun.COM  *	See header spcs_s_k.h for functional spec
297836SJohn.Forte@Sun.COM  */
307836SJohn.Forte@Sun.COM #include <sys/types.h>
317836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
327836SJohn.Forte@Sun.COM #include <sys/kmem.h>
337836SJohn.Forte@Sun.COM #include <sys/errno.h>
347836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
357836SJohn.Forte@Sun.COM #include <sys/ddi.h>
367836SJohn.Forte@Sun.COM #include <sys/sunddi.h>
377836SJohn.Forte@Sun.COM #include <sys/varargs.h>
387836SJohn.Forte@Sun.COM 
397836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
407836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
417836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_impl.h>
427836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
437836SJohn.Forte@Sun.COM 
447836SJohn.Forte@Sun.COM #ifdef DS_DDICT
457836SJohn.Forte@Sun.COM #include <sys/nsctl/contract.h>
467836SJohn.Forte@Sun.COM #endif
477836SJohn.Forte@Sun.COM /*
487836SJohn.Forte@Sun.COM  *	Debug support to allow testing in userspace
497836SJohn.Forte@Sun.COM  */
507836SJohn.Forte@Sun.COM 
517836SJohn.Forte@Sun.COM #if	UNISTAT_ASSERTIONS
527836SJohn.Forte@Sun.COM #define	_CELEVEL CE_PANIC
537836SJohn.Forte@Sun.COM #else
547836SJohn.Forte@Sun.COM #define	_CELEVEL CE_WARN
557836SJohn.Forte@Sun.COM #endif
567836SJohn.Forte@Sun.COM 
577836SJohn.Forte@Sun.COM 
587836SJohn.Forte@Sun.COM /*
597836SJohn.Forte@Sun.COM  *	Unistat state data
607836SJohn.Forte@Sun.COM  */
617836SJohn.Forte@Sun.COM 
627836SJohn.Forte@Sun.COM /*
637836SJohn.Forte@Sun.COM  * This flag is made nonzero to indicate the bytestream transport mechanism
647836SJohn.Forte@Sun.COM  * is initalized.
657836SJohn.Forte@Sun.COM  */
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM static int bytestream_transport_initialized = 0;
687836SJohn.Forte@Sun.COM 
697836SJohn.Forte@Sun.COM /*
707836SJohn.Forte@Sun.COM  *	Common code for status init
717836SJohn.Forte@Sun.COM  *
727836SJohn.Forte@Sun.COM  */
737836SJohn.Forte@Sun.COM 
init_status(spcs_s_pinfo_t * p)747836SJohn.Forte@Sun.COM static void init_status(spcs_s_pinfo_t *p)
757836SJohn.Forte@Sun.COM {
767836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
77*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!init_status entry");
787836SJohn.Forte@Sun.COM #endif
797836SJohn.Forte@Sun.COM 	p->major = SPCS_S_MAJOR_REV;
807836SJohn.Forte@Sun.COM 	p->minor = SPCS_S_MINOR_REV;
817836SJohn.Forte@Sun.COM 	p->icount = 0;
827836SJohn.Forte@Sun.COM 	p->scount = 0;
837836SJohn.Forte@Sun.COM 	p->tcount = 0;
847836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
85*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!init_status exit");
867836SJohn.Forte@Sun.COM #endif
877836SJohn.Forte@Sun.COM }
887836SJohn.Forte@Sun.COM 
897836SJohn.Forte@Sun.COM /*
907836SJohn.Forte@Sun.COM  *	Create and initialize local ioctl status.
917836SJohn.Forte@Sun.COM  *
927836SJohn.Forte@Sun.COM  */
937836SJohn.Forte@Sun.COM 
947836SJohn.Forte@Sun.COM spcs_s_info_t
spcs_s_kcreate()957836SJohn.Forte@Sun.COM spcs_s_kcreate()
967836SJohn.Forte@Sun.COM {
977836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *kstatus;
987836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
99*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_kcreate entry");
1007836SJohn.Forte@Sun.COM #endif
1017836SJohn.Forte@Sun.COM 	kstatus = (spcs_s_pinfo_t *)
102*9093SRamana.Srikanth@Sun.COM 	    kmem_alloc(sizeof (spcs_s_pinfo_t), KM_SLEEP);
1037836SJohn.Forte@Sun.COM 
1047836SJohn.Forte@Sun.COM 	if (kstatus)
1057836SJohn.Forte@Sun.COM 		init_status(kstatus);
1067836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
107*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_kcreate exit");
1087836SJohn.Forte@Sun.COM #endif
1097836SJohn.Forte@Sun.COM 	return ((spcs_s_info_t)kstatus);
1107836SJohn.Forte@Sun.COM }
1117836SJohn.Forte@Sun.COM 
1127836SJohn.Forte@Sun.COM /*
1137836SJohn.Forte@Sun.COM  *	Initialize existing ioctl status.
1147836SJohn.Forte@Sun.COM  */
1157836SJohn.Forte@Sun.COM 
1167836SJohn.Forte@Sun.COM void
spcs_s_kinit(spcs_s_info_t kstatus)1177836SJohn.Forte@Sun.COM spcs_s_kinit(spcs_s_info_t kstatus)
1187836SJohn.Forte@Sun.COM {
1197836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
120*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_kinit called");
1217836SJohn.Forte@Sun.COM #endif
1227836SJohn.Forte@Sun.COM 	init_status((spcs_s_pinfo_t *)kstatus);
1237836SJohn.Forte@Sun.COM }
1247836SJohn.Forte@Sun.COM 
1257836SJohn.Forte@Sun.COM /*
1267836SJohn.Forte@Sun.COM  *	Release (free) ioctl status storage.
1277836SJohn.Forte@Sun.COM  *	BUG: this should take an spcs_s_info_t** or else the userspace
1287836SJohn.Forte@Sun.COM  *	version shoud just take a pointer. Could hopefully fix up Simon and
1297836SJohn.Forte@Sun.COM  *	Phil's code without too much trouble to fix this. Being inconsistent
1307836SJohn.Forte@Sun.COM  *	over the long term is bad.
1317836SJohn.Forte@Sun.COM  */
1327836SJohn.Forte@Sun.COM 
1337836SJohn.Forte@Sun.COM void
spcs_s_kfree(spcs_s_info_t kstatus)1347836SJohn.Forte@Sun.COM spcs_s_kfree(spcs_s_info_t kstatus)
1357836SJohn.Forte@Sun.COM {
1367836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
137*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_kfree entry");
1387836SJohn.Forte@Sun.COM #endif
1397836SJohn.Forte@Sun.COM 	kmem_free((void *)kstatus, sizeof (spcs_s_pinfo_t));
1407836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
141*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_kfree exit");
1427836SJohn.Forte@Sun.COM #endif
1437836SJohn.Forte@Sun.COM }
1447836SJohn.Forte@Sun.COM 
1457836SJohn.Forte@Sun.COM /*
1467836SJohn.Forte@Sun.COM  *	Delete one error code and its supplemental info
1477836SJohn.Forte@Sun.COM  *	The "oldest" error code is removed.
1487836SJohn.Forte@Sun.COM  *	The assumption is that there is at least one status code present.
1497836SJohn.Forte@Sun.COM  *	Neither sdata nor tdata space is reclaimed
1507836SJohn.Forte@Sun.COM  */
1517836SJohn.Forte@Sun.COM 
1527836SJohn.Forte@Sun.COM static void
spcs_delete(spcs_s_pinfo_t * p)1537836SJohn.Forte@Sun.COM spcs_delete(spcs_s_pinfo_t *p)
1547836SJohn.Forte@Sun.COM {
1557836SJohn.Forte@Sun.COM 	int i;
1567836SJohn.Forte@Sun.COM 	int d;
1577836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
158*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_delete entry");
1597836SJohn.Forte@Sun.COM #endif
1607836SJohn.Forte@Sun.COM 	d = p->idata[0].f.sup_count + 1;
1617836SJohn.Forte@Sun.COM 
1627836SJohn.Forte@Sun.COM 	for (i = 0; i < (p->icount - d); i++)
1637836SJohn.Forte@Sun.COM 		p->idata[i] = p->idata[i+d];
1647836SJohn.Forte@Sun.COM 	p->icount -= d;
1657836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
166*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_delete exit");
1677836SJohn.Forte@Sun.COM #endif
1687836SJohn.Forte@Sun.COM }
1697836SJohn.Forte@Sun.COM 
1707836SJohn.Forte@Sun.COM /*
1717836SJohn.Forte@Sun.COM  * 	Common code for adding a status code
1727836SJohn.Forte@Sun.COM  *	Return 1 if overflow detected, 0 if enough space for code and support
1737836SJohn.Forte@Sun.COM  *      info.
1747836SJohn.Forte@Sun.COM  */
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM static boolean_t
add_code(spcs_s_pinfo_t * p,spcs_s_status_t stcode)1777836SJohn.Forte@Sun.COM add_code(spcs_s_pinfo_t *p, spcs_s_status_t stcode)
1787836SJohn.Forte@Sun.COM {
1797836SJohn.Forte@Sun.COM 	spcs_s_udata_t c;
1807836SJohn.Forte@Sun.COM 	c.s = stcode;
1817836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
182*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!add_code entry");
1837836SJohn.Forte@Sun.COM #endif
1847836SJohn.Forte@Sun.COM 
1857836SJohn.Forte@Sun.COM 	if ((p->icount + c.f.sup_count + 1) > SPCS_S_IDSIZE) {
1867836SJohn.Forte@Sun.COM 		if (p->icount == SPCS_S_IDSIZE)
1877836SJohn.Forte@Sun.COM 			spcs_delete(p);
1887836SJohn.Forte@Sun.COM 		p->idata[p->icount++].s = SPCS_EOVERFLOW;
1897836SJohn.Forte@Sun.COM 
190*9093SRamana.Srikanth@Sun.COM 		cmn_err(_CELEVEL, "!SPCS Unistat: not enough room in idata!");
1917836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
192*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!add_code exit 1");
1937836SJohn.Forte@Sun.COM #endif
1947836SJohn.Forte@Sun.COM 
1957836SJohn.Forte@Sun.COM 		return (B_TRUE);
1967836SJohn.Forte@Sun.COM 	} else
1977836SJohn.Forte@Sun.COM 		p->idata[p->icount++] = c;
1987836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
199*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!add_code exit 2");
2007836SJohn.Forte@Sun.COM #endif
2017836SJohn.Forte@Sun.COM 	return (B_FALSE);
2027836SJohn.Forte@Sun.COM }
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM /*
2057836SJohn.Forte@Sun.COM  * 	Common code for adding a string as supplemental info.
2067836SJohn.Forte@Sun.COM  *	Add_code is assumed to have been called already to ensure enough space
2077836SJohn.Forte@Sun.COM  *      idata. The string is copied into the sdata array and the index to the
2087836SJohn.Forte@Sun.COM  *	first character is put in idata along with the datatype indicator.
2097836SJohn.Forte@Sun.COM  */
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM static void
add_item(spcs_s_pinfo_t * p,char * string)2127836SJohn.Forte@Sun.COM add_item(spcs_s_pinfo_t *p, char *string)
2137836SJohn.Forte@Sun.COM {
2147836SJohn.Forte@Sun.COM 	int len;
2157836SJohn.Forte@Sun.COM 	char *nullstr = "XXXXXXXX";
2167836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
217*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!add_item entry");
2187836SJohn.Forte@Sun.COM #endif
2197836SJohn.Forte@Sun.COM 	len = strlen(string);
2207836SJohn.Forte@Sun.COM 
2217836SJohn.Forte@Sun.COM /*
2227836SJohn.Forte@Sun.COM  * The following HACK is for RDC which is somewhat careless about
2237836SJohn.Forte@Sun.COM  * it's usage of strings. It does not make sense to panic the machine
2247836SJohn.Forte@Sun.COM  * because we botched an informational message. Print something
2257836SJohn.Forte@Sun.COM  * usefull so we can go back and fix it.
2267836SJohn.Forte@Sun.COM  * This can be removed when everyone has played by the correct unistat rules
2277836SJohn.Forte@Sun.COM  */
2287836SJohn.Forte@Sun.COM 	if (len == 0) {
2297836SJohn.Forte@Sun.COM 		string = nullstr;
2307836SJohn.Forte@Sun.COM 		len = strlen(nullstr);
2317836SJohn.Forte@Sun.COM 	}
2327836SJohn.Forte@Sun.COM 	if ((len + 1) > (SPCS_S_SDSIZE - p->scount))
2337836SJohn.Forte@Sun.COM 		cmn_err(_CELEVEL,
234*9093SRamana.Srikanth@Sun.COM 		    "!SPCS: Unistat sdata array too small: needed %d bytes",
235*9093SRamana.Srikanth@Sun.COM 		    len + 1);
2367836SJohn.Forte@Sun.COM 
2377836SJohn.Forte@Sun.COM 	p->idata[p->icount].su.type = SU_STRING;
2387836SJohn.Forte@Sun.COM 	p->idata[p->icount++].su.offset = p->scount;
2397836SJohn.Forte@Sun.COM 	(void) strcpy(&(p->sdata[p->scount]), string);
2407836SJohn.Forte@Sun.COM 	p->scount += len + 1;
2417836SJohn.Forte@Sun.COM }
2427836SJohn.Forte@Sun.COM 
2437836SJohn.Forte@Sun.COM /*
2447836SJohn.Forte@Sun.COM  *	Check the rev level of the userspace status structure
2457836SJohn.Forte@Sun.COM  *	and spew some chunks if it doesn't match the kernel's unistat rev.
2467836SJohn.Forte@Sun.COM  *	Some day something more intelligent should happen to try to provide
2477836SJohn.Forte@Sun.COM  *	backward compatiblity with some mismatches (see the impl header file).
2487836SJohn.Forte@Sun.COM  *	Returns true if the revisions are compatible, false otherwise.
2497836SJohn.Forte@Sun.COM  */
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM static boolean_t
check_revision(spcs_s_info_t ustatus)2527836SJohn.Forte@Sun.COM check_revision(spcs_s_info_t ustatus)
2537836SJohn.Forte@Sun.COM {
2547836SJohn.Forte@Sun.COM 	char *m;
2557836SJohn.Forte@Sun.COM 	char buf[SPCS_S_REVSIZE];
2567836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p = (spcs_s_pinfo_t *)buf;
2577836SJohn.Forte@Sun.COM 	int mode = 0;
2587836SJohn.Forte@Sun.COM 
2597836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
260*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!check_revision entry");
2617836SJohn.Forte@Sun.COM #endif
2627836SJohn.Forte@Sun.COM 
2637836SJohn.Forte@Sun.COM 	m =
264*9093SRamana.Srikanth@Sun.COM 	    "!SPCS Unistat failure (packaging error): data struct mismatch";
2657836SJohn.Forte@Sun.COM 	(void) ddi_copyin((void *) ustatus, (void *) p, SPCS_S_REVSIZE, mode);
2667836SJohn.Forte@Sun.COM 
2677836SJohn.Forte@Sun.COM 	if ((p->major == SPCS_S_MAJOR_REV) && (p->minor == SPCS_S_MINOR_REV)) {
2687836SJohn.Forte@Sun.COM 		/* Both match */
2697836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
270*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!check_revision exit 1");
2717836SJohn.Forte@Sun.COM #endif
2727836SJohn.Forte@Sun.COM 		return (B_TRUE);
2737836SJohn.Forte@Sun.COM 	}
2747836SJohn.Forte@Sun.COM 
2757836SJohn.Forte@Sun.COM 	/*
2767836SJohn.Forte@Sun.COM 	 * We have a major and/or minor version mismatch.
2777836SJohn.Forte@Sun.COM 	 * Deal with each case individually.
2787836SJohn.Forte@Sun.COM 	 */
2797836SJohn.Forte@Sun.COM 
2807836SJohn.Forte@Sun.COM #ifdef DEBUG
281*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!unistat kernel v%d.%d, user v%d.%d\n",
282*9093SRamana.Srikanth@Sun.COM 	    SPCS_S_MAJOR_REV, SPCS_S_MINOR_REV, (int)p->major, (int)p->minor);
2837836SJohn.Forte@Sun.COM #endif
2847836SJohn.Forte@Sun.COM 
2857836SJohn.Forte@Sun.COM 	if (p->major > SPCS_S_MAJOR_REV) {
2867836SJohn.Forte@Sun.COM 		/*
2877836SJohn.Forte@Sun.COM 		 * couldn't guess what to do if the userspace version is ahead
2887836SJohn.Forte@Sun.COM 		 * of the kernel version, so issue a warning
2897836SJohn.Forte@Sun.COM 		 */
2907836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, m);
2917836SJohn.Forte@Sun.COM 	} else if (p->major < SPCS_S_MAJOR_REV) {
2927836SJohn.Forte@Sun.COM 		/*
2937836SJohn.Forte@Sun.COM 		 * kernel's major version is ahead of userspace version: do
2947836SJohn.Forte@Sun.COM 		 * something extremely clever here some day instead of the
2957836SJohn.Forte@Sun.COM 		 * warning
2967836SJohn.Forte@Sun.COM 		 */
2977836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, m);
2987836SJohn.Forte@Sun.COM 	} else if (p->minor < SPCS_S_MINOR_REV) {
2997836SJohn.Forte@Sun.COM 
3007836SJohn.Forte@Sun.COM 		/*
3017836SJohn.Forte@Sun.COM 		 * kernel's minor version is ahead of userspace version: do
3027836SJohn.Forte@Sun.COM 		 * something clever here some day instead of the warning
3037836SJohn.Forte@Sun.COM 		 */
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, m);
3067836SJohn.Forte@Sun.COM 	} else {
3077836SJohn.Forte@Sun.COM 		/*
3087836SJohn.Forte@Sun.COM 		 * couldn't guess what to do if the userspace version is ahead
3097836SJohn.Forte@Sun.COM 		 * of the kernel's minor version, so issue a warning
3107836SJohn.Forte@Sun.COM 		 */
3117836SJohn.Forte@Sun.COM 
3127836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, m);
3137836SJohn.Forte@Sun.COM 	}
3147836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
315*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!check_revision exit 2");
3167836SJohn.Forte@Sun.COM #endif
3177836SJohn.Forte@Sun.COM 	return (B_FALSE);
3187836SJohn.Forte@Sun.COM }
3197836SJohn.Forte@Sun.COM 
3207836SJohn.Forte@Sun.COM /*
3217836SJohn.Forte@Sun.COM  *	Add a code and optional support information to status
3227836SJohn.Forte@Sun.COM  *
3237836SJohn.Forte@Sun.COM  *	The support info can only consist of char pointers.
3247836SJohn.Forte@Sun.COM  *
3257836SJohn.Forte@Sun.COM  *	Varargs doesn't provide a means of detecting too few supplemental
3267836SJohn.Forte@Sun.COM  *	values...
3277836SJohn.Forte@Sun.COM  */
3287836SJohn.Forte@Sun.COM 
3297836SJohn.Forte@Sun.COM void
spcs_s_add(spcs_s_info_t kstatus,spcs_s_status_t stcode,...)3307836SJohn.Forte@Sun.COM spcs_s_add(spcs_s_info_t kstatus, spcs_s_status_t stcode, ...)
3317836SJohn.Forte@Sun.COM {
3327836SJohn.Forte@Sun.COM 	va_list ap;
3337836SJohn.Forte@Sun.COM 	spcs_s_udata_t c;
3347836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
3357836SJohn.Forte@Sun.COM 	char *sp;
3367836SJohn.Forte@Sun.COM 
3377836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
338*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!cspcs_s_add entry");
3397836SJohn.Forte@Sun.COM #endif
3407836SJohn.Forte@Sun.COM 	p = (spcs_s_pinfo_t *)kstatus;
3417836SJohn.Forte@Sun.COM 	c.s = stcode;
3427836SJohn.Forte@Sun.COM 
3437836SJohn.Forte@Sun.COM 	if (add_code(p, stcode) == B_TRUE) {
3447836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
345*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!cspcs_s_add exit 1");
3467836SJohn.Forte@Sun.COM #endif
3477836SJohn.Forte@Sun.COM 		return;
3487836SJohn.Forte@Sun.COM 	}
3497836SJohn.Forte@Sun.COM 
3507836SJohn.Forte@Sun.COM 	va_start(ap, stcode);
3517836SJohn.Forte@Sun.COM 
3527836SJohn.Forte@Sun.COM 	while (c.f.sup_count--) {
3537836SJohn.Forte@Sun.COM 		sp = va_arg(ap, caddr_t);
3547836SJohn.Forte@Sun.COM 		if (sp != (char *)NULL)
3557836SJohn.Forte@Sun.COM 			add_item(p, sp);
3567836SJohn.Forte@Sun.COM 	}
3577836SJohn.Forte@Sun.COM 
3587836SJohn.Forte@Sun.COM 	va_end(ap);
3597836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
360*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!cspcs_s_add exit 2");
3617836SJohn.Forte@Sun.COM #endif
3627836SJohn.Forte@Sun.COM }
3637836SJohn.Forte@Sun.COM 
3647836SJohn.Forte@Sun.COM /*
3657836SJohn.Forte@Sun.COM  *	Common code to copy status to userspace
3667836SJohn.Forte@Sun.COM  *
3677836SJohn.Forte@Sun.COM  *	Only "used" data is copied to minimize overhead.
3687836SJohn.Forte@Sun.COM  */
3697836SJohn.Forte@Sun.COM 
3707836SJohn.Forte@Sun.COM static void
scopyout(spcs_s_pinfo_t * kstatus,spcs_s_pinfo_t * ustatus)3717836SJohn.Forte@Sun.COM scopyout(spcs_s_pinfo_t *kstatus, spcs_s_pinfo_t *ustatus)
3727836SJohn.Forte@Sun.COM {
3737836SJohn.Forte@Sun.COM 	int mode = 0;
3747836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
375*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!scopyout entry");
3767836SJohn.Forte@Sun.COM #endif
3777836SJohn.Forte@Sun.COM 
3787836SJohn.Forte@Sun.COM 	/*
3797836SJohn.Forte@Sun.COM 	 * If tdata is in use, blow up: asynch data is not intended for ioctls.
3807836SJohn.Forte@Sun.COM 	 * How would we ship it back? (the user hasn't given us any place to
3817836SJohn.Forte@Sun.COM 	 * put it!)
3827836SJohn.Forte@Sun.COM 	 */
3837836SJohn.Forte@Sun.COM 
3847836SJohn.Forte@Sun.COM 	if (kstatus->tcount)
385*9093SRamana.Srikanth@Sun.COM 		cmn_err(_CELEVEL, "!SPCS: Unistat async data in ioctl status!");
3867836SJohn.Forte@Sun.COM 
3877836SJohn.Forte@Sun.COM 	/*
3887836SJohn.Forte@Sun.COM 	 * Gently, Bentley
3897836SJohn.Forte@Sun.COM 	 * Have to copy all the header stuff even though there is no need for
3907836SJohn.Forte@Sun.COM 	 * some items like the revisions. This is unavoidable without making
3917836SJohn.Forte@Sun.COM 	 * the structure more complex or guessing about alignment and the true
3927836SJohn.Forte@Sun.COM 	 * size of the part of the structure sitting ahead of the {i,s,t}data
3937836SJohn.Forte@Sun.COM 	 * arrays.
3947836SJohn.Forte@Sun.COM 	 */
3957836SJohn.Forte@Sun.COM 
3967836SJohn.Forte@Sun.COM 	(void) ddi_copyout((void *) kstatus, (void *) ustatus,
397*9093SRamana.Srikanth@Sun.COM 	    sizeof (spcs_s_pinfo_t) - (sizeof (kstatus->idata) +
398*9093SRamana.Srikanth@Sun.COM 	    sizeof (kstatus->sdata) + sizeof (kstatus->tdata)), mode);
3997836SJohn.Forte@Sun.COM 	(void) ddi_copyout((void *)kstatus->idata, (void *) ustatus->idata,
400*9093SRamana.Srikanth@Sun.COM 	    (kstatus->icount * sizeof (kstatus->idata[0])), mode);
4017836SJohn.Forte@Sun.COM 	(void) ddi_copyout((void *)kstatus->sdata, (void *) ustatus->sdata,
402*9093SRamana.Srikanth@Sun.COM 	    (kstatus->scount * sizeof (kstatus->sdata[0])), mode);
4037836SJohn.Forte@Sun.COM 	(void) ddi_copyout((void *)kstatus->tdata, (void *) ustatus->tdata,
404*9093SRamana.Srikanth@Sun.COM 	    (kstatus->tcount * sizeof (kstatus->tdata[0])), mode);
4057836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
406*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!scopyout exit");
4077836SJohn.Forte@Sun.COM #endif
4087836SJohn.Forte@Sun.COM }
4097836SJohn.Forte@Sun.COM 
4107836SJohn.Forte@Sun.COM /*
4117836SJohn.Forte@Sun.COM  *	Copy the ioctl status info to userspace
4127836SJohn.Forte@Sun.COM  */
4137836SJohn.Forte@Sun.COM 
4147836SJohn.Forte@Sun.COM void
spcs_s_copyout(spcs_s_info_t * kstatus_a,spcs_s_info_t ustatus)4157836SJohn.Forte@Sun.COM spcs_s_copyout(spcs_s_info_t *kstatus_a, spcs_s_info_t ustatus)
4167836SJohn.Forte@Sun.COM {
4177836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
418*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_copyout entry");
4197836SJohn.Forte@Sun.COM #endif
4207836SJohn.Forte@Sun.COM 	if (check_revision(ustatus) == B_TRUE)
4217836SJohn.Forte@Sun.COM 		scopyout((spcs_s_pinfo_t *)*kstatus_a,
4227836SJohn.Forte@Sun.COM 		    (spcs_s_pinfo_t *)ustatus);
4237836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
424*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_copyout exit");
4257836SJohn.Forte@Sun.COM #endif
4267836SJohn.Forte@Sun.COM }
4277836SJohn.Forte@Sun.COM 
4287836SJohn.Forte@Sun.COM 
4297836SJohn.Forte@Sun.COM /*
4307836SJohn.Forte@Sun.COM  *	Copy the ioctl status info to userspace
4317836SJohn.Forte@Sun.COM  *      Free the status info storage.
4327836SJohn.Forte@Sun.COM  */
4337836SJohn.Forte@Sun.COM 
4347836SJohn.Forte@Sun.COM void
spcs_s_copyoutf(spcs_s_info_t * kstatus_a,spcs_s_info_t ustatus)4357836SJohn.Forte@Sun.COM spcs_s_copyoutf(spcs_s_info_t *kstatus_a, spcs_s_info_t ustatus)
4367836SJohn.Forte@Sun.COM {
4377836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
438*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_copyoutf entry");
4397836SJohn.Forte@Sun.COM #endif
4407836SJohn.Forte@Sun.COM 	if (check_revision(ustatus) == B_TRUE)
4417836SJohn.Forte@Sun.COM 		scopyout((spcs_s_pinfo_t *)*kstatus_a,
4427836SJohn.Forte@Sun.COM 		    (spcs_s_pinfo_t *)ustatus);
4437836SJohn.Forte@Sun.COM 	spcs_s_kfree(*kstatus_a);
4447836SJohn.Forte@Sun.COM 	*kstatus_a = NULL;
4457836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
446*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_copyoutf exit");
4477836SJohn.Forte@Sun.COM #endif
4487836SJohn.Forte@Sun.COM }
4497836SJohn.Forte@Sun.COM 
4507836SJohn.Forte@Sun.COM /*
4517836SJohn.Forte@Sun.COM  *	Return the oldest status code from the status info or SPCS_S_OK if
4527836SJohn.Forte@Sun.COM  *      there is none.
4537836SJohn.Forte@Sun.COM  */
4547836SJohn.Forte@Sun.COM 
4557836SJohn.Forte@Sun.COM spcs_s_status_t
spcs_s_oldest_status(spcs_s_info_t kstatus)4567836SJohn.Forte@Sun.COM spcs_s_oldest_status(spcs_s_info_t kstatus)
4577836SJohn.Forte@Sun.COM {
4587836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
4597836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
460*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_oldest_status entry");
4617836SJohn.Forte@Sun.COM #endif
4627836SJohn.Forte@Sun.COM 	p = (spcs_s_pinfo_t *)kstatus;
4637836SJohn.Forte@Sun.COM 
4647836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
465*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_oldest_status exit");
4667836SJohn.Forte@Sun.COM #endif
4677836SJohn.Forte@Sun.COM 	return (p->icount ? p->idata[0].s : SPCS_S_OK);
4687836SJohn.Forte@Sun.COM }
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM /*
4717836SJohn.Forte@Sun.COM  *      Return the idata index of the last status code in the array (i.e.
4727836SJohn.Forte@Sun.COM  *      the "youngest" code present). The assumption is that the caller has
4737836SJohn.Forte@Sun.COM  *      checked to see that pcount is nonzero.
4747836SJohn.Forte@Sun.COM  */
4757836SJohn.Forte@Sun.COM 
4767836SJohn.Forte@Sun.COM static int
last_code_idx(spcs_s_pinfo_t * p)4777836SJohn.Forte@Sun.COM last_code_idx(spcs_s_pinfo_t *p)
4787836SJohn.Forte@Sun.COM {
4797836SJohn.Forte@Sun.COM 	int last = 0;
4807836SJohn.Forte@Sun.COM 	int idx = 0;
4817836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
482*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!last_code_idx entry");
4837836SJohn.Forte@Sun.COM #endif
4847836SJohn.Forte@Sun.COM 
4857836SJohn.Forte@Sun.COM 	while (idx < p->icount) {
4867836SJohn.Forte@Sun.COM 		last = idx;
4877836SJohn.Forte@Sun.COM 		idx += p->idata[idx].f.sup_count + 1;
4887836SJohn.Forte@Sun.COM 	}
4897836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
490*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!last_code_idx exit");
4917836SJohn.Forte@Sun.COM #endif
4927836SJohn.Forte@Sun.COM 	return (last);
4937836SJohn.Forte@Sun.COM }
4947836SJohn.Forte@Sun.COM 
4957836SJohn.Forte@Sun.COM /*
4967836SJohn.Forte@Sun.COM  *	Return the youngest status code form the status info or SPCS_S_OK if
4977836SJohn.Forte@Sun.COM  *      there is none.
4987836SJohn.Forte@Sun.COM  */
4997836SJohn.Forte@Sun.COM 
5007836SJohn.Forte@Sun.COM spcs_s_status_t
spcs_s_youngest_status(spcs_s_info_t kstatus)5017836SJohn.Forte@Sun.COM spcs_s_youngest_status(spcs_s_info_t kstatus)
5027836SJohn.Forte@Sun.COM {
5037836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
5047836SJohn.Forte@Sun.COM 	spcs_s_status_t temp;
5057836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
506*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_youngest_status entry");
5077836SJohn.Forte@Sun.COM #endif
5087836SJohn.Forte@Sun.COM 	p = (spcs_s_pinfo_t *)kstatus;
5097836SJohn.Forte@Sun.COM 
5107836SJohn.Forte@Sun.COM 	if (p->icount)
5117836SJohn.Forte@Sun.COM 		temp = p->idata[last_code_idx(p)].s;
5127836SJohn.Forte@Sun.COM 	else
5137836SJohn.Forte@Sun.COM 		temp = SPCS_S_OK;
5147836SJohn.Forte@Sun.COM 
5157836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
516*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_youngest_status exit");
5177836SJohn.Forte@Sun.COM #endif
5187836SJohn.Forte@Sun.COM 	return (temp);
5197836SJohn.Forte@Sun.COM }
5207836SJohn.Forte@Sun.COM 
5217836SJohn.Forte@Sun.COM /*
5227836SJohn.Forte@Sun.COM  *      Insert a new status code or NULL if there is none.
5237836SJohn.Forte@Sun.COM  *      Copy the status info to userspace.
5247836SJohn.Forte@Sun.COM  *      return a value to use as an return value (e.g. ioctl return).
5257836SJohn.Forte@Sun.COM  */
5267836SJohn.Forte@Sun.COM 
5277836SJohn.Forte@Sun.COM spcs_s_status_t
spcs_s_ocopyout(spcs_s_info_t * kstatus_a,spcs_s_info_t ustatus,spcs_s_status_t stcode,...)5287836SJohn.Forte@Sun.COM spcs_s_ocopyout(spcs_s_info_t *kstatus_a,
5297836SJohn.Forte@Sun.COM 			spcs_s_info_t ustatus, spcs_s_status_t stcode, ...)
5307836SJohn.Forte@Sun.COM {
5317836SJohn.Forte@Sun.COM 	spcs_s_udata_t ret;
5327836SJohn.Forte@Sun.COM 	va_list ap;
5337836SJohn.Forte@Sun.COM 	spcs_s_udata_t c;
5347836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
5357836SJohn.Forte@Sun.COM 	char *sp;
5367836SJohn.Forte@Sun.COM 
5377836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
538*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_ocopyout entry");
5397836SJohn.Forte@Sun.COM #endif
5407836SJohn.Forte@Sun.COM 	p  = (spcs_s_pinfo_t *)*kstatus_a;
5417836SJohn.Forte@Sun.COM 	c.s = stcode;
5427836SJohn.Forte@Sun.COM 
5437836SJohn.Forte@Sun.COM 	if (check_revision(ustatus) == B_FALSE)
5447836SJohn.Forte@Sun.COM 		ret.s = EINVAL;
5457836SJohn.Forte@Sun.COM 	else {
5467836SJohn.Forte@Sun.COM 		if (stcode) {
5477836SJohn.Forte@Sun.COM 			if (add_code(p, stcode) == B_FALSE) {
5487836SJohn.Forte@Sun.COM 				va_start(ap, stcode);
5497836SJohn.Forte@Sun.COM 
5507836SJohn.Forte@Sun.COM 				while (c.f.sup_count--) {
5517836SJohn.Forte@Sun.COM 					sp = va_arg(ap, caddr_t);
5527836SJohn.Forte@Sun.COM 					if (sp != (char *)NULL)
5537836SJohn.Forte@Sun.COM 						add_item(p, sp);
5547836SJohn.Forte@Sun.COM 				}
5557836SJohn.Forte@Sun.COM 
5567836SJohn.Forte@Sun.COM 				va_end(ap);
5577836SJohn.Forte@Sun.COM 			}
5587836SJohn.Forte@Sun.COM 		}
5597836SJohn.Forte@Sun.COM 		ret.s = p->icount ? p->idata[last_code_idx(p)].s: SPCS_S_OK;
5607836SJohn.Forte@Sun.COM 		scopyout(p, (spcs_s_pinfo_t *)ustatus);
5617836SJohn.Forte@Sun.COM 	}
5627836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
563*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_ocopyout exit");
5647836SJohn.Forte@Sun.COM #endif
5657836SJohn.Forte@Sun.COM 	return (ret.s);
5667836SJohn.Forte@Sun.COM }
5677836SJohn.Forte@Sun.COM 
5687836SJohn.Forte@Sun.COM 
5697836SJohn.Forte@Sun.COM /*
5707836SJohn.Forte@Sun.COM  *      Insert a new status code or NULL if there is none.
5717836SJohn.Forte@Sun.COM  *      Copy the status info to userspace.
5727836SJohn.Forte@Sun.COM  *      Free the kernel status info storage
5737836SJohn.Forte@Sun.COM  *      return a value to use as an operatiion return value (e.g. ioctl return)
5747836SJohn.Forte@Sun.COM  */
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM spcs_s_status_t
spcs_s_ocopyoutf(spcs_s_info_t * kstatus_a,spcs_s_info_t ustatus,spcs_s_status_t stcode,...)5777836SJohn.Forte@Sun.COM spcs_s_ocopyoutf(spcs_s_info_t *kstatus_a,
5787836SJohn.Forte@Sun.COM 		spcs_s_info_t ustatus, spcs_s_status_t stcode, ...)
5797836SJohn.Forte@Sun.COM {
5807836SJohn.Forte@Sun.COM 	spcs_s_udata_t ret;
5817836SJohn.Forte@Sun.COM 	va_list ap;
5827836SJohn.Forte@Sun.COM 	spcs_s_udata_t c;
5837836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
5847836SJohn.Forte@Sun.COM 	char *sp;
5857836SJohn.Forte@Sun.COM 
5867836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
587*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_ocopyoutf entry");
5887836SJohn.Forte@Sun.COM #endif
5897836SJohn.Forte@Sun.COM 	p = *(spcs_s_pinfo_t **)kstatus_a;
5907836SJohn.Forte@Sun.COM 	c.s = stcode;
5917836SJohn.Forte@Sun.COM 
5927836SJohn.Forte@Sun.COM 	if (check_revision(ustatus) == B_FALSE) {
5937836SJohn.Forte@Sun.COM 		ret.s = EINVAL;
5947836SJohn.Forte@Sun.COM 	} else {
5957836SJohn.Forte@Sun.COM 		if (stcode) {
5967836SJohn.Forte@Sun.COM 			if (add_code(p, stcode) == B_FALSE) {
5977836SJohn.Forte@Sun.COM 				va_start(ap, stcode);
5987836SJohn.Forte@Sun.COM 
5997836SJohn.Forte@Sun.COM 				while (c.f.sup_count--) {
6007836SJohn.Forte@Sun.COM 					sp = va_arg(ap, caddr_t);
6017836SJohn.Forte@Sun.COM 					if (sp != (char *)NULL)
6027836SJohn.Forte@Sun.COM 						add_item(p, sp);
6037836SJohn.Forte@Sun.COM 				}
6047836SJohn.Forte@Sun.COM 
6057836SJohn.Forte@Sun.COM 				va_end(ap);
6067836SJohn.Forte@Sun.COM 			}
6077836SJohn.Forte@Sun.COM 		}
6087836SJohn.Forte@Sun.COM 
6097836SJohn.Forte@Sun.COM 		ret.s = p->icount ? p->idata[last_code_idx(p)].s: SPCS_S_OK;
6107836SJohn.Forte@Sun.COM 		scopyout(p, (spcs_s_pinfo_t *)ustatus);
6117836SJohn.Forte@Sun.COM 	}
6127836SJohn.Forte@Sun.COM 	spcs_s_kfree((spcs_s_info_t)p);
6137836SJohn.Forte@Sun.COM 	*kstatus_a = NULL;
6147836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
615*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_ocopyoutf exit");
6167836SJohn.Forte@Sun.COM #endif
6177836SJohn.Forte@Sun.COM 	return (ret.s);
6187836SJohn.Forte@Sun.COM }
6197836SJohn.Forte@Sun.COM 
6207836SJohn.Forte@Sun.COM /*
6217836SJohn.Forte@Sun.COM  * Return true if a status code is a Solaris error code
6227836SJohn.Forte@Sun.COM  */
6237836SJohn.Forte@Sun.COM 
6247836SJohn.Forte@Sun.COM boolean_t
spcs_s_is_solaris(spcs_s_status_t error)6257836SJohn.Forte@Sun.COM spcs_s_is_solaris(spcs_s_status_t error)
6267836SJohn.Forte@Sun.COM {
6277836SJohn.Forte@Sun.COM 	spcs_s_udata_t c;
6287836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
629*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_is_solaris called");
6307836SJohn.Forte@Sun.COM #endif
6317836SJohn.Forte@Sun.COM 	c.s = error;
6327836SJohn.Forte@Sun.COM 	return (c.f.module == 0 ? B_TRUE : B_FALSE);
6337836SJohn.Forte@Sun.COM }
6347836SJohn.Forte@Sun.COM 
6357836SJohn.Forte@Sun.COM /*
6367836SJohn.Forte@Sun.COM  * Edit a value into a numeric string
6377836SJohn.Forte@Sun.COM  */
6387836SJohn.Forte@Sun.COM 
6397836SJohn.Forte@Sun.COM char
spcs_s_inttostring(int val,char * buf,int buflen,int hex)6407836SJohn.Forte@Sun.COM *spcs_s_inttostring(int val, char *buf, int buflen, int hex)
6417836SJohn.Forte@Sun.COM {
6427836SJohn.Forte@Sun.COM 	char tempbuf[20];
6437836SJohn.Forte@Sun.COM 
6447836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
645*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!spcs_s_inttostring entry 0x%x", val);
6467836SJohn.Forte@Sun.COM #endif
6477836SJohn.Forte@Sun.COM 	if (buflen) {
6487836SJohn.Forte@Sun.COM 		if (hex)
6497836SJohn.Forte@Sun.COM 			(void) sprintf(tempbuf, "0x%0X", val);
6507836SJohn.Forte@Sun.COM 		else
6517836SJohn.Forte@Sun.COM 			(void) sprintf(tempbuf, "%d", val);
6527836SJohn.Forte@Sun.COM 		if (strlen(tempbuf) < (size_t)buflen)
6537836SJohn.Forte@Sun.COM 			(void) strcpy(buf, tempbuf);
6547836SJohn.Forte@Sun.COM 		else
6557836SJohn.Forte@Sun.COM 			(void) strcpy(buf, "***");
6567836SJohn.Forte@Sun.COM 	} else  {
6577836SJohn.Forte@Sun.COM 		(void) strcpy(buf, "***");
6587836SJohn.Forte@Sun.COM 	}
6597836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
660*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_inttostring exit: %s", buf);
6617836SJohn.Forte@Sun.COM #endif
6627836SJohn.Forte@Sun.COM 	return (buf);
6637836SJohn.Forte@Sun.COM }
6647836SJohn.Forte@Sun.COM 
6657836SJohn.Forte@Sun.COM /*
6667836SJohn.Forte@Sun.COM  *	Initialize the bytestream mechanism.
6677836SJohn.Forte@Sun.COM  *	This is a prototype. Specification TBD. Not in 10/22 commitment
6687836SJohn.Forte@Sun.COM  */
6697836SJohn.Forte@Sun.COM 
6707836SJohn.Forte@Sun.COM int
spcs_s_start_bytestream()6717836SJohn.Forte@Sun.COM spcs_s_start_bytestream()
6727836SJohn.Forte@Sun.COM {
6737836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
674*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_start_bytestream called");
6757836SJohn.Forte@Sun.COM #endif
6767836SJohn.Forte@Sun.COM 	bytestream_transport_initialized = 1;
6777836SJohn.Forte@Sun.COM 	return (SPCS_S_OK);
6787836SJohn.Forte@Sun.COM }
6797836SJohn.Forte@Sun.COM 
6807836SJohn.Forte@Sun.COM /*
6817836SJohn.Forte@Sun.COM  *	Stop (shut off) the bytestream mechanism.
6827836SJohn.Forte@Sun.COM  *
6837836SJohn.Forte@Sun.COM  *	This is a prototype. Specification TBD. Not in 10/22 commitment
6847836SJohn.Forte@Sun.COM  */
6857836SJohn.Forte@Sun.COM 
6867836SJohn.Forte@Sun.COM int
spcs_s_stop_bytestream()6877836SJohn.Forte@Sun.COM spcs_s_stop_bytestream()
6887836SJohn.Forte@Sun.COM {
6897836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
690*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_stop_bytestream called");
6917836SJohn.Forte@Sun.COM #endif
6927836SJohn.Forte@Sun.COM 	bytestream_transport_initialized = 0;
6937836SJohn.Forte@Sun.COM 	return (SPCS_S_OK);
6947836SJohn.Forte@Sun.COM }
6957836SJohn.Forte@Sun.COM 
6967836SJohn.Forte@Sun.COM /*
6977836SJohn.Forte@Sun.COM  *	Add a status code and the address and length of arbitrary binary
6987836SJohn.Forte@Sun.COM  *	data to be held (possibly with other status) for later transmission to
6997836SJohn.Forte@Sun.COM  *	userspace via a pipe facility (i.e. NOT via ioctl return). This is a
7007836SJohn.Forte@Sun.COM  *	means of getting arbitrary information with or without other status
7017836SJohn.Forte@Sun.COM  *	info shipped out as an alternative to cmn_err and/or trace file
7027836SJohn.Forte@Sun.COM  *	mechanisms.
7037836SJohn.Forte@Sun.COM  *	@param kstatus  The status info pointer
7047836SJohn.Forte@Sun.COM  *	@param stcode   The status code to annotate the data
7057836SJohn.Forte@Sun.COM  *	@param address  The starting address of the data
7067836SJohn.Forte@Sun.COM  *	@param length   The byte length of the data
7077836SJohn.Forte@Sun.COM  *	This is a prototype. Specification TBD. Not in the 10/22/98 unistat
7087836SJohn.Forte@Sun.COM  *	commitment
7097836SJohn.Forte@Sun.COM  */
7107836SJohn.Forte@Sun.COM 
7117836SJohn.Forte@Sun.COM void
spcs_s_add_bytestream(spcs_s_info_t kstatus,spcs_s_status_t stcode,spcs_s_bytestream_ptr_t data,int size)7127836SJohn.Forte@Sun.COM spcs_s_add_bytestream(spcs_s_info_t kstatus, spcs_s_status_t stcode,
7137836SJohn.Forte@Sun.COM 	spcs_s_bytestream_ptr_t data, int size)
7147836SJohn.Forte@Sun.COM {
7157836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
7167836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
717*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_add_bytestream entry");
7187836SJohn.Forte@Sun.COM #endif
7197836SJohn.Forte@Sun.COM 	p = (spcs_s_pinfo_t *)kstatus;
7207836SJohn.Forte@Sun.COM 
7217836SJohn.Forte@Sun.COM 	if (p->tcount == SPCS_S_TDSIZE)
7227836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC,
723*9093SRamana.Srikanth@Sun.COM 		    "SPCS: Unistat too many calls to spcs_s_add_bytestream");
7247836SJohn.Forte@Sun.COM 	if ((p->icount + 2) >= SPCS_S_TDSIZE)
7257836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC,
726*9093SRamana.Srikanth@Sun.COM 		    "SPCS: Unistat idata array too small in "
727*9093SRamana.Srikanth@Sun.COM 		    "spcs_s_add_bytestream");
7287836SJohn.Forte@Sun.COM 	p->idata[p->icount].s = stcode;
7297836SJohn.Forte@Sun.COM 	if (p->idata[p->icount++].f.sup_count != 1)
7307836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC,
731*9093SRamana.Srikanth@Sun.COM 		    "SPCS: Unistat wrong sup_count in spcs_s_add_bytestream");
7327836SJohn.Forte@Sun.COM 	p->idata[p->icount].su.type = SU_BYTESTREAM;
7337836SJohn.Forte@Sun.COM 	p->idata[p->icount].su.offset = p->tcount++;
7347836SJohn.Forte@Sun.COM 	p->tdata[p->idata[p->icount].su.offset].size = size;
7357836SJohn.Forte@Sun.COM 	p->tdata[p->idata[p->icount++].su.offset].u_p.data = data;
7367836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
737*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_add_bytestream exit");
7387836SJohn.Forte@Sun.COM #endif
7397836SJohn.Forte@Sun.COM }
7407836SJohn.Forte@Sun.COM 
7417836SJohn.Forte@Sun.COM /*
7427836SJohn.Forte@Sun.COM  *	Asynchronously output unistat info and possibly bytestreams to
7437836SJohn.Forte@Sun.COM  *	userspace. The bytestream mechanism must have been initialized.
7447836SJohn.Forte@Sun.COM  *	@param kstatus  The status info pointer
7457836SJohn.Forte@Sun.COM  *	@return SPCS_S_OK for normal completion, SPCS_S_ERROR otherwise
7467836SJohn.Forte@Sun.COM  *	This is a prototype. Specification TBD. Not in the 10/22/98 unistat
7477836SJohn.Forte@Sun.COM  *	commitment
7487836SJohn.Forte@Sun.COM  */
7497836SJohn.Forte@Sun.COM 
7507836SJohn.Forte@Sun.COM int
spcs_s_asynch_status(spcs_s_info_t kstatus)7517836SJohn.Forte@Sun.COM spcs_s_asynch_status(spcs_s_info_t kstatus)
7527836SJohn.Forte@Sun.COM {
7537836SJohn.Forte@Sun.COM 	spcs_s_pinfo_t *p;
7547836SJohn.Forte@Sun.COM 	int i, s, b, suppcount;
7557836SJohn.Forte@Sun.COM 	uchar_t *bp;
7567836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
757*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_asynch_status entry");
7587836SJohn.Forte@Sun.COM #endif
7597836SJohn.Forte@Sun.COM 	p = (spcs_s_pinfo_t *)kstatus;
7607836SJohn.Forte@Sun.COM 
7617836SJohn.Forte@Sun.COM 	/*
7627836SJohn.Forte@Sun.COM 	 * Any real code would have to go through and process the
7637836SJohn.Forte@Sun.COM 	 * address/length pairs in the tdata array. The lengths would be
7647836SJohn.Forte@Sun.COM 	 * valid but the addresses would be meaningless. Instead, for a
7657836SJohn.Forte@Sun.COM 	 * stream transport mechanism the bytestream(s) would follow the
7667836SJohn.Forte@Sun.COM 	 * spcs_s_pinfo_t structure. So after the last call to
7677836SJohn.Forte@Sun.COM 	 * spcs_s_add_bytestream things the spcs_pinfo_t would look like this:
7687836SJohn.Forte@Sun.COM 	 * |-------------|
7697836SJohn.Forte@Sun.COM 	 * | preamble	 |
7707836SJohn.Forte@Sun.COM 	 * |-------------|
7717836SJohn.Forte@Sun.COM 	 * | idata	 |
7727836SJohn.Forte@Sun.COM 	 * |(sup offset) |-----------------|
7737836SJohn.Forte@Sun.COM 	 * |(sup offset) |--|		   | bytestream reference (index)
7747836SJohn.Forte@Sun.COM 	 * |-------------|  | string	   |
7757836SJohn.Forte@Sun.COM 	 * | sdata	 |  | ref (offset) |
7767836SJohn.Forte@Sun.COM 	 * | (strings)   |<-|		   |
7777836SJohn.Forte@Sun.COM 	 * |-------------|		   |
7787836SJohn.Forte@Sun.COM 	 * | tdata	 |		   |
7797836SJohn.Forte@Sun.COM 	 * |		 |<----------------|
7807836SJohn.Forte@Sun.COM 	 * | (length)    |
7817836SJohn.Forte@Sun.COM 	 * | (address)   |-------------------->byte data "out there somewhere"
7827836SJohn.Forte@Sun.COM 	 * |-------------|
7837836SJohn.Forte@Sun.COM 	 *
7847836SJohn.Forte@Sun.COM 	 * After processing in this function the data headed for a pipe or
7857836SJohn.Forte@Sun.COM 	 * other sequention stream would look like this:
7867836SJohn.Forte@Sun.COM 	 *
7877836SJohn.Forte@Sun.COM 	 * |-------------|
7887836SJohn.Forte@Sun.COM 	 * | preamble    |
7897836SJohn.Forte@Sun.COM 	 * |-------------|
7907836SJohn.Forte@Sun.COM 	 * | idata	 |
7917836SJohn.Forte@Sun.COM 	 * |		 |-----------------|
7927836SJohn.Forte@Sun.COM 	 * |		 |--|		   | bytestream reference (index)
7937836SJohn.Forte@Sun.COM 	 * |-------------|  | string	   |
7947836SJohn.Forte@Sun.COM 	 * | sdata	 |  | ref (offset) |
7957836SJohn.Forte@Sun.COM 	 * | (strings)	 |<-|		   |
7967836SJohn.Forte@Sun.COM 	 * |-------------|		   |
7977836SJohn.Forte@Sun.COM 	 * | tdata	 |		   |
7987836SJohn.Forte@Sun.COM 	 * |		 |<----------------|
7997836SJohn.Forte@Sun.COM 	 * | (length)    |
8007836SJohn.Forte@Sun.COM 	 * | (null addr) |
8017836SJohn.Forte@Sun.COM 	 * |-------------|
8027836SJohn.Forte@Sun.COM 	 * |first	 |
8037836SJohn.Forte@Sun.COM 	 * |bytestream	 |
8047836SJohn.Forte@Sun.COM 	 * |group	 |
8057836SJohn.Forte@Sun.COM 	 * |-------------|
8067836SJohn.Forte@Sun.COM 	 * |second	 |
8077836SJohn.Forte@Sun.COM 	 * |bytestream   |
8087836SJohn.Forte@Sun.COM 	 * |group	 |
8097836SJohn.Forte@Sun.COM 	 * |-------------|
8107836SJohn.Forte@Sun.COM 	 * | . . .	 |
8117836SJohn.Forte@Sun.COM 	 * |-------------|
8127836SJohn.Forte@Sun.COM 	 *
8137836SJohn.Forte@Sun.COM 	 * For the prototype we just dump the stuff out so we can see the
8147836SJohn.Forte@Sun.COM 	 * functions work.
8157836SJohn.Forte@Sun.COM 	 */
8167836SJohn.Forte@Sun.COM 
8177836SJohn.Forte@Sun.COM 	if (! bytestream_transport_initialized) {
8187836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
819*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_asynch_status exit 1");
8207836SJohn.Forte@Sun.COM #endif
8217836SJohn.Forte@Sun.COM 		return (SPCS_S_ERROR);
8227836SJohn.Forte@Sun.COM 	}
8237836SJohn.Forte@Sun.COM 
824*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SPCS Unistat Asynchronous Status Dump");
825*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!This is a test fixture waiting for a pipe or");
826*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!shared memory");
8277836SJohn.Forte@Sun.COM 
8287836SJohn.Forte@Sun.COM 	/*
8297836SJohn.Forte@Sun.COM 	 * I'd like nothing more than to code up a really cool pipe or mmap'd
8307836SJohn.Forte@Sun.COM 	 * shared memory scheme to shovel this stuff up to a daemon that feeds
8317836SJohn.Forte@Sun.COM 	 * Java events out to listener threads belonging to both management
8327836SJohn.Forte@Sun.COM 	 * software, coresw product code and developer code. As it is I just
8337836SJohn.Forte@Sun.COM 	 * have time to spew stuff out via cmn_err. Have to make believe this
8347836SJohn.Forte@Sun.COM 	 * is an alternative to cmn_err and not just another dang client!
8357836SJohn.Forte@Sun.COM 	 */
8367836SJohn.Forte@Sun.COM 
8377836SJohn.Forte@Sun.COM 	i = 0;
8387836SJohn.Forte@Sun.COM 
8397836SJohn.Forte@Sun.COM 	while (i < p->icount) {
8407836SJohn.Forte@Sun.COM 
8417836SJohn.Forte@Sun.COM 		/*
8427836SJohn.Forte@Sun.COM 		 * can't access the status text or anything else proper and
8437836SJohn.Forte@Sun.COM 		 * pretty from here in the kernel, have to just dump it. Put
8447836SJohn.Forte@Sun.COM 		 * the status codes out as decimal to make them look as weird
8457836SJohn.Forte@Sun.COM 		 * as possible so we see that the point of this is not for
8467836SJohn.Forte@Sun.COM 		 * anybody to actually pay attention to them but to use this
8477836SJohn.Forte@Sun.COM 		 * as a means of testing the rest of the prototype and
8487836SJohn.Forte@Sun.COM 		 * suggesting potental functionality. We also put the oldest
8497836SJohn.Forte@Sun.COM 		 * stuff out first, backwards from ioctl status. That's
8507836SJohn.Forte@Sun.COM 		 * because there are only minutes to implement this and the
8517836SJohn.Forte@Sun.COM 		 * point is to see the potential, etc.
8527836SJohn.Forte@Sun.COM 		 */
8537836SJohn.Forte@Sun.COM 
8547836SJohn.Forte@Sun.COM 		suppcount = p->idata[i].f.sup_count;
8557836SJohn.Forte@Sun.COM 
856*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!Status item %d value %x supplements %d",
857*9093SRamana.Srikanth@Sun.COM 		    i, p->idata[i].s, suppcount);
8587836SJohn.Forte@Sun.COM 		i++;
8597836SJohn.Forte@Sun.COM 
8607836SJohn.Forte@Sun.COM 		for (s = 0; s < suppcount; s++) {
8617836SJohn.Forte@Sun.COM 			if (p->idata[i+s].su.type == SU_STRING)
8627836SJohn.Forte@Sun.COM 				cmn_err(CE_NOTE,
863*9093SRamana.Srikanth@Sun.COM 				    "!Supplement %d string value: %s", s,
864*9093SRamana.Srikanth@Sun.COM 				    (char *)(p->sdata +
865*9093SRamana.Srikanth@Sun.COM 				    p->idata[i+s].su.offset));
8667836SJohn.Forte@Sun.COM 			else {
8677836SJohn.Forte@Sun.COM 				cmn_err(CE_NOTE,
868*9093SRamana.Srikanth@Sun.COM 				    "!Supplement %d bytestream dump:", s);
869*9093SRamana.Srikanth@Sun.COM 				cmn_err(CE_NOTE, "!offset data");
8707836SJohn.Forte@Sun.COM 				bp = p->tdata[p->idata[i+s].su.offset].u_p.data;
8717836SJohn.Forte@Sun.COM 				/* The SunSoft mandated 8 character tabstops */
8727836SJohn.Forte@Sun.COM 				/* really BITE MY BUTT */
8737836SJohn.Forte@Sun.COM 				for (b = 0;
8747836SJohn.Forte@Sun.COM 				    b < p->tdata[p->idata[i+s].su.offset].size;
8757836SJohn.Forte@Sun.COM 				    b++)
876*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE, "!%6d   %2x",
877*9093SRamana.Srikanth@Sun.COM 					    b, *bp++);
8787836SJohn.Forte@Sun.COM 			}
8797836SJohn.Forte@Sun.COM 		}
8807836SJohn.Forte@Sun.COM 
8817836SJohn.Forte@Sun.COM 		i += suppcount;
8827836SJohn.Forte@Sun.COM 	}
8837836SJohn.Forte@Sun.COM 
8847836SJohn.Forte@Sun.COM #ifdef UNISTAT_TRACE
885*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!spcs_s_asynch_status exit 2");
8867836SJohn.Forte@Sun.COM #endif
8877836SJohn.Forte@Sun.COM 	return (SPCS_S_OK);
8887836SJohn.Forte@Sun.COM }
889