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