2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include <stddef.h>
2N/A#include <locale.h>
2N/A#include <ctype.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <fcntl.h>
2N/A#include <unistd.h>
2N/A#include <errno.h>
2N/A#include <locale.h>
2N/A#include <langinfo.h>
2N/A#include <time.h>
2N/A#include <stdarg.h>
2N/A#include <sys/types.h>
2N/A#include <sys/ioctl.h>
2N/A#include <sys/dditypes.h>
2N/A#include <sys/modctl.h>
2N/A#include <sys/obpdefs.h>
2N/A#include <sys/fhc.h>
2N/A#include <sys/sysctrl.h>
2N/A#include <sys/openpromio.h>
2N/A#ifdef SIM
2N/A#include <sys/stat.h>
2N/A#endif
2N/A#define CFGA_PLUGIN_LIB
2N/A#include <config_admin.h>
2N/A
2N/A#ifdef DEBUG
2N/A#define DBG printf
2N/A#define DBG1 printf
2N/A#define DBG3 printf
2N/A#define DBG4 printf
2N/A#else
2N/A#define DBG(a, b)
2N/A#define DBG1(a)
2N/A#define DBG3(a, b, c)
2N/A#define DBG4(a, b, c, d)
2N/A#endif
2N/A
2N/A#define BD_CPU 1
2N/A#define BD_MEM 2
2N/A#define BD_IO_2SBUS 3
2N/A#define BD_IO_SBUS_FFB 4
2N/A#define BD_IO_PCI 5
2N/A#define BD_DISK 6
2N/A#define BD_IO_2SBUS_SOCPLUS 7
2N/A#define BD_IO_SBUS_FFB_SOCPLUS 8
2N/A#define BD_UNKNOWN 9
2N/A#define CMD_GETSTAT 10
2N/A#define CMD_LIST 11
2N/A#define CMD_CONNECT 12
2N/A#define CMD_DISCONNECT 13
2N/A#define CMD_CONFIGURE 14
2N/A#define CMD_UNCONFIGURE 15
2N/A#define CMD_QUIESCE 16
2N/A#define CMD_INSERT 17
2N/A#define CMD_REMOVE 18
2N/A#define CMD_SET_COND 19
2N/A#define OPT_ENABLE 20
2N/A#define OPT_DISABLE 21
2N/A#define ERR_PROM_OPEN 22
2N/A#define ERR_PROM_GETPROP 23
2N/A#define ERR_PROM_SETPROP 24
2N/A#define ERR_TRANS 25
2N/A#define ERR_CMD_INVAL 26
2N/A#define ERR_OPT_INVAL 27
2N/A#define ERR_AP_INVAL 28
2N/A#define ERR_DISABLED 29
2N/A#define DIAG_FORCE 30
2N/A#define DIAG_TRANS_OK 31
2N/A#define DIAG_FAILED 32
2N/A#define DIAG_WAS_ENABLED 33
2N/A#define DIAG_WAS_DISABLED 34
2N/A#define DIAG_WILL_ENABLE 35
2N/A#define DIAG_WILL_DISABLE 36
2N/A#define HELP_HEADER 37
2N/A#define HELP_QUIESCE 38
2N/A#define HELP_INSERT 39
2N/A#define HELP_REMOVE 40
2N/A#define HELP_SET_COND 41
2N/A#define HELP_ENABLE 42
2N/A#define HELP_DISABLE 43
2N/A#define HELP_UNKNOWN 44
2N/A#define ASK_CONNECT 45
2N/A#define STR_BD 46
2N/A#define STR_COL 47
2N/A#define COND_UNKNOWN 48
2N/A#define COND_OK 49
2N/A#define COND_FAILING 50
2N/A#define COND_FAILED 51
2N/A#define COND_UNUSABLE 52
2N/A#define SYSC_COOLING 53
2N/A#define SYSC_POWER 54
2N/A#define SYSC_PRECHARGE 55
2N/A#define SYSC_INTRANS 56
2N/A#define SYSC_UTHREAD 57
2N/A#define SYSC_KTHREAD 58
2N/A#define SYSC_DEV_ATTACH 59
2N/A#define SYSC_DEV_DETACH 60
2N/A#define SYSC_NDI_ATTACH 61
2N/A#define SYSC_NDI_DETACH 62
2N/A#define SYSC_CORE_RESOURCE 63
2N/A#define SYSC_OSTATE 64
2N/A#define SYSC_RSTATE 65
2N/A#define SYSC_COND 66
2N/A#define SYSC_PROM 67
2N/A#define SYSC_NOMEM 68
2N/A#define SYSC_HOTPLUG 69
2N/A#define SYSC_HW_COMPAT 70
2N/A#define SYSC_NON_DR_PROM 71
2N/A#define SYSC_SUSPEND 72
2N/A#define SYSC_RESUME 73
2N/A#define SYSC_UNKNOWN 74
2N/A#define SYSC_DEVSTR 75
2N/A
2N/A/*
2N/A * The string table contains all the strings used by the platform
2N/A * library. The comment next to each string specifies whether the
2N/A * string should be internationalized (y) or not (n).
2N/A * Note that there are calls to dgettext() with strings other than
2N/A * the ones below, they are marked by the li18 symbol.
2N/A */
2N/Astatic char *
2N/Acfga_strs[] = {
2N/A /* */ NULL,
2N/A /* n */ "cpu/mem ",
2N/A /* n */ "mem ",
2N/A /* n */ "dual-sbus ",
2N/A /* n */ "sbus-upa ",
2N/A /* n */ "dual-pci ",
2N/A /* n */ "disk ",
2N/A /* n */ "soc+sbus ",
2N/A /* n */ "soc+upa ",
2N/A /* n */ "unknown ",
2N/A /* n */ "get-status",
2N/A /* n */ "list",
2N/A /* n */ "connect",
2N/A /* n */ "disconnect",
2N/A /* n */ "configure",
2N/A /* n */ "unconfigure",
2N/A /* n */ "quiesce-test",
2N/A /* n */ "insert-test",
2N/A /* n */ "remove-test",
2N/A /* n */ "set-condition-test",
2N/A /* n */ "enable-at-boot",
2N/A /* n */ "disable-at-boot",
2N/A /* n */ "prom open",
2N/A /* n */ "prom getprop",
2N/A /* n */ "prom setprop",
2N/A /* y */ "invalid transition",
2N/A /* y */ "invalid command: ",
2N/A /* y */ "invalid option: ",
2N/A /* y */ "invalid attachment point: ",
2N/A /* y */ "board is disabled: must override with ",
2N/A /* n */ "[-f][-o enable-at-boot]",
2N/A /* y */ "transition succeeded but ",
2N/A /* y */ " failed: ",
2N/A /* y */ "was already enabled at boot time",
2N/A /* y */ "was already disabled at boot time",
2N/A /* y */ "will be enabled at boot time",
2N/A /* y */ "will be disabled at boot time",
2N/A /* y */ "\nSysctrl specific commands/options:",
2N/A /* n */ "\t-x quiesce-test ap_id [ap_id...]",
2N/A /* n */ "\t-x insert-test ap_id [ap_id...]",
2N/A /* n */ "\t-x remove-test ap_id [ap_id...]",
2N/A /* n */ "\t-x set-condition-test=<condition>",
2N/A /* n */ "\t-o enable-at-boot",
2N/A /* n */ "\t-o disable-at-boot",
2N/A /* y */ "\tunknown command or option: ",
2N/A /* y */
2N/A "system will be temporarily suspended to connect a board: proceed",
2N/A /* y */ "board ",
2N/A /* y */ ": ",
2N/A /* n */ "unknown",
2N/A /* n */ "ok",
2N/A /* n */ "failing",
2N/A /* n */ "failed",
2N/A /* n */ "unusable",
2N/A /* y */ "not enough cooling for a new board",
2N/A /* y */ "not enough power for a new board",
2N/A /* y */ "not enough precharge power for a new board",
2N/A /* y */ "configuration operation already in progress on this board",
2N/A /* y */ "could not suspend user process: ",
2N/A /* y */ "could not suspend system processes",
2N/A /* y */ "device did not attach",
2N/A /* y */ "device did not detach",
2N/A /* y */ "nexus error during attach",
2N/A /* y */ "nexus error during detach",
2N/A /* y */ "attempt to remove core system resource",
2N/A /* y */ "invalid occupant state",
2N/A /* y */ "invalid receptacle state",
2N/A /* y */ "insufficient condition",
2N/A /* y */ "firmware operation error",
2N/A /* y */ "not enough memory",
2N/A /* y */ "hotplug feature unavailable on this machine",
2N/A /* y */ "board does not support dynamic reconfiguration",
2N/A /* y */ "firmware does not support dynamic reconfiguration",
2N/A /* y */ "system suspend error",
2N/A /* y */ "system resume error",
2N/A /* y */ "unknown system error",
2N/A /* */ NULL
2N/A};
2N/A
2N/A#define cfga_str(i) cfga_strs[(i)]
2N/A
2N/A#define cfga_eid(a, b) (((a) << 8) + (b))
2N/A
2N/A/*
2N/A *
2N/A * Translation table for mapping from an <errno,sysc_err>
2N/A * pair to an error string.
2N/A *
2N/A *
2N/A * SYSC_COOLING, EAGAIN, SYSC_ERR_COOLING
2N/A * SYSC_POWER, EAGAIN, SYSC_ERR_POWER
2N/A * SYSC_PRECHARGE, EAGAIN, SYSC_ERR_PRECHARGE
2N/A * SYSC_INTRANS, EBUSY, SYSC_ERR_INTRANS
2N/A * SYSC_KTHREAD, EBUSY, SYSC_ERR_KTHREAD
2N/A * SYSC_DEV_ATTACH, EBUSY, SYSC_ERR_NDI_ATTACH
2N/A * SYSC_DEV_DETACH, EBUSY, SYSC_ERR_NDI_DETACH
2N/A * SYSC_NDI_ATTACH, EFAULT, SYSC_ERR_NDI_ATTACH
2N/A * SYSC_NDI_DETACH, EFAULT, SYSC_ERR_NDI_DETACH
2N/A * SYSC_CORE_RESOURCE, EINVAL, SYSC_ERR_CORE_RESOURCE
2N/A * SYSC_OSTATE, EINVAL, SYSC_ERR_OSTATE
2N/A * SYSC_RSTATE, EINVAL, SYSC_ERR_RSTATE
2N/A * SYSC_COND, EINVAL, SYSC_ERR_COND
2N/A * SYSC_PROM, EIO, SYSC_ERR_PROM
2N/A * SYSC_NOMEM, ENOMEM, SYSC_ERR_DR_INIT
2N/A * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_ATTACH
2N/A * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_DETACH
2N/A * SYSC_HOTPLUG, ENOTSUP, SYSC_ERR_HOTPLUG
2N/A * SYSC_HW_COMPAT, ENOTSUP, SYSC_ERR_HW_COMPAT
2N/A * SYSC_NON_DR_PROM, ENOTSUP, SYSC_ERR_NON_DR_PROM
2N/A * SYSC_SUSPEND, ENXIO, SYSC_ERR_SUSPEND
2N/A * SYSC_RESUME, ENXIO, SYSC_ERR_RESUME
2N/A * SYSC_UTHREAD, ESRCH, SYSC_ERR_UTHREAD
2N/A */
2N/Astatic int
2N/Acfga_sid(int err, int scerr)
2N/A{
2N/A if (scerr == SYSC_ERR_DEFAULT)
2N/A return (SYSC_UNKNOWN);
2N/A
2N/A switch (cfga_eid(err, scerr)) {
2N/A case cfga_eid(EAGAIN, SYSC_ERR_COOLING):
2N/A return (SYSC_COOLING);
2N/A case cfga_eid(EAGAIN, SYSC_ERR_POWER):
2N/A return (SYSC_POWER);
2N/A case cfga_eid(EAGAIN, SYSC_ERR_PRECHARGE):
2N/A return (SYSC_PRECHARGE);
2N/A case cfga_eid(EBUSY, SYSC_ERR_INTRANS):
2N/A return (SYSC_INTRANS);
2N/A case cfga_eid(EBUSY, SYSC_ERR_KTHREAD):
2N/A return (SYSC_KTHREAD);
2N/A case cfga_eid(EBUSY, SYSC_ERR_NDI_ATTACH):
2N/A return (SYSC_DEV_ATTACH);
2N/A case cfga_eid(EBUSY, SYSC_ERR_NDI_DETACH):
2N/A return (SYSC_DEV_DETACH);
2N/A case cfga_eid(EFAULT, SYSC_ERR_NDI_ATTACH):
2N/A return (SYSC_NDI_ATTACH);
2N/A case cfga_eid(EFAULT, SYSC_ERR_NDI_DETACH):
2N/A return (SYSC_NDI_DETACH);
2N/A case cfga_eid(EINVAL, SYSC_ERR_CORE_RESOURCE):
2N/A return (SYSC_CORE_RESOURCE);
2N/A case cfga_eid(EINVAL, SYSC_ERR_OSTATE):
2N/A return (SYSC_OSTATE);
2N/A case cfga_eid(EINVAL, SYSC_ERR_RSTATE):
2N/A return (SYSC_RSTATE);
2N/A case cfga_eid(EINVAL, SYSC_ERR_COND):
2N/A return (SYSC_COND);
2N/A case cfga_eid(EIO, SYSC_ERR_PROM):
2N/A return (SYSC_PROM);
2N/A case cfga_eid(ENOMEM, SYSC_ERR_DR_INIT):
2N/A return (SYSC_NOMEM);
2N/A case cfga_eid(ENOMEM, SYSC_ERR_NDI_ATTACH):
2N/A return (SYSC_NOMEM);
2N/A case cfga_eid(ENOMEM, SYSC_ERR_NDI_DETACH):
2N/A return (SYSC_NOMEM);
2N/A case cfga_eid(ENOTSUP, SYSC_ERR_HOTPLUG):
2N/A return (SYSC_HOTPLUG);
2N/A case cfga_eid(ENOTSUP, SYSC_ERR_HW_COMPAT):
2N/A return (SYSC_HW_COMPAT);
2N/A case cfga_eid(ENOTSUP, SYSC_ERR_NON_DR_PROM):
2N/A return (SYSC_NON_DR_PROM);
2N/A case cfga_eid(ENXIO, SYSC_ERR_SUSPEND):
2N/A return (SYSC_SUSPEND);
2N/A case cfga_eid(ENXIO, SYSC_ERR_RESUME):
2N/A return (SYSC_RESUME);
2N/A case cfga_eid(ESRCH, SYSC_ERR_UTHREAD):
2N/A return (SYSC_UTHREAD);
2N/A default:
2N/A break;
2N/A }
2N/A
2N/A return (SYSC_UNKNOWN);
2N/A}
2N/A
2N/Astatic void
2N/Asysc_cmd_init(sysc_cfga_cmd_t *sc, char *outputstr, int force)
2N/A{
2N/A sc->force = force;
2N/A sc->outputstr = outputstr;
2N/A sc->errtype = SYSC_ERR_DEFAULT;
2N/A
2N/A (void) memset((void *)outputstr, 0, sizeof (outputstr));
2N/A
2N/A cfga_str(SYSC_DEVSTR) = outputstr;
2N/A}
2N/A
2N/A/*
2N/A * cfga_err() accepts a variable number of message IDs and constructs
2N/A * a corresponding error string which is returned via the errstring argument.
2N/A * cfga_err() calls dgettext() to internationalize proper messages.
2N/A */
2N/Astatic void
2N/Acfga_err(sysc_cfga_cmd_t *sc, char **errstring, ...)
2N/A{
2N/A int a;
2N/A int i;
2N/A int n;
2N/A int len;
2N/A int flen;
2N/A char *p;
2N/A char *q;
2N/A char *s[32];
2N/A char *failed;
2N/A va_list ap;
2N/A char syserr_num[20];
2N/A
2N/A /*
2N/A * If errstring is null it means user in not interested in getting
2N/A * error status. So we don't do all the work
2N/A */
2N/A if (errstring == NULL) {
2N/A return;
2N/A }
2N/A va_start(ap, errstring);
2N/A
2N/A failed = dgettext(TEXT_DOMAIN, cfga_str(DIAG_FAILED));
2N/A flen = strlen(failed);
2N/A
2N/A for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
2N/A
2N/A switch (a) {
2N/A case ERR_PROM_OPEN:
2N/A case ERR_PROM_GETPROP:
2N/A case ERR_PROM_SETPROP:
2N/A case CMD_GETSTAT:
2N/A case CMD_LIST:
2N/A case CMD_CONNECT:
2N/A case CMD_DISCONNECT:
2N/A case CMD_CONFIGURE:
2N/A case CMD_UNCONFIGURE:
2N/A case CMD_QUIESCE:
2N/A case CMD_INSERT:
2N/A case CMD_REMOVE:
2N/A case CMD_SET_COND:
2N/A p = cfga_str(a);
2N/A len += (strlen(p) + flen);
2N/A s[n] = p;
2N/A s[++n] = failed;
2N/A
2N/A DBG("<%s>", p);
2N/A DBG("<%s>", failed);
2N/A break;
2N/A
2N/A case OPT_ENABLE:
2N/A case OPT_DISABLE:
2N/A p = dgettext(TEXT_DOMAIN, cfga_str(DIAG_TRANS_OK));
2N/A q = cfga_str(a);
2N/A len += (strlen(p) + strlen(q) + flen);
2N/A s[n] = p;
2N/A s[++n] = q;
2N/A s[++n] = failed;
2N/A
2N/A DBG("<%s>", p);
2N/A DBG("<%s>", q);
2N/A DBG("<%s>", failed);
2N/A break;
2N/A
2N/A case ERR_CMD_INVAL:
2N/A case ERR_AP_INVAL:
2N/A case ERR_OPT_INVAL:
2N/A p = dgettext(TEXT_DOMAIN, cfga_str(a));
2N/A q = va_arg(ap, char *);
2N/A len += (strlen(p) + strlen(q));
2N/A s[n] = p;
2N/A s[++n] = q;
2N/A
2N/A DBG("<%s>", p);
2N/A DBG("<%s>", q);
2N/A break;
2N/A
2N/A case ERR_TRANS:
2N/A case ERR_DISABLED:
2N/A p = dgettext(TEXT_DOMAIN, cfga_str(a));
2N/A len += strlen(p);
2N/A s[n] = p;
2N/A
2N/A DBG("<%s>", p);
2N/A break;
2N/A
2N/A case DIAG_FORCE:
2N/A default:
2N/A p = cfga_str(a);
2N/A len += strlen(p);
2N/A s[n] = p;
2N/A
2N/A DBG("<%s>", p);
2N/A break;
2N/A }
2N/A }
2N/A
2N/A DBG1("\n");
2N/A va_end(ap);
2N/A
2N/A if (errno) {
2N/A if (sc)
2N/A i = cfga_sid(errno, (int)sc->errtype);
2N/A else
2N/A i = SYSC_UNKNOWN;
2N/A
2N/A DBG4("cfga_sid(%d,%d)=%d\n", errno, sc->errtype, i);
2N/A
2N/A if (i == SYSC_UNKNOWN) {
2N/A p = strerror(errno);
2N/A if (p == NULL) {
2N/A (void) sprintf(syserr_num, "errno=%d", errno);
2N/A p = syserr_num;
2N/A }
2N/A } else
2N/A p = dgettext(TEXT_DOMAIN, cfga_str(i));
2N/A
2N/A len += strlen(p);
2N/A s[n++] = p;
2N/A p = cfga_str(SYSC_DEVSTR);
2N/A if (p && p[0]) {
2N/A q = cfga_str(STR_COL);
2N/A
2N/A len += strlen(q);
2N/A s[n++] = q;
2N/A len += strlen(p);
2N/A s[n++] = p;
2N/A }
2N/A }
2N/A
2N/A if ((p = (char *)calloc(len, 1)) == NULL)
2N/A return;
2N/A
2N/A for (i = 0; i < n; i++)
2N/A (void) strcat(p, s[i]);
2N/A
2N/A *errstring = p;
2N/A#ifdef SIM_MSG
2N/A printf("%s\n", *errstring);
2N/A#endif
2N/A}
2N/A
2N/A/*
2N/A * This routine accepts a variable number of message IDs and constructs
2N/A * a corresponding error string which is printed via the message print routine
2N/A * argument. The HELP_UNKNOWN message ID has an argument string (the unknown
2N/A * help topic) that follows.
2N/A */
2N/Astatic void
2N/Acfga_msg(struct cfga_msg *msgp, ...)
2N/A{
2N/A int a;
2N/A int i;
2N/A int n;
2N/A int len;
2N/A char *p;
2N/A char *s[32];
2N/A va_list ap;
2N/A
2N/A va_start(ap, msgp);
2N/A
2N/A for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) {
2N/A DBG("<%d>", a);
2N/A p = dgettext(TEXT_DOMAIN, cfga_str(a));
2N/A len += strlen(p);
2N/A s[n] = p;
2N/A if (a == HELP_UNKNOWN) {
2N/A p = va_arg(ap, char *);
2N/A len += strlen(p);
2N/A s[++n] = p;
2N/A }
2N/A }
2N/A
2N/A va_end(ap);
2N/A
2N/A if ((p = (char *)calloc(len + 1, 1)) == NULL)
2N/A return;
2N/A
2N/A for (i = 0; i < n; i++)
2N/A (void) strcat(p, s[i]);
2N/A (void) strcat(p, "\n");
2N/A
2N/A#ifdef SIM_MSG
2N/A printf("%s", p);
2N/A#else
2N/A (*msgp->message_routine)(msgp->appdata_ptr, p);
2N/A#endif
2N/A free(p);
2N/A}
2N/A
2N/Astatic sysc_cfga_stat_t *
2N/Asysc_stat(const char *ap_id, int *fdp)
2N/A{
2N/A int fd;
2N/A static sysc_cfga_stat_t sc_list[MAX_BOARDS];
2N/A
2N/A
2N/A if ((fd = open(ap_id, O_RDWR, 0)) == -1)
2N/A return (NULL);
2N/A else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sc_list) == -1) {
2N/A (void) close(fd);
2N/A return (NULL);
2N/A } else if (fdp)
2N/A *fdp = fd;
2N/A else
2N/A (void) close(fd);
2N/A
2N/A return (sc_list);
2N/A}
2N/A
2N/A/*
2N/A * This code implementes the simulation of the ioctls that transition state.
2N/A * The GETSTAT ioctl is not simulated. In this way a snapshot of the system
2N/A * state is read and manipulated by the simulation routines. It is basically
2N/A * a useful debugging tool.
2N/A */
2N/A#ifdef SIM
2N/Astatic int sim_idx;
2N/Astatic int sim_fd = -1;
2N/Astatic int sim_size = MAX_BOARDS * sizeof (sysc_cfga_stat_t);
2N/Astatic sysc_cfga_stat_t sim_sc_list[MAX_BOARDS];
2N/A
2N/Astatic sysc_cfga_stat_t *
2N/Asim_sysc_stat(const char *ap_id, int *fdp)
2N/A{
2N/A int fd;
2N/A struct stat buf;
2N/A
2N/A if (sim_fd != -1)
2N/A return (sim_sc_list);
2N/A
2N/A if ((sim_fd = open("/tmp/cfga_simdata", O_RDWR|O_CREAT)) == -1) {
2N/A perror("sim_open");
2N/A exit(1);
2N/A } else if (fstat(sim_fd, &buf) == -1) {
2N/A perror("sim_stat");
2N/A exit(1);
2N/A }
2N/A
2N/A if (buf.st_size) {
2N/A if (buf.st_size != sim_size) {
2N/A perror("sim_size");
2N/A exit(1);
2N/A } else if (read(sim_fd, sim_sc_list, sim_size) == -1) {
2N/A perror("sim_read");
2N/A exit(1);
2N/A }
2N/A } else if ((fd = open(ap_id, O_RDWR, 0)) == -1)
2N/A return (NULL);
2N/A else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sim_sc_list) == -1) {
2N/A (void) close(fd);
2N/A return (NULL);
2N/A } else if (fdp)
2N/A *fdp = fd;
2N/A
2N/A return (sim_sc_list);
2N/A}
2N/A
2N/Astatic int
2N/Asim_open(char *a, int b, int c)
2N/A{
2N/A printf("sim_open(%s)\n", a);
2N/A
2N/A if (strcmp(a, "/dev/openprom") == 0)
2N/A return (open(a, b, c));
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Asim_close(int a) { return (0); }
2N/A
2N/Astatic int
2N/Asim_ioctl(int fd, int cmd, void *a)
2N/A{
2N/A printf("sim_ioctl(%d)\n", sim_idx);
2N/A
2N/A switch (cmd) {
2N/A case SYSC_CFGA_CMD_CONNECT:
2N/A sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_CONNECTED;
2N/A break;
2N/A case SYSC_CFGA_CMD_CONFIGURE:
2N/A sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_CONFIGURED;
2N/A break;
2N/A case SYSC_CFGA_CMD_UNCONFIGURE:
2N/A sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
2N/A break;
2N/A case SYSC_CFGA_CMD_DISCONNECT:
2N/A sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
2N/A break;
2N/A case SYSC_CFGA_CMD_QUIESCE_TEST:
2N/A case SYSC_CFGA_CMD_TEST:
2N/A return (0);
2N/A case OPROMGETOPT:
2N/A return (ioctl(fd, OPROMGETOPT, a));
2N/A case OPROMSETOPT:
2N/A return (ioctl(fd, OPROMSETOPT, a));
2N/A }
2N/A
2N/A if (lseek(sim_fd, SEEK_SET, 0) == -1) {
2N/A perror("sim_seek");
2N/A exit(1);
2N/A }
2N/A if (write(sim_fd, sim_sc_list, sim_size) == -1) {
2N/A perror("sim_write");
2N/A exit(1);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A#define open(a, b, c) sim_open((char *)(a), (int)(b), (int)(c))
2N/A#define close(a) sim_close(a)
2N/A#define ioctl(a, b, c) sim_ioctl((int)(a), (int)(b), (void *)(c))
2N/A#define sysc_stat(a, b) sim_sysc_stat(a, b)
2N/A#endif /* SIM */
2N/A
2N/Astatic char *promdev = "/dev/openprom";
2N/Astatic char *dlprop = "disabled-board-list";
2N/A
2N/A#define BUFSIZE 128
2N/A
2N/Atypedef union {
2N/A char buf[BUFSIZE];
2N/A struct openpromio opp;
2N/A} oppbuf_t;
2N/A
2N/Astatic int
2N/Aprom_get_prop(int prom_fd, char *var, char **val)
2N/A{
2N/A static oppbuf_t oppbuf;
2N/A struct openpromio *opp = &(oppbuf.opp);
2N/A
2N/A (void) strncpy(opp->oprom_array, var, OBP_MAXPROPNAME);
2N/A opp->oprom_array[OBP_MAXPROPNAME + 1] = '\0';
2N/A opp->oprom_size = BUFSIZE;
2N/A
2N/A DBG3("getprop(%s, %d)\n", opp->oprom_array, opp->oprom_size);
2N/A
2N/A if (ioctl(prom_fd, OPROMGETOPT, opp) < 0)
2N/A return (ERR_PROM_GETPROP);
2N/A else if (opp->oprom_size > 0)
2N/A *val = opp->oprom_array;
2N/A else
2N/A *val = NULL;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic cfga_err_t
2N/Aprom_set_prop(int prom_fd, char *var, char *val)
2N/A{
2N/A oppbuf_t oppbuf;
2N/A struct openpromio *opp = &(oppbuf.opp);
2N/A int varlen = strlen(var) + 1;
2N/A int vallen = strlen(val);
2N/A
2N/A DBG("prom_set_prop(%s)\n", val);
2N/A
2N/A (void) strcpy(opp->oprom_array, var);
2N/A (void) strcpy(opp->oprom_array + varlen, val);
2N/A opp->oprom_size = varlen + vallen;
2N/A
2N/A if (ioctl(prom_fd, OPROMSETOPT, opp) < 0)
2N/A return (ERR_PROM_SETPROP);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Adlist_find(int board, char **dlist, int *disabled)
2N/A{
2N/A int i;
2N/A int err;
2N/A int prom_fd;
2N/A char *p;
2N/A char *dl;
2N/A char b[2];
2N/A
2N/A if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
2N/A return (ERR_PROM_OPEN);
2N/A else if (err = prom_get_prop(prom_fd, dlprop, dlist)) {
2N/A (void) close(prom_fd);
2N/A return (err);
2N/A } else
2N/A (void) close(prom_fd);
2N/A
2N/A b[1] = 0;
2N/A *disabled = 0;
2N/A
2N/A if ((dl = *dlist) != NULL) {
2N/A int len = strlen(dl);
2N/A
2N/A for (i = 0; i < len; i++) {
2N/A int bd;
2N/A
2N/A b[0] = dl[i];
2N/A bd = strtol(b, &p, 16);
2N/A
2N/A if (p != b && bd == board)
2N/A (*disabled)++;
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Adlist_update(int board, int disable, char *dlist, struct cfga_msg *msgp,
2N/A int verbose)
2N/A{
2N/A int i, j, n;
2N/A int err;
2N/A int found;
2N/A int update;
2N/A int prom_fd;
2N/A char *p;
2N/A char b[2];
2N/A char ndlist[64];
2N/A
2N/A b[1] = 0;
2N/A ndlist[0] = 0;
2N/A j = 0;
2N/A found = 0;
2N/A update = 0;
2N/A
2N/A if ((prom_fd = open(promdev, O_RDWR, 0)) < 0)
2N/A return (ERR_PROM_OPEN);
2N/A
2N/A if (dlist) {
2N/A int len = strlen(dlist);
2N/A
2N/A for (i = 0; i < len; i++) {
2N/A int bd;
2N/A
2N/A b[0] = dlist[i];
2N/A bd = strtol(b, &p, 16);
2N/A
2N/A if (p != b && bd == board) {
2N/A
2N/A found++;
2N/A if (disable) {
2N/A if (verbose)
2N/A cfga_msg(msgp, STR_BD,
2N/A DIAG_WAS_DISABLED, 0);
2N/A } else {
2N/A if (verbose)
2N/A cfga_msg(msgp, STR_BD,
2N/A DIAG_WILL_ENABLE, 0);
2N/A update++;
2N/A continue;
2N/A }
2N/A }
2N/A ndlist[j++] = dlist[i];
2N/A }
2N/A ndlist[j] = 0;
2N/A }
2N/A
2N/A if (!found)
2N/A if (disable) {
2N/A if (verbose)
2N/A cfga_msg(msgp, STR_BD, DIAG_WILL_DISABLE, 0);
2N/A p = &ndlist[j];
2N/A n = sprintf(p, "%x", board);
2N/A p[n] = 0;
2N/A update++;
2N/A } else {
2N/A if (verbose)
2N/A cfga_msg(msgp, STR_BD, DIAG_WAS_ENABLED, 0);
2N/A }
2N/A
2N/A if (update)
2N/A err = prom_set_prop(prom_fd, dlprop, ndlist);
2N/A else
2N/A err = 0;
2N/A
2N/A (void) close(prom_fd);
2N/A
2N/A return (err);
2N/A}
2N/A
2N/Astatic int
2N/Aap_idx(const char *ap_id)
2N/A{
2N/A int id;
2N/A char *s;
2N/A static char *slot = "slot";
2N/A
2N/A DBG("ap_idx(%s)\n", ap_id);
2N/A
2N/A if ((s = strstr(ap_id, slot)) == NULL)
2N/A return (-1);
2N/A else {
2N/A int n;
2N/A
2N/A s += strlen(slot);
2N/A n = strlen(s);
2N/A
2N/A DBG3("ap_idx: s=%s, n=%d\n", s, n);
2N/A
2N/A switch (n) {
2N/A case 2:
2N/A if (!isdigit(s[1]))
2N/A return (-1);
2N/A /* FALLTHROUGH */
2N/A case 1:
2N/A if (!isdigit(s[0]))
2N/A return (-1);
2N/A break;
2N/A default:
2N/A return (-1);
2N/A }
2N/A }
2N/A
2N/A if ((id = atoi(s)) > MAX_BOARDS)
2N/A return (-1);
2N/A
2N/A DBG3("ap_idx(%s)=%d\n", s, id);
2N/A
2N/A return (id);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_change_state(
2N/A cfga_cmd_t state_change_cmd,
2N/A const char *ap_id,
2N/A const char *options,
2N/A struct cfga_confirm *confp,
2N/A struct cfga_msg *msgp,
2N/A char **errstring,
2N/A cfga_flags_t flags)
2N/A{
2N/A int fd;
2N/A int idx;
2N/A int err;
2N/A int force;
2N/A int verbose;
2N/A int opterr;
2N/A int disable;
2N/A int disabled;
2N/A cfga_err_t rc;
2N/A sysc_cfga_stat_t *ss;
2N/A sysc_cfga_cmd_t *sc, sysc_cmd;
2N/A sysc_cfga_rstate_t rs;
2N/A sysc_cfga_ostate_t os;
2N/A char *dlist;
2N/A char outputstr[SYSC_OUTPUT_LEN];
2N/A
2N/A if (errstring != NULL)
2N/A *errstring = NULL;
2N/A
2N/A rc = CFGA_ERROR;
2N/A
2N/A if (options) {
2N/A disable = 0;
2N/A if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
2N/A disable++;
2N/A else if (strcmp(options, cfga_str(OPT_ENABLE))) {
2N/A cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
2N/A return (rc);
2N/A }
2N/A }
2N/A
2N/A if ((idx = ap_idx(ap_id)) == -1) {
2N/A cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
2N/A return (rc);
2N/A } else if ((ss = sysc_stat(ap_id, &fd)) == NULL) {
2N/A cfga_err(NULL, errstring, CMD_GETSTAT, 0);
2N/A return (rc);
2N/A }
2N/A#ifdef SIM
2N/A sim_idx = idx;
2N/A#endif
2N/A /*
2N/A * We disallow connecting on the disabled list unless
2N/A * either the FORCE flag or the enable-at-boot option
2N/A * is set. The check is made further below
2N/A */
2N/A if (opterr = dlist_find(idx, &dlist, &disabled)) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A (void) close(fd);
2N/A return (rc);
2N/A } else
2N/A force = flags & CFGA_FLAG_FORCE;
2N/A
2N/A rs = ss[idx].rstate;
2N/A os = ss[idx].ostate;
2N/A
2N/A sc = &sysc_cmd;
2N/A sysc_cmd_init(sc, outputstr, force);
2N/A verbose = flags & CFGA_FLAG_VERBOSE;
2N/A
2N/A switch (state_change_cmd) {
2N/A case CFGA_CMD_CONNECT:
2N/A if (rs != SYSC_CFGA_RSTATE_DISCONNECTED)
2N/A cfga_err(NULL, errstring, ERR_TRANS, 0);
2N/A else if (disabled && !(force || (options && !disable)))
2N/A cfga_err(NULL, errstring, CMD_CONNECT,
2N/A ERR_DISABLED, DIAG_FORCE, 0);
2N/A else if (!(*confp->confirm)(confp->appdata_ptr,
2N/A cfga_str(ASK_CONNECT))) {
2N/A (void) close(fd);
2N/A return (CFGA_NACK);
2N/A } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1)
2N/A cfga_err(sc, errstring, CMD_CONNECT, 0);
2N/A else if (options && (opterr = dlist_update(idx, disable,
2N/A dlist, msgp, verbose))) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A } else
2N/A rc = CFGA_OK;
2N/A break;
2N/A
2N/A case CFGA_CMD_DISCONNECT:
2N/A if ((os == SYSC_CFGA_OSTATE_CONFIGURED) &&
2N/A (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)) {
2N/A cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
2N/A (void) close(fd);
2N/A return (CFGA_ERROR);
2N/A } else
2N/A sysc_cmd_init(sc, outputstr, force);
2N/A
2N/A if (rs == SYSC_CFGA_RSTATE_CONNECTED) {
2N/A if (ioctl(fd, SYSC_CFGA_CMD_DISCONNECT, sc) == -1)
2N/A cfga_err(sc, errstring, CMD_DISCONNECT, 0);
2N/A else if (options && (opterr = dlist_update(idx, disable,
2N/A dlist, msgp, verbose))) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A } else
2N/A rc = CFGA_OK;
2N/A } else
2N/A cfga_err(NULL, errstring, ERR_TRANS, 0);
2N/A break;
2N/A
2N/A case CFGA_CMD_CONFIGURE:
2N/A if (rs == SYSC_CFGA_RSTATE_DISCONNECTED)
2N/A if (disabled && !(force || (options && !disable))) {
2N/A cfga_err(NULL, errstring, CMD_CONFIGURE,
2N/A ERR_DISABLED, DIAG_FORCE, 0);
2N/A (void) close(fd);
2N/A return (CFGA_ERROR);
2N/A } else if (!(*confp->confirm)(confp->appdata_ptr,
2N/A cfga_str(ASK_CONNECT))) {
2N/A (void) close(fd);
2N/A return (CFGA_NACK);
2N/A } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1) {
2N/A cfga_err(sc, errstring, CMD_CONNECT, 0);
2N/A (void) close(fd);
2N/A return (CFGA_ERROR);
2N/A } else
2N/A sysc_cmd_init(sc, outputstr, force);
2N/A
2N/A if (os == SYSC_CFGA_OSTATE_UNCONFIGURED) {
2N/A if (ioctl(fd, SYSC_CFGA_CMD_CONFIGURE, sc) == -1)
2N/A cfga_err(sc, errstring, CMD_CONFIGURE, 0);
2N/A else if (options && (opterr = dlist_update(idx,
2N/A disable, dlist, msgp, verbose))) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A } else
2N/A rc = CFGA_OK;
2N/A } else
2N/A cfga_err(NULL, errstring, ERR_TRANS, 0);
2N/A break;
2N/A
2N/A case CFGA_CMD_UNCONFIGURE:
2N/A if (os != SYSC_CFGA_OSTATE_CONFIGURED)
2N/A cfga_err(NULL, errstring, ERR_TRANS, 0);
2N/A else if (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)
2N/A cfga_err(sc, errstring, CMD_UNCONFIGURE, 0);
2N/A else if (options && (opterr = dlist_update(idx, disable,
2N/A dlist, msgp, verbose))) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A } else
2N/A rc = CFGA_OK;
2N/A break;
2N/A
2N/A default:
2N/A rc = CFGA_OPNOTSUPP;
2N/A break;
2N/A }
2N/A
2N/A (void) close(fd);
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Astr2cond(const char *cond)
2N/A{
2N/A int c;
2N/A
2N/A if (strcmp(cond, cfga_str(COND_UNKNOWN)) == 0)
2N/A c = SYSC_CFGA_COND_UNKNOWN;
2N/A else if (strcmp(cond, cfga_str(COND_OK)) == 0)
2N/A c = SYSC_CFGA_COND_OK;
2N/A else if (strcmp(cond, cfga_str(COND_FAILING)) == 0)
2N/A c = SYSC_CFGA_COND_FAILING;
2N/A else if (strcmp(cond, cfga_str(COND_FAILED)) == 0)
2N/A c = SYSC_CFGA_COND_FAILED;
2N/A else if (strcmp(cond, cfga_str(COND_UNUSABLE)) == 0)
2N/A c = SYSC_CFGA_COND_UNUSABLE;
2N/A else
2N/A c = -1;
2N/A
2N/A return (c);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_private_func(
2N/A const char *function,
2N/A const char *ap_id,
2N/A const char *options,
2N/A struct cfga_confirm *confp,
2N/A struct cfga_msg *msgp,
2N/A char **errstring,
2N/A cfga_flags_t flags)
2N/A{
2N/A int fd;
2N/A int idx;
2N/A int len;
2N/A int cmd;
2N/A int cond;
2N/A int err;
2N/A int opterr;
2N/A int verbose;
2N/A int disable;
2N/A int disabled;
2N/A cfga_err_t rc;
2N/A char *str;
2N/A char *dlist;
2N/A char outputstr[SYSC_OUTPUT_LEN];
2N/A sysc_cfga_cmd_t *sc, sysc_cmd;
2N/A
2N/A if (errstring != NULL)
2N/A *errstring = NULL;
2N/A
2N/A verbose = flags & CFGA_FLAG_VERBOSE;
2N/A
2N/A rc = CFGA_ERROR;
2N/A
2N/A if (options) {
2N/A disable = 0;
2N/A if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
2N/A disable++;
2N/A else if (strcmp(options, cfga_str(OPT_ENABLE))) {
2N/A cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
2N/A return (rc);
2N/A }
2N/A }
2N/A
2N/A sc = &sysc_cmd;
2N/A str = cfga_str(CMD_SET_COND);
2N/A len = strlen(str);
2N/A
2N/A if ((strncmp(function, str, len) == 0) && (function[len++] == '=') &&
2N/A ((cond = (str2cond(&function[len]))) != -1)) {
2N/A cmd = SYSC_CFGA_CMD_TEST_SET_COND;
2N/A err = CMD_SET_COND;
2N/A sc->arg = cond;
2N/A } else if (strcmp(function, cfga_str(CMD_QUIESCE)) == 0) {
2N/A cmd = SYSC_CFGA_CMD_QUIESCE_TEST;
2N/A err = CMD_QUIESCE;
2N/A } else if (strcmp(function, cfga_str(CMD_INSERT)) == 0) {
2N/A cmd = SYSC_CFGA_CMD_TEST;
2N/A err = CMD_INSERT;
2N/A } else if (strcmp(function, cfga_str(CMD_REMOVE)) == 0) {
2N/A cmd = SYSC_CFGA_CMD_TEST;
2N/A err = CMD_REMOVE;
2N/A } else {
2N/A cfga_err(NULL, errstring, ERR_CMD_INVAL, (char *)function, 0);
2N/A return (rc);
2N/A }
2N/A
2N/A sysc_cmd_init(sc, outputstr, 0);
2N/A
2N/A if ((idx = ap_idx(ap_id)) == -1)
2N/A cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
2N/A else if (((fd = open(ap_id, O_RDWR, 0)) == -1) ||
2N/A (ioctl(fd, cmd, sc) == -1))
2N/A cfga_err(NULL, errstring, err, 0);
2N/A else
2N/A rc = CFGA_OK;
2N/A
2N/A if (options) {
2N/A opterr = (dlist_find(idx, &dlist, &disabled) ||
2N/A dlist_update(idx, disable, dlist, msgp, verbose));
2N/A if (opterr) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A if (verbose)
2N/A cfga_msg(msgp, err, opterr, 0);
2N/A }
2N/A }
2N/A
2N/A (void) close(fd);
2N/A return (rc);
2N/A}
2N/A
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_test(
2N/A const char *ap_id,
2N/A const char *options,
2N/A struct cfga_msg *msgp,
2N/A char **errstring,
2N/A cfga_flags_t flags)
2N/A{
2N/A if (errstring != NULL)
2N/A *errstring = NULL;
2N/A
2N/A return (CFGA_OPNOTSUPP);
2N/A}
2N/A
2N/Astatic cfga_stat_t
2N/Arstate_cvt(sysc_cfga_rstate_t rs)
2N/A{
2N/A cfga_stat_t cs;
2N/A
2N/A switch (rs) {
2N/A case SYSC_CFGA_RSTATE_EMPTY:
2N/A cs = CFGA_STAT_EMPTY;
2N/A break;
2N/A case SYSC_CFGA_RSTATE_DISCONNECTED:
2N/A cs = CFGA_STAT_DISCONNECTED;
2N/A break;
2N/A case SYSC_CFGA_RSTATE_CONNECTED:
2N/A cs = CFGA_STAT_CONNECTED;
2N/A break;
2N/A default:
2N/A cs = CFGA_STAT_NONE;
2N/A break;
2N/A }
2N/A
2N/A return (cs);
2N/A}
2N/A
2N/Astatic cfga_stat_t
2N/Aostate_cvt(sysc_cfga_ostate_t os)
2N/A{
2N/A cfga_stat_t cs;
2N/A
2N/A switch (os) {
2N/A case SYSC_CFGA_OSTATE_UNCONFIGURED:
2N/A cs = CFGA_STAT_UNCONFIGURED;
2N/A break;
2N/A case SYSC_CFGA_OSTATE_CONFIGURED:
2N/A cs = CFGA_STAT_CONFIGURED;
2N/A break;
2N/A default:
2N/A cs = CFGA_STAT_NONE;
2N/A break;
2N/A }
2N/A
2N/A return (cs);
2N/A}
2N/A
2N/Astatic cfga_cond_t
2N/Acond_cvt(sysc_cfga_cond_t sc)
2N/A{
2N/A cfga_cond_t cc;
2N/A
2N/A switch (sc) {
2N/A case SYSC_CFGA_COND_OK:
2N/A cc = CFGA_COND_OK;
2N/A break;
2N/A case SYSC_CFGA_COND_FAILING:
2N/A cc = CFGA_COND_FAILING;
2N/A break;
2N/A case SYSC_CFGA_COND_FAILED:
2N/A cc = CFGA_COND_FAILED;
2N/A break;
2N/A case SYSC_CFGA_COND_UNUSABLE:
2N/A cc = CFGA_COND_UNUSABLE;
2N/A break;
2N/A case SYSC_CFGA_COND_UNKNOWN:
2N/A default:
2N/A cc = CFGA_COND_UNKNOWN;
2N/A break;
2N/A }
2N/A
2N/A return (cc);
2N/A}
2N/A
2N/Astatic char *
2N/Atype_str(enum board_type type)
2N/A{
2N/A char *type_str;
2N/A
2N/A switch (type) {
2N/A case MEM_BOARD:
2N/A type_str = cfga_str(BD_MEM);
2N/A break;
2N/A case CPU_BOARD:
2N/A type_str = cfga_str(BD_CPU);
2N/A break;
2N/A case IO_2SBUS_BOARD:
2N/A type_str = cfga_str(BD_IO_2SBUS);
2N/A break;
2N/A case IO_SBUS_FFB_BOARD:
2N/A type_str = cfga_str(BD_IO_SBUS_FFB);
2N/A break;
2N/A case IO_PCI_BOARD:
2N/A type_str = cfga_str(BD_IO_PCI);
2N/A break;
2N/A case DISK_BOARD:
2N/A type_str = cfga_str(BD_DISK);
2N/A break;
2N/A case IO_2SBUS_SOCPLUS_BOARD:
2N/A type_str = cfga_str(BD_IO_2SBUS_SOCPLUS);
2N/A break;
2N/A case IO_SBUS_FFB_SOCPLUS_BOARD:
2N/A type_str = cfga_str(BD_IO_SBUS_FFB_SOCPLUS);
2N/A break;
2N/A case UNKNOWN_BOARD:
2N/A default:
2N/A type_str = cfga_str(BD_UNKNOWN);
2N/A break;
2N/A }
2N/A return (type_str);
2N/A}
2N/A
2N/Astatic void
2N/Ainfo_set(sysc_cfga_stat_t *sc, cfga_info_t info, int disabled)
2N/A{
2N/A int i;
2N/A struct cpu_info *cpu;
2N/A union bd_un *bd = &sc->bd;
2N/A
2N/A *info = NULL;
2N/A
2N/A switch (sc->type) {
2N/A case CPU_BOARD:
2N/A for (i = 0, cpu = bd->cpu; i < 2; i++, cpu++) {
2N/A if (cpu->cpu_speed > 1) {
2N/A info += sprintf(info, "cpu %d: ", i);
2N/A info += sprintf(info, "%3d MHz ",
2N/A cpu->cpu_speed);
2N/A if (cpu->cache_size)
2N/A info += sprintf(info, "%0.1fM ",
2N/A (float)cpu->cache_size /
2N/A (float)(1024 * 1024));
2N/A }
2N/A }
2N/A break;
2N/A case IO_SBUS_FFB_BOARD:
2N/A switch (bd->io2.ffb_size) {
2N/A case FFB_SINGLE:
2N/A info += sprintf(info, "single buffered ffb ");
2N/A break;
2N/A case FFB_DOUBLE:
2N/A info += sprintf(info, "double buffered ffb ");
2N/A break;
2N/A case FFB_NOT_FOUND:
2N/A#ifdef FFB_DR_SUPPORT
2N/A info += sprintf(info, "no ffb installed ");
2N/A#endif
2N/A break;
2N/A default:
2N/A info += sprintf(info, "illegal ffb size ");
2N/A break;
2N/A }
2N/A break;
2N/A case DISK_BOARD:
2N/A for (i = 0; i < 2; i++)
2N/A if (bd->dsk.disk_pres[i])
2N/A info += sprintf(info, "target: %2d ",
2N/A bd->dsk.disk_id[i]);
2N/A else
2N/A info += sprintf(info, "no disk ");
2N/A break;
2N/A }
2N/A
2N/A if (disabled)
2N/A info += sprintf(info, "disabled at boot ");
2N/A
2N/A if (sc->no_detach)
2N/A info += sprintf(info, "non-detachable ");
2N/A
2N/A if (sc->plus_board)
2N/A info += sprintf(info, "100 MHz capable ");
2N/A}
2N/A
2N/Astatic void
2N/Asysc_cvt(sysc_cfga_stat_t *sc, cfga_stat_data_t *cs, int disabled)
2N/A{
2N/A (void) strcpy(cs->ap_type, type_str(sc->type));
2N/A cs->ap_r_state = rstate_cvt(sc->rstate);
2N/A cs->ap_o_state = ostate_cvt(sc->ostate);
2N/A cs->ap_cond = cond_cvt(sc->condition);
2N/A cs->ap_busy = (cfga_busy_t)sc->in_transition;
2N/A cs->ap_status_time = sc->last_change;
2N/A info_set(sc, cs->ap_info, disabled);
2N/A cs->ap_log_id[0] = NULL;
2N/A cs->ap_phys_id[0] = NULL;
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_list(
2N/A const char *ap_id,
2N/A cfga_stat_data_t **ap_list,
2N/A int *nlist,
2N/A const char *options,
2N/A char **errstring)
2N/A{
2N/A int i;
2N/A cfga_err_t rc;
2N/A sysc_cfga_stat_t *sc;
2N/A cfga_stat_data_t *cs;
2N/A
2N/A if (errstring != NULL)
2N/A *errstring = NULL;
2N/A
2N/A rc = CFGA_ERROR;
2N/A
2N/A if (ap_idx(ap_id) == -1)
2N/A cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
2N/A else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
2N/A cfga_err(NULL, errstring, CMD_LIST, 0);
2N/A else if (!(cs = (cfga_stat_data_t *)malloc(MAX_BOARDS * sizeof (*cs))))
2N/A cfga_err(NULL, errstring, CMD_LIST, 0);
2N/A else {
2N/A *ap_list = cs;
2N/A
2N/A for (*nlist = 0, i = 0; i < MAX_BOARDS; i++, sc++) {
2N/A if (sc->board == -1)
2N/A continue;
2N/A sysc_cvt(sc, cs++, 0); /* XXX - disable */
2N/A (*nlist)++;
2N/A }
2N/A
2N/A rc = CFGA_OK;
2N/A }
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_stat(
2N/A const char *ap_id,
2N/A struct cfga_stat_data *cs,
2N/A const char *options,
2N/A char **errstring)
2N/A{
2N/A cfga_err_t rc;
2N/A int idx;
2N/A int err;
2N/A int opterr;
2N/A int disable;
2N/A int disabled;
2N/A char *dlist;
2N/A sysc_cfga_stat_t *sc;
2N/A
2N/A if (errstring != NULL)
2N/A *errstring = NULL;
2N/A
2N/A rc = CFGA_ERROR;
2N/A
2N/A if (options && options[0]) {
2N/A disable = 0;
2N/A if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
2N/A disable++;
2N/A else if (strcmp(options, cfga_str(OPT_ENABLE))) {
2N/A cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0);
2N/A return (rc);
2N/A }
2N/A }
2N/A
2N/A if ((idx = ap_idx(ap_id)) == -1)
2N/A cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0);
2N/A else if ((sc = sysc_stat(ap_id, NULL)) == NULL)
2N/A cfga_err(NULL, errstring, CMD_GETSTAT, 0);
2N/A else {
2N/A opterr = dlist_find(idx, &dlist, &disabled);
2N/A sysc_cvt(sc + idx, cs, disabled);
2N/A
2N/A rc = CFGA_OK;
2N/A
2N/A if (options && options[0] && ((opterr != 0) ||
2N/A ((opterr = dlist_update(idx, disable, dlist, NULL, 0))
2N/A != 0))) {
2N/A err = disable ? OPT_DISABLE : OPT_ENABLE;
2N/A cfga_err(NULL, errstring, err, opterr, 0);
2N/A }
2N/A }
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Acfga_err_t
2N/Acfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
2N/A{
2N/A int help = 0;
2N/A
2N/A if (options) {
2N/A if (strcmp(options, cfga_str(OPT_DISABLE)) == 0)
2N/A help = HELP_DISABLE;
2N/A else if (strcmp(options, cfga_str(OPT_ENABLE)) == 0)
2N/A help = HELP_ENABLE;
2N/A else if (strcmp(options, cfga_str(CMD_INSERT)) == 0)
2N/A help = HELP_INSERT;
2N/A else if (strcmp(options, cfga_str(CMD_REMOVE)) == 0)
2N/A help = HELP_REMOVE;
2N/A else if (strcmp(options, cfga_str(CMD_QUIESCE)) == 0)
2N/A help = HELP_QUIESCE;
2N/A else
2N/A help = HELP_UNKNOWN;
2N/A }
2N/A
2N/A if (help) {
2N/A if (help == HELP_UNKNOWN)
2N/A cfga_msg(msgp, help, options, 0);
2N/A else
2N/A cfga_msg(msgp, help, 0);
2N/A } else {
2N/A cfga_msg(msgp, HELP_HEADER, 0);
2N/A cfga_msg(msgp, HELP_DISABLE, 0);
2N/A cfga_msg(msgp, HELP_ENABLE, 0);
2N/A cfga_msg(msgp, HELP_INSERT, 0);
2N/A cfga_msg(msgp, HELP_REMOVE, 0);
2N/A cfga_msg(msgp, HELP_QUIESCE, 0);
2N/A cfga_msg(msgp, HELP_SET_COND, 0);
2N/A }
2N/A
2N/A return (CFGA_OK);
2N/A}
2N/A
2N/A/*
2N/A * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
2N/A */