Ejemplo n.º 1
0
vertex_hdl_t
pciio_device_info_register(
		vertex_hdl_t connectpt,		/* vertex at center of bus */
		pciio_info_t pciio_info)	/* details about the connectpt */
{
    char		name[32];
    vertex_hdl_t	pconn;
    int device_master_set(vertex_hdl_t, vertex_hdl_t);

    pciio_slot_func_to_name(name,
			    pciio_info->c_slot,
			    pciio_info->c_func);

    if (GRAPH_SUCCESS !=
	hwgraph_path_add(connectpt, name, &pconn))
	return pconn;

    pciio_info->c_vertex = pconn;
    pciio_info_set(pconn, pciio_info);
#ifdef DEBUG_PCIIO
    {
	int pos;
	char dname[256];
	pos = devfs_generate_path(pconn, dname, 256);
	printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]);
    }
#endif /* DEBUG_PCIIO */

    /*
     * create link to our pci provider
     */

    device_master_set(pconn, pciio_info->c_master);
    return pconn;
}
Ejemplo n.º 2
0
/* ARGSUSED */
static void __init
klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
{
        vertex_hdl_t my_cpu, cpu_dir;
        char name[120];
        cpuid_t cpu_id;
	nasid_t nasid;

	nasid = cnodeid_to_nasid(cnode);
        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);

        snprintf(name, 120, "%s/%d/%c",
                EDGE_LBL_CPUBUS,
                0,
                'a' + cpu->cpu_info.physid);

        (void) hwgraph_path_add(node_vertex, name, &my_cpu);

	HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n");

	mark_cpuvertex_as_cpu(my_cpu, cpu_id);
        device_master_set(my_cpu, node_vertex);

        /* Add an alias under the node's CPU directory */
        if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
                snprintf(name, 120, "%c", 'a' + cpu->cpu_info.physid);
                (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
		HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name);
        }
}
Ejemplo n.º 3
0
devfs_handle_t
pciio_device_info_register(
    devfs_handle_t connectpt,		/* vertex at center of bus */
    pciio_info_t pciio_info)	/* details about the connectpt */
{
    char		name[32];
    devfs_handle_t	pconn;

    pciio_slot_func_to_name(name,
                            pciio_info->c_slot,
                            pciio_info->c_func);

    if (GRAPH_SUCCESS !=
            hwgraph_path_add(connectpt, name, &pconn))
        return pconn;

    pciio_info->c_vertex = pconn;
    pciio_info_set(pconn, pciio_info);
#ifdef BRINGUP
    {
        int pos;
        char dname[256];
        pos = devfs_generate_path(pconn, dname, 256);
#ifdef DEBUG_PCIIO
        printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]);
#endif
    }
#endif /* BRINGUP */

    /*
     * create link to our pci provider
     */

    device_master_set(pconn, pciio_info->c_master);

#if USRPCI
    /*
     * Call into usrpci provider to let it initialize for
     * the given slot.
     */
    if (pciio_info->c_slot != PCIIO_SLOT_NONE)
        usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot);
#endif

    return pconn;
}
Ejemplo n.º 4
0
/*
 * xwidget_register:
 *	Register a xtalk device (xwidget) by doing the following.
 *      -allocate and initialize xwidget_info data
 *      -allocate a hwgraph vertex with name based on widget number (id)
 *      -look up the widget's initialization function and call it,
 *      or remember the vertex for later initialization.
 *
 */
