* Move platform support.cpp into less generic of_support.cpp

* Add header file to support of_support.cpp
* Add support functions to obtain address and size cell lengths
* Small style cleanups
* Add support for G5 PowerPC cpus...
* Refactor memory region code to be aware of 64-bit OF addresses.
  As-is the boot loader wouldn't start on G5 systems because
  OpenFirmware memory base addresses are stored as two 32-bit
  unsigned int 'cells' vs one 32-bit unsigned int 'cell' on G3/G4.
  I removed the static struct and replaced it with a template
  and pass uint32 or uint64 depending on the address cell size.
  Thanks for the idea DeadYak!


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42486 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV 2011-07-25 22:26:35 +00:00
parent 0bb924af97
commit d24ddec4e4
6 changed files with 135 additions and 31 deletions

View File

@ -15,6 +15,13 @@
extern int gChosen;
template<typename addressSize>
struct of_region
{
addressSize base;
uint32 size;
};
struct of_arguments {
const char *name;
int num_args;
@ -27,11 +34,6 @@ struct of_arguments {
#endif
};
struct of_region {
void *base;
uint32 size;
};
#ifdef __cplusplus
extern "C" {

View File

@ -17,7 +17,7 @@ KernelMergeObject boot_platform_openfirmware.o :
network.cpp
real_time_clock.cpp
start.cpp
support.cpp
of_support.cpp
video.cpp
openfirmware.cpp

View File

@ -17,6 +17,7 @@
#include <arch_mmu.h>
#include <kernel.h>
#include "of_support.h"
// set protection to WIMGNPP: -----PP
// PP: 00 - no access
@ -69,30 +70,81 @@ remove_virtual_range_to_keep(void *start, uint32 size)
static status_t
find_physical_memory_ranges(size_t &total)
{
int memory, package;
int memory;
dprintf("checking for memory...\n");
if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED)
return B_ERROR;
package = of_instance_to_package(memory);
int package = of_instance_to_package(memory);
total = 0;
struct of_region regions[64];
int count;
count = of_getprop(package, "reg", regions, sizeof(regions));
/* Memory base addresses are provided in 32 or 64 bit flavors
#address-cells and #size-cells matches the number of 32-bit 'cells'
representing the length of the base address and size fields
*/
int root = of_finddevice("/");
int regAddressCount = of_address_cells(root);
int regSizeCount = of_size_cells(root);
if (regAddressCount == OF_FAILED || regSizeCount == OF_FAILED) {
dprintf("finding base/size length counts failed, assume 32-bit.\n");
regAddressCount = 1;
regSizeCount = 1;
}
dprintf("memory range address cells: %d; size cells: %d;\n",
regAddressCount, regSizeCount);
if (regAddressCount > 2 || regSizeCount > 1) {
dprintf("Unsupported cell size detected. (machine is > 64bit?).\n");
return B_ERROR;
}
// On 64-bit PowerPC systems (G5), our mem base range address is larger
if (regAddressCount == 2) {
struct of_region<uint64> regions[64];
int count = of_getprop(package, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
count = of_getprop(memory, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
return B_ERROR;
count /= sizeof(regions[0]);
for (int32 i = 0; i < count; i++) {
if (regions[i].size <= 0) {
dprintf("%ld: empty region\n", i);
continue;
}
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
"size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size);
total += regions[i].size;
if (insert_physical_memory_range((addr_t)regions[i].base,
regions[i].size) != B_OK) {
dprintf("cannot map physical memory range "
"(num ranges = %" B_PRIu32 ")!\n",
gKernelArgs.num_physical_memory_ranges);
return B_ERROR;
}
}
return B_OK;
}
// Otherwise, normal 32-bit PowerPC G3 or G4 have a smaller 32-bit one
struct of_region<uint32> regions[64];
int count = of_getprop(package, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
count = of_getprop(memory, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
return B_ERROR;
count /= sizeof(of_region);
count /= sizeof(regions[0]);
for (int32 i = 0; i < count; i++) {
if (regions[i].size <= 0) {
dprintf("%ld: empty region\n", i);
continue;
}
dprintf("%" B_PRIu32 ": base = %p, size = %" B_PRIu32 "\n", i,
regions[i].base, regions[i].size);
dprintf("%" B_PRIu32 ": base = %" B_PRIu32 ","
"size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size);
total += regions[i].size;

View File

@ -0,0 +1,48 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold, bonefish@cs.tu-berlin.de
* Alexander von Gluck, kallisti5@unixzen.com
*/
#include "of_support.h"
#include <platform/openfirmware/openfirmware.h>
bigtime_t
system_time(void)
{
int result = of_milliseconds();
return (result == OF_FAILED ? 0 : bigtime_t(result) * 1000);
}
/** given the package provided, get the number of cells
+ in the reg property
+ */
uint32
of_address_cells(int package) {
uint32 address_cells;
if (of_getprop(package, "#address-cells",
&address_cells, sizeof(address_cells)) == OF_FAILED)
return OF_FAILED;
return address_cells;
}
uint32
of_size_cells(int package) {
uint32 size_cells;
if (of_getprop(package, "#size-cells",
&size_cells, sizeof(size_cells)) == OF_FAILED)
return OF_FAILED;
return size_cells;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck, kallisti5@unixzen.com
*/
#ifndef OF_SUPPORT_H
#define OF_SUPPORT_H
#include <OS.h>
bigtime_t system_time(void);
uint32 of_address_cells(int package);
uint32 of_size_cells(int package);
#endif

View File

@ -1,17 +0,0 @@
/*
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <OS.h>
#include <platform/openfirmware/openfirmware.h>
bigtime_t
system_time(void)
{
int result = of_milliseconds();
return (result == OF_FAILED ? 0 : bigtime_t(result) * 1000);
}