ml_iograph.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 771 行 · 第 1/2 页

C
771
字号
			(board->brd_type == KLTYPE_OPUSBRICK) ? EDGE_LBL_OPUSBRICK : "?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);		(void)xwidget_register(&hwid, widgetv, widgetnum,				       hubv, hub_widgetid);		io_module = iomoduleid_get(nasid);		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));			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);			to = hwgraph_path_to_vertex(pathname);			ASSERT_ALWAYS(to);			rc = hwgraph_edge_add(from, to,				EDGE_LBL_INTERCONNECT);			if (rc != -EEXIST && rc != GRAPH_SUCCESS) {				printk("%s: Unable to establish link"					" for xbmon.", pathname);			}		}	}}static voidio_init_xswitch_widgets(vertex_hdl_t xswitchv, cnodeid_t cnode){	xwidgetnum_t		widgetnum;		DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 	     widgetnum++) {		io_xswitch_widget_init(xswitchv,				       cnodeid_to_vertex(cnode),				       widgetnum);	}}/* * Initialize all I/O on the specified node. */static voidio_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;	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);	/* 	 * 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);	/* 	 * 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) {		DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);		return;		/* NOTREACHED */	}	/*	 * 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			(cnodeid_to_nasid(cnodeid), 0) + 			WIDGET_ID))) & WIDGET_PART_NUM) 			>> WIDGET_PART_NUM_SHFT;	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 {		void	*bridge;		bridge = (void *)NODE_SWIN_BASE(cnodeid_to_nasid(cnodeid), 0);		npdap->basew_id = pcireg_bridge_control_get(bridge) & WIDGET_WIDGET_ID;		printk(" ****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);		return;	}	{		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);		/* 		 * 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		 */		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_cnodeid(npdap->xbow_peer));			peer_sema = &peer_npdap->xbow_sema;			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);	}	/* Now both nodes can safely inititialize widgets */	io_init_xswitch_widgets(switchv, cnodeid);	DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);}#include <asm/sn/ioerror_handling.h>/* * Initialize all I/O devices.  Starting closest to nodes, probe and * initialize outward. */voidinit_all_devices(void){	cnodeid_t cnodeid, active;	active = 0;	for (cnodeid = 0; cnodeid < numionodes; cnodeid++) {                DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid);                io_init_node(cnodeid);		DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid);	}	for (cnodeid = 0; cnodeid < numnodes; cnodeid++) {		/*	 	 * Update information generated by IO init.		 */		update_node_information(cnodeid);	}}staticstruct io_brick_map_s io_brick_tab[] = {/* PXbrick widget number to PCI bus number map */ {      MODULE_PXBRICK,                         /* PXbrick type   */     /*  PCI Bus #                                  Widget #       */    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */        0,                                      /* 0x8            */        0,                                      /* 0x9            */        0, 0,                                   /* 0xa - 0xb      */        1,                                      /* 0xc            */        5,                                      /* 0xd            */        0,                                      /* 0xe            */        3                                       /* 0xf            */    } },/* OPUSbrick widget number to PCI bus number map */ {      MODULE_OPUSBRICK,                       /* OPUSbrick type */     /*  PCI Bus #                                  Widget #       */    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */        0,                                      /* 0x8            */        0,                                      /* 0x9            */        0, 0,                                   /* 0xa - 0xb      */        0,                                      /* 0xc            */        0,                                      /* 0xd            */        0,                                      /* 0xe            */        1                                       /* 0xf            */    } },/* IXbrick widget number to PCI bus number map */ {      MODULE_IXBRICK,                         /* IXbrick type   */     /*  PCI Bus #                                  Widget #       */    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */        0,                                      /* 0x8            */        0,                                      /* 0x9            */        0, 0,                                   /* 0xa - 0xb      */        1,                                      /* 0xc            */        5,                                      /* 0xd            */        0,                                      /* 0xe            */        3                                       /* 0xf            */    } },/* CG brick widget number to PCI bus number map */ {      MODULE_CGBRICK,				/* CG brick       */    /*  PCI Bus #                                  Widget #       */    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */        0,                                      /* 0x8            */        0,                                      /* 0x9            */        0, 1,                                   /* 0xa - 0xb      */        0,                                      /* 0xc            */        0,                                      /* 0xd            */        0,                                      /* 0xe            */        0                                       /* 0xf            */     } },};/* * Use the brick's type to map a widget number to a meaningful int */intio_brick_map_widget(int brick_type, int widget_num){        int num_bricks, i;        /* Calculate number of bricks in table */        num_bricks = sizeof(io_brick_tab)/sizeof(io_brick_tab[0]);        /* Look for brick prefix in table */        for (i = 0; i < num_bricks; i++) {               if (brick_type == io_brick_tab[i].ibm_type)                       return io_brick_tab[i].ibm_map_wid[widget_num];        }        return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?