From: Pat Gefre <pfg@sgi.com>

arch/ia64/sn/io/platform_init/sgi_io_init.c
   use numionodes instead of numnodes

arch/ia64/sn/io/sn2/klconflib.c
    find_lboard changes - generalized a number of the interface funcs

arch/ia64/sn/io/sn2/klgraph.c
    call the more general find_lboard funcs

arch/ia64/sn/io/sn2/ml_iograph.c
    call the more general lboard funcs

arch/ia64/sn/io/sn2/module.c
    lboard changes
    mod for headless/memless nodes

arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
    isIO9 mod

arch/ia64/sn/kernel/setup.c
    headless/memless mod

include/asm-ia64/sn/klconfig.h
    generalized find_lboard funs



---

 arch/ia64/sn/io/platform_init/sgi_io_init.c |    2 
 arch/ia64/sn/io/sn2/klconflib.c             |  215 +++++++---------------------
 arch/ia64/sn/io/sn2/klgraph.c               |   87 +----------
 arch/ia64/sn/io/sn2/ml_iograph.c            |   13 -
 arch/ia64/sn/io/sn2/module.c                |   37 ++++
 arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c       |   14 +
 arch/ia64/sn/kernel/setup.c                 |   35 ++++
 include/asm-ia64/sn/klconfig.h              |    7 
 8 files changed, 153 insertions(+), 257 deletions(-)

diff -puN arch/ia64/sn/io/platform_init/sgi_io_init.c~altix-05 arch/ia64/sn/io/platform_init/sgi_io_init.c
--- 25/arch/ia64/sn/io/platform_init/sgi_io_init.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/platform_init/sgi_io_init.c	2004-02-02 23:19:46.000000000 -0800
@@ -131,7 +131,7 @@ sgi_master_io_infr_init(void)
 	klhwg_add_all_modules(hwgraph_root);
 	klhwg_add_all_nodes(hwgraph_root);
 