int
xwidget_register(xwidget_hwid_t hwid,		/* widget's hardware ID */
		 vertex_hdl_t 	widget,		/* widget to initialize */
		 xwidgetnum_t 	id,		/* widget's target id (0..f) */
		 vertex_hdl_t 	master,		/* widget's master vertex */
		 xwidgetnum_t 	targetid)	/* master's target id (9/a) */
{			
    xwidget_info_t          widget_info;
    char		    *s,devnm[MAXDEVNAME];

    /* Allocate widget_info and associate it with widget vertex */
    NEW(widget_info);

    /* Initialize widget_info */
    widget_info->w_vertex = widget;
    widget_info->w_id = id;
    widget_info->w_master = master;
    widget_info->w_masterid = targetid;
    widget_info->w_hwid = *hwid;	/* structure copy */
    widget_info->w_efunc = 0;
    widget_info->w_einfo = 0;
    /*
     * get the name of this xwidget vertex and keep the info.
     * This is needed during errors and interupts, but as
     * long as we have it, we can use it elsewhere.
     */
    s = dev_to_name(widget,devnm,MAXDEVNAME);
    widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
    strcpy(widget_info->w_name,s);
    
    xwidget_info_set(widget, widget_info);

    device_master_set(widget, master);

    /* 
     * Add pointer to async attach info -- tear down will be done when
     * the particular descendant is done with the info.
     */
    return cdl_add_connpt(hwid->part_num, hwid->mfg_num,
                          widget, 0);
}
Ejemplo n.º 5
0
/* ARGSUSED */
static void __init
klhwg_add_disabled_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
{
        vertex_hdl_t my_cpu;
        char name[120];
        cpuid_t cpu_id;
	nasid_t nasid;

	nasid = cnodeid_to_nasid(cnode);
        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
        if(cpu_id != -1){
		snprintf(name, 120, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
		(void) hwgraph_path_add(node_vertex, name, &my_cpu);

		HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for disabled cpu slice.\n");

		mark_cpuvertex_as_cpu(my_cpu, cpu_id);
		device_master_set(my_cpu, node_vertex);
		return;
        }
}
Ejemplo n.º 6
0
/* ARGSUSED */
static void __init
klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
{
	vertex_hdl_t myhubv;
	vertex_hdl_t hub_mon;
	int rc;
	extern struct file_operations shub_mon_fops;

	hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);

	HWGRAPH_DEBUG(__FILE__, __FUNCTION__,__LINE__, myhubv, NULL, "Created path for hub vertex for Shub node.\n");

	rc = device_master_set(myhubv, node_vertex);
	if (rc) {
		printk("klhwg_add_hub: Unable to create hub vertex.\n");
		return;
	}
	hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
		0, 0, 0, 0,
		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
		&shub_mon_fops, (void *)(long)cnode);
}
Ejemplo n.º 7
0
/*
 * Initialize all I/O on the specified node.
 */
