xref: /illumos-gate/usr/src/lib/cfgadm_plugins/sbd/common/ap_sbd.c (revision bbf215553c7233fbab8a0afdf1fac74c44781867)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a3114836SGerry Liu  * Common Development and Distribution License (the "License").
6a3114836SGerry Liu  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22a3114836SGerry Liu  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <ctype.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <libintl.h>
357c478bd9Sstevel@tonic-gate #define	CFGA_PLUGIN_LIB
367c478bd9Sstevel@tonic-gate #include <config_admin.h>
377c478bd9Sstevel@tonic-gate #include "ap.h"
387c478bd9Sstevel@tonic-gate #include <sys/obpdefs.h>
397c478bd9Sstevel@tonic-gate #include <sys/processor.h>
407c478bd9Sstevel@tonic-gate #include <sys/stat.h>
417c478bd9Sstevel@tonic-gate #include <sys/sbd_ioctl.h>
427c478bd9Sstevel@tonic-gate #include <sys/int_fmtio.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static cfga_err_t
ap_getncm(apd_t * a,sbd_comp_type_t type,int * ncm)457c478bd9Sstevel@tonic-gate ap_getncm(apd_t *a, sbd_comp_type_t type, int *ncm)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
487c478bd9Sstevel@tonic-gate 	sbd_getncm_cmd_t *cp;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 	if (a->fd == -1 || a->ctl == NULL)
517c478bd9Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
547c478bd9Sstevel@tonic-gate 	ctl->ic_type = type;
557c478bd9Sstevel@tonic-gate 	ctl->ic_name[0] = '\0';
567c478bd9Sstevel@tonic-gate 	ctl->ic_unit = 0;
577c478bd9Sstevel@tonic-gate 	ctl->i_len = 0;
587c478bd9Sstevel@tonic-gate 	ctl->i_opts = NULL;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	DBG("ioctl(%d SBD_CMD_GETNCM, 0x%p)\n", a->fd, (void *)ctl);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	if (ioctl(a->fd, SBD_CMD_GETNCM, ctl) == -1) {
637c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_GETNCM);
647c478bd9Sstevel@tonic-gate 		return (CFGA_ERROR);
657c478bd9Sstevel@tonic-gate 	}
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	cp = &ctl->i_cmd.cmd_getncm;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	DBG("ncm(%d)=%d\n", type, cp->g_ncm);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	if (ncm)
727c478bd9Sstevel@tonic-gate 		*ncm = cp->g_ncm;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	return (CFGA_OK);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate cfga_err_t
ap_stat(apd_t * a,int all)787c478bd9Sstevel@tonic-gate ap_stat(apd_t *a, int all)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 	int fd;
817c478bd9Sstevel@tonic-gate 	int ncm;
827c478bd9Sstevel@tonic-gate 	int select;
837c478bd9Sstevel@tonic-gate 	int stsize;
847c478bd9Sstevel@tonic-gate 	int oflag;
857c478bd9Sstevel@tonic-gate 	sbd_stat_cmd_t *sc;
867c478bd9Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
877c478bd9Sstevel@tonic-gate 	cfga_err_t rc;
887c478bd9Sstevel@tonic-gate 	sbd_stat_t *new_stat;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	rc = CFGA_LIB_ERROR;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	DBG("ap_stat(%s)\n", a->path);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	/* Open the file descriptor if not already open */
957c478bd9Sstevel@tonic-gate 	if (a->fd == -1) {
967c478bd9Sstevel@tonic-gate 		DBG("open(%s)\n", a->path);
977c478bd9Sstevel@tonic-gate 		if (a->statonly != 0)
987c478bd9Sstevel@tonic-gate 			oflag = O_RDONLY;
997c478bd9Sstevel@tonic-gate 		else
1007c478bd9Sstevel@tonic-gate 			oflag = O_RDWR;
1017c478bd9Sstevel@tonic-gate 		if ((fd = open(a->path, oflag, 0)) == -1) {
1027c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_AP_INVAL);
1037c478bd9Sstevel@tonic-gate 			return (rc);
1047c478bd9Sstevel@tonic-gate 		}
1057c478bd9Sstevel@tonic-gate 		a->fd = fd;
1067c478bd9Sstevel@tonic-gate 	} else {
1077c478bd9Sstevel@tonic-gate 		fd = a->fd;
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	if (a->ctl == NULL && (a->ctl = calloc(1, sizeof (*ctl))) == NULL) {
1117c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1127c478bd9Sstevel@tonic-gate 		return (rc);
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	if (a->tgt == AP_BOARD) {
1167c478bd9Sstevel@tonic-gate 		/*
1177c478bd9Sstevel@tonic-gate 		 * The status target is the board. If we need to
1187c478bd9Sstevel@tonic-gate 		 * return component data (to support the -a option),
1197c478bd9Sstevel@tonic-gate 		 * get the number of components on the board.
1207c478bd9Sstevel@tonic-gate 		 */
1217c478bd9Sstevel@tonic-gate 		select = 0;
1227c478bd9Sstevel@tonic-gate 		if (all) {
1237c478bd9Sstevel@tonic-gate 			cfga_err_t r;
1247c478bd9Sstevel@tonic-gate 			r = ap_getncm(a, SBD_COMP_NONE, &ncm);
1257c478bd9Sstevel@tonic-gate 			if (r != CFGA_OK) {
1267c478bd9Sstevel@tonic-gate 				return (r);
1277c478bd9Sstevel@tonic-gate 			}
1287c478bd9Sstevel@tonic-gate 		} else {
1297c478bd9Sstevel@tonic-gate 			ncm = 0;
1307c478bd9Sstevel@tonic-gate 		}
1317c478bd9Sstevel@tonic-gate 	} else {
1327c478bd9Sstevel@tonic-gate 		select = 1;
1337c478bd9Sstevel@tonic-gate 		ncm = 1;
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	DBG("ncm=%d\n", ncm);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	a->ncm = ncm;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/*
1417c478bd9Sstevel@tonic-gate 	 * The status structure contains space for one component;
1427c478bd9Sstevel@tonic-gate 	 * add the space for the other components if necessary.
1437c478bd9Sstevel@tonic-gate 	 */
1447c478bd9Sstevel@tonic-gate 	stsize = sizeof (sbd_stat_t);
1457c478bd9Sstevel@tonic-gate 	if (ncm > 1)
1467c478bd9Sstevel@tonic-gate 		stsize += ((ncm - 1) * sizeof (sbd_dev_stat_t));
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if ((new_stat = realloc(a->stat, stsize)) == NULL) {
1497c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1507c478bd9Sstevel@tonic-gate 		return (rc);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	a->stat = new_stat;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
1577c478bd9Sstevel@tonic-gate 	ctl->i_len = 0;
1587c478bd9Sstevel@tonic-gate 	ctl->i_opts = NULL;
1597c478bd9Sstevel@tonic-gate 	ctl->ic_type = SBD_COMP_NONE;
1607c478bd9Sstevel@tonic-gate 	if (all)
1617c478bd9Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_ALLCMP;
1627c478bd9Sstevel@tonic-gate 	sc = &ctl->i_cmd.cmd_stat;
1637c478bd9Sstevel@tonic-gate 	sc->s_statp = (caddr_t)a->stat;
1647c478bd9Sstevel@tonic-gate 	sc->s_nbytes = stsize;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (select) {
1677c478bd9Sstevel@tonic-gate 		/*
1687c478bd9Sstevel@tonic-gate 		 * The target is a specific component.  Pass its
1697c478bd9Sstevel@tonic-gate 		 * name and unit number to the driver.  Set its
1707c478bd9Sstevel@tonic-gate 		 * type to UNKNOWN since the plugin does not know
1717c478bd9Sstevel@tonic-gate 		 * the type of the component specified by the user.
1727c478bd9Sstevel@tonic-gate 		 */
1737c478bd9Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_UNKNOWN;
1747c478bd9Sstevel@tonic-gate 		ctl->ic_unit = a->cnum;
175a3114836SGerry Liu 		(void) strcpy(ctl->ic_name, a->cname);
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	DBG("ioctl(%d SBD_CMD_STATUS, sc=0x%p sz=%d flags=%d",
1797c478bd9Sstevel@tonic-gate 	    fd, (void *)sc->s_statp, sc->s_nbytes, ctl->i_flags);
1807c478bd9Sstevel@tonic-gate 	if (select)
1817c478bd9Sstevel@tonic-gate 		DBG(" cname=<%s> cnum=%d", a->cname, a->cnum);
1827c478bd9Sstevel@tonic-gate 	DBG(")\n");
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	if (ioctl(fd, SBD_CMD_STATUS, ctl) == -1) {
1857c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, CMD_STATUS);
1867c478bd9Sstevel@tonic-gate 		rc = CFGA_ERROR;
1877c478bd9Sstevel@tonic-gate 	} else
1887c478bd9Sstevel@tonic-gate 		rc = CFGA_OK;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	DBG("ap_stat()=%d\n", rc);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	return (rc);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate  * Convert a component to a target type.
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate static ap_target_t
ap_cm_tgt(sbd_comp_type_t type)1997c478bd9Sstevel@tonic-gate ap_cm_tgt(sbd_comp_type_t type)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	ap_target_t c;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	switch (type) {
2047c478bd9Sstevel@tonic-gate 	case SBD_COMP_CPU:
2057c478bd9Sstevel@tonic-gate 		c = AP_CPU;
2067c478bd9Sstevel@tonic-gate 		break;
2077c478bd9Sstevel@tonic-gate 	case SBD_COMP_MEM:
2087c478bd9Sstevel@tonic-gate 		c = AP_MEM;
2097c478bd9Sstevel@tonic-gate 		break;
2107c478bd9Sstevel@tonic-gate 	case SBD_COMP_IO:
2117c478bd9Sstevel@tonic-gate 		c = AP_IO;
2127c478bd9Sstevel@tonic-gate 		break;
2137c478bd9Sstevel@tonic-gate 	case SBD_COMP_CMP:
2147c478bd9Sstevel@tonic-gate 		c = AP_CMP;
2157c478bd9Sstevel@tonic-gate 		break;
2167c478bd9Sstevel@tonic-gate 	default:
2177c478bd9Sstevel@tonic-gate 		c = AP_NONE;
2187c478bd9Sstevel@tonic-gate 		break;
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	return (c);
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate cfga_err_t
apd_init(apd_t * a,int all)2257c478bd9Sstevel@tonic-gate apd_init(apd_t *a, int all)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	int i;
2287c478bd9Sstevel@tonic-gate 	char *cn, *dn;
2297c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
2307c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
2317c478bd9Sstevel@tonic-gate 	cfga_err_t rc;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/*
2347c478bd9Sstevel@tonic-gate 	 * Ideally, for board operations (other than status) it is not
2357c478bd9Sstevel@tonic-gate 	 * necessary to issue the STATUS ioctl.  The call however allows a
2367c478bd9Sstevel@tonic-gate 	 * final sanity check to ensure that the board number returned
2377c478bd9Sstevel@tonic-gate 	 * by the driver matches the plugin's notion of the board number
2387c478bd9Sstevel@tonic-gate 	 * as extracted from the ap_id.  If this check is not desirable,
2397c478bd9Sstevel@tonic-gate 	 * we can change the code to issue the status call only when
2407c478bd9Sstevel@tonic-gate 	 * necessary.  Note that for component operations, we need to do
2417c478bd9Sstevel@tonic-gate 	 * the STATUS in order to figure out the component type and
2427c478bd9Sstevel@tonic-gate 	 * validate the command/options accordingly. XXX
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 	if ((rc = ap_stat(a, all)) != CFGA_OK) {
2457c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_AP_INVAL);
2467c478bd9Sstevel@tonic-gate 		return (rc);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	/*
2527c478bd9Sstevel@tonic-gate 	 * Set the component count to the returned stat count.
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	if (a->ncm > st->s_nstat) {
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		DBG("ncm=%d nstat=%d (truncated)\n", a->ncm, st->s_nstat);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 		a->ncm = st->s_nstat;
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if (a->tgt == AP_BOARD) {
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		DBG("tgt=%d\n", a->tgt);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		/*
2667c478bd9Sstevel@tonic-gate 		 * Initialize the RCM module here so that it can record
2677c478bd9Sstevel@tonic-gate 		 * the initial state of the capacity information.
2687c478bd9Sstevel@tonic-gate 		 */
2697c478bd9Sstevel@tonic-gate 		rc = ap_rcm_init(a);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 		return (rc);
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	a->tgt = AP_NONE;
2757c478bd9Sstevel@tonic-gate 	cn = a->cname;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	DBG("cname=<%s> cunit=<%d>\n", a->cname, a->cnum);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	for (dst = st->s_stat, i = 0; i < st->s_nstat; i++, dst++) {
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		DBG("ds_name,ds_unit,ds_type=<%s,%d,%d> ",
2827c478bd9Sstevel@tonic-gate 		    dst->ds_name, dst->ds_unit, dst->ds_type);
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 		if (dst->ds_unit != a->cnum)
2857c478bd9Sstevel@tonic-gate 			continue;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		/*
2887c478bd9Sstevel@tonic-gate 		 * Consider the names matched if they are either
2897c478bd9Sstevel@tonic-gate 		 * both absent or the same. It is conceivable that
2907c478bd9Sstevel@tonic-gate 		 * a NULL component name be considered valid
2917c478bd9Sstevel@tonic-gate 		 * by the driver.
2927c478bd9Sstevel@tonic-gate 		 */
2937c478bd9Sstevel@tonic-gate 		dn = dst->ds_name;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		if ((dn == NULL && cn == NULL) ||
2967c478bd9Sstevel@tonic-gate 		    (dn != NULL && cn != NULL && strcmp(dn, cn) == 0)) {
2977c478bd9Sstevel@tonic-gate 			a->tgt = ap_cm_tgt(dst->ds_type);
2987c478bd9Sstevel@tonic-gate 			a->cmstat = (void *)dst;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 			DBG("found ");
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 			break;
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	DBG("tgt=%d\n", a->tgt);
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (a->tgt == AP_NONE) {
3097c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CM_INVAL, a->cid);
3107c478bd9Sstevel@tonic-gate 		return (CFGA_INVAL);
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	/*
3147c478bd9Sstevel@tonic-gate 	 * Initialize the RCM module here so that it can record
3157c478bd9Sstevel@tonic-gate 	 * the initial state of the capacity information.
3167c478bd9Sstevel@tonic-gate 	 */
3177c478bd9Sstevel@tonic-gate 	rc = ap_rcm_init(a);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	return (rc);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate void
apd_free(apd_t * a)3237c478bd9Sstevel@tonic-gate apd_free(apd_t *a)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate 	if (a == NULL)
3267c478bd9Sstevel@tonic-gate 		return;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	ap_rcm_fini(a);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	if (a->fd != -1)
331a3114836SGerry Liu 		(void) close(a->fd);
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	s_free(a->options);
3347c478bd9Sstevel@tonic-gate 	s_free(a->path);
3357c478bd9Sstevel@tonic-gate 	s_free(a->drv);
3367c478bd9Sstevel@tonic-gate 	s_free(a->target);
3377c478bd9Sstevel@tonic-gate 	s_free(a->cname);
3387c478bd9Sstevel@tonic-gate 	s_free(a->ctl);
3397c478bd9Sstevel@tonic-gate 	s_free(a->stat);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	free(a);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate apd_t *
apd_alloc(const char * ap_id,cfga_flags_t flags,char ** errstring,struct cfga_msg * msgp,struct cfga_confirm * confp)3457c478bd9Sstevel@tonic-gate apd_alloc(const char *ap_id, cfga_flags_t flags, char **errstring,
3467c478bd9Sstevel@tonic-gate 	struct cfga_msg *msgp, struct cfga_confirm *confp)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	apd_t *a;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	if ((a = calloc(1, sizeof (*a))) == NULL)
3517c478bd9Sstevel@tonic-gate 		return (NULL);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	if (errstring != NULL)
3547c478bd9Sstevel@tonic-gate 		*errstring = NULL;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	a->fd = -1;
3577c478bd9Sstevel@tonic-gate 	a->errstring = errstring;
3587c478bd9Sstevel@tonic-gate 	a->msgp = msgp;
3597c478bd9Sstevel@tonic-gate 	a->confp = confp;
3607c478bd9Sstevel@tonic-gate 	a->class = "sbd";
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (flags & CFGA_FLAG_LIST_ALL)
3637c478bd9Sstevel@tonic-gate 		ap_setopt(a, OPT_LIST_ALL);
3647c478bd9Sstevel@tonic-gate 	if (flags & CFGA_FLAG_FORCE)
3657c478bd9Sstevel@tonic-gate 		ap_setopt(a, OPT_FORCE);
3667c478bd9Sstevel@tonic-gate 	if (flags & CFGA_FLAG_VERBOSE)
3677c478bd9Sstevel@tonic-gate 		ap_setopt(a, OPT_VERBOSE);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (ap_id == NULL || ap_parse(a, ap_id) == 0)
3707c478bd9Sstevel@tonic-gate 		return (a);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	apd_free(a);
3737c478bd9Sstevel@tonic-gate 	return (NULL);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate /*
377*bbf21555SRichard Lowe  * The type field is defined to be parsable by cfgadm(8): It
3787c478bd9Sstevel@tonic-gate  * must not contain white space characters. This function
3797c478bd9Sstevel@tonic-gate  * converts white space to underscore.
3807c478bd9Sstevel@tonic-gate  */
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate static void
parsable_strncpy(char * op,const char * ip,size_t n)3837c478bd9Sstevel@tonic-gate parsable_strncpy(char *op, const char *ip, size_t n)
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate 	char c;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
3887c478bd9Sstevel@tonic-gate 		c = *ip++;
3897c478bd9Sstevel@tonic-gate 		if (isspace(c))
3907c478bd9Sstevel@tonic-gate 			c = '_';
3917c478bd9Sstevel@tonic-gate 		*op++ = c;
3927c478bd9Sstevel@tonic-gate 		if (c == '\0')
3937c478bd9Sstevel@tonic-gate 			break;
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate void
ap_init(apd_t * a,cfga_list_data_t * ap)3987c478bd9Sstevel@tonic-gate ap_init(apd_t *a, cfga_list_data_t *ap)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	DBG("ap_init bd=%d rs=%d os=%d type=<%s>\n",
4057c478bd9Sstevel@tonic-gate 	    a->bnum, st->s_rstate, st->s_ostate, st->s_type);
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	parsable_strncpy(ap->ap_type, st->s_type, sizeof (ap->ap_type));
4087c478bd9Sstevel@tonic-gate 	ap->ap_r_state = (cfga_stat_t)st->s_rstate;
4097c478bd9Sstevel@tonic-gate 	ap->ap_o_state = (cfga_stat_t)st->s_ostate;
4107c478bd9Sstevel@tonic-gate 	ap->ap_cond = (cfga_cond_t)st->s_cond;
4117c478bd9Sstevel@tonic-gate 	ap->ap_busy = (cfga_busy_t)st->s_busy;
4127c478bd9Sstevel@tonic-gate 	ap->ap_status_time = st->s_time;
4137c478bd9Sstevel@tonic-gate 	ap_info(a, ap->ap_info, AP_BOARD);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate typedef struct {
4177c478bd9Sstevel@tonic-gate 	int cmd;
4187c478bd9Sstevel@tonic-gate 	int ioc;
4197c478bd9Sstevel@tonic-gate } ap_ioc_t;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate static ap_ioc_t
4227c478bd9Sstevel@tonic-gate ap_iocs[] =  {
4237c478bd9Sstevel@tonic-gate 	{CMD_ASSIGN,	  SBD_CMD_ASSIGN	},
4247c478bd9Sstevel@tonic-gate 	{CMD_POWERON,	  SBD_CMD_POWERON	},
4257c478bd9Sstevel@tonic-gate 	{CMD_TEST,	  SBD_CMD_TEST		},
4267c478bd9Sstevel@tonic-gate 	{CMD_CONNECT,	  SBD_CMD_CONNECT	},
4277c478bd9Sstevel@tonic-gate 	{CMD_CONFIGURE,	  SBD_CMD_CONFIGURE	},
4287c478bd9Sstevel@tonic-gate 	{CMD_UNCONFIGURE, SBD_CMD_UNCONFIGURE	},
4297c478bd9Sstevel@tonic-gate 	{CMD_DISCONNECT,  SBD_CMD_DISCONNECT	},
4307c478bd9Sstevel@tonic-gate 	{CMD_POWEROFF,	  SBD_CMD_POWEROFF	},
4317c478bd9Sstevel@tonic-gate 	{CMD_STATUS,	  SBD_CMD_STATUS	},
4327c478bd9Sstevel@tonic-gate 	{CMD_GETNCM,	  SBD_CMD_GETNCM	},
4337c478bd9Sstevel@tonic-gate 	{CMD_UNASSIGN,	  SBD_CMD_UNASSIGN	},
4347c478bd9Sstevel@tonic-gate 	{CMD_PASSTHRU,	  SBD_CMD_PASSTHRU	},
4357c478bd9Sstevel@tonic-gate 	{CMD_NONE,	  0			}
4367c478bd9Sstevel@tonic-gate };
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate static int
ap_ioc(int cmd)4397c478bd9Sstevel@tonic-gate ap_ioc(int cmd)
4407c478bd9Sstevel@tonic-gate {
4417c478bd9Sstevel@tonic-gate 	ap_ioc_t *acp;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	DBG("ap_ioc(%d)\n", cmd);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	for (acp = ap_iocs; acp->cmd != CMD_NONE; acp++)
4467c478bd9Sstevel@tonic-gate 		if (acp->cmd == cmd)
4477c478bd9Sstevel@tonic-gate 			break;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	DBG("ap_ioc(%d)=0x%x\n", cmd, acp->ioc);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	return (acp->ioc);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate cfga_err_t
ap_suspend_query(apd_t * a,int cmd,int * check)4557c478bd9Sstevel@tonic-gate ap_suspend_query(apd_t *a, int cmd, int *check)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	int ioc;
4587c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	/*
4617c478bd9Sstevel@tonic-gate 	 * See if the a quiesce operation is required for
4627c478bd9Sstevel@tonic-gate 	 * this command for any of the components.  If the
4637c478bd9Sstevel@tonic-gate 	 * command does not map to an ioctl, then there is
4647c478bd9Sstevel@tonic-gate 	 * nothing to do.
4657c478bd9Sstevel@tonic-gate 	 */
4667c478bd9Sstevel@tonic-gate 	if ((ioc = ap_ioc(cmd)) == 0)
4677c478bd9Sstevel@tonic-gate 		return (CFGA_OK);
4687c478bd9Sstevel@tonic-gate 	else if (a->tgt == AP_BOARD) {
4697c478bd9Sstevel@tonic-gate 		int i;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		dst = ((sbd_stat_t *)a->stat)->s_stat;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 		/*
4747c478bd9Sstevel@tonic-gate 		 * See if any component requires a
4757c478bd9Sstevel@tonic-gate 		 * OS suspension for this command.
4767c478bd9Sstevel@tonic-gate 		 */
4777c478bd9Sstevel@tonic-gate 		for (i = 0; i < a->ncm; i++, dst++)
4787c478bd9Sstevel@tonic-gate 			if (SBD_CHECK_SUSPEND(ioc, dst->ds_suspend))
4797c478bd9Sstevel@tonic-gate 				(*check)++;
4807c478bd9Sstevel@tonic-gate 	} else {
4817c478bd9Sstevel@tonic-gate 		dst = (sbd_dev_stat_t *)a->cmstat;
4827c478bd9Sstevel@tonic-gate 		if (SBD_CHECK_SUSPEND(ioc, dst->ds_suspend))
4837c478bd9Sstevel@tonic-gate 				(*check)++;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	return (CFGA_OK);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate cfga_err_t
ap_platopts_check(apd_t * a,int first,int last)4907c478bd9Sstevel@tonic-gate ap_platopts_check(apd_t *a, int first, int last)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate 	int c;
4937c478bd9Sstevel@tonic-gate 	uint_t platopts;
4947c478bd9Sstevel@tonic-gate 	sbd_stat_t *stat;
4957c478bd9Sstevel@tonic-gate 	ap_opts_t *opts;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	opts = &a->opts;
4987c478bd9Sstevel@tonic-gate 	stat = (sbd_stat_t *)a->stat;
4997c478bd9Sstevel@tonic-gate 	platopts = stat->s_platopts;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * If there are no platform options set then there
5047c478bd9Sstevel@tonic-gate 	 * is no need to check this operation
5057c478bd9Sstevel@tonic-gate 	 */
5067c478bd9Sstevel@tonic-gate 	if (opts->platform == NULL)
5077c478bd9Sstevel@tonic-gate 		return (CFGA_OK);
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	/*
5107c478bd9Sstevel@tonic-gate 	 * Check if any of the steps in the sequence
5117c478bd9Sstevel@tonic-gate 	 * allows for a platform option
5127c478bd9Sstevel@tonic-gate 	 */
5137c478bd9Sstevel@tonic-gate 	for (c = first; c <= last; c++)
5147c478bd9Sstevel@tonic-gate 		/*
5157c478bd9Sstevel@tonic-gate 		 * If the platopt is set it means that the platform does not
5167c478bd9Sstevel@tonic-gate 		 * support options for this cmd
5177c478bd9Sstevel@tonic-gate 		 */
5187c478bd9Sstevel@tonic-gate 		if (SBD_CHECK_PLATOPTS(ap_ioc(c), platopts) == 0) {
5197c478bd9Sstevel@tonic-gate 			return (CFGA_OK);
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	ap_err(a, ERR_OPT_INVAL, opts->platform);
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	return (CFGA_INVAL);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate cfga_err_t
ap_ioctl(apd_t * a,int cmd)5287c478bd9Sstevel@tonic-gate ap_ioctl(apd_t *a, int cmd)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	int ioc;
5317c478bd9Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (a->ctl == NULL && (a->ctl = calloc(1, sizeof (*ctl))) == NULL) {
5347c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5357c478bd9Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	ap_msg(a, MSG_ISSUE, cmd, a->target);
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	ctl = (sbd_ioctl_arg_t *)a->ctl;
5417c478bd9Sstevel@tonic-gate 	ctl->i_flags = 0;
5427c478bd9Sstevel@tonic-gate 	ctl->i_len = 0;
5437c478bd9Sstevel@tonic-gate 	ctl->i_opts = NULL;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	if (ap_getopt(a, OPT_FORCE))
5467c478bd9Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_FORCE;
5477c478bd9Sstevel@tonic-gate 	if (ap_getopt(a, OPT_SUSPEND_OK))
5487c478bd9Sstevel@tonic-gate 		ctl->i_flags |= SBD_FLAG_QUIESCE_OKAY;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (a->tgt == AP_BOARD)
5517c478bd9Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_NONE;
5527c478bd9Sstevel@tonic-gate 	else {
5537c478bd9Sstevel@tonic-gate 		ctl->ic_type = SBD_COMP_UNKNOWN;
5547c478bd9Sstevel@tonic-gate 		ctl->ic_unit = a->cnum;
555a3114836SGerry Liu 		(void) strcpy(ctl->ic_name, a->cname);
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	if (!(ioc = ap_ioc(cmd))) {
5597c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5607c478bd9Sstevel@tonic-gate 		return (CFGA_LIB_ERROR);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/*
5647c478bd9Sstevel@tonic-gate 	 * If this is a passthru command, pass all of its
5657c478bd9Sstevel@tonic-gate 	 * options; otherwise, pass all options after the
5667c478bd9Sstevel@tonic-gate 	 * platform keyword.
5677c478bd9Sstevel@tonic-gate 	 */
5687c478bd9Sstevel@tonic-gate 	if (cmd == CMD_PASSTHRU)
5697c478bd9Sstevel@tonic-gate 		ctl->i_opts = a->options;
5707c478bd9Sstevel@tonic-gate 	else {
5717c478bd9Sstevel@tonic-gate 		/*
5727c478bd9Sstevel@tonic-gate 		 * Only pass the platform option to the cmds that the platform
5737c478bd9Sstevel@tonic-gate 		 * has specified as ok
5747c478bd9Sstevel@tonic-gate 		 */
5757c478bd9Sstevel@tonic-gate 		sbd_stat_t *stat;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 		stat = (sbd_stat_t *)a->stat;
5787c478bd9Sstevel@tonic-gate 		if (SBD_CHECK_PLATOPTS(ioc, stat->s_platopts) == 0)
5797c478bd9Sstevel@tonic-gate 			ctl->i_opts = a->opts.platform;
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (ctl->i_opts != NULL)
5837c478bd9Sstevel@tonic-gate 		ctl->i_len = strlen(ctl->i_opts) + 1;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	DBG("i_opts=%s\n", ctl->i_opts ? ctl->i_opts : "NULL");
5867c478bd9Sstevel@tonic-gate 	DBG("i_flags=0x%x\n", ctl->i_flags);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (ap_getopt(a, OPT_SIM)) {
5897c478bd9Sstevel@tonic-gate 		ap_msg(a, MSG_DONE, cmd, a->target);
5907c478bd9Sstevel@tonic-gate 		return (CFGA_OK);
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	if (ioctl(a->fd, ioc, ctl) == -1) {
5947c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_FAIL, cmd);
5957c478bd9Sstevel@tonic-gate 		return (CFGA_ERROR);
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 	ap_msg(a, MSG_DONE, cmd, a->target);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	return (CFGA_OK);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate  * Return the error string corresponding to a given error code.
6047c478bd9Sstevel@tonic-gate  * String table and error code sets are provided by sbd_etab.  This data
6057c478bd9Sstevel@tonic-gate  * structure is automatically generated at compile time from the error
6067c478bd9Sstevel@tonic-gate  * code and message text information in sbd_ioctl.h.
6077c478bd9Sstevel@tonic-gate  */
6087c478bd9Sstevel@tonic-gate static char *
mod_estr(int code)6097c478bd9Sstevel@tonic-gate mod_estr(int code)
6107c478bd9Sstevel@tonic-gate {
6117c478bd9Sstevel@tonic-gate 	int i;
6127c478bd9Sstevel@tonic-gate 	char *s;
6137c478bd9Sstevel@tonic-gate 	extern sbd_etab_t sbd_etab[];
6147c478bd9Sstevel@tonic-gate 	extern int sbd_etab_len;
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	s = NULL;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	for (i = 0; i < sbd_etab_len; i++) {
6197c478bd9Sstevel@tonic-gate 		sbd_etab_t *eptr = &sbd_etab[i];
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 		if ((code >= eptr->t_base) && (code <= eptr->t_bnd)) {
6227c478bd9Sstevel@tonic-gate 			int index;
6237c478bd9Sstevel@tonic-gate 			char **t_text;
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 			/*
6267c478bd9Sstevel@tonic-gate 			 * Found it. Just extract the string
6277c478bd9Sstevel@tonic-gate 			 */
6287c478bd9Sstevel@tonic-gate 			index = code - eptr->t_base;
6297c478bd9Sstevel@tonic-gate 			t_text = eptr->t_text;
6307c478bd9Sstevel@tonic-gate 			s = strdup(t_text[index]);
6317c478bd9Sstevel@tonic-gate 			break;
6327c478bd9Sstevel@tonic-gate 		}
6337c478bd9Sstevel@tonic-gate 	}
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	if (i == sbd_etab_len) {
6367c478bd9Sstevel@tonic-gate 		char buf[32];
6377c478bd9Sstevel@tonic-gate 
638a3114836SGerry Liu 		(void) snprintf(buf, sizeof (buf), "error %d", code);
6397c478bd9Sstevel@tonic-gate 		s = strdup(buf);
6407c478bd9Sstevel@tonic-gate 	}
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	return (s);
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate char *
ap_sys_err(apd_t * a,char ** rp)6467c478bd9Sstevel@tonic-gate ap_sys_err(apd_t *a, char **rp)
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate 	int code;
6497c478bd9Sstevel@tonic-gate 	char *p;
6507c478bd9Sstevel@tonic-gate 	char *rsc;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	sbd_ioctl_arg_t *ctl = (sbd_ioctl_arg_t *)a->ctl;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	/*
6557c478bd9Sstevel@tonic-gate 	 * The driver sets the errno to EIO if it returns
6567c478bd9Sstevel@tonic-gate 	 * more detailed error info via e_code.  In all
6577c478bd9Sstevel@tonic-gate 	 * other cases, use standard error text.
6587c478bd9Sstevel@tonic-gate 	 */
6597c478bd9Sstevel@tonic-gate 	if (ctl == NULL || errno != EIO) {
6607c478bd9Sstevel@tonic-gate 		if ((p = strerror(errno)) != NULL)
6617c478bd9Sstevel@tonic-gate 			p = strdup(p);
6627c478bd9Sstevel@tonic-gate 		return (p);
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	code = ctl->ie_code;
6667c478bd9Sstevel@tonic-gate 	rsc = ctl->ie_rsc;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (code)
6697c478bd9Sstevel@tonic-gate 		p = mod_estr(code);
6707c478bd9Sstevel@tonic-gate 	else if ((p = strerror(errno)) != NULL)
6717c478bd9Sstevel@tonic-gate 		p = strdup(p);
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	if (*rsc != '\0' && rp != NULL)
6747c478bd9Sstevel@tonic-gate 		*rp = strdup(rsc);
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	return (p);
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate /*
6807c478bd9Sstevel@tonic-gate  * cfgadm -o err=plugin-err,cmd=name,code=ecode -x errtest ap_id.
6817c478bd9Sstevel@tonic-gate  */
6827c478bd9Sstevel@tonic-gate cfga_err_t
ap_test_err(apd_t * a,const char * options)6837c478bd9Sstevel@tonic-gate ap_test_err(apd_t *a, const char *options)
6847c478bd9Sstevel@tonic-gate {
6857c478bd9Sstevel@tonic-gate 	int err;
6867c478bd9Sstevel@tonic-gate 	int cmd;
6877c478bd9Sstevel@tonic-gate 	ap_opts_t *opts;
6887c478bd9Sstevel@tonic-gate 	sbd_ioctl_arg_t ctl;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	opts = &a->opts;
6917c478bd9Sstevel@tonic-gate 	err = opts->err;
6927c478bd9Sstevel@tonic-gate 	cmd = CMD_DISCONNECT;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	DBG("ap_test_err(%d %d)\n", opts->code, opts->err);
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	switch (err) {
6977c478bd9Sstevel@tonic-gate 	case ERR_CMD_INVAL:
6987c478bd9Sstevel@tonic-gate 		ap_err(a, err, ap_cmd_name(cmd));
6997c478bd9Sstevel@tonic-gate 		break;
7007c478bd9Sstevel@tonic-gate 	case ERR_CMD_NOTSUPP:
7017c478bd9Sstevel@tonic-gate 		ap_err(a, err, cmd);
7027c478bd9Sstevel@tonic-gate 		break;
7037c478bd9Sstevel@tonic-gate 	case ERR_CMD_FAIL:
7047c478bd9Sstevel@tonic-gate 		errno = EIO;
7057c478bd9Sstevel@tonic-gate 		ctl.i_err.e_code = opts->code;
7067c478bd9Sstevel@tonic-gate 		*ctl.i_err.e_rsc = '\0';
7077c478bd9Sstevel@tonic-gate 		a->ctl = &ctl;
7087c478bd9Sstevel@tonic-gate 		ap_err(a, err, cmd);
7097c478bd9Sstevel@tonic-gate 		a->ctl = NULL;
7107c478bd9Sstevel@tonic-gate 		break;
7117c478bd9Sstevel@tonic-gate 	case ERR_OPT_INVAL:
7127c478bd9Sstevel@tonic-gate 		ap_err(a, err, options);
7137c478bd9Sstevel@tonic-gate 		break;
7147c478bd9Sstevel@tonic-gate 	case ERR_OPT_NOVAL:
7157c478bd9Sstevel@tonic-gate 		ap_err(a, err, options);
7167c478bd9Sstevel@tonic-gate 		break;
7177c478bd9Sstevel@tonic-gate 	case ERR_AP_INVAL:
7187c478bd9Sstevel@tonic-gate 		ap_err(a, err);
7197c478bd9Sstevel@tonic-gate 		break;
7207c478bd9Sstevel@tonic-gate 	case ERR_CM_INVAL:
7217c478bd9Sstevel@tonic-gate 		ap_err(a, err, a->cid);
7227c478bd9Sstevel@tonic-gate 		break;
7237c478bd9Sstevel@tonic-gate 	case ERR_TRANS_INVAL:
7247c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_TRANS_INVAL, cmd);
7257c478bd9Sstevel@tonic-gate 		break;
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	return (CFGA_LIB_ERROR);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate static char *
7327c478bd9Sstevel@tonic-gate ap_help_topics[] = {
7337c478bd9Sstevel@tonic-gate 	"\nSbd specific commands/options:\n\n",
7347c478bd9Sstevel@tonic-gate 	"\tcfgadm [-o parsable] -l ap_id\n",
7357c478bd9Sstevel@tonic-gate 	"\tcfgadm [-o unassign|nopoweroff] -c disconnect ap_id\n",
7367c478bd9Sstevel@tonic-gate 	"\tcfgadm -t ap_id\n",
7377c478bd9Sstevel@tonic-gate 	"\tcfgadm -x assign ap_id\n",
7387c478bd9Sstevel@tonic-gate 	"\tcfgadm -x unassign ap_id\n",
7397c478bd9Sstevel@tonic-gate 	"\tcfgadm -x poweron ap_id\n",
7407c478bd9Sstevel@tonic-gate 	"\tcfgadm -x poweroff ap_id\n",
7417c478bd9Sstevel@tonic-gate 	NULL
7427c478bd9Sstevel@tonic-gate };
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7457c478bd9Sstevel@tonic-gate cfga_err_t
ap_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)7467c478bd9Sstevel@tonic-gate ap_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
7477c478bd9Sstevel@tonic-gate {
7487c478bd9Sstevel@tonic-gate 	int len;
7497c478bd9Sstevel@tonic-gate 	char **p;
7507c478bd9Sstevel@tonic-gate 	char *q;
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	if (msgp == NULL || msgp->message_routine == NULL)
7537c478bd9Sstevel@tonic-gate 		return (CFGA_OK);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	for (p = ap_help_topics; *p != NULL; p++) {
7567c478bd9Sstevel@tonic-gate 		if ((len = strlen(*p)) == 0)
7577c478bd9Sstevel@tonic-gate 			continue;
7587c478bd9Sstevel@tonic-gate 		if ((q = (char *)calloc(len + 1, 1)) == NULL)
7597c478bd9Sstevel@tonic-gate 			continue;
760a3114836SGerry Liu 		(void) strcpy(q, *p);
7617c478bd9Sstevel@tonic-gate 		(*msgp->message_routine)(msgp->appdata_ptr, q);
7627c478bd9Sstevel@tonic-gate 		free(q);
7637c478bd9Sstevel@tonic-gate 	}
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	return (CFGA_OK);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate static char *
ap_dev_type(sbd_dev_stat_t * dst)7697c478bd9Sstevel@tonic-gate ap_dev_type(sbd_dev_stat_t *dst)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	char *type;
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 	switch (dst->ds_type) {
7747c478bd9Sstevel@tonic-gate 	case SBD_COMP_CPU:
7757c478bd9Sstevel@tonic-gate 		type = "cpu";
7767c478bd9Sstevel@tonic-gate 		break;
7777c478bd9Sstevel@tonic-gate 	case SBD_COMP_MEM:
7787c478bd9Sstevel@tonic-gate 		type = "memory";
7797c478bd9Sstevel@tonic-gate 		break;
7807c478bd9Sstevel@tonic-gate 	case SBD_COMP_IO:
7817c478bd9Sstevel@tonic-gate 		type = "io";
7827c478bd9Sstevel@tonic-gate 		break;
7837c478bd9Sstevel@tonic-gate 	case SBD_COMP_CMP:
7847c478bd9Sstevel@tonic-gate 		type = "cpu";
7857c478bd9Sstevel@tonic-gate 		break;
7867c478bd9Sstevel@tonic-gate 	default:
7877c478bd9Sstevel@tonic-gate 		type = "other";
7887c478bd9Sstevel@tonic-gate 		break;
7897c478bd9Sstevel@tonic-gate 	}
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	DBG("ap_dev_type(%d)=%s\n", dst->ds_type, type);
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	return (type);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate static sbd_dev_stat_t *
ap_cm_stat(apd_t * a,int seq)7977c478bd9Sstevel@tonic-gate ap_cm_stat(apd_t *a, int seq)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	if (seq == CM_DFLT)
8027c478bd9Sstevel@tonic-gate 		return (a->cmstat);
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
8057c478bd9Sstevel@tonic-gate 	return (st->s_stat + seq);
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate char *
ap_cm_devpath(apd_t * a,int seq)8097c478bd9Sstevel@tonic-gate ap_cm_devpath(apd_t *a, int seq)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	int len;
8127c478bd9Sstevel@tonic-gate 	char *path;
8137c478bd9Sstevel@tonic-gate 	char *devpath;
8147c478bd9Sstevel@tonic-gate 	sbd_io_stat_t *dst;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	/*
8187c478bd9Sstevel@tonic-gate 	 * If no component sequence number is provided
8197c478bd9Sstevel@tonic-gate 	 * default to the current target component.
8207c478bd9Sstevel@tonic-gate 	 * Assume an io component so that we can get
8217c478bd9Sstevel@tonic-gate 	 * the path if the component is indeed of type io.
8227c478bd9Sstevel@tonic-gate 	 */
823a3114836SGerry Liu 	if (seq == CM_DFLT)
8247c478bd9Sstevel@tonic-gate 		dst = (sbd_io_stat_t *)a->cmstat;
8257c478bd9Sstevel@tonic-gate 	else {
8267c478bd9Sstevel@tonic-gate 		sbd_stat_t *st;
8277c478bd9Sstevel@tonic-gate 		st = (sbd_stat_t *)a->stat;
8287c478bd9Sstevel@tonic-gate 		dst = (sbd_io_stat_t *)st->s_stat + seq;
8297c478bd9Sstevel@tonic-gate 	}
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	if (dst->is_type != SBD_COMP_IO)
8327c478bd9Sstevel@tonic-gate 		path = NULL;
8337c478bd9Sstevel@tonic-gate 	else
8347c478bd9Sstevel@tonic-gate 		path = dst->is_pathname;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	if (str_valid(path)) {
8377c478bd9Sstevel@tonic-gate 		len = strlen(DEVDIR) + strlen(path) + 1;
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 		if ((devpath = calloc(1, len)) == NULL)
8407c478bd9Sstevel@tonic-gate 			return (NULL);
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 		(void) snprintf(devpath, len, "%s%s", DEVDIR, path);
8437c478bd9Sstevel@tonic-gate 	} else
8447c478bd9Sstevel@tonic-gate 		devpath = NULL;
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	DBG("ap_cm_path(%d)=%s\n", seq, devpath ? devpath : "");
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	return (devpath);
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate void
ap_cm_id(apd_t * a,int seq,char * id,size_t bufsize)8527c478bd9Sstevel@tonic-gate ap_cm_id(apd_t *a, int seq, char *id, size_t bufsize)
8537c478bd9Sstevel@tonic-gate {
8547c478bd9Sstevel@tonic-gate 	int unit;
8557c478bd9Sstevel@tonic-gate 	char *name;
8567c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	unit = dst->ds_unit;
8617c478bd9Sstevel@tonic-gate 	name = dst->ds_name;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	/*
8647c478bd9Sstevel@tonic-gate 	 * If the component has a unit number,
8657c478bd9Sstevel@tonic-gate 	 * add it to the id, otherwise just use
8667c478bd9Sstevel@tonic-gate 	 * the component's name.
8677c478bd9Sstevel@tonic-gate 	 */
8687c478bd9Sstevel@tonic-gate 	if (unit == -1)
8697c478bd9Sstevel@tonic-gate 		(void) snprintf(id, bufsize, "%s", name);
8707c478bd9Sstevel@tonic-gate 	else
8717c478bd9Sstevel@tonic-gate 		(void) snprintf(id, bufsize, "%s%d", name, unit);
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	DBG("ap_cm_id(%d)=%s\n", seq, id);
8747c478bd9Sstevel@tonic-gate }
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate /*
8777c478bd9Sstevel@tonic-gate  * Convert a component to a target type.
8787c478bd9Sstevel@tonic-gate  */
8797c478bd9Sstevel@tonic-gate ap_target_t
ap_cm_type(apd_t * a,int seq)8807c478bd9Sstevel@tonic-gate ap_cm_type(apd_t *a, int seq)
8817c478bd9Sstevel@tonic-gate {
8827c478bd9Sstevel@tonic-gate 	ap_target_t c;
8837c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	switch (dst->ds_type) {
8887c478bd9Sstevel@tonic-gate 	case SBD_COMP_CPU:
8897c478bd9Sstevel@tonic-gate 		c = AP_CPU;
8907c478bd9Sstevel@tonic-gate 		break;
8917c478bd9Sstevel@tonic-gate 	case SBD_COMP_MEM:
8927c478bd9Sstevel@tonic-gate 		c = AP_MEM;
8937c478bd9Sstevel@tonic-gate 		break;
8947c478bd9Sstevel@tonic-gate 	case SBD_COMP_IO:
8957c478bd9Sstevel@tonic-gate 		c = AP_IO;
8967c478bd9Sstevel@tonic-gate 		break;
8977c478bd9Sstevel@tonic-gate 	case SBD_COMP_CMP:
8987c478bd9Sstevel@tonic-gate 		c = AP_CMP;
8997c478bd9Sstevel@tonic-gate 		break;
9007c478bd9Sstevel@tonic-gate 	default:
9017c478bd9Sstevel@tonic-gate 		c = AP_NONE;
9027c478bd9Sstevel@tonic-gate 		break;
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	return (c);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate int
ap_cm_ncap(apd_t * a,int seq)9097c478bd9Sstevel@tonic-gate ap_cm_ncap(apd_t *a, int seq)
9107c478bd9Sstevel@tonic-gate {
9117c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t	*dst;
9127c478bd9Sstevel@tonic-gate 	int		ncap;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	switch (dst->ds_type) {
9177c478bd9Sstevel@tonic-gate 	case SBD_COMP_CPU:
9187c478bd9Sstevel@tonic-gate 	case SBD_COMP_MEM:
9197c478bd9Sstevel@tonic-gate 	case SBD_COMP_IO:
9207c478bd9Sstevel@tonic-gate 		ncap = 1;
9217c478bd9Sstevel@tonic-gate 		break;
9227c478bd9Sstevel@tonic-gate 	case SBD_COMP_CMP:
9237c478bd9Sstevel@tonic-gate 		ncap = ((sbd_cmp_stat_t *)dst)->ps_ncores;
9247c478bd9Sstevel@tonic-gate 		break;
9257c478bd9Sstevel@tonic-gate 	default:
9267c478bd9Sstevel@tonic-gate 		ncap = 0;
9277c478bd9Sstevel@tonic-gate 		break;
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	return (ncap);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate int
ap_cm_capacity(apd_t * a,int seq,void * cap,int * ncap,cfga_stat_t * ostate)9347c478bd9Sstevel@tonic-gate ap_cm_capacity(apd_t *a, int seq, void *cap, int *ncap, cfga_stat_t *ostate)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	int i;
9377c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
9387c478bd9Sstevel@tonic-gate 	cfga_stat_t os;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	if (cap == NULL)
9417c478bd9Sstevel@tonic-gate 		return (0);
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	dst = ap_cm_stat(a, seq);
9447c478bd9Sstevel@tonic-gate 	os = (cfga_stat_t)dst->ds_ostate;
9457c478bd9Sstevel@tonic-gate 	if (os != CFGA_STAT_CONFIGURED && os != CFGA_STAT_UNCONFIGURED)
9467c478bd9Sstevel@tonic-gate 		return (0);
9477c478bd9Sstevel@tonic-gate 	if (ostate)
9487c478bd9Sstevel@tonic-gate 		*ostate = os;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	*ncap = 1;
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 	switch (dst->ds_type) {
9537c478bd9Sstevel@tonic-gate 	case SBD_COMP_CPU: {
9547c478bd9Sstevel@tonic-gate 		sbd_cpu_stat_t *cpu = (sbd_cpu_stat_t *)dst;
9557c478bd9Sstevel@tonic-gate 		*((processorid_t *)cap) = cpu->cs_cpuid;
9567c478bd9Sstevel@tonic-gate 		break;
9577c478bd9Sstevel@tonic-gate 	}
9587c478bd9Sstevel@tonic-gate 	case SBD_COMP_MEM: {
9597c478bd9Sstevel@tonic-gate 		sbd_mem_stat_t *mem = (sbd_mem_stat_t *)dst;
9607c478bd9Sstevel@tonic-gate 		*((long *)cap) = mem->ms_totpages;
9617c478bd9Sstevel@tonic-gate 		break;
9627c478bd9Sstevel@tonic-gate 	}
9637c478bd9Sstevel@tonic-gate 	case SBD_COMP_CMP: {
9647c478bd9Sstevel@tonic-gate 		sbd_cmp_stat_t	*cmp = (sbd_cmp_stat_t *)dst;
9657c478bd9Sstevel@tonic-gate 		processorid_t	*cpuid;
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 		cpuid = (processorid_t *)cap;
9687c478bd9Sstevel@tonic-gate 		for (i = 0; i < cmp->ps_ncores; i++) {
9697c478bd9Sstevel@tonic-gate 			cpuid[i] = cmp->ps_cpuid[i];
9707c478bd9Sstevel@tonic-gate 		}
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		*ncap = cmp->ps_ncores;
9737c478bd9Sstevel@tonic-gate 		break;
9747c478bd9Sstevel@tonic-gate 	}
9757c478bd9Sstevel@tonic-gate 	default:
9767c478bd9Sstevel@tonic-gate 		return (0);
9777c478bd9Sstevel@tonic-gate 	}
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	DBG("ap_cm_capacity(%d)=(", seq);
9807c478bd9Sstevel@tonic-gate 	for (i = 0; i < *ncap; i++) {
9817c478bd9Sstevel@tonic-gate 		DBG("%d ", ((int *)cap)[i]);
9827c478bd9Sstevel@tonic-gate 	}
9837c478bd9Sstevel@tonic-gate 	DBG("%d)\n", *ostate);
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	return (1);
9867c478bd9Sstevel@tonic-gate }
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate void
ap_cm_init(apd_t * a,cfga_list_data_t * ap,int seq)9897c478bd9Sstevel@tonic-gate ap_cm_init(apd_t *a, cfga_list_data_t *ap, int seq)
9907c478bd9Sstevel@tonic-gate {
9917c478bd9Sstevel@tonic-gate 	char *type;
9927c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
9937c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
9967c478bd9Sstevel@tonic-gate 	dst = st->s_stat + seq;
9977c478bd9Sstevel@tonic-gate 	type = ap_dev_type(dst);
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	a->cmstat = (void *)dst;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	DBG("ap_cm_init bd=%d rs=%d os=%d type=<%s> seq=%d\n",
10027c478bd9Sstevel@tonic-gate 	    a->bnum, st->s_rstate, dst->ds_ostate, type, seq);
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	(void) strncpy(ap->ap_type, type, sizeof (ap->ap_type));
10057c478bd9Sstevel@tonic-gate 	ap->ap_r_state = (cfga_stat_t)st->s_rstate;
10067c478bd9Sstevel@tonic-gate 	ap->ap_o_state = (cfga_stat_t)dst->ds_ostate;
10077c478bd9Sstevel@tonic-gate 	ap->ap_cond = (cfga_cond_t)dst->ds_cond;
10087c478bd9Sstevel@tonic-gate 	ap->ap_busy = (cfga_busy_t)dst->ds_busy;
10097c478bd9Sstevel@tonic-gate 	ap->ap_status_time = dst->ds_time;
10107c478bd9Sstevel@tonic-gate 	ap_info(a, ap->ap_info, ap_cm_tgt(dst->ds_type));
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate void
ap_state(apd_t * a,cfga_stat_t * rs,cfga_stat_t * os)10147c478bd9Sstevel@tonic-gate ap_state(apd_t *a, cfga_stat_t *rs, cfga_stat_t *os)
10157c478bd9Sstevel@tonic-gate {
10167c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
10177c478bd9Sstevel@tonic-gate 	sbd_dev_stat_t *dst;
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
10207c478bd9Sstevel@tonic-gate 	dst = (sbd_dev_stat_t *)a->cmstat;
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	if (rs != NULL) {
10237c478bd9Sstevel@tonic-gate 		if (a->tgt == AP_NONE)
10247c478bd9Sstevel@tonic-gate 			*rs = CFGA_STAT_NONE;
10257c478bd9Sstevel@tonic-gate 		else
10267c478bd9Sstevel@tonic-gate 			*rs = (cfga_stat_t)st->s_rstate;
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	if (os != NULL) {
10307c478bd9Sstevel@tonic-gate 		if (a->tgt == AP_NONE)
10317c478bd9Sstevel@tonic-gate 			*os = CFGA_STAT_NONE;
10327c478bd9Sstevel@tonic-gate 		else if (a->tgt == AP_BOARD)
10337c478bd9Sstevel@tonic-gate 			*os = (cfga_stat_t)st->s_ostate;
10347c478bd9Sstevel@tonic-gate 		else
10357c478bd9Sstevel@tonic-gate 			*os = (cfga_stat_t)dst->ds_ostate;
10367c478bd9Sstevel@tonic-gate 	}
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate #define	BI_POWERED		0
10407c478bd9Sstevel@tonic-gate #define	BI_ASSIGNED		1
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate static const char *
10437c478bd9Sstevel@tonic-gate binfo[] = {
10447c478bd9Sstevel@tonic-gate 	"powered-on",
10457c478bd9Sstevel@tonic-gate 	", assigned"
10467c478bd9Sstevel@tonic-gate };
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate static const char *
10497c478bd9Sstevel@tonic-gate binfo_parsable[] = {
10507c478bd9Sstevel@tonic-gate 	"powered-on",
10517c478bd9Sstevel@tonic-gate 	" assigned"
10527c478bd9Sstevel@tonic-gate };
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate static void
bd_info(apd_t * a,cfga_info_t info,int parsable)10557c478bd9Sstevel@tonic-gate bd_info(apd_t *a, cfga_info_t info, int parsable)
10567c478bd9Sstevel@tonic-gate {
10577c478bd9Sstevel@tonic-gate 	int i;
10587c478bd9Sstevel@tonic-gate 	int nsep;
10597c478bd9Sstevel@tonic-gate 	const char **p;
10607c478bd9Sstevel@tonic-gate 	sbd_stat_t *st;
10617c478bd9Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 	DBG("bd_info(%p)\n", (void *)info);
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 	st = (sbd_stat_t *)a->stat;
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	if (parsable) {
10687c478bd9Sstevel@tonic-gate 		p = binfo_parsable;
10697c478bd9Sstevel@tonic-gate 		nsep = 1;
10707c478bd9Sstevel@tonic-gate 	} else {
10717c478bd9Sstevel@tonic-gate 		p = binfo;
10727c478bd9Sstevel@tonic-gate 		nsep = 2;
10737c478bd9Sstevel@tonic-gate 	}
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	i = nsep;
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	if (st->s_power) {
10787c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[BI_POWERED]);
10797c478bd9Sstevel@tonic-gate 		i = 0;
10807c478bd9Sstevel@tonic-gate 	}
10817c478bd9Sstevel@tonic-gate 	if (st->s_assigned)
10827c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[BI_ASSIGNED] + i);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate #define	CI_CPUID		0
10867c478bd9Sstevel@tonic-gate #define	CI_SPEED		1
10877c478bd9Sstevel@tonic-gate #define	CI_ECACHE		2
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate static const char *
10907c478bd9Sstevel@tonic-gate cpuinfo[] = {
10917c478bd9Sstevel@tonic-gate 	"cpuid %d",
10927c478bd9Sstevel@tonic-gate 	", speed %d MHz",
10937c478bd9Sstevel@tonic-gate 	", ecache %d MBytes"
10947c478bd9Sstevel@tonic-gate };
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate static const char *
10977c478bd9Sstevel@tonic-gate cpuinfo_parsable[] = {
10987c478bd9Sstevel@tonic-gate 	"cpuid=%d",
10997c478bd9Sstevel@tonic-gate 	" speed=%d",
11007c478bd9Sstevel@tonic-gate 	" ecache=%d"
11017c478bd9Sstevel@tonic-gate };
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate static void
cpu_info(apd_t * a,cfga_info_t info,int parsable)11047c478bd9Sstevel@tonic-gate cpu_info(apd_t *a, cfga_info_t info, int parsable)
11057c478bd9Sstevel@tonic-gate {
11067c478bd9Sstevel@tonic-gate 	const char **p;
11077c478bd9Sstevel@tonic-gate 	sbd_cpu_stat_t *dst;
11087c478bd9Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	DBG("cpu_info(%p)\n", (void *)info);
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	dst = (sbd_cpu_stat_t *)a->cmstat;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 	if (parsable)
11157c478bd9Sstevel@tonic-gate 		p = cpuinfo_parsable;
11167c478bd9Sstevel@tonic-gate 	else
11177c478bd9Sstevel@tonic-gate 		p = cpuinfo;
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_CPUID], dst->cs_cpuid);
11207c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_SPEED], dst->cs_speed);
11217c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[CI_ECACHE], dst->cs_ecache);
11227c478bd9Sstevel@tonic-gate }
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate #define	MI_ADDRESS		0
11257c478bd9Sstevel@tonic-gate #define	MI_SIZE			1
11267c478bd9Sstevel@tonic-gate #define	MI_PERMANENT		2
11277c478bd9Sstevel@tonic-gate #define	MI_UNCONFIGURABLE	3
11287c478bd9Sstevel@tonic-gate #define	MI_SOURCE		4
11297c478bd9Sstevel@tonic-gate #define	MI_TARGET		5
11307c478bd9Sstevel@tonic-gate #define	MI_DELETED		6
11317c478bd9Sstevel@tonic-gate #define	MI_REMAINING		7
11327c478bd9Sstevel@tonic-gate #define	MI_INTERLEAVE		8
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate static const char *
11357c478bd9Sstevel@tonic-gate meminfo_nonparsable[] = {
11367c478bd9Sstevel@tonic-gate 	"base address 0x%" PRIx64,
11377c478bd9Sstevel@tonic-gate 	", %lu KBytes total",
11387c478bd9Sstevel@tonic-gate 	", %lu KBytes permanent",
11397c478bd9Sstevel@tonic-gate 	", unconfigurable",
11407c478bd9Sstevel@tonic-gate 	", memory delete requested on %s",
11417c478bd9Sstevel@tonic-gate 	", memory delete in progress on %s",
11427c478bd9Sstevel@tonic-gate 	", %lu KBytes deleted",
11437c478bd9Sstevel@tonic-gate 	", %lu KBytes remaining",
11447c478bd9Sstevel@tonic-gate 	", inter board interleave"
11457c478bd9Sstevel@tonic-gate };
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate static const char *
11487c478bd9Sstevel@tonic-gate meminfo_parsable[] = {
11497c478bd9Sstevel@tonic-gate 	"address=0x%" PRIx64,
11507c478bd9Sstevel@tonic-gate 	" size=%lu",
11517c478bd9Sstevel@tonic-gate 	" permanent=%lu",
11527c478bd9Sstevel@tonic-gate 	" unconfigurable",
11537c478bd9Sstevel@tonic-gate 	" source=%s",
11547c478bd9Sstevel@tonic-gate 	" target=%s",
11557c478bd9Sstevel@tonic-gate 	" deleted=%lu",
11567c478bd9Sstevel@tonic-gate 	" remaining=%lu",
11577c478bd9Sstevel@tonic-gate 	" inter-board-interleave"
11587c478bd9Sstevel@tonic-gate };
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate #define	_K1	1024
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate /*
11647c478bd9Sstevel@tonic-gate  * This function assumes pagesize > 1024 and that
11657c478bd9Sstevel@tonic-gate  * pagesize is a multiple of 1024.
11667c478bd9Sstevel@tonic-gate  */
11677c478bd9Sstevel@tonic-gate static ulong_t
pages_to_kbytes(uint_t pgs)11687c478bd9Sstevel@tonic-gate pages_to_kbytes(uint_t pgs)
11697c478bd9Sstevel@tonic-gate {
11707c478bd9Sstevel@tonic-gate 	long pagesize;
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
11737c478bd9Sstevel@tonic-gate 	return (pgs * (pagesize / _K1));
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate static uint64_t
pages_to_bytes(uint_t pgs)11777c478bd9Sstevel@tonic-gate pages_to_bytes(uint_t pgs)
11787c478bd9Sstevel@tonic-gate {
11797c478bd9Sstevel@tonic-gate 	long pagesize;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
11827c478bd9Sstevel@tonic-gate 	return ((uint64_t)pgs * pagesize);
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate static void
mem_info(apd_t * a,cfga_info_t info,int parsable)11867c478bd9Sstevel@tonic-gate mem_info(apd_t *a, cfga_info_t info, int parsable)
11877c478bd9Sstevel@tonic-gate {
11887c478bd9Sstevel@tonic-gate 	const char **p;
11897c478bd9Sstevel@tonic-gate 	sbd_mem_stat_t *dst;
11907c478bd9Sstevel@tonic-gate 	int want_progress;
11917c478bd9Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 	DBG("mem_info(%p)\n", (void *)info);
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	dst = (sbd_mem_stat_t *)a->cmstat;
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	if (parsable)
11987c478bd9Sstevel@tonic-gate 		p = meminfo_parsable;
11997c478bd9Sstevel@tonic-gate 	else
12007c478bd9Sstevel@tonic-gate 		p = meminfo_nonparsable;
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[MI_ADDRESS],
12037c478bd9Sstevel@tonic-gate 	    pages_to_bytes(dst->ms_basepfn));
12047c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[MI_SIZE],
12057c478bd9Sstevel@tonic-gate 	    pages_to_kbytes(dst->ms_totpages));
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	if (dst->ms_noreloc_pages)
12087c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_PERMANENT],
12097c478bd9Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_noreloc_pages));
12107c478bd9Sstevel@tonic-gate 	if (!dst->ms_cage_enabled)
12117c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_UNCONFIGURABLE]);
12127c478bd9Sstevel@tonic-gate 	if (dst->ms_interleave)
12137c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_INTERLEAVE]);
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	/*
12167c478bd9Sstevel@tonic-gate 	 * If there is a valid peer physical ap_id specified,
12177c478bd9Sstevel@tonic-gate 	 * convert it to a logical id.
12187c478bd9Sstevel@tonic-gate 	 */
12197c478bd9Sstevel@tonic-gate 	want_progress = 0;
12207c478bd9Sstevel@tonic-gate 	if (str_valid(dst->ms_peer_ap_id)) {
12217c478bd9Sstevel@tonic-gate 		char *cm;
12227c478bd9Sstevel@tonic-gate 		char *peer;
12237c478bd9Sstevel@tonic-gate 		char physid[MAXPATHLEN];
12247c478bd9Sstevel@tonic-gate 		char logid[MAXPATHLEN];
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 		(void) snprintf(physid, sizeof (physid), "%s%s",
12277c478bd9Sstevel@tonic-gate 		    DEVDIR, dst->ms_peer_ap_id);
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 		/*
12307c478bd9Sstevel@tonic-gate 		 * Save the component portion of the physid and
12317c478bd9Sstevel@tonic-gate 		 * add it back after converting to logical format.
12327c478bd9Sstevel@tonic-gate 		 */
12337c478bd9Sstevel@tonic-gate 		if ((cm = strstr(physid, "::")) != NULL) {
12347c478bd9Sstevel@tonic-gate 			*cm = '\0';
12357c478bd9Sstevel@tonic-gate 			cm += 2;
12367c478bd9Sstevel@tonic-gate 		}
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 		/* attempt to resolve to symlink */
12397c478bd9Sstevel@tonic-gate 		if (ap_symid(a, physid, logid, sizeof (logid)) == 0)
12407c478bd9Sstevel@tonic-gate 			peer = logid;
12417c478bd9Sstevel@tonic-gate 		else
12427c478bd9Sstevel@tonic-gate 			peer = physid;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		if (dst->ms_peer_is_target) {
12457c478bd9Sstevel@tonic-gate 			info += snprintf(info, end - info, p[MI_TARGET], peer);
12467c478bd9Sstevel@tonic-gate 			if (cm)
12477c478bd9Sstevel@tonic-gate 				info += snprintf(info, end - info, "::%s", cm);
12487c478bd9Sstevel@tonic-gate 			want_progress = 1;
12497c478bd9Sstevel@tonic-gate 		} else {
12507c478bd9Sstevel@tonic-gate 			info += snprintf(info, end - info, p[MI_SOURCE], peer);
12517c478bd9Sstevel@tonic-gate 			if (cm)
12527c478bd9Sstevel@tonic-gate 				info += snprintf(info, end - info, "::%s", cm);
12537c478bd9Sstevel@tonic-gate 		}
12547c478bd9Sstevel@tonic-gate 	}
12557c478bd9Sstevel@tonic-gate 	if (want_progress ||
12567c478bd9Sstevel@tonic-gate 	    (dst->ms_detpages != 0 && dst->ms_detpages != dst->ms_totpages)) {
12577c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_DELETED],
12587c478bd9Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_detpages));
12597c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[MI_REMAINING],
12607c478bd9Sstevel@tonic-gate 		    pages_to_kbytes(dst->ms_totpages -
12617c478bd9Sstevel@tonic-gate 		    dst->ms_detpages));
12627c478bd9Sstevel@tonic-gate 	}
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate #define	II_DEVICE		0
12667c478bd9Sstevel@tonic-gate #define	II_REFERENCED		1
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate static const char *
12697c478bd9Sstevel@tonic-gate ioinfo[] = {
12707c478bd9Sstevel@tonic-gate 	"device %s",
12717c478bd9Sstevel@tonic-gate 	", referenced"
12727c478bd9Sstevel@tonic-gate };
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate static const char *
12757c478bd9Sstevel@tonic-gate ioinfo_parsable[] = {
12767c478bd9Sstevel@tonic-gate 	"device=%s",
12777c478bd9Sstevel@tonic-gate 	" referenced"
12787c478bd9Sstevel@tonic-gate };
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate static void
io_info(apd_t * a,cfga_info_t info,int parsable)12817c478bd9Sstevel@tonic-gate io_info(apd_t *a, cfga_info_t info, int parsable)
12827c478bd9Sstevel@tonic-gate {
12837c478bd9Sstevel@tonic-gate 	const char **p;
12847c478bd9Sstevel@tonic-gate 	sbd_io_stat_t *dst;
12857c478bd9Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 	dst = (sbd_io_stat_t *)a->cmstat;
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	if (parsable)
12907c478bd9Sstevel@tonic-gate 		p = ioinfo_parsable;
12917c478bd9Sstevel@tonic-gate 	else
12927c478bd9Sstevel@tonic-gate 		p = ioinfo;
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[II_DEVICE], dst->is_pathname);
12957c478bd9Sstevel@tonic-gate 	if (dst->is_referenced)
12967c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[II_REFERENCED]);
12977c478bd9Sstevel@tonic-gate }
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate #define	PI_CPUID		0
13007c478bd9Sstevel@tonic-gate #define	PI_CPUID_PAIR		1
13017c478bd9Sstevel@tonic-gate #define	PI_CPUID_CONT		2
13027c478bd9Sstevel@tonic-gate #define	PI_CPUID_LAST		3
13037c478bd9Sstevel@tonic-gate #define	PI_SPEED		4
13047c478bd9Sstevel@tonic-gate #define	PI_ECACHE		5
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate static const char *
13077c478bd9Sstevel@tonic-gate cmpinfo[] = {
13087c478bd9Sstevel@tonic-gate 	"cpuid %d",
13097c478bd9Sstevel@tonic-gate 	" and %d",
13107c478bd9Sstevel@tonic-gate 	", %d",
13117c478bd9Sstevel@tonic-gate 	", and %d",
13127c478bd9Sstevel@tonic-gate 	", speed %d MHz",
13137c478bd9Sstevel@tonic-gate 	", ecache %d MBytes"
13147c478bd9Sstevel@tonic-gate };
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate static const char *
13177c478bd9Sstevel@tonic-gate cmpinfo_parsable[] = {
13187c478bd9Sstevel@tonic-gate 	"cpuid=%d",
13197c478bd9Sstevel@tonic-gate 	",%d",
13207c478bd9Sstevel@tonic-gate 	",%d",
13217c478bd9Sstevel@tonic-gate 	",%d",
13227c478bd9Sstevel@tonic-gate 	" speed=%d",
13237c478bd9Sstevel@tonic-gate 	" ecache=%d"
13247c478bd9Sstevel@tonic-gate };
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate static void
cmp_info(apd_t * a,cfga_info_t info,int parsable)13277c478bd9Sstevel@tonic-gate cmp_info(apd_t *a, cfga_info_t info, int parsable)
13287c478bd9Sstevel@tonic-gate {
13297c478bd9Sstevel@tonic-gate 	int		i;
13307c478bd9Sstevel@tonic-gate 	int		last;
13317c478bd9Sstevel@tonic-gate 	const char	**p;
13327c478bd9Sstevel@tonic-gate 	sbd_cmp_stat_t	*dst;
13337c478bd9Sstevel@tonic-gate 	char *end = &info[sizeof (cfga_info_t)];
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 	DBG("cmp_info(%p)\n", (void *)info);
13367c478bd9Sstevel@tonic-gate 
13377c478bd9Sstevel@tonic-gate 	dst = (sbd_cmp_stat_t *)a->cmstat;
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 	if (parsable)
13407c478bd9Sstevel@tonic-gate 		p = cmpinfo_parsable;
13417c478bd9Sstevel@tonic-gate 	else
13427c478bd9Sstevel@tonic-gate 		p = cmpinfo;
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	/* Print the first cpuid */
13457c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_CPUID], dst->ps_cpuid[0]);
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 	/*
13487c478bd9Sstevel@tonic-gate 	 * Print the middle cpuids, if necessary. Stop before
13497c478bd9Sstevel@tonic-gate 	 * the last one, since printing the last cpuid is a
13507c478bd9Sstevel@tonic-gate 	 * special case for the non parsable form.
13517c478bd9Sstevel@tonic-gate 	 */
13527c478bd9Sstevel@tonic-gate 	for (i = 1; i < (dst->ps_ncores - 1); i++) {
13537c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info, p[PI_CPUID_CONT],
13547c478bd9Sstevel@tonic-gate 		    dst->ps_cpuid[i]);
13557c478bd9Sstevel@tonic-gate 	}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	/* Print the last cpuid, if necessary */
13587c478bd9Sstevel@tonic-gate 	if (dst->ps_ncores > 1) {
13597c478bd9Sstevel@tonic-gate 		last = (dst->ps_ncores == 2) ? PI_CPUID_PAIR : PI_CPUID_LAST;
13607c478bd9Sstevel@tonic-gate 		info += snprintf(info, end - info,
13617c478bd9Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, p[last]), dst->ps_cpuid[i]);
13627c478bd9Sstevel@tonic-gate 	}
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_SPEED], dst->ps_speed);
13657c478bd9Sstevel@tonic-gate 	info += snprintf(info, end - info, p[PI_ECACHE], dst->ps_ecache);
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate void
ap_info(apd_t * a,cfga_info_t info,ap_target_t tgt)13697c478bd9Sstevel@tonic-gate ap_info(apd_t *a, cfga_info_t info, ap_target_t tgt)
13707c478bd9Sstevel@tonic-gate {
13717c478bd9Sstevel@tonic-gate 	int parsable = ap_getopt(a, OPT_PARSABLE);
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 	DBG("ap_info(%p, %d)\n", (void *)info, parsable);
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 	switch (tgt) {
13767c478bd9Sstevel@tonic-gate 	case AP_BOARD:
13777c478bd9Sstevel@tonic-gate 		bd_info(a, info, parsable);
13787c478bd9Sstevel@tonic-gate 		break;
13797c478bd9Sstevel@tonic-gate 	case AP_CPU:
13807c478bd9Sstevel@tonic-gate 		cpu_info(a, info, parsable);
13817c478bd9Sstevel@tonic-gate 		break;
13827c478bd9Sstevel@tonic-gate 	case AP_MEM:
13837c478bd9Sstevel@tonic-gate 		mem_info(a, info, parsable);
13847c478bd9Sstevel@tonic-gate 		break;
13857c478bd9Sstevel@tonic-gate 	case AP_IO:
13867c478bd9Sstevel@tonic-gate 		io_info(a, info, parsable);
13877c478bd9Sstevel@tonic-gate 		break;
13887c478bd9Sstevel@tonic-gate 	case AP_CMP:
13897c478bd9Sstevel@tonic-gate 		cmp_info(a, info, parsable);
13907c478bd9Sstevel@tonic-gate 		break;
13917c478bd9Sstevel@tonic-gate 	default:
13927c478bd9Sstevel@tonic-gate 		break;
13937c478bd9Sstevel@tonic-gate 	}
13947c478bd9Sstevel@tonic-gate }
1395