-	for (cnode = 0; cnode < numnodes; cnode++) {
+	for (cnode = 0; cnode < numionodes; cnode++) {
 		extern void per_hub_init(cnodeid_t);
 		per_hub_init(cnode);
 	}
diff -puN arch/ia64/sn/io/sn2/klconflib.c~altix-05 arch/ia64/sn/io/sn2/klconflib.c
--- 25/arch/ia64/sn/io/sn2/klconflib.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/sn2/klconflib.c	2004-02-02 23:19:46.000000000 -0800
@@ -31,6 +31,8 @@
 #define DBG(x...)
 #endif /* DEBUG_KLGRAPH */
 
+extern int numionodes;
+
 lboard_t *root_lboard[MAX_COMPACT_NODES];
 static int hasmetarouter;
 
@@ -38,13 +40,13 @@ static int hasmetarouter;
 char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo^34567890123456789...";
 
 lboard_t *
-find_lboard(lboard_t *start, unsigned char brd_type)
+find_lboard_any(lboard_t *start, unsigned char brd_type)
 {
 	/* Search all boards stored on this node. */
 	while (start) {
 		if (start->brd_type == brd_type)
 			return start;
-		start = KLCF_NEXT(start);
+		start = KLCF_NEXT_ANY(start);
 	}
 
 	/* Didn't find it. */
@@ -52,19 +54,59 @@ find_lboard(lboard_t *start, unsigned ch
 }
 
 lboard_t *
-find_lboard_class(lboard_t *start, unsigned char brd_type)
+find_lboard_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type)
 {
-	/* Search all boards stored on this node. */
+
+	while (start) {
+		if ((start->brd_type == brd_type) && 
+		    (start->brd_nasid == nasid))
+			return start;
+
+		if (numionodes == numnodes)
+			start = KLCF_NEXT_ANY(start);
+		else
+			start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_class_any(lboard_t *start, unsigned char brd_type)
+{
+        /* Search all boards stored on this node. */
 	while (start) {
 		if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
 			return start;
-		start = KLCF_NEXT(start);
+		start = KLCF_NEXT_ANY(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_class_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (KLCLASS(start->brd_type) == KLCLASS(brd_type) && 
+		    (start->brd_nasid == nasid))
+			return start;
+
+		if (numionodes == numnodes)
+			start = KLCF_NEXT_ANY(start);
+		else
+			start = KLCF_NEXT(start);
 	}
 
 	/* Didn't find it. */
 	return (lboard_t *)NULL;
 }
 
+
+
 klinfo_t *
 find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
 {
@@ -116,20 +158,6 @@ find_lboard_modslot(lboard_t *start, geo
 	return (lboard_t *)NULL;
 }
 
-lboard_t *
-find_lboard_module(lboard_t *start, geoid_t geoid)
-{
-        /* Search all boards stored on this node. */
-        while (start) {
-                if (geo_cmp(start->brd_geoid, geoid))
-                        return start;
-                start = KLCF_NEXT(start);
-        }
-
-        /* Didn't find it. */
-        return (lboard_t *)NULL;
-}
-
 /*
  * Convert a NIC name to a name for use in the hardware graph.
  */
@@ -218,7 +246,7 @@ xbow_port_io_enabled(nasid_t nasid, int 
 	/*
 	 * look for boards that might contain an xbow or xbridge
 	 */
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
+	brd = find_lboard_nasid((lboard_t *)KL_CONFIG_INFO(nasid), nasid, KLTYPE_IOBRICK_XBOW);
 	if (brd == NULL) return 0;
 		
 	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
@@ -285,40 +313,6 @@ board_to_path(lboard_t *brd, char *path)
 
 #define MHZ	1000000
 
-
-/* Get the canonical hardware graph name for the given pci component
- * on the given io board.
- */
-void
-device_component_canonical_name_get(lboard_t 	*brd,
-				    klinfo_t 	*component,
-				    char 	*name)
-{
-	slotid_t 	slot;
-	char 		board_name[20];
-
-	ASSERT(brd);
-
-	/* Convert the [ CLASS | TYPE ] kind of slotid
-	 * into a string
-	 */
-	slot = brd->brd_slot;
-
-	/* Get the io board name  */
-	if (!brd || (brd->brd_sversion < 2)) {
-		strcpy(name, EDGE_LBL_XWIDGET);
-	} else {
-		nic_name_convert(brd->brd_name, board_name);
-	}
-
-	/* Give out the canonical  name of the pci device*/
-	sprintf(name,
-		"/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
-		EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
-		geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), 
-		board_name, KLCF_BRIDGE_W_ID(component));
-}
-
 /*
  * Get the serial number of the main  component of a board
  * Returns 0 if a valid serial number is found
@@ -506,7 +500,7 @@ void
 format_module_id(char *buffer, moduleid_t m, int fmt)
 {
 	int rack, position;
-	char brickchar;
+	unsigned char brickchar;
 
 	rack = MODULE_GET_RACK(m);
 	ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
@@ -560,112 +554,21 @@ format_module_id(char *buffer, moduleid_
 
 }
 
-/*
- * Parse a module id, in either brief or long form.
- * Returns < 0 on error.
- * The long form does not include a brick type, so it defaults to 0 (CBrick)
- */
-int
-parse_module_id(char *buffer)
-{
-	unsigned int	v, rack, bay, type, form;
-	moduleid_t	m;
-	char 		c;
-
-	if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
-		form = MODULE_FORMAT_LONG;
-		buffer += strlen(EDGE_LBL_RACK "/");
-
-		/* A long module ID must be exactly 5 non-template chars. */
-		if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
-			return -1;
-	}
-	else {
-		form = MODULE_FORMAT_BRIEF;
-
-		/* A brief module id must be exactly 6 characters */
-		if (strlen(buffer) != 6)
-			return -2;
-	}
-
-	/* The rack number must be exactly 3 digits */
-	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
-		return -3;
-
-	rack = 0;
-	v = *buffer++ - '0';
-	if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
-		return -4;
-	RACK_ADD_CLASS(rack, v);
-
-	v = *buffer++ - '0';
-	if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
-		return -5;
-	RACK_ADD_GROUP(rack, v);
-
-	v = *buffer++ - '0';
-	/* rack numbers are 1-based */
-	if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
-		return -6;
-	RACK_ADD_NUM(rack, v);
-
-	if (form == MODULE_FORMAT_BRIEF) {
-		/* Next should be a module type character.  Accept ucase or lcase. */
-		c = *buffer++;
-		if (!isalpha(c))
-			return -7;
-
-		/* strchr() returns a pointer into brick_types[], or NULL */
-		type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
-		if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
-			return -8;
-	}
-	else {
-		/* Hardcode the module type, and skip over the boilerplate */
-		type = MODULE_CBRICK;
-
-		if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
-			return -9;
-
-		buffer += strlen("/" EDGE_LBL_RPOS "/");
-	}
-		
-	/* The bay number is last.  Make sure it's exactly two digits */
-
-	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
-		return -10;
-
-	bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
-
-	if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
-		return -11;
-
-	m = RBT_TO_MODULE(rack, bay, type);
-
-	/* avoid sign extending the moduleid_t */
-	return (int)(unsigned short)m;
-}
-
 int
 cbrick_type_get_nasid(nasid_t nasid)
 {
-	lboard_t *brd;
 	moduleid_t module;
-	uint type;
 	int t;
 
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
-	module = geo_module(brd->brd_geoid);
-	type = (module & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT;
-	/* convert brick_type to lower case */
-	if ((type >= 'A') && (type <= 'Z'))
-		type = type - 'A' + 'a';
-    
-	/* convert to a module.h brick type */
-	for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
-		if( brick_types[t] == type ) {
-			return t;
-		}
-	} 
+	module = iomoduleid_get(nasid);
+	if (module < 0 ) {
+		return MODULE_CBRICK;
+	}
+	t = MODULE_GET_BTYPE(module);
+	if ((char)t == 'o') {
+		return MODULE_OPUSBRICK;
+	} else {
+		return MODULE_CBRICK;
+	}
 	return -1;
 }
diff -puN arch/ia64/sn/io/sn2/klgraph.c~altix-05 arch/ia64/sn/io/sn2/klgraph.c
--- 25/arch/ia64/sn/io/sn2/klgraph.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/sn2/klgraph.c	2004-02-02 23:19:46.000000000 -0800
@@ -124,8 +124,9 @@ klhwg_add_xbow(cnodeid_t cnode, nasid_t 
 	/*REFERENCED*/
 	graph_error_t err;
 
-	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
-			return;
+	if (!(brd = find_lboard_nasid((lboard_t *)KL_CONFIG_INFO(nasid), 
+			nasid, KLTYPE_IOBRICK_XBOW)))
+		return;
 
 	if (KL_CONFIG_DUPLICATE_BOARD(brd))
 	    return;
@@ -200,7 +201,7 @@ klhwg_add_node(vertex_hdl_t hwgraph_root
 	vertex_hdl_t cpu_dir;
 
 	nasid = COMPACT_TO_NASID_NODEID(cnode);
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	brd = find_lboard_any((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
 	ASSERT(brd);
 
 	/* Generate a hardware graph path for this board. */
@@ -280,7 +281,7 @@ klhwg_add_all_routers(vertex_hdl_t hwgra
 
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
-		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+		brd = find_lboard_class_any((lboard_t *)KL_CONFIG_INFO(nasid),
 				KLTYPE_ROUTER);
 
 		if (!brd)
@@ -307,7 +308,7 @@ klhwg_add_all_routers(vertex_hdl_t hwgra
 			HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created router path.\n"));
 
 		/* Find the rest of the routers stored on this node. */
-		} while ( (brd = find_lboard_class(KLCF_NEXT(brd),
+		} while ( (brd = find_lboard_class_any(KLCF_NEXT_ANY(brd),
 			 KLTYPE_ROUTER)) );
 	}
 
@@ -414,7 +415,7 @@ klhwg_connect_routers(vertex_hdl_t hwgra
 
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
-		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+		brd = find_lboard_class_any((lboard_t *)KL_CONFIG_INFO(nasid),
 				KLTYPE_ROUTER);
 
 		if (!brd)
@@ -428,7 +429,7 @@ klhwg_connect_routers(vertex_hdl_t hwgra
 						 cnode, nasid);
 
 		/* Find the rest of the routers stored on this node. */
-		} while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+		} while ( (brd = find_lboard_class_any(KLCF_NEXT_ANY(brd), KLTYPE_ROUTER)) );
 	}
 }
 
@@ -452,8 +453,7 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_
 	for (cnode = 0; cnode < numionodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
 
-		brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
-		ASSERT(brd);
+		brd = find_lboard_any((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
 
 		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
 		ASSERT(hub);
@@ -511,69 +511,6 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_
 	}
 }
 
-/* Store the pci/vme disabled board information as extended administrative
- * hints which can later be used by the drivers using the device/driver
- * admin interface. 
- */
-static void __init
-klhwg_device_disable_hints_add(void)
-{
-	cnodeid_t	cnode; 		/* node we are looking at */
-	nasid_t		nasid;		/* nasid of the node */
-	lboard_t	*board;		/* board we are looking at */
-	int		comp_index;	/* component index */
-	klinfo_t	*component;	/* component in the board we are
-					 * looking at 
-					 */
-	char		device_name[MAXDEVNAME];
-	
-	for(cnode = 0; cnode < numnodes; cnode++) {
-		nasid = COMPACT_TO_NASID_NODEID(cnode);
-		board = (lboard_t *)KL_CONFIG_INFO(nasid);
-		/* Check out all the board info stored  on a node */
-		while(board) {
-			/* No need to look at duplicate boards or non-io 
-			 * boards
-			 */
-			if (KL_CONFIG_DUPLICATE_BOARD(board) ||
-			    KLCLASS(board->brd_type) != KLCLASS_IO) {
-				board = KLCF_NEXT(board);
-				continue;
-			}
-			/* Check out all the components of a board */
-			for (comp_index = 0; 
-			     comp_index < KLCF_NUM_COMPS(board);
-			     comp_index++) {
-				component = KLCF_COMP(board,comp_index);
-				/* If the component is enabled move on to
-				 * the next component
-				 */
-				if (KLCONFIG_INFO_ENABLED(component))
-					continue;
-				/* NOTE : Since the prom only supports
-				 * the disabling of pci devices the following
-				 * piece of code makes sense. 
-				 * Make sure that this assumption is valid
-				 */
-				/* This component is disabled. Store this
-				 * hint in the extended device admin table
-				 */
-				/* Get the canonical name of the pci device */
-				device_component_canonical_name_get(board,
-							    component,
-							    device_name);
-#ifdef DEBUG
-				printf("%s DISABLED\n",device_name);
-#endif				
-			}
-			/* go to the next board info stored on this 
-			 * node 
-			 */
-			board = KLCF_NEXT(board);
-		}
-	}
-}
-
 void __init
 klhwg_add_all_modules(vertex_hdl_t hwgraph_root)
 {
@@ -637,10 +574,4 @@ klhwg_add_all_nodes(vertex_hdl_t hwgraph
 	klhwg_add_all_routers(hwgraph_root);
 	klhwg_connect_routers(hwgraph_root);
 	klhwg_connect_hubs(hwgraph_root);
-
-	/* Go through the entire system's klconfig
-	 * to figure out which pci components have been disabled
-	 */
-	klhwg_device_disable_hints_add();
-
 }
diff -puN arch/ia64/sn/io/sn2/ml_iograph.c~altix-05 arch/ia64/sn/io/sn2/ml_iograph.c
--- 25/arch/ia64/sn/io/sn2/ml_iograph.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/sn2/ml_iograph.c	2004-02-02 23:19:46.000000000 -0800
@@ -345,13 +345,12 @@ io_xswitch_widget_init(vertex_hdl_t  	xs
 			return;
 		}
 
-		board = find_lboard_class(
-				(lboard_t *)KL_CONFIG_INFO(nasid),
-				KLCLASS_IOBRICK);
+		board = find_lboard_class_nasid( (lboard_t *)KL_CONFIG_INFO(nasid),
+				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);
+		    	board = find_lboard_class_nasid(
+				(lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer),
+					NODEPDA(cnode)->xbow_peer, KLCLASS_IOBRICK);
 		}
 
 		if (board) {
@@ -366,7 +365,7 @@ io_xswitch_widget_init(vertex_hdl_t  	xs
 		{
 			lboard_t *brd;
 
-			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+			brd = find_lboard_any((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
 			if ( brd != (lboard_t *)0 ) {
 				board->brd_geoid = brd->brd_geoid;
 			}
diff -puN arch/ia64/sn/io/sn2/module.c~altix-05 arch/ia64/sn/io/sn2/module.c
--- 25/arch/ia64/sn/io/sn2/module.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/sn2/module.c	2004-02-02 23:19:46.000000000 -0800
@@ -139,7 +139,7 @@ module_probe_snum(module_t *m, nasid_t h
     /*
      * record brick serial number
      */
-    board = find_lboard((lboard_t *) KL_CONFIG_INFO(host_nasid), KLTYPE_SNIA);
+    board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(host_nasid), host_nasid, KLTYPE_SNIA);
 
     if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
     {
@@ -152,8 +152,8 @@ module_probe_snum(module_t *m, nasid_t h
 	m->snum_valid = 1;
     }
 
-    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid),
-			KLTYPE_IOBRICK_XBOW);
+    board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid),
+			nasid, KLTYPE_IOBRICK_XBOW);
 
     if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
 	return 0;
@@ -185,6 +185,7 @@ io_module_init(void)
     nasid_t		nasid;
     int			nserial;
     module_t	       *m;
+    extern		int numionodes;
 
     DPRINTF("*******module_init\n");
 
@@ -196,8 +197,7 @@ io_module_init(void)
      */
     for (node = 0; node < numnodes; node++) {
 	nasid = COMPACT_TO_NASID_NODEID(node);
-
-	board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), nasid, KLTYPE_SNIA);
 	ASSERT(board);
 
 	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found Shub lboard 0x%lx nasid 0x%x cnode 0x%x \n", (unsigned long)board, (int)nasid, (int)node));
@@ -206,4 +206,31 @@ io_module_init(void)
 	if (! m->snum_valid && module_probe_snum(m, nasid, nasid))
 	    nserial++;
     }
+
+    /*
+     * Second scan, look for headless/memless board hosted by compute nodes.
+     */
+    for (node = numnodes; node < numionodes; node++) {
+	nasid_t		nasid;
+	char		serial_number[16];
+
+        nasid = COMPACT_TO_NASID_NODEID(node);
+	board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), 
+				nasid, KLTYPE_SNIA);
+	ASSERT(board);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found headless/memless lboard 0x%lx node %d nasid %d cnode %d\n", (unsigned long)board, node, (int)nasid, (int)node));
+
+        m = module_add_node(board->brd_geoid, node);
+
+	/*
+	 * Get and initialize the serial number.
+	 */
+	board_serial_number_get( board, serial_number );
+    	if( serial_number[0] != '\0' ) {
+        	encode_str_serial( serial_number, m->snum.snum_str );
+        	m->snum_valid = 1;
+		nserial++;
+	}
+    }
 }
diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c~altix-05 arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
--- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	2004-02-02 23:19:46.000000000 -0800
@@ -2638,14 +2638,18 @@ pcibr_bridge_ptr_get(vertex_hdl_t widget
 
 
 int
-isIO9(nasid_t nasid) {
+isIO9(nasid_t nasid)
+{
 	lboard_t *brd = (lboard_t *)KL_CONFIG_INFO(nasid);
 
 	while (brd) {
 		if (brd->brd_flags & LOCAL_MASTER_IO6) {
 			return 1;
 		}
-		brd = KLCF_NEXT(brd);
+                if (numionodes == numnodes)
+                        brd = KLCF_NEXT_ANY(brd);
+                else
+                        brd = KLCF_NEXT(brd);
 	}
 	/* if it's dual ported, check the peer also */
 	nasid = NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer;
@@ -2655,7 +2659,11 @@ isIO9(nasid_t nasid) {
 		if (brd->brd_flags & LOCAL_MASTER_IO6) {
 			return 1;
 		}
-		brd = KLCF_NEXT(brd);
+                if (numionodes == numnodes)
+                        brd = KLCF_NEXT_ANY(brd);
+                else
+                        brd = KLCF_NEXT(brd);
+
 	}
 	return 0;
 }
diff -puN arch/ia64/sn/kernel/setup.c~altix-05 arch/ia64/sn/kernel/setup.c
--- 25/arch/ia64/sn/kernel/setup.c~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/arch/ia64/sn/kernel/setup.c	2004-02-02 23:19:46.000000000 -0800
@@ -7,6 +7,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
@@ -70,8 +71,7 @@ u64 sn_partition_serial_number;
 
 short physical_node_map[MAX_PHYSNODE_ID];
 
-int     numionodes;
-
+int	numionodes;
 /*
  * This is the address of the RRegs in the HSpace of the global
  * master.  It is used by a hack in serial.c (serial_[in|out],
@@ -340,7 +340,7 @@ sn_init_pdas(char **cmdline_p)
 	/*
 	 * Now copy the array of nodepda pointers to each nodepda.
 	 */
-        for (cnode=0; cnode < numnodes; cnode++)
+        for (cnode=0; cnode < numionodes; cnode++)
 		memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr));
 
 
@@ -437,8 +437,10 @@ sn_cpu_init(void)
  */
 
 void
-scan_for_ionodes(void) {
+scan_for_ionodes(void)
+{
 	int nasid = 0;
+	lboard_t *brd;
 
 	/* Setup ionodes with memory */
 	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) {
@@ -458,4 +460,29 @@ scan_for_ionodes(void) {
 					((kl_config_hdr_t *)(klgraph_header))->
 					ch_board_info);
 	}
+
+	/* Scan headless/memless IO Nodes. */
+	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) {
+		/* if there's no nasid, don't try to read the klconfig on the node */
+		if (physical_node_map[nasid] == -1) continue;
+		brd = find_lboard_any((lboard_t *)root_lboard[nasid_to_cnodeid(nasid)], KLTYPE_SNIA);
+		if (brd) {
+			brd = KLCF_NEXT_ANY(brd); /* Skip this node's lboard */
+			if (!brd)
+				continue;
+		}
+
+		brd = find_lboard_any(brd, KLTYPE_SNIA);
+		while (brd) {
+			pda->cnodeid_to_nasid_table[numionodes] = brd->brd_nasid;
+			physical_node_map[brd->brd_nasid] = numionodes;
+			root_lboard[numionodes] = brd;
+			numionodes++;
+			brd = KLCF_NEXT_ANY(brd);
+			if (!brd)
+				break;
+
+			brd = find_lboard_any(brd, KLTYPE_SNIA);
+		}
+	}
 }
diff -puN include/asm-ia64/sn/klconfig.h~altix-05 include/asm-ia64/sn/klconfig.h
--- 25/include/asm-ia64/sn/klconfig.h~altix-05	2004-02-02 23:19:46.000000000 -0800
+++ 25-akpm/include/asm-ia64/sn/klconfig.h	2004-02-02 23:19:46.000000000 -0800
@@ -672,18 +672,19 @@ typedef union kldev_s {      /* for devi
 /* external declarations of Linux kernel functions. */
 
 extern lboard_t *root_lboard[];
-extern lboard_t *find_lboard(lboard_t *start, unsigned char type);
+extern lboard_t *find_lboard_any(lboard_t *start, unsigned char type);
+extern lboard_t *find_lboard_nasid(lboard_t *start, nasid_t, unsigned char type);
 extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type);
 extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type);
 extern klcpu_t *nasid_slice_to_cpuinfo(nasid_t, int);
 
 
 extern lboard_t *find_gfxpipe(int pipenum);
-extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class);
+extern lboard_t *find_lboard_class_any(lboard_t *start, unsigned char brd_class);
+extern lboard_t *find_lboard_class_nasid(lboard_t *start, nasid_t, unsigned char brd_class);
 extern lboard_t *find_nic_lboard(lboard_t *, nic_t);
 extern lboard_t *find_nic_type_lboard(nasid_t, unsigned char, nic_t);
 extern lboard_t *find_lboard_modslot(lboard_t *start, geoid_t geoid);
-extern lboard_t *find_lboard_module(lboard_t *start, geoid_t geoid);
 extern int	config_find_nic_router(nasid_t, nic_t, lboard_t **, klrou_t**);
 extern int	config_find_nic_hub(nasid_t, nic_t, lboard_t **, klhub_t**);
 extern int	config_find_xbow(nasid_t, lboard_t **, klxbow_t**);

_