ddf7e949aa070c68d20e8b16b6d83bd301607525
[linux-flexiantxendom0-3.2.10.git] / arch / mips / sgi-ip27 / ip27-init.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General
3  * Public License.  See the file "COPYING" in the main directory of this
4  * archive for more details.
5  *
6  * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
7  * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
8  */
9
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <linux/mmzone.h>       /* for numnodes */
15 #include <linux/mm.h>
16 #include <asm/cpu.h>
17 #include <asm/pgalloc.h>
18 #include <asm/pgtable.h>
19 #include <asm/sn/types.h>
20 #include <asm/sn/sn0/addrs.h>
21 #include <asm/sn/sn0/hubni.h>
22 #include <asm/sn/sn0/hubio.h>
23 #include <asm/sn/klconfig.h>
24 #include <asm/sn/ioc3.h>
25 #include <asm/mipsregs.h>
26 #include <asm/sn/gda.h>
27 #include <asm/sn/intr.h>
28 #include <asm/current.h>
29 #include <asm/smp.h>
30 #include <asm/processor.h>
31 #include <asm/mmu_context.h>
32 #include <asm/thread_info.h>
33 #include <asm/sn/launch.h>
34 #include <asm/sn/sn_private.h>
35 #include <asm/sn/sn0/ip27.h>
36 #include <asm/sn/mapped_kernel.h>
37 #include <asm/sn/sn0/addrs.h>
38 #include <asm/sn/gda.h>
39
40 #define CPU_NONE                (cpuid_t)-1
41
42 /*
43  * The following should work till 64 nodes, ie 128p SN0s.
44  */
45 #define CNODEMASK_CLRALL(p)     (p) = 0
46 #define CNODEMASK_TSTB(p, bit)  ((p) & (1ULL << (bit)))
47 #define CNODEMASK_SETB(p, bit)  ((p) |= 1ULL << (bit))
48
49 cpumask_t       boot_cpumask;
50 hubreg_t        region_mask;
51 static int      fine_mode;
52 int             maxcpus;
53 static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
54 static cnodemask_t hub_init_mask;
55 static atomic_t numstarted = ATOMIC_INIT(1);
56 static int router_distance;
57 nasid_t master_nasid = INVALID_NASID;
58
59 cnodeid_t       nasid_to_compact_node[MAX_NASIDS];
60 nasid_t         compact_to_nasid_node[MAX_COMPACT_NODES];
61 cnodeid_t       cpuid_to_compact_node[MAXCPUS];
62 char            node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
63
64 hubreg_t get_region(cnodeid_t cnode)
65 {
66         if (fine_mode)
67                 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT;
68         else
69                 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT;
70 }
71
72 static void gen_region_mask(hubreg_t *region_mask, int maxnodes)
73 {
74         cnodeid_t cnode;
75
76         (*region_mask) = 0;
77         for (cnode = 0; cnode < maxnodes; cnode++) {
78                 (*region_mask) |= 1ULL << get_region(cnode);
79         }
80 }
81
82 int is_fine_dirmode(void)
83 {
84         return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK)
85                 >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE);
86 }
87
88 nasid_t get_actual_nasid(lboard_t *brd)
89 {
90         klhub_t *hub;
91
92         if (!brd)
93                 return INVALID_NASID;
94
95         /* find out if we are a completely disabled brd. */
96         hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
97         if (!hub)
98                 return INVALID_NASID;
99         if (!(hub->hub_info.flags & KLINFO_ENABLE))     /* disabled node brd */
100                 return hub->hub_info.physid;
101         else
102                 return brd->brd_nasid;
103 }
104
105 /* Tweak this for maximum number of CPUs to activate */
106 static int max_cpus = NR_CPUS;
107
108 int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask,
109                                                         int *highest)
110 {
111         static int tot_cpus_found = 0;
112         lboard_t *brd;
113         klcpu_t *acpu;
114         int cpus_found = 0;
115         cpuid_t cpuid;
116
117         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
118
119         do {
120                 acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
121                 while (acpu) {
122                         cpuid = acpu->cpu_info.virtid;
123                         /* cnode is not valid for completely disabled brds */
124                         if (get_actual_nasid(brd) == brd->brd_nasid)
125                                 cpuid_to_compact_node[cpuid] = cnode;
126                         if (cpuid > *highest)
127                                 *highest = cpuid;
128                         /* Only let it join in if it's marked enabled */
129                         if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
130                                                 (tot_cpus_found != max_cpus)) {
131                                 CPUMASK_SETB(*boot_cpumask, cpuid);
132                                 cpus_found++;
133                                 tot_cpus_found++;
134                         }
135                         acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
136                                                                 KLSTRUCT_CPU);
137                 }
138                 brd = KLCF_NEXT(brd);
139                 if (brd)
140                         brd = find_lboard(brd,KLTYPE_IP27);
141                 else
142                         break;
143         } while (brd);
144
145         return cpus_found;
146 }
147
148 cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes)
149 {
150         int i, cpus = 0, highest = 0;
151         gda_t *gdap = GDA;
152         nasid_t nasid;
153
154         /*
155          * Initialize the arrays to invalid nodeid (-1)
156          */
157         for (i = 0; i < MAX_COMPACT_NODES; i++)
158                 compact_to_nasid_node[i] = INVALID_NASID;
159         for (i = 0; i < MAX_NASIDS; i++)
160                 nasid_to_compact_node[i] = INVALID_CNODEID;
161         for (i = 0; i < MAXCPUS; i++)
162                 cpuid_to_compact_node[i] = INVALID_CNODEID;
163
164         *numnodes = 0;
165         for (i = 0; i < MAX_COMPACT_NODES; i++) {
166                 if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) {
167                         break;
168                 } else {
169                         compact_to_nasid_node[i] = nasid;
170                         nasid_to_compact_node[nasid] = i;
171                         (*numnodes)++;
172                         cpus += do_cpumask(i, nasid, boot_cpumask, &highest);
173                 }
174         }
175
176         /*
177          * Cpus are numbered in order of cnodes. Currently, disabled
178          * cpus are not numbered.
179          */
180
181         return highest + 1;
182 }
183
184 int cpu_enabled(cpuid_t cpu)
185 {
186         if (cpu == CPU_NONE)
187                 return 0;
188         return CPUMASK_TSTB(boot_cpumask, cpu) != 0;
189 }
190
191 void mlreset(void)
192 {
193         int i;
194         void init_topology_matrix(void);
195         void dump_topology(void);
196
197
198         master_nasid = get_nasid();
199         fine_mode = is_fine_dirmode();
200
201         /*
202          * Probe for all CPUs - this creates the cpumask and
203          * sets up the mapping tables.
204          */
205         CPUMASK_CLRALL(boot_cpumask);
206         maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
207         printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
208
209         init_topology_matrix();
210         dump_topology();
211
212         gen_region_mask(&region_mask, numnodes);
213         CNODEMASK_CLRALL(hub_init_mask);
214
215         setup_replication_mask(numnodes);
216
217         /*
218          * Set all nodes' calias sizes to 8k
219          */
220         for (i = 0; i < numnodes; i++) {
221                 nasid_t nasid;
222
223                 nasid = COMPACT_TO_NASID_NODEID(i);
224
225                 /*
226                  * Always have node 0 in the region mask, otherwise
227                  * CALIAS accesses get exceptions since the hub
228                  * thinks it is a node 0 address.
229                  */
230                 REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
231 #ifdef CONFIG_REPLICATE_EXHANDLERS
232                 REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
233 #else
234                 REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
235 #endif
236
237 #ifdef LATER
238                 /*
239                  * Set up all hubs to have a big window pointing at
240                  * widget 0. Memory mode, widget 0, offset 0
241                  */
242                 REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
243                         ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
244                         (0 << IIO_ITTE_WIDGET_SHIFT)));
245 #endif
246         }
247 }
248
249
250 void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,
251                                                         char *name)
252 {
253         volatile hubreg_t bits;
254         int i;
255
256         /* Check pending interrupts */
257         if ((bits = HUB_L(pend)) != 0)
258                 for (i = 0; i < N_INTPEND_BITS; i++)
259                         if (bits & (1 << i))
260                                 LOCAL_HUB_CLR_INTR(base_level + i);
261 }
262
263 void intr_clear_all(nasid_t nasid)
264 {
265         REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
266         REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
267         REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
268         REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
269         intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
270                 INT_PEND0_BASELVL, "INT_PEND0");
271         intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
272                 INT_PEND1_BASELVL, "INT_PEND1");
273 }
274
275 void sn_mp_setup(void)
276 {
277         cnodeid_t       cnode;
278 #if 0
279         cpuid_t         cpu;
280 #endif
281
282         for (cnode = 0; cnode < numnodes; cnode++) {
283 #if 0
284                 init_platform_nodepda();
285 #endif
286                 intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
287         }
288 #if 0
289         for (cpu = 0; cpu < maxcpus; cpu++) {
290                 init_platform_pda();
291         }
292 #endif
293 }
294
295 void per_hub_init(cnodeid_t cnode)
296 {
297         extern void pcibr_setup(cnodeid_t);
298         cnodemask_t     done;
299         nasid_t         nasid;
300
301         nasid = COMPACT_TO_NASID_NODEID(cnode);
302
303         spin_lock(&hub_mask_lock);
304         /* Test our bit. */
305         if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
306                 /* Turn our bit on in the mask. */
307                 CNODEMASK_SETB(hub_init_mask, cnode);
308                 /*
309                  * Do the actual initialization if it hasn't been done yet.
310                  * We don't need to hold a lock for this work.
311                  */
312                 /*
313                  * Set CRB timeout at 5ms, (< PI timeout of 10ms)
314                  */
315                 REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
316                 REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
317                 hub_rtc_init(cnode);
318                 pcibr_setup(cnode);
319 #ifdef CONFIG_REPLICATE_EXHANDLERS
320                 /*
321                  * If this is not a headless node initialization,
322                  * copy over the caliased exception handlers.
323                  */
324                 if (get_compact_nodeid() == cnode) {
325                         extern char except_vec0, except_vec1_r10k;
326                         extern char except_vec2_generic, except_vec3_generic;
327
328                         memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic,
329                                                                 0x80);
330                         memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
331                                                                 0x80);
332                         memcpy((void *)KSEG0, &except_vec0, 0x80);
333                         memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
334                         memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
335                         memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
336                                                                 0x100);
337                         __flush_cache_all();
338                 }
339 #endif
340         }
341         spin_unlock(&hub_mask_lock);
342 }
343
344 /*
345  * This is similar to hard_smp_processor_id().
346  */
347 cpuid_t getcpuid(void)
348 {
349         klcpu_t *klcpu;
350
351         klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM));
352         return klcpu->cpu_info.virtid;
353 }
354
355 void per_cpu_init(void)
356 {
357         extern void install_cpu_nmi_handler(int slice);
358         extern void load_mmu(void);
359         static int is_slave = 0;
360         int cpu = smp_processor_id();
361         cnodeid_t cnode = get_compact_nodeid();
362
363         TLBMISS_HANDLER_SETUP();
364 #if 0
365         intr_init();
366 #endif
367         clear_c0_status(ST0_IM);
368         per_hub_init(cnode);
369         cpu_time_init();
370         if (smp_processor_id()) /* master can't do this early, no kmalloc */
371                 install_cpuintr(cpu);
372         /* Install our NMI handler if symmon hasn't installed one. */
373         install_cpu_nmi_handler(cputoslice(cpu));
374 #if 0
375         install_tlbintr(cpu);
376 #endif
377         set_c0_status(SRB_DEV0 | SRB_DEV1);
378         if (is_slave) {
379                 clear_c0_status(ST0_BEV);
380                 if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
381                         set_c0_status(ST0_XX);
382                 set_c0_status(ST0_KX|ST0_SX|ST0_UX);
383                 local_irq_enable();
384                 load_mmu();
385                 atomic_inc(&numstarted);
386         } else {
387                 is_slave = 1;
388         }
389 }
390
391 cnodeid_t get_compact_nodeid(void)
392 {
393         nasid_t nasid;
394
395         nasid = get_nasid();
396         /*
397          * Map the physical node id to a virtual node id (virtual node ids
398          * are contiguous).
399          */
400         return NASID_TO_COMPACT_NODEID(nasid);
401 }
402
403 #ifdef CONFIG_SMP
404
405 /*
406  * Takes as first input the PROM assigned cpu id, and the kernel
407  * assigned cpu id as the second.
408  */
409 static void alloc_cpupda(cpuid_t cpu, int cpunum)
410 {
411         cnodeid_t       node;
412         nasid_t         nasid;
413
414         node = get_cpu_cnode(cpu);
415         nasid = COMPACT_TO_NASID_NODEID(node);
416
417         cputonasid(cpunum) = nasid;
418         cputocnode(cpunum) = node;
419         cputoslice(cpunum) = get_cpu_slice(cpu);
420         cpu_data[cpunum].p_cpuid = cpu;
421 }
422
423 static struct task_struct * __init fork_by_hand(void)
424 {
425         struct pt_regs regs;
426         /*
427          * don't care about the eip and regs settings since
428          * we'll never reschedule the forked task.
429          */
430         return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
431 }
432
433 static int __init do_boot_cpu(int cpu, int num_cpus)
434 {
435         extern void smp_bootstrap(void);
436         cpuid_t mycpuid = getcpuid();
437         struct task_struct *idle;
438
439         if (cpu == mycpuid) {
440                 alloc_cpupda(cpu, num_cpus);
441                 return 1;
442         }
443
444         /* Skip holes in CPU space */
445         if (!CPUMASK_TSTB(boot_cpumask, cpu))
446                 return 0;
447
448         /*
449          * The following code is purely to make sure
450          * Linux can schedule processes on this slave.
451          */
452         idle = fork_by_hand();
453         if (IS_ERR(idle))
454                 panic("failed fork for CPU %d", cpu);
455
456         /*
457          * We remove it from the pidhash and the runqueue
458          * once we got the process:
459          */
460         init_idle(idle, cpu);
461
462         alloc_cpupda(cpu, num_cpus);
463
464         unhash_process(idle);
465
466         /*
467          * Launch a slave into smp_bootstrap().  It doesn't take an
468          * argument, and we set sp to the kernel stack of the newly
469          * created idle process, gp to the proc struct so that
470          * current_thread_info() will work.
471          */
472         LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
473                 (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
474                 0, (void *)((unsigned long)idle->thread_info +
475                 KERNEL_STACK_SIZE - 32), (void *)idle);
476
477         /*
478          * Now optimistically set the mapping arrays. We
479          * need to wait here, verify the cpu booted up, then
480          * fire up the next cpu.
481          */
482         __cpu_number_map[cpu] = num_cpus;
483         __cpu_logical_map[num_cpus] = cpu;
484         CPUMASK_SETB(cpu_online_map, cpu);
485
486         /*
487          * Wait this cpu to start up and initialize its hub,
488          * and discover the io devices it will control.
489          *
490          * XXX: We really want to fire up launch all the CPUs
491          * at once.  We have to preserve the order of the
492          * devices on the bridges first though.
493          */
494         while (atomic_read(&numstarted) != num_cpus);
495
496         return 1;
497 }
498
499 void __init smp_boot_cpus(void)
500 {
501         int             num_cpus = 0;
502         cpuid_t         cpu;
503         cnodeid_t       cnode;
504
505         init_new_context(current, &init_mm);
506         current_thread_info()->cpu = 0;
507         smp_tune_scheduling();
508
509         sn_mp_setup();
510         /* Master has already done per_cpu_init() */
511         install_cpuintr(smp_processor_id());
512 #if 0
513         bte_lateinit();
514         ecc_init();
515 #endif
516
517         replicate_kernel_text(numnodes);
518         /* Launch slaves. */
519         for (cpu = 0; cpu < maxcpus; cpu++) {
520                 num_cpus += do_boot_cpu(cpu, num_cpus);
521         }
522
523 #ifdef LATER
524         Wait logic goes here.
525 #endif
526         for (cnode = 0; cnode < numnodes; cnode++) {
527 #if 0
528                 if (cnodetocpu(cnode) == -1) {
529                         printk("Initializing headless hub,cnode %d", cnode);
530                         per_hub_init(cnode);
531                 }
532 #endif
533         }
534 #if 0
535         cpu_io_setup();
536         init_mfhi_war();
537 #endif
538 }
539
540 #else /* CONFIG_SMP */
541 void __init start_secondary(void)
542 {
543         /* XXX Why do we need this empty definition at all?  */
544 }
545 #endif /* CONFIG_SMP */
546
547
548 #define rou_rflag       rou_flags
549
550 void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
551 {
552         klrou_t *router;
553         lboard_t *brd;
554         int     port;
555
556         if (router_a->rou_rflag == 1)
557                 return;
558
559         if (depth >= router_distance)
560                 return;
561
562         router_a->rou_rflag = 1;
563
564         for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
565                 if (router_a->rou_port[port].port_nasid == INVALID_NASID)
566                         continue;
567
568                 brd = (lboard_t *)NODE_OFFSET_TO_K0(
569                         router_a->rou_port[port].port_nasid,
570                         router_a->rou_port[port].port_offset);
571
572                 if (brd->brd_type == KLTYPE_ROUTER) {
573                         router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
574                         if (router == router_b) {
575                                 if (depth < router_distance)
576                                         router_distance = depth;
577                         }
578                         else
579                                 router_recurse(router, router_b, depth + 1);
580                 }
581         }
582
583         router_a->rou_rflag = 0;
584 }
585
586 int node_distance(nasid_t nasid_a, nasid_t nasid_b)
587 {
588         nasid_t nasid;
589         cnodeid_t cnode;
590         lboard_t *brd, *dest_brd;
591         int port;
592         klrou_t *router, *router_a = NULL, *router_b = NULL;
593
594         /* Figure out which routers nodes in question are connected to */
595         for (cnode = 0; cnode < numnodes; cnode++) {
596                 nasid = COMPACT_TO_NASID_NODEID(cnode);
597
598                 if (nasid == -1) continue;
599
600                 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
601                                         KLTYPE_ROUTER);
602
603                 if (!brd)
604                         continue;
605
606                 do {
607                         if (brd->brd_flags & DUPLICATE_BOARD)
608                                 continue;
609
610                         router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
611                         router->rou_rflag = 0;
612
613                         for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
614                                 if (router->rou_port[port].port_nasid == INVALID_NASID)
615                                         continue;
616
617                                 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
618                                         router->rou_port[port].port_nasid,
619                                         router->rou_port[port].port_offset);
620
621                                 if (dest_brd->brd_type == KLTYPE_IP27) {
622                                         if (dest_brd->brd_nasid == nasid_a)
623                                                 router_a = router;
624                                         if (dest_brd->brd_nasid == nasid_b)
625                                                 router_b = router;
626                                 }
627                         }
628
629                 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
630         }
631
632         if (router_a == NULL) {
633                 printk("node_distance: router_a NULL\n");
634                 return -1;
635         }
636         if (router_b == NULL) {
637                 printk("node_distance: router_b NULL\n");
638                 return -1;
639         }
640
641         if (nasid_a == nasid_b)
642                 return 0;
643
644         if (router_a == router_b)
645                 return 1;
646
647         router_distance = 100;
648         router_recurse(router_a, router_b, 2);
649
650         return router_distance;
651 }
652
653 void init_topology_matrix(void)
654 {
655         nasid_t nasid, nasid2;
656         cnodeid_t row, col;
657
658         for (row = 0; row < MAX_COMPACT_NODES; row++)
659                 for (col = 0; col < MAX_COMPACT_NODES; col++)
660                         node_distances[row][col] = -1;
661
662         for (row = 0; row < numnodes; row++) {
663                 nasid = COMPACT_TO_NASID_NODEID(row);
664                 for (col = 0; col < numnodes; col++) {
665                         nasid2 = COMPACT_TO_NASID_NODEID(col);
666                         node_distances[row][col] = node_distance(nasid, nasid2);
667                 }
668         }
669 }
670
671 void dump_topology(void)
672 {
673         nasid_t nasid;
674         cnodeid_t cnode;
675         lboard_t *brd, *dest_brd;
676         int port;
677         int router_num = 0;
678         klrou_t *router;
679         cnodeid_t row, col;
680
681         printk("************** Topology ********************\n");
682
683         printk("    ");
684         for (col = 0; col < numnodes; col++)
685                 printk("%02d ", col);
686         printk("\n");
687         for (row = 0; row < numnodes; row++) {
688                 printk("%02d  ", row);
689                 for (col = 0; col < numnodes; col++)
690                         printk("%2d ", node_distances[row][col]);
691                 printk("\n");
692         }
693
694         for (cnode = 0; cnode < numnodes; cnode++) {
695                 nasid = COMPACT_TO_NASID_NODEID(cnode);
696
697                 if (nasid == -1) continue;
698
699                 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
700                                         KLTYPE_ROUTER);
701
702                 if (!brd)
703                         continue;
704
705                 do {
706                         if (brd->brd_flags & DUPLICATE_BOARD)
707                                 continue;
708                         printk("Router %d:", router_num);
709                         router_num++;
710
711                         router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
712
713                         for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
714                                 if (router->rou_port[port].port_nasid == INVALID_NASID)
715                                         continue;
716
717                                 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
718                                         router->rou_port[port].port_nasid,
719                                         router->rou_port[port].port_offset);
720
721                                 if (dest_brd->brd_type == KLTYPE_IP27)
722                                         printk(" %d", dest_brd->brd_nasid);
723                                 if (dest_brd->brd_type == KLTYPE_ROUTER)
724                                         printk(" r");
725                         }
726                         printk("\n");
727
728                 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
729         }
730 }
731
732 #if 0
733 #define         brd_widgetnum   brd_slot
734 #define NODE_OFFSET_TO_KLINFO(n,off)    ((klinfo_t*) TO_NODE_CAC(n,off))
735 void
736 dump_klcfg(void)
737 {
738         cnodeid_t       cnode;
739         int i;
740         nasid_t         nasid;
741         lboard_t        *lbptr;
742         gda_t           *gdap;
743
744         gdap = (gda_t *)GDA_ADDR(get_nasid());
745         if (gdap->g_magic != GDA_MAGIC) {
746                 printk("dumpklcfg_cmd: Invalid GDA MAGIC\n");
747                 return;
748         }
749
750         for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
751                 nasid = gdap->g_nasidtable[cnode];
752
753                 if (nasid == INVALID_NASID)
754                         continue;
755
756                 printk("\nDumpping klconfig Nasid %d:\n", nasid);
757
758                 lbptr = KL_CONFIG_INFO(nasid);
759
760                 while (lbptr) {
761                         printk("    %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx",
762                                 "board name here", /* BOARD_NAME(lbptr->brd_type), */
763                                 lbptr->brd_nasid, lbptr->brd_module,
764                                 lbptr->brd_widgetnum,
765                                 lbptr->brd_partition,
766                                 (lbptr->brd_nic), lbptr);
767                         if (lbptr->brd_flags & DUPLICATE_BOARD)
768                                 printk(" -D");
769                         printk("\n");
770                         for (i = 0; i < lbptr->brd_numcompts; i++) {
771                                 klinfo_t *kli;
772                                 kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]);
773                                 printk("        type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n",
774                                         kli->struct_type,
775                                         kli->flags,
776                                         kli->diagval,
777                                         kli->physid,
778                                         kli->virtid,
779                                         "comp. name here");
780                                         /* COMPONENT_NAME(kli->struct_type)); */
781                         }
782                         lbptr = KLCF_NEXT(lbptr);
783                 }
784         }
785         printk("\n");
786
787         /* Useful to print router maps also */
788
789         for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
790                 klrou_t *kr;
791                 int i;
792
793                 nasid = gdap->g_nasidtable[cnode];
794                 if (nasid == INVALID_NASID)
795                         continue;
796                 lbptr = KL_CONFIG_INFO(nasid);
797
798                 while (lbptr) {
799
800                         lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER);
801                         if(!lbptr)
802                                 break;
803                         if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) {
804                                 printk("%llx -> \n", lbptr->brd_nic);
805                                 kr = (klrou_t *)find_first_component(lbptr,
806                                         KLSTRUCT_ROU);
807                                 for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
808                                         printk("[%d, %llx]; ",
809                                                 kr->rou_port[i].port_nasid,
810                                                 kr->rou_port[i].port_offset);
811                                 }
812                                 printk("\n");
813                         }
814                         lbptr = KLCF_NEXT(lbptr);
815                 }
816                 printk("\n");
817         }
818
819         dump_topology();
820 }
821 #endif