⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ml_iograph.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <linux/ctype.h>#include <asm/sn/sgi.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/hcl_util.h>#include <asm/sn/labelcl.h>#include <asm/sn/xtalk/xbow.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/klconfig.h>#include <asm/sn/eeprom.h>#include <asm/sn/sn_private.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/xtalk/xtalk.h>#include <asm/sn/xtalk/xswitch.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/xtalk/xtalk_private.h>#include <asm/sn/xtalk/xtalkaddrs.h>extern int maxnodes;/* #define PROBE_TEST *//* At most 2 hubs can be connected to an xswitch */#define NUM_XSWITCH_VOLUNTEER 2/* * Track which hubs have volunteered to manage devices hanging off of * a Crosstalk Switch (e.g. xbow).  This structure is allocated, * initialized, and hung off the xswitch vertex early on when the * xswitch vertex is created. */typedef struct xswitch_vol_s {	struct semaphore xswitch_volunteer_mutex;	int		xswitch_volunteer_count;	devfs_handle_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];} *xswitch_vol_t;voidxswitch_vertex_init(devfs_handle_t xswitch){	xswitch_vol_t xvolinfo;	int rc;	xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);	init_MUTEX(&xvolinfo->xswitch_volunteer_mutex);	xvolinfo->xswitch_volunteer_count = 0;	rc = hwgraph_info_add_LBL(xswitch, 			INFO_LBL_XSWITCH_VOL,			(arbitrary_info_t)xvolinfo);	ASSERT(rc == GRAPH_SUCCESS); rc = rc;}/* * When assignment of hubs to widgets is complete, we no longer need the * xswitch volunteer structure hanging around.  Destroy it. */static voidxswitch_volunteer_delete(devfs_handle_t xswitch){	xswitch_vol_t xvolinfo;	int rc;	rc = hwgraph_info_remove_LBL(xswitch, 				INFO_LBL_XSWITCH_VOL,				(arbitrary_info_t *)&xvolinfo);#ifndef CONFIG_IA64_SGI_IO	ASSERT(rc == GRAPH_SUCCESS); rc = rc;#endif	kfree(xvolinfo);}/* * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. *//* ARGSUSED */static voidvolunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master){	xswitch_vol_t xvolinfo = NULL;	(void)hwgraph_info_get_LBL(xswitch, 				INFO_LBL_XSWITCH_VOL, 				(arbitrary_info_t *)&xvolinfo);	if (xvolinfo == NULL) {#ifndef CONFIG_IA64_SGI_IO	    if (!is_headless_node_vertex(master))		cmn_err(CE_WARN, 			"volunteer for widgets: vertex %v has no info label",			xswitch);#endif	    return;	}#ifndef CONFIG_IA64_SGI_IO	mutex_lock(&xvolinfo->xswitch_volunteer_mutex, PZERO);#endif	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;	xvolinfo->xswitch_volunteer_count++;#ifndef CONFIG_IA64_SGI_IO	mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);#endif}#ifndef	BRINGUP/*  * The "ideal fixed assignment" of 12 IO slots to 4 node slots. * At index N is the node slot number of the node board that should * ideally control the widget in IO slot N.  Note that if there is * only one node board on a given xbow, it will control all of the * devices on that xbow regardless of these defaults. * * 	N1 controls IO slots IO1, IO3, IO5	(upper left) * 	N3 controls IO slots IO2, IO4, IO6	(upper right) * 	N2 controls IO slots IO7, IO9, IO11	(lower left) * 	N4 controls IO slots IO8, IO10, IO12	(lower right) * * This makes assignments predictable and easily controllable. * TBD: Allow administrator to override these defaults. */static slotid_t ideal_assignment[] = {	-1,	/* IO0 -->non-existent */	1,	/* IO1 -->N1 */	3,	/* IO2 -->N3 */	1,	/* IO3 -->N1 */	3,	/* IO4 -->N3 */	1,	/* IO5 -->N1 */	3,	/* IO6 -->N3 */	2,	/* IO7 -->N2 */	4,	/* IO8 -->N4 */	2,	/* IO9 -->N2 */	4,	/* IO10-->N4 */	2,	/* IO11-->N2 */	4	/* IO12-->N4 */};static intis_ideal_assignment(slotid_t hubslot, slotid_t ioslot){	return(ideal_assignment[ioslot] == hubslot);}#endif /* ifndef BRINGUP */extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);/* * Assign all the xwidgets hanging off the specified xswitch to the * Crosstalk masters that have volunteered for xswitch duty. *//* ARGSUSED */static voidassign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv){	xswitch_info_t xswitch_info;	xswitch_vol_t xvolinfo = NULL;	xwidgetnum_t widgetnum;	int curr_volunteer, num_volunteer;	nasid_t nasid;	hubinfo_t hubinfo;#ifndef BRINGUP	int xbownum;#endif	hubinfo_get(hubv, &hubinfo);	nasid = hubinfo->h_nasid;		xswitch_info = xswitch_info_get(xswitch);	ASSERT(xswitch_info != NULL);	(void)hwgraph_info_get_LBL(xswitch, 				INFO_LBL_XSWITCH_VOL, 				(arbitrary_info_t *)&xvolinfo);	if (xvolinfo == NULL) {#ifndef CONFIG_IA64_SGI_IO	    if (!is_headless_node_vertex(hubv))		cmn_err(CE_WARN, 			"assign_widgets_to_volunteers:vertex %v has "			" no info label",			xswitch);#endif	    return;	}	num_volunteer = xvolinfo->xswitch_volunteer_count;	ASSERT(num_volunteer > 0);	curr_volunteer = 0;	/* Assign master hub for xswitch itself.  */	if (HUB_WIDGET_ID_MIN > 0) {		hubv = xvolinfo->xswitch_volunteer[0];		xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);	}#ifndef	BRINGUP	xbownum = get_node_crossbow(nasid);#endif /* ifndef BRINGUP */	/*	 * TBD: Use administrative information to alter assignment of	 * widgets to hubs.	 */	for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {#ifndef BRINGUP		int i;#endif		/*		 * Ignore disabled/empty ports.		 */		if (!xbow_port_io_enabled(nasid, widgetnum)) 		    continue;		/*		 * If this is the master IO board, assign it to the same 		 * hub that owned it in the prom.		 */		if (is_master_nasid_widget(nasid, widgetnum)) {			int i;			for (i=0; i<num_volunteer; i++) {				hubv = xvolinfo->xswitch_volunteer[i];				hubinfo_get(hubv, &hubinfo);				nasid = hubinfo->h_nasid;				if (nasid == get_console_nasid())					goto do_assignment;			}#ifndef CONFIG_IA64_SGI_IO			cmn_err(CE_PANIC,				"Nasid == %d, console nasid == %d",				nasid, get_console_nasid());#endif		}#ifndef	BRINGUP		/*		 * Try to do the "ideal" assignment if IO slots to nodes.		 */		for (i=0; i<num_volunteer; i++) {			hubv = xvolinfo->xswitch_volunteer[i];			hubinfo_get(hubv, &hubinfo);			nasid = hubinfo->h_nasid;			if (is_ideal_assignment(SLOTNUM_GETSLOT(get_node_slotid(nasid)),						SLOTNUM_GETSLOT(get_widget_slotnum(xbownum, widgetnum)))) {				goto do_assignment;							}		}#endif /* ifndef BRINGUP */		/*		 * Do a round-robin assignment among the volunteer nodes.		 */		hubv = xvolinfo->xswitch_volunteer[curr_volunteer];		curr_volunteer = (curr_volunteer + 1) % num_volunteer;		/* fall through */do_assignment:		/*		 * At this point, we want to make hubv the master of widgetnum.		 */		xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv);	}	xswitch_volunteer_delete(xswitch);}/* * Early iograph initialization.  Called by master CPU in mlreset(). * Useful for including iograph.o in kernel.o. */voidiograph_early_init(void){/* * Need new way to get this information .. */	cnodeid_t cnode;	nasid_t nasid;	lboard_t *board;	/*	 * Init. the board-to-hwgraph link early, so FRU analyzer	 * doesn't trip on leftover values if we panic early on.	 */	for(cnode = 0; cnode < numnodes; cnode++) {		nasid = COMPACT_TO_NASID_NODEID(cnode);		board = (lboard_t *)KL_CONFIG_INFO(nasid);		printk("iograph_early_init: Found board 0x%p\n", board);		/* Check out all the board info stored on a node */		while(board) {			board->brd_graph_link = GRAPH_VERTEX_NONE;			board = KLCF_NEXT(board);			printk("iograph_early_init: Found board 0x%p\n", board);		}	}	hubio_init();}#ifndef CONFIG_IA64_SGI_IO/* There is an identical definition of this in os/scheduler/runq.c */#define INIT_COOKIE(cookie) cookie.must_run = 0; cookie.cpu = PDA_RUNANYWHERE/* * These functions absolutely doesn't belong here.  It's  here, though,  * until the scheduler provides a platform-independent version * that works the way it should.  The interface will definitely change,  * too.  Currently used only in this file and by io/cdl.c in order to * bind various I/O threads to a CPU on the proper node. */cpu_cookie_tsetnoderun(cnodeid_t cnodeid){	int i;	cpuid_t cpunum;	cpu_cookie_t cookie;	INIT_COOKIE(cookie);	if (cnodeid == CNODEID_NONE)		return(cookie);	/*	 * Do a setmustrun to one of the CPUs on the specified	 * node.	 */	if ((cpunum = CNODE_TO_CPU_BASE(cnodeid)) == CPU_NONE) {		return(cookie);	}	cpunum += CNODE_NUM_CPUS(cnodeid) - 1;	for (i = 0; i < CNODE_NUM_CPUS(cnodeid); i++, cpunum--) {		if (cpu_enabled(cpunum)) {			cookie = setmustrun(cpunum);			break;		}	}	return(cookie);}voidrestorenoderun(cpu_cookie_t cookie){	restoremustrun(cookie);}static sema_t io_init_sema;#endif	/* !CONFIG_IA64_SGI_IO */struct semaphore io_init_sema;/* * Let boot processor know that we're done initializing our node's IO * and then exit. *//* ARGSUSED */static voidio_init_done(cnodeid_t cnodeid,cpu_cookie_t c){#ifndef CONFIG_IA64_SGI_IO	/* Let boot processor know that we're done. */	up(&io_init_sema);	/* This is for the setnoderun done when the io_init thread	 * started 	 */	restorenoderun(c);	sthread_exit();#endif}/*  * Probe to see if this hub's xtalk link is active.  If so, * return the Crosstalk Identification of the widget that we talk to.   * This is called before any of the Crosstalk infrastructure for  * this hub is set up.  It's usually called on the node that we're * probing, but not always. * * TBD: Prom code should actually do this work, and pass through  * hwid for our use. */static voidearly_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid){	hubreg_t llp_csr_reg;	nasid_t nasid;	hubinfo_t hubinfo;	hubinfo_get(hubv, &hubinfo);	nasid = hubinfo->h_nasid;	llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);	/* 	 * If link is up, read the widget's part number.	 * A direct connect widget must respond to widgetnum=0.	 */	if (llp_csr_reg & IIO_LLP_CSR_IS_UP) {		/* TBD: Put hub into "indirect" mode */		/*		 * We're able to read from a widget because our hub's 		 * WIDGET_ID was set up earlier.		 */#ifdef	BRINGUP		widgetreg_t widget_id = *(volatile widgetreg_t *)			(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);		printk("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id,		(volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) );#else	/* !BRINGUP */		widgetreg_t widget_id = XWIDGET_ID_READ(nasid, 0);#endif	/* BRINGUP */		hwid->part_num = XWIDGET_PART_NUM(widget_id);		hwid->rev_num = XWIDGET_REV_NUM(widget_id);		hwid->mfg_num = XWIDGET_MFG_NUM(widget_id);		/* TBD: link reset */	} else {		panic("\n\n**** early_probe_for_widget: Hub Vertex 0x%p is DOWN llp_csr_reg 0x%x ****\n\n", hubv, llp_csr_reg);		hwid->part_num = XWIDGET_PART_NUM_NONE;		hwid->rev_num = XWIDGET_REV_NUM_NONE;		hwid->mfg_num = XWIDGET_MFG_NUM_NONE;	}}/* Add inventory information to the widget vertex  * Right now (module,slot,revision) is being * added as inventory information. */static voidxwidget_inventory_add(devfs_handle_t 		widgetv,		      lboard_t 			*board,		      struct xwidget_hwid_s 	hwid){	if (!board)		return;	/* Donot add inventory information for the baseio	 * on a speedo with an xbox. It has already been	 * taken care of in SN00_vmc.	 * Speedo with xbox's baseio comes in at slot io1 (widget 9)	 */	device_inventory_add(widgetv,INV_IOBD,board->brd_type,			     board->brd_module,			     SLOTNUM_GETSLOT(board->brd_slot),			     hwid.rev_num);}/* * io_xswitch_widget_init *	 *//* defined in include/linux/ctype.h  *//* #define toupper(c)	(islower(c) ? (c) - 'a' + 'A' : (c)) */voidio_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			slotname[SLOTNUM_MAXLENGTH];	char 			pathname[128];	char			new_name[64];	moduleid_t		module;	slotid_t		slot;	lboard_t		*board = NULL;		printk("\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;	/* Who's the other guy on out crossbow (if anyone) */	peer_nasid = NODEPDA(cnode)->xbow_peer;	if (peer_nasid == INVALID_NASID)		/* If I don't have a peer, use myself. */		peer_nasid = nasid;	/* Check my xbow structure and my peer's */	if (!xbow_port_io_enabled(nasid, widgetnum) &&	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {		return;	}

⌨️ 快捷键说明

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