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