static void
io_init_node(cnodeid_t cnodeid)
{
	/*REFERENCED*/
	vertex_hdl_t hubv, switchv, widgetv;
	struct xwidget_hwid_s hwid;
	hubinfo_t hubinfo;
	int is_xswitch;
	nodepda_t	*npdap;
	struct semaphore *peer_sema = 0;
	uint32_t	widget_partnum;
	cpuid_t	c = 0;

	npdap = NODEPDA(cnodeid);

	/*
	 * Get the "top" vertex for this node's hardware
	 * graph; it will carry the per-hub hub-specific
	 * data, and act as the crosstalk provider master.
	 * It's canonical path is probably something of the
	 * form /hw/module/%M/slot/%d/node
	 */
	hubv = cnodeid_to_vertex(cnodeid);
	DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap);

	ASSERT(hubv != GRAPH_VERTEX_NONE);

	/*
	 * Read mfg info on this hub
	 */

	/* 
	 * If nothing connected to this hub's xtalk port, we're done.
	 */
	early_probe_for_widget(hubv, &hwid);
	if (hwid.part_num == XWIDGET_PART_NUM_NONE) {
#ifdef PROBE_TEST
		if ((cnodeid == 1) || (cnodeid == 2)) {
			int index;

			for (index = 0; index < 600; index++)
				DBG("Interfering with device probing!!!\n");
		}
#endif
		/* io_init_done takes cpu cookie as 2nd argument 
		 * to do a restorenoderun for the setnoderun done 
		 * at the start of this thread 
		 */
		
		DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);
		return;
		/* NOTREACHED */
	}

	/* 
	 * attach our hub_provider information to hubv,
	 * so we can use it as a crosstalk provider "master"
	 * vertex.
	 */
	xtalk_provider_register(hubv, &hub_provider);
	xtalk_provider_startup(hubv);

	/*
	 * Create a vertex to represent the crosstalk bus
	 * attached to this hub, and a vertex to be used
	 * as the connect point for whatever is out there
	 * on the other side of our crosstalk connection.
	 *
	 * Crosstalk Switch drivers "climb up" from their
	 * connection point to try and take over the switch
	 * point.
	 *
	 * Of course, the edges and verticies may already
	 * exist, in which case our net effect is just to
	 * associate the "xtalk_" driver with the connection
	 * point for the device.
	 */

	(void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv);

	DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv);

	ASSERT(switchv != GRAPH_VERTEX_NONE);

	(void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO);

	DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n");

	/*
	 * We need to find the widget id and update the basew_id field
	 * accordingly. In particular, SN00 has direct connected bridge,
	 * and hence widget id is Not 0.
	 */

	widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT;

	if (widget_partnum == BRIDGE_WIDGET_PART_NUM ||
				widget_partnum == XBRIDGE_WIDGET_PART_NUM){
		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);

		DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum);

	} else if ((widget_partnum == XBOW_WIDGET_PART_NUM) ||
			(widget_partnum == XXBOW_WIDGET_PART_NUM) ||
			(widget_partnum == PXBOW_WIDGET_PART_NUM) ) {
		/* 
		 * Xbow control register does not have the widget ID field.
		 * So, hard code the widget ID to be zero.
		 */
		DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum);
		npdap->basew_id = 0;

	} else {
		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);

		panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv);

		/*NOTREACHED*/
	}
	{
		char widname[10];
		sprintf(widname, "%x", npdap->basew_id);
		(void)hwgraph_path_add(switchv, widname, &widgetv);
		DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv);
		ASSERT(widgetv != GRAPH_VERTEX_NONE);
	}
	
	nodepda->basew_xc = widgetv;

	is_xswitch = xwidget_hwid_is_xswitch(&hwid);

	/* 
	 * Try to become the master of the widget.  If this is an xswitch
	 * with multiple hubs connected, only one will succeed.  Mastership
	 * of an xswitch is used only when touching registers on that xswitch.
	 * The slave xwidgets connected to the xswitch can be owned by various
	 * masters.
	 */
	if (device_master_set(widgetv, hubv) == 0) {

		/* Only one hub (thread) per Crosstalk device or switch makes
		 * it to here.
		 */

		/* 
		 * Initialize whatever xwidget is hanging off our hub.
		 * Whatever it is, it's accessible through widgetnum 0.
		 */
		hubinfo_get(hubv, &hubinfo);

		(void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid);

		if (!is_xswitch) {
			/* io_init_done takes cpu cookie as 2nd argument 
			 * to do a restorenoderun for the setnoderun done 
			 * at the start of this thread 
			 */
			io_init_done(cnodeid,c);
			/* NOTREACHED */
		}

		/* 
		 * Special handling for Crosstalk Switches (e.g. xbow).
		 * We need to do things in roughly the following order:
		 *	1) Initialize xswitch hardware (done above)
		 *	2) Determine which hubs are available to be widget masters
		 *	3) Discover which links are active from the xswitch
		 *	4) Assign xwidgets hanging off the xswitch to hubs
		 *	5) Initialize all xwidgets on the xswitch
		 */

		DBG("call volunteer_for_widgets\n");

		volunteer_for_widgets(switchv, hubv);

		/* If there's someone else on this crossbow, recognize him */
		if (npdap->xbow_peer != INVALID_NASID) {
			nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer));
			peer_sema = &peer_npdap->xbow_sema;
			DBG("call volunteer_for_widgets again\n");
			volunteer_for_widgets(switchv, peer_npdap->node_vertex);
		}

		assign_widgets_to_volunteers(switchv, hubv);

		/* Signal that we're done */
		if (peer_sema) {
			up(peer_sema);
		}
		
	}
	else {
	    /* Wait 'til master is done assigning widgets. */
	    down(&npdap->xbow_sema);
	}

#ifdef PROBE_TEST
	if ((cnodeid == 1) || (cnodeid == 2)) {
		int index;

		for (index = 0; index < 500; index++)
			DBG("Interfering with device probing!!!\n");
	}
