xref: /onnv-gate/usr/src/lib/cfgadm_plugins/sbd/common/ap_sbd.c (revision 12004:93f274d4a367)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*12004Sjiang.liu@intel.com  * Common Development and Distribution License (the "License").
6*12004Sjiang.liu@intel.com  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12004Sjiang.liu@intel.com  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <ctype.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <libdevinfo.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <libintl.h>
350Sstevel@tonic-gate #define	CFGA_PLUGIN_LIB
360Sstevel@tonic-gate #include <config_admin.h>
370Sstevel@tonic-gate #include "ap.h"
380Sstevel@tonic-gate #include <sys/obpdefs.h>
390Sstevel@tonic-gate #include <sys/processor.h>
400Sstevel@tonic-gate #include <sys/stat.h>
410Sstevel@tonic-gate #include <sys/sbd_ioctl.h>
420Sstevel@tonic-gate #include <sys/int_fmtio.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static cfga_err_t
ap_getncm(apd_t * a,sbd_comp_type_t type,int * ncm)450Sstevel@tonic-gate ap_getncm(apd_t *a, sbd_comp_type_t type, int *ncm)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
480Sstevel@tonic-gate 	sbd_getncm_cmd_t *cp;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	if (a->fd == -1 || a->ctl == NULL)
510Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
540Sstevel@tonic-gate 	ctl->ic_type = type;
550Sstevel@tonic-gate 	ctl->ic_name[0] = '\0';
560Sstevel@tonic-gate 	ctl->ic_unit = 0;
570Sstevel@tonic-gate 	ctl->i_len = 0;
580Sstevel@tonic-gate 	ctl->i_opts = NULL;
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	DBG("ioctl(%d SBD_CMD_GETNCM, 0x%p)\n", a->fd, (void *)ctl);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	if (ioctl(a->fd, SBD_CMD_GETNCM, ctl) == -1) {
630Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_GETNCM);
640Sstevel@tonic-gate 		return (CFGA_ERROR);
650Sstevel@tonic-gate 	}
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	cp = &ctl->i_cmd.cmd_getncm;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	DBG("ncm(%d)=%d\n", type, cp->g_ncm);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	if (ncm)
720Sstevel@tonic-gate 		*ncm = cp->g_ncm;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	return (CFGA_OK);
750Sstevel@tonic-gate }
760Sstevel@tonic-gate 
770Sstevel@tonic-gate cfga_err_t
ap_stat(apd_t * a,int all)780Sstevel@tonic-gate ap_stat(apd_t *a, int all)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate 	int fd;
810Sstevel@tonic-gate 	int ncm;
820Sstevel@tonic-gate 	int select;
830Sstevel@tonic-gate 	int stsize;
840Sstevel@tonic-gate 	int oflag;
850Sstevel@tonic-gate 	sbd_stat_cmd_t *sc;
860Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
870Sstevel@tonic-gate 	cfga_err_t rc;
880Sstevel@tonic-gate 	sbd_stat_t *new_stat;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	rc = CFGA_LIB_ERROR;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	DBG("ap_stat(%s)\n", a->path);
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	/* Open the file descriptor if not already open */
950Sstevel@tonic-gate 	if (a->fd == -1) {
960Sstevel@tonic-gate 		DBG("open(%s)\n", a->path);
970Sstevel@tonic-gate 		if (a->statonly != 0)
980Sstevel@tonic-gate 			oflag = O_RDONLY;
990Sstevel@tonic-gate 		else
1000Sstevel@tonic-gate 			oflag = O_RDWR;
1010Sstevel@tonic-gate 		if ((fd = open(a->path, oflag, 0)) == -1) {
1020Sstevel@tonic-gate 			ap_err(a, ERR_AP_INVAL);
1030Sstevel@tonic-gate 			return (rc);
1040Sstevel@tonic-gate 		}
1050Sstevel@tonic-gate 		a->fd = fd;
1060Sstevel@tonic-gate 	} else {
1070Sstevel@tonic-gate 		fd = a->fd;
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	if (a->ctl == NULL && (a->ctl = calloc(1, sizeof (*ctl))) == NULL) {
1110Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1120Sstevel@tonic-gate 		return (rc);
1130Sstevel@tonic-gate 	}
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	if (a->tgt == AP_BOARD) {
1160Sstevel@tonic-gate 		/*
1170Sstevel@tonic-gate 		 * The status target is the board. If we need to
1180Sstevel@tonic-gate 		 * return component data (to support the -a option),
1190Sstevel@tonic-gate 		 * get the number of components on the board.
1200Sstevel@tonic-gate 		 */
1210Sstevel@tonic-gate 		select = 0;
1220Sstevel@tonic-gate 		if (all) {
1230Sstevel@tonic-gate 			cfga_err_t r;
1240Sstevel@tonic-gate 			r = ap_getncm(a, SBD_COMP_NONE, &ncm);
1250Sstevel@tonic-gate 			if (r != CFGA_OK) {
1260Sstevel@tonic-gate 				return (r);
1270Sstevel@tonic-gate 			}
1280Sstevel@tonic-gate 		} else {
1290Sstevel@tonic-gate 			ncm = 0;
1300Sstevel@tonic-gate 		}
1310Sstevel@tonic-gate 	} else {
1320Sstevel@tonic-gate 		select = 1;
1330Sstevel@tonic-gate 		ncm = 1;
1340Sstevel@tonic-gate 	}
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	DBG("ncm=%d\n", ncm);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	a->ncm = ncm;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	/*
1410Sstevel@tonic-gate 	 * The status structure contains space for one component;
1420Sstevel@tonic-gate 	 * add the space for the other components if necessary.
1430Sstevel@tonic-gate 	 */
1440Sstevel@tonic-gate 	stsize = sizeof (sbd_stat_t);
1450Sstevel@tonic-gate 	if (ncm > 1)
1460Sstevel@tonic-gate 		stsize += ((ncm - 1) * sizeof (sbd_dev_stat_t));
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	if ((new_stat = realloc(a->stat, stsize)) == NULL) {
1490Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1500Sstevel@tonic-gate 		return (rc);
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	a->stat = new_stat;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
1570Sstevel@tonic-gate 	ctl->i_len = 0;
1580Sstevel@tonic-gate 	ctl->i_opts = NULL;
1590Sstevel@tonic-gate 	ctl->ic_type = SBD_COMP_NONE;
1600Sstevel@tonic-gate 	if (all)
1610Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_ALLCMP;
1620Sstevel@tonic-gate 	sc = &ctl->i_cmd.cmd_stat;
1630Sstevel@tonic-gate 	sc->s_statp = (caddr_t)a->stat;
1640Sstevel@tonic-gate 	sc->s_nbytes = stsize;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	if (select) {
1670Sstevel@tonic-gate 		/*
1680Sstevel@tonic-gate 		 * The target is a specific component.  Pass its
1690Sstevel@tonic-gate 		 * name and unit number to the driver.  Set its
1700Sstevel@tonic-gate 		 * type to UNKNOWN since the plugin does not know
1710Sstevel@tonic-gate 		 * the type of the component specified by the user.
1720Sstevel@tonic-gate 		 */
1730Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_UNKNOWN;
1740Sstevel@tonic-gate 		ctl->ic_unit = a->cnum;
175*12004Sjiang.liu@intel.com 		(void) strcpy(ctl->ic_name, a->cname);
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	DBG("ioctl(%d SBD_CMD_STATUS, sc=0x%p sz=%d flags=%d",
179*12004Sjiang.liu@intel.com 	    fd, (void *)sc->s_statp, sc->s_nbytes, ctl->i_flags);
1800Sstevel@tonic-gate 	if (select)
1810Sstevel@tonic-gate 		DBG(" cname=<%s> cnum=%d", a->cname, a->cnum);
1820Sstevel@tonic-gate 	DBG(")\n");
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if (ioctl(fd, SBD_CMD_STATUS, ctl) == -1) {
1850Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1860Sstevel@tonic-gate 		rc = CFGA_ERROR;
1870Sstevel@tonic-gate 	} else
1880Sstevel@tonic-gate 		rc = CFGA_OK;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	DBG("ap_stat()=%d\n", rc);
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	return (rc);
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate /*
1960Sstevel@tonic-gate  * Convert a component to a target type.
1970Sstevel@tonic-gate  */
1980Sstevel@tonic-gate static ap_target_t
ap_cm_tgt(sbd_comp_type_t type)1990Sstevel@tonic-gate ap_cm_tgt(sbd_comp_type_t type)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	ap_target_t c;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	switch (type) {
2040Sstevel@tonic-gate 	case SBD_COMP_CPU:
2050Sstevel@tonic-gate 		c = AP_CPU;
2060Sstevel@tonic-gate 		break;
2070Sstevel@tonic-gate 	case SBD_COMP_MEM:
2080Sstevel@tonic-gate 		c = AP_MEM;
2090Sstevel@tonic-gate 		break;
2100Sstevel@tonic-gate 	case SBD_COMP_IO:
2110Sstevel@tonic-gate 		c = AP_IO;
2120Sstevel@tonic-gate 		break;
2130Sstevel@tonic-gate 	case SBD_COMP_CMP:
2140Sstevel@tonic-gate 		c = AP_CMP;
2150Sstevel@tonic-gate 		break;
2160Sstevel@tonic-gate 	default:
2170Sstevel@tonic-gate 		c = AP_NONE;
2180Sstevel@tonic-gate 		break;
2190Sstevel@tonic-gate 	}
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	return (c);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate cfga_err_t
apd_init(apd_t * a,int all)2250Sstevel@tonic-gate apd_init(apd_t *a, int all)
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate 	int i;
2280Sstevel@tonic-gate 	char *cn, *dn;
2290Sstevel@tonic-gate 	sbd_stat_t *st;
2300Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
2310Sstevel@tonic-gate 	cfga_err_t rc;
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	/*
2340Sstevel@tonic-gate 	 * Ideally, for board operations (other than status) it is not
2350Sstevel@tonic-gate 	 * necessary to issue the STATUS ioctl.  The call however allows a
2360Sstevel@tonic-gate 	 * final sanity check to ensure that the board number returned
2370Sstevel@tonic-gate 	 * by the driver matches the plugin's notion of the board number
2380Sstevel@tonic-gate 	 * as extracted from the ap_id.  If this check is not desirable,
2390Sstevel@tonic-gate 	 * we can change the code to issue the status call only when
2400Sstevel@tonic-gate 	 * necessary.  Note that for component operations, we need to do
2410Sstevel@tonic-gate 	 * the STATUS in order to figure out the component type and
2420Sstevel@tonic-gate 	 * validate the command/options accordingly. XXX
2430Sstevel@tonic-gate 	 */
2440Sstevel@tonic-gate 	if ((rc = ap_stat(a, all)) != CFGA_OK) {
2450Sstevel@tonic-gate 		ap_err(a, ERR_AP_INVAL);
2460Sstevel@tonic-gate 		return (rc);
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	/*
2520Sstevel@tonic-gate 	 * Set the component count to the returned stat count.
2530Sstevel@tonic-gate 	 */
2540Sstevel@tonic-gate 	if (a->ncm > st->s_nstat) {
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 		DBG("ncm=%d nstat=%d (truncated)\n", a->ncm, st->s_nstat);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 		a->ncm = st->s_nstat;
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	if (a->tgt == AP_BOARD) {
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 		DBG("tgt=%d\n", a->tgt);
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 		/*
2660Sstevel@tonic-gate 		 * Initialize the RCM module here so that it can record
2670Sstevel@tonic-gate 		 * the initial state of the capacity information.
2680Sstevel@tonic-gate 		 */
2690Sstevel@tonic-gate 		rc = ap_rcm_init(a);
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		return (rc);
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	a->tgt = AP_NONE;
2750Sstevel@tonic-gate 	cn = a->cname;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	DBG("cname=<%s> cunit=<%d>\n", a->cname, a->cnum);
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	for (dst = st->s_stat, i = 0; i < st->s_nstat; i++, dst++) {
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		DBG("ds_name,ds_unit,ds_type=<%s,%d,%d> ",
282*12004Sjiang.liu@intel.com 		    dst->ds_name, dst->ds_unit, dst->ds_type);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 		if (dst->ds_unit != a->cnum)
2850Sstevel@tonic-gate 			continue;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		/*
2880Sstevel@tonic-gate 		 * Consider the names matched if they are either
2890Sstevel@tonic-gate 		 * both absent or the same. It is conceivable that
2900Sstevel@tonic-gate 		 * a NULL component name be considered valid
2910Sstevel@tonic-gate 		 * by the driver.
2920Sstevel@tonic-gate 		 */
2930Sstevel@tonic-gate 		dn = dst->ds_name;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		if ((dn == NULL && cn == NULL) ||
2960Sstevel@tonic-gate 		    (dn != NULL && cn != NULL && strcmp(dn, cn) == 0)) {
2970Sstevel@tonic-gate 			a->tgt = ap_cm_tgt(dst->ds_type);
2980Sstevel@tonic-gate 			a->cmstat = (void *)dst;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 			DBG("found ");
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 			break;
3030Sstevel@tonic-gate 		}
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	DBG("tgt=%d\n", a->tgt);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (a->tgt == AP_NONE) {
3090Sstevel@tonic-gate 		ap_err(a, ERR_CM_INVAL, a->cid);
3100Sstevel@tonic-gate 		return (CFGA_INVAL);
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	/*
3140Sstevel@tonic-gate 	 * Initialize the RCM module here so that it can record
3150Sstevel@tonic-gate 	 * the initial state of the capacity information.
3160Sstevel@tonic-gate 	 */
3170Sstevel@tonic-gate 	rc = ap_rcm_init(a);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	return (rc);
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate void
apd_free(apd_t * a)3230Sstevel@tonic-gate apd_free(apd_t *a)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	if (a == NULL)
3260Sstevel@tonic-gate 		return;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	ap_rcm_fini(a);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	if (a->fd != -1)
331*12004Sjiang.liu@intel.com 		(void) close(a->fd);
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	s_free(a->options);
3340Sstevel@tonic-gate 	s_free(a->path);
3350Sstevel@tonic-gate 	s_free(a->drv);
3360Sstevel@tonic-gate 	s_free(a->target);
3370Sstevel@tonic-gate 	s_free(a->cname);
3380Sstevel@tonic-gate 	s_free(a->ctl);
3390Sstevel@tonic-gate 	s_free(a->stat);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	free(a);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate apd_t *
apd_alloc(const char * ap_id,cfga_flags_t flags,char ** errstring,struct cfga_msg * msgp,struct cfga_confirm * confp)3450Sstevel@tonic-gate apd_alloc(const char *ap_id, cfga_flags_t flags, char **errstring,
3460Sstevel@tonic-gate 	struct cfga_msg *msgp, struct cfga_confirm *confp)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate 	apd_t *a;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	if ((a = calloc(1, sizeof (*a))) == NULL)
3510Sstevel@tonic-gate 		return (NULL);
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	if (errstring != NULL)
3540Sstevel@tonic-gate 		*errstring = NULL;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	a->fd = -1;
3570Sstevel@tonic-gate 	a->errstring = errstring;
3580Sstevel@tonic-gate 	a->msgp = msgp;
3590Sstevel@tonic-gate 	a->confp = confp;
3600Sstevel@tonic-gate 	a->class = "sbd";
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	if (flags & CFGA_FLAG_LIST_ALL)
3630Sstevel@tonic-gate 		ap_setopt(a, OPT_LIST_ALL);
3640Sstevel@tonic-gate 	if (flags & CFGA_FLAG_FORCE)
3650Sstevel@tonic-gate 		ap_setopt(a, OPT_FORCE);
3660Sstevel@tonic-gate 	if (flags & CFGA_FLAG_VERBOSE)
3670Sstevel@tonic-gate 		ap_setopt(a, OPT_VERBOSE);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	if (ap_id == NULL || ap_parse(a, ap_id) == 0)
3700Sstevel@tonic-gate 		return (a);
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	apd_free(a);
3730Sstevel@tonic-gate 	return (NULL);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate  * The type field is defined to be parsable by cfgadm(1M): It
3780Sstevel@tonic-gate  * must not contain white space characters. This function
3790Sstevel@tonic-gate  * converts white space to underscore.
3800Sstevel@tonic-gate  */
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate static void
parsable_strncpy(char * op,const char * ip,size_t n)3830Sstevel@tonic-gate parsable_strncpy(char *op, const char *ip, size_t n)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	char c;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	while (n-- > 0) {
3880Sstevel@tonic-gate 		c = *ip++;
3890Sstevel@tonic-gate 		if (isspace(c))
3900Sstevel@tonic-gate 			c = '_';
3910Sstevel@tonic-gate 		*op++ = c;
3920Sstevel@tonic-gate 		if (c == '\0')
3930Sstevel@tonic-gate 			break;
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate void
ap_init(apd_t * a,cfga_list_data_t * ap)3980Sstevel@tonic-gate ap_init(apd_t *a, cfga_list_data_t *ap)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate 	sbd_stat_t *st;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	DBG("ap_init bd=%d rs=%d os=%d type=<%s>\n",
405*12004Sjiang.liu@intel.com 	    a->bnum, st->s_rstate, st->s_ostate, st->s_type);
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	parsable_strncpy(ap->ap_type, st->s_type, sizeof (ap->ap_type));
4080Sstevel@tonic-gate 	ap->ap_r_state = (cfga_stat_t)st->s_rstate;
4090Sstevel@tonic-gate 	ap->ap_o_state = (cfga_stat_t)st->s_ostate;
4100Sstevel@tonic-gate 	ap->ap_cond = (cfga_cond_t)st->s_cond;
4110Sstevel@tonic-gate 	ap->ap_busy = (cfga_busy_t)st->s_busy;
4120Sstevel@tonic-gate 	ap->ap_status_time = st->s_time;
4130Sstevel@tonic-gate 	ap_info(a, ap->ap_info, AP_BOARD);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate typedef struct {
4170Sstevel@tonic-gate 	int cmd;
4180Sstevel@tonic-gate 	int ioc;
4190Sstevel@tonic-gate } ap_ioc_t;
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate static ap_ioc_t
4220Sstevel@tonic-gate ap_iocs[] =  {
4230Sstevel@tonic-gate 	{CMD_ASSIGN,	  SBD_CMD_ASSIGN	},
4240Sstevel@tonic-gate 	{CMD_POWERON,	  SBD_CMD_POWERON	},
4250Sstevel@tonic-gate 	{CMD_TEST,	  SBD_CMD_TEST		},
4260Sstevel@tonic-gate 	{CMD_CONNECT,	  SBD_CMD_CONNECT	},
4270Sstevel@tonic-gate 	{CMD_CONFIGURE,	  SBD_CMD_CONFIGURE	},
4280Sstevel@tonic-gate 	{CMD_UNCONFIGURE, SBD_CMD_UNCONFIGURE	},
4290Sstevel@tonic-gate 	{CMD_DISCONNECT,  SBD_CMD_DISCONNECT	},
4300Sstevel@tonic-gate 	{CMD_POWEROFF,	  SBD_CMD_POWEROFF	},
4310Sstevel@tonic-gate 	{CMD_STATUS,	  SBD_CMD_STATUS	},
4320Sstevel@tonic-gate 	{CMD_GETNCM,	  SBD_CMD_GETNCM	},
4330Sstevel@tonic-gate 	{CMD_UNASSIGN,	  SBD_CMD_UNASSIGN	},
4340Sstevel@tonic-gate 	{CMD_PASSTHRU,	  SBD_CMD_PASSTHRU	},
4350Sstevel@tonic-gate 	{CMD_NONE,	  0			}
4360Sstevel@tonic-gate };
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate static int
ap_ioc(int cmd)4390Sstevel@tonic-gate ap_ioc(int cmd)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate 	ap_ioc_t *acp;
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	DBG("ap_ioc(%d)\n", cmd);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	for (acp = ap_iocs; acp->cmd != CMD_NONE; acp++)
4460Sstevel@tonic-gate 		if (acp->cmd == cmd)
4470Sstevel@tonic-gate 			break;
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	DBG("ap_ioc(%d)=0x%x\n", cmd, acp->ioc);
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	return (acp->ioc);
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate cfga_err_t
ap_suspend_query(apd_t * a,int cmd,int * check)4550Sstevel@tonic-gate ap_suspend_query(apd_t *a, int cmd, int *check)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate 	int ioc;
4580Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	/*
4610Sstevel@tonic-gate 	 * See if the a quiesce operation is required for
4620Sstevel@tonic-gate 	 * this command for any of the components.  If the
4630Sstevel@tonic-gate 	 * command does not map to an ioctl, then there is
4640Sstevel@tonic-gate 	 * nothing to do.
4650Sstevel@tonic-gate 	 */
4660Sstevel@tonic-gate 	if ((ioc = ap_ioc(cmd)) == 0)
4670Sstevel@tonic-gate 		return (CFGA_OK);
4680Sstevel@tonic-gate 	else if (a->tgt == AP_BOARD) {
4690Sstevel@tonic-gate 		int i;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 		dst = ((sbd_stat_t *)a->stat)->s_stat;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 		/*
4740Sstevel@tonic-gate 		 * See if any component requires a
4750Sstevel@tonic-gate 		 * OS suspension for this command.
4760Sstevel@tonic-gate 		 */
4770Sstevel@tonic-gate 		for (i = 0; i < a->ncm; i++, dst++)
4780Sstevel@tonic-gate 			if (SBD_CHECK_SUSPEND(ioc, dst->ds_suspend))
4790Sstevel@tonic-gate 				(*check)++;
4800Sstevel@tonic-gate 	} else {
4810Sstevel@tonic-gate 		dst = (sbd_dev_stat_t *)a->cmstat;
4820Sstevel@tonic-gate 		if (SBD_CHECK_SUSPEND(ioc, dst->ds_suspend))
4830Sstevel@tonic-gate 				(*check)++;
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	return (CFGA_OK);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate cfga_err_t
ap_platopts_check(apd_t * a,int first,int last)4900Sstevel@tonic-gate ap_platopts_check(apd_t *a, int first, int last)
4910Sstevel@tonic-gate {
4920Sstevel@tonic-gate 	int c;
4930Sstevel@tonic-gate 	uint_t platopts;
4940Sstevel@tonic-gate 	sbd_stat_t *stat;
4950Sstevel@tonic-gate 	ap_opts_t *opts;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	opts = &a->opts;
4980Sstevel@tonic-gate 	stat = (sbd_stat_t *)a->stat;
4990Sstevel@tonic-gate 	platopts = stat->s_platopts;
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/*
5030Sstevel@tonic-gate 	 * If there are no platform options set then there
5040Sstevel@tonic-gate 	 * is no need to check this operation
5050Sstevel@tonic-gate 	 */
5060Sstevel@tonic-gate 	if (opts->platform == NULL)
5070Sstevel@tonic-gate 		return (CFGA_OK);
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	/*
5100Sstevel@tonic-gate 	 * Check if any of the steps in the sequence
5110Sstevel@tonic-gate 	 * allows for a platform option
5120Sstevel@tonic-gate 	 */
5130Sstevel@tonic-gate 	for (c = first; c <= last; c++)
5140Sstevel@tonic-gate 		/*
5150Sstevel@tonic-gate 		 * If the platopt is set it means that the platform does not
5160Sstevel@tonic-gate 		 * support options for this cmd
5170Sstevel@tonic-gate 		 */
5180Sstevel@tonic-gate 		if (SBD_CHECK_PLATOPTS(ap_ioc(c), platopts) == 0) {
5190Sstevel@tonic-gate 			return (CFGA_OK);
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	ap_err(a, ERR_OPT_INVAL, opts->platform);
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	return (CFGA_INVAL);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate cfga_err_t
ap_ioctl(apd_t * a,int cmd)5280Sstevel@tonic-gate ap_ioctl(apd_t *a, int cmd)
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate 	int ioc;
5310Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (a->ctl == NULL && (a->ctl = calloc(1, sizeof (*ctl))) == NULL) {
5340Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5350Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	ap_msg(a, MSG_ISSUE, cmd, a->target);
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
5410Sstevel@tonic-gate 	ctl->i_flags = 0;
5420Sstevel@tonic-gate 	ctl->i_len = 0;
5430Sstevel@tonic-gate 	ctl->i_opts = NULL;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	if (ap_getopt(a, OPT_FORCE))
5460Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_FORCE;
5470Sstevel@tonic-gate 	if (ap_getopt(a, OPT_SUSPEND_OK))
5480Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_QUIESCE_OKAY;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	if (a->tgt == AP_BOARD)
5510Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_NONE;
5520Sstevel@tonic-gate 	else {
5530Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_UNKNOWN;
5540Sstevel@tonic-gate 		ctl->ic_unit = a->cnum;
555*12004Sjiang.liu@intel.com 		(void) strcpy(ctl->ic_name, a->cname);
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	if (!(ioc = ap_ioc(cmd))) {
5590Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5600Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
5610Sstevel@tonic-gate 	}
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	/*
5640Sstevel@tonic-gate 	 * If this is a passthru command, pass all of its
5650Sstevel@tonic-gate 	 * options; otherwise, pass all options after the
5660Sstevel@tonic-gate 	 * platform keyword.
5670Sstevel@tonic-gate 	 */
5680Sstevel@tonic-gate 	if (cmd == CMD_PASSTHRU)
5690Sstevel@tonic-gate 		ctl->i_opts = a->options;
5700Sstevel@tonic-gate 	else {
5710Sstevel@tonic-gate 		/*
5720Sstevel@tonic-gate 		 * Only pass the platform option to the cmds that the platform
5730Sstevel@tonic-gate 		 * has specified as ok
5740Sstevel@tonic-gate 		 */
5750Sstevel@tonic-gate 		sbd_stat_t *stat;
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 		stat = (sbd_stat_t *)a->stat;
5780Sstevel@tonic-gate 		if (SBD_CHECK_PLATOPTS(ioc, stat->s_platopts) == 0)
5790Sstevel@tonic-gate 			ctl->i_opts = a->opts.platform;
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	if (ctl->i_opts != NULL)
5830Sstevel@tonic-gate 		ctl->i_len = strlen(ctl->i_opts) + 1;
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	DBG("i_opts=%s\n", ctl->i_opts ? ctl->i_opts : "NULL");
5860Sstevel@tonic-gate 	DBG("i_flags=0x%x\n", ctl->i_flags);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	if (ap_getopt(a, OPT_SIM)) {
5890Sstevel@tonic-gate 		ap_msg(a, MSG_DONE, cmd, a->target);
5900Sstevel@tonic-gate 		return (CFGA_OK);
5910Sstevel@tonic-gate 	}
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	if (ioctl(a->fd, ioc, ctl) == -1) {
5940Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5950Sstevel@tonic-gate 		return (CFGA_ERROR);
5960Sstevel@tonic-gate 	}
5970Sstevel@tonic-gate 	ap_msg(a, MSG_DONE, cmd, a->target);
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	return (CFGA_OK);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate  * Return the error string corresponding to a given error code.
6040Sstevel@tonic-gate  * String table and error code sets are provided by sbd_etab.  This data
6050Sstevel@tonic-gate  * structure is automatically generated at compile time from the error
6060Sstevel@tonic-gate  * code and message text information in sbd_ioctl.h.
6070Sstevel@tonic-gate  */
6080Sstevel@tonic-gate static char *
mod_estr(int code)6090Sstevel@tonic-gate mod_estr(int code)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	int i;
6120Sstevel@tonic-gate 	char *s;
6130Sstevel@tonic-gate 	extern sbd_etab_t sbd_etab[];
6140Sstevel@tonic-gate 	extern int sbd_etab_len;
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	s = NULL;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	for (i = 0; i < sbd_etab_len; i++) {
6190Sstevel@tonic-gate 		sbd_etab_t *eptr = &sbd_etab[i];
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 		if ((code >= eptr->t_base) && (code <= eptr->t_bnd)) {
6220Sstevel@tonic-gate 			int index;
6230Sstevel@tonic-gate 			char **t_text;
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 			/*
6260Sstevel@tonic-gate 			 * Found it. Just extract the string
6270Sstevel@tonic-gate 			 */
6280Sstevel@tonic-gate 			index = code - eptr->t_base;
6290Sstevel@tonic-gate 			t_text = eptr->t_text;
6300Sstevel@tonic-gate 			s = strdup(t_text[index]);
6310Sstevel@tonic-gate 			break;
6320Sstevel@tonic-gate 		}
6330Sstevel@tonic-gate 	}
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	if (i == sbd_etab_len) {
6360Sstevel@tonic-gate 		char buf[32];
6370Sstevel@tonic-gate 
638*12004Sjiang.liu@intel.com 		(void) snprintf(buf, sizeof (buf), "error %d", code);
6390Sstevel@tonic-gate 		s = strdup(buf);
6400Sstevel@tonic-gate 	}
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	return (s);
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate char *
ap_sys_err(apd_t * a,char ** rp)6460Sstevel@tonic-gate ap_sys_err(apd_t *a, char **rp)
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate 	int code;
6490Sstevel@tonic-gate 	char *p;
6500Sstevel@tonic-gate 	char *rsc;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl = (sbd_ioctl_arg_t *)a->ctl;
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	/*
6550Sstevel@tonic-gate 	 * The driver sets the errno to EIO if it returns
6560Sstevel@tonic-gate 	 * more detailed error info via e_code.  In all
6570Sstevel@tonic-gate 	 * other cases, use standard error text.
6580Sstevel@tonic-gate 	 */
6590Sstevel@tonic-gate 	if (ctl == NULL || errno != EIO) {
6600Sstevel@tonic-gate 		if ((p = strerror(errno)) != NULL)
6610Sstevel@tonic-gate 			p = strdup(p);
6620Sstevel@tonic-gate 		return (p);
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	code = ctl->ie_code;
6660Sstevel@tonic-gate 	rsc = ctl->ie_rsc;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	if (code)
6690Sstevel@tonic-gate 		p = mod_estr(code);
6700Sstevel@tonic-gate 	else if ((p = strerror(errno)) != NULL)
6710Sstevel@tonic-gate 		p = strdup(p);
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 	if (*rsc != '\0' && rp != NULL)
6740Sstevel@tonic-gate 		*rp = strdup(rsc);
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	return (p);
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate /*
6800Sstevel@tonic-gate  * cfgadm -o err=plugin-err,cmd=name,code=ecode -x errtest ap_id.
6810Sstevel@tonic-gate  */
6820Sstevel@tonic-gate cfga_err_t
ap_test_err(apd_t * a,const char * options)6830Sstevel@tonic-gate ap_test_err(apd_t *a, const char *options)
6840Sstevel@tonic-gate {
6850Sstevel@tonic-gate 	int err;
6860Sstevel@tonic-gate 	int cmd;
6870Sstevel@tonic-gate 	ap_opts_t *opts;
6880Sstevel@tonic-gate 	sbd_ioctl_arg_t ctl;
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	opts = &a->opts;
6910Sstevel@tonic-gate 	err = opts->err;
6920Sstevel@tonic-gate 	cmd = CMD_DISCONNECT;
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	DBG("ap_test_err(%d %d)\n", opts->code, opts->err);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	switch (err) {
6970Sstevel@tonic-gate 	case ERR_CMD_INVAL:
6980Sstevel@tonic-gate 		ap_err(a, err, ap_cmd_name(cmd));
6990Sstevel@tonic-gate 		break;
7000Sstevel@tonic-gate 	case ERR_CMD_NOTSUPP:
7010Sstevel@tonic-gate 		ap_err(a, err, cmd);
7020Sstevel@tonic-gate 		break;
7030Sstevel@tonic-gate 	case ERR_CMD_FAIL:
7040Sstevel@tonic-gate 		errno = EIO;
7050Sstevel@tonic-gate 		ctl.i_err.e_code = opts->code;
7060Sstevel@tonic-gate 		*ctl.i_err.e_rsc = '\0';
7070Sstevel@tonic-gate 		a->ctl = &ctl;
7080Sstevel@tonic-gate 		ap_err(a, err, cmd);
7090Sstevel@tonic-gate 		a->ctl = NULL;
7100Sstevel@tonic-gate 		break;
7110Sstevel@tonic-gate 	case ERR_OPT_INVAL:
7120Sstevel@tonic-gate 		ap_err(a, err, options);
7130Sstevel@tonic-gate 		break;
7140Sstevel@tonic-gate 	case ERR_OPT_NOVAL:
7150Sstevel@tonic-gate 		ap_err(a, err, options);
7160Sstevel@tonic-gate 		break;
7170Sstevel@tonic-gate 	case ERR_AP_INVAL:
7180Sstevel@tonic-gate 		ap_err(a, err);
7190Sstevel@tonic-gate 		break;
7200Sstevel@tonic-gate 	case ERR_CM_INVAL:
7210Sstevel@tonic-gate 		ap_err(a, err, a->cid);
7220Sstevel@tonic-gate 		break;
7230Sstevel@tonic-gate 	case ERR_TRANS_INVAL:
7240Sstevel@tonic-gate 		ap_err(a, ERR_TRANS_INVAL, cmd);
7250Sstevel@tonic-gate 		break;
7260Sstevel@tonic-gate 	}
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	return (CFGA_LIB_ERROR);
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate static char *
7320Sstevel@tonic-gate ap_help_topics[] = {
7330Sstevel@tonic-gate 	"\nSbd specific commands/options:\n\n",
7340Sstevel@tonic-gate 	"\tcfgadm [-o parsable] -l ap_id\n",
7350Sstevel@tonic-gate 	"\tcfgadm [-o unassign|nopoweroff] -c disconnect ap_id\n",
7360Sstevel@tonic-gate 	"\tcfgadm -t ap_id\n",
7370Sstevel@tonic-gate 	"\tcfgadm -x assign ap_id\n",
7380Sstevel@tonic-gate 	"\tcfgadm -x unassign ap_id\n",
7390Sstevel@tonic-gate 	"\tcfgadm -x poweron ap_id\n",
7400Sstevel@tonic-gate 	"\tcfgadm -x poweroff ap_id\n",
7410Sstevel@tonic-gate 	NULL
7420Sstevel@tonic-gate };
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate /*ARGSUSED*/
7450Sstevel@tonic-gate cfga_err_t
ap_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)7460Sstevel@tonic-gate ap_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
7470Sstevel@tonic-gate {
7480Sstevel@tonic-gate 	int len;
7490Sstevel@tonic-gate 	char **p;
7500Sstevel@tonic-gate 	char *q;
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	if (msgp == NULL || msgp->message_routine == NULL)
7530Sstevel@tonic-gate 		return (CFGA_OK);
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	for (p = ap_help_topics; *p != NULL; p++) {
7560Sstevel@tonic-gate 		if ((len = strlen(*p)) == 0)
7570Sstevel@tonic-gate 			continue;
7580Sstevel@tonic-gate 		if ((q = (char *)calloc(len + 1, 1)) == NULL)
7590Sstevel@tonic-gate 			continue;
760*12004Sjiang.liu@intel.com 		(void) strcpy(q, *p);
7610Sstevel@tonic-gate 		(*msgp->message_routine)(msgp->appdata_ptr, q);
7620Sstevel@tonic-gate 		free(q);
7630Sstevel@tonic-gate 	}
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	return (CFGA_OK);
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate static char *
ap_dev_type(sbd_dev_stat_t * dst)7690Sstevel@tonic-gate ap_dev_type(sbd_dev_stat_t *dst)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate 	char *type;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	switch (dst->ds_type) {
7740Sstevel@tonic-gate 	case SBD_COMP_CPU:
7750Sstevel@tonic-gate 		type = "cpu";
7760Sstevel@tonic-gate 		break;
7770Sstevel@tonic-gate 	case SBD_COMP_MEM:
7780Sstevel@tonic-gate 		type = "memory";
7790Sstevel@tonic-gate 		break;
7800Sstevel@tonic-gate 	case SBD_COMP_IO:
7810Sstevel@tonic-gate 		type = "io";
7820Sstevel@tonic-gate 		break;
7830Sstevel@tonic-gate 	case SBD_COMP_CMP:
7840Sstevel@tonic-gate 		type = "cpu";
7850Sstevel@tonic-gate 		break;
7860Sstevel@tonic-gate 	default:
7870Sstevel@tonic-gate 		type = "other";
7880Sstevel@tonic-gate 		break;
7890Sstevel@tonic-gate 	}
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	DBG("ap_dev_type(%d)=%s\n", dst->ds_type, type);
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	return (type);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate static sbd_dev_stat_t *
ap_cm_stat(apd_t * a,int seq)7970Sstevel@tonic-gate ap_cm_stat(apd_t *a, int seq)
7980Sstevel@tonic-gate {
7990Sstevel@tonic-gate 	sbd_stat_t *st;
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 	if (seq == CM_DFLT)
8020Sstevel@tonic-gate 		return (a->cmstat);
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
8050Sstevel@tonic-gate 	return (st->s_stat + seq);
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate char *
ap_cm_devpath(apd_t * a,int seq)8090Sstevel@tonic-gate ap_cm_devpath(apd_t *a, int seq)
8100Sstevel@tonic-gate {
8110Sstevel@tonic-gate 	int len;
8120Sstevel@tonic-gate 	char *path;
8130Sstevel@tonic-gate 	char *devpath;
8140Sstevel@tonic-gate 	sbd_io_stat_t *dst;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 	/*
8180Sstevel@tonic-gate 	 * If no component sequence number is provided
8190Sstevel@tonic-gate 	 * default to the current target component.
8200Sstevel@tonic-gate 	 * Assume an io component so that we can get
8210Sstevel@tonic-gate 	 * the path if the component is indeed of type io.
8220Sstevel@tonic-gate 	 */
823*12004Sjiang.liu@intel.com 	if (seq == CM_DFLT)
8240Sstevel@tonic-gate 		dst = (sbd_io_stat_t *)a->cmstat;
8250Sstevel@tonic-gate 	else {
8260Sstevel@tonic-gate 		sbd_stat_t *st;
8270Sstevel@tonic-gate 		st = (sbd_stat_t *)a->stat;
8280Sstevel@tonic-gate 		dst = (sbd_io_stat_t *)st->s_stat + seq;
8290Sstevel@tonic-gate 	}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	if (dst->is_type != SBD_COMP_IO)
8320Sstevel@tonic-gate 		path = NULL;
8330Sstevel@tonic-gate 	else
8340Sstevel@tonic-gate 		path = dst->is_pathname;
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	if (str_valid(path)) {
8370Sstevel@tonic-gate 		len = strlen(DEVDIR) + strlen(path) + 1;
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 		if ((devpath = calloc(1, len)) == NULL)
8400Sstevel@tonic-gate 			return (NULL);
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 		(void) snprintf(devpath, len, "%s%s", DEVDIR, path);
8430Sstevel@tonic-gate 	} else
8440Sstevel@tonic-gate 		devpath = NULL;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	DBG("ap_cm_path(%d)=%s\n", seq, devpath ? devpath : "");
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 	return (devpath);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate void
ap_cm_id(apd_t * a,int seq,char * id,size_t bufsize)8520Sstevel@tonic-gate ap_cm_id(apd_t *a, int seq, char *id, size_t bufsize)
8530Sstevel@tonic-gate {
8540Sstevel@tonic-gate 	int unit;
8550Sstevel@tonic-gate 	char *name;
8560Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	unit = dst->ds_unit;
8610Sstevel@tonic-gate 	name = dst->ds_name;
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	/*
8640Sstevel@tonic-gate 	 * If the component has a unit number,
8650Sstevel@tonic-gate 	 * add it to the id, otherwise just use
8660Sstevel@tonic-gate 	 * the component's name.
8670Sstevel@tonic-gate 	 */
8680Sstevel@tonic-gate 	if (unit == -1)
8690Sstevel@tonic-gate 		(void) snprintf(id, bufsize, "%s", name);
8700Sstevel@tonic-gate 	else
8710Sstevel@tonic-gate 		(void) snprintf(id, bufsize, "%s%d", name, unit);
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 	DBG("ap_cm_id(%d)=%s\n", seq, id);
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate /*
8770Sstevel@tonic-gate  * Convert a component to a target type.
8780Sstevel@tonic-gate  */
8790Sstevel@tonic-gate ap_target_t
ap_cm_type(apd_t * a,int seq)8800Sstevel@tonic-gate ap_cm_type(apd_t *a, int seq)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 	ap_target_t c;
8830Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
8860Sstevel@tonic-gate 
8870Sstevel@tonic-gate 	switch (dst->ds_type) {
8880Sstevel@tonic-gate 	case SBD_COMP_CPU:
8890Sstevel@tonic-gate 		c = AP_CPU;
8900Sstevel@tonic-gate 		break;
8910Sstevel@tonic-gate 	case SBD_COMP_MEM:
8920Sstevel@tonic-gate 		c = AP_MEM;
8930Sstevel@tonic-gate 		break;
8940Sstevel@tonic-gate 	case SBD_COMP_IO:
8950Sstevel@tonic-gate 		c = AP_IO;
8960Sstevel@tonic-gate 		break;
8970Sstevel@tonic-gate 	case SBD_COMP_CMP:
8980Sstevel@tonic-gate 		c = AP_CMP;
8990Sstevel@tonic-gate 		break;
9000Sstevel@tonic-gate 	default:
9010Sstevel@tonic-gate 		c = AP_NONE;
9020Sstevel@tonic-gate 		break;
9030Sstevel@tonic-gate 	}
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	return (c);
9060Sstevel@tonic-gate }
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate int
ap_cm_ncap(apd_t * a,int seq)9090Sstevel@tonic-gate ap_cm_ncap(apd_t *a, int seq)
9100Sstevel@tonic-gate {
9110Sstevel@tonic-gate 	sbd_dev_stat_t	*dst;
9120Sstevel@tonic-gate 	int		ncap;
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	switch (dst->ds_type) {
9170Sstevel@tonic-gate 	case SBD_COMP_CPU:
9180Sstevel@tonic-gate 	case SBD_COMP_MEM:
9190Sstevel@tonic-gate 	case SBD_COMP_IO:
9200Sstevel@tonic-gate 		ncap = 1;
9210Sstevel@tonic-gate 		break;
9220Sstevel@tonic-gate 	case SBD_COMP_CMP:
9230Sstevel@tonic-gate 		ncap = ((sbd_cmp_stat_t *)dst)->ps_ncores;
9240Sstevel@tonic-gate 		break;
9250Sstevel@tonic-gate 	default:
9260Sstevel@tonic-gate 		ncap = 0;
9270Sstevel@tonic-gate 		break;
9280Sstevel@tonic-gate 	}
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	return (ncap);
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate int
ap_cm_capacity(apd_t * a,int seq,void * cap,int * ncap,cfga_stat_t * ostate)9340Sstevel@tonic-gate ap_cm_capacity(apd_t *a, int seq, void *cap, int *ncap, cfga_stat_t *ostate)
9350Sstevel@tonic-gate {
9360Sstevel@tonic-gate 	int i;
9370Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
9380Sstevel@tonic-gate 	cfga_stat_t os;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	if (cap == NULL)
9410Sstevel@tonic-gate 		return (0);
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
9440Sstevel@tonic-gate 	os = (cfga_stat_t)dst->ds_ostate;
9450Sstevel@tonic-gate 	if (os != CFGA_STAT_CONFIGURED && os != CFGA_STAT_UNCONFIGURED)
9460Sstevel@tonic-gate 		return (0);
9470Sstevel@tonic-gate 	if (ostate)
9480Sstevel@tonic-gate 		*ostate = os;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	*ncap = 1;
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	switch (dst->ds_type) {
9530Sstevel@tonic-gate 	case SBD_COMP_CPU: {
9540Sstevel@tonic-gate 		sbd_cpu_stat_t *cpu = (sbd_cpu_stat_t *)dst;
9550Sstevel@tonic-gate 		*((processorid_t *)cap) = cpu->cs_cpuid;
9560Sstevel@tonic-gate 		break;
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 	case SBD_COMP_MEM: {
9590Sstevel@tonic-gate 		sbd_mem_stat_t *mem = (sbd_mem_stat_t *)dst;
9600Sstevel@tonic-gate 		*((long *)cap) = mem->ms_totpages;
9610Sstevel@tonic-gate 		break;
9620Sstevel@tonic-gate 	}
9630Sstevel@tonic-gate 	case SBD_COMP_CMP: {
9640Sstevel@tonic-gate 		sbd_cmp_stat_t	*cmp = (sbd_cmp_stat_t *)dst;
9650Sstevel@tonic-gate 		processorid_t	*cpuid;
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 		cpuid = (processorid_t *)cap;
9680Sstevel@tonic-gate 		for (i = 0; i < cmp->ps_ncores; i++) {
9690Sstevel@tonic-gate 			cpuid[i] = cmp->ps_cpuid[i];
9700Sstevel@tonic-gate 		}
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 		*ncap = cmp->ps_ncores;
9730Sstevel@tonic-gate 		break;
9740Sstevel@tonic-gate 	}
9750Sstevel@tonic-gate 	default:
9760Sstevel@tonic-gate 		return (0);
9770Sstevel@tonic-gate 	}
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 	DBG("ap_cm_capacity(%d)=(", seq);
9800Sstevel@tonic-gate 	for (i = 0; i < *ncap; i++) {
9810Sstevel@tonic-gate 		DBG("%d ", ((int *)cap)[i]);
9820Sstevel@tonic-gate 	}
9830Sstevel@tonic-gate 	DBG("%d)\n", *ostate);
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 	return (1);
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate void
ap_cm_init(apd_t * a,cfga_list_data_t * ap,int seq)9890Sstevel@tonic-gate ap_cm_init(apd_t *a, cfga_list_data_t *ap, int seq)
9900Sstevel@tonic-gate {
9910Sstevel@tonic-gate 	char *type;
9920Sstevel@tonic-gate 	sbd_stat_t *st;
9930Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
9960Sstevel@tonic-gate 	dst = st->s_stat + seq;
9970Sstevel@tonic-gate 	type = ap_dev_type(dst);
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 	a->cmstat = (void *)dst;
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	DBG("ap_cm_init bd=%d rs=%d os=%d type=<%s> seq=%d\n",
1002*12004Sjiang.liu@intel.com 	    a->bnum, st->s_rstate, dst->ds_ostate, type, seq);
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	(void) strncpy(ap->ap_type, type, sizeof (ap->ap_type));
10050Sstevel@tonic-gate 	ap->ap_r_state = (cfga_stat_t)st->s_rstate;
10060Sstevel@tonic-gate 	ap->ap_o_state = (cfga_stat_t)dst->ds_ostate;
10070Sstevel@tonic-gate 	ap->ap_cond = (cfga_cond_t)dst->ds_cond;
10080Sstevel@tonic-gate 	ap->ap_busy = (cfga_busy_t)dst->ds_busy;
10090Sstevel@tonic-gate 	ap->ap_status_time = dst->ds_time;
10100Sstevel@tonic-gate 	ap_info(a, ap->ap_info, ap_cm_tgt(dst->ds_type));
10110Sstevel@tonic-gate }
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate void
ap_state(apd_t * a,cfga_stat_t * rs,cfga_stat_t * os)10140Sstevel@tonic-gate ap_state(apd_t *a, cfga_stat_t *rs, cfga_stat_t *os)
10150Sstevel@tonic-gate {
10160Sstevel@tonic-gate 	sbd_stat_t *st;
10170Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
10200Sstevel@tonic-gate 	dst = (sbd_dev_stat_t *)a->cmstat;
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate 	if (rs != NULL) {
10230Sstevel@tonic-gate 		if (a->tgt == AP_NONE)
10240Sstevel@tonic-gate 			*rs = CFGA_STAT_NONE;
10250Sstevel@tonic-gate 		else
10260Sstevel@tonic-gate 			*rs = (cfga_stat_t)st->s_rstate;
10270Sstevel@tonic-gate 	}
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	if (os != NULL) {
10300Sstevel@tonic-gate 		if (a->tgt == AP_NONE)
10310Sstevel@tonic-gate 			*os = CFGA_STAT_NONE;
10320Sstevel@tonic-gate 		else if (a->tgt == AP_BOARD)
10330Sstevel@tonic-gate 			*os = (cfga_stat_t)st->s_ostate;
10340Sstevel@tonic-gate 		else
10350Sstevel@tonic-gate 			*os = (cfga_stat_t)dst->ds_ostate;
10360Sstevel@tonic-gate 	}
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate #define	BI_POWERED		0
10400Sstevel@tonic-gate #define	BI_ASSIGNED		1
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate static const char *
10430Sstevel@tonic-gate binfo[] = {
10440Sstevel@tonic-gate 	"powered-on",
10450Sstevel@tonic-gate 	", assigned"
10460Sstevel@tonic-gate };
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate static const char *
10490Sstevel@tonic-gate binfo_parsable[] = {
10500Sstevel@tonic-gate 	"powered-on",
10510Sstevel@tonic-gate 	" assigned"
10520Sstevel@tonic-gate };
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate static void
bd_info(apd_t * a,cfga_info_t info,int parsable)10550Sstevel@tonic-gate bd_info(apd_t *a, cfga_info_t info, int parsable)
10560Sstevel@tonic-gate {
10570Sstevel@tonic-gate 	int i;
10580Sstevel@tonic-gate 	int nsep;
10590Sstevel@tonic-gate 	const char **p;
10600Sstevel@tonic-gate 	sbd_stat_t *st;
10610Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	DBG("bd_info(%p)\n", (void *)info);
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	if (parsable) {
10680Sstevel@tonic-gate 		p = binfo_parsable;
10690Sstevel@tonic-gate 		nsep = 1;
10700Sstevel@tonic-gate 	} else {
10710Sstevel@tonic-gate 		p = binfo;
10720Sstevel@tonic-gate 		nsep = 2;
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	i = nsep;
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	if (st->s_power) {
10780Sstevel@tonic-gate 		info += snprintf(info, end - info, p[BI_POWERED]);
10790Sstevel@tonic-gate 		i = 0;
10800Sstevel@tonic-gate 	}
10810Sstevel@tonic-gate 	if (st->s_assigned)
10820Sstevel@tonic-gate 		info += snprintf(info, end - info, p[BI_ASSIGNED] + i);
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate #define	CI_CPUID		0
10860Sstevel@tonic-gate #define	CI_SPEED		1
10870Sstevel@tonic-gate #define	CI_ECACHE		2
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate static const char *
10900Sstevel@tonic-gate cpuinfo[] = {
10910Sstevel@tonic-gate 	"cpuid %d",
10920Sstevel@tonic-gate 	", speed %d MHz",
10930Sstevel@tonic-gate 	", ecache %d MBytes"
10940Sstevel@tonic-gate };
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate static const char *
10970Sstevel@tonic-gate cpuinfo_parsable[] = {
10980Sstevel@tonic-gate 	"cpuid=%d",
10990Sstevel@tonic-gate 	" speed=%d",
11000Sstevel@tonic-gate 	" ecache=%d"
11010Sstevel@tonic-gate };
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate static void
cpu_info(apd_t * a,cfga_info_t info,int parsable)11040Sstevel@tonic-gate cpu_info(apd_t *a, cfga_info_t info, int parsable)
11050Sstevel@tonic-gate {
11060Sstevel@tonic-gate 	const char **p;
11070Sstevel@tonic-gate 	sbd_cpu_stat_t *dst;
11080Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	DBG("cpu_info(%p)\n", (void *)info);
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate 	dst = (sbd_cpu_stat_t *)a->cmstat;
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	if (parsable)
11150Sstevel@tonic-gate 		p = cpuinfo_parsable;
11160Sstevel@tonic-gate 	else
11170Sstevel@tonic-gate 		p = cpuinfo;
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_CPUID], dst->cs_cpuid);
11200Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_SPEED], dst->cs_speed);
11210Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_ECACHE], dst->cs_ecache);
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate #define	MI_ADDRESS		0
11250Sstevel@tonic-gate #define	MI_SIZE			1
11260Sstevel@tonic-gate #define	MI_PERMANENT		2
11270Sstevel@tonic-gate #define	MI_UNCONFIGURABLE	3
11280Sstevel@tonic-gate #define	MI_SOURCE		4
11290Sstevel@tonic-gate #define	MI_TARGET		5
11300Sstevel@tonic-gate #define	MI_DELETED		6
11310Sstevel@tonic-gate #define	MI_REMAINING		7
11320Sstevel@tonic-gate #define	MI_INTERLEAVE		8
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate static const char *
11350Sstevel@tonic-gate meminfo_nonparsable[] = {
11360Sstevel@tonic-gate 	"base address 0x%" PRIx64,
11370Sstevel@tonic-gate 	", %lu KBytes total",
11380Sstevel@tonic-gate 	", %lu KBytes permanent",
11390Sstevel@tonic-gate 	", unconfigurable",
11400Sstevel@tonic-gate 	", memory delete requested on %s",
11410Sstevel@tonic-gate 	", memory delete in progress on %s",
11420Sstevel@tonic-gate 	", %lu KBytes deleted",
11430Sstevel@tonic-gate 	", %lu KBytes remaining",
11440Sstevel@tonic-gate 	", inter board interleave"
11450Sstevel@tonic-gate };
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate static const char *
11480Sstevel@tonic-gate meminfo_parsable[] = {
11490Sstevel@tonic-gate 	"address=0x%" PRIx64,
11500Sstevel@tonic-gate 	" size=%lu",
11510Sstevel@tonic-gate 	" permanent=%lu",
11520Sstevel@tonic-gate 	" unconfigurable",
11530Sstevel@tonic-gate 	" source=%s",
11540Sstevel@tonic-gate 	" target=%s",
11550Sstevel@tonic-gate 	" deleted=%lu",
11560Sstevel@tonic-gate 	" remaining=%lu",
11570Sstevel@tonic-gate 	" inter-board-interleave"
11580Sstevel@tonic-gate };
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate #define	_K1	1024
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate /*
11640Sstevel@tonic-gate  * This function assumes pagesize > 1024 and that
11650Sstevel@tonic-gate  * pagesize is a multiple of 1024.
11660Sstevel@tonic-gate  */
11670Sstevel@tonic-gate static ulong_t
pages_to_kbytes(uint_t pgs)11680Sstevel@tonic-gate pages_to_kbytes(uint_t pgs)
11690Sstevel@tonic-gate {
11700Sstevel@tonic-gate 	long pagesize;
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
11730Sstevel@tonic-gate 	return (pgs * (pagesize / _K1));
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate static uint64_t
pages_to_bytes(uint_t pgs)11770Sstevel@tonic-gate pages_to_bytes(uint_t pgs)
11780Sstevel@tonic-gate {
11790Sstevel@tonic-gate 	long pagesize;
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
11820Sstevel@tonic-gate 	return ((uint64_t)pgs * pagesize);
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate static void
mem_info(apd_t * a,cfga_info_t info,int parsable)11860Sstevel@tonic-gate mem_info(apd_t *a, cfga_info_t info, int parsable)
11870Sstevel@tonic-gate {
11880Sstevel@tonic-gate 	const char **p;
11890Sstevel@tonic-gate 	sbd_mem_stat_t *dst;
11900Sstevel@tonic-gate 	int want_progress;
11910Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 	DBG("mem_info(%p)\n", (void *)info);
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 	dst = (sbd_mem_stat_t *)a->cmstat;
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate 	if (parsable)
11980Sstevel@tonic-gate 		p = meminfo_parsable;
11990Sstevel@tonic-gate 	else
12000Sstevel@tonic-gate 		p = meminfo_nonparsable;
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate 	info += snprintf(info, end - info, p[MI_ADDRESS],
12030Sstevel@tonic-gate 	    pages_to_bytes(dst->ms_basepfn));
12040Sstevel@tonic-gate 	info += snprintf(info, end - info, p[MI_SIZE],
12050Sstevel@tonic-gate 	    pages_to_kbytes(dst->ms_totpages));
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	if (dst->ms_noreloc_pages)
12080Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_PERMANENT],
12090Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_noreloc_pages));
12100Sstevel@tonic-gate 	if (!dst->ms_cage_enabled)
12110Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_UNCONFIGURABLE]);
12120Sstevel@tonic-gate 	if (dst->ms_interleave)
12130Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_INTERLEAVE]);
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	/*
12160Sstevel@tonic-gate 	 * If there is a valid peer physical ap_id specified,
12170Sstevel@tonic-gate 	 * convert it to a logical id.
12180Sstevel@tonic-gate 	 */
12190Sstevel@tonic-gate 	want_progress = 0;
12200Sstevel@tonic-gate 	if (str_valid(dst->ms_peer_ap_id)) {
12210Sstevel@tonic-gate 		char *cm;
12220Sstevel@tonic-gate 		char *peer;
12230Sstevel@tonic-gate 		char physid[MAXPATHLEN];
12240Sstevel@tonic-gate 		char logid[MAXPATHLEN];
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 		(void) snprintf(physid, sizeof (physid), "%s%s",
12270Sstevel@tonic-gate 		    DEVDIR, dst->ms_peer_ap_id);
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 		/*
12300Sstevel@tonic-gate 		 * Save the component portion of the physid and
12310Sstevel@tonic-gate 		 * add it back after converting to logical format.
12320Sstevel@tonic-gate 		 */
12330Sstevel@tonic-gate 		if ((cm = strstr(physid, "::")) != NULL) {
12340Sstevel@tonic-gate 			*cm = '\0';
12350Sstevel@tonic-gate 			cm += 2;
12360Sstevel@tonic-gate 		}
12370Sstevel@tonic-gate 
12380Sstevel@tonic-gate 		/* attempt to resolve to symlink */
12390Sstevel@tonic-gate 		if (ap_symid(a, physid, logid, sizeof (logid)) == 0)
12400Sstevel@tonic-gate 			peer = logid;
12410Sstevel@tonic-gate 		else
12420Sstevel@tonic-gate 			peer = physid;
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate 		if (dst->ms_peer_is_target) {
12450Sstevel@tonic-gate 			info += snprintf(info, end - info, p[MI_TARGET], peer);
12460Sstevel@tonic-gate 			if (cm)
12470Sstevel@tonic-gate 				info += snprintf(info, end - info, "::%s", cm);
12480Sstevel@tonic-gate 			want_progress = 1;
12490Sstevel@tonic-gate 		} else {
12500Sstevel@tonic-gate 			info += snprintf(info, end - info, p[MI_SOURCE], peer);
12510Sstevel@tonic-gate 			if (cm)
12520Sstevel@tonic-gate 				info += snprintf(info, end - info, "::%s", cm);
12530Sstevel@tonic-gate 		}
12540Sstevel@tonic-gate 	}
12550Sstevel@tonic-gate 	if (want_progress ||
12560Sstevel@tonic-gate 	    (dst->ms_detpages != 0 && dst->ms_detpages != dst->ms_totpages)) {
12570Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_DELETED],
12580Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_detpages));
12590Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_REMAINING],
12600Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_totpages -
12610Sstevel@tonic-gate 		    dst->ms_detpages));
12620Sstevel@tonic-gate 	}
12630Sstevel@tonic-gate }
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate #define	II_DEVICE		0
12660Sstevel@tonic-gate #define	II_REFERENCED		1
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate static const char *
12690Sstevel@tonic-gate ioinfo[] = {
12700Sstevel@tonic-gate 	"device %s",
12710Sstevel@tonic-gate 	", referenced"
12720Sstevel@tonic-gate };
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate static const char *
12750Sstevel@tonic-gate ioinfo_parsable[] = {
12760Sstevel@tonic-gate 	"device=%s",
12770Sstevel@tonic-gate 	" referenced"
12780Sstevel@tonic-gate };
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate static void
io_info(apd_t * a,cfga_info_t info,int parsable)12810Sstevel@tonic-gate io_info(apd_t *a, cfga_info_t info, int parsable)
12820Sstevel@tonic-gate {
12830Sstevel@tonic-gate 	const char **p;
12840Sstevel@tonic-gate 	sbd_io_stat_t *dst;
12850Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate 	dst = (sbd_io_stat_t *)a->cmstat;
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	if (parsable)
12900Sstevel@tonic-gate 		p = ioinfo_parsable;
12910Sstevel@tonic-gate 	else
12920Sstevel@tonic-gate 		p = ioinfo;
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	info += snprintf(info, end - info, p[II_DEVICE], dst->is_pathname);
12950Sstevel@tonic-gate 	if (dst->is_referenced)
12960Sstevel@tonic-gate 		info += snprintf(info, end - info, p[II_REFERENCED]);
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate #define	PI_CPUID		0
13000Sstevel@tonic-gate #define	PI_CPUID_PAIR		1
13010Sstevel@tonic-gate #define	PI_CPUID_CONT		2
13020Sstevel@tonic-gate #define	PI_CPUID_LAST		3
13030Sstevel@tonic-gate #define	PI_SPEED		4
13040Sstevel@tonic-gate #define	PI_ECACHE		5
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate static const char *
13070Sstevel@tonic-gate cmpinfo[] = {
13080Sstevel@tonic-gate 	"cpuid %d",
13090Sstevel@tonic-gate 	" and %d",
13100Sstevel@tonic-gate 	", %d",
13110Sstevel@tonic-gate 	", and %d",
13120Sstevel@tonic-gate 	", speed %d MHz",
13130Sstevel@tonic-gate 	", ecache %d MBytes"
13140Sstevel@tonic-gate };
13150Sstevel@tonic-gate 
13160Sstevel@tonic-gate static const char *
13170Sstevel@tonic-gate cmpinfo_parsable[] = {
13180Sstevel@tonic-gate 	"cpuid=%d",
13190Sstevel@tonic-gate 	",%d",
13200Sstevel@tonic-gate 	",%d",
13210Sstevel@tonic-gate 	",%d",
13220Sstevel@tonic-gate 	" speed=%d",
13230Sstevel@tonic-gate 	" ecache=%d"
13240Sstevel@tonic-gate };
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate static void
cmp_info(apd_t * a,cfga_info_t info,int parsable)13270Sstevel@tonic-gate cmp_info(apd_t *a, cfga_info_t info, int parsable)
13280Sstevel@tonic-gate {
13290Sstevel@tonic-gate 	int		i;
13300Sstevel@tonic-gate 	int		last;
13310Sstevel@tonic-gate 	const char	**p;
13320Sstevel@tonic-gate 	sbd_cmp_stat_t	*dst;
13330Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate 	DBG("cmp_info(%p)\n", (void *)info);
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 	dst = (sbd_cmp_stat_t *)a->cmstat;
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 	if (parsable)
13400Sstevel@tonic-gate 		p = cmpinfo_parsable;
13410Sstevel@tonic-gate 	else
13420Sstevel@tonic-gate 		p = cmpinfo;
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	/* Print the first cpuid */
13450Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_CPUID], dst->ps_cpuid[0]);
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 	/*
13480Sstevel@tonic-gate 	 * Print the middle cpuids, if necessary. Stop before
13490Sstevel@tonic-gate 	 * the last one, since printing the last cpuid is a
13500Sstevel@tonic-gate 	 * special case for the non parsable form.
13510Sstevel@tonic-gate 	 */
13520Sstevel@tonic-gate 	for (i = 1; i < (dst->ps_ncores - 1); i++) {
13530Sstevel@tonic-gate 		info += snprintf(info, end - info, p[PI_CPUID_CONT],
13540Sstevel@tonic-gate 		    dst->ps_cpuid[i]);
13550Sstevel@tonic-gate 	}
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	/* Print the last cpuid, if necessary */
13580Sstevel@tonic-gate 	if (dst->ps_ncores > 1) {
13590Sstevel@tonic-gate 		last = (dst->ps_ncores == 2) ? PI_CPUID_PAIR : PI_CPUID_LAST;
13600Sstevel@tonic-gate 		info += snprintf(info, end - info,
13610Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, p[last]), dst->ps_cpuid[i]);
13620Sstevel@tonic-gate 	}
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_SPEED], dst->ps_speed);
13650Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_ECACHE], dst->ps_ecache);
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate 
13680Sstevel@tonic-gate void
ap_info(apd_t * a,cfga_info_t info,ap_target_t tgt)13690Sstevel@tonic-gate ap_info(apd_t *a, cfga_info_t info, ap_target_t tgt)
13700Sstevel@tonic-gate {
13710Sstevel@tonic-gate 	int parsable = ap_getopt(a, OPT_PARSABLE);
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	DBG("ap_info(%p, %d)\n", (void *)info, parsable);
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 	switch (tgt) {
13760Sstevel@tonic-gate 	case AP_BOARD:
13770Sstevel@tonic-gate 		bd_info(a, info, parsable);
13780Sstevel@tonic-gate 		break;
13790Sstevel@tonic-gate 	case AP_CPU:
13800Sstevel@tonic-gate 		cpu_info(a, info, parsable);
13810Sstevel@tonic-gate 		break;
13820Sstevel@tonic-gate 	case AP_MEM:
13830Sstevel@tonic-gate 		mem_info(a, info, parsable);
13840Sstevel@tonic-gate 		break;
13850Sstevel@tonic-gate 	case AP_IO:
13860Sstevel@tonic-gate 		io_info(a, info, parsable);
13870Sstevel@tonic-gate 		break;
13880Sstevel@tonic-gate 	case AP_CMP:
13890Sstevel@tonic-gate 		cmp_info(a, info, parsable);
13900Sstevel@tonic-gate 		break;
13910Sstevel@tonic-gate 	default:
13920Sstevel@tonic-gate 		break;
13930Sstevel@tonic-gate 	}
13940Sstevel@tonic-gate }
1395