1/*
2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6#include <boot/platform/openfirmware/platform_arch.h>
7
8#include <stdio.h>
9
10#include <KernelExport.h>
11
12#include <boot/kernel_args.h>
13#include <boot/stage2.h>
14#include <kernel.h>
15#include <platform/openfirmware/devices.h>
16#include <platform/openfirmware/openfirmware.h>
17
18#define TRACE_CPU
19#ifdef TRACE_CPU
20#	define TRACE(x) dprintf x
21#else
22#	define TRACE(x) ;
23#endif
24
25
26status_t
27boot_arch_cpu_init(void)
28{
29	// iterate through the "/cpus" node to find all CPUs
30	int cpus = of_finddevice("/cpus");
31	if (cpus == OF_FAILED) {
32		printf("boot_arch_cpu_init(): Failed to open \"/cpus\"!\n");
33		return B_ERROR;
34	}
35
36	char cpuPath[256];
37	int cookie = 0;
38	int cpuCount = 0;
39	while (of_get_next_device(&cookie, cpus, "cpu", cpuPath,
40			sizeof(cpuPath)) == B_OK) {
41		TRACE(("found CPU: %s\n", cpuPath));
42
43		// For the first CPU get the frequencies of CPU, bus, and time base.
44		// We assume they are the same for all CPUs.
45		if (cpuCount == 0) {
46			int cpu = of_finddevice(cpuPath);
47			if (cpu == OF_FAILED) {
48				printf("boot_arch_cpu_init: Failed get CPU device node!\n");
49				return B_ERROR;
50			}
51
52			// TODO: Does encode-int really encode quadlet (32 bit numbers)
53			// only?
54			int32 clockFrequency;
55			if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4)
56					== OF_FAILED) {
57				printf("boot_arch_cpu_init: Failed to get CPU clock "
58					"frequency!\n");
59				return B_ERROR;
60			}
61			int32 busFrequency;
62			if (of_getprop(cpu, "bus-frequency", &busFrequency, 4)
63					== OF_FAILED) {
64				printf("boot_arch_cpu_init: Failed to get bus clock "
65					"frequency!\n");
66				return B_ERROR;
67			}
68			int32 timeBaseFrequency;
69			if (of_getprop(cpu, "timebase-frequency", &timeBaseFrequency, 4)
70					== OF_FAILED) {
71				printf("boot_arch_cpu_init: Failed to get time base "
72					"frequency!\n");
73				return B_ERROR;
74			}
75
76			gKernelArgs.arch_args.cpu_frequency = clockFrequency;
77			gKernelArgs.arch_args.bus_frequency = busFrequency;
78			gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency;
79
80			TRACE(("  CPU clock frequency: %ld\n", clockFrequency));
81			TRACE(("  bus clock frequency: %ld\n", busFrequency));
82			TRACE(("  time base frequency: %ld\n", timeBaseFrequency));
83		}
84
85		cpuCount++;
86	}
87
88	if (cpuCount == 0) {
89		printf("boot_arch_cpu_init(): Found no CPUs!\n");
90		return B_ERROR;
91	}
92
93	gKernelArgs.num_cpus = cpuCount;
94
95	// allocate the kernel stacks (the memory stuff is already initialized
96	// at this point)
97	addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000,
98		cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE),
99		B_READ_AREA | B_WRITE_AREA, false);
100	if (!stack) {
101		printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n");
102		return B_NO_MEMORY;
103	}
104
105	for (int i = 0; i < cpuCount; i++) {
106		gKernelArgs.cpu_kstack[i].start = stack;
107		gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
108			+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
109		stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
110	}
111
112	return B_OK;
113}
114
115