http://www.hht-eu.com/pls/hht/docs/F3140/bcm963xx_Speedport500V.0.09.04L.300L01.V27_c...
[bcm963xx.git] / kernel / linux / arch / ia64 / sn / io / sn2 / klconflib.c
1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9
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>
25
26
27 #undef DEBUG_KLGRAPH
28 #ifdef DEBUG_KLGRAPH
29 #define DBG(x...) printk(x)
30 #else
31 #define DBG(x...)
32 #endif /* DEBUG_KLGRAPH */
33
34 extern int numionodes;
35
36 lboard_t *root_lboard[MAX_COMPACT_NODES];
37 static int hasmetarouter;
38
39
40 char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo^34567890123456789...";
41
42 lboard_t *
43 find_lboard_any(lboard_t *start, unsigned char brd_type)
44 {
45         /* Search all boards stored on this node. */
46         while (start) {
47                 if (start->brd_type == brd_type)
48                         return start;
49                 start = KLCF_NEXT_ANY(start);
50         }
51
52         /* Didn't find it. */
53         return (lboard_t *)NULL;
54 }
55
56 lboard_t *
57 find_lboard_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type)
58 {
59
60         while (start) {
61                 if ((start->brd_type == brd_type) && 
62                     (start->brd_nasid == nasid))
63                         return start;
64
65                 if (numionodes == numnodes)
66                         start = KLCF_NEXT_ANY(start);
67                 else
68                         start = KLCF_NEXT(start);
69         }
70
71         /* Didn't find it. */
72         return (lboard_t *)NULL;
73 }
74
75 lboard_t *
76 find_lboard_class_any(lboard_t *start, unsigned char brd_type)
77 {
78         /* Search all boards stored on this node. */
79         while (start) {
80                 if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
81                         return start;
82                 start = KLCF_NEXT_ANY(start);
83         }
84
85         /* Didn't find it. */
86         return (lboard_t *)NULL;
87 }
88
89 lboard_t *
90 find_lboard_class_nasid(lboard_t *start, nasid_t nasid, unsigned char brd_type)
91 {
92         /* Search all boards stored on this node. */
93         while (start) {
94                 if (KLCLASS(start->brd_type) == KLCLASS(brd_type) && 
95                     (start->brd_nasid == nasid))
96                         return start;
97
98                 if (numionodes == numnodes)
99                         start = KLCF_NEXT_ANY(start);
100                 else
101                         start = KLCF_NEXT(start);
102         }
103
104         /* Didn't find it. */
105         return (lboard_t *)NULL;
106 }
107
108
109
110 klinfo_t *
111 find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
112 {
113         int index, j;
114
115         if (kli == (klinfo_t *)NULL) {
116                 index = 0;
117         } else {
118                 for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
119                         if (kli == KLCF_COMP(brd, j))
120                                 break;
121                 }
122                 index = j;
123                 if (index == KLCF_NUM_COMPS(brd)) {
124                         DBG("find_component: Bad pointer: 0x%p\n", kli);
125                         return (klinfo_t *)NULL;
126                 }
127                 index++;        /* next component */
128         }
129         
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)
134                         return kli;
135         }
136
137         /* Didn't find it. */
138         return (klinfo_t *)NULL;
139 }
140
141 klinfo_t *
142 find_first_component(lboard_t *brd, unsigned char struct_type)
143 {
144         return find_component(brd, (klinfo_t *)NULL, struct_type);
145 }
146
147 lboard_t *
148 find_lboard_modslot(lboard_t *start, geoid_t geoid)
149 {
150         /* Search all boards stored on this node. */
151         while (start) {
152                 if (geo_cmp(start->brd_geoid, geoid))
153                         return start;
154                 start = KLCF_NEXT(start);
155         }
156
157         /* Didn't find it. */
158         return (lboard_t *)NULL;
159 }
160
161 /*
162  * Convert a NIC name to a name for use in the hardware graph.
163  */
164 void
165 nic_name_convert(char *old_name, char *new_name)
166 {
167         int i;
168         char c;
169         char *compare_ptr;
170
171         if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
172                 strcpy(new_name, EDGE_LBL_XWIDGET);
173         } else {
174                 for (i = 0; i < strlen(old_name); i++) {
175                         c = old_name[i];
176
177                         if (isalpha(c))
178                                 new_name[i] = tolower(c);
179                         else if (isdigit(c))
180                                 new_name[i] = c;
181                         else
182                                 new_name[i] = '_';
183                 }
184                 new_name[i] = '\0';
185         }
186
187         /* XXX -
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
192          * baseio.
193          */
194
195         /* Skip underscores at the beginning of the name */
196         for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
197                 ;
198
199         /*
200          * Check for some names we need to replace.  Early boards
201          * had junk following the name so check only the first
202          * characters.
203          */
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") ;
210
211 }
212
213 /*
214  * get_actual_nasid
215  *
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.
220  */
221 nasid_t
222 get_actual_nasid(lboard_t *brd)
223 {
224         klhub_t *hub ;
225
226         if (!brd)
227                 return INVALID_NASID ;
228
229         /* find out if we are a completely disabled brd. */
230
231         hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
232         if (!hub)
233                 return INVALID_NASID ;
234         if (!(hub->hub_info.flags & KLINFO_ENABLE))     /* disabled node brd */
235                 return hub->hub_info.physid ;
236         else
237                 return brd->brd_nasid ;
238 }
239
240 int
241 xbow_port_io_enabled(nasid_t nasid, int link)
242 {
243         lboard_t *brd;
244         klxbow_t *xbow_p;
245
246         /*
247          * look for boards that might contain an xbow or xbridge
248          */
249         brd = find_lboard_nasid((lboard_t *)KL_CONFIG_INFO(nasid), nasid, KLTYPE_IOBRICK_XBOW);
250         if (brd == NULL) return 0;
251                 
252         if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
253             == NULL)
254             return 0;
255
256         if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
257             return 0;
258
259         return 1;
260 }
261
262 void
263 board_to_path(lboard_t *brd, char *path)
264 {
265         moduleid_t modnum;
266         char *board_name;
267         char buffer[16];
268
269         ASSERT(brd);
270
271         switch (KLCLASS(brd->brd_type)) {
272
273                 case KLCLASS_NODE:
274                         board_name = EDGE_LBL_NODE;
275                         break;
276                 case KLCLASS_ROUTER:
277                         if (brd->brd_type == KLTYPE_META_ROUTER) {
278                                 board_name = EDGE_LBL_META_ROUTER;
279                                 hasmetarouter++;
280                         } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
281                                 board_name = EDGE_LBL_REPEATER_ROUTER;
282                                 hasmetarouter++;
283                         } else
284                                 board_name = EDGE_LBL_ROUTER;
285                         break;
286                 case KLCLASS_MIDPLANE:
287                         board_name = EDGE_LBL_MIDPLANE;
288                         break;
289                 case KLCLASS_IO:
290                         board_name = EDGE_LBL_IO;
291                         break;
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;
301                         else 
302                                 board_name = EDGE_LBL_IOBRICK;
303                         break;
304                 default:
305                         board_name = EDGE_LBL_UNKNOWN;
306         }
307                         
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);
312 }
313
314 #define MHZ     1000000
315
316 /*
317  * Get the serial number of the main  component of a board
318  * Returns 0 if a valid serial number is found
319  * 1 otherwise.
320  * Assumptions: Nic manufacturing string  has the following format
321  *                      *Serial:<serial_number>;*
322  */
323 static int
324 component_serial_number_get(lboard_t            *board,
325                             klconf_off_t        mfg_nic_offset,
326                             char                *serial_number,
327                             char                *key_pattern)
328 {
329
330         char    *mfg_nic_string;
331         char    *serial_string,*str;
332         int     i;
333         char    *serial_pattern = "Serial:";
334
335         /* We have an error on a null mfg nic offset */
336         if (!mfg_nic_offset)
337                 return(1);
338         /* Get the hub's manufacturing nic information
339          * which is in the form of a pre-formatted string
340          */
341         mfg_nic_string = 
342                 (char *)NODE_OFFSET_TO_K0(NASID_GET(board),
343                                           mfg_nic_offset);
344         /* There is no manufacturing nic info */
345         if (!mfg_nic_string)
346                 return(1);
347
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.
351          */
352         if (strcmp(key_pattern,"") && 
353             !(str = strstr(mfg_nic_string,key_pattern)))
354                 return(1);
355
356         /* There is no serial number info in the manufacturing
357          * nic info
358          */
359         if (!(serial_string = strstr(str,serial_pattern)))
360                 return(1);
361
362         serial_string = serial_string + strlen(serial_pattern);
363         /*  Copy the serial number information from the klconfig */
364         i = 0;
365         while (serial_string[i] != ';') {
366                 serial_number[i] = serial_string[i];
367                 i++;
368         }
369         serial_number[i] = 0;
370         
371         return(0);
372 }
373 /*
374  * Get the serial number of a board
375  * Returns 0 if a valid serial number is found
376  * 1 otherwise.
377  */
378
379 int
380 board_serial_number_get(lboard_t *board,char *serial_number)
381 {
382         ASSERT(board && serial_number);
383         if (!board || !serial_number)
384                 return(1);
385
386         strcpy(serial_number,"");
387         switch(KLCLASS(board->brd_type)) {
388         case KLCLASS_CPU: {     /* Node board */
389                 klhub_t *hub;
390                 
391                 /* Get the hub component information */
392                 hub = (klhub_t *)find_first_component(board,
393                                                       KLSTRUCT_HUB);
394                 /* If we don't have a hub component on an IP27
395                  * then we have a weird klconfig.
396                  */
397                 if (!hub)
398                         return(1);
399                 /* Get the serial number information from
400                  * the hub's manufacturing nic info
401                  */
402                 if (component_serial_number_get(board,
403                                                 hub->hub_mfg_nic,
404                                                 serial_number,
405                                                 "IP37"))
406                                 return(1);
407                 break;
408         }
409         case KLCLASS_IO: {      /* IO board */
410                 klbri_t *bridge;
411                 
412                 /* Get the bridge component information */
413                 bridge = (klbri_t *)find_first_component(board,
414                                                          KLSTRUCT_BRI);
415                 /* If we don't have a bridge component on an IO board
416                  * then we have a weird klconfig.
417                  */
418                 if (!bridge)
419                         return(1);
420                 /* Get the serial number information from
421                  * the bridge's manufacturing nic info
422                  */
423                 if (component_serial_number_get(board,
424                                         bridge->bri_mfg_nic,
425                                         serial_number, ""))
426                         return(1);
427                 break;
428         }
429         case KLCLASS_ROUTER: {  /* Router board */
430                 klrou_t *router;        
431                 
432                 /* Get the router component information */
433                 router = (klrou_t *)find_first_component(board,
434                                                          KLSTRUCT_ROU);
435                 /* If we don't have a router component on a router board
436                  * then we have a weird klconfig.
437                  */
438                 if (!router)
439                         return(1);
440                 /* Get the serial number information from
441                  * the router's manufacturing nic info
442                  */
443                 if (component_serial_number_get(board,
444                                                 router->rou_mfg_nic,
445                                                 serial_number,
446                                                 ""))
447                         return(1);
448                 break;
449         }
450         case KLCLASS_GFX: {     /* Gfx board */
451                 klgfx_t *graphics;
452                 
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.
457                  */
458                 if (!graphics)
459                         return(1);
460                 /* Get the serial number information from
461                  * the graphics's manufacturing nic info
462                  */
463                 if (component_serial_number_get(board,
464                                                 graphics->gfx_mfg_nic,
465                                                 serial_number,
466                                                 ""))
467                         return(1);
468                 break;
469         }
470         default:
471                 strcpy(serial_number,"");
472                 break;
473         }
474         return(0);
475 }
476
477 /*
478  * Format a module id for printing.
479  *
480  * There are three possible formats:
481  *
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.
486  *
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).
490  *
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.
496  */
497 void
498 format_module_id(char *buffer, moduleid_t m, int fmt)
499 {
500         int rack, position;
501         unsigned char brickchar;
502
503         rack = MODULE_GET_RACK(m);
504         ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
505         brickchar = MODULE_GET_BTCHAR(m);
506
507         if (fmt == MODULE_FORMAT_LCD) {
508             /* Be sure we use the same brick type character as displayed
509              * on the brick's LCD
510              */
511             switch (brickchar) 
512             {
513             case L1_BRICKTYPE_PX:
514                 brickchar = L1_BRICKTYPE_P;
515                 break;
516
517             case L1_BRICKTYPE_IX:
518                 brickchar = L1_BRICKTYPE_I;
519                 break;
520             }
521         }
522
523         position = MODULE_GET_BPOS(m);
524
525         if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) {
526             /* Brief module number format, eg. 002c15 */
527
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);
532
533             /* Add the brick type */
534             *buffer++ = brickchar;
535         }
536         else if (fmt == MODULE_FORMAT_LONG) {
537             /* Fuller hwgraph format, eg. rack/002/bay/15 */
538
539             strcpy(buffer, EDGE_LBL_RACK "/");  buffer += strlen(buffer);
540
541             *buffer++ = '0' + RACK_GET_CLASS(rack);
542             *buffer++ = '0' + RACK_GET_GROUP(rack);
543             *buffer++ = '0' + RACK_GET_NUM(rack);
544
545             strcpy(buffer, "/" EDGE_LBL_RPOS "/");  buffer += strlen(buffer);
546         }
547
548         /* Add the bay position, using at least two digits */
549         if (position < 10)
550             *buffer++ = '0';
551         sprintf(buffer, "%d", position);
552
553 }
554
555 int
556 cbrick_type_get_nasid(nasid_t nasid)
557 {
558         moduleid_t module;
559         int t;
560
561         module = iomoduleid_get(nasid);
562         if (module < 0 ) {
563                 return MODULE_CBRICK;
564         }
565         t = MODULE_GET_BTYPE(module);
566         if ((char)t == 'o') {
567                 return MODULE_OPUSBRICK;
568         } else {
569                 return MODULE_CBRICK;
570         }
571         return -1;
572 }