more changes on original files
[linux-2.4.git] / arch / ia64 / sn / io / sn2 / klgraph.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-2003 Silicon Graphics, Inc. All rights reserved.
8  */
9
10 /*
11  * klgraph.c-
12  *      This file specifies the interface between the kernel and the PROM's
13  *      configuration data structures.
14  */
15
16 #include <linux/types.h>
17 #include <linux/slab.h>
18 #include <asm/sn/sgi.h>
19 #include <asm/sn/sn_sal.h>
20 #include <asm/sn/io.h>
21 #include <asm/sn/iograph.h>
22 #include <asm/sn/invent.h>
23 #include <asm/sn/hcl.h>
24 #include <asm/sn/labelcl.h>
25 #include <asm/sn/kldir.h>
26 #include <asm/sn/klconfig.h>
27 #include <asm/sn/router.h>
28 #include <asm/sn/xtalk/xbow.h>
29 #include <asm/sn/hcl_util.h>
30
31 // #define KLGRAPH_DEBUG 1
32 #ifdef KLGRAPH_DEBUG
33 #define GRPRINTF(x)     printk x
34 #define CE_GRPANIC      CE_PANIC
35 #else
36 #define GRPRINTF(x)
37 #define CE_GRPANIC      CE_PANIC
38 #endif
39
40 #include <asm/sn/sn_private.h>
41
42 extern char arg_maxnodes[];
43 extern u64 klgraph_addr[];
44 void mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid);
45 extern int is_specified(char *);
46
47
48 /*
49  * Support for verbose inventory via hardware graph. 
50  * klhwg_invent_alloc allocates the necessary size of inventory information
51  * and fills in the generic information.
52  */
53 invent_generic_t *
54 klhwg_invent_alloc(cnodeid_t cnode, int class, int size)
55 {
56         invent_generic_t *invent;
57
58         invent = kmalloc(size, GFP_KERNEL);
59         if (!invent) return NULL;
60         
61         invent->ig_module = NODE_MODULEID(cnode);
62         invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode));
63         invent->ig_invclass = class;
64
65         return invent;
66 }
67
68 /*
69  * Add detailed disabled cpu inventory info to the hardware graph.
70  */
71 void
72 klhwg_disabled_cpu_invent_info(vertex_hdl_t cpuv,
73                                cnodeid_t cnode,
74                                klcpu_t *cpu, slotid_t slot)
75 {
76         invent_cpuinfo_t *cpu_invent;
77         diag_inv_t       *diag_invent;
78
79         cpu_invent = (invent_cpuinfo_t *)
80         klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
81         if (!cpu_invent)
82                 return;
83
84         /* Diag information on this processor */
85         diag_invent = (diag_inv_t *)
86         klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t));
87
88         if (!diag_invent)
89                 return;
90
91
92         /* Disabled CPU */
93         cpu_invent->ic_gen.ig_flag = 0x0;
94         cpu_invent->ic_gen.ig_slot = slot;
95         cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
96         cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
97         cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
98
99         cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
100         cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
101         cpu_invent->ic_slice = cpu->cpu_info.physid;
102
103         /* Disabled CPU label */
104         hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
105                         (arbitrary_info_t) cpu_invent);
106         hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
107                         sizeof(invent_cpuinfo_t));
108
109         /* Diagval label - stores reason for disable +{virt,phys}id +diagval*/
110         hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL,
111                         (arbitrary_info_t) diag_invent);
112
113         hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL,
114                         sizeof(diag_inv_t));
115 }
116
117 /*
118  * Add detailed cpu inventory info to the hardware graph.
119  */
120 void
121 klhwg_cpu_invent_info(vertex_hdl_t cpuv,
122                         cnodeid_t cnode,
123                         klcpu_t *cpu)
124 {
125         invent_cpuinfo_t *cpu_invent;
126
127         cpu_invent = (invent_cpuinfo_t *)
128                 klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
129         if (!cpu_invent)
130                 return;
131
132         if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu))
133                 cpu_invent->ic_gen.ig_flag = INVENT_ENABLED;
134         else
135                 cpu_invent->ic_gen.ig_flag = 0x0;
136
137         cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
138         cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
139         cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
140
141         cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
142         cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
143         cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid);
144
145         hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
146                         (arbitrary_info_t) cpu_invent);
147         hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
148                         sizeof(invent_cpuinfo_t));
149 }
150
151 /* 
152  * Add information about the baseio prom version number
153  * as a part of detailed inventory info in the hwgraph.
154  */
155 void
156 klhwg_baseio_inventory_add(vertex_hdl_t baseio_vhdl,cnodeid_t cnode)
157 {
158         invent_miscinfo_t       *baseio_inventory;
159         unsigned char           version = 0,revision = 0;
160
161         /* Allocate memory for the "detailed inventory" info
162          * for the baseio
163          */
164         baseio_inventory = (invent_miscinfo_t *) 
165                 klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
166         baseio_inventory->im_type = INV_IO6PROM;
167         /* Store the revision info  in the inventory */
168         baseio_inventory->im_version = version;
169         baseio_inventory->im_rev = revision;
170         /* Put the inventory info in the hardware graph */
171         hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, 
172                              (arbitrary_info_t) baseio_inventory);
173         /* Make the information available to the user programs
174          * thru hwgfs.
175          */
176         hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
177                                 sizeof(invent_miscinfo_t));
178 }
179
180 /*
181  * Add detailed cpu inventory info to the hardware graph.
182  */
183 void
184 klhwg_hub_invent_info(vertex_hdl_t hubv,
185                       cnodeid_t cnode, 
186                       klhub_t *hub)
187 {
188         invent_miscinfo_t *hub_invent;
189
190         hub_invent = (invent_miscinfo_t *) 
191             klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t));
192         if (!hub_invent)
193             return;
194
195         if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub))
196             hub_invent->im_gen.ig_flag = INVENT_ENABLED;
197
198         hub_invent->im_type = INV_HUB;
199         hub_invent->im_rev = hub->hub_info.revision;
200         hub_invent->im_speed = hub->hub_speed;
201         hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, 
202                              (arbitrary_info_t) hub_invent);
203         hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT,
204                                 sizeof(invent_miscinfo_t));
205 }
206
207 /* ARGSUSED */
208 void
209 klhwg_add_ice(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
210 {
211         vertex_hdl_t myicev;
212         vertex_hdl_t ice_mon;
213         int rc;
214         extern struct file_operations shub_mon_fops;
215
216         (void) hwgraph_path_add(node_vertex, EDGE_LBL_ICE, &myicev);
217
218         HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, myicev, NULL, "Created path for ice vertex for TIO node.\n"));
219
220         rc = device_master_set(myicev, node_vertex);
221         if (rc)
222                 panic("klhwg_add_ice: Unable to create ice vertex.\n");
223
224         ice_mon = hwgraph_register(myicev, EDGE_LBL_PERFMON,
225                 0, DEVFS_FL_AUTO_DEVNUM,
226                 0, 0,
227                 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
228                 &shub_mon_fops, (void *)(long)cnode);
229 }
230
231 /* ARGSUSED */
232 void
233 klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
234 {
235         vertex_hdl_t myhubv;
236         vertex_hdl_t hub_mon;
237         int rc;
238         extern struct file_operations shub_mon_fops;
239
240         GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
241         (void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
242
243         HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, myhubv, NULL, "Created path for hub vertex for Shub node.\n"));
244
245         rc = device_master_set(myhubv, node_vertex);
246         if (rc)
247                 panic("klhwg_add_hub: Unable to create hub vertex.\n");
248
249         hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
250                 0, DEVFS_FL_AUTO_DEVNUM,
251                 0, 0,
252                 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
253                 &shub_mon_fops, (void *)(long)cnode);
254 }
255
256 /* ARGSUSED */
257 void
258 klhwg_add_disabled_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
259 {
260         vertex_hdl_t my_cpu;
261         char name[120];
262         cpuid_t cpu_id;
263         nasid_t nasid;
264
265         nasid = COMPACT_TO_NASID_NODEID(cnode);
266         cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
267         if(cpu_id != -1){
268                 sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
269                 (void) hwgraph_path_add(node_vertex, name, &my_cpu);
270
271                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for disabled cpu slice.\n"));
272
273                 mark_cpuvertex_as_cpu(my_cpu, cpu_id);
274                 device_master_set(my_cpu, node_vertex);
275
276                 klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot);
277                 return;
278         }
279 }
280
281 /* ARGSUSED */
282 void
283 klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
284 {
285         vertex_hdl_t my_cpu, cpu_dir;
286         char name[120];
287         cpuid_t cpu_id;
288         nasid_t nasid;
289
290         nasid = COMPACT_TO_NASID_NODEID(cnode);
291         cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
292
293         sprintf(name, "%s/%d/%c",
294                 EDGE_LBL_CPUBUS,
295                 0,
296                 'a' + cpu->cpu_info.physid);
297
298         GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
299         (void) hwgraph_path_add(node_vertex, name, &my_cpu);
300
301         HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n"));
302
303         mark_cpuvertex_as_cpu(my_cpu, cpu_id);
304         device_master_set(my_cpu, node_vertex);
305
306         /* Add an alias under the node's CPU directory */
307         if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
308                 sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
309                 (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
310                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name));
311         }
312
313         klhwg_cpu_invent_info(my_cpu, cnode, cpu);
314 }
315
316
317 void
318 klhwg_add_coretalk(cnodeid_t cnode, nasid_t tio_nasid)
319 {
320         lboard_t *brd;
321         vertex_hdl_t coretalk_v, icev;
322         /*REFERENCED*/
323         graph_error_t err;
324
325         if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
326                         return;
327
328         if (KL_CONFIG_DUPLICATE_BOARD(brd))
329             return;
330
331         icev = cnodeid_to_vertex(cnode);
332
333         err = hwgraph_path_add(icev, EDGE_LBL_CORETALK, &coretalk_v);
334         if (err != GRAPH_SUCCESS) {
335                 if (err == GRAPH_DUP)
336                         printk(KERN_WARNING  "klhwg_add_coretalk: Check for "
337                                         "working routers and router links!");
338
339                  panic("klhwg_add_coretalkk: Failed to add "
340                              "edge: vertex 0x%p to vertex 0x%p,"
341                              "error %d\n",
342                               (void *)icev, (void *)coretalk_v, err);
343         }
344
345         HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, coretalk_v, NULL, "Created coretalk path for TIO node.\n"));
346
347         NODEPDA(cnode)->xbow_vhdl = coretalk_v;
348
349 }
350
351
352 void
353 klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
354 {
355         lboard_t *brd;
356         klxbow_t *xbow_p;
357         nasid_t hub_nasid;
358         cnodeid_t hub_cnode;
359         int widgetnum;
360         vertex_hdl_t xbow_v, hubv;
361         /*REFERENCED*/
362         graph_error_t err;
363
364         if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
365                         return;
366
367         if (KL_CONFIG_DUPLICATE_BOARD(brd))
368             return;
369
370         if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
371             == NULL)
372             return;
373
374         for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
375                 if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) 
376                     continue;
377
378                 hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
379                 if (hub_nasid == INVALID_NASID) {
380                         printk(KERN_WARNING  "hub widget %d, skipping xbow graph\n", widgetnum);
381                         continue;
382                 }
383
384                 hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
385
386                 if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
387                         continue;
388                 }
389                         
390                 hubv = cnodeid_to_vertex(hub_cnode);
391
392                 err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
393                 if (err != GRAPH_SUCCESS) {
394                         if (err == GRAPH_DUP)
395                                 printk(KERN_WARNING  "klhwg_add_xbow: Check for "
396                                         "working routers and router links!");
397
398                         panic("klhwg_add_xbow: Failed to add "
399                                 "edge: vertex 0x%p to vertex 0x%p,"
400                                 "error %d\n",
401                                 (void *)hubv, (void *)xbow_v, err);
402                 }
403
404                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, xbow_v, NULL, "Created path for xtalk.\n"));
405
406                 xswitch_vertex_init(xbow_v); 
407
408                 NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
409
410                 /*
411                  * XXX - This won't work is we ever hook up two hubs
412                  * by crosstown through a crossbow.
413                  */
414                 if (hub_nasid != nasid) {
415                         NODEPDA(hub_cnode)->xbow_peer = nasid;
416                         NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer =
417                                 hub_nasid;
418                 }
419
420         }
421 }
422
423
424 /* ARGSUSED */
425 void
426 klhwg_add_tionode(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
427 {
428         nasid_t tio_nasid;
429         lboard_t *brd;
430         klhub_t *hub;
431         vertex_hdl_t node_vertex = NULL;
432         char path_buffer[100];
433         int rv;
434         char *s;
435         int board_disabled = 0;
436
437         tio_nasid = COMPACT_TO_NASID_NODEID(cnode);
438         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_TIO);
439         ASSERT(brd);
440
441         /* Generate a hardware graph path for this board. */
442         board_to_path(brd, path_buffer);
443         rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
444         if (rv != GRAPH_SUCCESS)
445                 panic("TIO Node vertex creation failed.  "
446                                           "Path == %s", path_buffer);
447
448         HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for TIO node.\n"));
449         hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
450         ASSERT(hub);
451         if(hub->hub_info.flags & KLINFO_ENABLE)
452                 board_disabled = 0;
453         else
454                 board_disabled = 1;
455
456         if(!board_disabled) {
457                 mark_nodevertex_as_node(node_vertex,
458                                     cnode + board_disabled * numionodes);
459
460                 s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
461                 NODEPDA(cnode)->hwg_node_name =
462                                         kmalloc(strlen(s) + 1,
463                                         GFP_KERNEL);
464                 ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
465                 strcpy(NODEPDA(cnode)->hwg_node_name, s);
466
467                 hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
468
469                 /* Set up node board's slot */
470                 NODEPDA(cnode)->slotdesc = brd->brd_slot;
471
472                 /* Set up the module we're in */
473                 NODEPDA(cnode)->geoid = brd->brd_geoid;
474                 NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
475         }
476
477         if(!board_disabled)
478                 klhwg_add_ice(node_vertex, hub, cnode);
479
480 }
481
482
483 /* ARGSUSED */
484 void
485 klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
486 {
487         nasid_t nasid;
488         lboard_t *brd;
489         klhub_t *hub;
490         vertex_hdl_t node_vertex = NULL;
491         char path_buffer[100];
492         int rv;
493         char *s;
494         int board_disabled = 0;
495         klcpu_t *cpu;
496
497         nasid = COMPACT_TO_NASID_NODEID(cnode);
498         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
499         ASSERT(brd);
500
501         do {
502                 vertex_hdl_t cpu_dir;
503
504                 /* Generate a hardware graph path for this board. */
505                 board_to_path(brd, path_buffer);
506                 rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
507                 if (rv != GRAPH_SUCCESS)
508                         panic("Node vertex creation failed.  Path == %s", path_buffer);
509
510                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for SHUB node.\n"));
511                 hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
512                 ASSERT(hub);
513                 if(hub->hub_info.flags & KLINFO_ENABLE)
514                         board_disabled = 0;
515                 else
516                         board_disabled = 1;
517                 
518                 if(!board_disabled) {
519                         mark_nodevertex_as_node(node_vertex,
520                                             cnode + board_disabled * numnodes);
521
522                         s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
523                         NODEPDA(cnode)->hwg_node_name =
524                                                 kmalloc(strlen(s) + 1,
525                                                 GFP_KERNEL);
526                         ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
527                         strcpy(NODEPDA(cnode)->hwg_node_name, s);
528
529                         hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
530
531                         /* Set up node board's slot */
532                         NODEPDA(cnode)->slotdesc = brd->brd_slot;
533
534                         /* Set up the module we're in */
535                         NODEPDA(cnode)->geoid = brd->brd_geoid;
536                         NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
537                 }
538
539                 /* Get the first CPU structure */
540                 cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
541
542                 /*
543                 * If there's at least 1 CPU, add a "cpu" directory to represent
544                 * the collection of all CPUs attached to this node.
545                 */
546                 if (cpu) {
547                         graph_error_t rv;
548
549                         rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
550                         if (rv != GRAPH_SUCCESS)
551                                 panic("klhwg_add_node: Cannot create CPU directory\n");
552                         HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, cpu_dir, NULL, "Created cpu directiry on SHUB node.\n"));
553
554                 }
555
556                 /* Add each CPU */
557                 while (cpu) {
558                         cpuid_t cpu_id;
559                         cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid);
560                         if (cpu_online(cpu_id))
561                                 klhwg_add_cpu(node_vertex, cnode, cpu);
562                         else
563                                 klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot);
564
565                         cpu = (klcpu_t *)
566                                 find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU);
567                 } /* while */
568
569                 if(!board_disabled)
570                         klhwg_add_hub(node_vertex, hub, cnode);
571                 
572                 brd = KLCF_NEXT(brd);
573                 if (brd)
574                         brd = find_lboard(brd, KLTYPE_SNIA);
575                 else
576                         break;
577         } while(brd);
578 }
579
580
581 /* ARGSUSED */
582 void
583 klhwg_add_all_routers(vertex_hdl_t hwgraph_root)
584 {
585         nasid_t nasid;
586         cnodeid_t cnode;
587         lboard_t *brd;
588         vertex_hdl_t node_vertex;
589         char path_buffer[100];
590         int rv;
591
592         for (cnode = 0; cnode < numnodes; cnode++) {
593                 nasid = COMPACT_TO_NASID_NODEID(cnode);
594                 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
595                                 KLTYPE_ROUTER);
596                 if (!brd)
597                         /* No routers stored in this node's memory */
598                         continue;
599
600                 do {
601                         ASSERT(brd);
602
603                         /* Don't add duplicate boards. */
604                         if (brd->brd_flags & DUPLICATE_BOARD)
605                                 continue;
606
607                         /* Generate a hardware graph path for this board. */
608                         board_to_path(brd, path_buffer);
609
610                         /* Add the router */
611                         rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
612                         if (rv != GRAPH_SUCCESS)
613                                 panic("Router vertex creation "
614                                                   "failed.  Path == %s",
615                                         path_buffer);
616
617                         HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created router path.\n"));
618
619                 /* Find the rest of the routers stored on this node. */
620                 } while ( (brd = find_lboard_class(KLCF_NEXT(brd),
621                          KLTYPE_ROUTER)) );
622         }
623
624 }
625
626 /* ARGSUSED */
627 void
628 klhwg_connect_one_router(vertex_hdl_t hwgraph_root, lboard_t *brd,
629                          cnodeid_t cnode, nasid_t nasid)
630 {
631         klrou_t *router;
632         char path_buffer[50];
633         char dest_path[50];
634         vertex_hdl_t router_hndl;
635         vertex_hdl_t dest_hndl;
636         int rc;
637         int port;
638         lboard_t *dest_brd;
639
640         /* Don't add duplicate boards. */
641         if (brd->brd_flags & DUPLICATE_BOARD) {
642                 return;
643         }
644
645         /* Generate a hardware graph path for this board. */
646         board_to_path(brd, path_buffer);
647
648         rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl);
649
650         if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes))
651                         return;
652
653         if (rc != GRAPH_SUCCESS)
654                 printk(KERN_WARNING  "Can't find router: %s", path_buffer);
655
656         /* We don't know what to do with multiple router components */
657         if (brd->brd_numcompts != 1) {
658                 panic("klhwg_connect_one_router: %d cmpts on router\n",
659                         brd->brd_numcompts);
660                 return;
661         }
662
663
664         /* Convert component 0 to klrou_t ptr */
665         router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd),
666                                               brd->brd_compts[0]);
667
668         for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
669                 /* See if the port's active */
670                 if (router->rou_port[port].port_nasid == INVALID_NASID) {
671                         GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n",
672                                  port));
673                         continue;
674                 }
675                 if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) 
676                     == INVALID_CNODEID) {
677                         continue;
678                 }
679
680                 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
681                                 router->rou_port[port].port_nasid,
682                                 router->rou_port[port].port_offset);
683
684                 /* Generate a hardware graph path for this board. */
685                 board_to_path(dest_brd, dest_path);
686
687                 rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
688
689                 if (rc != GRAPH_SUCCESS) {
690                         if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
691                                 continue;
692                         panic("Can't find router: %s", dest_path);
693                 }
694
695                 sprintf(dest_path, "%d", port);
696
697                 rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
698                 if (rc == GRAPH_DUP) {
699                         GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
700                                   port, router->rou_port[port].port_nasid,
701                                   path_buffer, dest_path));
702                         continue;
703                 }
704
705                 if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
706                         panic("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
707                                 path_buffer, dest_path, (void *)dest_hndl, rc);
708
709                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, router_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", dest_path));
710                 
711         }
712 }
713
714
715 void
716 klhwg_connect_routers(vertex_hdl_t hwgraph_root)
717 {
718         nasid_t nasid;
719         cnodeid_t cnode;
720         lboard_t *brd;
721
722         for (cnode = 0; cnode < numnodes; cnode++) {
723                 nasid = COMPACT_TO_NASID_NODEID(cnode);
724
725                 GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n",
726                         cnode));
727
728                 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
729                                 KLTYPE_ROUTER);
730
731                 if (!brd)
732                         continue;
733
734                 do {
735
736                         nasid = COMPACT_TO_NASID_NODEID(cnode);
737
738                         klhwg_connect_one_router(hwgraph_root, brd,
739                                                  cnode, nasid);
740
741                 /* Find the rest of the routers stored on this node. */
742                 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
743         }
744 }
745
746
747
748 void
749 klhwg_connect_hubs(vertex_hdl_t hwgraph_root)
750 {
751         nasid_t nasid;
752         cnodeid_t cnode;
753         lboard_t *brd;
754         klhub_t *hub;
755         lboard_t *dest_brd;
756         vertex_hdl_t hub_hndl;
757         vertex_hdl_t dest_hndl;
758         char path_buffer[50];
759         char dest_path[50];
760         graph_error_t rc;
761         int port;
762
763         for (cnode = 0; cnode < numionodes; cnode++) {
764                 nasid = COMPACT_TO_NASID_NODEID(cnode);
765
766                 if (!(nasid & 1)) {
767                         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
768                         ASSERT(brd);
769                 } else {
770                         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_TIO);
771                         ASSERT(brd);
772                 }
773
774                 hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
775                 ASSERT(hub);
776
777                 for (port = 1; port <= MAX_NI_PORTS; port++) {
778                         /* See if the port's active */
779                         if (hub->hub_port[port].port_nasid == INVALID_NASID) {
780                                 GRPRINTF(("klhwg_connect_hubs: port inactive.\n"));
781                                 continue;
782                         }
783
784                         if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID)
785                                 continue;
786
787                         /* Generate a hardware graph path for this board. */
788                         board_to_path(brd, path_buffer);
789                         rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
790                         if (rc != GRAPH_SUCCESS)
791                                 printk(KERN_WARNING  "Can't find hub: %s", path_buffer);
792
793                         dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
794                                         hub->hub_port[port].port_nasid,
795                                         hub->hub_port[port].port_offset);
796
797                         /* Generate a hardware graph path for this board. */
798                         board_to_path(dest_brd, dest_path);
799
800                         rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
801
802                         if (rc != GRAPH_SUCCESS) {
803                                 if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
804                                         continue;
805                                 panic("Can't find board: %s", dest_path);
806                         } else {
807                                 char buf[1024];
808                 
809
810                                 GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n",
811                                 path_buffer, dest_path));
812
813                                 rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
814
815                                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, NULL, "Created link path.\n"));
816
817                                 sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
818                                 rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
819                                 sprintf(buf,"%d",port);
820                                 rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
821
822                                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", buf));
823
824                                 if (rc != GRAPH_SUCCESS)
825                                         panic("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
826                                         path_buffer, dest_path, (void *)dest_hndl, rc);
827
828                         }
829                 }
830         }
831 }
832
833 /* Store the pci/vme disabled board information as extended administrative
834  * hints which can later be used by the drivers using the device/driver
835  * admin interface. 
836  */
837 void
838 klhwg_device_disable_hints_add(void)
839 {
840         cnodeid_t       cnode;          /* node we are looking at */
841         nasid_t         nasid;          /* nasid of the node */
842         lboard_t        *board;         /* board we are looking at */
843         int             comp_index;     /* component index */
844         klinfo_t        *component;     /* component in the board we are
845                                          * looking at 
846                                          */
847         char            device_name[MAXDEVNAME];
848         
849         for(cnode = 0; cnode < numnodes; cnode++) {
850                 nasid = COMPACT_TO_NASID_NODEID(cnode);
851                 board = (lboard_t *)KL_CONFIG_INFO(nasid);
852                 /* Check out all the board info stored  on a node */
853                 while(board) {
854                         /* No need to look at duplicate boards or non-io 
855                          * boards
856                          */
857                         if (KL_CONFIG_DUPLICATE_BOARD(board) ||
858                             KLCLASS(board->brd_type) != KLCLASS_IO) {
859                                 board = KLCF_NEXT(board);
860                                 continue;
861                         }
862                         /* Check out all the components of a board */
863                         for (comp_index = 0; 
864                              comp_index < KLCF_NUM_COMPS(board);
865                              comp_index++) {
866                                 component = KLCF_COMP(board,comp_index);
867                                 /* If the component is enabled move on to
868                                  * the next component
869                                  */
870                                 if (KLCONFIG_INFO_ENABLED(component))
871                                         continue;
872                                 /* NOTE : Since the prom only supports
873                                  * the disabling of pci devices the following
874                                  * piece of code makes sense. 
875                                  * Make sure that this assumption is valid
876                                  */
877                                 /* This component is disabled. Store this
878                                  * hint in the extended device admin table
879                                  */
880                                 /* Get the canonical name of the pci device */
881                                 device_component_canonical_name_get(board,
882                                                             component,
883                                                             device_name);
884 #ifdef DEBUG
885                                 printf("%s DISABLED\n",device_name);
886 #endif                          
887                         }
888                         /* go to the next board info stored on this 
889                          * node 
890                          */
891                         board = KLCF_NEXT(board);
892                 }
893         }
894 }
895
896 void
897 klhwg_add_all_modules(vertex_hdl_t hwgraph_root)
898 {
899         cmoduleid_t     cm;
900         char            name[128];
901         vertex_hdl_t    vhdl;
902         vertex_hdl_t  module_vhdl;
903         int             rc;
904         char            buffer[16];
905
906         /* Add devices under each module */
907
908         for (cm = 0; cm < nummodules; cm++) {
909                 /* Use module as module vertex fastinfo */
910
911                 memset(buffer, 0, 16);
912                 format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
913                 sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
914
915                 rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
916                 ASSERT(rc == GRAPH_SUCCESS);
917                 rc = rc; /* Shut the compiler up */
918                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n"));
919
920                 hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
921
922                 /* Add system controller */
923                 sprintf(name,
924                         EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
925                         buffer);
926
927                 rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
928                 ASSERT_ALWAYS(rc == GRAPH_SUCCESS);
929                 rc = rc; /* Shut the compiler up */
930                 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, vhdl, NULL, "Created L1 path.\n"));
931
932                 hwgraph_info_add_LBL(vhdl,
933                                      INFO_LBL_ELSC,
934                                      (arbitrary_info_t) (int64_t) 1);
935
936         }
937 }
938
939 void
940 klhwg_add_all_nodes(vertex_hdl_t hwgraph_root)
941 {
942         cnodeid_t       cnode;
943
944         for (cnode = 0; cnode < numnodes; cnode++) {
945                 klhwg_add_node(hwgraph_root, cnode);
946         }
947
948         for (cnode = numnodes; cnode < numionodes; cnode++) {
949                 klhwg_add_tionode(hwgraph_root, cnode);
950         }
951
952         for (cnode = 0; cnode < numnodes; cnode++) {
953                 klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
954         }
955
956         for (cnode = numnodes; cnode < numionodes; cnode++) {
957                 klhwg_add_coretalk(cnode, cnodeid_to_nasid(cnode));
958         }
959
960         /*
961          * As for router hardware inventory information, we set this
962          * up in router.c. 
963          */
964         
965         klhwg_add_all_routers(hwgraph_root);
966         klhwg_connect_routers(hwgraph_root);
967         klhwg_connect_hubs(hwgraph_root);
968
969         /* Go through the entire system's klconfig
970          * to figure out which pci components have been disabled
971          */
972         klhwg_device_disable_hints_add();
973
974 }