xref: /titanic_51/usr/src/lib/cfgadm_plugins/sbd/common/ap.c (revision a31148363f598def767ac48c5d82e1572e44b935)
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
5*a3114836SGerry Liu  * Common Development and Distribution License (the "License").
6*a3114836SGerry 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 /*
22*a3114836SGerry 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 <assert.h>
277c478bd9Sstevel@tonic-gate #include <ctype.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <macros.h>
337c478bd9Sstevel@tonic-gate #include <dirent.h>
347c478bd9Sstevel@tonic-gate #include <libgen.h>
357c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
367c478bd9Sstevel@tonic-gate #define	CFGA_PLUGIN_LIB
377c478bd9Sstevel@tonic-gate #include <config_admin.h>
387c478bd9Sstevel@tonic-gate #include "ap.h"
397c478bd9Sstevel@tonic-gate 
40*a3114836SGerry Liu /*ARGSUSED0*/
417c478bd9Sstevel@tonic-gate int
427c478bd9Sstevel@tonic-gate ap_symid(apd_t *a, char *apid, char *symid, size_t bufsize)
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate 	int n;
457c478bd9Sstevel@tonic-gate 	int rc;
467c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
477c478bd9Sstevel@tonic-gate 	char *p;
487c478bd9Sstevel@tonic-gate 	DIR *dirp;
497c478bd9Sstevel@tonic-gate 	struct dirent *dp;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 	*symid = '\0';
527c478bd9Sstevel@tonic-gate 	n = sprintf(path, "/dev/cfg/");
537c478bd9Sstevel@tonic-gate 	rc = -1;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	if ((dirp = opendir(path)) == NULL)
567c478bd9Sstevel@tonic-gate 		return (rc);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	p = path + n;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	while ((dp = readdir(dirp)) != NULL) {
617c478bd9Sstevel@tonic-gate 		char buf[MAXPATHLEN];
627c478bd9Sstevel@tonic-gate 		char *cp;
637c478bd9Sstevel@tonic-gate 		size_t len;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 		*p = '\0';
667c478bd9Sstevel@tonic-gate 		(void) strcat(path, dp->d_name);
677c478bd9Sstevel@tonic-gate 		if ((len = readlink(path, buf, sizeof (buf))) == (size_t)-1)
687c478bd9Sstevel@tonic-gate 			continue;
697c478bd9Sstevel@tonic-gate 		buf[len] = '\0';
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 		len = strlen("../");
727c478bd9Sstevel@tonic-gate 		cp = buf;
737c478bd9Sstevel@tonic-gate 		while (strncmp(cp, "../", len) == 0)
747c478bd9Sstevel@tonic-gate 			cp += len;
757c478bd9Sstevel@tonic-gate 		if (cp != buf)
767c478bd9Sstevel@tonic-gate 			cp--;	/* Get the '/' */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 		if (strcmp(cp, apid) == 0) {
79*a3114836SGerry Liu 			(void) snprintf(symid, bufsize, "%s", dp->d_name);
807c478bd9Sstevel@tonic-gate 			rc = 0;
817c478bd9Sstevel@tonic-gate 			break;
827c478bd9Sstevel@tonic-gate 		}
837c478bd9Sstevel@tonic-gate 	}
847c478bd9Sstevel@tonic-gate 
85*a3114836SGerry Liu 	(void) closedir(dirp);
867c478bd9Sstevel@tonic-gate 	return (rc);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate char *
907c478bd9Sstevel@tonic-gate ap_logid(apd_t *a, char *apid)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	int n;
937c478bd9Sstevel@tonic-gate 	char *buf;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	if ((buf = calloc(1, MAXPATHLEN)) == NULL)
967c478bd9Sstevel@tonic-gate 		return (NULL);
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	/*
997c478bd9Sstevel@tonic-gate 	 * Look for a symlink.  On any error, fallback to
1007c478bd9Sstevel@tonic-gate 	 * driver and instance based logical ap_ids.
1017c478bd9Sstevel@tonic-gate 	 */
1027c478bd9Sstevel@tonic-gate 	if (ap_symid(a, apid, buf, MAXPATHLEN) == 0)
1037c478bd9Sstevel@tonic-gate 		n = strlen(buf);
1047c478bd9Sstevel@tonic-gate 	else
1057c478bd9Sstevel@tonic-gate 		n = snprintf(buf, MAXPATHLEN, "%s%d:%s",
1067c478bd9Sstevel@tonic-gate 		    a->drv, a->inst, a->minor);
1077c478bd9Sstevel@tonic-gate 	/*
1087c478bd9Sstevel@tonic-gate 	 * Append the dynamic portion, if any.
1097c478bd9Sstevel@tonic-gate 	 */
1107c478bd9Sstevel@tonic-gate 	if (a->cid != NULL)
1117c478bd9Sstevel@tonic-gate 		(void) snprintf(&buf[n], MAXPATHLEN - n, "::%s", a->cid);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	return (buf);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate int
1177c478bd9Sstevel@tonic-gate ap_parse(apd_t *a, const char *ap_id)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	int i;
1207c478bd9Sstevel@tonic-gate 	int rc;
1217c478bd9Sstevel@tonic-gate 	int phys;
1227c478bd9Sstevel@tonic-gate 	char c;
1237c478bd9Sstevel@tonic-gate 	char *s;
1247c478bd9Sstevel@tonic-gate 	char *p;
1257c478bd9Sstevel@tonic-gate 	char *q;
1267c478bd9Sstevel@tonic-gate 	char *base;
1277c478bd9Sstevel@tonic-gate 	int len;
1287c478bd9Sstevel@tonic-gate 	char *t;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	if (a == NULL)
1317c478bd9Sstevel@tonic-gate 		return (-1);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	a->cnum = -1;
1347c478bd9Sstevel@tonic-gate 	a->bnum = -1;
1357c478bd9Sstevel@tonic-gate 	a->inst = -1;
1367c478bd9Sstevel@tonic-gate 	a->apid = ap_id;
1377c478bd9Sstevel@tonic-gate 	rc = ERR_NONE;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	if (!str_valid(ap_id)) {
1407c478bd9Sstevel@tonic-gate 		rc = ERR_AP_INVAL;
1417c478bd9Sstevel@tonic-gate 		goto done;
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if ((a->path = strdup(ap_id)) == NULL) {
1457c478bd9Sstevel@tonic-gate 		rc = ERR_NOMEM;
1467c478bd9Sstevel@tonic-gate 		goto done;
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/*
1507c478bd9Sstevel@tonic-gate 	 * For a physical ap_id, look only at the base part.
1517c478bd9Sstevel@tonic-gate 	 * For a logical/symbolic one, use the entire ap_id.
1527c478bd9Sstevel@tonic-gate 	 */
1537c478bd9Sstevel@tonic-gate 	if (strncmp(a->path, DEVDIR, strlen(DEVDIR)) == 0) {
1547c478bd9Sstevel@tonic-gate 		phys = 1;
1557c478bd9Sstevel@tonic-gate 		base = strrchr((const char *)a->path, '/') + 1;
1567c478bd9Sstevel@tonic-gate 	} else {
1577c478bd9Sstevel@tonic-gate 		phys = 0;
1587c478bd9Sstevel@tonic-gate 		base = a->path;
1597c478bd9Sstevel@tonic-gate 		if ((a->target = strdup(a->path)) == NULL) {
1607c478bd9Sstevel@tonic-gate 			rc = ERR_NOMEM;
1617c478bd9Sstevel@tonic-gate 			goto done;
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	if ((s = strchr(base, ':')) == NULL || s[1] == ':') {
1667c478bd9Sstevel@tonic-gate 		/*
1677c478bd9Sstevel@tonic-gate 		 * No ':' found, or got a '::'.  If this is a physical
1687c478bd9Sstevel@tonic-gate 		 * ap_id, it must have a minor separtor ':' which must
1697c478bd9Sstevel@tonic-gate 		 * appear before the dynamic part (starting with '::').
1707c478bd9Sstevel@tonic-gate 		 * For a symbolic ap_id, skip looking for driver/minor
1717c478bd9Sstevel@tonic-gate 		 * names.
1727c478bd9Sstevel@tonic-gate 		 */
1737c478bd9Sstevel@tonic-gate 		if (phys) {
1747c478bd9Sstevel@tonic-gate 			rc = ERR_AP_INVAL;
1757c478bd9Sstevel@tonic-gate 			goto done;
1767c478bd9Sstevel@tonic-gate 		} else
1777c478bd9Sstevel@tonic-gate 			s = base;
1787c478bd9Sstevel@tonic-gate 	} else {
1797c478bd9Sstevel@tonic-gate 		/*
1807c478bd9Sstevel@tonic-gate 		 * Look for driver name/instance only up to the first ':',
1817c478bd9Sstevel@tonic-gate 		 * i.e. up to the minor node name.
1827c478bd9Sstevel@tonic-gate 		 */
1837c478bd9Sstevel@tonic-gate 		*s = '\0';
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 		if ((p = strchr(base, '@')) != NULL) {
1867c478bd9Sstevel@tonic-gate 			/*
1877c478bd9Sstevel@tonic-gate 			 * Get the driver name/instance.
1887c478bd9Sstevel@tonic-gate 			 */
1897c478bd9Sstevel@tonic-gate 			*p = '\0';
1907c478bd9Sstevel@tonic-gate 			if ((a->drv = strdup(base)) == NULL) {
1917c478bd9Sstevel@tonic-gate 				rc = ERR_NOMEM;
1927c478bd9Sstevel@tonic-gate 				goto done;
1937c478bd9Sstevel@tonic-gate 			}
1947c478bd9Sstevel@tonic-gate 			*p++ = '@';
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 			i = strtol(p, &q, 10);
1977c478bd9Sstevel@tonic-gate 			if (q > p)
1987c478bd9Sstevel@tonic-gate 				a->inst = i;
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		*s++ = ':';
2027c478bd9Sstevel@tonic-gate 		a->minor = s;
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/*
2067c478bd9Sstevel@tonic-gate 	 * Need to go to the end of the string before the :: if any
2077c478bd9Sstevel@tonic-gate 	 * If the string is null then we are done
2087c478bd9Sstevel@tonic-gate 	 */
2097c478bd9Sstevel@tonic-gate 	t = strstr(s, "::");
2107c478bd9Sstevel@tonic-gate 	if (t != NULL)
2117c478bd9Sstevel@tonic-gate 		len = strlen(t);
2127c478bd9Sstevel@tonic-gate 	else
2137c478bd9Sstevel@tonic-gate 		len = 0;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	s += (strlen(s) - len);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	p = s;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (*p == '\0')
2207c478bd9Sstevel@tonic-gate 		a->tgt = AP_BOARD;
2217c478bd9Sstevel@tonic-gate 	else if (strncmp(p, "::", 2) != 0) {
2227c478bd9Sstevel@tonic-gate 		rc = ERR_AP_INVAL;
2237c478bd9Sstevel@tonic-gate 		goto done;
2247c478bd9Sstevel@tonic-gate 	} else {
2257c478bd9Sstevel@tonic-gate 		/*
2267c478bd9Sstevel@tonic-gate 		 * Save the component id.
2277c478bd9Sstevel@tonic-gate 		 */
2287c478bd9Sstevel@tonic-gate 		*p++ = '\0';
2297c478bd9Sstevel@tonic-gate 		*p++ = '\0';
2307c478bd9Sstevel@tonic-gate 		a->cid = p;
2317c478bd9Sstevel@tonic-gate 	}
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/*
2347c478bd9Sstevel@tonic-gate 	 * Get the operation target, e.g. slot0, slot0::cpu0.
2357c478bd9Sstevel@tonic-gate 	 * At this point, a->path points to the /devices path
2367c478bd9Sstevel@tonic-gate 	 * minus the dynamic part, for a physical ap_id. In
2377c478bd9Sstevel@tonic-gate 	 * the case of a logical ap_id, the target is already
2387c478bd9Sstevel@tonic-gate 	 * initialized above.
2397c478bd9Sstevel@tonic-gate 	 */
2407c478bd9Sstevel@tonic-gate 	if (phys != 0 && (a->target = ap_logid(a, a->path)) == NULL) {
2417c478bd9Sstevel@tonic-gate 		rc = ERR_NOMEM;
2427c478bd9Sstevel@tonic-gate 		goto done;
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (a->tgt == AP_BOARD)
2467c478bd9Sstevel@tonic-gate 		goto done;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	while ((*p != '\0') && !isdigit(*p))
2497c478bd9Sstevel@tonic-gate 		p++;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	/*
2527c478bd9Sstevel@tonic-gate 	 * Get the component unit number, if present.
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	i = strtol(p, &s, 10);
2557c478bd9Sstevel@tonic-gate 	/*
2567c478bd9Sstevel@tonic-gate 	 * There must be no characters after the unit number.
2577c478bd9Sstevel@tonic-gate 	 */
2587c478bd9Sstevel@tonic-gate 	if (*s != '\0') {
2597c478bd9Sstevel@tonic-gate 		rc = ERR_CM_INVAL;
2607c478bd9Sstevel@tonic-gate 		goto done;
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 	if (s > p) {
2637c478bd9Sstevel@tonic-gate 		/*
2647c478bd9Sstevel@tonic-gate 		 * Disallow leading zeroes, e.g. cpu00, cpu01, cpu001.
2657c478bd9Sstevel@tonic-gate 		 * If there are 2 or more digits and the first is a zero,
2667c478bd9Sstevel@tonic-gate 		 * we fail.
2677c478bd9Sstevel@tonic-gate 		 */
2687c478bd9Sstevel@tonic-gate 		if ((s-p) >= 2 && *p == '0') {
2697c478bd9Sstevel@tonic-gate 			rc = ERR_CM_INVAL;
2707c478bd9Sstevel@tonic-gate 			goto done;
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 		a->cnum = i;
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	c = *p;
2767c478bd9Sstevel@tonic-gate 	*p = '\0';
2777c478bd9Sstevel@tonic-gate 	if ((a->cname = strdup(a->cid)) == NULL)
2787c478bd9Sstevel@tonic-gate 		rc = ERR_NOMEM;
2797c478bd9Sstevel@tonic-gate 	*p = c;
2807c478bd9Sstevel@tonic-gate done:
2817c478bd9Sstevel@tonic-gate 	switch (rc) {
2827c478bd9Sstevel@tonic-gate 	case ERR_NONE:
2837c478bd9Sstevel@tonic-gate 		break;
2847c478bd9Sstevel@tonic-gate 	case ERR_CM_INVAL:
2857c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CM_INVAL, a->cid);
2867c478bd9Sstevel@tonic-gate 		break;
2877c478bd9Sstevel@tonic-gate 	default:
2887c478bd9Sstevel@tonic-gate 		ap_err(a, rc);
2897c478bd9Sstevel@tonic-gate 		break;
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	DBG("path=<%s> ", a->path ? a->path : "");
2937c478bd9Sstevel@tonic-gate 	DBG("drv=<%s> inst=%d minor=<%s> ",
2947c478bd9Sstevel@tonic-gate 	    a->drv ? a->drv : "", a->inst, a->minor ? a->minor : "");
2957c478bd9Sstevel@tonic-gate 	DBG("target=<%s>\n", a->target ? a->target : "");
2967c478bd9Sstevel@tonic-gate 	DBG("cid=<%s> ", a->cid ? a->cid : "");
2977c478bd9Sstevel@tonic-gate 	DBG("cname=<%s> ", a->cname ? a->cname : "");
2987c478bd9Sstevel@tonic-gate 	DBG("cnum=%d\n", a->cnum);
2997c478bd9Sstevel@tonic-gate 	DBG("tgt=%d opts=%x\n", a->tgt, a->opts.flags);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	return (rc == ERR_NONE? 0 :  -1);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate  * Command table.
3067c478bd9Sstevel@tonic-gate  *
3077c478bd9Sstevel@tonic-gate  * The first set of commands in the table are in sequencing order,
3087c478bd9Sstevel@tonic-gate  * for example, the first group starts with assign and ends with
3097c478bd9Sstevel@tonic-gate  * configure.  command sequencer relies on this ordering.
3107c478bd9Sstevel@tonic-gate  */
3117c478bd9Sstevel@tonic-gate static char *
3127c478bd9Sstevel@tonic-gate ap_cmd_names[] = {
3137c478bd9Sstevel@tonic-gate 	"assign",
3147c478bd9Sstevel@tonic-gate 	"poweron",
3157c478bd9Sstevel@tonic-gate 	"test",
3167c478bd9Sstevel@tonic-gate 	"connect",
3177c478bd9Sstevel@tonic-gate 	"configure",
3187c478bd9Sstevel@tonic-gate 	"notify online",
3197c478bd9Sstevel@tonic-gate 	"notify add capacity",
3207c478bd9Sstevel@tonic-gate 	"suspend check",
3217c478bd9Sstevel@tonic-gate 	"request suspend",
3227c478bd9Sstevel@tonic-gate 	"request delete capacity",
3237c478bd9Sstevel@tonic-gate 	"request offline",
3247c478bd9Sstevel@tonic-gate 	"unconfigure",
3257c478bd9Sstevel@tonic-gate 	"notify remove",
3267c478bd9Sstevel@tonic-gate 	"notify capacity change",
3277c478bd9Sstevel@tonic-gate 	"disconnect",
3287c478bd9Sstevel@tonic-gate 	"poweroff",
3297c478bd9Sstevel@tonic-gate 	"unassign",
3307c478bd9Sstevel@tonic-gate 	"notify resume",
3317c478bd9Sstevel@tonic-gate 	"status",
3327c478bd9Sstevel@tonic-gate 	"getncm",
3337c478bd9Sstevel@tonic-gate 	"passthru",
3347c478bd9Sstevel@tonic-gate 	"help",
3357c478bd9Sstevel@tonic-gate 	"errtest",
3367c478bd9Sstevel@tonic-gate 	NULL
3377c478bd9Sstevel@tonic-gate };
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate char *
3407c478bd9Sstevel@tonic-gate ap_cmd_name(int i)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	return (ap_cmd_names[min(i, CMD_NONE)]);
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate static char *
3467c478bd9Sstevel@tonic-gate ap_opt_names[] = {
3477c478bd9Sstevel@tonic-gate 	"unassign",
3487c478bd9Sstevel@tonic-gate 	"skip",
3497c478bd9Sstevel@tonic-gate 	"parsable",
3507c478bd9Sstevel@tonic-gate 	"nopoweroff",
3517c478bd9Sstevel@tonic-gate 	"code",
3527c478bd9Sstevel@tonic-gate 	"mid",
3537c478bd9Sstevel@tonic-gate 	"err",
3547c478bd9Sstevel@tonic-gate 	"platform",
3557c478bd9Sstevel@tonic-gate 	"sim",
3567c478bd9Sstevel@tonic-gate 	NULL
3577c478bd9Sstevel@tonic-gate };
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate char *
3607c478bd9Sstevel@tonic-gate ap_opt_name(int i)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	return (ap_opt_names[i]);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate /*
3667c478bd9Sstevel@tonic-gate  * Command descriptor.
3677c478bd9Sstevel@tonic-gate  *
3687c478bd9Sstevel@tonic-gate  * Each command has a (command) mask specifying the AP target classes
3697c478bd9Sstevel@tonic-gate  * it operates on, e.g. the assign command applies only to boards.
3707c478bd9Sstevel@tonic-gate  * In addition each AP target class has a separate option mask specifying
3717c478bd9Sstevel@tonic-gate  * which command options are valid for that target class.
3727c478bd9Sstevel@tonic-gate  * A global value mask specifies which options require values.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate typedef struct {
3757c478bd9Sstevel@tonic-gate 	int cmd;
3767c478bd9Sstevel@tonic-gate 	uint_t cmask;
3777c478bd9Sstevel@tonic-gate 	uint_t omask[AP_NCLASS];
3787c478bd9Sstevel@tonic-gate } ap_cmd_t;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate  * Command option definitions.
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate #define	SHFT(i)	((uint_t)1 << (i))
3847c478bd9Sstevel@tonic-gate #define	NULOPT	0
3857c478bd9Sstevel@tonic-gate #define	ALLOPT	0xffffffff
3867c478bd9Sstevel@tonic-gate #define	CMNOPT	(SHFT(OPT_VERBOSE)|SHFT(OPT_PLATFORM)|SHFT(OPT_SIM))
3877c478bd9Sstevel@tonic-gate #define	CMFOPT	(CMNOPT|SHFT(OPT_FORCE))
3887c478bd9Sstevel@tonic-gate #define	STSOPT	(CMNOPT|SHFT(OPT_PARSABLE))
3897c478bd9Sstevel@tonic-gate #define	BRDDCN	(CMNOPT|SHFT(OPT_UNASSIGN)|SHFT(OPT_NOPOWEROFF))
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate #define	BRD	SHFT(AP_BOARD)
3927c478bd9Sstevel@tonic-gate #define	BIO	SHFT(AP_BOARD)|SHFT(AP_IO)
3937c478bd9Sstevel@tonic-gate #define	ALL	(BRD|SHFT(AP_CPU)|SHFT(AP_MEM)|SHFT(AP_IO)|SHFT(AP_CMP))
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate static ap_cmd_t
3967c478bd9Sstevel@tonic-gate ap_cmds[] = {
3977c478bd9Sstevel@tonic-gate 	/*
3987c478bd9Sstevel@tonic-gate 	 *	cmd		cmd	 board	 cpu	 mem	 io	cmp
3997c478bd9Sstevel@tonic-gate 	 *			cmask	 omask	 omask   omask   omask	omask
4007c478bd9Sstevel@tonic-gate 	 */
4017c478bd9Sstevel@tonic-gate 	{CMD_ASSIGN,		BRD, 0, CMNOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4027c478bd9Sstevel@tonic-gate 	{CMD_UNASSIGN,		BRD, 0, CMNOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4037c478bd9Sstevel@tonic-gate 	{CMD_POWERON,		BRD, 0, CMNOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4047c478bd9Sstevel@tonic-gate 	{CMD_POWEROFF,		BRD, 0, CMNOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4057c478bd9Sstevel@tonic-gate 	{CMD_CONNECT,		BRD, 0, CMFOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4067c478bd9Sstevel@tonic-gate 	{CMD_DISCONNECT,	BRD, 0, BRDDCN, NULOPT, NULOPT, NULOPT, NULOPT},
4077c478bd9Sstevel@tonic-gate 	{CMD_CONFIGURE,		ALL, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4087c478bd9Sstevel@tonic-gate 	{CMD_UNCONFIGURE,	ALL, 0, CMFOPT, CMFOPT, CMFOPT, CMFOPT, CMNOPT},
4097c478bd9Sstevel@tonic-gate 	{CMD_RCM_OFFLINE,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4107c478bd9Sstevel@tonic-gate 	{CMD_RCM_ONLINE,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4117c478bd9Sstevel@tonic-gate 	{CMD_RCM_SUSPEND,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4127c478bd9Sstevel@tonic-gate 	{CMD_RCM_RESUME,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4137c478bd9Sstevel@tonic-gate 	{CMD_RCM_CAP_ADD,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4147c478bd9Sstevel@tonic-gate 	{CMD_RCM_CAP_DEL,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4157c478bd9Sstevel@tonic-gate 	{CMD_RCM_CAP_NOTIFY,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4167c478bd9Sstevel@tonic-gate 	{CMD_RCM_REMOVE,	BIO, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4177c478bd9Sstevel@tonic-gate 	{CMD_TEST,		BRD, 0, CMFOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4187c478bd9Sstevel@tonic-gate 	{CMD_STATUS,		ALL, 0, STSOPT, STSOPT, STSOPT, STSOPT, STSOPT},
4197c478bd9Sstevel@tonic-gate 	{CMD_GETNCM,		BRD, 0, CMNOPT, NULOPT, NULOPT, NULOPT, NULOPT},
4207c478bd9Sstevel@tonic-gate 	{CMD_PASSTHRU,		ALL, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4217c478bd9Sstevel@tonic-gate 	{CMD_HELP,		ALL, 0, CMNOPT, CMNOPT, CMNOPT, CMNOPT, CMNOPT},
4227c478bd9Sstevel@tonic-gate 	{CMD_ERRTEST,		ALL, 0, ALLOPT, ALLOPT, ALLOPT, ALLOPT, ALLOPT},
4237c478bd9Sstevel@tonic-gate 	{CMD_NONE,		0,   0,	0,	0,	0,	0,	0    }
4247c478bd9Sstevel@tonic-gate };
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate  * Global mask for options that require values.
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate #define	AP_VMASK (\
4307c478bd9Sstevel@tonic-gate 	SHFT(OPT_CODE)|SHFT(OPT_MID)|SHFT(OPT_ERR)| \
4317c478bd9Sstevel@tonic-gate 	SHFT(OPT_PLATFORM)|SHFT(OPT_SKIP))
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate #if SBD_DEBUG
4347c478bd9Sstevel@tonic-gate void
4357c478bd9Sstevel@tonic-gate ap_cmds_dump()
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate 	int i;
4387c478bd9Sstevel@tonic-gate 	ap_cmd_t *acp;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	dbg("vmask=0x%x\n", AP_VMASK);
4417c478bd9Sstevel@tonic-gate 	dbg("%23s%5s%5s%9s%9s%9s%9s%9s\n",
4427c478bd9Sstevel@tonic-gate 	    "cmd", "msk", "none", "brd", "cpu", "mem", "io", "cmp");
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	for (acp = ap_cmds; acp->cmd != CMD_NONE; acp++) {
4457c478bd9Sstevel@tonic-gate 		dbg("%23s%5x%5x", ap_cmd_name(acp->cmd), acp->cmask,
4467c478bd9Sstevel@tonic-gate 		    acp->omask[AP_NONE]);
4477c478bd9Sstevel@tonic-gate 		for (i = AP_BOARD; i < AP_NCLASS; i++) {
4487c478bd9Sstevel@tonic-gate 			dbg("%9x", acp->omask[i]);
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 		dbg("\n");
4517c478bd9Sstevel@tonic-gate 	}
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate #endif
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate int
4567c478bd9Sstevel@tonic-gate ap_state_cmd(cfga_cmd_t i, int *cmd)
4577c478bd9Sstevel@tonic-gate {
4587c478bd9Sstevel@tonic-gate 	int c;
4597c478bd9Sstevel@tonic-gate 	int rc;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	rc = CFGA_OK;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	switch (i) {
4647c478bd9Sstevel@tonic-gate 	case CFGA_CMD_CONNECT:
4657c478bd9Sstevel@tonic-gate 		c = CMD_CONNECT;
4667c478bd9Sstevel@tonic-gate 		break;
4677c478bd9Sstevel@tonic-gate 	case CFGA_CMD_DISCONNECT:
4687c478bd9Sstevel@tonic-gate 		c = CMD_DISCONNECT;
4697c478bd9Sstevel@tonic-gate 		break;
4707c478bd9Sstevel@tonic-gate 	case CFGA_CMD_CONFIGURE:
4717c478bd9Sstevel@tonic-gate 		c = CMD_CONFIGURE;
4727c478bd9Sstevel@tonic-gate 		break;
4737c478bd9Sstevel@tonic-gate 	case CFGA_CMD_UNCONFIGURE:
4747c478bd9Sstevel@tonic-gate 		c = CMD_UNCONFIGURE;
4757c478bd9Sstevel@tonic-gate 		break;
4767c478bd9Sstevel@tonic-gate 	case CFGA_CMD_LOAD:
4777c478bd9Sstevel@tonic-gate 	case CFGA_CMD_UNLOAD:
4787c478bd9Sstevel@tonic-gate 		rc = CFGA_OPNOTSUPP;
4797c478bd9Sstevel@tonic-gate 		c = CMD_NONE;
4807c478bd9Sstevel@tonic-gate 		break;
4817c478bd9Sstevel@tonic-gate 	default:
4827c478bd9Sstevel@tonic-gate 		rc = CFGA_INVAL;
4837c478bd9Sstevel@tonic-gate 		c = CMD_NONE;
4847c478bd9Sstevel@tonic-gate 		break;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	*cmd = c;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	return (rc);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate static int
4937c478bd9Sstevel@tonic-gate ap_cmd(char *name)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	int i;
4967c478bd9Sstevel@tonic-gate 	char **p;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (name == NULL)
4997c478bd9Sstevel@tonic-gate 		return (CMD_NONE);
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	for (i = 0, p = ap_cmd_names; *p != NULL; p++, i++)
5027c478bd9Sstevel@tonic-gate 		if (strcmp(*p, name) == 0)
5037c478bd9Sstevel@tonic-gate 			break;
5047c478bd9Sstevel@tonic-gate 	if (*p == NULL)
5057c478bd9Sstevel@tonic-gate 		i = CMD_NONE;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	return (i);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate static int
5117c478bd9Sstevel@tonic-gate ap_opt_parse(apd_t *a, ap_cmd_t *acp, const char *options)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	char *optstr;
5147c478bd9Sstevel@tonic-gate 	ap_opts_t *opts;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	/*
5177c478bd9Sstevel@tonic-gate 	 * Set default values.
5187c478bd9Sstevel@tonic-gate 	 */
5197c478bd9Sstevel@tonic-gate 	opts = &a->opts;
5207c478bd9Sstevel@tonic-gate 	opts->mid = (char *)a->class;
5217c478bd9Sstevel@tonic-gate 	opts->err = ERR_CMD_FAIL;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if (options == NULL)
5247c478bd9Sstevel@tonic-gate 		return (0);
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	if ((optstr = strdup(options)) == NULL) {
5277c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_NOMEM);
5287c478bd9Sstevel@tonic-gate 		return (-1);
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	a->options = optstr;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (acp->cmd == CMD_PASSTHRU)
5347c478bd9Sstevel@tonic-gate 		return (0);
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	while (*optstr != '\0') {
5377c478bd9Sstevel@tonic-gate 		int i;
5387c478bd9Sstevel@tonic-gate 		int opt;
5397c478bd9Sstevel@tonic-gate 		int omask;
5407c478bd9Sstevel@tonic-gate 		char *p;
5417c478bd9Sstevel@tonic-gate 		char *value;
5427c478bd9Sstevel@tonic-gate 		char *optname;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		value = NULL;
5457c478bd9Sstevel@tonic-gate 		opt = getsubopt(&optstr, ap_opt_names, &value);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 		DBG("opt=%d\n", opt);
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		if (opt == -1) {
5507c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_OPT_INVAL, value);
5517c478bd9Sstevel@tonic-gate 			return (-1);
5527c478bd9Sstevel@tonic-gate 		}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		optname = ap_opt_names[opt];
5557c478bd9Sstevel@tonic-gate 		omask = acp->omask[a->tgt];
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 		i = mask(opt) & omask;
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 		DBG("tgt=%d opt=%x omask=%x\n", a->tgt, mask(opt), omask);
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		if (i == 0) {
5627c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_OPT_INVAL, optname);
5637c478bd9Sstevel@tonic-gate 			return (-1);
5647c478bd9Sstevel@tonic-gate 		}
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		/*
5677c478bd9Sstevel@tonic-gate 		 * Check whether the option requires a value.
5687c478bd9Sstevel@tonic-gate 		 */
5697c478bd9Sstevel@tonic-gate 		i = mask(opt) & AP_VMASK;
5707c478bd9Sstevel@tonic-gate 		if (i != 0 && value == NULL) {
5717c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_OPT_NOVAL, optname);
5727c478bd9Sstevel@tonic-gate 			return (-1);
5737c478bd9Sstevel@tonic-gate 		} else if (i == 0 && value != NULL) {
5747c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_OPT_VAL, optname);
5757c478bd9Sstevel@tonic-gate 			return (-1);
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		if (value == NULL)
5797c478bd9Sstevel@tonic-gate 			assert(opt != OPT_CODE);	/* XXX prefix */
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 		/*
5827c478bd9Sstevel@tonic-gate 		 * Set the options's value.
5837c478bd9Sstevel@tonic-gate 		 */
5847c478bd9Sstevel@tonic-gate 		switch (opt) {
5857c478bd9Sstevel@tonic-gate 		case OPT_SIM:
5867c478bd9Sstevel@tonic-gate 		case OPT_PARSABLE:
5877c478bd9Sstevel@tonic-gate 		case OPT_UNASSIGN:
5887c478bd9Sstevel@tonic-gate 			break;
5897c478bd9Sstevel@tonic-gate 		case OPT_CODE:
5907c478bd9Sstevel@tonic-gate 			i = strtol(value, &p, 10);
5917c478bd9Sstevel@tonic-gate 			if (p > value)
5927c478bd9Sstevel@tonic-gate 				opts->code = i;
5937c478bd9Sstevel@tonic-gate 			break;
5947c478bd9Sstevel@tonic-gate 		case OPT_MID:
5957c478bd9Sstevel@tonic-gate 			opts->mid = value;
5967c478bd9Sstevel@tonic-gate 			break;
5977c478bd9Sstevel@tonic-gate 		case OPT_ERR:
5987c478bd9Sstevel@tonic-gate 			i = strtol(value, &p, 10);
5997c478bd9Sstevel@tonic-gate 			if (p > value)
6007c478bd9Sstevel@tonic-gate 				opts->err = i;
6017c478bd9Sstevel@tonic-gate 			break;
6027c478bd9Sstevel@tonic-gate 		case OPT_NOPOWEROFF:
6037c478bd9Sstevel@tonic-gate 			i = ap_cmd("poweroff");
6047c478bd9Sstevel@tonic-gate 			opts->skip |= mask(i);
6057c478bd9Sstevel@tonic-gate 			break;
6067c478bd9Sstevel@tonic-gate 		case OPT_SKIP:	/* for debugging */
6077c478bd9Sstevel@tonic-gate 			/*
6087c478bd9Sstevel@tonic-gate 			 * The skip value may be a ':' separated
6097c478bd9Sstevel@tonic-gate 			 * list of steps (commands) to be skipped
6107c478bd9Sstevel@tonic-gate 			 * during sequencing.
6117c478bd9Sstevel@tonic-gate 			 */
6127c478bd9Sstevel@tonic-gate 			for (p = strtok(value, ":"); p != NULL;
6137c478bd9Sstevel@tonic-gate 			    p = strtok(NULL, ":")) {
6147c478bd9Sstevel@tonic-gate 				if ((i = ap_cmd(p)) == CMD_NONE) {
6157c478bd9Sstevel@tonic-gate 					ap_err(a, ERR_CMD_INVAL, p);
6167c478bd9Sstevel@tonic-gate 					return (-1);
6177c478bd9Sstevel@tonic-gate 				}
6187c478bd9Sstevel@tonic-gate 				opts->skip |= mask(i);
6197c478bd9Sstevel@tonic-gate 			}
6207c478bd9Sstevel@tonic-gate 			break;
6217c478bd9Sstevel@tonic-gate 		case OPT_PLATFORM:
6227c478bd9Sstevel@tonic-gate 			opts->platform = value;
6237c478bd9Sstevel@tonic-gate 			break;
6247c478bd9Sstevel@tonic-gate 		default:
6257c478bd9Sstevel@tonic-gate 			ap_err(a, ERR_OPT_INVAL, optname);
6267c478bd9Sstevel@tonic-gate 			return (-1);
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 		ap_setopt(a, opt);
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	return (0);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate static ap_cmd_t *
6367c478bd9Sstevel@tonic-gate ap_cmdp(int cmd)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate 	ap_cmd_t *acp;
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 	for (acp = ap_cmds; acp->cmd != CMD_NONE; acp++)
6417c478bd9Sstevel@tonic-gate 		if (acp->cmd == cmd)
6427c478bd9Sstevel@tonic-gate 			break;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	if (acp->cmd == CMD_NONE)
6457c478bd9Sstevel@tonic-gate 		return (NULL);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	return (acp);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate cfga_err_t
6517c478bd9Sstevel@tonic-gate ap_cmd_parse(apd_t *a, const char *f, const char *options, int *cmd)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate 	int c;
6547c478bd9Sstevel@tonic-gate 	int all;
6557c478bd9Sstevel@tonic-gate 	int tgt;
6567c478bd9Sstevel@tonic-gate 	int target;
6577c478bd9Sstevel@tonic-gate 	ap_cmd_t *acp;
6587c478bd9Sstevel@tonic-gate 	cfga_err_t rc;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate #ifdef	_SBD_DEBUG
6617c478bd9Sstevel@tonic-gate 	ap_cmds_dump();
6627c478bd9Sstevel@tonic-gate #endif
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	rc = CFGA_INVAL;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	if ((c = ap_cmd((char *)f)) == CMD_NONE ||
6677c478bd9Sstevel@tonic-gate 	    (acp = ap_cmdp(c)) == NULL) {
6687c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_INVAL, f);
6697c478bd9Sstevel@tonic-gate 		return (rc);
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/*
6737c478bd9Sstevel@tonic-gate 	 * Change a->statonly to 1, if the case is CMD_STATUS.  We are only
6747c478bd9Sstevel@tonic-gate 	 * wanting to read the devices and no more
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	/*
6777c478bd9Sstevel@tonic-gate 	 * Get the status for all components if either the list all
6787c478bd9Sstevel@tonic-gate 	 * option being specified or if we are configuring/unconfiguring
6797c478bd9Sstevel@tonic-gate 	 * the board.  The latter is needed for the RCM interface.
6807c478bd9Sstevel@tonic-gate 	 */
6817c478bd9Sstevel@tonic-gate 	switch (c) {
6827c478bd9Sstevel@tonic-gate 	case CMD_STATUS:
6837c478bd9Sstevel@tonic-gate 		all = ap_getopt(a, OPT_LIST_ALL);
6847c478bd9Sstevel@tonic-gate 		a->statonly = 1;
6857c478bd9Sstevel@tonic-gate 		break;
6867c478bd9Sstevel@tonic-gate 	case CMD_CONFIGURE:
6877c478bd9Sstevel@tonic-gate 	case CMD_UNCONFIGURE:
6887c478bd9Sstevel@tonic-gate 	case CMD_CONNECT:
6897c478bd9Sstevel@tonic-gate 	case CMD_DISCONNECT:
6907c478bd9Sstevel@tonic-gate 		all = (a->tgt == AP_BOARD);
6917c478bd9Sstevel@tonic-gate 		a->statonly = 0;
6927c478bd9Sstevel@tonic-gate 		break;
6937c478bd9Sstevel@tonic-gate 	default:
6947c478bd9Sstevel@tonic-gate 		all = 0;
6957c478bd9Sstevel@tonic-gate 		a->statonly = 0;
6967c478bd9Sstevel@tonic-gate 		break;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if ((rc = apd_init(a, all)) != CFGA_OK)
7007c478bd9Sstevel@tonic-gate 		return (rc);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	rc = CFGA_INVAL;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/*
7057c478bd9Sstevel@tonic-gate 	 * Get the target here in case it is a component in which
7067c478bd9Sstevel@tonic-gate 	 * case its type is known after the initialization.
7077c478bd9Sstevel@tonic-gate 	 */
7087c478bd9Sstevel@tonic-gate 	tgt = a->tgt;
7097c478bd9Sstevel@tonic-gate 	target = mask(tgt);
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	DBG("cmd=%s(%d) tmask=0x%x cmask=0x%x omask=0x%x\n",
712*a3114836SGerry Liu 	    ap_cmd_name(c), c, target, acp->cmask, acp->omask[tgt]);
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	if ((acp->cmask & target) == 0)
7157c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_CMD_NOTSUPP, c);
7167c478bd9Sstevel@tonic-gate 	else if (options != NULL && acp->omask[tgt] == 0)
7177c478bd9Sstevel@tonic-gate 		ap_err(a, ERR_OPT_INVAL, options);
7187c478bd9Sstevel@tonic-gate 	else if (ap_opt_parse(a, acp, options) != -1) {
7197c478bd9Sstevel@tonic-gate 		if (c == CMD_STATUS)
7207c478bd9Sstevel@tonic-gate 			rc = ap_platopts_check(a, c, c);
7217c478bd9Sstevel@tonic-gate 		else
7227c478bd9Sstevel@tonic-gate 			rc = CFGA_OK;
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if (cmd)
7267c478bd9Sstevel@tonic-gate 		*cmd = c;
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	return (rc);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate int
7327c478bd9Sstevel@tonic-gate ap_cnt(apd_t *a)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	int cnt;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	if ((a->tgt == AP_BOARD) && ap_getopt(a, OPT_LIST_ALL))
7377c478bd9Sstevel@tonic-gate 		cnt = a->ncm + 1;
7387c478bd9Sstevel@tonic-gate 	else
7397c478bd9Sstevel@tonic-gate 		cnt = 1;
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	return (cnt);
7427c478bd9Sstevel@tonic-gate }
743