#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ddi_impldefs.h>
#include <sys/obpdefs.h>
#include <sys/promif.h>
#include <sys/cmn_err.h>
#include <sys/errno.h>
#include <sys/kmem.h>
#include <sys/kstat.h>
#include <sys/debug.h>
#include <sys/fhc.h>
#include <sys/jtag.h>
#include <sys/sysctrl.h>
static fhc_bd_resizable_t boards;
static fhc_bd_resizable_t clocks;
static int fhc_bdmax;
static krwlock_t fhc_bdlist_rwlock;
static sysc_evt_handle_t fhc_bd_evt;
static sysc_evt_handle_t *fbe = &fhc_bd_evt;
#define fhc_bd_sc_evt(s, e) (*fbe->update)(fbe->soft, s, e)
#define FHC_INCREMENT 4
#define FHC_B_SEARCH(in_array, board) \
fhc_b_search(in_array.boards, board, 0, in_array.last);
static int fhc_bd_disabled(int);
static void fhc_check_array(int);
static void fhc_shell_sort(fhc_bd_t **, int, int);
static int fhc_b_search(fhc_bd_t **, int, int, int);
static void fhc_check_size(fhc_bd_resizable_t *);
static void fhc_resize(fhc_bd_t ***, int, int);
int
fhc_max_boards()
{
return (fhc_bdmax + 1);
}
static int
fhc_bd_disabled(int board)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
return (boards.boards[index]->flags & BDF_DISABLED);
}
static void
fhc_check_array(int btype)
{
if (btype == FHC_BOARDS) {
ASSERT(fhc_bdlist_locked());
if (!boards.sorted) {
fhc_shell_sort(boards.boards, 0, boards.last);
boards.sorted = TRUE;
}
} else {
ASSERT(fhc_bdlist_locked());
if (!clocks.sorted) {
fhc_shell_sort(clocks.boards, 0, clocks.last);
clocks.sorted = TRUE;
}
}
}
static void
fhc_shell_sort(fhc_bd_t *a[], int lb, int ub)
{
int n, h, i, j;
fhc_bd_t *t;
n = ub - lb + 1;
h = 1;
if (n < 14)
h = 1;
else {
while (h < n)
h = 3 * h + 1;
h /= 3;
h /= 3;
}
while (h > 0) {
for (i = lb + h; i <= ub; i++) {
t = a[i];
for (j = i - h;
j >= lb && a[j]->sc.board > t->sc.board;
j -= h) {
a[j+h] = a[j];
}
a[j+h] = t;
}
h /= 3;
}
}
static int
fhc_b_search(fhc_bd_t *in_array[], int board, int first, int last)
{
int mid;
if (in_array == NULL)
return (-1);
while (first < last) {
mid = (first + last) / 2;
if (in_array[mid]->sc.board < board)
first = mid + 1;
else
last = mid;
}
if (in_array[first]->sc.board == board) {
return (first);
} else {
return (-1);
}
}
static void
fhc_check_size(fhc_bd_resizable_t *resizable)
{
int oldsize;
int newsize;
ASSERT(fhc_bdlist_locked());
if (resizable->size == resizable->last + 1) {
oldsize = sizeof (fhc_bd_t *) * resizable->size;
resizable->size += FHC_INCREMENT;
newsize = sizeof (fhc_bd_t *) * resizable->size;
fhc_resize(&(resizable->boards), oldsize, newsize);
}
}
int
fhc_bdlist_locked()
{
if (panicstr)
return (1);
return (rw_owner(&fhc_bdlist_rwlock) == curthread);
}
int
fhc_bd_busy(int board)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
return (boards.boards[index]->sc.in_transition);
}
int
fhc_bd_is_jtag_master(int board)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
if (boards.boards[index]->softsp == NULL)
return (FALSE);
else
return ((boards.boards[index]->softsp)->jt_master.is_master);
}
int
fhc_bd_is_plus(int board)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
if (boards.boards[index]->sc.plus_board)
return (boards.boards[index]->sc.plus_board);
else
return (FALSE);
}
void
fhc_bdlist_init()
{
ASSERT(!fhc_bdmax);
rw_init(&fhc_bdlist_rwlock, NULL, RW_DEFAULT, NULL);
boards.boards = NULL;
boards.size = 0;
boards.last = -1;
boards.sorted = TRUE;
clocks.boards = NULL;
clocks.size = 0;
clocks.last = -1;
clocks.sorted = TRUE;
}
void
fhc_bdlist_fini()
{
rw_destroy(&fhc_bdlist_rwlock);
}
fhc_bd_t *
fhc_bdlist_lock(int board)
{
int index;
ASSERT(!fhc_bdlist_locked());
rw_enter(&fhc_bdlist_rwlock, RW_WRITER);
if (board == -1)
return (NULL);
else {
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
return (boards.boards[index]);
}
}
void
fhc_bdlist_unlock()
{
ASSERT(fhc_bdlist_locked());
rw_exit(&fhc_bdlist_rwlock);
}
static void
fhc_resize(fhc_bd_t ***in_array, int oldsize, int newsize)
{
fhc_bd_t **temp;
ASSERT(newsize > oldsize);
temp = kmem_alloc(newsize, KM_SLEEP);
if (*in_array != NULL) {
ASSERT(oldsize > 0);
bcopy(*in_array, temp, oldsize);
kmem_free(*in_array, oldsize);
}
*in_array = temp;
}
void
fhc_bd_init(struct fhc_soft_state *softsp, int board, enum board_type type)
{
fhc_bd_t *bdp;
int index;
(void) fhc_bdlist_lock(-1);
ASSERT(boards.sorted);
ASSERT(clocks.sorted);
if (softsp->is_central) {
index = FHC_B_SEARCH(clocks, board);
} else {
index = FHC_B_SEARCH(boards, board);
}
if (index != -1) {
if (softsp->is_central) {
bdp = clocks.boards[index];
} else {
bdp = boards.boards[index];
}
} else {
if (softsp->is_central) {
fhc_check_size(&clocks);
clocks.boards[clocks.last + 1] =
kmem_zalloc(sizeof (fhc_bd_t), KM_SLEEP);
bdp = clocks.boards[clocks.last + 1];
clocks.last++;
clocks.sorted = FALSE;
} else {
fhc_check_size(&boards);
boards.boards[boards.last + 1] =
kmem_zalloc(sizeof (fhc_bd_t), KM_SLEEP);
bdp = boards.boards[boards.last + 1];
boards.last++;
boards.sorted = FALSE;
}
}
softsp->list = bdp;
bdp->flags |= BDF_VALID;
bdp->softsp = softsp;
bdp->sc.type = type;
bdp->sc.board = board;
bdp->sc.plus_board = ISPLUSBRD(*softsp->bsr);
fhc_check_array(FHC_BOARDS);
fhc_check_array(FHC_CLOCKS);
fhc_bdlist_unlock();
}
fhc_bd_t *
fhc_bd(int board)
{
int index;
if (fhc_bdmax) {
ASSERT(fhc_bdlist_locked());
}
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
ASSERT(index != -1);
return (boards.boards[index]);
}
fhc_bd_t *
fhc_bd_clock(void)
{
ASSERT(fhc_bdlist_locked());
ASSERT(clocks.size != 0);
return (clocks.boards[0]);
}
fhc_bd_t *
fhc_bd_first()
{
ASSERT(fhc_bdlist_locked());
if (boards.boards != NULL)
return (boards.boards[0]);
else
return (NULL);
}
fhc_bd_t *
fhc_bd_next(fhc_bd_t *bdp)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, bdp->sc.board);
ASSERT(index != -1);
if (index < boards.last)
return (boards.boards[index + 1]);
else
return (NULL);
}
int
fhc_bd_valid(int bd)
{
int index;
ASSERT(bd >= 0);
if (!fhc_bdmax)
return (TRUE);
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, bd);
if (index == -1)
return (FALSE);
else
return (TRUE);
}
enum board_type
fhc_bd_type(int board)
{
int index;
ASSERT(boards.sorted);
index = FHC_B_SEARCH(boards, board);
if (index == -1)
return (-1);
return (boards.boards[index]->sc.type);
}
char *
fhc_bd_typestr(enum board_type type)
{
char *type_str;
switch (type) {
case MEM_BOARD:
type_str = MEM_BD_NAME;
break;
case CPU_BOARD:
type_str = CPU_BD_NAME;
break;
case IO_2SBUS_BOARD:
type_str = IO_2SBUS_BD_NAME;
break;
case IO_SBUS_FFB_BOARD:
type_str = IO_SBUS_FFB_BD_NAME;
break;
case IO_2SBUS_SOCPLUS_BOARD:
type_str = IO_2SBUS_SOCPLUS_BD_NAME;
break;
case IO_SBUS_FFB_SOCPLUS_BOARD:
type_str = IO_SBUS_FFB_SOCPLUS_BD_NAME;
break;
case IO_PCI_BOARD:
type_str = IO_PCI_BD_NAME;
break;
case DISK_BOARD:
type_str = DISK_BD_NAME;
break;
case UNKNOWN_BOARD:
default:
type_str = "unknown";
break;
}
return (type_str);
}
void
fhc_bd_env_set(int board, void *env)
{
fhc_bd_t *bdp;
bdp = fhc_bd(board);
bdp->dev_softsp = env;
}
static void
fhc_bd_dlist_init()
{
int i;
int len;
int board;
pnode_t node;
char *dlist;
int index;
if (((node = prom_finddevice("/options")) == OBP_BADNODE) ||
((len = prom_getproplen(node, "disabled-board-list")) == -1))
return;
dlist = kmem_alloc(len, KM_SLEEP);
(void) prom_getprop(node, "disabled-board-list", dlist);
for (i = 0; (i < len) && (dlist[i] != 0); i++) {
char ch = dlist[i];
if (ch >= '0' && ch <= '9')
board = ch - '0';
else if (ch >= 'A' && ch <= 'F')
board = ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
board = ch - 'a' + 10;
else
continue;
index = FHC_B_SEARCH(boards, board);
if (index != -1) {
boards.boards[index]->flags |= BDF_DISABLED;
}
}
kmem_free(dlist, len);
}
static struct bd_info fhc_bd_info;
static int
fhc_bd_ks_update(kstat_t *ksp, int rw)
{
fhc_bd_t *bdp;
sysc_cfga_stat_t *sc;
struct bd_info *uip;
enum board_state state;
if (rw == KSTAT_WRITE)
return (EACCES);
bdp = (fhc_bd_t *)ksp->ks_private;
uip = &fhc_bd_info;
sc = &bdp->sc;
ASSERT(fhc_bd_valid(sc->board));
uip->board = sc->board;
uip->type = sc->type;
uip->fhc_compid = sc->fhc_compid;
uip->ac_compid = sc->ac_compid;
bcopy((caddr_t)sc->prom_rev, uip->prom_rev, sizeof (uip->prom_rev));
bcopy((caddr_t)&sc->bd, &uip->bd, sizeof (union bd_un));
switch (sc->rstate) {
case SYSC_CFGA_RSTATE_DISCONNECTED:
switch (sc->condition) {
case SYSC_CFGA_COND_OK:
case SYSC_CFGA_COND_UNKNOWN:
state = DISABLED_STATE;
break;
case SYSC_CFGA_COND_FAILING:
case SYSC_CFGA_COND_FAILED:
case SYSC_CFGA_COND_UNUSABLE:
state = FAILED_STATE;
break;
default:
state = UNKNOWN_STATE;
break;
}
break;
default:
state = UNKNOWN_STATE;
break;
}
uip->state = state;
return (0);
}
void
fhc_bd_ks_alloc(fhc_bd_t *bdp)
{
ASSERT(!bdp->ksp);
bdp->ksp = kstat_create("unix", bdp->sc.board,
BDLIST_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
sizeof (struct bd_info), KSTAT_FLAG_VIRTUAL);
if (bdp->ksp != NULL) {
bdp->ksp->ks_data = &fhc_bd_info;
bdp->ksp->ks_update = fhc_bd_ks_update;
bdp->ksp->ks_private = (void *)bdp;
kstat_install(bdp->ksp);
}
}
static void
fhc_bdlist_dk_init()
{
dev_info_t *dnode;
for (dnode = ddi_get_child(ddi_root_node());
dnode != NULL; dnode = ddi_get_next_sibling(dnode)) {
if (strcmp(ddi_node_name(dnode), "disk-board") == 0) {
int id;
int board;
fhc_bd_t *bdp;
sysc_cfga_stat_t *sc;
if ((board = (int)ddi_getprop(DDI_DEV_T_ANY, dnode,
DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) {
cmn_err(CE_WARN,
"Could not find board number");
continue;
}
bdp = fhc_bd(board);
sc = &bdp->sc;
if ((id = (int)ddi_getprop(DDI_DEV_T_ANY, dnode,
DDI_PROP_DONTPASS, "disk0-scsi-id", -1)) != -1) {
sc->bd.dsk.disk_pres[0] = 1;
sc->bd.dsk.disk_id[0] = id;
} else {
sc->bd.dsk.disk_pres[0] = 0;
}
if ((id = (int)ddi_getprop(DDI_DEV_T_ANY, dnode,
DDI_PROP_DONTPASS, "disk1-scsi-id", -1)) != -1) {
sc->bd.dsk.disk_pres[1] = 1;
sc->bd.dsk.disk_id[1] = id;
} else {
sc->bd.dsk.disk_pres[1] = 0;
}
}
}
}
struct jt_mstr *
jtag_master_lock(void)
{
fhc_bd_t *bdp;
struct jt_mstr *master = NULL;
ASSERT(fhc_bdlist_locked());
for (bdp = fhc_bd_first(); bdp; bdp = fhc_bd_next(bdp))
if (bdp->softsp && (bdp->softsp->jt_master.is_master == 1)) {
master = &bdp->softsp->jt_master;
mutex_enter(&master->lock);
break;
}
return (master);
}
void
jtag_master_unlock(struct jt_mstr *mstr)
{
ASSERT(fhc_bdlist_locked());
ASSERT(mutex_owned(&mstr->lock));
mutex_exit(&mstr->lock);
}
void
fhc_bdlist_prime(int first, int count, int incr)
{
int board;
fhc_bd_t *bdp;
sysc_evt_t se;
sysc_cfga_stat_t *sc;
struct jt_mstr *jtm;
int index;
int nadded;
ASSERT(fbe->update);
(void) fhc_bdlist_lock(-1);
nadded = 0;
for (board = first; board < count; board += incr) {
index = fhc_b_search(boards.boards, board, 0,
boards.last - nadded);
if (index == -1) {
fhc_check_size(&boards);
boards.boards[boards.last + 1] =
kmem_zalloc(sizeof (fhc_bd_t), KM_SLEEP);
boards.boards[boards.last + 1]->sc.type = UNKNOWN_BOARD;
boards.boards[boards.last + 1]->sc.board = board;
boards.boards[boards.last + 1]->softsp = NULL;
boards.last++;
nadded++;
boards.sorted = FALSE;
}
}
fhc_check_array(FHC_BOARDS);
fhc_bdlist_unlock();
fhc_bdmax = count - 1;
fhc_bd_dlist_init();
(void) fhc_bdlist_lock(-1);
if ((jtm = jtag_master_lock()) == NULL)
cmn_err(CE_PANIC, "fhc_bdlist_prime: no jtag master");
for (bdp = fhc_bd_first(); bdp; bdp = fhc_bd_next(bdp)) {
sc = &bdp->sc;
board = sc->board;
se = SYSC_EVT_BD_PRESENT;
if (sc->type == UNKNOWN_BOARD) {
uint_t fhc_csr;
uint_t fhc_bsr;
enum board_type type;
type = jtag_get_board_type(jtm->jtag_cmd, sc);
switch (type) {
case EMPTY_BOARD:
fhc_bd_sc_evt(sc, SYSC_EVT_BD_EMPTY);
continue;
case DISK_BOARD:
sc->type = DISK_BOARD;
(void) jtag_init_disk_board(jtm->jtag_cmd,
board,
&fhc_csr, &fhc_bsr);
fhc_bd_ks_alloc(bdp);
break;
default:
if (fhc_bd_disabled(board)) {
fhc_bd_ks_alloc(bdp);
se = SYSC_EVT_BD_DISABLED;
} else
se = SYSC_EVT_BD_FAILED;
sc->type = type;
break;
}
}
fhc_bd_sc_evt(sc, se);
}
fhc_bdlist_dk_init();
jtag_master_unlock(jtm);
fhc_bdlist_unlock();
}
struct cpu_speed {
int cpu_freq;
int sram_mode;
int system_div;
int system_dvd;
};
struct cpu_speed ultraI_speed_table[] = {
{ 0, 0, 0, 0},
{ 143, 1, 2, 1},
{ 154, 1, 2, 1},
{ 168, 1, 2, 1},
{ 182, 1, 3, 1},
{ 200, 1, 3, 1},
{ 222, 1, 3, 1},
{ 250, 1, 3, 1}
};
struct cpu_speed ultraII_speed_table[] = {
{ 0, 0, 0, 0},
{ 360, 2, 2, 1},
{ 400, 2, 4, 1},
{ 400, 2, 5, 2},
{ 248, 2, 3, 2},
{ 496, 2, 5, 2},
{ 296, 2, 2, 1},
{ 336, 2, 2, 1}
};
static void
set_cpu_info(sysc_cfga_stat_t *sc, uint_t fhc_bsr)
{
int i;
int speed_pins;
struct cpu_speed *table;
for (i = 0; i < 2; i++) {
sc->bd.cpu[i].cpu_speed = 0;
sc->bd.cpu[i].cpu_sram_mode = 0;
if (!sc->bd.cpu[i].cpu_detected)
continue;
speed_pins = (i == 0) ? CPU_0_PINS(fhc_bsr) :
CPU_1_PINS(fhc_bsr);
switch (sc->bd.cpu[i].cpu_compid & CID_REV_MASK) {
case ULTRAI_COMPID:
table = ultraI_speed_table;
break;
case ULTRAII_COMPID:
table = ultraII_speed_table;
break;
default:
cmn_err(CE_WARN, "board %d, cpu module %c "
"unknown type", sc->board,
(i == 0) ? 'A' : 'B');
sc->bd.cpu[i].cpu_speed = -1;
continue;
}
sc->bd.cpu[i].cpu_speed = table[speed_pins].cpu_freq;
sc->bd.cpu[i].cpu_sram_mode = table[speed_pins].sram_mode;
}
}
int
fhc_bdlist_scan(sysc_cfga_rstate_t rstate, struct jt_mstr *jtm)
{
int board;
int error;
int found = 0;
uint_t fhc_csr;
uint_t fhc_bsr;
fhc_bd_t *bdp;
sysc_cfga_stat_t *sc;
enum board_type type;
for (bdp = fhc_bd_first(); bdp; bdp = fhc_bd_next(bdp)) {
sc = &bdp->sc;
board = sc->board;
if (sc->in_transition || sc->rstate != rstate)
continue;
else if (sc->rstate == SYSC_CFGA_RSTATE_EMPTY) {
type = jtag_get_board_type(jtm->jtag_cmd, sc);
if (type == -1)
continue;
sc->type = type;
} else
type = sc->type;
if (type != UNKNOWN_BOARD)
(void) jtag_get_board_info(jtm->jtag_cmd, sc);
error = 0;
if (type == DISK_BOARD)
(void) jtag_init_disk_board(jtm->jtag_cmd, board,
&fhc_csr, &fhc_bsr);
else
error = jtag_powerdown_board(jtm->jtag_cmd,
board, type, &fhc_csr, &fhc_bsr, FALSE);
if (error) {
fhc_bd_sc_evt(sc, SYSC_EVT_BD_INS_FAILED);
continue;
}
if (fhc_csr & FHC_NOT_BRD_PRES)
continue;
if (type == CPU_BOARD) {
set_cpu_info(sc, fhc_bsr);
}
fhc_bd_sc_evt(sc, SYSC_EVT_BD_INSERTED);
if (!bdp->ksp)
fhc_bd_ks_alloc(bdp);
found++;
break;
}
return (found);
}
int
fhc_bd_insert_scan()
{
struct jt_mstr *jtm;
int found;
ASSERT(fhc_bdlist_locked());
if ((jtm = jtag_master_lock()) == NULL)
cmn_err(CE_PANIC, "fhc_bd_insert_scan: no jtag master");
found = fhc_bdlist_scan(SYSC_CFGA_RSTATE_EMPTY, jtm);
if (!found)
found |= fhc_bdlist_scan(SYSC_CFGA_RSTATE_DISCONNECTED, jtm);
if (!found)
cmn_err(CE_WARN, "Could not find hotplugged core system board");
jtag_master_unlock(jtm);
return (found);
}
int
fhc_bd_remove_scan()
{
int poll = 0;
fhc_bd_t *bdp;
struct jt_mstr *jtm;
sysc_cfga_stat_t *sc;
ASSERT(fhc_bdlist_locked());
if ((jtm = jtag_master_lock()) == NULL)
cmn_err(CE_PANIC, "fhc_bd_remove_scan: no jtag master");
for (bdp = fhc_bd_first(); bdp; bdp = fhc_bd_next(bdp)) {
sc = &bdp->sc;
if (sc->rstate != SYSC_CFGA_RSTATE_DISCONNECTED)
continue;
poll++;
if (sc->in_transition)
continue;
if (jtag_get_board_type(jtm->jtag_cmd, sc) == -1) {
if (bdp->ksp) {
kstat_delete(bdp->ksp);
bdp->ksp = NULL;
}
fhc_bd_sc_evt(sc, SYSC_EVT_BD_REMOVED);
}
}
jtag_master_unlock(jtm);
return (poll);
}
int
fhc_bd_detachable(int board)
{
fhc_bd_t *bdp = fhc_bd(board);
if (bdp->softsp != NULL)
return (bdp->flags & BDF_DETACH);
else
return (FALSE);
}
void
fhc_bd_sc_register(void (*f)(void *, sysc_cfga_stat_t *, sysc_evt_t), void *sp)
{
fhc_bd_evt.update = f;
fhc_bd_evt.soft = sp;
}
void
fhc_bd_update(int board, sysc_evt_t evt)
{
fhc_bd_t *bdp;
ASSERT(fhc_bd_valid(board));
if (!(fbe->update))
return;
bdp = fhc_bdlist_lock(board);
fhc_bd_sc_evt(&bdp->sc, evt);
fhc_bdlist_unlock();
}
int
fhc_bd_test(int board, sysc_cfga_pkt_t *pkt)
{
uint_t fhc_csr, fhc_bsr;
fhc_bd_t *bdp;
struct jt_mstr *jtm;
sysc_cfga_stat_t *sc;
ASSERT(fhc_bdlist_locked());
ASSERT(fhc_bd_busy(board));
bdp = fhc_bd(board);
sc = &bdp->sc;
switch (sc->rstate) {
case SYSC_CFGA_RSTATE_EMPTY:
cmn_err(CE_NOTE, "fhc_bd_test: simulate board %d insertion",
board);
jtm = jtag_master_lock();
ASSERT(jtm);
jtag_master_unlock(jtm);
(void) jtag_powerdown_board(jtm->jtag_cmd, board,
sc->type, &fhc_csr, &fhc_bsr, TRUE);
break;
case SYSC_CFGA_RSTATE_DISCONNECTED:
cmn_err(CE_NOTE, "fhc_bd_test: simulate board %d removal",
board);
if (bdp->ksp) {
kstat_delete(bdp->ksp);
bdp->ksp = NULL;
}
fhc_bd_sc_evt(sc, SYSC_EVT_BD_REMOVED);
break;
default:
cmn_err(CE_NOTE,
"fhc_bd_test: invalid board state: %d", board);
break;
}
return (0);
}
int
fhc_bd_test_set_cond(int board, sysc_cfga_pkt_t *sysc_pkt)
{
fhc_bd_t *bdp;
sysc_cfga_stat_t *sc;
sysc_cfga_cond_t cond;
ASSERT(fhc_bdlist_locked());
ASSERT(fhc_bd_busy(board));
bdp = fhc_bd(board);
sc = &bdp->sc;
cond = (sysc_cfga_cond_t)sysc_pkt->cmd_cfga.arg;
switch (cond) {
case SYSC_CFGA_COND_UNKNOWN:
case SYSC_CFGA_COND_OK:
case SYSC_CFGA_COND_FAILING:
case SYSC_CFGA_COND_FAILED:
case SYSC_CFGA_COND_UNUSABLE:
sc->condition = cond;
return (0);
default:
return (EINVAL);
}
}