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-2003 Silicon Graphics, Inc. All rights reserved.
8 */
9
10
11 #include <linux/types.h>
12 #include <linux/ctype.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/sn_sal.h>
15 #include <asm/sn/io.h>
16 #include <asm/sn/sn_cpuid.h>
17 #include <asm/sn/iograph.h>
18 #include <asm/sn/invent.h>
19 #include <asm/sn/hcl.h>
20 #include <asm/sn/labelcl.h>
21 #include <asm/sn/klconfig.h>
22 #include <asm/sn/nodepda.h>
23 #include <asm/sn/module.h>
24 #include <asm/sn/router.h>
25 #include <asm/sn/xtalk/xbow.h>
26
27
28 #define LDEBUG 0
29 #define NIC_UNKNOWN ((nic_t) -1)
30
31 #undef DEBUG_KLGRAPH
32 #ifdef DEBUG_KLGRAPH
33 #define DBG(x...) printk(x)
34 #else
35 #define DBG(x...)
36 #endif /* DEBUG_KLGRAPH */
37
38 u64 klgraph_addr[MAX_COMPACT_NODES];
39 static int hasmetarouter;
40
41
42 char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo2345";
43
44 lboard_t *
find_lboard(lboard_t * start,unsigned char brd_type)45 find_lboard(lboard_t *start, unsigned char brd_type)
46 {
47 /* Search all boards stored on this node. */
48 while (start) {
49 if (start->brd_type == brd_type)
50 return start;
51 start = KLCF_NEXT(start);
52 }
53
54 /* Didn't find it. */
55 return (lboard_t *)NULL;
56 }
57
58 lboard_t *
find_lboard_class(lboard_t * start,unsigned char brd_type)59 find_lboard_class(lboard_t *start, unsigned char brd_type)
60 {
61 /* Search all boards stored on this node. */
62 while (start) {
63 if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
64 return start;
65 start = KLCF_NEXT(start);
66 }
67
68 /* Didn't find it. */
69 return (lboard_t *)NULL;
70 }
71
72 klinfo_t *
find_component(lboard_t * brd,klinfo_t * kli,unsigned char struct_type)73 find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
74 {
75 int index, j;
76
77 if (kli == (klinfo_t *)NULL) {
78 index = 0;
79 } else {
80 for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
81 if (kli == KLCF_COMP(brd, j))
82 break;
83 }
84 index = j;
85 if (index == KLCF_NUM_COMPS(brd)) {
86 DBG("find_component: Bad pointer: 0x%p\n", kli);
87 return (klinfo_t *)NULL;
88 }
89 index++; /* next component */
90 }
91
92 for (; index < KLCF_NUM_COMPS(brd); index++) {
93 kli = KLCF_COMP(brd, index);
94 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));
95 if (KLCF_COMP_TYPE(kli) == struct_type)
96 return kli;
97 }
98
99 /* Didn't find it. */
100 return (klinfo_t *)NULL;
101 }
102
103 klinfo_t *
find_first_component(lboard_t * brd,unsigned char struct_type)104 find_first_component(lboard_t *brd, unsigned char struct_type)
105 {
106 return find_component(brd, (klinfo_t *)NULL, struct_type);
107 }
108
109 lboard_t *
find_lboard_modslot(lboard_t * start,geoid_t geoid)110 find_lboard_modslot(lboard_t *start, geoid_t geoid)
111 {
112 /* Search all boards stored on this node. */
113 while (start) {
114 if (geo_cmp(start->brd_geoid, geoid))
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 *
find_lboard_module(lboard_t * start,geoid_t geoid)124 find_lboard_module(lboard_t *start, geoid_t geoid)
125 {
126 /* Search all boards stored on this node. */
127 while (start) {
128 if (geo_cmp(start->brd_geoid, geoid))
129 return start;
130 start = KLCF_NEXT(start);
131 }
132
133 /* Didn't find it. */
134 return (lboard_t *)NULL;
135 }
136
137 /*
138 * Convert a NIC name to a name for use in the hardware graph.
139 */
140 void
nic_name_convert(char * old_name,char * new_name)141 nic_name_convert(char *old_name, char *new_name)
142 {
143 int i;
144 char c;
145 char *compare_ptr;
146
147 if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
148 strcpy(new_name, EDGE_LBL_XWIDGET);
149 } else {
150 for (i = 0; i < strlen(old_name); i++) {
151 c = old_name[i];
152
153 if (isalpha(c))
154 new_name[i] = tolower(c);
155 else if (isdigit(c))
156 new_name[i] = c;
157 else
158 new_name[i] = '_';
159 }
160 new_name[i] = '\0';
161 }
162
163 /* XXX -
164 * Since a bunch of boards made it out with weird names like
165 * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
166 * replace it with "baseio" to avoid confusion in the field.
167 * We also have to make sure we don't report media_io instead of
168 * baseio.
169 */
170
171 /* Skip underscores at the beginning of the name */
172 for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
173 ;
174
175 /*
176 * Check for some names we need to replace. Early boards
177 * had junk following the name so check only the first
178 * characters.
179 */
180 if (!strncmp(new_name, "io6", 3) ||
181 !strncmp(new_name, "mio", 3) ||
182 !strncmp(new_name, "media_io", 8))
183 strcpy(new_name, "baseio");
184 else if (!strncmp(new_name, "divo", 4))
185 strcpy(new_name, "divo") ;
186
187 }
188
189 /*
190 * get_actual_nasid
191 *
192 * Completely disabled brds have their klconfig on
193 * some other nasid as they have no memory. But their
194 * actual nasid is hidden in the klconfig. Use this
195 * routine to get it. Works for normal boards too.
196 */
197 nasid_t
get_actual_nasid(lboard_t * brd)198 get_actual_nasid(lboard_t *brd)
199 {
200 klhub_t *hub ;
201
202 if (!brd)
203 return INVALID_NASID ;
204
205 /* find out if we are a completely disabled brd. */
206
207 hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
208 if (!hub)
209 return INVALID_NASID ;
210 if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */
211 return hub->hub_info.physid ;
212 else
213 return brd->brd_nasid ;
214 }
215
216 int
xbow_port_io_enabled(nasid_t nasid,int link)217 xbow_port_io_enabled(nasid_t nasid, int link)
218 {
219 lboard_t *brd;
220 klxbow_t *xbow_p;
221
222 /*
223 * look for boards that might contain an xbow or xbridge
224 */
225 brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
226 if (brd == NULL) return 0;
227
228 if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
229 == NULL)
230 return 0;
231
232 if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
233 return 0;
234
235 return 1;
236 }
237
238 void
board_to_path(lboard_t * brd,char * path)239 board_to_path(lboard_t *brd, char *path)
240 {
241 moduleid_t modnum;
242 char *board_name;
243 char buffer[16];
244
245 ASSERT(brd);
246
247 switch (KLCLASS(brd->brd_type)) {
248
249 case KLCLASS_NODE:
250 board_name = EDGE_LBL_NODE;
251 break;
252 case KLCLASS_ROUTER:
253 if (brd->brd_type == KLTYPE_META_ROUTER) {
254 board_name = EDGE_LBL_META_ROUTER;
255 hasmetarouter++;
256 } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
257 board_name = EDGE_LBL_REPEATER_ROUTER;
258 hasmetarouter++;
259 } else
260 board_name = EDGE_LBL_ROUTER;
261 break;
262 case KLCLASS_MIDPLANE:
263 board_name = EDGE_LBL_MIDPLANE;
264 break;
265 case KLCLASS_IO:
266 board_name = EDGE_LBL_IO;
267 break;
268 case KLCLASS_IOBRICK:
269 if (brd->brd_type == KLTYPE_PXBRICK)
270 board_name = EDGE_LBL_PXBRICK;
271 else if (brd->brd_type == KLTYPE_IXBRICK)
272 board_name = EDGE_LBL_IXBRICK;
273 else if (brd->brd_type == KLTYPE_PBRICK)
274 board_name = EDGE_LBL_PBRICK;
275 else if (brd->brd_type == KLTYPE_IBRICK)
276 board_name = EDGE_LBL_IBRICK;
277 else if (brd->brd_type == KLTYPE_XBRICK)
278 board_name = EDGE_LBL_XBRICK;
279 else if (brd->brd_type == KLTYPE_PEBRICK)
280 board_name = EDGE_LBL_PEBRICK;
281 else if (brd->brd_type == KLTYPE_OPUSBRICK)
282 board_name = EDGE_LBL_OPUSBRICK;
283 else if (brd->brd_type == KLTYPE_CGBRICK)
284 board_name = EDGE_LBL_CGBRICK;
285 else
286 board_name = EDGE_LBL_IOBRICK;
287 break;
288 default:
289 board_name = EDGE_LBL_UNKNOWN;
290 }
291
292 modnum = geo_module(brd->brd_geoid);
293 memset(buffer, 0, 16);
294 format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
295 sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
296 }
297
298 #define MHZ 1000000
299
300
301 /* Get the canonical hardware graph name for the given pci component
302 * on the given io board.
303 */
304 void
device_component_canonical_name_get(lboard_t * brd,klinfo_t * component,char * name)305 device_component_canonical_name_get(lboard_t *brd,
306 klinfo_t *component,
307 char *name)
308 {
309 slotid_t slot;
310 char board_name[20];
311
312 ASSERT(brd);
313
314 /* Convert the [ CLASS | TYPE ] kind of slotid
315 * into a string
316 */
317 slot = brd->brd_slot;
318
319 /* Get the io board name */
320 if (!brd || (brd->brd_sversion < 2)) {
321 strcpy(name, EDGE_LBL_XWIDGET);
322 } else {
323 nic_name_convert(brd->brd_name, board_name);
324 }
325
326 /* Give out the canonical name of the pci device*/
327 sprintf(name,
328 "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
329 EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
330 geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid),
331 board_name, KLCF_BRIDGE_W_ID(component));
332 }
333
334 /*
335 * Get the serial number of the main component of a board
336 * Returns 0 if a valid serial number is found
337 * 1 otherwise.
338 * Assumptions: Nic manufacturing string has the following format
339 * *Serial:<serial_number>;*
340 */
341 static int
component_serial_number_get(lboard_t * board,klconf_off_t mfg_nic_offset,char * serial_number,char * key_pattern)342 component_serial_number_get(lboard_t *board,
343 klconf_off_t mfg_nic_offset,
344 char *serial_number,
345 char *key_pattern)
346 {
347
348 char *mfg_nic_string;
349 char *serial_string,*str;
350 int i;
351 char *serial_pattern = "Serial:";
352
353 /* We have an error on a null mfg nic offset */
354 if (!mfg_nic_offset)
355 return(1);
356 /* Get the hub's manufacturing nic information
357 * which is in the form of a pre-formatted string
358 */
359 mfg_nic_string =
360 (char *)NODE_OFFSET_TO_K0(NASID_GET(board),
361 mfg_nic_offset);
362 /* There is no manufacturing nic info */
363 if (!mfg_nic_string)
364 return(1);
365
366 str = mfg_nic_string;
367 /* Look for the key pattern first (if it is specified)
368 * and then print the serial number corresponding to that.
369 */
370 if (strcmp(key_pattern,"") &&
371 !(str = strstr(mfg_nic_string,key_pattern)))
372 return(1);
373
374 /* There is no serial number info in the manufacturing
375 * nic info
376 */
377 if (!(serial_string = strstr(str,serial_pattern)))
378 return(1);
379
380 serial_string = serial_string + strlen(serial_pattern);
381 /* Copy the serial number information from the klconfig */
382 i = 0;
383 while (serial_string[i] != ';') {
384 serial_number[i] = serial_string[i];
385 i++;
386 }
387 serial_number[i] = 0;
388
389 return(0);
390 }
391 /*
392 * Get the serial number of a board
393 * Returns 0 if a valid serial number is found
394 * 1 otherwise.
395 */
396
397 int
board_serial_number_get(lboard_t * board,char * serial_number)398 board_serial_number_get(lboard_t *board,char *serial_number)
399 {
400 ASSERT(board && serial_number);
401 if (!board || !serial_number)
402 return(1);
403
404 strcpy(serial_number,"");
405 switch(KLCLASS(board->brd_type)) {
406 case KLCLASS_CPU: { /* Node board */
407 klhub_t *hub;
408
409 if (board->brd_type == KLTYPE_TIO) {
410 printk("*****board_serial_number_get: Need to support TIO.*****\n");
411 strcpy(serial_number,"");
412 return(0);
413 }
414
415 /* Get the hub component information */
416 hub = (klhub_t *)find_first_component(board,
417 KLSTRUCT_HUB);
418 /* If we don't have a hub component on an IP27
419 * then we have a weird klconfig.
420 */
421 if (!hub)
422 return(1);
423 /* Get the serial number information from
424 * the hub's manufacturing nic info
425 */
426 if (component_serial_number_get(board,
427 hub->hub_mfg_nic,
428 serial_number,
429 "IP37"))
430 return(1);
431 break;
432 }
433 case KLCLASS_IO: { /* IO board */
434 if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
435 /* Special case for TPU boards */
436 kltpu_t *tpu;
437
438 /* Get the tpu component information */
439 tpu = (kltpu_t *)find_first_component(board,
440 KLSTRUCT_TPU);
441 /* If we don't have a tpu component on a tpu board
442 * then we have a weird klconfig.
443 */
444 if (!tpu)
445 return(1);
446 /* Get the serial number information from
447 * the tpu's manufacturing nic info
448 */
449 if (component_serial_number_get(board,
450 tpu->tpu_mfg_nic,
451 serial_number,
452 ""))
453 return(1);
454 break;
455 } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
456 (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
457 /* Special case for GSN boards */
458 klgsn_t *gsn;
459
460 /* Get the gsn component information */
461 gsn = (klgsn_t *)find_first_component(board,
462 ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
463 KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
464 /* If we don't have a gsn component on a gsn board
465 * then we have a weird klconfig.
466 */
467 if (!gsn)
468 return(1);
469 /* Get the serial number information from
470 * the gsn's manufacturing nic info
471 */
472 if (component_serial_number_get(board,
473 gsn->gsn_mfg_nic,
474 serial_number,
475 ""))
476 return(1);
477 break;
478 } else {
479 klbri_t *bridge;
480
481 /* Get the bridge component information */
482 bridge = (klbri_t *)find_first_component(board,
483 KLSTRUCT_BRI);
484 /* If we don't have a bridge component on an IO board
485 * then we have a weird klconfig.
486 */
487 if (!bridge)
488 return(1);
489 /* Get the serial number information from
490 * the bridge's manufacturing nic info
491 */
492 if (component_serial_number_get(board,
493 bridge->bri_mfg_nic,
494 serial_number,
495 ""))
496 return(1);
497 break;
498 }
499 }
500 case KLCLASS_ROUTER: { /* Router board */
501 klrou_t *router;
502
503 /* Get the router component information */
504 router = (klrou_t *)find_first_component(board,
505 KLSTRUCT_ROU);
506 /* If we don't have a router component on a router board
507 * then we have a weird klconfig.
508 */
509 if (!router)
510 return(1);
511 /* Get the serial number information from
512 * the router's manufacturing nic info
513 */
514 if (component_serial_number_get(board,
515 router->rou_mfg_nic,
516 serial_number,
517 ""))
518 return(1);
519 break;
520 }
521 case KLCLASS_GFX: { /* Gfx board */
522 klgfx_t *graphics;
523
524 /* Get the graphics component information */
525 graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
526 /* If we don't have a gfx component on a gfx board
527 * then we have a weird klconfig.
528 */
529 if (!graphics)
530 return(1);
531 /* Get the serial number information from
532 * the graphics's manufacturing nic info
533 */
534 if (component_serial_number_get(board,
535 graphics->gfx_mfg_nic,
536 serial_number,
537 ""))
538 return(1);
539 break;
540 }
541 default:
542 strcpy(serial_number,"");
543 break;
544 }
545 return(0);
546 }
547
548 #include "asm/sn/sn_private.h"
549
550 /*
551 * Format a module id for printing.
552 */
553 void
format_module_id(char * buffer,moduleid_t m,int fmt)554 format_module_id(char *buffer, moduleid_t m, int fmt)
555 {
556 int rack, position;
557 char brickchar;
558
559 rack = MODULE_GET_RACK(m);
560 ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
561 brickchar = MODULE_GET_BTCHAR(m);
562
563 position = MODULE_GET_BPOS(m);
564
565 if (fmt == MODULE_FORMAT_BRIEF) {
566 /* Brief module number format, eg. 002c15 */
567
568 /* Decompress the rack number */
569 *buffer++ = '0' + RACK_GET_CLASS(rack);
570 *buffer++ = '0' + RACK_GET_GROUP(rack);
571 *buffer++ = '0' + RACK_GET_NUM(rack);
572
573 /* Add the brick type */
574 *buffer++ = brickchar;
575 }
576 else if (fmt == MODULE_FORMAT_LONG) {
577 /* Fuller hwgraph format, eg. rack/002/bay/15 */
578
579 strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer);
580
581 *buffer++ = '0' + RACK_GET_CLASS(rack);
582 *buffer++ = '0' + RACK_GET_GROUP(rack);
583 *buffer++ = '0' + RACK_GET_NUM(rack);
584
585 strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer);
586 }
587
588 /* Add the bay position, using at least two digits */
589 if (position < 10)
590 *buffer++ = '0';
591 sprintf(buffer, "%d", position);
592
593 }
594
595 /*
596 * Parse a module id, in either brief or long form.
597 * Returns < 0 on error.
598 * The long form does not include a brick type, so it defaults to 0 (CBrick)
599 */
600 int
parse_module_id(char * buffer)601 parse_module_id(char *buffer)
602 {
603 unsigned int v, rack, bay, type, form;
604 moduleid_t m;
605 char c;
606
607 if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
608 form = MODULE_FORMAT_LONG;
609 buffer += strlen(EDGE_LBL_RACK "/");
610
611 /* A long module ID must be exactly 5 non-template chars. */
612 if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
613 return -1;
614 }
615 else {
616 form = MODULE_FORMAT_BRIEF;
617
618 /* A brief module id must be exactly 6 characters */
619 if (strlen(buffer) != 6)
620 return -2;
621 }
622
623 /* The rack number must be exactly 3 digits */
624 if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
625 return -3;
626
627 rack = 0;
628 v = *buffer++ - '0';
629 if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
630 return -4;
631 RACK_ADD_CLASS(rack, v);
632
633 v = *buffer++ - '0';
634 if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
635 return -5;
636 RACK_ADD_GROUP(rack, v);
637
638 v = *buffer++ - '0';
639 /* rack numbers are 1-based */
640 if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
641 return -6;
642 RACK_ADD_NUM(rack, v);
643
644 if (form == MODULE_FORMAT_BRIEF) {
645 /* Next should be a module type character. Accept ucase or lcase. */
646 c = *buffer++;
647 if (!isalpha(c))
648 return -7;
649
650 /* strchr() returns a pointer into brick_types[], or NULL */
651 type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
652 if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
653 return -8;
654 }
655 else {
656 /* Hardcode the module type, and skip over the boilerplate */
657 type = MODULE_CBRICK;
658
659 if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
660 return -9;
661
662 buffer += strlen("/" EDGE_LBL_RPOS "/");
663 }
664
665 /* The bay number is last. Make sure it's exactly two digits */
666
667 if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
668 return -10;
669
670 bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
671
672 if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
673 return -11;
674
675 m = RBT_TO_MODULE(rack, bay, type);
676
677 /* avoid sign extending the moduleid_t */
678 return (int)(unsigned short)m;
679 }
680