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