diff --git a/devices/hwcomponent.h b/devices/hwcomponent.h new file mode 100644 index 0000000..5ee0312 --- /dev/null +++ b/devices/hwcomponent.h @@ -0,0 +1,57 @@ +/* +DingusPPC - The Experimental PowerPC Macintosh emulator +Copyright (C) 2018-20 divingkatae and maximum + (theweirdo) spatium + +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef HW_COMPONENT_H +#define HW_COMPONENT_H + +#include + +/** types of different HW components */ +enum HWCompType : int { + UNKNOWN = 0, /* unknown component type */ + MEM_CTRL = 10, /* memory controller */ + ROM = 20, /* read-only memory */ + RAM = 30, /* random access memory */ + MMIO_DEV = 40, /* memory mapped I/O device */ + PCI_HOST = 50, /* PCI host */ + PCI_DEV = 51, /* PCI device */ + I2C_HOST = 60, /* I2C host */ + I2C_DEV = 61, /* I2C device */ + ADB_HOST = 70, /* ADB host */ + ADB_DEV = 71, /* ADB device */ +}; + + +/** Abstract base class for HW components. */ +class HWComponent { +public: + virtual ~HWComponent() = default; + + virtual std::string get_name(void) { return this->name; }; + virtual void set_name(std::string name) { this->name = name; }; + + virtual bool supports_type(HWCompType type) = 0; + +protected: + std::string name; +}; + +#endif /* HW_COMPONENT_H */ diff --git a/devices/machineid.h b/devices/machineid.h index 6398187..114fa69 100644 --- a/devices/machineid.h +++ b/devices/machineid.h @@ -23,6 +23,7 @@ along with this program. If not, see . #define MACHINE_ID_H #include +#include "hwcomponent.h" #include "mmiodevice.h" /** @@ -46,6 +47,10 @@ public: GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; }; ~GossamerID() = default; + bool supports_type(HWCompType type) { + return type == HWCompType::MMIO_DEV; + }; + uint32_t read(uint32_t offset, int size) { return ((!offset && size == 2) ? this->id : 0); }; diff --git a/devices/macio.h b/devices/macio.h index d39816c..b84926e 100644 --- a/devices/macio.h +++ b/devices/macio.h @@ -52,6 +52,7 @@ along with this program. If not, see . #define MACIO_H #include +#include "hwcomponent.h" #include "pcidevice.h" #include "memctrlbase.h" #include "mmiodevice.h" @@ -86,11 +87,11 @@ along with this program. If not, see . class HeathrowIC : public PCIDevice { public: - using PCIDevice::name; - HeathrowIC(); ~HeathrowIC(); + bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; }; + void set_host(PCIHost *host_instance) {this->host_instance = host_instance;}; /* PCI device methods */ diff --git a/devices/memctrlbase.cpp b/devices/memctrlbase.cpp index a9528d3..ea18bbc 100644 --- a/devices/memctrlbase.cpp +++ b/devices/memctrlbase.cpp @@ -27,12 +27,6 @@ along with this program. If not, see . #include "memctrlbase.h" -MemCtrlBase::MemCtrlBase(std::string name) -{ - this->name = name; -} - - MemCtrlBase::~MemCtrlBase() { for (auto ® : mem_regions) { diff --git a/devices/memctrlbase.h b/devices/memctrlbase.h index 2228971..b445946 100644 --- a/devices/memctrlbase.h +++ b/devices/memctrlbase.h @@ -25,7 +25,6 @@ along with this program. If not, see . #include #include #include - #include "mmiodevice.h" enum RangeType { @@ -49,7 +48,7 @@ typedef struct AddressMapEntry { /** Base class for memory controllers. */ class MemCtrlBase { public: - MemCtrlBase(std::string name); + MemCtrlBase() = default; virtual ~MemCtrlBase(); virtual bool add_rom_region(uint32_t start_addr, uint32_t size); virtual bool add_ram_region(uint32_t start_addr, uint32_t size); @@ -62,9 +61,8 @@ public: AddressMapEntry *find_range(uint32_t addr); protected: - bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val); - - std::string name; + bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr, + uint32_t type, uint8_t init_val); private: std::vector mem_regions; diff --git a/devices/mmiodevice.h b/devices/mmiodevice.h index a1ea462..e5c7711 100644 --- a/devices/mmiodevice.h +++ b/devices/mmiodevice.h @@ -24,16 +24,14 @@ along with this program. If not, see . #include #include +#include "hwcomponent.h" /** Abstract class representing a simple, memory-mapped I/O device */ -class MMIODevice { +class MMIODevice : public HWComponent { public: virtual uint32_t read(uint32_t offset, int size) = 0; virtual void write(uint32_t offset, uint32_t value, int size) = 0; virtual ~MMIODevice() = default; - -protected: - std::string name; }; #endif /* MMIO_DEVICE_H */ diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp index cda5674..7a3b755 100644 --- a/devices/mpc106.cpp +++ b/devices/mpc106.cpp @@ -32,11 +32,14 @@ along with this program. If not, see . #include "memreadwrite.h" #include "memctrlbase.h" #include "mmiodevice.h" +#include "hwcomponent.h" #include "mpc106.h" -MPC106::MPC106() : MemCtrlBase("Grackle"), PCIDevice("Grackle PCI host bridge") +MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge") { + this->name = "Grackle"; + /* add memory mapped I/O region for MPC106 registers */ add_mmio_region(0xFEC00000, 0x300000, this); @@ -48,6 +51,16 @@ MPC106::~MPC106() this->pci_0_bus.clear(); } +bool MPC106::supports_type(HWCompType type) +{ + if (type == HWCompType::MEM_CTRL || type == HWCompType::MMIO_DEV || + type == HWCompType::PCI_HOST || type == HWCompType::PCI_DEV) { + return true; + } else { + return false; + } +} + uint32_t MPC106::read(uint32_t offset, int size) { if (offset >= 0x200000) { diff --git a/devices/mpc106.h b/devices/mpc106.h index 245a1b2..c971d78 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -37,6 +37,7 @@ along with this program. If not, see . #include #include +#include "hwcomponent.h" #include "memctrlbase.h" #include "mmiodevice.h" #include "pcidevice.h" @@ -46,10 +47,11 @@ along with this program. If not, see . class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost { public: - using MemCtrlBase::name; - MPC106(); ~MPC106(); + + bool supports_type(HWCompType type); + uint32_t read(uint32_t offset, int size); void write(uint32_t offset, uint32_t value, int size); diff --git a/devices/pcidevice.h b/devices/pcidevice.h index 2a945b0..2ee1851 100644 --- a/devices/pcidevice.h +++ b/devices/pcidevice.h @@ -37,7 +37,7 @@ enum { class PCIDevice : public MMIODevice { public: - PCIDevice(std::string name) {this->name = name;}; + PCIDevice(std::string name) { this->pci_name = name; }; virtual ~PCIDevice() = default; /* configuration space access methods */ @@ -47,9 +47,9 @@ public: virtual void set_host(PCIHost *host_instance) = 0; protected: - std::string name; // human-readable device name + std::string pci_name; // human-readable device name PCIHost *host_instance; // host bridge instance to call back - uint32_t base_addr; // base address register 0 + uint32_t base_addr; // base address register 0 }; #endif /* PCI_DEVICE_H */ diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index e83ea0c..5969912 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -35,6 +35,8 @@ using namespace std; ViaCuda::ViaCuda() { + this->name = "ViaCuda"; + /* FIXME: is this the correct VIA initialization? */ this->via_regs[VIA_A] = 0x80; diff --git a/devices/viacuda.h b/devices/viacuda.h index 98b4662..2fb9262 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -42,11 +42,12 @@ along with this program. If not, see . firmware using bit banging (https://en.wikipedia.org/wiki/Bit_banging). */ -#include "nvram.h" - #ifndef VIACUDA_H #define VIACUDA_H +#include "hwcomponent.h" +#include "nvram.h" + /** VIA register offsets. */ enum { VIA_B = 0x00, /* input/output register B */ @@ -99,12 +100,16 @@ enum { }; -class ViaCuda +class ViaCuda : public HWComponent { public: ViaCuda(); ~ViaCuda(); + bool supports_type(HWCompType type) { + return (type == HWCompType::ADB_HOST || type == HWCompType::I2C_HOST); + }; + uint8_t read(int reg); void write(int reg, uint8_t value); diff --git a/machines/machinebase.cpp b/machines/machinebase.cpp index 76f12b6..141ba80 100644 --- a/machines/machinebase.cpp +++ b/machines/machinebase.cpp @@ -2,6 +2,7 @@ #include #include #include "machinebase.h" +#include "devices/hwcomponent.h" std::unique_ptr gMachineObj = 0; @@ -12,7 +13,6 @@ MachineBase::MachineBase(std::string name) /* initialize internal maps */ this->comp_map.clear(); - this->name_to_type.clear(); this->aliases.clear(); } @@ -24,7 +24,7 @@ MachineBase::~MachineBase() this->comp_map.clear(); } -bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *dev_obj) +bool MachineBase::add_component(std::string name, HWCompType type, HWComponent *dev_obj) { if (this->comp_map.count(name)) { LOG_F(ERROR, "Component %s already exists!", name.c_str()); @@ -32,7 +32,6 @@ bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *d } this->comp_map[name] = dev_obj; - this->name_to_type[name] = type; return true; } @@ -40,10 +39,9 @@ bool MachineBase::add_component(std::string name, HWCompType type, MMIODevice *d void MachineBase::add_alias(std::string name, std::string alias, HWCompType type) { this->aliases[alias] = name; - this->name_to_type[alias] = type; } -MMIODevice *MachineBase::get_comp_by_name(std::string name) +HWComponent *MachineBase::get_comp_by_name(std::string name) { if (this->aliases.count(name)) { name = this->aliases[name]; @@ -56,13 +54,13 @@ MMIODevice *MachineBase::get_comp_by_name(std::string name) } } -MMIODevice *MachineBase::get_comp_by_type(HWCompType type) +HWComponent *MachineBase::get_comp_by_type(HWCompType type) { std::string comp_name; bool found = false; - for(auto it = this->name_to_type.begin(); it != this->name_to_type.end(); it++) { - if (it->second == type) { + for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) { + if (it->second->supports_type(type)) { comp_name = it->first; found = true; break; diff --git a/machines/machinebase.h b/machines/machinebase.h index b3a1928..4d9e6e5 100644 --- a/machines/machinebase.h +++ b/machines/machinebase.h @@ -30,20 +30,7 @@ along with this program. If not, see . #include #include #include -#include "devices/mmiodevice.h" - -/** types of different HW components */ -enum HWCompType : int { - UNKNOWN = 0, /* unknown component type */ - MEM_CTRL = 1, /* memory controller */ - ROM = 2, /* read-only memory */ - RAM = 3, /* random access memory */ - MMIO_DEV = 4, /* memory mapped I/O device */ - PCI_HOST = 5, /* PCI host */ - PCI_DEV = 6, /* PCI device */ - I2C_DEV = 7, /* I2C device */ - ADB_DEV = 8 /* ADB device */ -}; +#include "devices/hwcomponent.h" class MachineBase { @@ -51,15 +38,14 @@ public: MachineBase(std::string name); ~MachineBase(); - bool add_component(std::string name, HWCompType type, MMIODevice *dev_obj); + bool add_component(std::string name, HWCompType type, HWComponent *dev_obj); void add_alias(std::string name, std::string alias, HWCompType type); - MMIODevice *get_comp_by_name(std::string name); - MMIODevice *get_comp_by_type(HWCompType type); + HWComponent *get_comp_by_name(std::string name); + HWComponent *get_comp_by_type(HWCompType type); private: std::string name; - std::mapcomp_map; - std::map name_to_type; + std::mapcomp_map; std::map aliases; }; diff --git a/machines/machinegossamer.cpp b/machines/machinegossamer.cpp index 0cdd11e..6e001cd 100644 --- a/machines/machinegossamer.cpp +++ b/machines/machinegossamer.cpp @@ -26,11 +26,11 @@ along with this program. If not, see . #include #include "machinebase.h" +#include "cpu/ppc/ppcemu.h" #include "devices/mpc106.h" #include "devices/machineid.h" #include "devices/macio.h" -#include "cpu/ppc/ppcemu.h" -#include "machinebase.h" +#include "devices/viacuda.h" int create_gossamer() { @@ -55,7 +55,7 @@ int create_gossamer() gMachineObj->add_component("MachineID", HWCompType::MMIO_DEV, new GossamerID(0x3d8c)); grackle_obj->add_mmio_region(0xFF000004, 4096, - gMachineObj->get_comp_by_name("MachineID")); + dynamic_cast(gMachineObj->get_comp_by_name("MachineID"))); /* add the Heathrow I/O controller */ gMachineObj->add_component("Heathrow", HWCompType::MMIO_DEV, new HeathrowIC);