/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/ddi_impldefs.h>
#include <sys/autoconf.h>
#include <sys/ndi_impldefs.h>
#include <vm/seg_kmem.h>
#include <sys/prom_plat.h>
#include <sys/machsystm.h>
#include <sys/sbd_ioctl.h>
#include <sys/sbdp_priv.h>
#include <sys/sbdp_mem.h>
#include <sys/sbdp_error.h>
#include <sys/serengeti.h>
/*
* Config information
*/
#ifdef DEBUG
#endif /* DEBUG */
/*
* Enable or disable dr
*/
/* name properties for some Serengeti device nodes */
/* last item must be blank */
};
/*
* In the case of a busy mbox, if a status cmd comes in we return a cached
* copy. This cache is a link list of wnodes that contains bd structs with
* the appropriate info. When a new wnode is created a whole entry is added
* to the list.
*/
/* Macros to access fields in the previous array */
/*
* Prototypes
*/
sbdp_wnode_t *sbdp_get_wnodep(int);
/*
* Module linkage information for the kernel.
*/
"Serengeti sbdp",
};
(void *)&modlmisc,
};
/*
* VA area used during CPU shutdown.
*/
/*
* Mutex to protect our inventory
*/
int
_init(void)
{
int e;
e = mod_install(&modlinkage);
if (e != 0)
return (e);
return (e);
}
int
_fini(void)
{
int e;
/*
* Remove the module.
*/
e = mod_remove(&modlinkage);
if (e != 0)
return (e);
return (e);
}
int
{
}
int
{
int portid;
static fn_t f = "sbdp_get_bd_and_wnode_num";
SBDP_DBG_FUNC("%s\n", f);
if (sbdp_is_node_bad(nodeid))
return (-1);
return (-1);
/*
* decode the board number
*/
return (0);
}
int
{
static fn_t f = "sbdp_get_board_num";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
/*
* Portid has encoded the nodeid and the agent id. The top
* 4 bits are correspond to the wcnodeid and the lower 5 are the
* agent id.
* Each agent id represents a physical location hence we can
* obtain the board number
*/
return (-1);
return (bd);
}
sbdp_get_devattr(void)
{
return (&sbdp_devattr[0]);
}
int
{
}
int
{
int portid;
int i;
static fn_t f = "sbdp_get_unit_num";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
if (sbdp_is_node_bad(nodeid))
return (-1);
SBDP_DBG_MISC("%s: couldn't get device_type\n", f);
return (-1);
}
for (i = 0; SBDP_CT(i) != SBD_COMP_UNKNOWN; i++) {
continue;
}
switch (type) {
case SBD_COMP_CPU:
}
break;
case SBD_COMP_MEM:
unit = 0;
break;
case SBD_COMP_IO: {
int len = 0;
/*
* Check to see if this is a cpci node
* cpci nodes are assign unit nums of 5 for now
* So they don't conflict with the pci unit nums
*/
SBDP_DBG_MISC("it is a sghsc\n");
return (4);
}
SBDP_DBG_MISC("%s: couldn't get portid\n", f);
return (-1);
}
if (len <= 0) {
SBDP_DBG_MISC("%s: couldn't get length\n", f);
return (-1);
}
SBDP_DBG_MISC("%s: couldn't get registers\n", f);
return (-1);
}
if ((portid % 2) != 0)
0x700000)
unit = 0;
else
unit = 1;
else
0x700000)
unit = 2;
else
unit = 3;
break;
}
default:
break;
}
return (unit);
}
struct sbdp_mem_dip {
};
static int
{
return (DDI_FAILURE);
/*
* We need to find the dip only for the first nodeid
*/
}
return (DDI_SUCCESS);
}
/*
* Update the board info. Required after a copy rename
*/
void
{
static fn_t f = "sbdp_update_bd_info";
SBDP_DBG_FUNC("%s\n", f);
return;
}
/*
* Grab the lock
*/
/*
* we get the top nodes here. This will have a side effect of
* updating the present bit for cpus
*/
apktp->num_of_nodes = 0;
(void *) apktp);
/*
* We need to clear nnum since we are looking again for the
* nodes
*/
/*
* If a dip is found by sbdp_get_mem_dip(), it will be
* returned held
*/
}
/*
* if the board doesn't have banks initialize them,
* otherwise we assume they have been updated if
* necessary
*/
}
#ifdef DEBUG
#endif
}
}
/*
* Initialize the board struct. This remains cached. We update it
* every time we have a successful show_board and after a copy-rename
*/
void
{
static fn_t f = "sbdp_bd_init";
SBDP_DBG_FUNC("%s\n", f);
bdp->cpus_present = 0;
KM_SLEEP);
}
/*
* This entry is going away. Clean up
*/
void
{
static fn_t f = "sbdp_bd_fini";
SBDP_DBG_FUNC("%s\n", f);
#ifdef DEBUG
#endif
}
/*
* A new wnode has arrived. Initialize the struct and create
* the board structures.
*/
void
{
int i;
static fn_t f = "sbdp_wnode_init";
SBDP_DBG_FUNC("%s\n", f);
for (i = 0; i < boards; i++)
}
/*
* Wnode got DRed out. Clean up all the node stuff including the boards
*/
void
{
int boards;
int i;
static fn_t f = "sbdp_wnode_fini";
SBDP_DBG_FUNC("%s\n", f);
for (i = 0; i < boards; i++)
}
/*
* Add all the necessary fields to this board's struct
*/
void
{
static fn_t f = "sbdp_add_new_bd_info";
SBDP_DBG_FUNC("%s\n", f);
}
/*
* This board has gone away. Clean the necessary fields
*/
void
{
int i;
static fn_t f = "sbdp_cleanup_bd";
SBDP_DBG_FUNC("%s\n", f);
SBDP_DBG_MISC("cur is null\n");
return;
}
/*
* Grab the lock
*/
}
bdp->cpus_present = 0;
}
/*
* Traverse the list looking for wnode. Return it when found
*/
{
int i;
static fn_t f = "sbdp_get_wnodep";
SBDP_DBG_FUNC("%s\n", f);
return (cur);
}
}
return (NULL);
}
/*
* Insert this brand new node into our master list. It leaves it all
* initialized
*/
void
{
static fn_t f = "sbdp_insert_wnode";
SBDP_DBG_FUNC("%s\n", f);
if (first_node == NULL) {
first_node = wnodep;
} else {
}
}
/*
* This node is gone. Remove it from the list and also clean up
*/
void
{
static fn_t f = "sbdp_remove_wnode";
SBDP_DBG_FUNC("%s\n", f);
if (first_node == wnodep)
first_node = NULL;
else {
}
}
}
/*
* Entry point from sbd. This is called when a new node is added. We
* create an entry in our inventory and initialize all the stuff that will be
* needed
*/
int
{
int instance;
int wnode;
int max_boards;
static fn_t f = "sbdp_setup_instance";
SBDP_DBG_FUNC("%s\n", f);
/*
* We get this directly from ssm
*/
/*
* This node has not been instanstiated
* create one
*/
}
return (DDI_SUCCESS);
}
/*
* Entry point from sbd. This is called when a node has been removed (or is
* going away. We do all the necessary cleanup
*/
int
{
int instance;
int wnode;
static fn_t f = "sbdp_teardown_instance";
SBDP_DBG_FUNC("%s\n", f);
/*
* ssm should have set this up
*/
SBDP_DBG_MISC("sbdp_teardown_instance: instance %d wnode %d\n",
/*
* Find this node and then remove it
*/
}
return (DDI_SUCCESS);
}
int
{
#ifdef lint
#endif
return (0);
}
/* ARGSUSED */
int
{
return (0);
}
void
{
static fn_t f = "sbdp_set_err";
SBDP_DBG_FUNC("%s\n", f);
}
}
/*
* Serengeti DR passthrus are for debugging purposes only.
*/
static struct {
const char *name;
} sbdp_passthrus[] = {
#ifdef DEBUG
{ "readmem", sbdp_passthru_readmem },
{ "prep-script", sbdp_passthru_prep_script },
{ "test-quiesce", sbdp_passthru_test_quiesce },
{ "inject-error", sbdp_passthru_inject_error },
{ "reset-error", sbdp_passthru_reset_error },
#endif
/* the following line must always be last */
};
/*ARGSUSED*/
int
{
#ifdef DEBUG
int rv;
int i;
static fn_t f = "sbdp_ioctl";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
}
i = 0;
int len;
break;
i++;
}
} else {
if (rv != ESBD_NOERROR) {
}
}
return (rv);
#else
return (0);
#endif
}
/*
* Check the dnode we obtained. Need to find a better way to determine
* if the node has the correct starting address
*/
int
{
static fn_t f = "sbdp_is_node_bad";
SBDP_DBG_FUNC("%s\n", f);
}
/*
* Retrieve the information we have on this board from
* the inventory
*/
{
int max_bds;
static fn_t f = "sbdp_get_bd_info";
SBDP_DBG_FUNC("%s\n", f);
max_bds = plat_max_boards();
return (NULL);
}
/*
* We might not have the complete bd info. With cheetah we
* cannot access the memory decode registers when then cpu is
* in reset. If the mem info is incomplete, then we try to gather it
* here
*/
return (bdp);
}
/*
* There are certain cases where obp marks components as failed
* If the status is ok the node won't have any status property. It
* is only there if the status is other than ok.
*/
{
static fn_t f = "sbdp_get_comp_status";
SBDP_DBG_FUNC("%s\n", f);
if (sbdp_is_node_bad(nodeid)) {
SBDP_DBG_STATE("node is not ok\n");
return (SBD_COND_UNKNOWN);
}
SBDP_DBG_STATE("status is ok\n");
return (SBD_COND_OK);
}
SBDP_DBG_STATE("status is unknown\n");
return (SBD_COND_UNKNOWN);
}
SBDP_DBG_STATE("status of failed\n");
return (SBD_COND_FAILED);
}
SBDP_DBG_STATE("status of unusable\n");
return (SBD_COND_UNUSABLE);
}
return (SBD_COND_OK);
}
void
{
static fn_t f = "sbdp_cpu_in_reset";
SBDP_DBG_FUNC("%s\n", f);
return;
}
return;
}
if (unit == SBDP_ALL_CPUS)
if (reset == 1)
else
else
if (reset == 1)
else
}
int
{
static fn_t f = "sbdp_set_cpu_present";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
}
return (-1);
}
return (0);
}
int
{
static fn_t f = "sbdp_is_cpu_present";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
}
return (-1);
}
}
int
{
static fn_t f = "sbdp_is_cpu_in_reset";
SBDP_DBG_FUNC("%s\n", f);
return (-1);
}
return (-1);
}
}
int
sbdp_dr_avail(void)
{
static fn_t f = "sbdp_dr_avail";
SBDP_DBG_FUNC("%s\n", f);
if (sbdp_dr_available)
if (sg_prom_sb_dr_check() == 0)
return (1);
return (0);
}