#endif
	/* Now both nodes can safely inititialize widgets */
	io_init_xswitch_widgets(switchv, cnodeid);
	io_link_xswitch_widgets(switchv, cnodeid);

	/* io_init_done takes cpu cookie as 2nd argument 
	 * to do a restorenoderun for the setnoderun done 
	 * at the start of this thread 
	 */
	io_init_done(cnodeid,c);

	DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);
}
Ejemplo n.º 8
0
void
io_xswitch_widget_init(vertex_hdl_t  	xswitchv,
		       vertex_hdl_t	hubv,
		       xwidgetnum_t	widgetnum)
{
	xswitch_info_t		xswitch_info;
	xwidgetnum_t		hub_widgetid;
	vertex_hdl_t		widgetv;
	cnodeid_t		cnode;
	widgetreg_t		widget_id;
	nasid_t			nasid, peer_nasid;
	struct xwidget_hwid_s 	hwid;
	hubinfo_t		hubinfo;
	/*REFERENCED*/
	int			rc;
	char 			pathname[128];
	lboard_t		*board = NULL;
	char			buffer[16];
	char			bt;
	moduleid_t		io_module;
	slotid_t get_widget_slotnum(int xbow, int widget);
	
	DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);

	/*
	 * Verify that xswitchv is indeed an attached xswitch.
	 */
	xswitch_info = xswitch_info_get(xswitchv);
	ASSERT(xswitch_info != NULL);

	hubinfo_get(hubv, &hubinfo);
	nasid = hubinfo->h_nasid;
	cnode = NASID_TO_COMPACT_NODEID(nasid);
	hub_widgetid = hubinfo->h_widgetid;

	/*
	 * Check that the widget is an io widget and is enabled
	 * on this nasid or the `peer' nasid.  The peer nasid
	 * is the other hub/bedrock connected to the xbow.
	 */
	peer_nasid = NODEPDA(cnode)->xbow_peer;
	if (peer_nasid == INVALID_NASID)
		/* If I don't have a peer, use myself. */
		peer_nasid = nasid;
	if (!xbow_port_io_enabled(nasid, widgetnum) &&
	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {
		return;
	}

	if (xswitch_info_link_ok(xswitch_info, widgetnum)) {
		char			name[4];
		lboard_t dummy;


		/*
		 * If the current hub is not supposed to be the master 
		 * for this widgetnum, then skip this widget.
		 */

		if (xswitch_info_master_assignment_get(xswitch_info, widgetnum) != hubv) {
			return;
		}

		board = find_lboard_class(
				(lboard_t *)KL_CONFIG_INFO(nasid),
				KLCLASS_IOBRICK);
		if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) {
		    	board = find_lboard_class(
					(lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer),
						KLCLASS_IOBRICK);
		}

		if (board) {
			DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
		} else {
			DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");
			board = &dummy;
		}


		/* Copy over the nodes' geoid info */
		{
			lboard_t *brd;

			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
			if ( brd != (lboard_t *)0 ) {
				board->brd_geoid = brd->brd_geoid;
			}
		}

		/*
 		 * Make sure we really want to say xbrick, pbrick,
		 * etc. rather than XIO, graphics, etc.
 		 */

		memset(buffer, 0, 16);
		format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);

		sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%s" "/%s/%d",
			buffer,
			geo_slab(board->brd_geoid),
			(board->brd_type == KLTYPE_IBRICK) ? EDGE_LBL_IBRICK :
			(board->brd_type == KLTYPE_PBRICK) ? EDGE_LBL_PBRICK :
			(board->brd_type == KLTYPE_PXBRICK) ? EDGE_LBL_PXBRICK :
			(board->brd_type == KLTYPE_IXBRICK) ? EDGE_LBL_IXBRICK :
			(board->brd_type == KLTYPE_CGBRICK) ? EDGE_LBL_CGBRICK :
			(board->brd_type == KLTYPE_OPUSBRICK) ? EDGE_LBL_OPUSBRICK :
			(board->brd_type == KLTYPE_XBRICK) ? EDGE_LBL_XBRICK : "?brick",
			EDGE_LBL_XTALK, widgetnum);
		
		DBG("io_xswitch_widget_init: path= %s\n", pathname);
		rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
		
		ASSERT(rc == GRAPH_SUCCESS);

		/* This is needed to let the user programs to map the
		 * module,slot numbers to the corresponding widget numbers
		 * on the crossbow.
		 */
		device_master_set(hwgraph_connectpt_get(widgetv), hubv);
		sprintf(name, "%d", widgetnum);
		DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
		rc = hwgraph_edge_add(xswitchv, widgetv, name);
		
		/*
		 * crosstalk switch code tracks which
		 * widget is attached to each link.
		 */
		xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv);
		
		/*
		 * Peek at the widget to get its crosstalk part and
		 * mfgr numbers, then present it to the generic xtalk
		 * bus provider to have its driver attach routine
		 * called (or not).
		 */
		widget_id = XWIDGET_ID_READ(nasid, widgetnum);
		hwid.part_num = XWIDGET_PART_NUM(widget_id);
		hwid.rev_num = XWIDGET_REV_NUM(widget_id);
		hwid.mfg_num = XWIDGET_MFG_NUM(widget_id);
		/* Store some inventory information about
		 * the xwidget in the hardware graph.
		 */
		xwidget_inventory_add(widgetv,board,hwid);

		(void)xwidget_register(&hwid, widgetv, widgetnum,
				       hubv, hub_widgetid);

		ia64_sn_sysctl_iobrick_module_get(nasid, &io_module);
		if (io_module >= 0) {
			char			buffer[16];
			vertex_hdl_t		to, from;
			char           		*brick_name;
			extern char *iobrick_L1bricktype_to_name(int type);


			memset(buffer, 0, 16);
			format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);

			if ( isupper(MODULE_GET_BTCHAR(io_module)) ) {
				bt = tolower(MODULE_GET_BTCHAR(io_module));
			}
			else {
				bt = MODULE_GET_BTCHAR(io_module);
			}

			brick_name = iobrick_L1bricktype_to_name(bt);

			/* Add a helper vertex so xbow monitoring
			* can identify the brick type. It's simply
			* an edge from the widget 0 vertex to the
			*  brick vertex.
			*/

			sprintf(pathname, EDGE_LBL_HW "/" EDGE_LBL_MODULE "/%s/"
				EDGE_LBL_SLAB "/%d/"
				EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/"
				"0",
				buffer, geo_slab(board->brd_geoid));
			DBG("io_xswitch_widget_init: FROM path '%s'\n", pathname);

			from = hwgraph_path_to_vertex(pathname);
			ASSERT_ALWAYS(from);

			sprintf(pathname, EDGE_LBL_HW "/" EDGE_LBL_MODULE "/%s/"
				EDGE_LBL_SLAB "/%d/"
				"%s",
				buffer, geo_slab(board->brd_geoid), brick_name);
			DBG("io_xswitch_widget_init: TO path '%s'\n", pathname);
			to = hwgraph_path_to_vertex(pathname);
			ASSERT_ALWAYS(to);
			rc = hwgraph_edge_add(from, to,
				EDGE_LBL_INTERCONNECT);
			if (rc == -EEXIST)
				goto link_done;
			if (rc != GRAPH_SUCCESS) {
				printk("%s: Unable to establish link"
					" for xbmon.", pathname);
			}
