#include <sys/time.h>
#include <sys/cpuvar.h>
#include <sys/dditypes.h>
#include <sys/ddipropdefs.h>
#include <sys/ddi_impldefs.h>
#include <sys/sunddi.h>
#include <sys/esunddi.h>
#include <sys/sunndi.h>
#include <sys/platform_module.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/modctl.h>
#include <sys/promif.h>
#include <sys/promimpl.h>
#include <sys/prom_plat.h>
#include <sys/cmn_err.h>
#include <sys/sysmacros.h>
#include <sys/mem_cage.h>
#include <sys/kobj.h>
#include <sys/utsname.h>
#include <sys/cpu_sgnblk_defs.h>
#include <sys/atomic.h>
#include <sys/kdi_impl.h>
#include <sys/sgsbbc.h>
#include <sys/sgsbbc_iosram.h>
#include <sys/sgsbbc_iosram_priv.h>
#include <sys/sgsbbc_mailbox.h>
#include <sys/sgsgn.h>
#include <sys/serengeti.h>
#include <sys/sgfrutypes.h>
#include <sys/machsystm.h>
#include <sys/sbd_ioctl.h>
#include <sys/sbd.h>
#include <sys/sbdp_mem.h>
#include <sys/sgcn.h>
#include <sys/memnode.h>
#include <vm/vm_dep.h>
#include <vm/page.h>
#include <sys/cheetahregs.h>
#include <sys/plat_ecc_unum.h>
#include <sys/plat_ecc_dimm.h>
#include <sys/lgrp.h>
#include <sys/clock_impl.h>
static int sg_debug = 0;
#ifdef DEBUG
#define DCMNERR if (sg_debug) cmn_err
#else
#define DCMNERR
#endif
int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
static void cpu_sgn_update(ushort_t sgn, uchar_t state,
uchar_t sub_state, int cpuid);
extern int iosram_write (int, uint32_t, caddr_t, uint32_t);
static int (*iosram_write_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL;
extern int iosram_read (int, uint32_t, caddr_t, uint32_t);
static int (*iosram_read_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL;
int todsg_use_sc = FALSE;
#define IOMMU_PER_SCHIZO 2
int serengeti_tsb_spares = (SG_MAX_IO_BDS * SG_SCHIZO_PER_IO_BD *
IOMMU_PER_SCHIZO);
int sg_max_ncpus = (12 * 2);
int sbbc_mbox_default_timeout = MBOX_DEFAULT_TIMEOUT;
int sbbc_mbox_min_timeout = MBOX_MIN_TIMEOUT;
pnode_t chosen_nodeid = (pnode_t)0;
int slice_to_memnode[SG_MAX_SLICE];
#define LW8_MAX_CPU_BDS 5
plat_dimm_sid_board_t domain_dimm_sids[LW8_MAX_CPU_BDS];
int
set_platform_tsb_spares()
{
return (MIN(serengeti_tsb_spares, MAX_UPA));
}
#pragma weak mmu_init_large_pages
void
set_platform_defaults(void)
{
extern int watchdog_enable;
extern uint64_t xc_tick_limit_scale;
extern void mmu_init_large_pages(size_t);
#ifdef DEBUG
char *todsg_name = "todsg";
ce_verbose_memory = 2;
ce_verbose_other = 2;
#endif
watchdog_enable = TRUE;
watchdog_available = TRUE;
cpu_sgn_func = cpu_sgn_update;
#ifdef DEBUG
if (tod_module_name && (strcmp(tod_module_name, todsg_name) == 0))
prom_printf("Using todsg driver\n");
else {
prom_printf("Force using todsg driver\n");
tod_module_name = todsg_name;
}
#endif
forthdebug_supported = 0;
xc_tick_limit_scale = 5;
if ((mmu_page_sizes == max_mmu_page_sizes) &&
(mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) {
if (&mmu_init_large_pages)
mmu_init_large_pages(mmu_ism_pagesize);
}
}
void
load_platform_modules(void)
{
if (modload("misc", "pcihp") < 0) {
cmn_err(CE_NOTE, "pcihp driver failed to load");
}
}
int
plat_cpu_poweron(struct cpu *cp)
{
int (*serengeti_cpu_poweron)(struct cpu *) = NULL;
serengeti_cpu_poweron =
(int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweron", 0);
if (serengeti_cpu_poweron == NULL)
return (ENOTSUP);
else
return ((serengeti_cpu_poweron)(cp));
}
int
plat_cpu_poweroff(struct cpu *cp)
{
int (*serengeti_cpu_poweroff)(struct cpu *) = NULL;
serengeti_cpu_poweroff =
(int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweroff", 0);
if (serengeti_cpu_poweroff == NULL)
return (ENOTSUP);
else
return ((serengeti_cpu_poweroff)(cp));
}
#ifdef DEBUG
pgcnt_t serengeti_cage_size_limit;
#endif
pgcnt_t serengeti_minimum_cage_size = 0;
void
set_platform_cage_params(void)
{
extern pgcnt_t total_pages;
extern struct memlist *phys_avail;
if (kernel_cage_enable) {
pgcnt_t preferred_cage_size;
preferred_cage_size =
MAX(serengeti_minimum_cage_size, total_pages / 256);
#ifdef DEBUG
if (serengeti_cage_size_limit)
preferred_cage_size = serengeti_cage_size_limit;
#endif
kcage_range_init(phys_avail, KCAGE_UP, preferred_cage_size);
}
kcage_startup_dir = KCAGE_UP;
if (!kcage_on)
cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
}
#define ALIGN(x, a) ((a) == 0 ? (uint64_t)(x) : \
(((uint64_t)(x) + (uint64_t)(a) - 1l) & ~((uint64_t)(a) - 1l)))
void
update_mem_bounds(int brd, uint64_t base, uint64_t sz)
{
uint64_t end;
int mnode;
end = base + sz - 1;
if ((mnode = plat_lgrphand_to_mem_node(brd)) == -1) {
if ((mnode = slice_to_memnode[PA_2_SLICE(base)]) == -1)
mnode = mem_node_alloc();
plat_assign_lgrphand_to_mem_node(brd, mnode);
}
base = ALIGN(base, (1ul << PA_SLICE_SHIFT));
while (base < end) {
slice_to_memnode[PA_2_SLICE(base)] = mnode;
base += (1ul << PA_SLICE_SHIFT);
}
}
void
plat_fill_mc(pnode_t nodeid)
{
uint64_t mc_addr, mask;
uint64_t mc_decode[SG_MAX_BANKS_PER_MC];
uint64_t base, size;
uint32_t regs[4];
int len;
int local_mc;
int portid;
int boardid;
int i;
if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
(portid == -1))
return;
boardid = SG_PORTID_TO_BOARD_NUM(portid);
len = prom_getproplen(nodeid, "reg");
if (len != (sizeof (uint32_t) * 4)) {
prom_printf("Warning: malformed 'reg' property\n");
return;
}
if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0)
return;
mc_addr = ((uint64_t)regs[0]) << 32;
mc_addr |= (uint64_t)regs[1];
if (portid == cpunodes[CPU->cpu_id].portid)
local_mc = 1;
else
local_mc = 0;
for (i = 0; i < SG_MAX_BANKS_PER_MC; i++) {
mask = SG_REG_2_OFFSET(i);
if (local_mc)
mc_decode[i] = lddmcdecode(mask & MC_OFFSET_MASK);
else
mc_decode[i] = lddphysio((mc_addr | mask));
if (mc_decode[i] >> MC_VALID_SHIFT) {
base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
size = MC_UK2SPAN(mc_decode[i]);
update_mem_bounds(boardid, base, size);
}
}
}
void
plat_build_mem_nodes(prom_memlist_t *list, size_t nelems)
{
int slice;
pfn_t basepfn;
pgcnt_t npgs;
mem_node_pfn_shift = PFN_SLICE_SHIFT;
mem_node_physalign = (1ull << PA_SLICE_SHIFT);
for (slice = 0; slice < SG_MAX_SLICE; slice++) {
if (slice_to_memnode[slice] == -1)
continue;
basepfn = (uint64_t)slice << PFN_SLICE_SHIFT;
npgs = 1ull << PFN_SLICE_SHIFT;
mem_node_add_slice(basepfn, basepfn + npgs - 1);
}
}
int
plat_pfn_to_mem_node(pfn_t pfn)
{
int node;
node = slice_to_memnode[PFN_2_SLICE(pfn)];
return (node);
}
#define CPUID_TO_BOARD(id) (((id) >> 2) & 0x7)
lgrp_handle_t
plat_lgrp_cpu_to_hand(processorid_t id)
{
return (CPUID_TO_BOARD(id));
}
void
plat_lgrp_init(void)
{
int i;
extern uint32_t lgrp_expand_proc_thresh;
extern uint32_t lgrp_expand_proc_diff;
for (i = 0; i < SG_MAX_SLICE; i++) {
slice_to_memnode[i] = -1;
}
lgrp_expand_proc_thresh = LGRP_LOADAVG_THREAD_MAX;
lgrp_expand_proc_diff = LGRP_LOADAVG_THREAD_MAX;
}
void
plat_lgrp_config(lgrp_config_flag_t evt, uintptr_t arg)
{
update_membounds_t *umb;
lgrp_config_mem_rename_t lmr;
lgrp_handle_t shand, thand;
int snode, tnode;
switch (evt) {
case LGRP_CONFIG_MEM_ADD:
umb = (update_membounds_t *)arg;
update_mem_bounds(umb->u_board, umb->u_base, umb->u_len);
break;
case LGRP_CONFIG_MEM_DEL:
break;
case LGRP_CONFIG_MEM_RENAME:
shand = arg & 0xffff;
thand = (arg & 0xffff0000) >> 16;
snode = plat_lgrphand_to_mem_node(shand);
tnode = plat_lgrphand_to_mem_node(thand);
plat_assign_lgrphand_to_mem_node(thand, snode);
plat_assign_lgrphand_to_mem_node(shand, tnode);
lmr.lmem_rename_from = shand;
lmr.lmem_rename_to = thand;
lgrp_config(LGRP_CONFIG_MEM_RENAME, (uintptr_t)snode,
(uintptr_t)&lmr);
break;
default:
break;
}
}
int
plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
{
if (lgrp_optimizations() && (from != to ||
from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
return (28);
else
return (23);
}
void
plat_freelist_process(int mnode)
{
}
dev_info_t *
find_chosen_dip(void)
{
dev_info_t *dip;
char master_sbbc[MAXNAMELEN];
int nodeid;
uint_t tunnel;
nodeid = prom_chosennode();
if (prom_getprop(nodeid, IOSRAM_CHOSEN_PROP, (caddr_t)&tunnel) <= 0) {
SBBC_ERR(CE_PANIC, "No iosram property found! \n");
}
if (prom_phandle_to_path((phandle_t)tunnel, master_sbbc,
sizeof (master_sbbc)) < 0) {
SBBC_ERR1(CE_PANIC, "prom_phandle_to_path(%d) failed\n",
tunnel);
}
chosen_nodeid = nodeid;
if (i_ddi_attach_hw_nodes("sgsbbc") != DDI_SUCCESS) {
cmn_err(CE_WARN, "sgsbbc failed to load\n");
}
dip = e_ddi_hold_devi_by_path(master_sbbc, 0);
if ((dip == NULL) || (ddi_get_nodeid(dip) != tunnel)) {
cmn_err(CE_PANIC,
"e_ddi_hold_devi_by_path(%x) failed for SBBC\n", tunnel);
}
ndi_rele_devi(dip);
DCMNERR(CE_CONT, "Chosen IOSRAM is at %s \n", master_sbbc);
return (dip);
}
void
load_platform_drivers(void)
{
int ret;
if (i_ddi_attach_hw_nodes("mc-us3") != DDI_SUCCESS)
cmn_err(CE_WARN, "mc-us3 failed to load");
else
(void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
(void) find_chosen_dip();
if (i_ddi_attach_hw_nodes("sgenv") != DDI_SUCCESS)
cmn_err(CE_WARN, "sgenv failed to load");
iosram_write_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t))
modgetsymvalue("iosram_write", 0);
if (iosram_write_ptr == NULL) {
DCMNERR(CE_WARN, "load_platform_defaults: iosram_write()"
" not found; signatures will not be updated\n");
} else {
iosram_read_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t))
modgetsymvalue("iosram_read", 0);
if (iosram_read_ptr == NULL)
DCMNERR(CE_WARN, "load_platform_defaults: iosram_read()"
" not found\n");
}
todsg_use_sc = TRUE;
mutex_enter(&tod_lock);
if (watchdog_enable)
ret = tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds);
mutex_exit(&tod_lock);
if (ret != 0)
printf("Hardware watchdog enabled\n");
plat_ecc_init();
}
char *platform_module_list[] = {
(char *)0
};
void
plat_tod_fault(enum tod_fault_type tod_bad)
{
}
int
plat_max_boards()
{
return (SG_MAX_BDS);
}
int
plat_max_io_units_per_board()
{
return (SG_MAX_IO_PER_BD);
}
int
plat_max_cmp_units_per_board()
{
return (SG_MAX_CMPS_PER_BD);
}
int
plat_max_cpu_units_per_board()
{
return (SG_MAX_CPUS_PER_BD);
}
int
plat_max_mc_units_per_board()
{
return (SG_MAX_CMPS_PER_BD);
}
int
plat_max_mem_units_per_board()
{
return (SG_MAX_MEM_PER_BD);
}
int
plat_max_cpumem_boards(void)
{
return (LW8_MAX_CPU_BDS);
}
int
set_platform_max_ncpus(void)
{
return (sg_max_ncpus);
}
void
plat_dmv_params(uint_t *hwint, uint_t *swint)
{
*hwint = MAX_UPA;
*swint = 0;
}
static int (*sg_mbox)(sbbc_msg_t *, sbbc_msg_t *, time_t) = NULL;
void
plat_nodename_set(void)
{
sbbc_msg_t req;
sbbc_msg_t resp;
int rv;
struct nodename_info {
int32_t namelen;
char nodename[_SYS_NMLN];
} nni;
if (sg_mbox == NULL)
sg_mbox = (int (*)(sbbc_msg_t *, sbbc_msg_t *, time_t))
modgetsymvalue("sbbc_mbox_request_response", 0);
if (sg_mbox == NULL) {
cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox not found\n");
return;
}
(void) strcpy(nni.nodename, utsname.nodename);
nni.namelen = (int32_t)strlen(nni.nodename);
req.msg_type.type = INFO_MBOX;
req.msg_type.sub_type = INFO_MBOX_NODENAME;
req.msg_status = 0;
req.msg_len = (int)(nni.namelen + sizeof (nni.namelen));
req.msg_bytes = 0;
req.msg_buf = (caddr_t)&nni;
req.msg_data[0] = 0;
req.msg_data[1] = 0;
resp.msg_type.type = INFO_MBOX;
resp.msg_type.sub_type = INFO_MBOX_NODENAME;
resp.msg_status = 0;
resp.msg_len = 0;
resp.msg_bytes = 0;
resp.msg_buf = (caddr_t)0;
resp.msg_data[0] = 0;
resp.msg_data[1] = 0;
rv = (sg_mbox)(&req, &resp, sbbc_mbox_default_timeout);
if (rv != 0) {
cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox retval %d\n", rv);
} else if (resp.msg_status != 0) {
cmn_err(CE_NOTE, "!plat_nodename_set: msg_status %d\n",
resp.msg_status);
} else {
DCMNERR(CE_NOTE, "!plat_nodename_set was successful\n");
rv = plat_ecc_capability_send();
if (rv == 0) {
DCMNERR(CE_NOTE, "!plat_ecc_capability_send was"
"successful\n");
}
}
}
int sg_use_prom_get_unum = 0;
int sg_use_prom_ecache_unum = 0;
#define SG_MEMORY_ECC 1
#define SG_ECACHE_ECC 2
#define SG_UNKNOWN_ECC (-1)
static int
sg_prom_get_unum(int synd_code, uint64_t paddr, char *buf, int buflen,
int *lenp)
{
if ((prom_get_unum(synd_code, (unsigned long long)paddr,
buf, buflen, lenp)) != 0)
return (EIO);
else if (*lenp <= 1)
return (EINVAL);
else
return (0);
}
int
plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
{
int (*unum_func)(int synd_code, uint64_t paddr, char *buf,
int buflen, int *lenp) = p2get_mem_unum;
if (flt_in_memory) {
if (sg_use_prom_get_unum) {
DCMNERR(CE_NOTE, "Using prom_get_unum from OBP");
return (sg_prom_get_unum(synd_code,
P2ALIGN(flt_addr, 8), buf, buflen, lenp));
} else if (unum_func != NULL) {
return (unum_func(synd_code, P2ALIGN(flt_addr, 8),
buf, buflen, lenp));
} else {
return (ENOTSUP);
}
} else if (flt_status & ECC_ECACHE) {
if (sg_use_prom_ecache_unum) {
DCMNERR(CE_NOTE,
"Using prom_serengeti_get_ecacheunum from OBP");
if (prom_serengeti_get_ecacheunum(flt_bus_id,
P2ALIGN(flt_addr, 8), buf, buflen, lenp) != 0) {
return (EIO);
}
} else {
return (sg_get_ecacheunum(flt_bus_id, flt_addr,
buf, buflen, lenp));
}
} else {
return (ENOTSUP);
}
return (0);
}
void
plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
{
char new_unum[UNUM_NAMLEN] = "";
int node = SG_PORTID_TO_NODEID(mcid);
int board = SG_CPU_BD_PORTID_TO_BD_NUM(mcid);
int position = SG_PORTID_TO_CPU_POSN(mcid);
bank = (bank % 2);
if (dimm == -1) {
SG_SET_FRU_NAME_NODE(new_unum, node);
SG_SET_FRU_NAME_CPU_BOARD(new_unum, board);
SG_SET_FRU_NAME_MODULE(new_unum, position);
SG_SET_FRU_NAME_BANK(new_unum, bank);
} else {
SG_SET_FRU_NAME_NODE(new_unum, node);
SG_SET_FRU_NAME_CPU_BOARD(new_unum, board);
SG_SET_FRU_NAME_MODULE(new_unum, position);
SG_SET_FRU_NAME_BANK(new_unum, bank);
SG_SET_FRU_NAME_DIMM(new_unum, dimm);
(void) strcat(new_unum, " ");
(void) strcat(new_unum, unum);
}
(void) strcpy(unum, new_unum);
}
int
plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
{
int node = SG_PORTID_TO_NODEID(cpuid);
int board = SG_CPU_BD_PORTID_TO_BD_NUM(cpuid);
if (snprintf(buf, buflen, "/N%d/%s%d", node,
SG_HPU_TYPE_CPU_BOARD_ID, board) >= buflen) {
return (ENOSPC);
} else {
*lenp = strlen(buf);
return (0);
}
}
static void (*sg_ecc_taskq_func)(sbbc_ecc_mbox_t *) = NULL;
static int (*sg_ecc_mbox_func)(sbbc_ecc_mbox_t *) = NULL;
int
plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap)
{
sbbc_ecc_mbox_t *msgp;
uint16_t msg_subtype;
int sleep_flag, log_error;
size_t msg_size;
if (sg_ecc_taskq_func == NULL) {
sg_ecc_taskq_func = (void (*)(sbbc_ecc_mbox_t *))
modgetsymvalue("sbbc_mbox_queue_ecc_event", 0);
if (sg_ecc_taskq_func == NULL) {
cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
"sbbc_mbox_queue_ecc_event not found");
return (ENODEV);
}
}
if (sg_ecc_mbox_func == NULL) {
sg_ecc_mbox_func = (int (*)(sbbc_ecc_mbox_t *))
modgetsymvalue("sbbc_mbox_ecc_output", 0);
if (sg_ecc_mbox_func == NULL) {
cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
"sbbc_mbox_ecc_output not found");
return (ENODEV);
}
}
switch (msg_type) {
case PLAT_ECC_ERROR_MESSAGE:
msg_subtype = INFO_MBOX_ERROR_ECC;
msg_size = sizeof (plat_ecc_error_data_t);
sleep_flag = KM_NOSLEEP;
log_error = 1;
break;
case PLAT_ECC_ERROR2_MESSAGE:
msg_subtype = INFO_MBOX_ECC;
msg_size = sizeof (plat_ecc_error2_data_t);
sleep_flag = KM_NOSLEEP;
log_error = 1;
break;
case PLAT_ECC_INDICTMENT_MESSAGE:
msg_subtype = INFO_MBOX_ERROR_INDICT;
msg_size = sizeof (plat_ecc_indictment_data_t);
sleep_flag = KM_SLEEP;
log_error = 0;
break;
case PLAT_ECC_INDICTMENT2_MESSAGE:
msg_subtype = INFO_MBOX_ECC;
msg_size = sizeof (plat_ecc_indictment2_data_t);
sleep_flag = KM_SLEEP;
log_error = 0;
break;
case PLAT_ECC_CAPABILITY_MESSAGE:
msg_subtype = INFO_MBOX_ECC_CAP;
msg_size = sizeof (plat_capability_data_t) +
strlen(utsname.release) + strlen(utsname.version) + 2;
sleep_flag = KM_SLEEP;
log_error = 0;
break;
case PLAT_ECC_DIMM_SID_MESSAGE:
msg_subtype = INFO_MBOX_ECC;
msg_size = sizeof (plat_dimm_sid_request_data_t);
sleep_flag = KM_SLEEP;
log_error = 0;
break;
default:
return (EINVAL);
}
msgp = (sbbc_ecc_mbox_t *)kmem_zalloc(sizeof (sbbc_ecc_mbox_t),
sleep_flag);
if (msgp == NULL) {
cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
"unable to allocate sbbc_ecc_mbox");
return (ENOMEM);
}
msgp->ecc_log_error = log_error;
msgp->ecc_req.msg_type.type = INFO_MBOX;
msgp->ecc_req.msg_type.sub_type = msg_subtype;
msgp->ecc_req.msg_status = 0;
msgp->ecc_req.msg_len = (int)msg_size;
msgp->ecc_req.msg_bytes = 0;
msgp->ecc_req.msg_buf = (caddr_t)kmem_zalloc(msg_size, sleep_flag);
msgp->ecc_req.msg_data[0] = 0;
msgp->ecc_req.msg_data[1] = 0;
if (msgp->ecc_req.msg_buf == NULL) {
cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: "
"unable to allocate request msg_buf");
kmem_free((void *)msgp, sizeof (sbbc_ecc_mbox_t));
return (ENOMEM);
}
bcopy(datap, (void *)msgp->ecc_req.msg_buf, msg_size);
msgp->ecc_resp.msg_type.type = INFO_MBOX;
msgp->ecc_resp.msg_type.sub_type = msg_subtype;
msgp->ecc_resp.msg_status = 0;
msgp->ecc_resp.msg_len = 0;
msgp->ecc_resp.msg_bytes = 0;
msgp->ecc_resp.msg_buf = NULL;
msgp->ecc_resp.msg_data[0] = 0;
msgp->ecc_resp.msg_data[1] = 0;
switch (msg_type) {
case PLAT_ECC_ERROR_MESSAGE:
case PLAT_ECC_ERROR2_MESSAGE:
(*sg_ecc_taskq_func)(msgp);
return (0);
case PLAT_ECC_CAPABILITY_MESSAGE:
msgp->ecc_resp.msg_len = (int)msg_size;
msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc(msg_size,
sleep_flag);
case PLAT_ECC_INDICTMENT_MESSAGE:
case PLAT_ECC_INDICTMENT2_MESSAGE:
return ((*sg_ecc_mbox_func)(msgp));
case PLAT_ECC_DIMM_SID_MESSAGE:
msgp->ecc_resp.msg_len = sizeof (plat_dimm_sid_board_data_t);
msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc(
sizeof (plat_dimm_sid_board_data_t), sleep_flag);
return ((*sg_ecc_mbox_func)(msgp));
default:
ASSERT(0);
return (EINVAL);
}
}
int
plat_make_fru_cpuid(int sb, int m, int proc)
{
return (MAKE_CPUID(sb, proc));
}
int
plat_make_fru_boardnum(int proc)
{
return (SG_PORTID_TO_BOARD_NUM(proc));
}
static
void
cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid)
{
uint32_t signature = CPU_SIG_BLD(sig, state, sub_state);
sig_state_t current_sgn;
int i;
if (iosram_write_ptr == NULL) {
DCMNERR(CE_WARN,
"cpu_sgn_update: iosram_write() not found;"
" cannot write signature 0x%x for CPU(s) or domain\n",
signature);
return;
}
if (sub_state == SIGSUBST_REBOOT) {
if (iosram_read_ptr == NULL) {
DCMNERR(CE_WARN,
"cpu_sgn_update: iosram_read() not found;"
" could not check current domain signature\n");
} else {
(void) (*iosram_read_ptr)(SBBC_SIGBLCK_KEY,
SG_SGNBLK_DOMAINSIG_OFFSET,
(char *)¤t_sgn, sizeof (current_sgn));
if (current_sgn.state_t.state == SIGST_EXIT)
signature = CPU_SIG_BLD(sig, state,
SIGSUBST_PANIC_REBOOT);
}
}
if (cpuid >= 0) {
(void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature,
sizeof (signature));
} else {
for (i = 0; i < NCPU; i++) {
if (cpu[i] == NULL || !(cpu[i]->cpu_flags &
(CPU_EXISTS|CPU_QUIESCED))) {
continue;
}
(void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature,
sizeof (signature));
}
}
if (state == SIGST_OFFLINE || state == SIGST_DETACHED) {
return;
}
(void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY,
SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature,
sizeof (signature));
}
void
startup_platform(void)
{
}
static int
isdigit(int ch)
{
return (ch >= '0' && ch <= '9');
}
#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
static int
strtoi(char *p, char **pos)
{
int n;
int c, neg = 0;
if (!isdigit(c = *p)) {
while (isspace(c))
c = *++p;
switch (c) {
case '-':
neg++;
case '+':
c = *++p;
}
if (!isdigit(c)) {
if (pos != NULL)
*pos = p;
return (0);
}
}
for (n = '0' - c; isdigit(c = *++p); ) {
n *= 10;
n += '0' - c;
}
if (pos != NULL)
*pos = p;
return (neg ? n : -n);
}
int
sg_get_prom_version(int *sysp, int *intfp, int *bldp)
{
int plen;
char vers[512];
static pnode_t node;
static char version[] = "version";
char *verp, *ep;
node = prom_finddevice("/openprom");
if (node == OBP_BADNODE)
return (-1);
plen = prom_getproplen(node, version);
if (plen <= 0 || plen >= sizeof (vers))
return (-1);
(void) prom_getprop(node, version, vers);
vers[plen] = '\0';
if (vers[0] != 'O' && vers[1] != 'B' && vers[2] != 'P') {
cmn_err(CE_WARN, "sg_get_prom_version: "
"unknown <version> string in </openprom>\n");
return (-1);
}
verp = &vers[4];
*sysp = strtoi(verp, &ep);
if (ep == verp || *ep != '.')
return (-1);
verp = ep + 1;
*intfp = strtoi(verp, &ep);
if (ep == verp || *ep != '.')
return (-1);
verp = ep + 1;
*bldp = strtoi(verp, &ep);
if (ep == verp || (*ep != '\0' && !isspace(*ep)))
return (-1);
return (0);
}
int
sg_prom_sb_dr_check(void)
{
static int prom_res = 1;
if (prom_res == 1) {
int sys, intf, bld;
int rv;
rv = sg_get_prom_version(&sys, &intf, &bld);
if (rv == 0 && sys == 5 &&
(intf >= 12 || (intf == 11 && bld >= 200))) {
prom_res = 0;
} else {
prom_res = -1;
}
}
return (prom_res);
}
int
sg_prom_cpci_dr_check(void)
{
return (sg_prom_sb_dr_check());
}
static void
sg_system_claim(void)
{
lbolt_debug_entry();
prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
}
static void
sg_system_release(void)
{
prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
lbolt_debug_return();
}
static void
sg_console_claim(void)
{
(void) prom_serengeti_set_console_input(SGCN_OBP_STR);
}
static void
sg_console_release(void)
{
(void) prom_serengeti_set_console_input(SGCN_CLNT_STR);
}
void
plat_kdi_init(kdi_t *kdi)
{
kdi->pkdi_system_claim = sg_system_claim;
kdi->pkdi_system_release = sg_system_release;
kdi->pkdi_console_claim = sg_console_claim;
kdi->pkdi_console_release = sg_console_release;
}