File: /usr/src/linux/arch/ia64/sn/io/klconflib.c

1     /* $Id$
2      *
3      * This file is subject to the terms and conditions of the GNU General Public
4      * License.  See the file "COPYING" in the main directory of this archive
5      * for more details.
6      *
7      * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
8      * Copyright (C) 2000 by Colin Ngam
9      */
10     
11     
12     #include <linux/types.h>
13     #include <linux/config.h>
14     #include <linux/ctype.h>
15     #include <asm/sn/sgi.h>
16     #include <asm/sn/iograph.h>
17     #include <asm/sn/invent.h>
18     #include <asm/sn/hcl.h>
19     #include <asm/sn/labelcl.h>
20     
21     #include <asm/sn/agent.h>
22     #include <asm/sn/klconfig.h>
23     #include <asm/sn/nodepda.h>
24     #include <asm/sn/module.h>
25     #include <asm/sn/router.h>
26     #include <asm/sn/xtalk/xbow.h>
27     
28     #define printf printk
29     int hasmetarouter;
30     
31     #define LDEBUG 0
32     #define NIC_UNKNOWN ((nic_t) -1)
33     
34     #undef DEBUG_KLGRAPH
35     #ifdef DEBUG_KLGRAPH
36     #define DBG(x...) printk(x)
37     #else
38     #define DBG(x...)
39     #endif /* DEBUG_KLGRAPH */
40     
41     static void sort_nic_names(lboard_t *) ;
42     
43     lboard_t *
44     find_lboard(lboard_t *start, unsigned char brd_type)
45     {
46     	/* Search all boards stored on this node. */
47     	while (start) {
48     		if (start->brd_type == brd_type)
49     			return start;
50     		start = KLCF_NEXT(start);
51     	}
52     
53     	/* Didn't find it. */
54     	return (lboard_t *)NULL;
55     }
56     
57     lboard_t *
58     find_lboard_class(lboard_t *start, unsigned char brd_type)
59     {
60     	/* Search all boards stored on this node. */
61     	while (start) {
62     		if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
63     			return start;
64     		start = KLCF_NEXT(start);
65     	}
66     
67     	/* Didn't find it. */
68     	return (lboard_t *)NULL;
69     }
70     
71     klinfo_t *
72     find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
73     {
74     	int index, j;
75     
76     	if (kli == (klinfo_t *)NULL) {
77     		index = 0;
78     	} else {
79     		for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
80     			if (kli == KLCF_COMP(brd, j))
81     				break;
82     		}
83     		index = j;
84     		if (index == KLCF_NUM_COMPS(brd)) {
85     			DBG("find_component: Bad pointer: 0x%p\n", kli);
86     			return (klinfo_t *)NULL;
87     		}
88     		index++;	/* next component */
89     	}
90     	
91     	for (; index < KLCF_NUM_COMPS(brd); index++) {		
92     		kli = KLCF_COMP(brd, index);
93     		DBG("find_component: brd %p kli %p  request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli));
94     		if (KLCF_COMP_TYPE(kli) == struct_type)
95     			return kli;
96     	}
97     
98     	/* Didn't find it. */
99     	return (klinfo_t *)NULL;
100     }
101     
102     klinfo_t *
103     find_first_component(lboard_t *brd, unsigned char struct_type)
104     {
105     	return find_component(brd, (klinfo_t *)NULL, struct_type);
106     }
107     
108     lboard_t *
109     find_lboard_modslot(lboard_t *start, moduleid_t mod, slotid_t slot)
110     {
111     	/* Search all boards stored on this node. */
112     	while (start) {
113     		if (MODULE_MATCH(start->brd_module, mod) &&
114     		    (start->brd_slot == slot))
115     			return start;
116     		start = KLCF_NEXT(start);
117     	}
118     
119     	/* Didn't find it. */
120     	return (lboard_t *)NULL;
121     }
122     
123     lboard_t *
124     find_lboard_module(lboard_t *start, moduleid_t mod)
125     {
126             /* Search all boards stored on this node. */
127             while (start) {
128                     if (MODULE_MATCH(start->brd_module, mod))
129                             return start;
130                     start = KLCF_NEXT(start);
131             }
132     
133             /* Didn't find it. */
134             return (lboard_t *)NULL;
135     }
136     
137     lboard_t *
138     find_lboard_module_class(lboard_t *start, moduleid_t mod,
139                                                     unsigned char brd_type)
140     {
141     	while (start) {
142     
143     		DBG("find_lboard_module_class: lboard 0x%p, start->brd_module 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_module, mod, start->brd_type, brd_type);
144     
145     		if (MODULE_MATCH(start->brd_module, mod) &&
146     			(KLCLASS(start->brd_type) == KLCLASS(brd_type)))
147     			return start;
148     		start = KLCF_NEXT(start);
149     	}
150     
151     	/* Didn't find it. */
152     	return (lboard_t *)NULL;
153     }
154     
155     
156     /*
157      * Convert a NIC name to a name for use in the hardware graph.
158      */
159     void
160     nic_name_convert(char *old_name, char *new_name)
161     {
162             int i;
163             char c;
164             char *compare_ptr;
165     
166     	if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
167                     strcpy(new_name, EDGE_LBL_XWIDGET);
168             } else {
169                     for (i = 0; i < strlen(old_name); i++) {
170                             c = old_name[i];
171     
172                             if (isalpha(c))
173                                     new_name[i] = tolower(c);
174                             else if (isdigit(c))
175                                     new_name[i] = c;
176                             else
177                                     new_name[i] = '_';
178                     }
179                     new_name[i] = '\0';
180             }
181     
182             /* XXX -
183              * Since a bunch of boards made it out with weird names like
184              * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
185              * replace it with "baseio" to avoid confusion in the field.
186     	 * We also have to make sure we don't report media_io instead of
187     	 * baseio.
188              */
189     
190             /* Skip underscores at the beginning of the name */
191             for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
192                     ;
193     
194     	/*
195     	 * Check for some names we need to replace.  Early boards
196     	 * had junk following the name so check only the first
197     	 * characters.
198     	 */
199             if (!strncmp(new_name, "io6", 3) || 
200                 !strncmp(new_name, "mio", 3) || 
201     	    !strncmp(new_name, "media_io", 8))
202     		strcpy(new_name, "baseio");
203     	else if (!strncmp(new_name, "divo", 4))
204     		strcpy(new_name, "divo") ;
205     
206     }
207     
208     /* Check if the given board corresponds to the global 
209      * master io6
210      */
211     int
212     is_master_baseio(nasid_t nasid,moduleid_t module,slotid_t slot)
213     {
214     	lboard_t	*board;
215     
216     #if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC
217     /* BRINGUP: If this works then look for callers of is_master_baseio()
218      * (e.g. iograph.c) and let them pass in a slot if they want
219      */
220     	board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), module);
221     #else
222     	board = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid),
223     				    module, slot);
224     #endif
225     
226     #ifndef _STANDALONE
227     	{
228     		cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
229     
230     		if (!board && (NODEPDA(cnode)->xbow_peer != INVALID_NASID))
231     #if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC
232     			board = find_lboard_module((lboard_t *)
233     				    KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
234     				    module);
235     #else
236     			board = find_lboard_modslot((lboard_t *)
237     				    KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
238     				    module, slot);
239     #endif
240     	}
241     #endif
242     	if (!board)
243     		return(0);
244     	return(board->brd_flags & GLOBAL_MASTER_IO6);
245     }
246     /*
247      * Find the lboard structure and get the board name.
248      * If we can't find the structure or it's too low a revision,
249      * use default name.
250      */
251     lboard_t *
252     get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name)
253     {
254     	lboard_t *brd;
255     
256     	brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid),
257     				  mod, slot);
258     
259     #ifndef _STANDALONE
260     	{
261     		cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
262     
263     		if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID))
264     			brd = find_lboard_modslot((lboard_t *)
265     				KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
266     				mod, slot);
267     	}
268     #endif
269     
270     	if (!brd || (brd->brd_sversion < 2)) {
271     		strcpy(name, EDGE_LBL_XWIDGET);
272     	} else {
273     		nic_name_convert(brd->brd_name, name);
274     	}
275     
276     	/*
277      	 * PV # 540860
278     	 * If the name is not 'baseio' 
279     	 * get the lowest of all the names in the nic string.
280     	 * This is needed for boards like divo, which can have
281     	 * a bunch of daughter cards, but would like to be called
282     	 * divo. We could do this for baseio 
283      	 * but it has some special case names that we would not
284      	 * like to disturb at this point.
285     	 */
286     
287     	/* gfx boards don't need any of this name scrambling */
288     	if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) {
289     		return(brd);
290     	}
291     
292     	if (!(!strcmp(name, "baseio") )) {
293     		if (brd) {
294     			sort_nic_names(brd) ;
295     			/* Convert to small case, '-' to '_' etc */
296     			nic_name_convert(brd->brd_name, name) ;
297     		}
298     	}
299     
300     	return(brd);
301     }
302     
303     int
304     get_cpu_slice(cpuid_t cpu)
305     {
306     	klcpu_t *acpu;
307     	if ((acpu = get_cpuinfo(cpu)) == NULL)
308     	    return -1;
309     	return acpu->cpu_info.physid;
310     }
311     
312     
313     /*
314      * get_actual_nasid
315      *
316      *	Completely disabled brds have their klconfig on 
317      *	some other nasid as they have no memory. But their
318      *	actual nasid is hidden in the klconfig. Use this
319      *	routine to get it. Works for normal boards too.
320      */
321     nasid_t
322     get_actual_nasid(lboard_t *brd)
323     {
324     	klhub_t	*hub ;
325     
326     	if (!brd)
327     		return INVALID_NASID ;
328     
329     	/* find out if we are a completely disabled brd. */
330     
331             hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
332     	if (!hub)
333                     return INVALID_NASID ;
334     	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
335     		return hub->hub_info.physid ;
336     	else
337     		return brd->brd_nasid ;
338     }
339     
340     int
341     xbow_port_io_enabled(nasid_t nasid, int link)
342     {
343     	lboard_t *brd;
344     	klxbow_t *xbow_p;
345     
346     	/*
347     	 * look for boards that might contain an xbow or xbridge
348     	 */
349     	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
350     	if (brd == NULL) return 0;
351     		
352     	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
353     	    == NULL)
354     	    return 0;
355     
356     	if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
357     	    return 0;
358     
359     	DBG("xbow_port_io_enabled:  brd 0x%p xbow_p 0x%p \n", brd, xbow_p);
360     
361     	return 1;
362     }
363     
364     void
365     board_to_path(lboard_t *brd, char *path)
366     {
367     	moduleid_t modnum;
368     	char *board_name;
369     #if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC)
370     	slotid_t slot;
371     	char slot_name[SLOTNUM_MAXLENGTH];
372     #endif
373     
374     	ASSERT(brd);
375     
376     	switch (KLCLASS(brd->brd_type)) {
377     
378     		case KLCLASS_NODE:
379     			board_name = EDGE_LBL_NODE;
380     			break;
381     		case KLCLASS_ROUTER:
382     			if (brd->brd_type == KLTYPE_META_ROUTER) {
383     				board_name = EDGE_LBL_META_ROUTER;
384     				hasmetarouter++;
385     			} else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
386     				board_name = EDGE_LBL_REPEATER_ROUTER;
387     				hasmetarouter++;
388     			} else
389     				board_name = EDGE_LBL_ROUTER;
390     			break;
391     		case KLCLASS_MIDPLANE:
392     			board_name = EDGE_LBL_MIDPLANE;
393     			break;
394     		case KLCLASS_IO:
395     			board_name = EDGE_LBL_IO;
396     			break;
397     		case KLCLASS_IOBRICK:
398     			if (brd->brd_type == KLTYPE_PBRICK)
399     				board_name = EDGE_LBL_PBRICK;
400     			else if (brd->brd_type == KLTYPE_IBRICK)
401     				board_name = EDGE_LBL_IBRICK;
402     			else if (brd->brd_type == KLTYPE_XBRICK)
403     				board_name = EDGE_LBL_XBRICK;
404     			else
405     				board_name = EDGE_LBL_IOBRICK;
406     			break;
407     		default:
408     			board_name = EDGE_LBL_UNKNOWN;
409     	}
410     			
411     	modnum = brd->brd_module;
412     
413     	ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE);
414     #ifdef __ia64
415     	{
416     		char	buffer[16];
417     		memset(buffer, 0, 16);
418     		format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
419     		sprintf(path, EDGE_LBL_MODULE "/%s/%s", buffer, board_name);
420     	}
421     #else
422     	sprintf(path, "%H/%s", modnum, board_name);
423     #endif
424     }
425     
426     /*
427      * Get the module number for a NASID.
428      */
429     moduleid_t
430     get_module_id(nasid_t nasid)
431     {
432     	lboard_t *brd;
433     
434     	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
435     
436     	if (!brd)
437     		return INVALID_MODULE;
438     	else
439     		return brd->brd_module;
440     }
441     
442     
443     #define MHZ	1000000
444     
445     
446     /* Get the canonical hardware graph name for the given pci component
447      * on the given io board.
448      */
449     void
450     device_component_canonical_name_get(lboard_t 	*brd,
451     				    klinfo_t 	*component,
452     				    char 	*name)
453     {
454     	moduleid_t 	modnum;
455     	slotid_t 	slot;
456     	char 		board_name[20];
457     
458     	ASSERT(brd);
459     
460     	/* Get the module number of this board */
461     	modnum = brd->brd_module;
462     
463     	/* Convert the [ CLASS | TYPE ] kind of slotid
464     	 * into a string 
465     	 */
466     	slot = brd->brd_slot;
467     	ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE);
468     
469     	/* Get the io board name  */
470     	if (!brd || (brd->brd_sversion < 2)) {
471     		strcpy(name, EDGE_LBL_XWIDGET);
472     	} else {
473     		nic_name_convert(brd->brd_name, board_name);
474     	}
475     
476     	/* Give out the canonical  name of the pci device*/
477     	sprintf(name, 
478     		"/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLOT"/%s/"
479     		EDGE_LBL_PCI"/%d", 
480     		modnum, board_name,KLCF_BRIDGE_W_ID(component));
481     }
482     
483     /*
484      * Get the serial number of the main  component of a board
485      * Returns 0 if a valid serial number is found
486      * 1 otherwise.
487      * Assumptions: Nic manufacturing string  has the following format
488      *			*Serial:<serial_number>;*
489      */
490     static int
491     component_serial_number_get(lboard_t 		*board,
492     			    klconf_off_t 	mfg_nic_offset,
493     			    char		*serial_number,
494     			    char		*key_pattern)
495     {
496     
497     	char	*mfg_nic_string;
498     	char	*serial_string,*str;
499     	int	i;
500     	char	*serial_pattern = "Serial:";
501     
502     	/* We have an error on a null mfg nic offset */
503     	if (!mfg_nic_offset)
504     		return(1);
505     	/* Get the hub's manufacturing nic information
506     	 * which is in the form of a pre-formatted string
507     	 */
508     	mfg_nic_string = 
509     		(char *)NODE_OFFSET_TO_K0(NASID_GET(board),
510     					  mfg_nic_offset);
511     	/* There is no manufacturing nic info */
512     	if (!mfg_nic_string)
513     		return(1);
514     
515     	str = mfg_nic_string;
516     	/* Look for the key pattern first (if it is  specified)
517     	 * and then print the serial number corresponding to that.
518     	 */
519     	if (strcmp(key_pattern,"") && 
520     	    !(str = strstr(mfg_nic_string,key_pattern)))
521     		return(1);
522     
523     	/* There is no serial number info in the manufacturing
524     	 * nic info
525     	 */
526     	if (!(serial_string = strstr(str,serial_pattern)))
527     		return(1);
528     
529     	serial_string = serial_string + strlen(serial_pattern);
530     	/*  Copy the serial number information from the klconfig */
531     	i = 0;
532     	while (serial_string[i] != ';') {
533     		serial_number[i] = serial_string[i];
534     		i++;
535     	}
536     	serial_number[i] = 0;
537     	
538     	return(0);
539     }
540     /*
541      * Get the serial number of a board
542      * Returns 0 if a valid serial number is found
543      * 1 otherwise.
544      */
545     
546     int
547     board_serial_number_get(lboard_t *board,char *serial_number)
548     {
549     	ASSERT(board && serial_number);
550     	if (!board || !serial_number)
551     		return(1);
552     
553     	strcpy(serial_number,"");
554     	switch(KLCLASS(board->brd_type)) {
555     	case KLCLASS_CPU: {	/* Node board */
556     		klhub_t	*hub;
557     		
558     		/* Get the hub component information */
559     		hub = (klhub_t *)find_first_component(board,
560     						      KLSTRUCT_HUB);
561     		/* If we don't have a hub component on an IP27
562     		 * then we have a weird klconfig.
563     		 */
564     		if (!hub)
565     			return(1);
566     		/* Get the serial number information from
567     		 * the hub's manufacturing nic info
568     		 */
569     		if (component_serial_number_get(board,
570     						hub->hub_mfg_nic,
571     						serial_number,
572     #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
573     						"IP35"))
574     #else
575     						"IP27"))
576     			/* Try with IP31 key if IP27 key fails */
577     			if (component_serial_number_get(board,
578     							hub->hub_mfg_nic,
579     							serial_number,
580     							"IP31"))
581     #endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
582     				return(1);
583     		break;
584     	}
585     	case KLCLASS_IO: {	/* IO board */
586     		if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
587     		/* Special case for TPU boards */
588     			kltpu_t *tpu;	
589     		
590     			/* Get the tpu component information */
591     			tpu = (kltpu_t *)find_first_component(board,
592     						      KLSTRUCT_TPU);
593     			/* If we don't have a tpu component on a tpu board
594     			 * then we have a weird klconfig.
595     			 */
596     			if (!tpu)
597     				return(1);
598     			/* Get the serial number information from
599     			 * the tpu's manufacturing nic info
600     			 */
601     			if (component_serial_number_get(board,
602     						tpu->tpu_mfg_nic,
603     						serial_number,
604     						""))
605     				return(1);
606     			break;
607     		} else  if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
608     		            (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
609     		/* Special case for GSN boards */
610     			klgsn_t *gsn;	
611     		
612     			/* Get the gsn component information */
613     			gsn = (klgsn_t *)find_first_component(board,
614     			      ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
615     					KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
616     			/* If we don't have a gsn component on a gsn board
617     			 * then we have a weird klconfig.
618     			 */
619     			if (!gsn)
620     				return(1);
621     			/* Get the serial number information from
622     			 * the gsn's manufacturing nic info
623     			 */
624     			if (component_serial_number_get(board,
625     						gsn->gsn_mfg_nic,
626     						serial_number,
627     						""))
628     				return(1);
629     			break;
630     		} else {
631     		     	klbri_t	*bridge;
632     		
633     			/* Get the bridge component information */
634     			bridge = (klbri_t *)find_first_component(board,
635     							 KLSTRUCT_BRI);
636     			/* If we don't have a bridge component on an IO board
637     			 * then we have a weird klconfig.
638     			 */
639     			if (!bridge)
640     				return(1);
641     			/* Get the serial number information from
642     		 	 * the bridge's manufacturing nic info
643     			 */
644     			if (component_serial_number_get(board,
645     						bridge->bri_mfg_nic,
646     						serial_number,
647     						""))
648     				return(1);
649     			break;
650     		}
651     	}
652     	case KLCLASS_ROUTER: {	/* Router board */
653     		klrou_t *router;	
654     		
655     		/* Get the router component information */
656     		router = (klrou_t *)find_first_component(board,
657     							 KLSTRUCT_ROU);
658     		/* If we don't have a router component on a router board
659     		 * then we have a weird klconfig.
660     		 */
661     		if (!router)
662     			return(1);
663     		/* Get the serial number information from
664     		 * the router's manufacturing nic info
665     		 */
666     		if (component_serial_number_get(board,
667     						router->rou_mfg_nic,
668     						serial_number,
669     						""))
670     			return(1);
671     		break;
672     	}
673     	case KLCLASS_GFX: {	/* Gfx board */
674     		klgfx_t *graphics;
675     		
676     		/* Get the graphics component information */
677     		graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
678     		/* If we don't have a gfx component on a gfx board
679     		 * then we have a weird klconfig.
680     		 */
681     		if (!graphics)
682     			return(1);
683     		/* Get the serial number information from
684     		 * the graphics's manufacturing nic info
685     		 */
686     		if (component_serial_number_get(board,
687     						graphics->gfx_mfg_nic,
688     						serial_number,
689     						""))
690     			return(1);
691     		break;
692     	}
693     	default:
694     		strcpy(serial_number,"");
695     		break;
696     	}
697     	return(0);
698     }
699     
700     #include "asm/sn/sn_private.h"
701     
702     xwidgetnum_t
703     nodevertex_widgetnum_get(devfs_handle_t node_vtx)
704     {
705     	hubinfo_t hubinfo_p;
706     
707     	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, 
708     			     (arbitrary_info_t *) &hubinfo_p);
709     	return(hubinfo_p->h_widgetid);
710     }
711     
712     devfs_handle_t
713     nodevertex_xbow_peer_get(devfs_handle_t node_vtx)
714     {
715     	hubinfo_t hubinfo_p;
716     	nasid_t xbow_peer_nasid;
717     	cnodeid_t xbow_peer;
718     
719     	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO,
720     				     (arbitrary_info_t *) &hubinfo_p);
721     	xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer;
722     	if(xbow_peer_nasid == INVALID_NASID) 
723     			return ( (devfs_handle_t)-1);
724     	xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid);
725     	return(NODEPDA(xbow_peer)->node_vertex);
726     }
727     
728     /* NIC Sorting Support */
729     
730     #define MAX_NICS_PER_STRING 	32
731     #define MAX_NIC_NAME_LEN	32
732     
733     static char *
734     get_nic_string(lboard_t *lb)
735     {
736             int         	i;
737             klinfo_t    	*k = NULL ;
738         	klconf_off_t    mfg_off = 0 ;
739         	char            *mfg_nic = NULL ;
740     
741             for (i = 0; i < KLCF_NUM_COMPS(lb); i++) {
742                     k = KLCF_COMP(lb, i) ;
743                     switch(k->struct_type) {
744                             case KLSTRUCT_BRI:
745                 			mfg_off = ((klbri_t *)k)->bri_mfg_nic ;
746     				break ;
747     
748                             case KLSTRUCT_HUB:
749                 			mfg_off = ((klhub_t *)k)->hub_mfg_nic ;
750     				break ;
751     
752                             case KLSTRUCT_ROU:
753                 			mfg_off = ((klrou_t *)k)->rou_mfg_nic ;
754     				break ;
755     
756                             case KLSTRUCT_GFX:
757                 			mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ;
758     				break ;
759     
760                             case KLSTRUCT_TPU:
761                 			mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ;
762     				break ;
763     
764                             case KLSTRUCT_GSN_A:
765                             case KLSTRUCT_GSN_B:
766                 			mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ;
767     				break ;
768     
769                             case KLSTRUCT_XTHD:
770                                     mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ;
771                                     break;
772     
773     			default:
774     				mfg_off = 0 ;
775                                     break ;
776                     }
777     		if (mfg_off)
778     			break ;
779             }
780     
781     	if ((mfg_off) && (k))
782     		mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ;
783     
784             return mfg_nic ;
785     }
786     
787     char *
788     get_first_string(char **ptrs, int n)
789     {
790             int     i ;
791             char    *tmpptr ;
792     
793             if ((ptrs == NULL) || (n == 0))
794                     return NULL ;
795     
796             tmpptr = ptrs[0] ;
797     
798             if (n == 1)
799                     return tmpptr ;
800     
801             for (i = 0 ; i < n ; i++) {
802                     if (strcmp(tmpptr, ptrs[i]) > 0)
803                             tmpptr = ptrs[i] ;
804             }
805     
806             return tmpptr ;
807     }
808     
809     int
810     get_ptrs(char *idata, char **ptrs, int n, char *label)
811     {
812             int     i = 0 ;
813             char    *tmp = idata ;
814     
815             if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0))
816                     return 0 ;
817     
818             while  ( (tmp = strstr(tmp, label)) ){
819                     tmp += strlen(label) ;
820                     /* check for empty name field, and last NULL ptr */
821                     if ((i < (n-1)) && (*tmp != ';')) {
822                             ptrs[i++] = tmp ;
823                     }
824             }
825     
826             ptrs[i] = NULL ;
827     
828             return i ;
829     }
830     
831     /*
832      * sort_nic_names
833      *
834      * 	Does not really do sorting. Find the alphabetically lowest
835      *	name among all the nic names found in a nic string.
836      *
837      * Return:
838      *	Nothing
839      *
840      * Side Effects:
841      *
842      *	lb->brd_name gets the new name found
843      */
844     
845     static void
846     sort_nic_names(lboard_t *lb)
847     {
848     	char 	*nic_str ;
849             char    *ptrs[MAX_NICS_PER_STRING] ;
850             char    name[MAX_NIC_NAME_LEN] ;
851             char    *tmp, *tmp1 ;
852     
853     	*name = 0 ;
854     
855     	/* Get the nic pointer from the lb */
856     
857     	if ((nic_str = get_nic_string(lb)) == NULL)
858     		return ;
859     
860             tmp = get_first_string(ptrs,
861                             get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ;
862     
863             if (tmp == NULL)
864     		return ;
865     
866             if  ( (tmp1 = strchr(tmp, ';')) ){
867                     strncpy(name, tmp, tmp1-tmp) ;
868                     name[tmp1-tmp] = 0 ;
869             } else {
870                     strncpy(name, tmp, (sizeof(name) -1)) ;
871                     name[sizeof(name)-1] = 0 ;
872             }
873     
874     	strcpy(lb->brd_name, name) ;
875     }
876     
877     
878     #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
879     
880     char brick_types[MAX_BRICK_TYPES + 1] = "crikxdp789012345";
881     
882     /*
883      * Format a module id for printing.
884      */
885     void
886     format_module_id(char *buffer, moduleid_t m, int fmt)
887     {
888     	int rack, position;
889     	char brickchar;
890     
891     	rack = MODULE_GET_RACK(m);
892     	ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
893     	brickchar = MODULE_GET_BTCHAR(m);
894     	position = MODULE_GET_BPOS(m);
895     
896     	if (fmt == MODULE_FORMAT_BRIEF) {
897     	    /* Brief module number format, eg. 002c15 */
898     
899     	    /* Decompress the rack number */
900     	    *buffer++ = '0' + RACK_GET_CLASS(rack);
901     	    *buffer++ = '0' + RACK_GET_GROUP(rack);
902     	    *buffer++ = '0' + RACK_GET_NUM(rack);
903     
904     	    /* Add the brick type */
905     	    *buffer++ = brickchar;
906     	}
907     	else if (fmt == MODULE_FORMAT_LONG) {
908     	    /* Fuller hwgraph format, eg. rack/002/bay/15 */
909     
910     	    strcpy(buffer, EDGE_LBL_RACK "/");  buffer += strlen(buffer);
911     
912     	    *buffer++ = '0' + RACK_GET_CLASS(rack);
913     	    *buffer++ = '0' + RACK_GET_GROUP(rack);
914     	    *buffer++ = '0' + RACK_GET_NUM(rack);
915     
916     	    strcpy(buffer, "/" EDGE_LBL_RPOS "/");  buffer += strlen(buffer);
917     	}
918     
919     	/* Add the bay position, using at least two digits */
920     	if (position < 10)
921     	    *buffer++ = '0';
922     	sprintf(buffer, "%d", position);
923     
924     }
925     
926     /*
927      * Parse a module id, in either brief or long form.
928      * Returns < 0 on error.
929      * The long form does not include a brick type, so it defaults to 0 (CBrick)
930      */
931     int
932     parse_module_id(char *buffer)
933     {
934     	unsigned int	v, rack, bay, type, form;
935     	moduleid_t	m;
936     	char 		c;
937     
938     	if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
939     		form = MODULE_FORMAT_LONG;
940     		buffer += strlen(EDGE_LBL_RACK "/");
941     
942     		/* A long module ID must be exactly 5 non-template chars. */
943     		if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
944     			return -1;
945     	}
946     	else {
947     		form = MODULE_FORMAT_BRIEF;
948     
949     		/* A brief module id must be exactly 6 characters */
950     		if (strlen(buffer) != 6)
951     			return -2;
952     	}
953     
954     	/* The rack number must be exactly 3 digits */
955     	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
956     		return -3;
957     
958     	rack = 0;
959     	v = *buffer++ - '0';
960     	if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
961     		return -4;
962     	RACK_ADD_CLASS(rack, v);
963     
964     	v = *buffer++ - '0';
965     	if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
966     		return -5;
967     	RACK_ADD_GROUP(rack, v);
968     
969     	v = *buffer++ - '0';
970     	/* rack numbers are 1-based */
971     	if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
972     		return -6;
973     	RACK_ADD_NUM(rack, v);
974     
975     	if (form == MODULE_FORMAT_BRIEF) {
976     		/* Next should be a module type character.  Accept ucase or lcase. */
977     		c = *buffer++;
978     		if (!isalpha(c))
979     			return -7;
980     
981     		/* strchr() returns a pointer into brick_types[], or NULL */
982     		type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
983     		if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
984     			return -8;
985     	}
986     	else {
987     		/* Hardcode the module type, and skip over the boilerplate */
988     		type = MODULE_CBRICK;
989     
990     		if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
991     			return -9;
992     
993     		buffer += strlen("/" EDGE_LBL_RPOS "/");
994     	}
995     		
996     	/* The bay number is last.  Make sure it's exactly two digits */
997     
998     	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
999     		return -10;
1000     
1001     	bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
1002     
1003     	if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
1004     		return -11;
1005     
1006     	m = RBT_TO_MODULE(rack, bay, type);
1007     
1008     	/* avoid sign extending the moduleid_t */
1009     	return (int)(unsigned short)m;
1010     }
1011     
1012     #else /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
1013     
1014     /*
1015      * Format a module id for printing.
1016      */
1017     void
1018     format_module_id(char *buffer, moduleid_t m, int fmt)
1019     {
1020         if (fmt == MODULE_FORMAT_BRIEF) {
1021     		sprintf(buffer, "%d", m);
1022         }
1023         else if (fmt == MODULE_FORMAT_LONG) {
1024     		sprintf(buffer, EDGE_LBL_MODULE "/%d", m);
1025         }
1026     }
1027     
1028     /*
1029      * Parse a module id, in either brief or long form.
1030      * Returns < 0 on error.
1031      */
1032     int
1033     parse_module_id(char *buffer)
1034     {
1035         moduleid_t m;
1036         char c;
1037     
1038         if (strstr(buffer, EDGE_LBL_MODULE "/") == buffer)
1039     	buffer += strlen(EDGE_LBL_MODULE "/");
1040     
1041         m = 0;
1042         while(c = *buffer++) {
1043     	if (!isdigit(c))
1044     	    return -1;
1045     	m = 10 * m + (c - '0');
1046         }
1047     
1048         /* avoid sign extending the moduleid_t */
1049         return (int)(unsigned short)m;
1050     }
1051     
1052     #endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
1053     
1054     
1055