link_done:
		}

#ifdef	SN0_USE_BTE
		bte_bpush_war(cnode, (void *)board);
#endif
	}
}
Ejemplo n.º 9
0
void
io_xswitch_widget_init(devfs_handle_t  	xswitchv,
		       devfs_handle_t	hubv,
		       xwidgetnum_t	widgetnum,
		       async_attach_t	aa)
{
	xswitch_info_t		xswitch_info;
	xwidgetnum_t		hub_widgetid;
	devfs_handle_t		widgetv;
	cnodeid_t		cnode;
	widgetreg_t		widget_id;
	nasid_t			nasid, peer_nasid;
	struct xwidget_hwid_s 	hwid;
	hubinfo_t		hubinfo;
	/*REFERENCED*/
	int			rc;
	char 			pathname[128];
	char			new_name[64];
	moduleid_t		module;
	slotid_t		slot;
	lboard_t		*board = NULL;
	char			buffer[16];
	slotid_t get_widget_slotnum(int xbow, int widget);
	
	DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);

	/*
	 * Verify that xswitchv is indeed an attached xswitch.
	 */
	xswitch_info = xswitch_info_get(xswitchv);
	ASSERT(xswitch_info != NULL);

	hubinfo_get(hubv, &hubinfo);
	nasid = hubinfo->h_nasid;
	cnode = NASID_TO_COMPACT_NODEID(nasid);
	hub_widgetid = hubinfo->h_widgetid;

	/*
	 * Check that the widget is an io widget and is enabled
	 * on this nasid or the `peer' nasid.  The peer nasid
	 * is the other hub/bedrock connected to the xbow.
	 */
	peer_nasid = NODEPDA(cnode)->xbow_peer;
	if (peer_nasid == INVALID_NASID)
		/* If I don't have a peer, use myself. */
		peer_nasid = nasid;
	if (!xbow_port_io_enabled(nasid, widgetnum) &&
	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {
		return;
	}

	if (xswitch_info_link_ok(xswitch_info, widgetnum)) {
		char			name[4];

		/*
		 * If the current hub is not supposed to be the master 
		 * for this widgetnum, then skip this widget.
		 */
		if (xswitch_info_master_assignment_get(xswitch_info,
						       widgetnum) != hubv) {
			return;
		}

		module  = NODEPDA(cnode)->module_id;
#ifdef XBRIDGE_REGS_SIM
		/* hardwire for now...could do this with something like:
		 * xbow_soft_t soft = hwgraph_fastinfo_get(vhdl);
		 * xbow_t xbow = soft->base;
		 * xbowreg_t xwidget_id = xbow->xb_wid_id;
		 * but I don't feel like figuring out vhdl right now..
		 * and I know for a fact the answer is 0x2d000049 
		 */
		DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
		DBG("XWIDGET_PART_NUM(0x2d000049)= 0x%x\n", XWIDGET_PART_NUM(0x2d000049));
		if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM)
#else
		if (nasid_has_xbridge(nasid))
#endif /* XBRIDGE_REGS_SIM */
		{
			board = find_lboard_module_class(
				(lboard_t *)KL_CONFIG_INFO(nasid),
				module,
				KLTYPE_IOBRICK);

DBG("io_xswitch_widget_init: Board 0x%p\n", board);
{
		lboard_t dummy;


			if (board) {
				DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
			} else {
				DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");
				board = &dummy;
			}
				
}

			/*
	 		 * Make sure we really want to say xbrick, pbrick,
			 * etc. rather than XIO, graphics, etc.
	 		 */

#ifdef SUPPORT_PRINTING_M_FORMAT
			sprintf(pathname, EDGE_LBL_MODULE "/%M/"
				"%cbrick" "/%s/%d",
				NODEPDA(cnode)->module_id,
				
#else
			memset(buffer, 0, 16);
			format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
			sprintf(pathname, EDGE_LBL_MODULE "/%s/"
				"%cbrick" "/%s/%d",
				buffer,
#endif

				(board->brd_type == KLTYPE_IBRICK) ? 'I' :
				(board->brd_type == KLTYPE_PBRICK) ? 'P' :
				(board->brd_type == KLTYPE_XBRICK) ? 'X' : '?',
				EDGE_LBL_XTALK, widgetnum);
		} 
		
		DBG("io_xswitch_widget_init: path= %s\n", pathname);
		rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
		
		ASSERT(rc == GRAPH_SUCCESS);

		/* This is needed to let the user programs to map the
		 * module,slot numbers to the corresponding widget numbers
		 * on the crossbow.
		 */
		rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv);

		/* If we are looking at the global master io6
		 * then add information about the version of
		 * the io6prom as a part of "detailed inventory"
		 * information.
		 */
		if (is_master_baseio(nasid,
				     NODEPDA(cnode)->module_id,
 				     get_widget_slotnum(0,widgetnum))) {
			extern void klhwg_baseio_inventory_add(devfs_handle_t,
							       cnodeid_t);
			module 	= NODEPDA(cnode)->module_id;

#ifdef XBRIDGE_REGS_SIM
			DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
			if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM)
#else
			if (nasid_has_xbridge(nasid))
#endif /* XBRIDGE_REGS_SIM */
			{
				board = find_lboard_module(
					(lboard_t *)KL_CONFIG_INFO(nasid),
					module);
				/*
				 * Change iobrick to correct i/o brick
				 */
#ifdef SUPPORT_PRINTING_M_FORMAT
				sprintf(pathname, EDGE_LBL_MODULE "/%M/"
#else
				sprintf(pathname, EDGE_LBL_MODULE "/%x/"
#endif
					"iobrick" "/%s/%d",
					NODEPDA(cnode)->module_id,
					EDGE_LBL_XTALK, widgetnum);
			} else {
				slot = get_widget_slotnum(0, widgetnum);
				board = get_board_name(nasid, module, slot,
								new_name);
				/*
			 	 * Create the vertex for the widget, 
				 * using the decimal 
			 	 * widgetnum as the name of the primary edge.
			 	 */
#ifdef SUPPORT_PRINTING_M_FORMAT
				sprintf(pathname, EDGE_LBL_MODULE "/%M/"
                                                EDGE_LBL_SLOT "/%s",
                                        NODEPDA(cnode)->module_id,
                                        new_name);
#else
				memset(buffer, 0, 16);
				format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
				sprintf(pathname, EDGE_LBL_MODULE "/%s/"
					  	EDGE_LBL_SLOT "/%s",
					buffer,
					new_name);
#endif
			}

			rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
			DBG("io_xswitch_widget_init: (2) path= %s\n", pathname);
		        /*
		         * This is a weird ass code needed for error injection
		         * purposes.
		         */
		        rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv);
			
			klhwg_baseio_inventory_add(widgetv,cnode);
		}
		sprintf(name, "%d", widgetnum);
		DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
		rc = hwgraph_edge_add(xswitchv, widgetv, name);
		
		/*
		 * crosstalk switch code tracks which
		 * widget is attached to each link.
		 */
		xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv);
		
		/*
		 * Peek at the widget to get its crosstalk part and
		 * mfgr numbers, then present it to the generic xtalk
		 * bus provider to have its driver attach routine
		 * called (or not).
		 */
