2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
10 #include <linux/types.h>
11 #include <linux/ctype.h>
12 #include <asm/sn/sgi.h>
13 #include <asm/sn/sn_sal.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/sn_cpuid.h>
16 #include <asm/sn/iograph.h>
17 #include <asm/sn/hcl.h>
18 #include <asm/sn/labelcl.h>
19 #include <asm/sn/klconfig.h>
20 #include <asm/sn/nodepda.h>
21 #include <asm/sn/module.h>
22 #include <asm/sn/router.h>
23 #include <asm/sn/xtalk/xbow.h>
24 #include <asm/sn/ksys/l1.h>
29 #define DBG(x...) printk(x)
32 #endif /* DEBUG_KLGRAPH */
34 extern int numionodes
;
36 lboard_t
*root_lboard
[MAX_COMPACT_NODES
];
37 static int hasmetarouter
;
40 char brick_types
[MAX_BRICK_TYPES
+ 1] = "crikxdpn%#=vo^34567890123456789...";
43 find_lboard_any(lboard_t
*start
, unsigned char brd_type
)
45 /* Search all boards stored on this node. */
47 if (start
->brd_type
== brd_type
)
49 start
= KLCF_NEXT_ANY(start
);
53 return (lboard_t
*)NULL
;
57 find_lboard_nasid(lboard_t
*start
, nasid_t nasid
, unsigned char brd_type
)
61 if ((start
->brd_type
== brd_type
) &&
62 (start
->brd_nasid
== nasid
))
65 if (numionodes
== numnodes
)
66 start
= KLCF_NEXT_ANY(start
);
68 start
= KLCF_NEXT(start
);
72 return (lboard_t
*)NULL
;
76 find_lboard_class_any(lboard_t
*start
, unsigned char brd_type
)
78 /* Search all boards stored on this node. */
80 if (KLCLASS(start
->brd_type
) == KLCLASS(brd_type
))
82 start
= KLCF_NEXT_ANY(start
);
86 return (lboard_t
*)NULL
;
90 find_lboard_class_nasid(lboard_t
*start
, nasid_t nasid
, unsigned char brd_type
)
92 /* Search all boards stored on this node. */
94 if (KLCLASS(start
->brd_type
) == KLCLASS(brd_type
) &&
95 (start
->brd_nasid
== nasid
))
98 if (numionodes
== numnodes
)
99 start
= KLCF_NEXT_ANY(start
);
101 start
= KLCF_NEXT(start
);
104 /* Didn't find it. */
105 return (lboard_t
*)NULL
;
111 find_component(lboard_t
*brd
, klinfo_t
*kli
, unsigned char struct_type
)
115 if (kli
== (klinfo_t
*)NULL
) {
118 for (j
= 0; j
< KLCF_NUM_COMPS(brd
); j
++) {
119 if (kli
== KLCF_COMP(brd
, j
))
123 if (index
== KLCF_NUM_COMPS(brd
)) {
124 DBG("find_component: Bad pointer: 0x%p\n", kli
);
125 return (klinfo_t
*)NULL
;
127 index
++; /* next component */
130 for (; index
< KLCF_NUM_COMPS(brd
); index
++) {
131 kli
= KLCF_COMP(brd
, index
);
132 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
));
133 if (KLCF_COMP_TYPE(kli
) == struct_type
)
137 /* Didn't find it. */
138 return (klinfo_t
*)NULL
;
142 find_first_component(lboard_t
*brd
, unsigned char struct_type
)
144 return find_component(brd
, (klinfo_t
*)NULL
, struct_type
);
148 find_lboard_modslot(lboard_t
*start
, geoid_t geoid
)
150 /* Search all boards stored on this node. */
152 if (geo_cmp(start
->brd_geoid
, geoid
))
154 start
= KLCF_NEXT(start
);
157 /* Didn't find it. */
158 return (lboard_t
*)NULL
;
162 * Convert a NIC name to a name for use in the hardware graph.
165 nic_name_convert(char *old_name
, char *new_name
)
171 if ((old_name
[0] == '\0') || (old_name
[1] == '\0')) {
172 strcpy(new_name
, EDGE_LBL_XWIDGET
);
174 for (i
= 0; i
< strlen(old_name
); i
++) {
178 new_name
[i
] = tolower(c
);
188 * Since a bunch of boards made it out with weird names like
189 * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
190 * replace it with "baseio" to avoid confusion in the field.
191 * We also have to make sure we don't report media_io instead of
195 /* Skip underscores at the beginning of the name */
196 for (compare_ptr
= new_name
; (*compare_ptr
) == '_'; compare_ptr
++)
200 * Check for some names we need to replace. Early boards
201 * had junk following the name so check only the first
204 if (!strncmp(new_name
, "io6", 3) ||
205 !strncmp(new_name
, "mio", 3) ||
206 !strncmp(new_name
, "media_io", 8))
207 strcpy(new_name
, "baseio");
208 else if (!strncmp(new_name
, "divo", 4))
209 strcpy(new_name
, "divo") ;
216 * Completely disabled brds have their klconfig on
217 * some other nasid as they have no memory. But their
218 * actual nasid is hidden in the klconfig. Use this
219 * routine to get it. Works for normal boards too.
222 get_actual_nasid(lboard_t
*brd
)
227 return INVALID_NASID
;
229 /* find out if we are a completely disabled brd. */
231 hub
= (klhub_t
*)find_first_component(brd
, KLSTRUCT_HUB
);
233 return INVALID_NASID
;
234 if (!(hub
->hub_info
.flags
& KLINFO_ENABLE
)) /* disabled node brd */
235 return hub
->hub_info
.physid
;
237 return brd
->brd_nasid
;
241 xbow_port_io_enabled(nasid_t nasid
, int link
)
247 * look for boards that might contain an xbow or xbridge
249 brd
= find_lboard_nasid((lboard_t
*)KL_CONFIG_INFO(nasid
), nasid
, KLTYPE_IOBRICK_XBOW
);
250 if (brd
== NULL
) return 0;
252 if ((xbow_p
= (klxbow_t
*)find_component(brd
, NULL
, KLSTRUCT_XBOW
))
256 if (!XBOW_PORT_TYPE_IO(xbow_p
, link
) || !XBOW_PORT_IS_ENABLED(xbow_p
, link
))
263 board_to_path(lboard_t
*brd
, char *path
)
271 switch (KLCLASS(brd
->brd_type
)) {
274 board_name
= EDGE_LBL_NODE
;
277 if (brd
->brd_type
== KLTYPE_META_ROUTER
) {
278 board_name
= EDGE_LBL_META_ROUTER
;
280 } else if (brd
->brd_type
== KLTYPE_REPEATER_ROUTER
) {
281 board_name
= EDGE_LBL_REPEATER_ROUTER
;
284 board_name
= EDGE_LBL_ROUTER
;
286 case KLCLASS_MIDPLANE
:
287 board_name
= EDGE_LBL_MIDPLANE
;
290 board_name
= EDGE_LBL_IO
;
292 case KLCLASS_IOBRICK
:
293 if (brd
->brd_type
== KLTYPE_PXBRICK
)
294 board_name
= EDGE_LBL_PXBRICK
;
295 else if (brd
->brd_type
== KLTYPE_IXBRICK
)
296 board_name
= EDGE_LBL_IXBRICK
;
297 else if (brd
->brd_type
== KLTYPE_OPUSBRICK
)
298 board_name
= EDGE_LBL_OPUSBRICK
;
299 else if (brd
->brd_type
== KLTYPE_CGBRICK
)
300 board_name
= EDGE_LBL_CGBRICK
;
302 board_name
= EDGE_LBL_IOBRICK
;
305 board_name
= EDGE_LBL_UNKNOWN
;
308 modnum
= geo_module(brd
->brd_geoid
);
309 memset(buffer
, 0, 16);
310 format_module_id(buffer
, modnum
, MODULE_FORMAT_BRIEF
);
311 sprintf(path
, EDGE_LBL_MODULE
"/%s/" EDGE_LBL_SLAB
"/%d/%s", buffer
, geo_slab(brd
->brd_geoid
), board_name
);
317 * Get the serial number of the main component of a board
318 * Returns 0 if a valid serial number is found
320 * Assumptions: Nic manufacturing string has the following format
321 * *Serial:<serial_number>;*
324 component_serial_number_get(lboard_t
*board
,
325 klconf_off_t mfg_nic_offset
,
330 char *mfg_nic_string
;
331 char *serial_string
,*str
;
333 char *serial_pattern
= "Serial:";
335 /* We have an error on a null mfg nic offset */
338 /* Get the hub's manufacturing nic information
339 * which is in the form of a pre-formatted string
342 (char *)NODE_OFFSET_TO_K0(NASID_GET(board
),
344 /* There is no manufacturing nic info */
348 str
= mfg_nic_string
;
349 /* Look for the key pattern first (if it is specified)
350 * and then print the serial number corresponding to that.
352 if (strcmp(key_pattern
,"") &&
353 !(str
= strstr(mfg_nic_string
,key_pattern
)))
356 /* There is no serial number info in the manufacturing
359 if (!(serial_string
= strstr(str
,serial_pattern
)))
362 serial_string
= serial_string
+ strlen(serial_pattern
);
363 /* Copy the serial number information from the klconfig */
365 while (serial_string
[i
] != ';') {
366 serial_number
[i
] = serial_string
[i
];
369 serial_number
[i
] = 0;
374 * Get the serial number of a board
375 * Returns 0 if a valid serial number is found
380 board_serial_number_get(lboard_t
*board
,char *serial_number
)
382 ASSERT(board
&& serial_number
);
383 if (!board
|| !serial_number
)
386 strcpy(serial_number
,"");
387 switch(KLCLASS(board
->brd_type
)) {
388 case KLCLASS_CPU
: { /* Node board */
391 /* Get the hub component information */
392 hub
= (klhub_t
*)find_first_component(board
,
394 /* If we don't have a hub component on an IP27
395 * then we have a weird klconfig.
399 /* Get the serial number information from
400 * the hub's manufacturing nic info
402 if (component_serial_number_get(board
,
409 case KLCLASS_IO
: { /* IO board */
412 /* Get the bridge component information */
413 bridge
= (klbri_t
*)find_first_component(board
,
415 /* If we don't have a bridge component on an IO board
416 * then we have a weird klconfig.
420 /* Get the serial number information from
421 * the bridge's manufacturing nic info
423 if (component_serial_number_get(board
,
429 case KLCLASS_ROUTER
: { /* Router board */
432 /* Get the router component information */
433 router
= (klrou_t
*)find_first_component(board
,
435 /* If we don't have a router component on a router board
436 * then we have a weird klconfig.
440 /* Get the serial number information from
441 * the router's manufacturing nic info
443 if (component_serial_number_get(board
,
450 case KLCLASS_GFX
: { /* Gfx board */
453 /* Get the graphics component information */
454 graphics
= (klgfx_t
*)find_first_component(board
, KLSTRUCT_GFX
);
455 /* If we don't have a gfx component on a gfx board
456 * then we have a weird klconfig.
460 /* Get the serial number information from
461 * the graphics's manufacturing nic info
463 if (component_serial_number_get(board
,
464 graphics
->gfx_mfg_nic
,
471 strcpy(serial_number
,"");
478 * Format a module id for printing.
480 * There are three possible formats:
482 * MODULE_FORMAT_BRIEF is the brief 6-character format, including
483 * the actual brick-type as recorded in the
484 * moduleid_t, eg. 002c15 for a C-brick, or
485 * 101#17 for a PX-brick.
487 * MODULE_FORMAT_LONG is the hwgraph format, eg. rack/002/bay/15
488 * of rack/101/bay/17 (note that the brick
489 * type does not appear in this format).
491 * MODULE_FORMAT_LCD is like MODULE_FORMAT_BRIEF, except that it
492 * ensures that the module id provided appears
493 * exactly as it would on the LCD display of
494 * the corresponding brick, eg. still 002c15
495 * for a C-brick, but 101p17 for a PX-brick.
498 format_module_id(char *buffer
, moduleid_t m
, int fmt
)
501 unsigned char brickchar
;
503 rack
= MODULE_GET_RACK(m
);
504 ASSERT(MODULE_GET_BTYPE(m
) < MAX_BRICK_TYPES
);
505 brickchar
= MODULE_GET_BTCHAR(m
);
507 if (fmt
== MODULE_FORMAT_LCD
) {
508 /* Be sure we use the same brick type character as displayed
513 case L1_BRICKTYPE_PX
:
514 brickchar
= L1_BRICKTYPE_P
;
517 case L1_BRICKTYPE_IX
:
518 brickchar
= L1_BRICKTYPE_I
;
523 position
= MODULE_GET_BPOS(m
);
525 if ((fmt
== MODULE_FORMAT_BRIEF
) || (fmt
== MODULE_FORMAT_LCD
)) {
526 /* Brief module number format, eg. 002c15 */
528 /* Decompress the rack number */
529 *buffer
++ = '0' + RACK_GET_CLASS(rack
);
530 *buffer
++ = '0' + RACK_GET_GROUP(rack
);
531 *buffer
++ = '0' + RACK_GET_NUM(rack
);
533 /* Add the brick type */
534 *buffer
++ = brickchar
;
536 else if (fmt
== MODULE_FORMAT_LONG
) {
537 /* Fuller hwgraph format, eg. rack/002/bay/15 */
539 strcpy(buffer
, EDGE_LBL_RACK
"/"); buffer
+= strlen(buffer
);
541 *buffer
++ = '0' + RACK_GET_CLASS(rack
);
542 *buffer
++ = '0' + RACK_GET_GROUP(rack
);
543 *buffer
++ = '0' + RACK_GET_NUM(rack
);
545 strcpy(buffer
, "/" EDGE_LBL_RPOS
"/"); buffer
+= strlen(buffer
);
548 /* Add the bay position, using at least two digits */
551 sprintf(buffer
, "%d", position
);
556 cbrick_type_get_nasid(nasid_t nasid
)
561 module
= iomoduleid_get(nasid
);
563 return MODULE_CBRICK
;
565 t
= MODULE_GET_BTYPE(module
);
566 if ((char)t
== 'o') {
567 return MODULE_OPUSBRICK
;
569 return MODULE_CBRICK
;