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

2226 lines
58 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 : promgraph.c
* Description: Build a Graph of the hardware from the KLCONFIG
* data.
* Assumption:
* Hardware discovery is done and KLCONFIG has been setup.
* Hardware includes the ASICS like HUB, BRIDGE etc
* and Device controllers like Qlogic.
* The graph is built in 2 phases:
* discover controllers
* discover devices and update KLCONFIG and the promgraph.
* Algorithm:
* graph_create() ;
* while (there are more lboards)
* for all components on the board
* graph_vertex_create()
* graph_info_add_LBL() Ptr to component struct
* Link internal components using
* graph_edge_add()
* Link all internal components to their respective
* Locator nodes, for eg: all cpus to /cpu etc.
*
* Inter link boards using IP27's cfg_t graph and
* other data from iodiscovery.
*/
#include <sys/SN/addrs.h>
#include <sys/SN/SN0/ip27config.h>
#include <sys/SN/klconfig.h> /* config stuff */
#include <arcs/eiob.h>
#include <sys/graph.h>
#include <sys/hwgraph.h>
#include <sys/SN/SN0/klhwinit.h>
#include <sys/SN/nvram.h>
#include <sys/SN/gda.h>
#include <sys/PCI/bridge.h>
#include <sys/iograph.h>
#include <libsc.h>
#include <libsk.h>
#include <libkl.h>
#include <promgraph.h>
#include <pgdrv.h>
#include "io6inst.c"
#ifndef SN_PDI
/* #define PG_DEBUG */
int pg_debug;
extern graph_hdl_t hwgraph ; /* To be initted so that we can */
extern int hwgraph_initted ; /* use the hwgraph routines */
extern moduleid_t master_baseio_modid ;
extern slotid_t master_baseio_slotid ;
#ifdef SABLE
extern int num_qlogic ;
extern int num_sbldsk ;
extern int num_ioc3 ;
extern int ioc3_installed ;
#endif
extern struct mod_tab module_table[] ;
extern int dksc_map[] ;
extern int dksc_inv_map[] ;
#define WEIRD_MODID -1
#define MAXPNT 5
#define PROM_EDGE_LBL_PCI_SLOT "pci"
#define PROM_EDGE_LBL_CPU "cpu"
/* This name starts with a '/' because it is going to
be appeneded to another string before getting passed to
create_graph_path.
Normally, the string should not begin with a '/'.
If it does, it will confuse the create_graph_path routine.
*/
#define PROM_EDGE_LBL_LUN_0_DISK "/lun/0/disk"
#define PROM_EDGE_LBL_LUN_0_CDROM "/lun/0/cdrom"
#define PROM_EDGE_LBL_LUN_0_TAPE "/lun/0/tape"
/*
* This flag gets set to 1 if this lib is linked into symmon.
* This is not the same as _prom. Symmon also sets _prom
* to 1, so that flag can't be used for some decisions.
* Declared here so it gets linked into all stand programs.
*/
extern int _symmon;
/* XXX - This should be correctly initted by IP27prom.
* This is one variable per SN0 partition assuming
* there is one IO PROM running per partition.
*/
extern int num_modules ;
static int num_scsi_drive ;
static int add_node_edge(lboard_t *) ;
int init_router_graph(lboard_t *, int , pcfg_router_t *) ;
graph_hdl_t prom_graph_hdl ; /* THE PROM GRAPH */
graph_attr_t prom_graph_attr ;
char graph_name[] = "PROM_GRAPH" ;
vertex_hdl_t root_vhdl ; /* The / vertex */
vertex_hdl_t hw_vertex_hdl ; /* The /hw vertex */
vertex_hdl_t mod_vertex_hdl ; /* The /hw/module vertex */
extern int sk_sable;
struct locator_info {
char *name ;
vertex_hdl_t vhdl ;
} ;
int
promgraph_connect_brd_compts(lboard_t *,
unsigned char,
vertex_hdl_t *, int);
/*
* This represents the top level locator string tree structure under the
* '/hw' vertex.
*/
struct locator_info hw_locator_edges[] = {
#define DEV_LOCATOR_INDEX 0
"dev", GRAPH_VERTEX_NONE, /* All devices */
#define CPU_LOCATOR_INDEX 1
EDGE_LBL_CPU, GRAPH_VERTEX_NONE, /* All CPUs */
#define HUB_LOCATOR_INDEX 2
"hub", GRAPH_VERTEX_NONE, /* All HUBs */
#define XBOW_LOCATOR_INDEX 3
"xbow", GRAPH_VERTEX_NONE, /* All Xbows */
#define ROUTER_LOCATOR_INDEX 4
"router", GRAPH_VERTEX_NONE, /* All Routers */
#define BRIDGE_LOCATOR_INDEX 5
"xwidget", GRAPH_VERTEX_NONE, /* All Bridges */
#define TPU_LOCATOR_INDEX 6
"tpu", GRAPH_VERTEX_NONE, /* All TPUs */
#define GSN_LOCATOR_INDEX 7
"gsn", GRAPH_VERTEX_NONE, /* All GSN boards */
NULL, GRAPH_VERTEX_NONE
} ;
/*
* The locator edges hanging off /dev vertex.
*/
char *dev_locator_edges[] = {
"disk",
"tape",
"cdrom",
"tty",
EDGE_LBL_ENET,
"audio",
"fddi",
"fc",
"input",
"graphics",
"tpu",
"gsn",
NULL
} ;
/*
* These correspond to the #define KLSTRUCT_* stuff in klconfig.h.
* The array index should match the corresponding string value.
*/
char *compt_names[] = {
"",
EDGE_LBL_CPU,
"hub",
"mem",
"xbow",
"bridge",
"ioc3",
"pci",
"vme",
"router",
"graphics",
"ql",
"fddi",
"mio",
"disk",
"tape",
"cdrom",
"hubuart",
EDGE_LBL_EF,
"ioc3uart",
"UNKNOWN",
"ioc3pckm",
"sgirad",
"hubtty",
"ioc3",
"fc",
"snum",
"ioc3ms",
"tpu",
"gsn", /* Primary GSN board */
"gsn", /* Auxiliary GSN board */
NULL
} ;
static struct {
struct inst_later *head;
struct inst_later *tail;
} instnext, instlist;
/*
* Initializes the complete graph from KLCFGINFO, cfg_t and other data.
*/
int
init_prom_graph(void)
{
graph_error_t graph_err ;
int i ;
gda_t *gdap;
nasid_t master_nasid = get_nasid() ;
prom_graph_hdl = 0 ;
/* create a graph */
/*
* Do all the stuff that is common for all NODES and
* PARTITIONS like, component locator struct, Module/partition
* locator structure etc.
* Then call init_prom_graph_node for each node that
* was found in IP27PROM.
pg_debug = 1 ;
*/
#if 0
if (!hwgraph_initted)
{
#endif
prom_graph_attr.ga_name = graph_name ;
prom_graph_attr.ga_separator = '/' ;
prom_graph_attr.ga_num_index = 64 ;
prom_graph_attr.ga_reserved_places = 32 ;
graph_err = graph_create(&prom_graph_attr,
&prom_graph_hdl,
0) ;
if (graph_err != GRAPH_SUCCESS) {
printf("PROM_GRAPH create error %d\n", graph_err) ;
return 0 ;
}
/* Create the top level locator string graph */
if (!init_component_locator())
return 0 ;
/* Init external variables so that hwgraph routines work */
hwgraph = prom_graph_hdl ;
hwgraph_initted = 1 ;
#if 0
}
#endif
if (!(init_module_locator()))
return 0 ;
gdap = (gda_t *)GDA_ADDR(master_nasid);
for (i = 0; i < MAX_COMPACT_NODES; i++) {
if (gdap->g_nasidtable[i] == INVALID_NASID)
break;
PG_DPRINT("initing prom node graph for nasid %d\n",
gdap->g_nasidtable[i]) ;
if (_symmon) {
lboard_t *lb ;
lb = (lboard_t *)KL_CONFIG_INFO(gdap->g_nasidtable[i]) ;
lb = find_lboard(lb, KLTYPE_BASEIO);
if ((lb) && (lb->brd_flags & GLOBAL_MASTER_IO6)) {
init_prom_node_graph(gdap->g_nasidtable[i]);
break ;
} else
continue ;
}
init_prom_node_graph(gdap->g_nasidtable[i]);
}
make_serial(1) ;
if (!_symmon) {
printf("Installing PROM Device drivers ............\t\t\n") ;
}
#ifdef SN0PROM
/*
* now perform any graphics console installation
*/
kl_graphics_install();
#endif
instnext.head = instnext.tail = NULL ;
prom_install_devices() ;
/* If any of the guys have registered for delayed install,
run them now.
*/
do {
struct inst_later *execute ;
instlist = instnext;
instnext.head = instnext.tail = (struct inst_later *)NULL;
while (execute=instlist.head) {
execute->install(execute->hw, execute->loc) ;
instlist.head = execute->next;
free(execute);
}
} while(instnext.head) ;
/*
* Setup a special node for the master bridge so that path
* aliases work.
*/
if (!pg_setup_bridge_alias())
printf("Could not setup node master_bridge.\
Path aliases like bootp() may not work\n") ;
return 1 ;
}
/*
* Create the Graph for a node. This includes the node board
* and all its associated IO boards.
*/
init_prom_node_graph(int node)
{
lboard_t *brd_ptr;
/* Create the graph for each of the boards found in this node. */
brd_ptr = (lboard_t *)KL_CONFIG_INFO(node);
while (brd_ptr) {
if (brd_ptr->struct_type == REMOTE_BOARD) {
printf("Remote board in init_prom_node_graph: fixme\n");
}
else {
/* XXX Avoid DISABLED boards too */
if ((!(brd_ptr->brd_flags & DUPLICATE_BOARD))
&& (brd_ptr->brd_flags & ENABLE_BOARD)) {
PG_DPRINT("init graph for brd %x P %x %x\n",
brd_ptr, brd_ptr->brd_parent, brd_ptr->brd_type) ;
init_board_graph(brd_ptr, node) ;
}
}
brd_ptr = KLCF_NEXT(brd_ptr);
}
/*
All boards with their individual graphs are linked to make the
complete graph. Info from ip27prom is used to link hubs routers
and info from iodiscover is used to link up others.
*/
/* Link all boards found in a node. */
link_node_boards(node) ;
return 1 ;
}
/*
* Build a internal 'locator' network which can be used to
* get to component's klinfo_t struct quickly. For example
* /dev/cpu/cpu/<id>, /xwidget/<number>/pci/slot/...
*/
int
init_component_locator(void)
{
/*
We need a base locator frame work to hang new compt vertices
off. This is the one that does the job.
*/
int i ;
graph_error_t graph_err ;
vertex_hdl_t dev_vhdl, devloc_vhdl ;
graph_err = graph_vertex_create(prom_graph_hdl, &root_vhdl) ;
if (graph_err != GRAPH_SUCCESS) {
printf("Root create err %d\n", graph_err) ;
return 0 ;
}
graph_err = graph_info_add_LBL(prom_graph_hdl, root_vhdl,
INFO_LBL_VERTEX_NAME, NULL,
(arbitrary_info_t)VERTEX_NAME_ROOT) ;
if (graph_err != GRAPH_SUCCESS) {
printf("Root addLBL error %d\n", graph_err) ;
return 0 ;
}
hw_vertex_hdl = create_graph_path(root_vhdl, EDGE_LBL_HARDWARE, 1) ;
graph_err = graph_info_add_LBL(prom_graph_hdl,
hw_vertex_hdl,
INFO_LBL_VERTEX_NAME, NULL,
(arbitrary_info_t)EDGE_LBL_SYSNAME) ;
if (graph_err != GRAPH_SUCCESS) {
printf("hw addLBL error %d\n", graph_err) ;
return 0 ;
}
/* Build the locator tree for / */
for (i = 0; hw_locator_edges[i].name != NULL; i++) {
hw_locator_edges[i].vhdl = create_graph_path(
hw_vertex_hdl,
hw_locator_edges[i].name, 1) ;
graph_err = graph_info_add_LBL(prom_graph_hdl,
hw_locator_edges[i].vhdl,
INFO_LBL_VERTEX_NAME,
NULL,
(arbitrary_info_t)
hw_locator_edges[i].name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("locedge addLBL error %d\n", graph_err) ;
return 0 ;
}
}
/* Build the locator tree for the /dev node */
devloc_vhdl = hw_locator_edges[DEV_LOCATOR_INDEX].vhdl ;
for (i=0; dev_locator_edges[i] != NULL; i++) {
dev_vhdl = create_graph_path(devloc_vhdl,
dev_locator_edges[i], 1) ;
graph_err = graph_info_add_LBL(prom_graph_hdl,
dev_vhdl,
INFO_LBL_VERTEX_NAME,
NULL,
(arbitrary_info_t)
dev_locator_edges[i]) ;
if (graph_err != GRAPH_SUCCESS) {
printf("devloc addLBL error %d\n", graph_err) ;
return 0 ;
}
}
/*
add an edge "hw" from the real "/hw" node to itself. This makes
pathnames like /hw/module work as well as /module or /dev/...
*/
graph_err = graph_edge_add(prom_graph_hdl, hw_vertex_hdl,
hw_vertex_hdl, EDGE_LBL_HARDWARE) ;
if (graph_err != GRAPH_SUCCESS) {
printf("err adding edge %s to itself %d\n",
EDGE_LBL_HARDWARE, graph_err) ;
return 0 ;
}
return 1 ;
}
int
init_module_locator(void)
{
graph_error_t graph_err ;
char tmp_buf[32] ;
int i ;
vertex_hdl_t vhdl ;
/* Create the vertex /hw/module */
mod_vertex_hdl = create_graph_path(hw_vertex_hdl, EDGE_LBL_MODULE, 1) ;
/*
* For all the modules found in this partition,
* add edge /hw/module/<module_id>.
* XXX - init_module_table should have initted the number of
* modules per partition.
*/
for (i = 1; i <= num_modules; i++) {
sprintf(tmp_buf, "%d\0", module_table[i].module_id) ;
module_table[i].vhdl = create_graph_path(mod_vertex_hdl,
tmp_buf, 1) ;
graph_err = graph_info_add_LBL(prom_graph_hdl,
module_table[i].vhdl,
INFO_LBL_VERTEX_NAME,
NULL,
(arbitrary_info_t)tmp_buf) ;
if (graph_err != GRAPH_SUCCESS) {
printf("module name add err %d\n", graph_err);
return 0 ;
}
/* create vertex for SLOT */
module_table[i].vhdl = create_graph_path(
module_table[i].vhdl,
EDGE_LBL_SLOT, 1) ;
} /* for */
return (1) ;
}
static int
add_node_edge(lboard_t *lbinfo)
{
vertex_hdl_t node_vhdl, vhdl = 0 ;
char tmp_buf[32], buf[32] ;
graph_error_t graph_err ;
int i ;
/* get the name of my slot */
get_slotname(lbinfo->brd_slot, tmp_buf);
/* Get the vertex handle of my module. It usually is /hw/module/<mid>slot */
for (i=1; i <= num_modules; i++) {
if (module_table[i].module_id == lbinfo->brd_module) {
vhdl = module_table[i].vhdl ;
break ;
}
}
if (!vhdl) {
printf("add_node_edge: No vertex for module %d\n",
lbinfo->brd_module) ;
return 0;
}
/* Add edge /<slotname> to /hw/module/<mid>slot */
node_vhdl = create_graph_path(vhdl, tmp_buf, 1) ;
graph_err = graph_info_add_LBL(prom_graph_hdl, node_vhdl,
INFO_LBL_BRD_INFO, NULL,
(arbitrary_info_t)lbinfo) ;
/* complete current path as /hw/module/<mid>/slot/<slotname>/node */
graph_err = graph_edge_add(prom_graph_hdl,
node_vhdl,
lbinfo->brd_graph_link,
EDGE_LBL_NODE) ;
if (graph_err != GRAPH_SUCCESS) {
printf("mod edge %s add err %d\n", tmp_buf, graph_err) ;
return 0 ;
}
return 1 ;
}
int
add_io_edge(lboard_t *lbinfo)
{
char tmp_buf[32], slotname[32] , board_name[32];
vertex_hdl_t vhdl, new_vhdl;
char *remain ;
graph_error_t graph_err ;
sprintf(tmp_buf, "/module/%d/slot", lbinfo->brd_module) ;
graph_err = hwgraph_path_lookup(hw_vertex_hdl, tmp_buf,
&vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("add_io_edge: %s lookup failed %d\n", remain, graph_err) ;
return 0 ;
}
get_slotname(lbinfo->brd_slot, slotname);
/*
* We pass 0 for the errflg as it is possible to add dups.
* On Origin 200 The motherboard is both a node and io board.
*/
if ((new_vhdl = create_graph_path(vhdl, slotname, 0)) == vhdl) {
printf("create_graph_path: %s can't be added to %s\n",
board_name, tmp_buf);
return 0;
}
graph_err = graph_info_add_LBL(prom_graph_hdl, new_vhdl,
INFO_LBL_BRD_INFO, NULL,
(arbitrary_info_t)lbinfo) ;
get_board_name(lbinfo->brd_nasid, lbinfo->brd_module,
lbinfo->brd_slot, board_name);
graph_err = graph_edge_add(prom_graph_hdl,
new_vhdl, lbinfo->brd_graph_link, board_name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("add_io_edge: edgeadd error %s %d\n",
slotname, graph_err) ;
return 0 ;
}
return 1 ;
}
/*
* Try adding router info to the promgraph.
* Do not report any errors. Meta routers need correct
* module numbers and new names. Till then, this routine
* will warn about duplicate edges as all meta routers
* get their parent module number, which would already
* have the normal routers
*/
int
add_router_edge(lboard_t *lbinfo)
{
char tmp_buf[32], slotname[32] ;
vertex_hdl_t vhdl ;
char *remain ;
graph_error_t graph_err ;
sprintf(tmp_buf, "/module/%d/slot", lbinfo->brd_module) ;
graph_err = hwgraph_path_lookup(hw_vertex_hdl, tmp_buf,
&vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
#if 0
printf("add_router_edge: %s lookup failed %d\n", remain, graph_err) ;
#endif
return 0 ;
}
get_slotname(lbinfo->brd_slot, slotname);
vhdl = create_graph_path(vhdl, slotname, 0) ;
if (!vhdl)
return 0 ;
graph_err = graph_info_add_LBL(prom_graph_hdl, vhdl,
INFO_LBL_BRD_INFO, NULL,
(arbitrary_info_t)lbinfo) ;
if (graph_err != GRAPH_SUCCESS) {
#if 0
printf("add_router_edge: brd info add err %d\n", graph_err) ;
#endif
return 0 ;
}
return 1 ;
}
int
init_board_graph(lboard_t *lbinfo, int node)
{
int rc = 0;
switch (lbinfo->brd_type) {
case KLTYPE_IP27:
if ((rc = init_ip27_graph(lbinfo, node)) == 0)
printf("init_board_graph:init_ip27_graph error,node %d\n",
node);
break ;
case KLTYPE_IO6:
if ((rc = init_baseio_graph(lbinfo, node)) == 0)
printf("init_board_graph:init_baseio_graph err,node %d\n",
node);
break ;
case KLTYPE_MSCSI:
case KLTYPE_MENET:
case KLTYPE_HAROLD: /* PCI SHOEBOX BOARD */
case KLTYPE_WEIRDIO:
if ((rc = init_xtalkbrd_graph(lbinfo, node)) == 0)
printf("init_board_graph:init_xtalkbrd_graph err,node %d\n",
node);
break ;
case KLTYPE_ROUTER:
case KLTYPE_META_ROUTER:
init_router_graph(lbinfo, node, NULL) ;
break ;
case KLTYPE_MIDPLANE:
/* In the case of non-speedo or a speedo with an xbow
* build the graph for midplane (which basically populates
* the graph with xbow & its components).
*/
if ((!(SN00) && !(CONFIG_12P4I)) || is_xbox_config(node))
if ((rc = init_midplane8_graph(lbinfo, node)) == 0)
printf("init_board_graph: midplane_graph err, node %d\n",
node);
break ;
case KLTYPE_TPU:
if ((rc = init_tpu_graph(lbinfo, node)) == 0)
printf("init_board_graph: tpu_graph err, node %d\n",
node);
break ;
case KLTYPE_GSN_A:
case KLTYPE_GSN_B:
if ((rc = init_gsn_graph(lbinfo, node)) == 0)
printf("init_board_graph: gsn_graph err, node %d\n",
node);
break ;
default:
if ((KLCLASS(lbinfo->brd_type) == KLCLASS_GFX) ||
(KLCLASS(lbinfo->brd_type) == KLCLASS_PSEUDO_GFX)) {
if ((rc = init_graphics_graph(lbinfo, node)) == 0)
printf("init_board_graph: graphics_graph err, node %d\n",
node);
} else
if (KLCLASS(lbinfo->brd_type) == KLCLASS_IO) {
if ((rc = init_xtalkbrd_graph(lbinfo, node)) == 0)
printf("init_board_graph:init_xtalkbrd_graph err,node %d\n",
node);
}
break ;
}
return rc ;
}
int
promgraph_edge_add(klinfo_t *klcompt, vertex_hdl_t vert1,
vertex_hdl_t vert2, int flag)
{
char buf[32];
graph_error_t err;
get_edge_name(klcompt, buf, flag);
err = graph_edge_add(prom_graph_hdl, vert1, vert2, buf) ;
if (err != GRAPH_SUCCESS) {
printf("node %d: %d<->%d edge %s add error %d\n",
klcompt->nasid, vert1, vert2, buf, err);
return 0;
}
return 1;
}
int
promgraph_connect(klinfo_t *klcompt1, klinfo_t *klcompt2,
vertex_hdl_t vert1, vertex_hdl_t vert2, int flag)
{
if (promgraph_edge_add(klcompt1, vert1, vert2, flag) == 0)
return 0;
#if 0
if (promgraph_edge_add(klcompt2, vert2, vert1, flag) == 0)
return 0;
#endif
return 1;
}
int
promgraph_create_board(lboard_t *lb, int node, vertex_hdl_t *vert, int type)
{
register int i;
klinfo_t *klcompt;
graph_error_t graph_err;
vertex_hdl_t tvert[MAX_COMPTS_PER_BRD], tmp_vhdl ;
char tmp_buf[32] ;
void *nic_info ;
for (i = 0; i < lb->brd_numcompts; i++) {
klcompt = (klinfo_t *)(NODE_OFFSET_TO_K1(
node, lb->brd_compts[i]));
/* XXX take care of DISABLED Components here */
#if 0
if (!(klcompt->flags & KLINFO_ENABLE))
continue ;
#endif
graph_err = graph_vertex_create(prom_graph_hdl, &vert[i]) ;
if (graph_err != GRAPH_SUCCESS) {
printf("node %d: %d create error %d\n",
node, i, graph_err);
return 0;
}
if (graph_err = pg_add_lbl(vert[i], INFO_LBL_KLCFG_INFO,
(void *)klcompt)) {
printf("%d: add LBL error %d\n", node, graph_err);
return 0 ;
}
switch(klcompt->struct_type) {
case KLSTRUCT_BRI:
case KLSTRUCT_HUB:
case KLSTRUCT_GFX:
case KLSTRUCT_ROU:
case KLSTRUCT_TPU:
case KLSTRUCT_GSN_A:
case KLSTRUCT_GSN_B:
case KLSTRUCT_XTHD:
if (graph_err = pg_add_lbl(vert[i],
INFO_LBL_BRD_INFO, (void *)lb)) {
printf("%d: add LBL BRD error %d\n",
node, graph_err);
return 0 ;
}
break;
default:
break ;
}
switch(klcompt->struct_type) {
case KLSTRUCT_BRI:
case KLSTRUCT_HUB:
case KLSTRUCT_ROU:
case KLSTRUCT_GFX:
case KLSTRUCT_TPU:
case KLSTRUCT_GSN_A:
case KLSTRUCT_GSN_B:
case KLSTRUCT_XTHD:
pg_add_nic_info(klcompt, vert[i]) ;
break;
default:
break ;
}
}
return 1;
}
int
init_ip27_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD];
klhub_t *klhubp;
/* Create a vertex for all components. */
if (promgraph_create_board(lbinfo, node, compt_vert, KLSTRUCT_HUB) == 0)
return 0;
#ifdef SABLE
if (promgraph_setup_ip27_devices(lbinfo, node, compt_vert) == 0)
return 0;
#endif
if (promgraph_connect_brd_compts(lbinfo, KLSTRUCT_HUB,compt_vert, 1) == 0)
return 0;
add_node_edge(lbinfo) ;
return 1 ;
}
int
init_baseio_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
if (promgraph_create_board(lbinfo, node,
compt_vert, KLSTRUCT_BRI) == 0)
return 0;
if (promgraph_setup_xtalk_devices(lbinfo, node, compt_vert) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, KLSTRUCT_BRI,compt_vert, 0) == 0)
return 0;
return 1 ;
}
int
init_xtalkbrd_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
if (promgraph_create_board(lbinfo, node, compt_vert, KLSTRUCT_SCSI) == 0)
return 0;
if (promgraph_setup_xtalk_devices(lbinfo, node, compt_vert) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, KLSTRUCT_BRI,compt_vert, 0) == 0)
return 0;
return 1 ;
}
int
init_router_graph(lboard_t *lbinfo, int node, pcfg_router_t *cfg_rp)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
if (promgraph_create_board(lbinfo, node, compt_vert, KLSTRUCT_ROU) == 0)
return 0;
add_router_edge(lbinfo) ;
return 1 ;
}
int
init_midplane8_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
if (promgraph_create_board(lbinfo, node, compt_vert, KLSTRUCT_XBOW) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, KLSTRUCT_XBOW, compt_vert, 1) == 0)
return 0;
return 1 ;
}
int
init_graphics_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
int type = 0 ;
if (KLCF_CLASS(lbinfo) == KLCLASS_GFX)
type = KLSTRUCT_GFX ;
else
if (KLCF_CLASS(lbinfo) == KLCLASS_PSEUDO_GFX)
type = KLSTRUCT_XTHD ;
if (promgraph_create_board(lbinfo, node, compt_vert, type) == 0)
return 0;
if (promgraph_setup_xtalk_devices(lbinfo, node, compt_vert) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, type, compt_vert, 1) == 0)
return 0;
return 1 ;
}
int
init_tpu_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
if (promgraph_create_board(lbinfo, node, compt_vert, KLSTRUCT_TPU) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, KLSTRUCT_TPU, compt_vert, 1) == 0)
return 0;
return 1;
}
int
init_gsn_graph(lboard_t *lbinfo, int node)
{
vertex_hdl_t compt_vert[MAX_COMPTS_PER_BRD] ;
int struct_type;
struct_type = (lbinfo->brd_type == KLTYPE_GSN_A) ?
KLSTRUCT_GSN_A : KLSTRUCT_GSN_B;
if (promgraph_create_board(lbinfo, node, compt_vert, struct_type) == 0)
return 0;
if (promgraph_connect_brd_compts(lbinfo, struct_type, compt_vert, 1) == 0)
return 0;
return 1;
}
link_node_boards(int node)
{
lboard_t *brd_ptr;
brd_ptr = (lboard_t *)KL_CONFIG_INFO(node) ;
while (brd_ptr) {
if (brd_ptr->struct_type == REMOTE_BOARD) {
printf("Remote board in link_node_boards: fixme\n");
}
else {
if ((brd_ptr->brd_parent) && /* not a root */
(!(brd_ptr->brd_flags & DUPLICATE_BOARD)) &&
(brd_ptr->brd_type != KLTYPE_ROUTER) &&
(brd_ptr->brd_type != KLTYPE_TPU) &&
(brd_ptr->brd_type != KLTYPE_GSN_A) &&
(brd_ptr->brd_type != KLTYPE_GSN_B) &&
(brd_ptr->brd_flags & KLINFO_ENABLE)) {
PG_DPRINT("link brd %x P %x %x\n",
brd_ptr, brd_ptr->brd_parent, brd_ptr->brd_type) ;
link_2_boards(brd_ptr);
}
}
brd_ptr = KLCF_NEXT(brd_ptr);
}
return 1 ;
}
link_2_boards(lboard_t *lbinfo)
{
vertex_hdl_t v1, v2, v3 ;
klinfo_t *aip1, *aip2 ;
graph_error_t graph_err ;
char edge_name[32] ;
v1 = lbinfo->brd_graph_link ; /* usually Non Node Brds */
v2 = lbinfo->brd_parent->brd_graph_link ; /* Usually, a node brd */
graph_err = graph_info_get_LBL(prom_graph_hdl, v1,
INFO_LBL_KLCFG_INFO, NULL,
(arbitrary_info_t *)&aip1) ;
if (graph_err != GRAPH_SUCCESS) {
printf("Get Label v1 failed in link_2_boards, grapherr=%d\n", graph_err) ;
return 0 ;
}
graph_err = graph_info_get_LBL(prom_graph_hdl, v2,
INFO_LBL_KLCFG_INFO, NULL,
(arbitrary_info_t *)&aip2) ;
if (graph_err != GRAPH_SUCCESS) {
printf("Get Label v2 failed in link_2_boards, graph_err=%d\n", graph_err) ;
return 0 ;
}
PG_DPRINT("v1 = %d, a1 = %lx, v2 = %d, a2 = %lx\n",
v1, aip1, v2, aip2) ;
PG_DPRINT("lbptrs - 1 = %lx, P = %lx\n", lbinfo, lbinfo->brd_parent) ;
/* If the target to which we are going is a XTALK brd,
use widget instead of actual component name. */
if (aip1->struct_type == KLSTRUCT_BRI) { /* XXX and any others */
v3 = create_graph_path(v2, EDGE_LBL_XTALK, 0) ;
sprintf(edge_name, "%d\0", aip1->widid) ;
PG_DPRINT("Add edge %s, from %s%x --> %s%x\n", edge_name,
compt_names[aip2->struct_type], aip2->virtid,
compt_names[aip1->struct_type], aip1->virtid) ;
PG_DPRINT("Phys ids: v2 = %x, v1 = %x\n",
aip2->physid, aip1->physid) ;
graph_err = graph_edge_add(prom_graph_hdl,
v3, v1, edge_name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("%s link2 v3 to v1 edgeadd error %d\n",
edge_name, graph_err) ;
return 0 ;
}
add_io_edge(lbinfo) ;
} else
if ((aip1->struct_type == KLSTRUCT_GFX) ||
(KLCF_CLASS(lbinfo) == KLCLASS_PSEUDO_GFX)) {
add_io_edge(lbinfo) ;
}
else {
get_edge_name(aip1, edge_name, 1);
PG_DPRINT("Add edge %s, from %s%x --> %s%x\n", edge_name,
compt_names[aip2->struct_type], aip2->virtid,
compt_names[aip1->struct_type], aip1->virtid) ;
graph_err = graph_edge_add(prom_graph_hdl,
v2, v1, edge_name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("%s link2 v2 to v1 edgeadd error %d\n",
edge_name, graph_err) ;
return 0 ;
}
}
return 1 ;
}
void
prom_install_devices(void)
{
vertex_hdl_t next_vertex_hdl;
graph_error_t graph_err ;
graph_vertex_visit(prom_graph_hdl, vvisit_install, &hw_vertex_hdl,
&graph_err, &next_vertex_hdl) ;
}
int
vvisit_install(void *arg, vertex_hdl_t vhdl)
{
prom_dev_info_t *arbinf_ptr ;
klinfo_t *kl_comp;
graph_error_t graph_err ;
/* Init all controller numbers and any driver specific
globals here. */
#ifdef SABLE
num_qlogic = 0 ;
num_sbldsk = 0 ;
num_ioc3 = 0 ;
ioc3_installed = 0 ;
#endif
/* Do we have a dev_info label associated with this vertex? */
graph_err = graph_info_get_LBL(prom_graph_hdl, vhdl,
INFO_LBL_DEV_INFO, NULL, (arbitrary_info_t *)&arbinf_ptr) ;
if (graph_err == GRAPH_SUCCESS) {
/* Is there a valid install routine */
/* Is it OK to call the install routine */
if ((inst_valid(arbinf_ptr->install)) &&
(((klinfo_t *)arbinf_ptr->kl_comp)->flags & KLINFO_INSTALL)
&&(((klinfo_t *)arbinf_ptr->kl_comp)->flags & KLINFO_ENABLE))
{
/* Can this be moved to init? XXX */
if (((klinfo_t *)arbinf_ptr->kl_comp)->struct_type
== KLSTRUCT_SCSI)
((klscsi_t *)arbinf_ptr->kl_comp)->scsi_numdevs = 0;
arbinf_ptr->install(*(vertex_hdl_t *)arg, vhdl) ;
}
}
return 0 ;
}
int pass ;
void
kl_init_devices(void)
{
vertex_hdl_t next_vertex_hdl;
graph_error_t graph_err ;
if (!_symmon)
printf("Initializing PROM Device drivers ..........\t\t") ;
pass ++ ;
graph_vertex_visit(prom_graph_hdl, vvisit_init, &hw_vertex_hdl,
&graph_err, &next_vertex_hdl) ;
if (!_symmon)
printf("DONE\n") ;
}
int
vvisit_init(void *arg, vertex_hdl_t vhdl)
{
prom_dev_info_t *arbinf_ptr ;
register struct eiob *io;
klinfo_t *kl_comp;
graph_error_t graph_err ;
graph_err = graph_info_get_LBL(prom_graph_hdl, vhdl,
INFO_LBL_DEV_INFO, NULL,
(arbitrary_info_t *)&arbinf_ptr) ;
if (graph_err == GRAPH_SUCCESS) {
kl_comp = (klinfo_t *)(arbinf_ptr->kl_comp);
if ((kl_comp->flags & KLINFO_CONTROLLER) &&
(arbinf_ptr->driver)) {
if ((io = new_eiob()) == NULL) {
printf("vvinit: Out of eiobs\n") ;
return 1;
}
io->iob.Controller = kl_comp->virtid ;
io->iob.FunctionCode = FC_INITIALIZE;
io->iob.Count = pass ;
if ((*arbinf_ptr->driver)
(kl_comp->arcs_compt, &io->iob) != 0) {
arbinf_ptr->flags |= Failed;
/* XXX verify that driver fills up
arcs_compt->Flags |= Failed */
}
if (arbinf_ptr->driver == dksc_strat)
tpsc_strat(kl_comp->arcs_compt, &io->iob) ;
free_eiob(io);
}
}
return 0 ; /* continue for all nodes */
}
int
get_locator_id(klinfo_t *klcompt)
{
int rv ;
switch(klcompt->struct_type)
{
case KLSTRUCT_DISK:
case KLSTRUCT_TAPE:
case KLSTRUCT_CDROM:
case KLSTRUCT_IOC3ENET:
case KLSTRUCT_IOC3UART:
rv = (klcompt->virtid * 16 + klcompt->physid) ;
break;
case KLSTRUCT_IOC3_TTY:
rv = klcompt->virtid ;
break ;
default:
rv = (klcompt->nasid * 16 + klcompt->physid) ;
break ;
}
return rv ;
}
/*
* Get the name of the edge to be used in edge add. This is derived
* based on the pre-defined component name based on component type
* and the virtual id of the component in the klinfo_t structure.
*/
void
get_edge_name(klinfo_t *klcompt, char *buf, int flag)
{
char tmp_buf[32] ;
int virtid ; /* Virtual id of the component */
if (klcompt->struct_type > (sizeof(compt_names)/sizeof(char *))) {
*buf = 0 ;
return ;
}
switch(flag) {
case 0:
sprintf(buf, "%d\0", klcompt->physid) ;
break ;
case 1:
strcpy(buf, compt_names[klcompt->struct_type]) ;
break ;
case 2:
strcpy(tmp_buf, compt_names[klcompt->struct_type]) ;
strcat(tmp_buf, "%d\0") ;
virtid = get_locator_id(klcompt) ;
sprintf(buf, tmp_buf, virtid) ;
break ;
default:
*buf = 0 ;
break ;
}
return ;
}
/*
* Creates the necessary data structures for a device discovered
* by the device driver. Covers all devices we are currently aware
* of. Returns a pointer to the actual device type, for example,
* klioc3_t * for IOC3, klscdev_t * for scsi devices etc.
*/
#define MAX_SCSI_DEV_PROBE 40
klinfo_t *
init_device_graph(vertex_hdl_t devctlr_vhdl, int dev_type)
{
graph_error_t graph_err ;
klinfo_t *ctrkli_ptr;
klioc3_t *ioc3kli_ptr ;
klinfo_t *devkli_ptr;
/* First get the controller's klinfo_t */
graph_err = graph_info_get_LBL(prom_graph_hdl, devctlr_vhdl,
INFO_LBL_KLCFG_INFO,NULL,
(arbitrary_info_t *)&ctrkli_ptr) ;
if (graph_err != GRAPH_SUCCESS) {
printf("init_dev_graph: getLBL e %d t %d\n", graph_err, dev_type) ;
return NULL ;
}
/* Return the controller klinfo ptr if dev_type does
not match. XXX this causes probs in case of unknown devs.
*/
devkli_ptr = ctrkli_ptr ;
/* call the respective init_klcfg based on dev_type */
switch (dev_type) {
/* XXX assuming that IOC3 has been inited */
case KLSTRUCT_IOC3ENET:
devkli_ptr=(klinfo_t *)init_klcfg_enet(
(klioc3_t *)ctrkli_ptr) ;
break ;
case KLSTRUCT_IOC3UART:
case KLSTRUCT_HUB_UART:
devkli_ptr=(klinfo_t *)init_klcfg_tty((klioc3_t *)ctrkli_ptr) ;
break ;
case KLSTRUCT_IOC3PCKM:
devkli_ptr = (klinfo_t *)init_klcfg_kbd((klioc3_t *)ctrkli_ptr, dev_type) ;
break ;
case KLSTRUCT_IOC3MS:
devkli_ptr = (klinfo_t *)init_klcfg_ms((klioc3_t *)ctrkli_ptr) ;
break ;
case KLSTRUCT_DISK:
case KLSTRUCT_CDROM:
case KLSTRUCT_TAPE:
/* XXX This can fillup the arcs stuff too based
on device type. */
/* Probing all buses here, leaves klcfg memory
* exhausted. And there is none left for symmon
* which panics. So limit number of buses even
* if probeall scsi is set. */
if (num_scsi_drive < MAX_SCSI_DEV_PROBE) {
devkli_ptr=(klinfo_t *)init_klcfg_scsi_drive(
(klscsi_t *)ctrkli_ptr, dev_type) ;
num_scsi_drive++ ;
} else
devkli_ptr = NULL ;
break ;
default:
printf("Invalid device type 0x%x!!\n", dev_type);
return NULL ;
}
if (devkli_ptr)
devkli_ptr->arcs_compt = (COMPONENT *)malloc(sizeof(COMPONENT)) ;
return(devkli_ptr) ;
}
link_device_to_graph(vertex_hdl_t hw_vhdl, vertex_hdl_t devctlr_vhdl,
klinfo_t *devkli_ptr, int(*dev_strat)())
{
char locedge_name[32], ctlredge_name[32], *remain ;
char tmp_buf[32] ;
graph_error_t graph_err ;
vertex_hdl_t newdev_vhdl, locator_vhdl, link_vhdl ;
klinfo_t *ctrkli_ptr ;
int i = 0 ;
prom_dev_info_t *dev_info;
klinfo_t *tmpkli_ptr ;
graph_edge_place_t eplace = GRAPH_EDGE_PLACE_NONE ;
char *ai ;
strcpy(locedge_name, "/dev/") ;
switch(devkli_ptr->struct_type) {
case KLSTRUCT_HUB_UART:
case KLSTRUCT_IOC3UART:
case KLSTRUCT_HUB_TTY:
case KLSTRUCT_IOC3_TTY:
strcat(locedge_name, "tty") ;
break ;
case KLSTRUCT_IOC3ENET:
strcat(locedge_name, EDGE_LBL_ENET) ;
break ;
case KLSTRUCT_DISK:
strcat(locedge_name, "disk") ;
break ;
case KLSTRUCT_IOC3PCKM:
case KLSTRUCT_IOC3MS:
strcat(locedge_name, "input");
break ;
default:
strcat(locedge_name,
compt_names[devkli_ptr->struct_type]);
break ;
}
graph_err = hwgraph_path_lookup(hw_vhdl, locedge_name,
&locator_vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("dev_vhdl lookup failed %d %s\n", graph_err, remain) ;
return 0 ;
}
graph_err = graph_info_get_LBL(prom_graph_hdl, devctlr_vhdl,
INFO_LBL_LINK, NULL,
(arbitrary_info_t *)&ai) ;
if (graph_err != GRAPH_SUCCESS) {
/* printf("get link LBL failed %d\n", graph_err) ; */
link_vhdl = devctlr_vhdl ;
}
else {
graph_err = hwgraph_path_lookup(devctlr_vhdl, ai,
&link_vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("link lookup err %d %s\n", graph_err, remain) ;
return 0 ;
}
}
/* Create new vertex and Fill up label INFO_LBL_KLCFG_INFO */
newdev_vhdl = create_device_graph(link_vhdl, devkli_ptr, dev_strat) ;
/* Create 3 path names */
get_edge_name(devkli_ptr, locedge_name, 2) ;
i = devkli_ptr->virtid ; /* save virtid */
devkli_ptr->virtid = devkli_ptr->physid ; /* XXX right value ?? */
get_edge_name(devkli_ptr, ctlredge_name, 1) ;
devkli_ptr->virtid = i ;
/* Locator substring to device */
graph_err = graph_edge_add(prom_graph_hdl, locator_vhdl,
newdev_vhdl, locedge_name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("locator device edge %s add err %d\n",
locedge_name, graph_err) ;
}
return 0 ;
}
vertex_hdl_t
create_device_graph(vertex_hdl_t link_vhdl, klinfo_t *kp, int(*dev_strat)())
{
vertex_hdl_t vhdl ;
graph_error_t graph_err ;
char tmp_buf[32] ;
prom_dev_info_t *dev_info ;
if (kp->struct_type == KLSTRUCT_DISK) {
sprintf(tmp_buf, "%d\0", kp->physid) ;
/* switch (kp->arcs_compt->Type) disk, tape, ... XXX */
strcat(tmp_buf, PROM_EDGE_LBL_LUN_0_DISK) ;
vhdl = create_graph_path(link_vhdl, tmp_buf, 1) ;
}
else if (kp->struct_type == KLSTRUCT_CDROM) {
vertex_hdl_t vhdl1 ;
sprintf(tmp_buf, "%d\0", kp->physid) ;
strcat(tmp_buf, "/lun/0") ;
vhdl1 = create_graph_path(link_vhdl, tmp_buf, 1) ;
vhdl = create_graph_path(vhdl1, "cdrom", 1) ;
graph_err=graph_edge_add(prom_graph_hdl, vhdl1, vhdl, "disk") ;
if (graph_err != GRAPH_SUCCESS)
printf("Add disk to cdrom fail %d\n", graph_err) ;
}
else if (kp->struct_type == KLSTRUCT_TAPE) {
sprintf(tmp_buf, "%d\0", kp->physid) ;
strcat(tmp_buf, PROM_EDGE_LBL_LUN_0_TAPE) ;
vhdl = create_graph_path(link_vhdl, tmp_buf, 1) ;
}
else if (kp->struct_type == KLSTRUCT_IOC3_TTY) {
get_edge_name(kp, tmp_buf, 2) ;
vhdl = create_graph_path(link_vhdl, tmp_buf, 1) ;
}
else {
get_edge_name(kp, tmp_buf, 1) ;
vhdl = create_graph_path(link_vhdl, tmp_buf, 1) ;
}
graph_err = graph_info_add_LBL(prom_graph_hdl, vhdl,
INFO_LBL_KLCFG_INFO, NULL,
(arbitrary_info_t)kp) ;
if (graph_err != GRAPH_SUCCESS) {
printf("dev info addLBL error %d\n", graph_err) ;
return 0 ;
}
dev_info = malloc(sizeof(prom_dev_info_t));
if (dev_info == NULL) {
printf("link device: Cannot allocate prom_dev_info\n");
return 0;
}
bzero(dev_info, sizeof(prom_dev_info_t)) ;
graph_err = graph_info_add_LBL(prom_graph_hdl, vhdl,
INFO_LBL_DEV_INFO, NULL,
(arbitrary_info_t)dev_info);
if (graph_err != GRAPH_SUCCESS) {
printf("add devinfo failed %d\n", graph_err) ;
return 0 ;
}
/* Just register the driver for the device */
/* This is the same as the driver for the controller */
dev_info->kl_comp = kp ;
kl_reg_drv_strat(dev_info, dev_strat) ;
return (vhdl) ;
}
/* Find the address of the driver routine given the sa_pci_ident_t */
__psunsigned_t
find_pci_driver(sa_pci_ident_t *pi)
{
sa_pci_ident_t *tpi ;
tpi = (sa_pci_ident_t *)prom_pci_info ;
while (tpi->vendor_id) /* entry valid */
if ((tpi->vendor_id == pi->vendor_id) &&
(tpi->device_id == pi->device_id))
/* Ignore Revision for now. */
return((__psunsigned_t)tpi->inst_fptr) ;
else
tpi ++ ;
return(NULL) ;
}
void
setup_pci_identity_info(klinfo_t *klcompt, sa_pci_ident_t *tpi)
{
pcicfg32_t *pci_cfg_dev_ptr ;
__uint64_t pci_key;
if (klcompt->struct_type == KLSTRUCT_HUB_UART) {
tpi->vendor_id = 0x0300;
tpi->device_id = 0xfafd;
tpi->revision_id = 10;
return;
}
if (klcompt->nic == 0xABfEDDDD) { /* SABLE disk magic*/
tpi->vendor_id = 0x0300 ;
tpi->device_id = 0xfafe ;
tpi->revision_id = 10 ;
} else {
pci_key = MK_SN0_KEY(klcompt->nasid,
klcompt->widid, klcompt->physid);
pci_cfg_dev_ptr =
(pcicfg32_t *)GET_PCICFGBASE_FROM_KEY(pci_key);
tpi->vendor_id = (pci_cfg_dev_ptr->pci_id >> 16);
tpi->device_id = (pci_cfg_dev_ptr->pci_id & 0xffff);
tpi->revision_id = 10 ;
}
return;
}
/* Check if the function pointer is a valid install routine */
inst_valid(int (*fptr)())
{
sa_pci_ident_t *tpi = (sa_pci_ident_t *)prom_pci_info ;
while (tpi->vendor_id) /* entry valid */
if(tpi->inst_fptr == fptr)
return 1 ;
else
tpi ++ ;
return(0) ;
}
#ifdef SABLE
int
promgraph_setup_ip27_devices(lboard_t *brd_ptr,
nasid_t nasid,
vertex_hdl_t *vert)
{
register int i;
klinfo_t *klcompt;
prom_dev_info_t *dev_info;
graph_error_t graph_err;
sa_pci_ident_t pi ;
char tmp_buf[32] ;
for (i = 0; i < brd_ptr->brd_numcompts; i++) {
klcompt =
(klinfo_t *)(NODE_OFFSET_TO_K1(nasid,
brd_ptr->brd_compts[i]));
switch(klcompt->struct_type) {
case KLSTRUCT_HUB_UART:
case KLSTRUCT_HUB_TTY:
dev_info = malloc(sizeof(prom_dev_info_t));
if (dev_info == NULL) {
printf("promgraph_setup_ip27_devices: \
Cannot allocate prom_dev_info for hub uart\n");
return 0;
}
setup_pci_identity_info(klcompt, &pi);
dev_info->install = (int (*)())
find_pci_driver(&pi);
if (nasid == 0)
dev_info->install = (int (*)())
kl_hubuart_install ;
dev_info->kl_comp = klcompt;
dev_info->flags = 0;
dev_info->driver = NULL;
klcompt->virtid = nasid ;
graph_err =
graph_info_add_LBL(prom_graph_hdl,
vert[i],
INFO_LBL_DEV_INFO, NULL,
(arbitrary_info_t)dev_info);
if (graph_err != GRAPH_SUCCESS) {
printf("promgraph_setup_ip27_devices: \
cannot add dev_info label\n");
return 0;
}
break;
default:
break;
}
}
return 1;
}
#endif
/*
* promgraph_setup_xtalk_devices
* Setup the device drivers for all controllers found in the system.
* This routine has become complicated due to various requirements.
* - do not setup drivers for disk if we are symmon.
* - If ProbeAllScsi is set to y then probe all boards/scsi buses.
* - do not setup drivers for any but the first/master IO6 board.
* - do not setup drivers for controllers disabled by the disable cmd.
*/
int
promgraph_setup_xtalk_devices(lboard_t *lb,
nasid_t n,
vertex_hdl_t *vert)
{
klinfo_t *k ;
prom_dev_info_t *d ;
sa_pci_ident_t pi ;
graph_error_t gerr;
int i ;
/* check nvram vars */
int mod, slot, ms ;
char *p = NULL ;
mod = slot = 0 ;
num_scsi_drive = 0 ;
if ((p=getenv("ProbeAllScsi")) && p && ((*p == 'y') || (*p == 'Y'))) {
mod = slot = -1 ;
} else if ((p=getenv("ProbeWhichScsi")) && p) {
if ((ms = check_console_path(p)) > 0) {
mod = ms >> 16 ;
slot = ms & 0xffff ;
}
}
/* Handle known compts with drivers. Skip the rest */
for (i = 0; i < lb->brd_numcompts; i++) {
k = (klinfo_t *)(NODE_OFFSET_TO_K1(n,
lb->brd_compts[i]));
/* Skip disabled components */
if (!(k->flags & KLINFO_ENABLE))
continue ;
switch (k->struct_type) {
case KLSTRUCT_SCSI:
/*
The order of these condition checks is very
important. Disturbing this has disastrous
consequences.
*/
if ((_symmon) || (p && (*p == 'X')))
continue ;
if (mod == -1) /* ProbeAllScsi */
break ;
if ((!_symmon) && /* master_baseio_modid invalid in symmon */
(lb->brd_type == KLTYPE_BASEIO) &&
(lb->brd_module == master_baseio_modid) &&
(lb->brd_slot == master_baseio_slotid))
break ;
else if (mod > 0) { /* ProbeWhichScsi */
/* Check if specified path is already master */
if ((mod == master_baseio_modid) &&
(slot == master_baseio_slotid))
continue ;
if ((lb->brd_module == mod) &&
((SLOTNUM_GETSLOT(lb->brd_slot)) == slot))
break ;
else
continue ;
} else /* not master and module == 0 */
continue ;
/* NOTREACHED */
break ;
case KLSTRUCT_IOC3:
if (lb->brd_type == KLTYPE_BASEIO)
break ;
else
continue ;
/* NOTREACHED */
break ;
case KLSTRUCT_GFX:
case KLSTRUCT_PCI:
if (_symmon)
continue ;
break ;
default :
continue ;
}
/* Install the driver */
d = malloc(sizeof(prom_dev_info_t));
if (d == NULL) {
printf("promgraph_setup_xtalk_devices: \
Cannot allocate prom_dev_info for %d.\n",
k->struct_type);
return 0;
}
if ((k->struct_type == KLSTRUCT_GFX) ||
(KLCF_CLASS(lb) == KLCLASS_PSEUDO_GFX)) {
d->install = (int (*)())NULL;
} else {
setup_pci_identity_info(k, &pi);
d->install = (int (*)())find_pci_driver(&pi);
}
d->kl_comp = k;
d->lb = lb ;
d->flags = 0;
d->driver = NULL;
d->modid = lb->brd_module ;
d->slotid = lb->brd_slot ;
k->arcs_compt = (COMPONENT *) malloc(sizeof(COMPONENT)) ;
gerr = graph_info_add_LBL(prom_graph_hdl, vert[i],
INFO_LBL_DEV_INFO, NULL,
(arbitrary_info_t)d);
if (gerr != GRAPH_SUCCESS) {
printf("promgraph_setup_xtalk_devices: \
cannot add dev_info label for %d, %d",
k->struct_type, gerr);
return 0;
}
}
return 1;
}
int
promgraph_connect_brd_compts(lboard_t *brd,
unsigned char type, vertex_hdl_t *compt_vert, int flag)
{
int i;
klinfo_t *klcompt;
int main_ndx = -1;
vertex_hdl_t bridge_vhdl, hubcpu_vhdl, v2 ;
graph_error_t graph_err ;
int saveflag = flag ;
bridge_vhdl = 0 ;
v2 = 0 ;
for (i = 0; i < KLCF_NUM_COMPS(brd); i++) {
if (KLCF_COMP_TYPE(KLCF_COMP(brd, i)) == type) {
brd->brd_graph_link = compt_vert[i];
main_ndx = i;
if (type == KLSTRUCT_BRI) {
v2 = create_graph_path(compt_vert[i],
PROM_EDGE_LBL_PCI_SLOT, 1) ;
bridge_vhdl = compt_vert[i] ;
compt_vert[i] = v2 ;
}
if (type == KLSTRUCT_HUB) {
v2 = create_graph_path(compt_vert[i],
PROM_EDGE_LBL_CPU, 1) ;
hubcpu_vhdl = v2 ;
}
break;
}
}
if (main_ndx == -1) {
printf("promgraph_connect_brd_components: \
cannot find type %x for brd %x\n", type, brd->brd_type);
return 0;
}
for (i = 0; i < KLCF_NUM_COMPS(brd); i++) {
klcompt = KLCF_COMP(brd, i);
if (i != main_ndx) {
vertex_hdl_t tmp_vhdl ;
if (klcompt->struct_type == KLSTRUCT_CPU) {
tmp_vhdl = hubcpu_vhdl ;
flag = 0 ;
}
else {
tmp_vhdl = compt_vert[main_ndx] ;
flag = saveflag ;
}
if (promgraph_connect(KLCF_COMP(brd, i),
KLCF_COMP(brd, main_ndx),
tmp_vhdl,
compt_vert[i], flag) == 0)
return 0;
}
switch (KLCF_COMP_TYPE(klcompt)) {
case KLSTRUCT_HUB:
/* locator edge /hw/hub to hub */
if (promgraph_edge_add(klcompt,
hw_locator_edges[HUB_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
case KLSTRUCT_CPU:
/* locator edge /hw/cpu to cpu */
if (promgraph_edge_add(klcompt,
hw_locator_edges[CPU_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
case KLSTRUCT_BRI:
if (promgraph_edge_add(klcompt,
hw_locator_edges[BRIDGE_LOCATOR_INDEX].vhdl,
bridge_vhdl, 2) == 0)
return 0;
break;
case KLSTRUCT_XBOW:
if (promgraph_edge_add(klcompt,
hw_locator_edges[XBOW_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
case KLSTRUCT_ROU:
if (promgraph_edge_add(klcompt,
hw_locator_edges[ROUTER_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
case KLSTRUCT_TPU:
if (promgraph_edge_add(klcompt,
hw_locator_edges[TPU_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
case KLSTRUCT_GSN_A:
case KLSTRUCT_GSN_B:
if (promgraph_edge_add(klcompt,
hw_locator_edges[GSN_LOCATOR_INDEX].vhdl,
compt_vert[i], 2) == 0)
return 0;
break;
/* add other interesting types here */
default:
break;
}
}
if (klcompt->struct_type == KLSTRUCT_BRI)
compt_vert[main_ndx] = bridge_vhdl ;
return 1;
}
/*
* Create a set of nodes and link them up with the given
* path name.
* If errflg is set report any error, else if an edge already
* exists, dont report error but return the existing edge as
* if it was just now created.
*/
vertex_hdl_t
create_graph_path(vertex_hdl_t start_vhdl, char *path, int errflg)
{
vertex_hdl_t v1, v2 ;
graph_error_t graph_err ;
char tmp_buf[32], *next ;
if (!(*path)) return 0 ; /* Null path */
v2 = start_vhdl ;
PG_DPRINT("crgfpth: path is %s\n",path);
do {
if ((next = index(path, '/'))!=0) {
strncpy(tmp_buf, path, next-path) ;
tmp_buf[next-path] = 0 ;
path = next+1 ;
}
else
strcpy(tmp_buf, path) ;
PG_DPRINT("crgfpth: tmp_buf is %s\n",tmp_buf);
graph_err = graph_vertex_create(prom_graph_hdl, &v1) ;
if (graph_err != GRAPH_SUCCESS) {
printf("crgfpth: %s create err %d\n", path, graph_err) ;
return 0 ;
}
graph_err = graph_edge_add(prom_graph_hdl, v2, v1, tmp_buf) ;
if (graph_err != GRAPH_SUCCESS) {
if (errflg) {
reporterr:
printf("crgfpth: %s add err %d \n", path, graph_err) ;
return 0 ;
}
else { /* dont report error if GRAPH_DUP only */
if (graph_err != GRAPH_DUP)
goto reporterr ;
else {
graph_vertex_destroy(prom_graph_hdl, v1) ;
if (graph_edge_get(prom_graph_hdl,
v2, tmp_buf, &v1) != GRAPH_SUCCESS) {
printf("Dup Edge %s not found\n", tmp_buf) ;
return 0;
}
}
}
}
v2 = v1 ;
}
while (next) ;
return (v1) ;
}
/*
* This routine manages a linked list of install routines.
* It is used to change the order of device driver install.
* Normally the drivers are installed as and when they are
* 'discovered' or in random order.
* For example, if we want to install all scsi drivers after
* all devices, then scsi_install registers itself first
* and gets called later.
*/
void
kl_register_install(vertex_hdl_t hw_vhdl, vertex_hdl_t loc_vhdl,
void (*install)())
{
struct inst_later *ilptr;
/* Allocate Q element */
if (!(ilptr = (struct inst_later *)malloc(sizeof(*ilptr))))
panic("cannont malloc space for RegisterInstall node\n");
/* Fill up Q element */
ilptr->next = (struct inst_later *)NULL;
ilptr->hw = hw_vhdl ;
ilptr->loc = loc_vhdl ;
ilptr->install = install;
/* Add to Q */
if (!instnext.head) {
instnext.head = instnext.tail = ilptr;
}
else {
instnext.tail->next = ilptr;
instnext.tail = ilptr;
#if 0
/* This will register devices in the order received.
This had to be changed to let qlogics install in the
reverse order received. BUG 376780
*/
ilptr->next = instnext.head ;
instnext.head = ilptr ;
#endif
}
}
int
pg_setup_bridge_alias()
{
graph_error_t graph_err ;
vertex_hdl_t xwidget_vhdl, pci_vhdl = GRAPH_VERTEX_NONE,
next_vhdl ;
graph_edge_place_t eplace = GRAPH_EDGE_PLACE_NONE ;
char *remain ;
char widget_name[64] ;
char tmp_buf[32] ;
int ab_num = 1, dm_num = 2, dm_tmp = 0 ;
int bridge_found = 0, i ;
lboard_t *brd_ptr ;
/* Lookup "/xwidget" */
graph_err = hwgraph_path_lookup(hw_vertex_hdl, EDGE_LBL_ROOT_XWIDGET,
&xwidget_vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("pg_setup_bridge_alias: Cannot find edge /xwidget %d\n",
graph_err) ;
return 0 ;
}
do {
graph_err = graph_edge_get_next(prom_graph_hdl,
xwidget_vhdl,
widget_name,
&next_vhdl, &eplace) ;
if (graph_err != GRAPH_SUCCESS) {
break ;
}
/* For all edges that begin with "bridge" */
if (strncmp(widget_name, "bridge", 6))
continue ;
graph_err = graph_info_get_LBL(prom_graph_hdl, next_vhdl,
INFO_LBL_BRD_INFO, NULL,
(arbitrary_info_t *)&brd_ptr) ;
if (graph_err != GRAPH_SUCCESS) {
printf("pg_setup_bridge_alias: Cannot find brdinfo %d\n",
graph_err) ;
return 0 ;
}
/* for all baseio boards */
if (brd_ptr->brd_flags & GLOBAL_MASTER_IO6) {
/* Setup an edge "alias_bridge0" */
graph_err = graph_edge_add(prom_graph_hdl,
xwidget_vhdl,
next_vhdl ,
"alias_bridge0") ;
if (graph_err != GRAPH_SUCCESS) {
printf("alias_bridge0 edge add err %d\n",
graph_err) ;
return 0 ;
}
dksc_map[0] = dksc_map[1] = 0 ;
dm_tmp = 0 ;
}
else { /* BASEIO or MSCSI or MENET */
sprintf(tmp_buf, "alias_bridge%d", ab_num) ;
graph_err = graph_edge_add(prom_graph_hdl,
xwidget_vhdl,
next_vhdl ,
tmp_buf) ;
if (graph_err != GRAPH_SUCCESS) {
printf("%s edge add err %d\n", tmp_buf, graph_err) ;
return 0 ;
}
if (brd_ptr->brd_type == KLTYPE_MSCSI) {
for (i=0; i<4; i++)
dksc_map[dm_num+i] = ab_num ;
dm_tmp = dm_num ;
dm_num += 4 ;
}
else
if (brd_ptr->brd_type == KLTYPE_BASEIO) {
for (i=0; i<2; i++)
dksc_map[dm_num+i] = ab_num ;
dm_tmp = dm_num ;
dm_num += 2 ;
}
ab_num++ ;
}
if ((brd_ptr->brd_type == KLTYPE_4CHSCSI) ||
(brd_ptr->brd_type == KLTYPE_BASEIO)) {
graph_err = hwgraph_path_lookup(next_vhdl, "pci",
&pci_vhdl, &remain) ;
if (graph_err != GRAPH_SUCCESS) {
printf("pg_setup_bridge_alias: pci-slot not found %d\n",
graph_err) ;
return 0 ;
}
/* XXX Call this routine only for the master io6 */
pg_setup_compt_alias(pci_vhdl,
brd_ptr, dm_tmp) ;
}
} while (graph_err == GRAPH_SUCCESS) ;
return 1 ;
}
int
pg_setup_compt_alias(vertex_hdl_t bvh, lboard_t *lb, int map_ind)
{
graph_error_t graph_err ;
vertex_hdl_t next_vhdl ;
graph_edge_place_t eplace = GRAPH_EDGE_PLACE_NONE ;
char *remain, *name ;
char widget_name[64], buf[32] ;
int master_ioc3_found = 0 ;
prom_dev_info_t *arbinf_ptr ;
extern int symmon;
do {
graph_err = graph_edge_get_next(prom_graph_hdl,
bvh,
widget_name,
&next_vhdl, &eplace) ;
if (graph_err != GRAPH_SUCCESS) {
break ;
}
/* Skip duplicate edges */
if (!strncmp(widget_name, "alias", 5) ||
!strncmp(widget_name, "master", 6))
continue ;
graph_err = graph_info_get_LBL(prom_graph_hdl, next_vhdl,
INFO_LBL_DEV_INFO, NULL,
(arbitrary_info_t *)&arbinf_ptr) ;
/* we may not find prom_dev_info for disabled controllers */
/* continue if we don't */
if (graph_err != GRAPH_SUCCESS) {
graph_err = GRAPH_SUCCESS;
continue ;
}
switch (((klinfo_t *)(arbinf_ptr->kl_comp))->struct_type) {
case KLSTRUCT_IOC3 :
if (!master_ioc3_found) {
master_ioc3_found = 1 ;
name = EDGE_LBL_MASTER_IOC3 ;
}
else {
graph_err = GRAPH_SUCCESS;
continue ;
}
break ;
case KLSTRUCT_SCSI:
{
unsigned short vid ;
vid = ((klinfo_t *)
(arbinf_ptr->kl_comp))->virtid ;
sprintf(buf, "alias_ql%d", vid) ;
dksc_map[map_ind] |= (vid << 8) ;
dksc_inv_map[vid] = map_ind ;
map_ind++ ;
name = buf ;
}
break ;
default:
continue ;
/* NOTREACHED */
break ;
}
graph_err = graph_edge_add(prom_graph_hdl,
bvh,
next_vhdl,
name) ;
if (graph_err != GRAPH_SUCCESS) {
printf("%s edge add err %d\n", name, graph_err) ;
return 0 ;
}
} while (graph_err == GRAPH_SUCCESS) ;
if ((!master_ioc3_found) && (lb->brd_type == KLTYPE_BASEIO)) {
/* No ioc3 on an io6 */
return 0 ;
}
return 1 ;
}
#endif /* !SN_PDI */
#ifdef PG_DEBUG
static void
dump_graph_info(nasid_t nasid)
{
lboard_t *brd_ptr;
int i ;
klrou_t *klroup ;
brd_ptr = (lboard_t *)KL_CONFIG_INFO(nasid);
while (brd_ptr) {
if (brd_ptr->struct_type == REMOTE_BOARD) {
printf("Remote board in dump_graph_info: fixme\n");
}
else {
if (brd_ptr->brd_flags & DUPLICATE_BOARD)
;
else if (brd_ptr->brd_type == KLTYPE_ROUTER) {
klroup = (klrou_t *)NODE_OFFSET_TO_K1(
nasid, brd_ptr->brd_compts[0]);
for (i=1; i<=MAX_ROUTER_PORTS; i++)
printf(" %d -> %d %x \n", i,
klroup->rou_port[i].port_nasid,
klroup->rou_port[i].port_offset) ;
}
}
brd_ptr = KLCF_NEXT(brd_ptr);
}
}
#endif /* DEBUG */