#ifdef XBRIDGE_REGS_SIM
		widget_id = 0x2d000049;
		DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_id\n");
#else
		widget_id = XWIDGET_ID_READ(nasid, widgetnum);
#endif /* XBRIDGE_REGS_SIM */
		hwid.part_num = XWIDGET_PART_NUM(widget_id);
		hwid.rev_num = XWIDGET_REV_NUM(widget_id);
		hwid.mfg_num = XWIDGET_MFG_NUM(widget_id);
		/* Store some inventory information about
		 * the xwidget in the hardware graph.
		 */
		xwidget_inventory_add(widgetv,board,hwid);
		
		(void)xwidget_register(&hwid, widgetv, widgetnum,
				       hubv, hub_widgetid,
				       aa);

#ifdef	SN0_USE_BTE
		bte_bpush_war(cnode, (void *)board);
#endif
	}
Ejemplo n.º 10
0
/*
 * If this PIC is attached to two Cbricks ("dual-ported") then
 * attach each bus to opposite Cbricks.
 *
 * If successful, return a new vertex suitable for attaching the PIC bus.
 * If not successful, return zero and both buses will attach to the
 * vertex passed into pic_attach().
 */
static vertex_hdl_t
pic_bus1_redist(nasid_t nasid, vertex_hdl_t conn_v)
{
	cnodeid_t cnode = nasid_to_cnodeid(nasid);
	cnodeid_t xbow_peer = -1;
	char pathname[256], peer_path[256], tmpbuf[256];
	char *p;
	int rc;
	vertex_hdl_t peer_conn_v, hubv;
	int pos;
	slabid_t slab;

	if (NODEPDA(cnode)->xbow_peer >= 0) {			/* if dual-ported */
		/* create a path for this widget on the peer Cbrick */
		/* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */
		/* sprintf(pathname, "%v", conn_v); */
		xbow_peer = nasid_to_cnodeid(NODEPDA(cnode)->xbow_peer);
		pos = hwgfs_generate_path(conn_v, tmpbuf, 256);
		strcpy(pathname, &tmpbuf[pos]);
		p = pathname + strlen("hw/module/001c01/slab/0/");

		memset(tmpbuf, 0, 16);
		format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF);
		slab = geo_slab((NODEPDA(xbow_peer))->geoid);
		sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); 
		
		/* Look for vertex for this widget on the peer Cbrick.
		 * Expect GRAPH_NOT_FOUND.
		 */
		rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v);
		if (GRAPH_SUCCESS == rc)
			printk("pic_attach: found unexpected vertex: 0x%lx\n",
								(uint64_t)peer_conn_v);
		else if (GRAPH_NOT_FOUND != rc) {
			printk("pic_attach: hwgraph_traverse unexpectedly"
					" returned 0x%x\n", rc);
		} else {
			/* try to add the widget vertex to the peer Cbrick */
			rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v);

			if (GRAPH_SUCCESS != rc)
			    printk("pic_attach: hwgraph_path_add"
						" failed with 0x%x\n", rc);
			else {
			    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
					"pic_bus1_redist: added vertex %v\n", peer_conn_v)); 

			    /* Now hang appropiate stuff off of the new
			     * vertex.	We bail out if we cannot add something.
			     * In that case, we don't remove the newly added
			     * vertex but that should be safe and we don't
			     * really expect the additions to fail anyway.
			     */
			    if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, 
							  xbow_peer, peer_path))
					return 0;

			    hubv = cnodeid_to_vertex(xbow_peer);
			    ASSERT(hubv != GRAPH_VERTEX_NONE);
			    device_master_set(peer_conn_v, hubv);
			    xtalk_provider_register(hubv, &hub_provider);
			    xtalk_provider_startup(hubv);
			    return peer_conn_v;
			}
		}
	}
	return 0;
}