Author: kallisti5 Date: 2011-07-26 00:26:35 +0200 (Tue, 26 Jul 2011) New Revision: 42486 Changeset: https://dev.haiku-os.org/changeset/42486 Added: haiku/trunk/src/system/boot/platform/openfirmware/of_support.cpp haiku/trunk/src/system/boot/platform/openfirmware/of_support.h Removed: haiku/trunk/src/system/boot/platform/openfirmware/support.cpp Modified: haiku/trunk/headers/private/kernel/platform/openfirmware/openfirmware.h haiku/trunk/src/system/boot/platform/openfirmware/Jamfile haiku/trunk/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp Log: * 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! Modified: haiku/trunk/headers/private/kernel/platform/openfirmware/openfirmware.h =================================================================== --- haiku/trunk/headers/private/kernel/platform/openfirmware/openfirmware.h 2011-07-25 17:39:20 UTC (rev 42485) +++ haiku/trunk/headers/private/kernel/platform/openfirmware/openfirmware.h 2011-07-25 22:26:35 UTC (rev 42486) @@ -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,12 +34,7 @@ #endif }; -struct of_region { - void *base; - uint32 size; -}; - #ifdef __cplusplus extern "C" { #endif Modified: haiku/trunk/src/system/boot/platform/openfirmware/Jamfile =================================================================== --- haiku/trunk/src/system/boot/platform/openfirmware/Jamfile 2011-07-25 17:39:20 UTC (rev 42485) +++ haiku/trunk/src/system/boot/platform/openfirmware/Jamfile 2011-07-25 22:26:35 UTC (rev 42486) @@ -17,7 +17,7 @@ network.cpp real_time_clock.cpp start.cpp - support.cpp + of_support.cpp video.cpp openfirmware.cpp Modified: haiku/trunk/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp 2011-07-25 17:39:20 UTC (rev 42485) +++ haiku/trunk/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp 2011-07-25 22:26:35 UTC (rev 42486) @@ -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 @@ 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; Copied: haiku/trunk/src/system/boot/platform/openfirmware/of_support.cpp (from rev 42485, haiku/trunk/src/system/boot/platform/openfirmware/support.cpp) =================================================================== --- haiku/trunk/src/system/boot/platform/openfirmware/of_support.cpp (rev 0) +++ haiku/trunk/src/system/boot/platform/openfirmware/of_support.cpp 2011-07-25 22:26:35 UTC (rev 42486) @@ -0,0 +1,48 @@ +/* + * Copyright 2005, Ingo Weinhold <bonefish@xxxxxxxxxxxxxxx>. + * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold, bonefish@xxxxxxxxxxxxxxx + * Alexander von Gluck, kallisti5@xxxxxxxxxxx + */ + + +#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; +} + + Added: haiku/trunk/src/system/boot/platform/openfirmware/of_support.h =================================================================== --- haiku/trunk/src/system/boot/platform/openfirmware/of_support.h (rev 0) +++ haiku/trunk/src/system/boot/platform/openfirmware/of_support.h 2011-07-25 22:26:35 UTC (rev 42486) @@ -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@xxxxxxxxxxx + */ +#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