1
0
Files
irix-657m-src/stand/arcs/lib/libkl/ml/klconfig.c
2022-09-29 17:59:04 +03:00

2888 lines
78 KiB
C

/**************************************************************************
* *
* Copyright (C) 1992-1996, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/*
* File: klconfig.c
* klconfig.c - Routines to init the KLCONFIG struct for each
* type of board.
*
*
* Runs in MP mode, on all processors. These routines write in their
* local memory areas.
*/
#include <sys/types.h>
#include <sys/mips_addrspace.h>
#include <sys/graph.h>
#include <sys/nic.h>
#include <sys/SN/addrs.h>
#include <sys/SN/promcfg.h>
#include <sys/SN/klconfig.h>
#include <sys/SN/SN0/klhwinit.h>
#include <sys/SN/SN0/ip27config.h>
#include <sys/SN/SN0/ip27log.h>
#include <sys/SN/error.h>
#include <sys/SN/xbow.h>
#include <sys/SN/nvram.h>
#include <sys/SN/slotnum.h>
#include <sys/SN/kldiag.h>
#include <sys/SN/router.h>
#include <sys/PCI/bridge.h>
#include <arcs/cfgdata.h>
#include <libsc.h>
#include <libkl.h>
#include <libsk.h>
#include <report.h>
#include <prom_msgs.h>
#include <klcfg_router.h>
#include <prom_leds.h>
#include <sys/sbd.h>
#ifndef SABLE
#define LDEBUG 0 /* Set for 1 for debug compilation */
#endif
#if defined(LD)
#undef LD
#endif
#define LD(x) (*(volatile __int64_t *) (x))
#define LW(x) (*(volatile __int32_t *) (x))
/* These are defined in different places in the IO6prom and IP27prom. */
extern int get_cpu_irr(void);
extern int get_fpc_irr(void);
extern off_t kl_config_info_alloc(nasid_t, int, unsigned int);
extern void init_config_malloc(nasid_t);
extern int config_find_nic_router_all(pcfg_t *, nic_t, lboard_t **,
klrou_t **, partid_t, int) ;
/*
* Local function prototype declarations.
*/
int klconfig_port_update(pcfg_t *, partid_t);
lboard_t *kl_config_alloc_board(nasid_t);
klinfo_t *kl_config_alloc_component(nasid_t, lboard_t *);
lboard_t *kl_config_add_board(nasid_t, lboard_t *);
static lboard_t * init_klcfg_routerb_hl(pcfg_t *p ,
nasid_t nasid ,
pcfg_router_t *pcfg_routerp ,
int router_type ,
partid_t partition) ;
int setup_hub_port(pcfg_hub_t *, pcfg_router_t *);
int setup_router_port_to_hub(pcfg_t *, pcfg_router_t *, pcfg_hub_t *, int);
int setup_router_port_to_router(pcfg_t *, pcfg_router_t *, pcfg_router_t *,int);
extern int get_hub_nic_info(nic_data_t, char *) ;
#define GET_PCI_VID(_id) (_id & 0xffff)
#define GET_PCI_DID(_id) ((_id >> 16) & 0xffff)
void
init_klcfg(nasid_t nasid)
{
init_config_malloc(nasid);
}
/* BOARDS */
/* IP27 and other NODE Boards */
/*
* Init a klcfg struct for a ip27 board.
* Fill all routine fields as usual. Get hardware info
* when required by calling respective hardware routines.
*/
lboard_t *
init_klcfg_ip27(__psunsigned_t hub_base, int flag)
{
lboard_t *brd_ptr;
nasid_t nasid;
short cpunum;
klhub_t *hubp;
char *c = NULL;
nasid = NASID_GET(hub_base);
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_ip27: Cannot allocate board struct\n");
return NULL;
}
/* Since there is only one module in the 12P 4IO config
* hardwire the brd module number to 1
*/
if (CONFIG_12P4I)
brd_ptr->brd_module = 1;
brd_ptr->brd_type = KLTYPE_IP27;
/*
* We're going from 2 to 3 to accomadate the addition of
* the CRB_B registers to the hubio error struct
*/
if (brd_ptr->brd_sversion <= 2)
brd_ptr->brd_sversion = 3;
brd_ptr->brd_brevision = (unsigned char)
((LD(hub_base + NI_STATUS_REV_ID) & NSRI_REV_MASK) >>
NSRI_REV_SHFT);
if (kl_sable) {
#ifdef SABLE
brd_ptr->brd_slot = (uchar)get_my_slotid() ;
#endif
}
else {
char buf[8];
brd_ptr->brd_slot = (unsigned char)
hub_slotbits_to_slot(LD(hub_base + MD_SLOTID_USTAT) &
MSU_SLOTID_MASK);
}
/*
* Who am I?
*/
cpunum = LD(hub_base + PI_CPU_NUM);
/*
* setup a cpu component for each cpu found. This should match
* what the ip27 prom has already found...
*/
if (LD(hub_base + PI_CPU_PRESENT_A))
init_klcfg_cpu(hub_base, brd_ptr, IP27_CPU0_INDEX, (cpunum == 0));
if (LD(hub_base + PI_CPU_PRESENT_B))
init_klcfg_cpu(hub_base, brd_ptr, IP27_CPU1_INDEX, (cpunum == 1));
init_klcfg_hub(hub_base, brd_ptr, IP27_HUB_INDEX) ;
init_klcfg_membnk(hub_base, brd_ptr, IP27_MEM_INDEX) ;
if (hubp = (klhub_t *)find_component(brd_ptr, NULL,
KLSTRUCT_HUB)) {
if (hubp->hub_mfg_nic)
c = (char *)NODE_OFFSET_TO_K1(
nasid,
hubp->hub_mfg_nic);
}
if(ip31_pimm_psc(nasid,NULL,c) == 0)
strcpy(brd_ptr->brd_name,"IP31");
else
strcpy(brd_ptr->brd_name,"IP27");
return (kl_config_add_board(nasid, brd_ptr));
}
/* NODE BOARD COMPONENTS */
void
add_klcfg_cpuinfo(nasid_t nasid, klcpu_t *cpuptr)
{
int divisor;
/* Get frequency from the prom config bits. Shift it into megahertz. */
cpuptr->cpu_speed = (short)((((ip27config_t *)(IP27CONFIG_ADDR_NODE(nasid)))->freq_cpu)/1000000);
/* Get the scache size in bytes (from config reg), shift it to MB */
cpuptr->cpu_scachesz = ((0x1 << (((((ip27config_t *)(IP27CONFIG_ADDR_NODE(nasid)))->r10k_mode)>>16) & 0x7))>> 1);
divisor = ((((ip27config_t *)(IP27CONFIG_ADDR_NODE(nasid)))->r10k_mode)>>19) & 0x3;
cpuptr->cpu_scachespeed = (cpuptr->cpu_speed * 2)/(divisor + 1);
#define MAX_T5_SPEED 250
if( nasid == get_nasid()) {
cpuptr->cpu_prid = get_cpu_irr();
cpuptr->cpu_fpirr = get_fpc_irr();
} else { /* The cpu's are both disabled ... headless node */
if(cpuptr->cpu_speed > MAX_T5_SPEED) {
cpuptr->cpu_prid = C0_IMP_R12000 << 8;
cpuptr->cpu_fpirr = C0_IMP_R12000 << 8;
} else {
cpuptr->cpu_prid = C0_IMP_R10000 << 8;
cpuptr->cpu_fpirr = C0_IMP_R10000 << 8;
}
}
cpuptr->cpu_info.struct_version = CPU_STRUCT_VERSION ;
}
/*
* Allow slave processors to add infromation to their klconfig structures.
*/
int
update_klcfg_cpuinfo(nasid_t nasid, int slice)
{
lboard_t *brd;
klcpu_t *acpu;
if (nasid == INVALID_NASID)
nasid = get_nasid();
if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid),
KLTYPE_IP27))) {
printf("update_klcfg_cpuinfo: Can't find IP27 on nasid %d\n",
nasid);
return -1;
}
if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU))) {
printf("update_klcfg_cpuinfo: Can't find any CPU structures\n");
return -1;
}
do {
if ((acpu->cpu_info.physid) == slice) {
add_klcfg_cpuinfo(nasid, acpu);
return 0;
}
} while (acpu = (klcpu_t *)find_component(brd,
(klinfo_t *)acpu,
KLSTRUCT_CPU));
printf("update_klcfg_cpuinfo: Couldn't find my structure.\n");
return -1;
}
void
init_klcfg_cpu(__psunsigned_t hub_base, lboard_t *brd_ptr, int cpu_ndx,
int updateme)
{
klcpu_t *cpuptr ;
nasid_t nasid;
__psunsigned_t x ;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((cpuptr = (klcpu_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_cpu: Cannot add cpu component.Node %d\n",
nasid);
return;
}
cpuptr->cpu_info.struct_type = KLSTRUCT_CPU ;
x = (cpu_ndx == IP27_CPU0_INDEX) ? PI_CPU_ENABLE_A : PI_CPU_ENABLE_B ;
cpuptr->cpu_info.flags = (LD(REMOTE_HUB(NASID_GET(hub_base), x)) ? KLINFO_ENABLE : 0) ;
if (cpuptr->cpu_info.flags != KLINFO_ENABLE) {
char *key, disable_why[64], *ptr;
key = (cpu_ndx == IP27_CPU0_INDEX) ? "DisableA" : "DisableB";
if (ip27log_getenv(NASID_GET(hub_base), key, disable_why, 0, 0) >= 0) {
cpuptr->cpu_info.flags = KLINFO_FAILED;
if (ptr = strchr(disable_why, ':')) {
*ptr = 0;
cpuptr->cpu_info.diagval = atoi(disable_why);
}
else
cpuptr->cpu_info.diagval = KLDIAG_TBD;
}
else {
/*
* We really don't know why this CPU failed. The LED
* value is stashed away in its PI_RT_COMPARE_X and
* we need to change it to a kldiag value
*/
__psunsigned_t rt_comp;
unsigned short kldg;
char led, buf[64];
char *key = ((cpu_ndx == IP27_CPU0_INDEX) ?
"DisableA" : "DisableB");
rt_comp = (cpu_ndx == IP27_CPU0_INDEX) ?
PI_RT_COMPARE_A : PI_RT_COMPARE_B;
led = (char) REMOTE_HUB_L(NASID_GET(hub_base), rt_comp);
kldg = hled_get_kldiag(led);
sprintf(buf, "%d: %x; %s", kldg, led,
get_diag_string(kldg));
if (!hled_tdisable(led))
{
if(led == FLED_MODEBIT)
ed_cpu_mem(NASID_GET(hub_base), key, buf, buf, 1, 0);
else
ed_cpu_mem(NASID_GET(hub_base), key, buf, buf, 0, 0);
}
cpuptr->cpu_info.diagval = kldg;
}
}
cpuptr->cpu_info.physid = cpu_ndx ;
cpuptr->cpu_info.virtid = -1;
if (updateme) {
add_klcfg_cpuinfo(NASID_GET(hub_base),cpuptr);
} else { /* cpu present but disabled or cpu not present */
cpuptr->cpu_prid = 0xffff;
cpuptr->cpu_fpirr = 0xffff;
cpuptr->cpu_speed = -1 ; /* XXX get these from cfgp */
}
/*
* allocate the cpu error structure for future use.
*/
cpuptr->cpu_info.errinfo = kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klcpu_err_t));
if (cpuptr->cpu_info.errinfo == -1) {
printf("init_klcfg_cpu: err struct alloc failed %d node\n",
nasid);
}
return;
}
void
init_klcfg_hub(__psunsigned_t hub_base, lboard_t *brd_ptr, int hub_ndx)
{
klhub_t *hubptr ;
nasid_t nasid;
#ifdef SABLE
klhub_uart_t *hub_uart_ptr;
#endif
char hub_nic_info[1024] ;
*hub_nic_info = 0 ;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((hubptr = (klhub_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_hub: Cannot add hub component.Node %d\n",
nasid);
return;
}
hubptr->hub_info.struct_type = KLSTRUCT_HUB ;
if(nasid == NASID_GET(hub_base))
hubptr->hub_info.flags = KLINFO_ENABLE ;
else
hubptr->hub_info.flags = 0 ;
hubptr->hub_port.port_nasid = INVALID_NASID;
hubptr->hub_info.physid = NASID_GET(hub_base) ;
hubptr->hub_info.nasid = nasid;
hubptr->hub_info.virtid = -1;
hubptr->hub_info.revision = (unsigned char)
((LD(hub_base + NI_STATUS_REV_ID) & NSRI_REV_MASK) >>
NSRI_REV_SHFT);
/* Allocate and read the MFG NIC header */
get_hub_nic_info((nic_data_t)REMOTE_HUB(NASID_GET(hub_base), MD_MLAN_CTL),
hub_nic_info) ;
if (hubptr->hub_mfg_nic = klmalloc_nic_off(nasid, strlen(hub_nic_info)))
strcpy((char *)NODE_OFFSET_TO_K1(nasid, hubptr->hub_mfg_nic),
hub_nic_info) ;
hubptr->hub_speed =
(((ip27config_t *)(IP27CONFIG_ADDR_NODE(nasid)))->freq_hub);
#ifdef SABLE
if ((hub_uart_ptr =
(klhub_uart_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_hub:Cannot add uart component.Node %d\n",
nasid);
return;
}
hub_uart_ptr->hubuart_info.struct_type = KLSTRUCT_HUB_UART ;
hub_uart_ptr->hubuart_info.flags =
KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_INSTALL ;
hub_uart_ptr->hubuart_info.virtid = 0; /* if you change this
* you are looking for
* trouble.
*/
hub_uart_ptr->hubuart_info.physid = 0 ;
hub_uart_ptr->hubuart_info.nasid = hubptr->hub_info.nasid ;
hub_uart_ptr->hubuart_info.widid = hubptr->hub_info.widid ;
hub_uart_ptr->hubuart_info.module = hubptr->hub_info.module ;
#endif /* SABLE */
/*
* allocate the cpu error structure for future use.
*/
hubptr->hub_info.errinfo = kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klhub_err_t));
if (hubptr->hub_info.errinfo == -1) {
printf("init_klcfg_hub: err struct alloc failed %d node\n",
nasid);
}
else if (((HUB_COMP_ERROR(brd_ptr, &hubptr->hub_info))->he_extension =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klhub_err_ext_t))) == -1)
printf("init_klcfg_hub: err struct alloc failed %d node\n",
nasid);
/*
* Do we need error info for hubuart??
*/
return;
}
void
init_klcfg_membnk(__psunsigned_t hub_base, lboard_t *brd_ptr, int n)
{
klmembnk_t *mem_ptr ;
int i;
nasid_t nasid;
__uint64_t mem_cfg;
char buf[8];
u_short prem_mask;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((mem_ptr =
(klmembnk_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_membnk: Cannot add memory component.Node %d\n",
nasid);
return;
}
mem_ptr->membnk_info.struct_type = KLSTRUCT_MEMBNK ;
mem_ptr->membnk_info.struct_version = MEMORY_STRUCT_VERSION ;
mem_ptr->membnk_info.flags = KLINFO_ENABLE ;
mem_ptr->membnk_info.physid = n ; /* XXX */
mem_ptr->membnk_info.virtid = -1;
mem_ptr->membnk_info.nasid = NASID_GET(hub_base);
if (ip27log_getenv(NASID_GET(hub_base), "DisableMemMask", 0, 0, 0) >= 0)
mem_ptr->membnk_info.diagval = KLDIAG_NOT_SET;
else
mem_ptr->membnk_info.diagval = KLDIAG_PASSED;
mem_ptr->membnk_memsz = 0 ;
mem_ptr->membnk_attr = 0;
/*
* The ip27 prom has programmed the memory config register. Read it
* and setup the dimm select and bank size information.
*/
mem_cfg = translate_hub_mcreg(LD(hub_base + MD_MEMORY_CONFIG));
mem_ptr->membnk_dimm_select =
(mem_cfg & MMC_DIMM0_SEL_MASK) >> MMC_DIMM0_SEL_SHFT;
for (i = 0; i < MD_MEM_BANKS; i++) {
mem_ptr->membnk_bnksz[i] =
MD_SIZE_MBYTES((mem_cfg & MMC_BANK_MASK(i))
>> MMC_BANK_SHFT(i));
#ifdef SABLE
if (mem_ptr->membnk_bnksz[i] > 16) {
#if 0
printf("Reducing %d MB bank to 16 MB\n",
mem_ptr->membnk_bnksz[i]);
#endif
mem_ptr->membnk_bnksz[i] = 16;
}
#endif
mem_ptr->membnk_memsz += mem_ptr->membnk_bnksz[i] ;
}
if (mem_cfg & MMC_DIR_PREMIUM)
mem_ptr->membnk_attr |= (MEMBNK_PREMIUM << MD_MEM_BANKS );
ip27log_getenv(NASID_GET(hub_base),PREMIUM_BANKS,buf,"00",0);
prem_mask = (u_short)strtoull(buf,0,16);
mem_ptr->membnk_attr |= prem_mask;
/*
* allocate the membnk error structure for future use.
*/
mem_ptr->membnk_info.errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klgeneric_error_t));
if (mem_ptr->membnk_info.errinfo == -1) {
printf("init_klcfg_membnk: err alloc failed %d node\n",
nasid);
}
return;
}
/* IO BOARDS */
lboard_t *
init_klcfg_baseio(__psunsigned_t widget_base)
{
lboard_t *brd_ptr ;
nasid_t nasid ;
int wid ;
nasid = NASID_GET(widget_base) ;
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_baseio: Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = KLTYPE_BASEIO ;
wid = WIDGETID_GET(widget_base);
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
return (kl_config_add_board(nasid, brd_ptr));
}
static int
HUB2METAROUTER_MODID(pcfg_t *p, int hubnum)
{
#define MAX_META_ROUTER_MODID 99
static int nhubs = 0;
int i, offset, subval;
if(!nhubs)
{
for(i = 0; i < p->count; i++)
{
if(p->array[i].any.type == PCFG_TYPE_HUB)
nhubs++;
}
}
if(nhubs <= 64)
{
/* 128p or less */
if(hubnum & 0x1)
return(MAX_META_ROUTER_MODID);
return(MAX_META_ROUTER_MODID-1);
}
/* else 256p or more */
offset = ((hubnum-1) / 20) * 4;
subval = (hubnum-1) % 4;
return(MAX_META_ROUTER_MODID - offset - subval);
}
/*
* This routine has been verified to work
*/
void
upd_rou_mod_meta_hubless(pcfg_t *p, pcfg_router_t *rou_cf, lboard_t *rou_ptr)
{
int peer_rtr, r1, r2 ;
if (!IS_META(rou_cf)) { /* Hubless */
if ((peer_rtr = rou_cf->port[6].index) == PCFG_INDEX_INVALID)
return ;
if (((r1 = p->array[peer_rtr].router.port[4].index)
!= PCFG_INDEX_INVALID) &&
!(p->array[r1].hub.flags & PCFG_HUB_HEADLESS)) {
rou_ptr->brd_module = p->array[r1].hub.module;
}
else
if (((r2 = p->array[peer_rtr].router.port[5].index)
!= PCFG_INDEX_INVALID) &&
!(p->array[r2].hub.flags & PCFG_HUB_HEADLESS)) {
rou_ptr->brd_module = p->array[r2].hub.module;
}
else
printf("***Warning: Could not find module number for router nic = 0x%x\n",
rou_ptr->brd_nic) ;
}
else { /* META ROUTERS */
int port, done = 0, odd;
/*
* XXX: HACK!!! If meta-rtr is connected to a odd numbered module
* moduleid = 1; else moduelid = 2 Refer to Jim Ammon's picture!
*/
/* The problem with this scheme is that it clashes with normal
* modules with id 1 and 2. Everyone will normally have their
* modules starting with 1 and 2. This will make meta routers in
* slots 1 and 2 looks as if they are on the same brd as routers
* in slots 1 and 2. Also if we want to distinguish between
* 2 routers by their module ids, this will not allow it.
* The fix is to start meta router module ids from a high value
* downwards and hope that the system does not get too big that
* they will clash.
*/
for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
int index;
if (((index = rou_cf->port[port].index) != PCFG_INDEX_INVALID) &&
(p->array[index].any.type == PCFG_TYPE_ROUTER) &&
IS_RESET_SPACE_RTR(&p->array[index].router)) {
int r_port, r_index;
for (r_port = 1; r_port <= MAX_ROUTER_PORTS; r_port++)
if (((r_index = p->array[index].router.port[r_port].index)
!= PCFG_INDEX_INVALID) &&
(p->array[r_index].any.type == PCFG_TYPE_HUB) &&
!(p->array[r_index].hub.flags & PCFG_HUB_HEADLESS)) {
if (!done) {
int hubmod = p->array[r_index].hub.module;
odd = hubmod & 0x1;
rou_ptr->brd_module = HUB2METAROUTER_MODID(p,
hubmod);
done = 1;
}
else if ((odd && !(p->array[r_index].hub.module & 0x1))
|| (!odd && (p->array[r_index].hub.module &
0x1)))
printf("*** Meta rtr NIC 0x%lx moduleid can't be "
"allocated. Check moduleids or cabling\n",
rou_cf->nic);
}
}
}
}
}
int
hubless_rtr(pcfg_t *p, pcfg_router_t *rou_cf, int flag)
{
int port;
pcfg_hub_t *ph ;
int index ;
ForEachValidRouterPort(rou_cf,port) {
index = rou_cf->port[port].index ;
if (pcfgIsHub(p,index)) {
ph = pcfgGetHub(p,index) ;
if (!flag)
if (!(IS_HUB_MEMLESS(ph)))
return 0;
else
if (!(IS_HUB_HEADLESS(ph)))
return 0;
}
}
return 1;
}
void
update_brd_module(lboard_t *brd_ptr)
{
char buf[8];
ip27log_getenv(NASID_GET(brd_ptr), IP27LOG_MODULE_KEY, buf, "0", 0);
brd_ptr->brd_module = (moduleid_t) atoi(buf);
}
lboard_t *
init_klcfg_routerb(pcfg_t *p,
nasid_t nasid,
pcfg_router_t *pcfg_routerp,
int router_type)
{
lboard_t *brd_ptr;
char buf[8];
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
return NULL;
}
brd_ptr->brd_type = router_type;
brd_ptr->brd_nic = pcfg_routerp->nic;
brd_ptr->brd_slot = pcfg_routerp->slot | SLOTNUM_ROUTER_CLASS;
if (!IS_META(pcfg_routerp))
brd_ptr->brd_partition = pcfg_routerp->partition;
if (IS_META(pcfg_routerp) || hubless_rtr(p, pcfg_routerp, 0))
upd_rou_mod_meta_hubless(p, pcfg_routerp, brd_ptr);
else
brd_ptr->brd_module = pcfg_routerp->module;
if (router_type != KLTYPE_NULL_ROUTER)
init_klcfg_routerc(pcfg_routerp, brd_ptr, 0, 0);
return (kl_config_add_board(nasid, brd_ptr));
}
klbri_t *
init_klcfg_bridge(__psunsigned_t bridge_base, lboard_t *brd_ptr, int n)
{
klbri_t *briptr ;
nasid_t nasid;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((briptr = (klbri_t *)
kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_bridge: Cannot add component. Node %d\n",
nasid);
return (klbri_t *)NULL;
}
briptr->bri_info.struct_type = KLSTRUCT_BRI ;
briptr->bri_info.struct_version = BRIDGE_STRUCT_VERSION ;
briptr->bri_info.flags = KLINFO_ENABLE ;
briptr->bri_info.nic = brd_ptr->brd_nic ;
briptr->bri_info.nasid = brd_ptr->brd_nasid ;
briptr->bri_info.physid = n ;
briptr->bri_info.virtid = -1 ;
briptr->bri_info.widid = WIDGETID_GET(bridge_base) ;
briptr->bri_info.revision =
(LW(bridge_base + BRIDGE_WID_ID) >> 28) & 0xf;
/* XXX */
briptr->bri_eprominfo = -1 ;
briptr->bri_bustype = KLSTRUCT_PCI ;
/* XXX */
/*
* allocate the bridge error structure for future use.
*/
briptr->bri_info.errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klbridge_err_t));
if (briptr->bri_info.errinfo == -1) {
printf("init_klcfg_bridge: err alloc failed %d node\n",
nasid);
}
return briptr;
}
void
init_klcfg_routerc(pcfg_router_t *router_base, lboard_t *brd_ptr, int v, int p)
{
klrou_t *rouptr ;
klrouter_err_t *err_info;
int i;
nasid_t nasid;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((rouptr = (klrou_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_routerc: Cannot add component.Node %d\n",
nasid);
return;
}
rouptr->rou_info.struct_type = KLSTRUCT_ROU ;
rouptr->rou_info.struct_version = ROUTER_VECTOR_VERS;
rouptr->rou_info.flags = KLINFO_ENABLE ;
rouptr->rou_info.nic = router_base->nic ;
rouptr->rou_info.physid = p ;
rouptr->rou_info.virtid = v ;
rouptr->rou_flags = router_base->flags ;
#if 0
rouptr->rou_box_nic = router_base->boxid ;
#endif
for (i=1; i<=MAX_ROUTER_PORTS; i++)
rouptr->rou_port[i].port_nasid = INVALID_NASID ;
rouptr->rou_mfg_nic = NULL ;
/*
* allocate the router error structure for future use.
*/
rouptr->rou_info.errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klrouter_err_t));
if (rouptr->rou_info.errinfo == -1) {
printf("init_klcfg_router: err alloc failed %d node\n",
nasid);
}
else {
err_info = ROU_COMP_ERROR(brd_ptr, (&(rouptr->rou_info)));
for (i = 1; i <= MAX_ROUTER_PORTS; i++)
err_info->re_status_error[i] = router_base->port[i].error;
}
return;
}
klinfo_t *
init_klcfg_ioc3(__psunsigned_t bridge_base, lboard_t *brd_ptr, int npci)
{
klioc3_t *ioc3p ;
nasid_t nasid;
klinfo_t *ktmp ;
unsigned char ioc3_flags = 0 ;
console_t *cons ;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((ioc3p = (klioc3_t *)kl_config_alloc_component
(nasid, brd_ptr)) == NULL) {
printf("init_klcfg_ioc3: Cannot add component.Node %d\n",
nasid);
return NULL ;
}
/* Find if this ioc3 is a valid console device */
cons = KL_CONFIG_CH_CONS_INFO(get_nasid()) ;
ioc3_flags = KLINFO_ENABLE|KLINFO_CONTROLLER;
if ((cons->uart_base) && (cons->wid == WIDGETID_GET(bridge_base))) {
db_printf("*** Local Master IO6 is on widget 0x%lx\n",
WIDGETID_GET(bridge_base)) ;
#if 0
ioc3_flags = KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_INSTALL ;
#endif
brd_ptr->brd_flags |= LOCAL_MASTER_IO6 ;
} else {
db_printf("*** Non-Master IO6 found on widget 0x%lx\n",
WIDGETID_GET(bridge_base)) ;
}
/* IOC3 */
ktmp = (klinfo_t *)&ioc3p->ioc3_info ;
ktmp->struct_type = KLSTRUCT_IOC3 ;
ktmp->flags = ioc3_flags ;
ktmp->nic = (nic_t) -1 ;
ktmp->physid = npci ;
ktmp->revision = LW(bridge_base + BRIDGE_TYPE0_CFG_DEV(npci) + 8) & 0xff ;
ktmp->nasid = brd_ptr->brd_nasid ;
ktmp->widid = WIDGETID_GET(bridge_base) ;
/* SUPERIO */
ktmp = (klinfo_t *)&ioc3p->ioc3_superio ;
ktmp->struct_type = KLSTRUCT_IOC3UART ;
ktmp->flags = ioc3_flags ;
ktmp->nic = (nic_t) -1 ;
ktmp->physid = 0 ; /* XXX UART's physid is 0 */
ktmp->virtid = -1 ;
ktmp->diagval = KLDIAG_PASSED ;
ktmp->nasid = brd_ptr->brd_nasid ;
ktmp->widid = ioc3p->ioc3_info.widid ;
ktmp->revision = -1 ;
/* ETHERNET */
ktmp = (klinfo_t *)&ioc3p->ioc3_enet ;
ktmp->struct_type = KLSTRUCT_IOC3ENET ;
ktmp->flags = ioc3_flags ;
ktmp->nic = (nic_t) -1 ;
ktmp->physid = 0 ;
ktmp->virtid = -1 ;
ktmp->diagval = KLDIAG_PASSED ;
ktmp->nasid = brd_ptr->brd_nasid ;
ktmp->widid = ioc3p->ioc3_info.widid ;
ktmp->revision = ioc3p->ioc3_info.revision ;
ktmp->errinfo = kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klgeneric_error_t));
if (ktmp->errinfo == -1) {
printf("init_klcfg_ioc3: err alloc failed %d node\n",
nasid);
}
return ((klinfo_t *)ioc3p) ;
}
void
init_klcfg_qscsi(__psunsigned_t bridge_base, lboard_t *brd_ptr, int npci)
{
klscsi_t *scsip ;
int i ;
nasid_t nasid;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((scsip = (klscsi_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_qscsi: Cannot add component. Node %d\n",
nasid);
return;
}
scsip->scsi_info.struct_type = KLSTRUCT_SCSI ;
scsip->scsi_info.flags =
KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_INSTALL ;
scsip->scsi_info.nasid = nasid ;
scsip->scsi_info.nic = (nic_t) -1 ;
scsip->scsi_info.physid = npci ;
scsip->scsi_info.widid = WIDGETID_GET(bridge_base) ;
scsip->scsi_info.revision =
LW(bridge_base + BRIDGE_TYPE0_CFG_DEV(npci) + 8) & 0xff ;
scsip->scsi_info.arcs_compt = 0 ;
#if 0 /* Printfs for debug */
scsip->scsi_info.virtid = brd_ptr->brd_nasid*MAX_PORT_NUM + npci ;
printf("init_klcfg_qscsi: nasid=%d, widget=%d, pciid=%d\n",
scsip->scsi_info.nasid,
scsip->scsi_info.widid,
scsip->scsi_info.physid) ;
#endif
scsip->scsi_numdevs = 0;
for (i = 0; i<MAX_SCSI_DEVS; i++)
scsip->scsi_devinfo[i] = NULL ;
/* add driver info */
/*
* allocate the scsi error structure for future use.
*/
scsip->scsi_info.errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klgeneric_error_t));
if (scsip->scsi_info.errinfo == -1) {
printf("init_klcfg_qscsi: err alloc failed %d node\n",
nasid);
}
return;
}
#if defined (SABLE)
void
init_klcfg_sscsi(__psunsigned_t bridge_base, lboard_t *brd_ptr, int npci)
{
klscsi_t *scsip ;
int i;
nasid_t nasid;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((scsip = (klscsi_t *)kl_config_alloc_component(nasid,
brd_ptr)) == NULL) {
printf("init_klcfg_sscsi: Cannot add component. Node %d\n",
nasid);
return;
}
scsip->scsi_info.struct_type = KLSTRUCT_SCSI ;
scsip->scsi_info.flags =
KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_INSTALL ;
scsip->scsi_info.nasid = nasid ;
scsip->scsi_info.nic = (nic_t) 0xABfEDDDD ;
scsip->scsi_info.physid = npci ;
#if 0
scsip->scsi_info.virtid = brd_ptr->brd_nasid*MAX_PORT_NUM + npci ;
#endif
scsip->scsi_info.widid = WIDGETID_GET(bridge_base) ;
scsip->scsi_numdevs = 0;
for (i = 0; i<MAX_SCSI_DEVS; i++)
scsip->scsi_devinfo[i] = NULL ;
/* add driver info */
}
#endif /* SABLE */
void
kl_disable_board(lboard_t *brd_ptr)
{
brd_ptr->brd_flags &= ~ENABLE_BOARD;
}
/* IO BOARD COMPONENTS */
void
init_klcfg_xbow(__psunsigned_t xbow_base, lboard_t *brd_ptr)
{
volatile __psunsigned_t wid_base;
klxbow_t *xbowptr ;
nasid_t nasid;
reg32_t wid_id;
nasid = KL_CONFIG_BOARD_NASID(brd_ptr);
if ((xbowptr = (klxbow_t *)kl_config_alloc_component(nasid,
brd_ptr))==NULL){
printf("init_klcfg_xbow: Cannot add component. Node %d\n",
nasid);
return;
}
wid_base = SN0_WIDGET_BASE(nasid, 0);
wid_id = LD32(wid_base + WIDGET_ID);
xbowptr->xbow_info.struct_type = KLSTRUCT_XBOW ;
xbowptr->xbow_info.nic = -1 ;
xbowptr->xbow_info.virtid = 0 ;
xbowptr->xbow_info.revision = XWIDGET_REV_NUM(wid_id) ;
xbowptr->xbow_master_hub_link = xbow_get_master_hub(xbow_base);
/*
* allocate the xbow error structure for future use.
*/
xbowptr->xbow_info.errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT, sizeof(klxbow_err_t));
if (xbowptr->xbow_info.errinfo == -1) {
printf("init_klcfg_xbow: err alloc failed %d node\n",
nasid);
}
return;
}
/* this function should be kept in sync with the copy in ml/SN0/module_info.c
and the decode routine in the same file */
#define SN0_SERIAL_FUDGE 0x6e
void
encode_str_serial(const char *src, char *dest) {
int i;
for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
dest[i] = src[MAX_SERIAL_NUM_SIZE/2 +
((i%2) ? ((i/2 * -1) - 1) : (i/2))] +
SN0_SERIAL_FUDGE;
}
}
lboard_t *
init_klcfg_midplane(__psunsigned_t widget_base, lboard_t *node_lbptr)
{
lboard_t *mpl_lbptr;
nasid_t nasid;
klmod_serial_num_t *ser_num ;
klhub_t *hubp ;
char *c ;
nasid = NASID_GET(widget_base) ;
if ((mpl_lbptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_midplane:Cannot alloc board struct\n");
return NULL;
}
mpl_lbptr->brd_type = KLTYPE_MIDPLANE8 ;
/* chosen arbitrarily. 0-3 cpu slots. 8-f are widget ids */
mpl_lbptr->brd_slot = SLOTNUM_MIDPLANE_CLASS;
/*
* This does not belong here! We need to discover each xbow, since
* we can have more than one xbow here.
* Normal speedo & 12p4i config donot have a crossbow. Whereas
* a speedo with a xbox does have a xbow.
*/
if ((!(SN00) && !(CONFIG_12P4I)) || is_xbox_config(nasid))
init_klcfg_xbow(widget_base, mpl_lbptr) ;
/* At Early Access time, the xbow does not have the NIC yet.
It is available off the first node board's NIC. Assuming
that this is already read. Process that info here. */
ser_num = (klmod_serial_num_t *)init_klcfg_compt(
widget_base, mpl_lbptr, 0, KLSTRUCT_MOD_SERIAL_NUM, 0) ;
ser_num->snum_info.flags = 0 ; /* No flags needed */
/* Decrease the number of compts by 1 so that this is
is not visible */
mpl_lbptr->brd_numcompts -= 1 ; /* for Compatibility */
if (!(SN00)) {
if ((hubp = (klhub_t *)find_component(node_lbptr, NULL,
KLSTRUCT_HUB))) {
if (hubp->hub_mfg_nic)
if (c = strstr((char *)NODE_OFFSET_TO_K1(
node_lbptr->brd_nasid,
hubp->hub_mfg_nic), "MODULEID")) {
int i;
char temp[MAX_SERIAL_NUM_SIZE];
c = strstr(c, "Serial:") ;
for (i = 0;i<MAX_SERIAL_NUM_SIZE &&
(*(c+7+i) != ';');i++) {
temp[i] = *(c+7+i);
}
if (i<MAX_SERIAL_NUM_SIZE)
temp[i] = '\0';
DB_PRINTF(("Serial Number: %s\n",
temp)) ;
encode_str_serial(temp,ser_num->snum.snum_str);
if (c)
c = strstr(c,"MPLN");
if (c)
c = strstr(c,"Laser:");
if (c)
c += 6;
if (c)
mpl_lbptr->brd_nic = strtoull(c, 0, 16);
}
}
} /* SN00 */
return (kl_config_add_board(nasid, mpl_lbptr));
}
void
add_klcfg_xbow_port(lboard_t *xbow_lbptr,
int link,
int wid_type,
lboard_t *widget_lbptr)
{
klxbow_t *xbow_p;
nasid_t nasid = NASID_GET((__psunsigned_t)(xbow_lbptr));
nasid_t port_nasid;
int xb_link = link - BASE_XBOW_PORT;
if (wid_type == HUB_WIDGET_PART_NUM) {
port_nasid = NASID_GET((__psunsigned_t)(widget_lbptr));
widget_lbptr = find_lboard((lboard_t *)
KL_CONFIG_INFO(nasid),
KLTYPE_IP27);
}
else port_nasid = 0;
xbow_p = (klxbow_t *)find_component(xbow_lbptr, NULL, KLSTRUCT_XBOW);
xbow_p->xbow_port_info[xb_link].port_nasid = port_nasid;
xbow_p->xbow_port_info[xb_link].port_offset = K0_TO_NODE_OFFSET(widget_lbptr);
if (wid_type == HUB_WIDGET_PART_NUM) {
xbow_p->xbow_port_info[xb_link].port_flag = XBOW_PORT_HUB;
}
else {
xbow_p->xbow_port_info[xb_link].port_flag = XBOW_PORT_IO;
}
xbow_p->xbow_port_info[xb_link].port_flag |= XBOW_PORT_ENABLE;
}
lboard_t *
init_klcfg_4chscsi(__psunsigned_t widget_base)
{
lboard_t *brd_ptr;
nasid_t nasid;
klscsi_t *qscsip ;
int wid ;
nasid = NASID_GET(widget_base) ;
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_4chscsi:Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = KLTYPE_4CHSCSI ;
wid = WIDGETID_GET(widget_base);
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
return (kl_config_add_board(nasid, brd_ptr));
}
lboard_t *
init_klcfg_tpu(__psunsigned_t widget_base)
{
lboard_t *brd_ptr;
nasid_t nasid;
int wid ;
klinfo_t *tpuci;
kltpu_t *tpuc;
nasid = NASID_GET(widget_base) ;
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_tpu: Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = KLTYPE_TPU ;
wid = WIDGETID_GET(widget_base);
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
if ((tpuc = (kltpu_t *)kl_config_alloc_component(nasid, brd_ptr))==NULL){
printf("init_klcfg_tpu: Cannot add component. Node %d\n",
nasid);
return NULL;
}
tpuci = &tpuc->tpu_info;
tpuci->struct_type = KLSTRUCT_TPU ;
tpuci->flags = KLINFO_ENABLE;
tpuci->nic = -1 ;
tpuci->physid = brd_ptr->brd_slot; /* To get unique locator names */
tpuci->revision = (LW(widget_base + WIDGET_ID) >> 28) & 0xf;
tpuci->virtid = -1;
tpuci->widid = wid;
tpuci->nasid = nasid ;
return (kl_config_add_board(nasid, brd_ptr));
}
lboard_t *
init_klcfg_gsn(__psunsigned_t widget_base, int gsntype)
{
lboard_t *brd_ptr;
nasid_t nasid;
int wid ;
klinfo_t *gsnci;
klgsn_t *gsnc;
nasid = NASID_GET(widget_base) ;
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_gsn: Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = (gsntype == KLSTRUCT_GSN_A) ?
KLTYPE_GSN_A : KLTYPE_GSN_B;
wid = WIDGETID_GET(widget_base);
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
if ((gsnc = (klgsn_t *)kl_config_alloc_component(nasid, brd_ptr))==NULL){
printf("init_klcfg_gsn: Cannot add component. Node %d\n",
nasid);
return NULL;
}
gsnci = &gsnc->gsn_info;
gsnci->struct_type = gsntype;
gsnci->flags = KLINFO_ENABLE;
gsnci->nic = -1 ;
gsnci->physid = brd_ptr->brd_slot; /* To get unique locator names */
gsnci->revision = (LW(widget_base + WIDGET_ID) >> 28) & 0xf;
gsnci->virtid = -1;
gsnci->widid = wid;
gsnci->nasid = nasid ;
return (kl_config_add_board(nasid, brd_ptr));
}
void
init_klcfg_uvme(__psunsigned_t bridge_base, lboard_t *brd_ptr, int npci)
{
printf("Fixme: init_klcfg_uvme: unimplemented\n");
printf("Fixme: init_klcfg_uvme: br base %x lbrd %x pci %x\n",
bridge_base, brd_ptr, npci);
}
/* called from gfx_widget_discover() for each gfx widget */
lboard_t *
init_klcfg_graphics(__psunsigned_t widget_base)
{
lboard_t *lb;
klgfx_t *klg;
klinfo_t *gi;
nasid_t nasid;
int wid;
nasid = NASID_GET(widget_base);
wid = WIDGETID_GET(widget_base);
if ((lb = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_graphics: Cannot allocate board struct\n");
return NULL;
}
lb->brd_type = KLTYPE_GFX;
lb->brd_slot = xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
if ((klg = (klgfx_t *)kl_config_alloc_component(nasid, lb)) == NULL){
printf("init_klcfg_graphics: Cannot add component. Node %d\n", nasid);
return NULL;
}
gi = &klg->gfx_info;
gi->struct_type = KLSTRUCT_GFX;
/* set both controller and device flags for gfx */
gi->flags = KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_DEVICE;
gi->nic = -1;
gi->physid = 0;
/* XXX where does 16 come from???? */
gi->virtid = nasid * 16; /* To get unique locator names */
gi->widid = wid;
gi->nasid = nasid ;
klg->cookie = KLGFX_COOKIE;
klg->old_gndevs = klg->old_gdoff0 = 0;
klg->gfx_mfg_nic = NULL;
/*
* [sigh] this can't be set until later, as brd_module doesn't
* get set until after this board is discovered.
*
* klg->moduleslot = (lb->brd_module << 8) | SLOTNUM_GETSLOT(lb->brd_slot);
*/
klg->moduleslot = 0;
klg->gfx_next_pipe = NULL;
klg->gfx_specific = NULL;
return (kl_config_add_board(nasid, lb));
}
lboard_t *
init_klcfg_xthd(__psunsigned_t widget_base)
{
lboard_t *lb;
klinfo_t *gi;
klxthd_t *klg;
nasid_t nasid;
int wid;
nasid = NASID_GET(widget_base);
wid = WIDGETID_GET(widget_base);
if ((lb = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_xthd: Cannot allocate board struct\n");
return NULL;
}
lb->brd_type = KLTYPE_XTHD;
lb->brd_slot = xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
if ((klg = (klxthd_t *)kl_config_alloc_component(nasid, lb)) == NULL){
printf("init_klcfg_xthd: Cannot add component. Node %d\n", nasid);
return NULL;
}
gi = &klg->xthd_info;
gi->struct_type = KLSTRUCT_XTHD;
/* set both controller and device flags for gfx */
gi->flags = KLINFO_ENABLE|KLINFO_CONTROLLER|KLINFO_DEVICE;
gi->nic = -1;
gi->physid = 0;
/* XXX where does 16 come from???? */
gi->virtid = nasid * 16; /* To get unique locator names */
gi->widid = wid;
gi->nasid = nasid ;
return (kl_config_add_board(nasid, lb));
}
lboard_t *
init_klcfg_brd(__psunsigned_t bridge_base, int type)
{
lboard_t *brd_ptr ;
nasid_t nasid;
int wid ;
nasid = NASID_GET(bridge_base);
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_brd: Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = type;
wid = WIDGETID_GET(bridge_base) ;
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
return (kl_config_add_board(nasid, brd_ptr));
}
klinfo_t *
init_klcfg_compt( __psunsigned_t cbase ,
lboard_t *bp ,
int physid, int type, int flag)
{
klcomp_t *compt ;
klinfo_t *ki ;
nasid_t nasid;
/* Get the nasid from lboard_t */
nasid = KL_CONFIG_BOARD_NASID(bp);
if ((compt = (klcomp_t *)kl_config_alloc_component(nasid,
bp))==NULL){
printf("init_klcfg_compt: Cannot add component. Node %d\n",
nasid);
return NULL ;
}
/* take a typical member of the union */
ki = &compt->kc_ioc3.ioc3_info ;
ki->struct_type = type ;
/* XXX different for CPU HUB etc. */
ki->flags =
KLINFO_ENABLE | KLINFO_CONTROLLER|KLINFO_INSTALL ;
ki->nic = -1 ;
ki->physid = physid ;
ki->virtid = nasid * 16 ; /* To get unique locator names */
ki->widid = WIDGETID_GET(cbase) ;
ki->nasid = nasid ;
if (flag)
ki->revision =
LW(cbase + BRIDGE_TYPE0_CFG_DEV(physid) + 8) & 0xff ;
ki->errinfo =
kl_config_info_alloc(nasid, ERRINFO_STRUCT,
sizeof(klgeneric_error_t));
if (ki->errinfo == -1) {
printf("init_klcfg_compt: errinfo alloc failed on %d node\n",
nasid);
}
return ki ;
}
lboard_t *
init_klcfg_menet(__psunsigned_t bridge_base)
{
lboard_t *brd_ptr ;
nasid_t nasid;
int wid ;
nasid = NASID_GET(bridge_base);
if ((brd_ptr = kl_config_alloc_board(nasid)) == NULL) {
printf("init_klcfg_menet: Cannot allocate board struct\n");
return NULL;
}
brd_ptr->brd_type = KLTYPE_ETHERNET;
wid = WIDGETID_GET(bridge_base) ;
if (SN00 && !is_xbox_config(nasid))
brd_ptr->brd_slot = get_node_slotid(nasid);
else if (CONFIG_12P4I)
brd_ptr->brd_slot =
SLOTNUM_XTALK_CLASS |
SLOTNUM_GETSLOT(get_node_slotid(nasid));
else
brd_ptr->brd_slot =
xbwidget_to_xtslot(get_node_crossbow(nasid), wid);
return (kl_config_add_board(nasid, brd_ptr));
}
void
master_xbow_port_update(klxbow_t *xb, nasid_t nasid)
{
int j;
for (j = 0; j < MAX_XBOW_PORTS; j++) {
xb->xbow_port_info[j].port_nasid = nasid;
}
return;
}
void
master_xbow_port_slave(klxbow_t *xb, int link, nasid_t nasid)
{
link -= BASE_XBOW_PORT;
xb->xbow_port_info[link].port_nasid = nasid;
return;
}
void
slave_xbow_port_update(klxbow_t *xb, nasid_t nasid,
klxbow_t *pxb, nasid_t pnasid, int plink)
{
int hlink = hub_xbow_link(nasid);
int j;
hlink -= BASE_XBOW_PORT;
plink -= BASE_XBOW_PORT;
for (j = 0; j < MAX_XBOW_PORTS; j++) {
if (j != hlink) {
xb->xbow_port_info[j].port_nasid = pnasid;
xb->xbow_port_info[j].port_flag = pxb->xbow_port_info[j].port_flag;
xb->xbow_port_info[j].port_offset =
pxb->xbow_port_info[j].port_offset;
}
else
xb->xbow_port_info[j].port_nasid = nasid;
}
}
int
klconfig_xbow_update(nasid_t nasid, int flag)
{
int link, hub_link = hub_xbow_link(nasid);
klxbow_t *xbow_p;
lboard_t *brd;
__psunsigned_t xbow_base;
xbow_base = SN0_WIDGET_BASE(nasid, 0);
if (!flag)
xbow_reset_arb_register(xbow_base, hub_link);
if (config_find_xbow(nasid, &brd, &xbow_p))
return 0;
if (xbow_p->xbow_master_hub_link != hub_link) {
klxbow_t *master_xbow_p;
lboard_t *master_brd;
nasid_t master_nasid;
int master_link;
master_link = xbow_p->xbow_master_hub_link;
master_nasid = xbow_get_link_nasid(xbow_base, master_link);
if (master_nasid != INVALID_NASID) {
if (config_find_xbow(master_nasid, &master_brd, &master_xbow_p))
return -1;
}
else {
printf("xbow_update: Could not get master nasid\n");
return -1;
}
db_printf("xbow_update: slave xbow 0x%lx master xbow 0x%lx\n",
xbow_p, master_xbow_p);
slave_xbow_port_update(xbow_p, nasid,
master_xbow_p, master_nasid, master_link);
return 0;
}
master_xbow_port_update(xbow_p, nasid);
for (link = BASE_XBOW_PORT; link < MAX_PORT_NUM; link++) {
klxbow_t *slave_xbow_p;
lboard_t *slave_brd;
nasid_t slave_nasid;
if (link == hub_link) continue;
if ((xbow_p->xbow_port_info[link - BASE_XBOW_PORT].port_flag &
XBOW_PORT_HUB) == 0) continue;
slave_nasid = xbow_get_link_nasid(xbow_base, link);
if (slave_nasid != INVALID_NASID) {
if (config_find_xbow(slave_nasid, &slave_brd, &slave_xbow_p)) {
printf("xbow_update: could not get slave xbow board\n");
continue;
}
}
else {
printf("xbow_update: Could not get slave nasid\n");
continue;
}
db_printf("xbow_update: updating slave nasid %d on link %d\n",
slave_nasid, link);
master_xbow_port_slave(xbow_p, link, slave_nasid);
}
return 0;
}
/*
* Function : update_board_nasid
* Parameters : brd_ptr -> pointer to board config structure.
* nasid -> nasid to be set
* Purpose : Update the nasid on the board and its components.
* Assumptions : none.
* Returns : none.
*/
void
update_board_nasid(lboard_t *brd_ptr, nasid_t nasid)
{
klinfo_t *kl_comp;
int i;
#if LDEBUG
printf("update_board_nasid: setting board nasid to 0x%x\n", nasid);
#endif
brd_ptr->brd_nasid = nasid;
for (i = 0; i < KLCF_NUM_COMPS(brd_ptr); i++) {
kl_comp = KLCF_COMP(brd_ptr, i);
kl_comp->nasid = nasid;
}
}
void
klconfig_nasid_update(nasid_t nasid, int flag)
{
lboard_t *brd_ptr;
console_t *cons;
cons = KL_CONFIG_CH_CONS_INFO(nasid);
if (cons->uart_base)
set_console_node(cons, nasid);
brd_ptr = (lboard_t *)KL_CONFIG_INFO(nasid);
while (brd_ptr) {
if (!KLCF_REMOTE(brd_ptr)) {
update_board_nasid(brd_ptr, nasid);
if (brd_ptr->brd_parent)
brd_ptr->brd_parent = (lboard_t *)
((__psunsigned_t)brd_ptr->brd_parent |
((__psunsigned_t)(nasid) << NASID_SHFT)) ;
}
brd_ptr = KLCF_NEXT(brd_ptr);
}
klconfig_xbow_update(nasid, flag);
}
/*
* Function : update_board_nic
* Parameters : brd_ptr -> pointer to board config structure.
* nic -> nic to be set
* Purpose : Update the nic on the board and the hub.
* Assumptions : none.
* Returns : none.
*/
void
update_board_nic(lboard_t *brd_ptr, nic_t nic)
{
klinfo_t *kl_comp;
int i;
#if LDEBUG
printf("update_board_nic: brd_ptr=0x%016llx, nic=%d\n",
brd_ptr, nic);
#endif
brd_ptr->brd_nic = nic;
for(i=0;i<brd_ptr->brd_numcompts;i++)
{
kl_comp = KLCF_COMP(brd_ptr,i);
if (kl_comp->struct_type == KLSTRUCT_HUB)
kl_comp->nic = nic;
}
#if LDEBUG
printf("update_board_nic: return\n");
#endif
}
/*
* Function: klcfg_meta_port_hub_indx -> returns the next hub
* indx connected to the meta rtr or connected to the
* rtr connected to the meta rtr
* Args: p -> pcfg_t ptr
* rou_indx -> meta rtr pcfg indx
* meta_port -> meta rtr port to explore
* last_port -> last port explored; initted to -1
* Returns: hub indx, if found
* -1 otherwise
*/
static int
klcfg_meta_port_hub_indx(pcfg_t *p,
int rou_indx,
int meta_port,
int *last_port)
{
int port, start, port_indx;
port_indx = p->array[rou_indx].router.port[meta_port].index;
if (port_indx == -1)
return -1;
/* There might never be a hub connected to a meta rtr, but why
* take a chance */
if (p->array[port_indx].any.type == PCFG_TYPE_HUB) {
if (*last_port == -2)
return -1;
else {
*last_port = -2;
return port_indx;
}
}
/* Router connected to a meta rtr */
if (IS_META((&p->array[port_indx].router)))
return -1;
if (*last_port == -1)
start = 1;
else
start = *last_port + 1;
for (port = start; port <= MAX_ROUTER_PORTS; port++) {
int index;
index = p->array[port_indx].router.port[port].index;
if (index == -1)
continue;
if (p->array[index].any.type == PCFG_TYPE_HUB) {
*last_port = port;
return index;
}
}
return -1;
}
/*
* Function: klcfg_add_meta_router -> Adds meta rtr to klconfig
* Args: p -> pcfg_t ptr
* rou_indx -> meta rtr indx
* partition -> Add only to partition
* Returns: Non-duplicate brd added
* Logic: Adds a brd structure to all first hubs found on
* each of the ports; Flags all except the first as
* duplicate
*/
lboard_t *
klcfg_add_meta_router(pcfg_t *p, int rou_indx, partid_t partition)
{
int port;
lboard_t *rou_brd, *first_brd = NULL;
for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
int indx, last_port = -1;
if (p->array[rou_indx].router.port[port].index ==
PCFG_INDEX_INVALID)
continue;
while ((indx = klcfg_meta_port_hub_indx(p, rou_indx, port,
&last_port)) != -1) {
pcfg_hub_t *ph = (pcfg_hub_t *)&p->array[indx].hub ;
if (p->array[indx].hub.partition != partition)
continue;
if (IS_HUB_MEMLESS(ph))
continue ;
rou_brd = init_klcfg_routerb(p,
p->array[indx].hub.nasid,
&p->array[rou_indx].router, KLTYPE_META_ROUTER);
if (!rou_brd) {
db_printf("WARNING: Can't add meta router brd"
" on nasid %d\n",
p->array[indx].hub.nasid);
} else {
rou_brd->brd_partition = partition;
if (!first_brd)
first_brd = rou_brd;
else
rou_brd->brd_flags |=
DUPLICATE_BOARD;
}
}
}
return first_brd;
}
/*
* Function : klconfig_discovery_update
* Parameters : none.
* Purpose : After the network discovery, the master cpu assigns the
* nasid to each node, and calls into this routine.
* The nasids on all boards system wide is updated.
* Also, if any router is found that is not to be connected
* to any hub, that router's config is setup.
* Since a router's board exists on each of the nodes it is
* connected to, all except the first router is marked
* as duplicate.
* Assumptions : Runs on master node.
* Returns : 0 or -1 (on failure)
*/
int
klconfig_discovery_update(pcfg_t *p, partid_t partition)
{
pcfg_hub_t *hub_cf;
pcfg_router_t *rou_cf;
int i, j, found_hub, orig_hub;
lboard_t *brd_ptr, *rou_brd;
ForAllPcfg(p,i) {
switch (pcfgGetType(p,i)) {
case PCFG_TYPE_HUB:
hub_cf = pcfgGetHub(p,i) ;
if ((hub_cf->partition != partition) ||
(IS_HUB_MEMLESS(hub_cf)))
continue ;
#if LDEBUG
printf("\tdisc upd: HUB: nasid %d, part %d\n", hub_cf->nasid,
hub_cf->partition);
#endif
/* For a good hub, update nic, part and mod */
brd_ptr = (lboard_t *)KL_CONFIG_INFO(
hub_cf->nasid);
while (brd_ptr) {
if (brd_ptr->brd_type == KLTYPE_IP27) {
update_board_nic(brd_ptr,
hub_cf->nic);
update_brd_module(brd_ptr);
brd_ptr->brd_partition =
hub_cf->partition;
}
brd_ptr = KLCF_NEXT(brd_ptr);
}
break;
case PCFG_TYPE_ROUTER:
rou_cf = pcfgGetRouter(p,i) ;
#if LDEBUG
printf("\tdisc upd: %s %s router: 0x%lx %d\n",
(IS_META(rou_cf) ? "META" : "NORMAL"),
(hubless_rtr(p, rou_cf, 0)? "hubless" : ""),
rou_cf->nic, rou_cf->partition);
#endif
if ( IS_META(rou_cf) ||
hubless_rtr(p, rou_cf, 0) ||
(rou_cf->partition != partition))
break;
/* For a good Router, update dup brd flag */
/* nic, mod, part updated elsewhere. */
found_hub = 0;
ForEachValidRouterPort(rou_cf,j) {
int index = rou_cf->port[j].index ;
#if LDEBUG
printf("\t\tport %d, index=%d\n", j,
index);
#endif
if (!pcfgIsHub(p,index))
continue;
hub_cf = pcfgGetHub(p,index) ;
if (IS_HUB_MEMLESS(hub_cf))
continue ;
if (found_hub) {
if (config_find_nic_router(
hub_cf->nasid,
rou_cf->nic,
&brd_ptr,
NULL) == 0)
brd_ptr->brd_flags |=
DUPLICATE_BOARD;
}
found_hub++;
}
break;
default:
break;
}
}
klconfig_port_update(p, partition);
return 0;
}
int
meta_in_partition(pcfg_t *p,
pcfg_router_t *rou_cf,
partid_t partition,
__uint64_t *port_mask)
{
int port, yes = 0;
int index;
partid_t next_rtr_partid;
*port_mask = 0;
for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
index = rou_cf->port[port].index;
if (index == PCFG_INDEX_INVALID) {
continue;
}
/*
* If this meta router is connected to other meta-routers
* follow the links to the next level of 8p routers
* to find the partition IDs.
*/
if (IS_META(&p->array[index].router)) {
int i;
int next_index;
pcfg_router_t *next_meta = &p->array[index].router;
for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
next_index = next_meta->port[i].index;
if (next_index == PCFG_INDEX_INVALID)
continue;
if (!IS_META(&p->array[next_index].router)) {
next_rtr_partid =
p->array[next_index].router.partition;
break;
}
}
db_printf("meta->meta connection found on port %d\n", port);
db_printf("meta port %d connects to module %d, slot %d\n",
port, p->array[next_index].router.module,
p->array[next_index].router.slot);
} else {
next_rtr_partid = p->array[index].router.partition;
}
if (next_rtr_partid == partition) {
*port_mask |= (1 << (port - 1));
yes = 1;
}
}
return yes;
}
/*
* Function : klconfig_port_update
* Parameters : none.
* Purpose : Update all the ports on the hubs and routers in the system.
* Assumptions : network discover complete, and config info built.
* Returns : 0 or -1 on error.
*/
int
klconfig_port_update(pcfg_t *p, partid_t partition)
{
pcfg_hub_t *hub_cf;
pcfg_router_t *rou_cf;
int i, j, type;
#if LDEBUG
printf("klconfig_port_update: part = %d. entered\n", partition);
#endif
for (i=0; i < p->count; i++) {
switch (p->array[i].any.type) {
case PCFG_TYPE_HUB:
hub_cf = &p->array[i].hub;
#if LDEBUG
printf("\tport_update: entry %d, found HUB nasid %d pttn %d\n", i,
hub_cf->nasid, hub_cf->partition);
#endif
if (hub_cf->partition != partition)
break;
if (IS_HUB_MEMLESS(hub_cf))
break ;
if ((hub_cf->port.index != PCFG_INDEX_INVALID) &&
!(hub_cf->port.flags & PCFG_PORT_FENCE_MASK)) {
rou_cf = &p->array[hub_cf->port.index].router;
/*
* update this hub's port to point to the connected
* hardware (router or hub)
*/
setup_hub_port(hub_cf, rou_cf);
}
break;
case PCFG_TYPE_ROUTER:
rou_cf = &p->array[i].router;
#if LDEBUG
printf("\tport_update: entry %d, found RTR NIC 0x%lx %s pttn %d\n",
i, rou_cf->nic, (IS_META(rou_cf) ? "META" : "NORMAL"),
rou_cf->partition);
#endif
if (rou_cf->partition != partition)
break;
for (j = 1; j <= MAX_ROUTER_PORTS; j++) {
if ((rou_cf->port[j].index == PCFG_INDEX_INVALID) ||
(rou_cf->port[j].flags & PCFG_PORT_FENCE_MASK))
continue;
type = p->array[rou_cf->port[j].index].any.type;
if (type == PCFG_TYPE_HUB) {
pcfg_hub_t *conn_cf;
conn_cf = &p->array[rou_cf->port[j].index].hub;
if (IS_HUB_MEMLESS(conn_cf))
continue ;
/*
* update the router's current port to point to the hub.
*/
setup_router_port_to_hub(p, rou_cf, conn_cf, j);
}
else if (type == PCFG_TYPE_ROUTER) {
pcfg_router_t *conn_cf;
conn_cf = &p->array[rou_cf->port[j].index].router;
/*
* update each instance of this router board's current
* port to point to any one instance of the connected
* router.
*/
setup_router_port_to_router(p, rou_cf, conn_cf, j);
}
else
printf("\tError: neither hub nor router on router port\n");
}
break;
default:
break;
}
}
#if LDEBUG
printf("klconfig_port_update: return\n");
#endif
return 0;
}
/*
* Function : setup_hub_port
* Parameters : hub_cf -> prom config for hub.
* rou_cf -> prom config to connected component.
* Purpose : point this hub's port to the node and offset of the
* board it is connected to.
* Assumptions : none.
* Returns : 0 or -1 on failure.
*/
int
setup_hub_port(pcfg_hub_t *hub_cf, pcfg_router_t *rou_cf)
{
lboard_t *node_brd;
lboard_t *connect_brd = NULL ;
pcfg_hub_t *ph;
klhub_t *hub_comp;
int rc;
#if LDEBUG
printf("\t\tsetup_hub_port: hub nasid=%d\n", hub_cf->nasid);
#endif
if (config_find_nic_hub(hub_cf->nasid, hub_cf->nic, &node_brd, &hub_comp)){
printf("setup_hub_port: cannot find node config, node %d\n",
hub_cf->nasid);
return -1;
}
switch (rou_cf->type) {
case PCFG_TYPE_ROUTER:
#if LDEBUG
printf("\t\tsetup_hub_port: connected to Router\n");
#endif
#if 0
connect_brd = find_nic_type_lboard(hub_cf->nasid, KLTYPE_ROUTER2,
rou_cf->nic);
#endif
if (config_find_nic_router(hub_cf->nasid, rou_cf->nic,
&connect_brd, NULL)) {
if(config_find_nic_router_all(PCFG(get_nasid()), rou_cf->nic, &connect_brd,
NULL,rou_cf->partition, 0)) {
printf("setup_hub_port: no connecting router board! Node %d index %d\n",
hub_cf->nasid, hub_cf->port.index);
return -1;
}
}
break;
case PCFG_TYPE_HUB:
#if LDEBUG
printf("\t\tsetup_hub_port: connected to hub\n");
#endif
ph = (pcfg_hub_t *)rou_cf;
if (IS_HUB_MEMLESS(ph))
return 0;
connect_brd = find_nic_type_lboard(ph->nasid, KLTYPE_IP27, ph->nic);
break;
default:
connect_brd = NULL;
break;
}
if (connect_brd) {
hub_comp->hub_port.port_nasid = connect_brd->brd_nasid;
hub_comp->hub_port.port_offset = K0_TO_NODE_OFFSET(connect_brd);
if (hub_cf->port.flags & PCFG_PORT_FENCE_MASK)
hub_comp->hub_port.port_flag |= SN0_PORT_FENCE_MASK;
rc = 0;
}
else {
printf("setup_hub_port: no connect board! Node %d index %d\n",
hub_cf->nasid, hub_cf->port.index);
rc = -1;
}
#if LDEBUG
printf("\t\tsetup_hub_port: hub 0x%lx, router 0x%lx return %d\n",
node_brd, connect_brd, rc);
#endif
return rc;
}
/*
* Function : setup_router_port_to_hub
* Parameters : rou_cf -> prom config for router
* hub_cf -> prom config to connected hub.
* port -> port number where hub is connected on router.
* Purpose : point this routers port to the node and offset of the
* hub board it is connected to.
* Assumptions : none.
* Returns : 0 or -1 on failure.
*/
int
setup_router_port_to_hub(pcfg_t *p,
pcfg_router_t *rou_cf,
pcfg_hub_t *hub_cf,
int port)
{
lboard_t *node_brd;
lboard_t *router_brd;
klrou_t *rou_comp;
int i;
pcfg_hub_t *chub_cf;
#if LDEBUG
printf("\t\tsetup_router_port_to_hub: port=%d\n", port);
#endif
if (config_find_nic_hub(hub_cf->nasid, hub_cf->nic, &node_brd, NULL)) {
printf("setup_hub_port: cannot find node config, node %d\n",
hub_cf->nasid);
return -1;
}
/*
* Now walk each port of this router, and for each hub found, find the
* instance of this router on that node. Setup the connection between
* the router board and the connecting component.
*/
for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
if ((rou_cf->port[i].index == PCFG_INDEX_INVALID) ||
(rou_cf->port[i].flags & PCFG_PORT_FENCE_MASK))
continue;
if (p->array[rou_cf->port[i].index].any.type == PCFG_TYPE_HUB) {
chub_cf = &p->array[rou_cf->port[i].index].hub;
if (IS_HUB_MEMLESS(chub_cf))
continue ;
if (config_find_nic_router(chub_cf->nasid, rou_cf->nic,
&router_brd, &rou_comp)) {
if(config_find_nic_router_all(p, rou_cf->nic, &router_brd,
&rou_comp,rou_cf->partition, 0)) {
printf("setup_router_port_to_hub: router missing %d\n",
chub_cf->nasid);
return -1;
}
}
#if LDEBUG
printf("\t\tsetup_router_port_to_hub: hub 0x%lx rtr 0x%lx\n",
node_brd, router_brd);
#endif
rou_comp->rou_port[port].port_nasid = hub_cf->nasid;
rou_comp->rou_port[port].port_offset = K0_TO_NODE_OFFSET(node_brd);
}
}
#if LDEBUG
printf("\t\tsetup_router_port_to_hub: return 0\n");
#endif
return 0;
}
/*
* Function : setup_router_port_to_router
* Parameters : rou_cf -> prom config for router.
* conn_cf -> prom config to connected component (router)
* port -> port on this router where component is connected.
* Purpose : point this routers's port to the node and offset of the
* router it is connected to.
* Since this router potentially has multiple instances of
* the board, one on each node it is connected to, update
* each instance of the router to point to any one instance
* of the connected board config.
* Assumptions : Runs on master node.
* Returns : 0 or -1 on failure.
*/
int
setup_router_port_to_router(pcfg_t *p,
pcfg_router_t *rou_cf,
pcfg_router_t *conn_cf,
int port)
{
lboard_t *router_brd;
lboard_t *connect_brd = NULL;
pcfg_hub_t *hub_cf;
klrou_t *rou_comp;
int i, hub_found, rc = 1;
int remote_router = 0;
#if LDEBUG
printf("\t\tsetup_router_port_to_router: port=%d\n", port);
printf("\t\t\tFrom rou NIC 0x%lx %s pttn %d %s\n", rou_cf->nic,
(IS_META(rou_cf) ? "META" : "NORMAL"), rou_cf->partition,
(IS_RESET_SPACE_RTR(rou_cf) ? "RESET" : "NON_RESET"));
printf("\t\t\tTo rou NIC 0x%lx %s pttn %d %s\n", conn_cf->nic,
(IS_META(conn_cf) ? "META" : "NORMAL"), conn_cf->partition,
(IS_RESET_SPACE_RTR(conn_cf) ? "RESET" : "NON_RESET"));
#endif
/*
* first walk all the links of the component we are connecting to.
* Find its first hub and locate an instance of the connecting routers
* board on that node.
* Meta rtrs have a lboard struct on each of the hubs that are
* connected to the normal rtr connected to the meta rtr
* If no hub is connected to that router, that router must be hubless
* router.
* Find the connecting router's board on the master node (which is
* assumed to be this node.)
*/
for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
int indx = conn_cf->port[i].index;
if ((indx == PCFG_INDEX_INVALID) ||
(conn_cf->port[i].flags & PCFG_PORT_FENCE_MASK))
continue;
if (p->array[indx].any.type == PCFG_TYPE_HUB) {
hub_cf = &p->array[indx].hub;
if (IS_HUB_MEMLESS(hub_cf))
continue ;
rc = config_find_nic_router(hub_cf->nasid, conn_cf->nic,
&connect_brd, NULL);
}
if (IS_META(conn_cf) && (p->array[indx].any.type == PCFG_TYPE_ROUTER)) {
int j;
for (j = 1; j <= MAX_ROUTER_PORTS; j++) {
int rtr_indx;
pcfg_hub_t *p_hub;
rtr_indx = p->array[indx].router.port[j].index;
if (rtr_indx == PCFG_INDEX_INVALID)
continue;
if (p->array[rtr_indx].any.type == PCFG_TYPE_HUB) {
p_hub = &p->array[rtr_indx].hub;
if (IS_HUB_MEMLESS(p_hub))
continue ;
rc = config_find_nic_router(p_hub->nasid, conn_cf->nic,
&connect_brd, NULL);
if (!rc)
break;
}
}
}
if (!rc)
break;
}
if (rc && config_find_nic_router_all(p, conn_cf->nic,
&connect_brd, NULL, conn_cf->partition, 0)) {
return -1;
}
#if LDEBUG
printf("\t\tsetup_router_port_to_router: connect_brd 0x%lx\n", connect_brd);
#endif
hub_found = 0;
/*
* Now walk each port of this router, and for each hub found, find the
* instance of this router on that node. Setup the connection between
* the router board and the connecting component.
* If rou_cf is a meta rtr, update all lboards on all the hubs connected
* to a normal rtr connected to a meta rtr
*/
for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
int indx = rou_cf->port[i].index;
#if 0
if ((indx == PCFG_INDEX_INVALID) ||
(rou_cf->port[i].flags & PCFG_PORT_FENCE_MASK))
continue;
#endif
/* For meta router systems, we were ignoring the router port
* that is connected to the meta router. Need to
* fill in rou_port_nasid for the ports that are connected
* to meta routers. Works and needs further investigation.
*/
if ((indx == PCFG_INDEX_INVALID) ||
((rou_cf->port[i].flags & PCFG_PORT_FENCE_MASK)
&& (!IS_META(pcfgGetRouter(p,indx)))))
continue;
/* If a meta router has been fenced off, it does not
* does not get into the normal router's klcfg. This
* is incomplete information. Under this special case
* get the port nasid, and offset.
*/
if (IS_META(pcfgGetRouter(p,indx)) &&
(rou_cf->port[i].flags & PCFG_PORT_FENCE_MASK)) {
lboard_t *rlb = NULL, *myrlb = NULL ;
klrou_t *myrkr = NULL ;
pcfg_router_t *rpcfg ;
int rc ;
rpcfg = pcfgGetRouter(p,indx) ;
/* get my router's klcfg to fill up */
rc = config_find_nic_router_all(p, rou_cf->nic, &myrlb,
&myrkr, rou_cf->partition, 0) ;
if (!rc && myrlb) {
/* Find the meta router's valid klcfg. */
config_find_nic_router_all(p, rpcfg->nic,
&rlb, NULL, rou_cf->partition, 0) ;
if (!rc && rlb && myrkr) {
#if LDEBUG
printf("In %llx,port %d filled nasid %d, offset %llx\n",
myrlb->brd_nic, i, rlb->brd_nasid,
K0_TO_NODE_OFFSET(rlb)) ;
#endif
myrkr->rou_port[i].port_nasid = rlb->brd_nasid ;
myrkr->rou_port[i].port_offset= K0_TO_NODE_OFFSET(rlb);
/* Fill the DUP also */
rc = config_find_nic_router_all(p, rou_cf->nic, &myrlb,
&myrkr, rou_cf->partition, 1) ;
if (!rc && myrlb && myrkr) {
myrkr->rou_port[i].port_nasid = rlb->brd_nasid ;
myrkr->rou_port[i].port_offset= K0_TO_NODE_OFFSET(rlb);
#if LDEBUG
printf("filled in dup for %llx\n", myrlb->brd_nic) ;
#endif
}
}
}
continue ;
}
if (p->array[indx].any.type == PCFG_TYPE_HUB) {
hub_cf = &p->array[indx].hub;
if (IS_HUB_MEMLESS(hub_cf))
continue ;
hub_found++;
if (config_find_nic_router(hub_cf->nasid, rou_cf->nic,
&router_brd, &rou_comp)) {
#if 0
printf("setup_router_port_to_router: router missing %d port %d\n",
hub_cf->nasid, port);
#endif
remote_router = 1;
}
else {
#if LDEBUG
printf("\t\tsetup_router_port_to_router: Updating rou_brd "
"0x%lx\n", router_brd);
#endif
rou_comp->rou_port[port].port_nasid = connect_brd->brd_nasid;
rou_comp->rou_port[port].port_offset =
K0_TO_NODE_OFFSET(connect_brd);
if (rou_cf->port[port].flags & PCFG_PORT_FENCE_MASK)
rou_comp->rou_port[port].port_flag |= SN0_PORT_FENCE_MASK;
}
}
if (IS_META(rou_cf) && (p->array[indx].any.type == PCFG_TYPE_ROUTER)) {
int j;
for (j = 1; j <= MAX_ROUTER_PORTS; j++) {
int rtr_indx;
pcfg_hub_t *p_hub;
rtr_indx = p->array[indx].router.port[j].index;
if (rtr_indx == PCFG_INDEX_INVALID)
continue;
if (p->array[rtr_indx].any.type == PCFG_TYPE_HUB) {
p_hub = &p->array[rtr_indx].hub;
if (IS_HUB_MEMLESS(p_hub))
continue ;
hub_found++;
if (config_find_nic_router(p_hub->nasid, rou_cf->nic,
&router_brd, &rou_comp)) {
#if 0
printf("setup_router_port_to_router: router missing"
" %d\n", hub_cf->nasid);
#endif
}
else {
#if LDEBUG
printf("\t\tsetup_router_port_to_router: Updating "
"rou_brd 0x%lx\n", router_brd);
#endif
rou_comp->rou_port[port].port_nasid =
connect_brd->brd_nasid;
rou_comp->rou_port[port].port_offset =
K0_TO_NODE_OFFSET(connect_brd);
if (rou_cf->port[port].flags & PCFG_PORT_FENCE_MASK)
rou_comp->rou_port[port].port_flag |=
SN0_PORT_FENCE_MASK;
}
}
}
}
}
if (!hub_found || remote_router) {
if (config_find_nic_router_all(p, rou_cf->nic,
&router_brd, &rou_comp, rou_cf->partition, 0)) {
return -1;
}
rou_comp->rou_port[port].port_nasid = connect_brd->brd_nasid;
rou_comp->rou_port[port].port_offset = K0_TO_NODE_OFFSET(connect_brd);
if (rou_cf->port[port].flags & PCFG_PORT_FENCE_MASK)
rou_comp->rou_port[port].port_flag |= SN0_PORT_FENCE_MASK;
}
#if LDEBUG
printf("\t\tsetup_router_port_to_router: return\n");
#endif
return 0;
}
int
add_router_config(pcfg_t *p, partid_t partition)
{
pcfg_hub_t *hub_cf;
pcfg_router_t *rou_cf = NULL;
int i;
nasid_t nasid ;
#if LDEBUG
printf("add_router_config: count=%d\n", p->count);
#endif
/*
* Add a router config for all router brds
* If HUB: add rtr brds for all rtrs directly connected
* If RTR: If meta, call klcfg_add_meta_router
* else if (hubless && in reset space) add to gmaster
* XXX: This must really be pmaster!
* Since this routine is called by pmaster in main.c
* it is OK to do get_nasid!!
* Skip remote partition HUBs.
*/
for (i = 0; i < p->count; i++) {
if ((p->array[i].any.type == PCFG_TYPE_HUB) &&
(p->array[i].hub.partition == partition)) {
hub_cf = &p->array[i].hub;
if (IS_HUB_MEMLESS(hub_cf))
continue ;
if (hub_cf->port.index != PCFG_INDEX_INVALID &&
p->array[hub_cf->port.index].any.type == PCFG_TYPE_ROUTER) {
lboard_t *rou_b;
rou_cf = &p->array[hub_cf->port.index].router;
#if LDEBUG
printf("add_router_config: adding rou lboard HUB nasid %d rou "
"NIC 0x%lx\n", hub_cf->nasid, rou_cf->nic);
#endif
nasid = hub_cf->nasid ;
if (!(rou_b = init_klcfg_routerb_hl(p, nasid, rou_cf,
KLTYPE_ROUTER, rou_cf->partition))) {
printf("*** WARNING: Can't add module %d, slot r%d rtr to nasid %d\n", rou_cf->module, rou_cf->slot, nasid);
return -1;
}
else
rou_b->brd_partition = rou_cf->partition;
}
}
else if (p->array[i].any.type == PCFG_TYPE_ROUTER) {
if (IS_META(&p->array[i].router)) {
db_printf("Adding meta router NIC 0x%lx\n",
p->array[i].router.nic);
/*
* On 256p, we may not have a meta router connection
* to this partition. So we don't necessarily want
* to see a warning message in this case.
*
* Only print a warning if we try to add a brd but can't.
* This is done within klcfg_add_meta_router() so we
* don't have to do it here.
*/
klcfg_add_meta_router(p, i, partition);
}
else if ((p->array[i].router.partition == partition) &&
hubless_rtr(p, &p->array[i].router, 0)) {
lboard_t *rou_brd;
db_printf("Adding HUBless rtr NIC 0x%lx\n",
p->array[i].router.nic);
if (!(rou_brd = init_klcfg_routerb_hl(p, get_nasid(),
&p->array[i].router, KLTYPE_ROUTER, partition))) {
db_printf("*** WARNING: Can't add HUBless rtr NIC 0x%lx to"
"nasid %d\n", p->array[i].router.nic, get_nasid());
} else {
klrou_t *rou_info;
rou_brd->brd_partition = p->array[i].router.partition;
rou_info = (klrou_t *) find_first_component(rou_brd,
KLSTRUCT_ROU);
rou_info->rou_info.flags |= KLINFO_HEADLESS;
}
}
}
}
#if LDEBUG
printf("add_router_config: return\n");
#endif
return 0;
}
/*
* Function: klconfig_update_failure -> Update klconfig of node brds'
* unexpected failure after discovery
*/
int
klconfig_failure_update(pcfg_t *p, partid_t partition)
{
int i;
jmp_buf new_buf;
void *old_buf;
if (setfault(new_buf, &old_buf)) {
printf("*** Exception occurred while accessing remote node!\n");
restorefault(old_buf);
return -1;
}
for (i = 0; i < p->count; i++)
if ((p->array[i].any.type == PCFG_TYPE_HUB) &&
(p->array[i].hub.partition == partition) &&
(p->array[i].hub.flags & PCFG_HUB_EXCP)) {
lboard_t *brd;
int flagged = 0;
klcpu_t *cpu1, *cpu2;
if (!(brd = find_lboard((lboard_t *)
KL_CONFIG_INFO(p->array[i].hub.nasid), KLTYPE_IP27)))
continue;
cpu1 = (klcpu_t *) find_first_component(brd, KLSTRUCT_CPU);
cpu2 = (klcpu_t *) find_component(brd, (klinfo_t *) cpu1,
KLSTRUCT_CPU);
/*
* Update klconfig if brd hasn't been flagged
*/
if (!(brd->brd_flags & ENABLE_BOARD) ||
(brd->brd_flags & FAILED_BOARD))
flagged = 1;
else if (cpu1 && (!(cpu1->cpu_info.flags & KLINFO_ENABLE) ||
(cpu1->cpu_info.flags & KLINFO_FAILED)))
flagged = 1;
else if (cpu2 && (!(cpu2->cpu_info.flags & KLINFO_ENABLE) ||
(cpu2->cpu_info.flags & KLINFO_FAILED)))
flagged = 1;
if (!flagged) {
net_vec_t vec;
__uint64_t ni_status;
nasid_t nasid;
char led, buf[64];
printf("*** /hw/module/%d/slot/n%d: CPU(s) took unexpected "
"exception.\n", p->array[i].hub.module,
p->array[i].hub.slot);
printf("*** One or both CPUs might be bad. Disabling both.\n");
REMOTE_HUB_S(p->array[i].hub.nasid, PI_CPU_ENABLE_A, 0);
REMOTE_HUB_S(p->array[i].hub.nasid, PI_CPU_ENABLE_B, 0);
if (cpu1) {
cpu1->cpu_info.flags &= ~KLINFO_ENABLE;
cpu1->cpu_info.diagval = KLDIAG_UNEXPEC_EXCP;
}
if (cpu2) {
cpu2->cpu_info.flags &= ~KLINFO_ENABLE;
cpu2->cpu_info.diagval = KLDIAG_UNEXPEC_EXCP;
}
/* XXX: This LED value is useless ? */
led = (char) REMOTE_HUB_L(p->array[i].hub.nasid,
PI_RT_COMPARE_A);
sprintf(buf, "%d: %x; %s\n", KLDIAG_UNEXPEC_EXCP, led,
get_diag_string(KLDIAG_UNEXPEC_EXCP));
ed_cpu_mem(p->array[i].hub.nasid, DISABLE_CPU_A,
buf, buf, 0, 0);
ed_cpu_mem(p->array[i].hub.nasid, DISABLE_CPU_B,
buf, buf, 0, 0);
klconfig_nasid_update(p->array[i].hub.nasid, 1);
}
}
restorefault(old_buf);
return 0;
}
void
klcfg_hubii_stat(nasid_t nasid)
{
int link_stat;
lboard_t *l;
klhub_t *h;
link_stat = GET_FIELD(REMOTE_HUB_L(nasid, IIO_LLP_CSR),
IIO_LLP_CSR_LLP_STAT);
l = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_IP27);
h = (klhub_t *) find_first_component(l, KLSTRUCT_HUB);
if ((link_stat == 0) || (link_stat == 1))
h->hub_info.diagval = KLDIAG_HUB_LLP_DOWN;
else
h->hub_info.diagval = KLDIAG_PASSED;
}
/*
* Support for maintaining a flag of all nasids searched.
* Note: This is really not needed as nasids are unique
* and when we go thro pcfg, we only search each nasid once.
*/
#define element_of_array __uint64_t
#define bits_per_unit 8
#define unit_per_element sizeof(element_of_array) /* units */
#define num_bits_per_element (unit_per_element * bits_per_unit)
static struct {
element_of_array bit_flag[(MAX_NASIDS/num_bits_per_element)+1] ;
} nasid_flag ;
#define num_elements (sizeof(nasid_flag)/sizeof(element_of_array))
#define MASK(_n) (((__uint64_t)1) << (num_bits_per_element - \
(_n%num_bits_per_element) - 1))
#define INDEX(_n) (_n/num_bits_per_element)
#define NASID_SET(_n) if (_n < MAX_NASIDS) \
nasid_flag.bit_flag[INDEX(_n)] |= \
MASK(_n) ;
#define NASID_ISSET(_n) (((INDEX(_n) + 1) <= num_elements) ? \
(nasid_flag.bit_flag[INDEX(_n)] & MASK(_n)) : 0)
/*
* init_klcfg_routerb_hl
* wrapper for init_klcfg_routerb. Meta routers, or hubless
* routers may not find a place for themselves on the global
* master. Allocate them on the next nearest node.
*/
static lboard_t *
init_klcfg_routerb_hl( pcfg_t *p ,
nasid_t preferred_nasid ,
pcfg_router_t *pcfg_routerp ,
int router_type ,
partid_t partition)
{
lboard_t *lb = NULL ;
int i ;
if (lb = init_klcfg_routerb(p, preferred_nasid,
pcfg_routerp, router_type))
return lb ;
bzero((char *)&nasid_flag, sizeof(nasid_flag)) ;
NASID_SET(preferred_nasid) ; /* finished searching this */
/* get the next nasid */
ForAllPcfg(p,i) {
if (pcfgIsHub(p,i)) {
if ((p->array[i].hub.partition == partition) &&
(!NASID_ISSET(p->array[i].hub.nasid))) {
lb = init_klcfg_routerb(p,
p->array[i].hub.nasid,
pcfg_routerp,
router_type) ;
if (lb) break ;
NASID_SET(p->array[i].hub.nasid) ;
}
}
}
#if LDEBUG
if (lb)
printf("looking for space on nasid %d, found it on nasid %d\n",
preferred_nasid, p->array[i].hub.nasid) ;
#endif
return lb ;
}
/*
* config_find_nic_router_all
* wrapper for config_find_nic_router.
* As the router klcfg may be present on any node,
* search all nasids.
*/
int
config_find_nic_router_all( pcfg_t *p ,
nic_t nic ,
lboard_t **lbp ,
klrou_t **krp ,
partid_t partition,
int dupflg)
{
int i ;
pcfg_hub_t *ph ;
ForAllPcfg(p,i) {
if (pcfgIsHub(p,i)) {
ph = pcfgGetHub(p,i) ;
if ( ((ph->partition == partition) ||
(partition == INVALID_PARTID)) &&
(!IS_HUB_MEMLESS(ph)))
if (config_find_nic_router(ph->nasid,
nic, lbp, krp)==0)
if (*lbp)
if (dupflg) {
if (KL_CONFIG_DUPLICATE_BOARD(*lbp))
return 0 ;
} else {
if (!(KL_CONFIG_DUPLICATE_BOARD(*lbp)))
return 0 ;
}
}
}
return -1 ;
}
lboard_t *
init_klcfg_ip27_disabled(__psunsigned_t hub_base, int flag, nasid_t good_nasid)
{
lboard_t *brd_ptr;
nasid_t nasid;
char buf[8];
char *c = NULL;
klhub_t *hubp;
nasid = NASID_GET(hub_base);
if ((brd_ptr = kl_config_alloc_board(good_nasid)) == NULL) {
printf("init_klcfg_ip27: Cannot allocate board struct\n");
return NULL;
}
/* Since there is only one module in the 12P 4IO config
* hardwire the brd module number to 1
*/
if (CONFIG_12P4I)
brd_ptr->brd_module = 1;
brd_ptr->brd_type = KLTYPE_IP27;
kl_disable_board(brd_ptr);
brd_ptr->brd_brevision = (unsigned char)
((LD(hub_base + NI_STATUS_REV_ID) & NSRI_REV_MASK) >>
NSRI_REV_SHFT);
if (kl_sable) {
#ifdef SABLE
brd_ptr->brd_slot = (uchar)get_my_slotid() ;
#endif
}
else {
brd_ptr->brd_slot = (unsigned char)
hub_slotbits_to_slot(LD(hub_base + MD_SLOTID_USTAT) &
MSU_SLOTID_MASK);
}
brd_ptr->brd_slot = get_node_slotid(nasid);
ip27log_getenv(nasid, IP27LOG_MODULE_KEY, buf, "0", 0);
brd_ptr->brd_module = (moduleid_t) atoi(buf);
/*
* Who am I?
*/
/*
* setup a cpu component for each cpu found. This should match
* what the ip27 prom has already found...
*/
/*if (LD(hub_base + PI_CPU_PRESENT_A))*/
init_klcfg_cpu(hub_base, brd_ptr, IP27_CPU0_INDEX, 1);
/*if (LD(hub_base + PI_CPU_PRESENT_B))*/
init_klcfg_cpu(hub_base, brd_ptr, IP27_CPU1_INDEX, 1);
init_klcfg_hub(hub_base, brd_ptr, IP27_HUB_INDEX) ;
init_klcfg_membnk(hub_base, brd_ptr, IP27_MEM_INDEX) ;
if (hubp = (klhub_t *)find_component(brd_ptr, NULL,
KLSTRUCT_HUB)) {
if (hubp->hub_mfg_nic)
c = (char *)NODE_OFFSET_TO_K1(
good_nasid,
hubp->hub_mfg_nic);
}
if(ip31_pimm_psc(nasid,NULL,c) == 0)
strcpy(brd_ptr->brd_name,"IP31");
else
strcpy(brd_ptr->brd_name,"IP27");
return (kl_config_add_board(good_nasid, brd_ptr));
}