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