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	int32 busFrequency = 0;
30
31	intptr_t cpus = of_finddevice("/");
32	if (cpus == OF_FAILED) {
33		printf("boot_arch_cpu_init(): Failed to open \"/\"!\n");
34		return B_ERROR;
35	}
36
37	of_getprop(cpus, "clock-frequency", &busFrequency, 4);
38
39	char cpuPath[256];
40	intptr_t cookie = 0;
41	int cpuCount = 0;
42	while (of_get_next_device(&cookie, cpus, "cpu", cpuPath,
43			sizeof(cpuPath)) == B_OK) {
44		TRACE(("found CPU: %s\n", cpuPath));
45
46		// For the first CPU get the frequencies of CPU, bus, and time base.
47		// We assume they are the same for all CPUs.
48		if (cpuCount == 0) {
49			intptr_t cpu = of_finddevice(cpuPath);
50			if (cpu == OF_FAILED) {
51				printf("boot_arch_cpu_init: Failed get CPU device node!\n");
52				return B_ERROR;
53			}
54
55			// TODO: Does encode-int really encode quadlet (32 bit numbers)
56			// only?
57			int32 clockFrequency;
58			if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4)
59					== OF_FAILED) {
60				printf("boot_arch_cpu_init: Failed to get CPU clock "
61					"frequency!\n");
62				return B_ERROR;
63			}
64			if (busFrequency == 0
65				&& of_getprop(cpu, "bus-frequency", &busFrequency, 4)
66					== OF_FAILED) {
67				printf("boot_arch_cpu_init: Failed to get bus clock "
68					"frequency!\n");
69				return B_ERROR;
70			}
71
72			gKernelArgs.arch_args.cpu_frequency = clockFrequency;
73			gKernelArgs.arch_args.bus_frequency = busFrequency;
74			gKernelArgs.arch_args.time_base_frequency = clockFrequency;
75
76			TRACE(("  CPU clock frequency: %d\n", clockFrequency));
77			TRACE(("  bus clock frequency: %d\n", busFrequency));
78		}
79
80		cpuCount++;
81	}
82
83	if (cpuCount == 0) {
84		printf("boot_arch_cpu_init(): Found no CPUs!\n");
85		return B_ERROR;
86	}
87
88	gKernelArgs.num_cpus = cpuCount;
89
90	// allocate the kernel stacks (the memory stuff is already initialized
91	// at this point)
92	addr_t stack = (addr_t)arch_mmu_allocate(NULL,
93		cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE),
94		B_READ_AREA | B_WRITE_AREA, false);
95	if (!stack) {
96		printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n");
97		return B_NO_MEMORY;
98	}
99
100	for (int i = 0; i < cpuCount; i++) {
101		gKernelArgs.cpu_kstack[i].start = stack;
102		gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
103			+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
104		stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
105	}
106
107	return B_OK;
108}
109
110