From fea91fdc77c1d8a9964f8cb5370b07e872bad90b Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Tue, 2 Apr 2019 22:56:29 +0200 Subject: [PATCH] sparc: pci bus manager Copied from PPC with the hooks for Apple hardware removed. To be completed with the actual PCI bus implementation for Sun machines. This is where we start doing machine specific stuff, apparently. Change-Id: I06af4de9621e9d40593d153642478d928083e49a Reviewed-on: https://review.haiku-os.org/c/1364 Reviewed-by: waddlesplash --- .../private/kernel/arch/sparc/arch_platform.h | 50 +++++++++ .../bus_managers/pci/arch/sparc/Jamfile | 2 +- .../sparc/openfirmware/pci_openfirmware.cpp | 105 ++++++++++++++++++ .../sparc/openfirmware/pci_openfirmware.h | 13 +++ .../openfirmware/pci_openfirmware_priv.h | 49 ++++++++ .../pci/arch/sparc/pci_controller.cpp | 27 +++++ .../bus_managers/pci/arch/sparc/pci_io.c | 61 ++++++++++ .../bus_managers/pci/arch/sparc/pci_io.h | 97 ++++++++++++++++ 8 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 headers/private/kernel/arch/sparc/arch_platform.h create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.cpp create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.h create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware_priv.h create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_controller.cpp create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.c create mode 100644 src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.h diff --git a/headers/private/kernel/arch/sparc/arch_platform.h b/headers/private/kernel/arch/sparc/arch_platform.h new file mode 100644 index 0000000000..24e774eb2f --- /dev/null +++ b/headers/private/kernel/arch/sparc/arch_platform.h @@ -0,0 +1,50 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_SPARC_ARCH_PLATFORM_H +#define _KERNEL_SPARC_ARCH_PLATFORM_H + +#include + +struct real_time_data; + +enum sparc_platform_type { + PPC_PLATFORM_OPEN_FIRMWARE = 0, +}; + +namespace BPrivate { + +class SparcPlatform { +public: + SparcPlatform(sparc_platform_type platformType); + virtual ~SparcPlatform(); + + static SparcPlatform *Default(); + + inline sparc_platform_type PlatformType() const { return fPlatformType; } + + virtual status_t Init(struct kernel_args *kernelArgs) = 0; + virtual status_t InitSerialDebug(struct kernel_args *kernelArgs) = 0; + virtual status_t InitPostVM(struct kernel_args *kernelArgs) = 0; + virtual status_t InitRTC(struct kernel_args *kernelArgs, + struct real_time_data *data) = 0; + + virtual char SerialDebugGetChar() = 0; + virtual void SerialDebugPutChar(char c) = 0; + + virtual void SetHardwareRTC(uint32 seconds) = 0; + virtual uint32 GetHardwareRTC() = 0; + + virtual void ShutDown(bool reboot) = 0; + +private: + sparc_platform_type fPlatformType; +}; + +} // namespace BPrivate + +using BPrivate::SparcPlatform; + + +#endif // _KERNEL_SPARC_ARCH_PLATFORM_H diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile b/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile index 3a4790e24e..8d0941693a 100644 --- a/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/Jamfile @@ -11,6 +11,6 @@ KernelStaticLibrary pci_arch_bus_manager : pci_io.c # openfirmware - # TODO + pci_openfirmware.cpp ; diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.cpp b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.cpp new file mode 100644 index 0000000000..7df3153a98 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.cpp @@ -0,0 +1,105 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "pci_openfirmware.h" + +#include +#include + +#include + +#include +#include +#include + +#include "pci_openfirmware_priv.h" + + +typedef status_t (*probeFunction)(int, const StringArrayPropertyValue&); + +static const probeFunction sProbeFunctions[] = { + NULL, +}; + + +status_t +sparc_openfirmware_pci_controller_init(void) +{ + char path[256]; + int cookie = 0; + while (of_get_next_device(&cookie, 0, "pci", path, sizeof(path)) + == B_OK) { +dprintf("sparc_openfirmware_pci_controller_init(): pci device node: %s\n", path); + // get the device node and the "compatible" property + int deviceNode = of_finddevice(path); + StringArrayPropertyValue compatible; + status_t error = openfirmware_get_property(deviceNode, "compatible", + compatible); + if (error != B_OK) { + dprintf("sparc_openfirmware_pci_controller_init: Failed to get " + "\"compatible\" property for pci device: %s\n", path); + continue; + } + + // probe + for (int i = 0; sProbeFunctions[i]; i++) { + error = sProbeFunctions[i](deviceNode, compatible); + if (error == B_OK) + break; + } + } + + return B_OK; +} + + +// #pragma mark - support functions + + +char * +StringArrayPropertyValue::NextElement(int &cookie) const +{ + if (cookie >= length) + return NULL; + + char *result = value + cookie; + cookie += strnlen(result, length - cookie) + 1; + return result; +} + + +bool +StringArrayPropertyValue::ContainsElement(const char *value) const +{ + int cookie = 0; + while (char *checkValue = NextElement(cookie)) { + if (strcmp(checkValue, value) == 0) + return true; + } + + return false; +} + + +status_t +openfirmware_get_property(int package, const char *propertyName, + PropertyValue &value) +{ + value.length = of_getproplen(package, propertyName); + if (value.length < 0) + return B_ENTRY_NOT_FOUND; + + value.value = (char*)malloc(value.length); + if (!value.value) + return B_NO_MEMORY; + + if (of_getprop(package, propertyName, value.value, value.length) + == OF_FAILED) { + return B_ERROR; + } + + return B_OK; +} + diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.h b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.h new file mode 100644 index 0000000000..5b8c2573b0 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware.h @@ -0,0 +1,13 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_H +#define PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_H + +#include + +status_t sparc_openfirmware_pci_controller_init(void); + +#endif // PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_H diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware_priv.h b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware_priv.h new file mode 100644 index 0000000000..6c9c917696 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/openfirmware/pci_openfirmware_priv.h @@ -0,0 +1,49 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_PRIV_H +#define PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_PRIV_H + +#include +#include + +#include + + +struct StringArrayPropertyValue; + + +// implementations + +// TODO + + +// property support + +struct PropertyValue { + PropertyValue() + : value(NULL) + { + } + + ~PropertyValue() + { + free(value); + } + + char *value; + int length; +}; + +struct StringArrayPropertyValue : PropertyValue { + + char *NextElement(int &cookie) const; + bool ContainsElement(const char *value) const; +}; + +status_t openfirmware_get_property(int package, const char *propertyName, + PropertyValue &value); + +#endif // PCI_BUS_MANAGER_SPARC_OPEN_FIRMWARE_PRIV_H diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_controller.cpp b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_controller.cpp new file mode 100644 index 0000000000..ff8eea2ac0 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_controller.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2006, Ingo Weinhold. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "pci_controller.h" + +#include + +#include "pci_private.h" + +#include "openfirmware/pci_openfirmware.h" + + +status_t +pci_controller_init(void) +{ + return sparc_openfirmware_pci_controller_init(); +} + + +phys_addr_t +pci_ram_address(phys_addr_t physical_address_in_system_memory) +{ + return physical_address_in_system_memory; +} diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.c b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.c new file mode 100644 index 0000000000..94877e26d9 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.c @@ -0,0 +1,61 @@ +/* + * Copyright 2006, Ingo Weinhold. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "pci_io.h" +#include "pci_private.h" + + +static const uint8_t* gPCIBase; + + +status_t +pci_io_init() +{ + // TODO set gPCIBase + return B_OK; +} + + +uint8 +pci_read_io_8(int mapped_io_addr) +{ + return sparc_in8((vuint8*)(gPCIBase + mapped_io_addr)); +} + + +void +pci_write_io_8(int mapped_io_addr, uint8 value) +{ + sparc_out8((vuint8*)(gPCIBase + mapped_io_addr), value); +} + + +uint16 +pci_read_io_16(int mapped_io_addr) +{ + return sparc_in16((vuint16*)(gPCIBase + mapped_io_addr)); +} + + +void +pci_write_io_16(int mapped_io_addr, uint16 value) +{ + sparc_out16((vuint16*)(gPCIBase + mapped_io_addr), value); +} + + +uint32 +pci_read_io_32(int mapped_io_addr) +{ + return sparc_in32((vuint32*)(gPCIBase + mapped_io_addr)); +} + + +void +pci_write_io_32(int mapped_io_addr, uint32 value) +{ + sparc_out32((vuint32*)(gPCIBase + mapped_io_addr), value); +} diff --git a/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.h b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.h new file mode 100644 index 0000000000..6cf0cbc70d --- /dev/null +++ b/src/add-ons/kernel/bus_managers/pci/arch/sparc/pci_io.h @@ -0,0 +1,97 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef PCI_BUS_MANAGER_SPARC_IO_H +#define PCI_BUS_MANAGER_SPARC_IO_H + +#include + +static inline void +sparc_out8(vuint8 *address, uint8 value) +{ + *address = value; + asm volatile("MEMBAR #MemIssue"); +} + + +static inline void +sparc_out16(vuint16 *address, uint16 value) +{ + *address = value; + asm volatile("MEMBAR #MemIssue"); +} + + +static inline void +sparc_out16_reverse(vuint16 *address, uint16 value) +{ + asm volatile("stha %1, [%0] 0x88" : : "r"(address), "r"(value)); + asm volatile("MEMBAR #MemIssue"); +} + + +static inline void +sparc_out32(vuint32 *address, uint32 value) +{ + *address = value; + asm volatile("MEMBAR #MemIssue"); +} + + +static inline void +sparc_out32_reverse(vuint32 *address, uint32 value) +{ + asm volatile("stwa %1, [%0] 0x88" : : "r"(address), "r"(value)); + asm volatile("MEMBAR #MemIssue"); +} + + +static inline uint8 +sparc_in8(const vuint8 *address) +{ + uint8 value = *address; + asm volatile("MEMBAR #MemIssue"); + return value; +} + + +static inline uint16 +sparc_in16(const vuint16 *address) +{ + uint16 value = *address; + asm volatile("MEMBAR #MemIssue"); + return value; +} + + +static inline uint16 +sparc_in16_reverse(const vuint16 *address) +{ + uint16 value; + asm volatile("lha [%1] 0x88, %0" : "=r"(value) : "r"(address)); + asm volatile("MEMBAR #MemIssue"); + return value; +} + + +static inline uint32 +sparc_in32(const vuint32 *address) +{ + uint32 value = *address; + asm volatile("MEMBAR #MemIssue"); + return value; +} + + +static inline uint32 +sparc_in32_reverse(const vuint32 *address) +{ + uint32 value; + asm volatile("ldwa [%1] 0x88, %0" : "=r"(value) : "r"(address)); + asm volatile("MEMBAR #MemIssue"); + return value; +} + +#endif // PCI_BUS_MANAGER_SPARC_IO_H