From ac1f770f92afd9d4eeee3b4534be34df3a420870 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 19 Aug 2019 01:34:24 +0200 Subject: [PATCH 01/13] Create base class for memory controller devices. Create 'devices' directory for virtual device sources and move MPC106 source to it. --- devices/memctrlbase.cpp | 131 +++++++++++++++++++++++++++++++ devices/memctrlbase.h | 53 +++++++++++++ devices/mmiodevice.h | 21 +++++ mpc106.cpp => devices/mpc106.cpp | 6 +- mpc106.h => devices/mpc106.h | 0 main.cpp | 2 +- makefile | 27 ++++--- ppcmemory.cpp | 2 +- 8 files changed, 228 insertions(+), 14 deletions(-) create mode 100644 devices/memctrlbase.cpp create mode 100644 devices/memctrlbase.h create mode 100644 devices/mmiodevice.h rename mpc106.cpp => devices/mpc106.cpp (96%) rename mpc106.h => devices/mpc106.h (100%) diff --git a/devices/memctrlbase.cpp b/devices/memctrlbase.cpp new file mode 100644 index 0000000..cd4af99 --- /dev/null +++ b/devices/memctrlbase.cpp @@ -0,0 +1,131 @@ +#include +#include + +#include "memctrlbase.h" + + +MemCtrlBase::MemCtrlBase(std::string name) +{ + this->name = name; +} + + +MemCtrlBase::~MemCtrlBase() +{ + for (auto ® : mem_regions) { + if (reg) + delete(reg); + } + this->mem_regions.clear(); + this->address_map.clear(); +} + + +AddressMapEntry *MemCtrlBase::find_range(uint32_t addr) +{ + for (auto &entry : address_map) { + if (addr >= entry.start && addr <= entry.end) + return &entry; + } + + return 0; +} + + +bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size, + uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) +{ + AddressMapEntry entry; + + /* error if a memory region for the given range already exists */ + if (find_range(start_addr) || find_range(start_addr + size)) + return false; + + uint8_t *reg_content = new uint8_t[size]; + if (!reg_content) + return false; + + this->mem_regions.push_back(reg_content); + + entry.start = start_addr; + entry.end = start_addr + size - 1; + entry.mirror = dest_addr; + entry.type = type; + entry.devobj = 0; + entry.mem_ptr = reg_content; + + this->address_map.push_back(entry); + + return true; +} + + +bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size) +{ + return add_mem_region(start_addr, size, 0, RT_ROM); +} + + +bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size) +{ + return add_mem_region(start_addr, size, 0, RT_RAM); +} + + +bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) +{ + AddressMapEntry entry, *ref_entry; + + ref_entry = find_range(dest_addr); + if (!ref_entry) + return false; + + entry.start = start_addr; + entry.end = start_addr + (ref_entry->end - ref_entry->start) + 1; + entry.mirror = dest_addr; + entry.type = ref_entry->type | RT_MIRROR; + entry.devobj = 0; + entry.mem_ptr = ref_entry->mem_ptr; + + this->address_map.push_back(entry); + + return true; +} + + +bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size) +{ + AddressMapEntry *ref_entry; + uint32_t cpy_size; + + ref_entry = find_range(reg_addr); + if (!ref_entry) + return false; + + cpy_size = std::min(ref_entry->end - ref_entry->start + 1, size); + memcpy(ref_entry->mem_ptr, data, cpy_size); + + return true; +} + + +bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, + MMIODevice *dev_instance) +{ + AddressMapEntry entry; + + /* error if another region for the given range already exists */ + if (find_range(start_addr) || find_range(start_addr + size)) + return false; + + entry.start = start_addr; + entry.end = start_addr + size - 1; + entry.mirror = 0; + entry.type = RT_MMIO; + entry.devobj = dev_instance; + entry.mem_ptr = 0; + + this->address_map.push_back(entry); + + return true; +} diff --git a/devices/memctrlbase.h b/devices/memctrlbase.h new file mode 100644 index 0000000..75e5c66 --- /dev/null +++ b/devices/memctrlbase.h @@ -0,0 +1,53 @@ +#ifndef MEMORY_CONTROLLER_BASE_H +#define MEMORY_CONTROLLER_BASE_H + +#include +#include +#include + +#include "mmiodevice.h" + +enum RangeType { + RT_ROM = 1, /* read-only memory */ + RT_RAM = 2, /* random access memory */ + RT_MMIO = 4, /* memory mapped I/O */ + RT_MIRROR = 8 /* region mirror (content of another region is acessible + at some other address) */ +}; + +typedef struct AddressMapEntry { + uint32_t start; /* first address of the corresponding range */ + uint32_t end; /* last address of the corresponding range */ + uint32_t mirror; /* mirror address for RT_MIRROR */ + uint32_t type; /* range type */ + MMIODevice *devobj; /* pointer to device object */ + unsigned char *mem_ptr; /* direct pointer to data for memory objects */ +} AddressMapEntry; + + +/** Base class for memory controllers. */ +class MemCtrlBase { +public: + MemCtrlBase(std::string name); + 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); + virtual bool add_mem_mirror(uint32_t start_addr, uint32_t dest_addr); + + virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice *dev_instance); + + virtual bool set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size); + + 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; + +private: + std::vector mem_regions; + std::vector address_map; +}; + +#endif /* MEMORY_CONTROLLER_BASE_H */ diff --git a/devices/mmiodevice.h b/devices/mmiodevice.h new file mode 100644 index 0000000..454d1af --- /dev/null +++ b/devices/mmiodevice.h @@ -0,0 +1,21 @@ +#ifndef MMIO_DEVICE_H +#define MMIO_DEVICE_H + +#include +#include + +#define READ_WORD_BE(addr) ((addr)[0] << 16) | (addr)[1] +#define READ_DWORD_BE(addr) ((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3] + +/** Abstract class representing a simple, memory-mapped I/O device */ +class MMIODevice { +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/mpc106.cpp b/devices/mpc106.cpp similarity index 96% rename from mpc106.cpp rename to devices/mpc106.cpp index e4ea06f..903ffc3 100644 --- a/mpc106.cpp +++ b/devices/mpc106.cpp @@ -10,10 +10,10 @@ #include #include #include -#include "viacuda.h" +#include "../viacuda.h" #include "mpc106.h" -#include "ppcemumain.h" -#include "ppcmemory.h" +#include "../ppcemumain.h" +#include "../ppcmemory.h" bool mpc106_membound_change; bool mpc106_mem_approve; //Confirm memory transaction diff --git a/mpc106.h b/devices/mpc106.h similarity index 100% rename from mpc106.h rename to devices/mpc106.h diff --git a/main.cpp b/main.cpp index 0971a97..bf0c7fd 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,7 @@ #include "macswim3.h" #include "ppcmemory.h" #include "viacuda.h" -#include "mpc106.h" +#include "devices/mpc106.h" #include "openpic.h" #include "debugger.h" //#include diff --git a/makefile b/makefile index e7d185c..0978439 100644 --- a/makefile +++ b/makefile @@ -1,17 +1,26 @@ -OBJS = main.o macioserial.o macscsi.o macswim3.o mpc106.o openpic.o poweropcodes.o \ - ppcfpopcodes.o ppcgekkoopcodes.o ppcmemory.o ppcopcodes.o viacuda.o davbus.o \ - debugger.o +EXE := dingusppc +MODULES := . devices +SRCS := $(foreach sdir,$(MODULES),$(wildcard $(sdir)/*.cpp)) +#SRCS = $(wildcard *.cpp) +OBJS := $(patsubst %.cpp, %.o, $(SRCS)) -OUT = dingusppc CXX = g++ CXXFLAGS = -g -c -Wall -std=c++11 LFLAGS = -all: $(OBJS) - $(CXX) -g $(OBJS) -o $(OUT) $(LFLAGS) +VPATH := devices -*.o : *.cpp - $(CXX) $(CXXFLAGS) -c $(input) -o $(output) +DEPS = $(OBJS:.o=.d) + +all: $(EXE) + +$(EXE) : $(OBJS) + $(CXX) -o $@ $^ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -MMD -o $@ $< clean: - rm -f *.o $(OUT) + rm -rf *.o *.d devices/*.o devices/*.d $(EXE) + +-include $(DEPS) diff --git a/ppcmemory.cpp b/ppcmemory.cpp index ccea6c5..ce55785 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -20,7 +20,7 @@ #include "ppcemumain.h" #include "ppcmemory.h" #include "openpic.h" -#include "mpc106.h" +#include "devices/mpc106.h" #include "davbus.h" std::vector pte_storage; From 2f06623c62eea8903467a9bda03c3eaf0fce9442 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Wed, 21 Aug 2019 08:33:01 +0200 Subject: [PATCH 02/13] Rewrite MPC106 emualation from scratch. From now on, ppcmemory delegates physical address translation to MPC106 on PowerMac Beige G3. --- .gitignore | 1 + devices/mpc106.cpp | 455 +++++++++-------------------------- devices/mpc106.h | 79 ++++-- main.cpp | 225 ++++++----------- ppcemumain.h | 6 +- ppcmemory.cpp | 584 +++++++++------------------------------------ 6 files changed, 364 insertions(+), 986 deletions(-) diff --git a/.gitignore b/.gitignore index 2d3b8c1..9c44707 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Ignore compiled object files *.o +*.d # Ignore generated executables dingusppc diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp index 903ffc3..3607199 100644 --- a/devices/mpc106.cpp +++ b/devices/mpc106.cpp @@ -5,368 +5,151 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) -//Functionality for the MPC106 +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski +*/ #include #include #include + +#include "memctrlbase.h" +#include "mmiodevice.h" #include "../viacuda.h" #include "mpc106.h" #include "../ppcemumain.h" #include "../ppcmemory.h" -bool mpc106_membound_change; -bool mpc106_mem_approve; //Confirm memory transaction -uint32_t mpc106_address; // For fe000000 - fe00ffff -uint32_t mpc_config_addr; // Device No. and Reg No. included -uint32_t mpc_config_dat; // Value to write to the device -uint32_t cust_grab_size; // Custom bit size - -uint32_t mpc106_write_word; -uint32_t mpc106_read_word; -uint16_t mpc106_write_half; -uint16_t mpc106_read_half; -uint8_t mpc106_write_byte; -uint8_t mpc106_read_byte; - -uint8_t mpc106_word_custom_size; - -//The below array is used for ROM banks -//Top eight entries are for the starting addresses -//Bottom eight entries are for the ending addresses -uint32_t mpc106_memory_bounds[16] = +MPC106::MPC106() : MemCtrlBase("Grackle") { -0x00000, 0x00000, 0x00000, 0x00000, -0x00000, 0x00000, 0x00000, 0x00000, -0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF, -0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF, -}; - -//Entries are organized like so... - -//ROM Banks 0-3 (ext. starting address) (starting address) (0x00000) -//ROM Banks 4-7 (ext. starting address) (starting address) (0x00000) -//ROM Banks 0-3 (ext. ending address) ( ending address) (0x00000) -//ROM Banks 4-7 (ext. ending address) ( ending address) (0x00000) - -void mpc106_init(){ - mpc_config_addr = 0; - mpc_config_dat = 0; - - //Initialize Vendor & Device IDs - machine_fexxxx_mem[0x00] = 0x57; - machine_fexxxx_mem[0x01] = 0x10; - - machine_fexxxx_mem[0x02] = 0x02; - - //PCI command + status - machine_fexxxx_mem[0x04] = 0x06; - machine_fexxxx_mem[0x06] = 0x80; - - machine_fexxxx_mem[0x0B] = 0x06; - machine_fexxxx_mem[0x0C] = 0x08; - - machine_fexxxx_mem[0x73] = 0xCD; - - machine_fexxxx_mem[0xA8] = 0x10; - machine_fexxxx_mem[0xA9] = 0x00; - machine_fexxxx_mem[0xAA] = 0x00; - machine_fexxxx_mem[0xAB] = 0xFF; - - machine_fexxxx_mem[0xAC] = 0x0C; - machine_fexxxx_mem[0xAD] = 0x06; - machine_fexxxx_mem[0xAE] = 0x0C; - machine_fexxxx_mem[0xAF] = 0x00; - - machine_fexxxx_mem[0xBA] = 0x04; - machine_fexxxx_mem[0xC0] = 0x01; - - machine_fexxxx_mem[0xE0] = 0x42; - machine_fexxxx_mem[0xE1] = 0x00; - machine_fexxxx_mem[0xE2] = 0xFF; - machine_fexxxx_mem[0xE3] = 0x0F; - - machine_fexxxx_mem[0xF0] = 0x00; - machine_fexxxx_mem[0xF1] = 0x00; - machine_fexxxx_mem[0xF2] = 0x02; - machine_fexxxx_mem[0xF3] = 0xFF; - - machine_fexxxx_mem[0xF4] = 0x03; - machine_fexxxx_mem[0xF5] = 0x00; - machine_fexxxx_mem[0xF6] = 0x00; - machine_fexxxx_mem[0xF7] = 0x00; - - machine_fexxxx_mem[0xFC] = 0x00; - machine_fexxxx_mem[0xFD] = 0x00; - machine_fexxxx_mem[0xFE] = 0x10; - machine_fexxxx_mem[0xFF] = 0x00; - - mpc106_mem_approve = false; - mpc106_word_custom_size = 0; + /* add memory mapped I/O region for MPC106 registers */ + add_mmio_region(0xFEC00000, 0x300000, this); } -uint32_t mpc106_write_device(uint32_t device_addr, uint32_t insert_to_device, uint8_t bit_length){ - //Write to the specified device - Invoked when a write is made to 0xFEExxxxx. - //device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register). +MPC106::~MPC106() +{ +} - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; +uint32_t MPC106::read(uint32_t offset, int size) +{ + if (offset >= 0x200000) { + if (this->config_addr & 0x80) // process only if bit E (enable) is set + return pci_read(size); + } - switch(dev_num){ - case 0: - //Device 0 is reserved to the grackle by default - mpc106_address = reg_num; - mpc106_write(insert_to_device); - break; - case 16: - case 17: - via_cuda_address = (reg_num << 9) + (dev_num << 12) + 0x3000000; - via_write_byte = (uint8_t)insert_to_device; - via_cuda_write(); - break; + /* FIXME: reading from CONFIG_ADDR is ignored for now */ + + return 0; +} + +void MPC106::write(uint32_t offset, uint32_t value, int size) +{ + if (offset < 0x200000) { + this->config_addr = value; + } else { + if (this->config_addr & 0x80) // process only if bit E (enable) is set + return pci_write(value, size); + } +} + +uint32_t MPC106::pci_read(uint32_t size) +{ + int bus_num, dev_num, fun_num, reg_num; + + bus_num = (this->config_addr >> 8) & 0xFF; + if (bus_num) { + std::cout << this->name << " err: read attempt from non-local PCI bus, " + << "config_addr = " << std::hex << this->config_addr << std::endl; + return 0; + } + + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_num = (this->config_addr >> 24) & 0xFC; + + if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself + return myself_read(reg_num, size); + } else { + std::cout << this->name << " err: reading from device " << dev_num + << " not supported yet" << std::endl; + return 0; } return 0; } -uint32_t mpc106_read_device(uint32_t device_addr, uint8_t bit_length){ - //Read to the specified device - Invoked when a read is made to 0xFEExxxxx. - //device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register). +void MPC106::pci_write(uint32_t value, uint32_t size) +{ + int bus_num, dev_num, fun_num, reg_num; - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; + bus_num = (this->config_addr >> 8) & 0xFF; + if (bus_num) { + std::cout << this->name << " err: write attempt to non-local PCI bus, " + << "config_addr = " << std::hex << this->config_addr << std::endl; + return; + } - uint32_t grab_value = 0; + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_num = (this->config_addr >> 24) & 0xFC; - switch(dev_num){ - case 0: - //Device 0 is reserved to the grackle by default - mpc106_address = reg_num; - mpc106_read(); - grab_value = mpc106_read_word; + if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself + myself_write(reg_num, value, size); + } else { + std::cout << this->name << " err: writing to device " << dev_num + << " not supported yet" << std::endl; + } +} + +uint32_t MPC106::myself_read(int reg_num, uint32_t size) +{ +#ifdef MPC106_DEBUG + printf("read from Grackle register %08X\n", reg_num); +#endif + + switch(size) { + case 1: + return this->my_pci_cfg_hdr[reg_num]; break; - case 16: - case 17: - via_cuda_address = (reg_num << 8) + (dev_num << 12) + 0x3000000; - via_cuda_read(); - grab_value = (uint32_t)via_read_byte; + case 2: + return READ_WORD_BE(&this->my_pci_cfg_hdr[reg_num]); break; - } - - return grab_value; -} - -bool mpc106_check_membound(uint32_t attempted_address){ - uint32_t mem_address_begin; - uint32_t mem_address_end; - for (int get_rom_bank = 0; get_rom_bank < 8; get_rom_bank++){ - mem_address_begin = mpc106_memory_bounds[get_rom_bank]; - mem_address_end = mpc106_memory_bounds[get_rom_bank + 8]; - if ((attempted_address >= mem_address_begin) & (attempted_address <= mem_address_end)){ - uint8_t is_valid = (machine_fexxxx_mem[0xA0] >> get_rom_bank) & 0x01; - if (is_valid == 0){ - return true; - } - } - } - return false; -} - - -void mpc106_set_membound_begin(uint8_t bound_area){ - uint32_t bcheck_area = 0x80 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = bound_area % 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0xfffff; - change_entry = newbound << 20; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_extbegin(uint8_t bound_area){ - uint32_t bcheck_area = 0x88 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = bound_area % 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0x0fffffff; - change_entry = (newbound & 0x3) << 28; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_end(uint8_t bound_area){ - uint32_t bcheck_area = 0x90 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = (bound_area % 8) + 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0xfffff; - change_entry = newbound << 20; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_extend(uint8_t bound_area){ - uint32_t bcheck_area = 0x98 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = (bound_area % 8) + 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0x0fffffff; - change_entry = (newbound & 0x3) << 28; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_read(){ - - uint8_t read_length = 4; - - - if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){ - mpc106_membound_change = true; - read_length = mpc106_word_custom_size; - } - else{ - switch (mpc106_address){ - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - case 0xE: - case 0xF: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x72: - case 0x73: - case 0xA0: - case 0xA3: - read_length = 1; + case 4: + return READ_DWORD_BE(&this->my_pci_cfg_hdr[reg_num]); break; - case 0x0: - case 0x2: - case 0x4: - case 0x6: - case 0x70: - read_length = 2; + default: + std::cout << "MPC106 read error: invalid size parameter " << size + << std::endl; + } + + return 0; +} + +void MPC106::myself_write(int reg_num, uint32_t value, uint32_t size) +{ +#ifdef MPC106_DEBUG + printf("write %08X to Grackle register %08X\n", value, reg_num); +#endif + + // FIXME: implement write-protection for read-only registers + switch(size) { + case 1: + this->my_pci_cfg_hdr[reg_num] = value & 0xFF; break; - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - read_length = 4; - default: //Avoid writing into reserved areas - read_length = 0; - } - } - - switch(read_length){ - case 1: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]); - break; - case 2: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]); - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 8; - break; - case 4: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]); - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 8; - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 16; - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 24; - break; - } - -} - -void mpc106_write(uint32_t write_word){ - - uint8_t write_length = 4; - - if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){ - mpc106_membound_change = true; - write_length = mpc106_word_custom_size; - } - else{ - switch (mpc106_address){ - case 0x70: - case 0x72: - case 0x73: - case 0xA0: - case 0xA3: - write_length = 1; - break; - case 0x4: - case 0x6: - write_length = 2; - break; - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - write_length = 4; - default: //Avoid writing into reserved areas - write_length = 0; - } - } - - if (mpc106_membound_change){ - switch(write_length){ - case 1: - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF); - break; - case 2: - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - break; - case 4: - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF); - break; - } - } - else{ - switch(write_length){ - case 1: - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF); - break; - case 2: - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - break; - case 4: - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF); - break; - } - } -} - -void change_membound_time(){ - if (mpc106_address < 0x88){ - mpc106_set_membound_begin(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0x90){ - mpc106_set_membound_extbegin(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0x98){ - mpc106_set_membound_end(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0xA0){ - mpc106_set_membound_extend(mpc106_address); - mpc106_membound_change = false; + case 2: + this->my_pci_cfg_hdr[reg_num] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_num+1] = value & 0xFF; + break; + case 4: + this->my_pci_cfg_hdr[reg_num] = (value >> 24) & 0xFF; + this->my_pci_cfg_hdr[reg_num+1] = (value >> 16) & 0xFF; + this->my_pci_cfg_hdr[reg_num+2] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_num+3] = value & 0xFF; + break; + default: + std::cout << "MPC106 read error: invalid size parameter " << size + << std::endl; } } diff --git a/devices/mpc106.h b/devices/mpc106.h index 91c96f5..13f6b74 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -5,34 +5,71 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) -//Functionality for the MPC106 +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski + + Grackle IC is a combined memory and PCI controller manufactored by Motorola. + It's the central device in the Gossamer architecture. + Manual: https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf + + This code emulate as much functionality as needed to run PowerMac Beige G3. + This implies that + - we only support address map B + - our virtual device reports revision 4.0 as expected by machine firmware +*/ #ifndef MPC106_H_ #define MPC106_H_ -#define mpc106_addres_map_a 1 -#define mpc106_addres_map_b 0 +#include +#include "memctrlbase.h" +#include "mmiodevice.h" -extern uint32_t mpc106_address; -extern uint32_t mpc_config_addr; -extern uint32_t mpc_config_dat; -extern uint32_t mpc106_write_word; -extern uint32_t mpc106_read_word; -extern uint16_t mpc106_write_half; -extern uint16_t mpc106_read_half; -extern uint8_t mpc106_write_byte; -extern uint8_t mpc106_read_byte; -extern uint8_t mpc106_word_custom_size; +class MPC106 : public MemCtrlBase, public MMIODevice +{ +public: + using MemCtrlBase::name; -extern unsigned char* mpc106_regs; + MPC106(); + ~MPC106(); + uint32_t read(uint32_t offset, int size); + void write(uint32_t offset, uint32_t value, int size); -extern void change_membound_time(); -extern void mpc106_init(); -extern void mpc106_read(); -extern void mpc106_write(uint32_t write_word); -extern uint32_t mpc106_write_device(uint32_t device_addr, uint32_t insert_to_device, uint8_t bit_length); -extern uint32_t mpc106_read_device(uint32_t device_addr, uint8_t bit_length); -extern bool mpc106_check_membound(uint32_t attempted_address); +protected: + /* PCI access */ + uint32_t pci_read(uint32_t size); + void pci_write(uint32_t value, uint32_t size); + + /* my own registers access */ + uint32_t myself_read(int reg_num, uint32_t size); + void myself_write(int reg_num, uint32_t value, uint32_t size); + +private: + uint8_t my_pci_cfg_hdr[256] = { + 0x57, 0x10, // vendor ID: Motorola + 0x02, 0x00, // device ID: MPC106 + 0x06, 0x00, // PCI command + 0x80, 0x00, // PCI status + 0x40, // revision ID: 4.0 + 0x00, // standard programming + 0x00, // subclass code + 0x06, // class code + [0x73] = 0xCD, // default value for ODCR + [0xA8] = 0x10, 0x00, 0x00, 0xFF, // PICR1 + [0xAC] = 0x0C, 0x06, 0x0C, 0x00, // PICR2 + [0xBA] = 0x04, + [0xC0] = 0x01, + [0xE0] = 0x42, 0x00, 0xFF, 0x0F, + [0xE8] = 0x20, + [0xF0] = 0x00, 0x00, 0x02, 0xFF, + [0xF4] = 0x03, + [0xFC] = 0x00, 0x00, 0x10, 0x00 + }; + + uint32_t config_addr; + //uint32_t config_data; +}; #endif diff --git a/main.cpp b/main.cpp index bf0c7fd..99eb81d 100644 --- a/main.cpp +++ b/main.cpp @@ -38,6 +38,33 @@ using namespace std; +/** + Power Macintosh ROM identification string + + is located in the ConfigInfo structure starting at 0x30D064 (PCI Macs) + or 0x30C064 (Nubus Macs). This helps a lot to determine which + hardware is to be used. +*/ +static const map PPCMac_ROMIdentity = { //Codename Abbreviation for... + {"Alch", "Performa 6400"}, //Alchemy + {"Come", "PowerBook 2400"}, //Comet + {"Cord", "Power Mac 5200/6200 series"}, //Cordyceps + {"Gaze", "Power Mac 6500"}, //Gazelle + {"Goss", "Power Mac G3 Beige"}, //Gossamer + {"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown) + {"Hoop", "PowerBook 3400"}, //Hooper + {"PBX ", "PowerBook Pre-G3"}, //(Unknown) + {"PDM ", "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100) + {"Pip ", "Pippin... uh... yeah..."}, //Pippin + {"Powe", "Generic Power Mac"}, //PowerMac? + {"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus + {"Tanz", "Power Mac 4400"}, //Tanzania + {"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-) + {"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM) + {"????", "A clone, perhaps?"} //N/A (Placeholder ID) +}; + + SetPRS ppc_state; bool power_on = 1; @@ -55,6 +82,7 @@ uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA uint32_t return_value; +MemCtrlBase *mem_ctrl_instance = 0; //A pointer to a pointer, used for quick movement to one of the following //memory areas. These are listed right below. @@ -90,7 +118,7 @@ bool msr_es_change; //Check Endian uint32_t rom_file_begin; //where to start storing ROM files in memory uint32_t pci_io_end; -uint32_t rom_file_setsize; +uint32_t rom_filesize; clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly. @@ -397,26 +425,14 @@ int main(int argc, char **argv) rom_file_begin = 0xFFF00000; //where to start storing ROM files in memory pci_io_end = 0x83FFFFFF; - rom_file_setsize = 0x400000; + rom_filesize = 0x400000; + //Init virtual CPU. reg_init(); - /** - uint16_t test_endianness = 0x1234; - - //Test for endianess before beginning - uint8_t grab_result = (uint8_t) (test_endianness >> 8); - endian_switch endis; - - //Special case for little-endian machines - switch(unsigned(grab_result)){ - case 18: - endis = little_end; - break; - default: - endis = big_end; - } - **/ + //0xFFF00100 is where the reset vector is. + //In other words, begin executing code here. + ppc_state.ppc_pc = 0xFFF00100; uint32_t opcode_entered = 0; //used for testing opcodes in playground @@ -431,38 +447,25 @@ int main(int argc, char **argv) romFile.open("rom.bin", ios::in|ios::binary); if (romFile.fail()){ - cerr << "rom.bin not present. Creating it right now. Please restart this program.\n"; - std::ofstream outfile ("rom.bin", ios::binary); - - outfile << "Testing!" << std::endl; - - outfile.close(); + cerr << "rom.bin not present. Please provide an appropriate ROM file" + << "and restart this program.\n"; + romFile.close(); return 1; } - //Allocate memory for ROM, RAM, and I/O. + //Calculate and validate ROM file size. romFile.seekg(0, romFile.end); - rom_file_setsize = romFile.tellg(); - printf("Rom SIZE: %d \n", rom_file_setsize); + rom_filesize = romFile.tellg(); + printf("Rom SIZE: %d \n", rom_filesize); romFile.seekg (0, romFile.beg); - /** - Allocate memory wisely. + if (rom_filesize != 0x400000){ + cerr << "Unsupported ROM File size. Expected size is 4 megabytes.\n"; + romFile.close(); + return 1; + } - Corresponds (mostly) to the follow memory patterns seen in - https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf - - machine_sysram_mem - 0x00000000 to 0x7FFFFFFF - machine_upperiocontrol_mem - 0x80000000 to 0x807FFFFF - machine_iocontrolcdma_mem - 0x80800000 to 0x80FFFFFF - machine_loweriocontrol_mem - 0x81000000 to 0xBF7FFFFF - machine_interruptack_mem - 0xBFFFFFF0 to 0xBFFFFFFF - machine_iocontrolmem_mem - 0xC0000000 to 0xFFBFFFFF - machine_sysrom_mem - 0xFFC00000 to 0xFFFFFFFF - **/ - - //grab_disk_buf = (unsigned char*) calloc (32768, 1); machine_sysram_mem = (unsigned char*) calloc (67108864, 1); machine_sysconfig_mem = (unsigned char*) calloc (2048, 1); machine_upperiocontrol_mem = (unsigned char*) calloc (8388608, 1); @@ -476,7 +479,7 @@ int main(int argc, char **argv) machine_feexxx_mem = (unsigned char*) calloc (4096, 1); machine_ff00xx_mem = (unsigned char*) calloc (4096, 1); machine_ff80xx_mem = (unsigned char*) calloc (1048576, 1); - machine_sysrom_mem = (unsigned char*) calloc (rom_file_setsize, 1); + machine_sysrom_mem = (unsigned char*) calloc (rom_filesize, 1); memset(machine_sysram_mem, 0x0, 67108864); memset(machine_sysconfig_mem, 0x0, 2048); @@ -492,19 +495,10 @@ int main(int argc, char **argv) memset(machine_ff80xx_mem, 0x0, 1048576); grab_sysram_size = sizeof(machine_sysram_mem); - grab_sysrom_size = rom_file_setsize; + grab_sysrom_size = rom_filesize; //Sanity checks - Prevent the input files being too small or too big. //Also prevent the ROM area from overflow. - if (grab_sysrom_size < 0x100000){ - cerr << "ROM File is too small. Must be at least 1 megabyte.\n"; - return 1; - } - else if (grab_sysrom_size > 0x400000){ - cerr << "ROM File is too big. Must be no more than 4 megabytes.\n"; - return 1; - } - if (ram_size_set < 0x800000){ cerr << "The RAM size must be at least 8 MB to function.\n"; return 1; @@ -516,41 +510,11 @@ int main(int argc, char **argv) rom_file_begin = 0xFFFFFFFF - grab_sysrom_size + 1; - /** - Test for PowerPC Mac ROMS - - Starting at 0x30D064 (0x30C064 in older ROMS), there is a boot - identifier string in the ROM. This helps a lot to determine which - setup is to by used. - **/ - char * memPPCBlock = new char[5]; - - map PPCMac_ROMIdentity = { //Codename Abbreviation for... - {"Alch", "Performa 6400"}, //Alchemy - {"Come", "PowerBook 2400"}, //Comet - {"Cord", "Power Mac 5200/6200 series"}, //Cordyceps - {"Gaze", "Power Mac 6500"}, //Gazelle - {"Goss", "Power Mac G3 Beige"}, //Gossamer - {"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown) - {"Hoop", "PowerBook 3400"}, //Hooper - {"PBX ", "PowerBook Pre-G3"}, //(Unknown) - {"PDM ", "Power Mac G1 or WGS"}, //(Unknown) - {"Pip ", "Pippin... uh... yeah..."}, //Pippin - {"Powe", "Generic Power Mac"}, //PowerMac? - {"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus - {"Tanz", "Power Mac 4400"}, //Tanzania - {"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-) - {"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM) - {"????", "A clone, perhaps?"} //N/A (Placeholder ID) - }; - char configGrab = 0; uint32_t configInfoOffset = 0; - if (grab_sysrom_size == 0x400000){ - romFile.seekg (0x300082, ios::beg); //This is where the place to get the offset is - romFile.get(configGrab); //just one byte to determine where the identifier string is + romFile.get(configGrab); //just one byte to determine ConfigInfo location configInfoOffset = (uint32_t)(configGrab & 0xff); if (configInfoOffset == 0xC0){ @@ -558,8 +522,11 @@ int main(int argc, char **argv) } uint32_t configInfoAddr = 0x300000 + (configInfoOffset << 8) + 0x69; //address to check the identifier string + char memPPCBlock[5]; //First four chars are enough to distinguish between codenames romFile.seekg (configInfoAddr, ios::beg); - romFile.read(memPPCBlock, sizeof(uint32_t)); //Only four chars needed to distinguish between codenames + romFile.read(memPPCBlock, 4); + memPPCBlock[4] = 0; + uint32_t rom_id = (memPPCBlock[0] << 24) | (memPPCBlock[1] << 16) | (memPPCBlock[2] << 8) | memPPCBlock[3]; std::string string_test = std::string(memPPCBlock); @@ -571,58 +538,35 @@ int main(int argc, char **argv) if (string_test.compare(redo_me) == 0){ cout << "The machine is identified as..." << iter->second << endl; romFile.seekg (0x0, ios::beg); - - //This is where the first real instruction is in the ROM - //0xFFF00000 - 0xFFF02FFF is for the exception table, - //which is stored in all PPC ROMs here, btw. - - //0xFFF00100 is where the reset vector is. - //In other words, begin executing code here. - - ppc_state.ppc_pc = 0xFFF00100;//Please don't move this from here. - //A strange bug will happen where this will prevent proper branching - mpc106_init(); - mac_serial_init(); - mac_swim3_init(); - via_cuda_init(); - openpic_init(); break; } else{ iter++; } } + + switch(rom_id) { + case 0x476F7373: + cout << "Initialize Gossamer hardware..."; + mem_ctrl_instance = new MPC106(); + if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000) || + !mem_ctrl_instance->add_ram_region(0x00000000, 0x800000)) { + cout << "failure!\n" << endl; + delete(mem_ctrl_instance); + romFile.close(); + return 1; + } + cout << "done" << endl; + break; + default: + cout << "This machine not supported yet." << endl; + return 1; } - //Copy the contents of the IO data and the ROM to memory appropriate locations. + //Read ROM file content and transfer it to the dedicated ROM region romFile.read ((char *)machine_sysrom_mem,grab_sysrom_size); - - /* - //Open the Disk File. - uint64_t disk_file_setsize = 0; - ifstream diskFile; - - diskFile.open("disk.img", ios::in|ios::binary); - - if (diskFile){ - diskFile.seekg(0, romFile.end); - disk_file_setsize = romFile.tellg(); - diskFile.seekg(0, romFile.beg); - - if (disk_file_setsize % 32678 != 0){ - cout << "WARNING - Disk file has improper offsets. Make sure the disk image has even 32 KB sectors." << endl; - } - else{ - //Copy the contents of the IO data and the ROM to memory appropriate locations. - diskFile.read ((char *)machine_sysram_mem,(sizeof(uint8_t)*0x8000)); - disk_inserted = 1; - disk_offset = 0; - } - } - else{ - disk_inserted = 0; - } - */ + mem_ctrl_instance->set_data(0xFFC00000, machine_sysrom_mem, rom_filesize); + romFile.close(); clock_test_begin = clock(); @@ -641,29 +585,6 @@ int main(int argc, char **argv) } else if ((checker=="1")|(checker=="realtime")|(checker=="/realtime")|(checker=="-realtime")){ execute_interpreter(); - /* - if (disk_inserted){ - if (disk_word == 32768){ - if (disk_offset < disk_file_setsize){ - disk_offset += 32768; - diskFile.seekg(disk_offset, romFile.beg); - char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000)); - diskFile.read (ptr,(sizeof(uint8_t)*0x8000)); - disk_word = 0; - } - else{ - disk_offset = 0; - diskFile.seekg(0, romFile.beg); - char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000)); - diskFile.read (ptr,(sizeof(uint8_t)*0x8000)); - disk_word = 0; - } - } - else{ - disk_word += 4; - } - } - */ } else if ((checker=="e")|(checker=="loadelf")|(checker=="/loadelf")|(checker=="-loadelf")){ ifstream elfFile; @@ -864,7 +785,7 @@ int main(int argc, char **argv) std::cout << "playground - Mess around with and opcodes. " << endl; } - romFile.close(); + delete(mem_ctrl_instance); //Free memory after the emulation is completed. free(machine_sysram_mem); diff --git a/ppcemumain.h b/ppcemumain.h index be374e6..23fc13c 100644 --- a/ppcemumain.h +++ b/ppcemumain.h @@ -10,6 +10,8 @@ #include +#include "devices/memctrlbase.h" + //Uncomment this to help debug the emulator further //#define EXHAUSTIVE_DEBUG 1 @@ -96,7 +98,7 @@ extern uint32_t ram_size_set; extern uint32_t rom_file_begin; //where to start storing ROM files in memory extern uint32_t pci_io_end; -extern uint32_t rom_file_setsize; +extern uint32_t rom_filesize; //Additional steps to prevent overflow? extern int32_t add_result; @@ -220,6 +222,8 @@ void ppc_tbr_update(); void ppc_exception_handler(uint32_t exception_type, uint32_t handle_args); //MEMORY DECLARATIONS +extern MemCtrlBase *mem_ctrl_instance; + extern unsigned char * machine_sysram_mem; extern unsigned char * machine_sysconfig_mem; //Mapped to 0x68000000 - extern unsigned char * machine_68kemu_mem; diff --git a/ppcmemory.cpp b/ppcmemory.cpp index ce55785..add6376 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -20,6 +20,8 @@ #include "ppcemumain.h" #include "ppcmemory.h" #include "openpic.h" +#include "devices/memctrlbase.h" +#include "devices/mmiodevice.h" #include "devices/mpc106.h" #include "davbus.h" @@ -94,76 +96,70 @@ void msr_status_update(){ msr_dr_test = (ppc_state.ppc_msr >> 4) & 1; } -inline void ppc_set_cur_instruction(uint32_t mem_index) +static inline void ppc_set_cur_instruction(unsigned char *ptr, uint32_t offset) { - ppc_cur_instruction = (grab_macmem_ptr[mem_index] << 24) | - (grab_macmem_ptr[mem_index+1] << 16) | - (grab_macmem_ptr[mem_index+2] << 8) | - grab_macmem_ptr[mem_index+3]; + ppc_cur_instruction = (ptr[offset] << 24) | (ptr[offset+1] << 16) | + (ptr[offset+2] << 8) | ptr[offset+3]; } -void ppc_set_return_val(uint32_t mem_index, int num_size) +static inline void ppc_set_return_val(unsigned char *ptr, uint32_t offset, + int num_size) { //Put the final result in return_value here //This is what gets put back into the register if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */ if (num_size == 1) { // BYTE - return_value = grab_macmem_ptr[mem_index]; + return_value = ptr[offset]; } else if (num_size == 2) { // WORD - return_value = grab_macmem_ptr[mem_index] | - (grab_macmem_ptr[mem_index+1] << 8); + return_value = ptr[offset] | (ptr[offset+1] << 8); } else if (num_size == 4) { // DWORD - return_value = grab_macmem_ptr[mem_index] | - (grab_macmem_ptr[mem_index+1] << 8) | - (grab_macmem_ptr[mem_index+2] << 16) | - (grab_macmem_ptr[mem_index+3] << 24); + return_value = ptr[offset] | (ptr[offset+1] << 8) | + (ptr[offset+2] << 16) | (ptr[offset+3] << 24); } } else { /* big-endian byte ordering */ if (num_size == 1) { // BYTE - return_value = grab_macmem_ptr[mem_index]; + return_value = ptr[offset]; } else if (num_size == 2) { // WORD - return_value = (grab_macmem_ptr[mem_index] << 8) | - grab_macmem_ptr[mem_index+1]; + return_value = (ptr[offset] << 8) | ptr[offset+1]; } else if (num_size == 4) { // DWORD - return_value = (grab_macmem_ptr[mem_index] << 24) | - (grab_macmem_ptr[mem_index+1] << 16) | - (grab_macmem_ptr[mem_index+2] << 8) | - grab_macmem_ptr[mem_index+3]; + return_value = (ptr[offset] << 24) | (ptr[offset+1] << 16) | + (ptr[offset+2] << 8) | ptr[offset+3]; } } } -void ppc_memstore_value(uint32_t value_insert, uint32_t mem_index, int num_size) +static inline void ppc_memstore_value(unsigned char *ptr, uint32_t value, + uint32_t offset, int num_size) { if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */ if (num_size >= 1) { // BYTE - grab_macmem_ptr[mem_index] = value_insert & 0xFF; + ptr[offset] = value & 0xFF; } if (num_size >= 2) { // WORD - grab_macmem_ptr[mem_index+1] = (value_insert >> 8) & 0xFF; + ptr[offset+1] = (value >> 8) & 0xFF; } if (num_size == 4) { // DWORD - grab_macmem_ptr[mem_index+2] = (value_insert >> 16) & 0xFF; - grab_macmem_ptr[mem_index+3] = (value_insert >> 24) & 0xFF; + ptr[offset+2] = (value >> 16) & 0xFF; + ptr[offset+3] = (value >> 24) & 0xFF; } } else { /* big-endian byte ordering */ if (num_size == 1) { // BYTE - grab_macmem_ptr[mem_index] = value_insert & 0xFF; + ptr[offset] = value & 0xFF; } else if (num_size == 2) { // WORD - grab_macmem_ptr[mem_index] = (value_insert >> 8) & 0xFF; - grab_macmem_ptr[mem_index+1] = value_insert & 0xFF; + ptr[offset] = (value >> 8) & 0xFF; + ptr[offset+1] = value & 0xFF; } else if (num_size == 4) { // DWORD - grab_macmem_ptr[mem_index] = (value_insert >> 24) & 0xFF; - grab_macmem_ptr[mem_index+1] = (value_insert >> 16) & 0xFF; - grab_macmem_ptr[mem_index+2] = (value_insert >> 8) & 0xFF; - grab_macmem_ptr[mem_index+3] = value_insert & 0xFF; + ptr[offset] = (value >> 24) & 0xFF; + ptr[offset+1] = (value >> 16) & 0xFF; + ptr[offset+2] = (value >> 8) & 0xFF; + ptr[offset+3] = value & 0xFF; } } } @@ -282,7 +278,7 @@ void get_pointer_pteg1(uint32_t address_grab){ } } else{ - pte_word1 = address_grab % rom_file_setsize; + pte_word1 = address_grab % rom_filesize; grab_pteg1_ptr = machine_sysrom_mem; } } @@ -359,7 +355,7 @@ void get_pointer_pteg2(uint32_t address_grab){ } } else{ - pte_word2 = address_grab % rom_file_setsize; + pte_word2 = address_grab % rom_filesize; grab_pteg2_ptr = machine_sysrom_mem; } } @@ -561,465 +557,101 @@ uint32_t ppc_mmu_addr_translate(uint32_t la, uint32_t access_type) } -/** Insert a value into memory from a register. */ -void address_quickinsert_translate(uint32_t value_insert, uint32_t address_grab, - uint8_t num_bytes) +uint32_t write_last_pa_start = 0; +uint32_t write_last_pa_end = 0; +unsigned char *write_last_ptr = 0; + +void address_quickinsert_translate(uint32_t value, uint32_t addr, uint8_t num_bytes) { - uint32_t storage_area = 0; - - printf("Inserting into address %x with %x \n", address_grab, value_insert); - - // data address translation if enabled - if (ppc_state.ppc_msr & 0x10) { - printf("DATA RELOCATION GO! - INSERTING \n"); - - address_grab = ppc_mmu_addr_translate(address_grab, 0); - } - - //regular grabbing - if (address_grab < 0x80000000){ - if (mpc106_check_membound(address_grab)){ - if (address_grab > 0x03ffffff){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - if (is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_memstore_value(value_insert, storage_area, num_bytes); - return; - } - else{ - return; - } - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - storage_area = address_grab % 0x04000000; - grab_macmem_ptr = machine_sysram_mem; - printf("Uncharted territory: %x \n", address_grab); - } - } - else{ - return; - } - } - else if (address_grab < 0x80800000){ - storage_area = address_grab % 0x800000; - if (address_grab == 0x80000CF8){ - storage_area = 0x0CF8; //CONFIG_ADDR - value_insert = rev_endian32(value_insert); - grab_macmem_ptr = machine_fecxxx_mem; - uint32_t reg_num = (value_insert & 0x07FC) >> 2; - uint32_t dev_num = (value_insert & 0xF800) >> 11; - printf("ADDRESS SET FOR GRACKLE: "); - printf("Device Number: %d ", dev_num); - printf("Hex Register Number: %x \n", reg_num); - mpc106_address = value_insert; - } - else{ - grab_macmem_ptr = machine_upperiocontrol_mem; - } - - - if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){ - openpic_address = address_grab - 0x80000000; - openpic_read_word = value_insert; - openpic_read(); - return; - } - - printf("Uncharted territory: %x \n", address_grab); - } - else if (address_grab < 0x81000000){ - if (address_grab > 0x83FFFFFF){ - return; - } - storage_area = address_grab; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_iocontrolcdma_mem; - } - else if (address_grab < 0xBF800000){ - storage_area = address_grab % 33554432; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_loweriocontrol_mem; - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_interruptack_mem; - } - else if (address_grab < 0xF0000000){ - printf("Invalid Memory Attempt: %x \n", address_grab); - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){ - mac_serial_address = storage_area; - serial_write_byte = (uint8_t)value_insert; - printf("Writing byte to Serial address %x ... %x \n", address_grab, via_write_byte); - mac_serial_write(); - return; - } - else if ((address_grab >= 0xF3014000) && (address_grab < 0xF3015000)){ - davbus_address = storage_area; - davbus_write_word = value_insert; - printf("\nWriting to DAVBus: %x \n", return_value); - davbus_write(); - return; - } - else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){ - mac_swim3_address = storage_area; - swim3_write_byte = (uint8_t)value_insert; - printf("Writing byte to SWIM3 address %x ... %x \n", address_grab, swim3_write_byte); - mac_swim3_write(); - return; - } - else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){ - via_cuda_address = storage_area; - via_write_byte = (uint8_t)value_insert; - printf("Writing byte to CUDA address %x ... %x \n", address_grab, via_write_byte); - via_cuda_write(); - return; - } - else if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){ - openpic_address = storage_area - 0x3000000; - openpic_write_word = value_insert; - printf("Writing byte to OpenPIC address %x ... %x \n", address_grab, openpic_write_word); - openpic_write(); - return; - } - else if (address_grab > 0xF3FFFFFF){ - printf("Uncharted territory: %x", address_grab); - return; - } - grab_macmem_ptr = machine_iocontrolmem_mem; - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - mpc106_address = address_grab % 65536; - mpc106_write(value_insert); - return; - } - else if (address_grab < 0xFEE00000){ - storage_area = 0x0CF8; //CONFIG_ADDR - grab_macmem_ptr = machine_fecxxx_mem; - value_insert = rev_endian32(value_insert); - uint32_t reg_num = (value_insert & 0x07FC) >> 2; - uint32_t dev_num = (value_insert & 0xF800) >> 11; - printf("ADDRESS SET FOR GRACKLE \n"); - printf("Device Number: %d ", dev_num); - printf("Hex Register Number: %x \n", reg_num); - mpc_config_addr = value_insert; - } - else if (address_grab < 0xFF000000){ - storage_area = 0x0CFC; //CONFIG_DATA - mpc106_word_custom_size = num_bytes; - mpc106_write_device(mpc_config_addr, value_insert, num_bytes); - grab_macmem_ptr = machine_feexxx_mem; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - else{ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - } - - ppc_memstore_value(value_insert, storage_area, num_bytes); -} - -/** Grab a value from memory into a register */ -void address_quickgrab_translate(uint32_t address_grab, uint8_t num_bytes) -{ - uint32_t storage_area = 0; - - //printf("Grabbing from address %x \n", address_grab); - - return_value = 0; //reset this before going into the real fun. - /* data address translation if enabled */ if (ppc_state.ppc_msr & 0x10) { - printf("DATA RELOCATION GO! - GRABBING \n"); - - address_grab = ppc_mmu_addr_translate(address_grab, 0); + addr = ppc_mmu_addr_translate(addr, 0); } - if (address_grab >= 0xFFC00000){ - //printf("Charting ROM Area: %x \n", address_grab); - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_return_val(storage_area, num_bytes); - return; - } - - //regular grabbing - else if (address_grab < 0x80000000){ - if ((address_grab >= 0x40000000) && (address_grab < 0x40400000) && is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_return_val(storage_area, num_bytes); - return; - } - - if (mpc106_check_membound(address_grab)){ - if (address_grab > 0x03ffffff){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; + if (addr >= write_last_pa_start && addr <= write_last_pa_end) { + ppc_memstore_value(write_last_ptr, value, addr - write_last_pa_start, num_bytes); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry) { + if (entry->type & RT_RAM) { + write_last_pa_start = entry->start; + write_last_pa_end = entry->end; + write_last_ptr = entry->mem_ptr; + ppc_memstore_value(write_last_ptr, value, addr - entry->start, num_bytes); + } else if (entry->type & RT_MMIO) { + entry->devobj->write(addr - entry->start, value, num_bytes); + } else { + printf("Please check your address map!\n"); } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - } - else{ - //The address is not within the ROM banks - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; + } else { + printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr); } } - else if (address_grab < 0x80800000){ - if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){ - openpic_address = address_grab - 0x80000000; - openpic_write(); - return_value = openpic_write_word; - return; - } - - storage_area = address_grab % 0x800000; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_upperiocontrol_mem; - } - else if (address_grab < 0x81000000){ - storage_area = address_grab; - if (address_grab > 0x83FFFFFF){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_iocontrolcdma_mem; - } - else if (address_grab < 0xBF800000){ - storage_area = address_grab % 33554432; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_loweriocontrol_mem; - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_interruptack_mem; - } - else if (address_grab < 0xF0000000){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){ - mac_serial_address = storage_area; - mac_serial_read(); - return_value = serial_read_byte; - printf("\n Read from Serial: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3014000) && (address_grab < 0xF3015000)){ - davbus_address = storage_area; - davbus_read(); - return_value = davbus_read_word; - printf("\n Read from DAVBus: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){ - mac_swim3_address = storage_area; - mac_swim3_read(); - return_value = swim3_read_byte; - printf("\n Read from Swim3: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){ - via_cuda_address = storage_area; - via_cuda_read(); - return_value = via_read_byte; - printf("\n Read from CUDA: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){ - openpic_address = storage_area - 0x3000000; - openpic_read(); - return_value = openpic_write_word; - return; - } - else if (address_grab > 0xF3FFFFFF){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - grab_macmem_ptr = machine_iocontrolmem_mem; - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - mpc106_address = address_grab % 65536; - mpc106_read(); - return_value = mpc106_read_word; - return; - } - else if (address_grab < 0xFEE00000){ - return_value = (num_bytes == 1)? (mpc106_address & 0xFF):(num_bytes == 2)?(mpc106_address & 0xFFFF):mpc106_address; - return; - } - else if (address_grab < 0xFF000000){ - mpc106_word_custom_size = num_bytes; - return_value = mpc106_read_device(mpc_config_addr, num_bytes); - return_value = rev_endian32(return_value); - return; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - - ppc_set_return_val(storage_area, num_bytes); - } -void quickinstruction_translate(uint32_t address_grab) + +uint32_t read_last_pa_start = 0; +uint32_t read_last_pa_end = 0; +unsigned char *read_last_ptr = 0; + +/** Grab a value from memory into a register */ +void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes) { - uint32_t storage_area = 0; + /* data address translation if enabled */ + if (ppc_state.ppc_msr & 0x10) { + //printf("DATA RELOCATION GO! - GRABBING \n"); - return_value = 0; //reset this before going into the real fun. + addr = ppc_mmu_addr_translate(addr, 0); + } + if (addr >= read_last_pa_start && addr <= read_last_pa_end) { + ppc_set_return_val(read_last_ptr, addr - read_last_pa_start, num_bytes); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry) { + if (entry->type & (RT_ROM | RT_RAM)) { + read_last_pa_start = entry->start; + read_last_pa_end = entry->end; + read_last_ptr = entry->mem_ptr; + ppc_set_return_val(read_last_ptr, addr - entry->start, num_bytes); + } else if (entry->type & RT_MMIO) { + return_value = entry->devobj->read(addr - entry->start, num_bytes); + } else { + printf("Please check your address map!\n"); + } + } else { + printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr); + + /* reading from unmapped memory will return unmapped value */ + for (return_value = 0xFF; --num_bytes > 0;) + return_value = (return_value << 8) | 0xFF; + } + } +} + + +uint32_t exec_last_pa_start = 0; +uint32_t exec_last_pa_end = 0; +unsigned char *exec_last_ptr = 0; + +void quickinstruction_translate(uint32_t addr) +{ /* instruction address translation if enabled */ if (ppc_state.ppc_msr & 0x20) { - printf("INSTRUCTION RELOCATION GO! \n"); - - address_grab = ppc_mmu_instr_translate(address_grab); + addr = ppc_mmu_instr_translate(addr); } - //grab opcode from memory area - if (address_grab >= 0xFFC00000){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_cur_instruction(storage_area); - return; - } - else if (address_grab < 0x80000000){ - if (address_grab < 0x040000000){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - if (is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_cur_instruction(storage_area); - return; - } - else{ - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - storage_area = address_grab % 0x04000000; - grab_macmem_ptr = machine_sysram_mem; - printf("Uncharted territory: %x \n", address_grab); + if (addr >= exec_last_pa_start && addr <= exec_last_pa_end) { + ppc_set_cur_instruction(exec_last_ptr, addr - exec_last_pa_start); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry && entry->type & (RT_ROM | RT_RAM)) { + exec_last_pa_start = entry->start; + exec_last_pa_end = entry->end; + exec_last_ptr = entry->mem_ptr; + ppc_set_cur_instruction(exec_last_ptr, addr - exec_last_pa_start); + } else { + printf("WARNING: attempt to execute code at %08X!\n", addr); } } - else if (address_grab < 0x80800000){ - storage_area = address_grab % 0x800000; - grab_macmem_ptr = machine_upperiocontrol_mem; - - } - else if (address_grab < 0x81000000){ - storage_area = address_grab % 0x800000; - grab_macmem_ptr = machine_iocontrolcdma_mem; - - } - else if (address_grab < 0xBF80000){ - storage_area = address_grab % 33554432; - grab_macmem_ptr = machine_loweriocontrol_mem; - - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - grab_macmem_ptr = machine_interruptack_mem; - - } - else if (address_grab < 0xF0000000){ - printf("Invalid Memory Attempt: %x \n", address_grab); - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - grab_macmem_ptr = machine_iocontrolmem_mem; - - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - storage_area = address_grab % 65536; - grab_macmem_ptr = machine_fexxxx_mem; - } - else if (address_grab < 0xFEE00000){ - storage_area = 0x0CF8; //CONFIG_ADDR - grab_macmem_ptr = machine_fecxxx_mem; - } - else if (address_grab < 0xFF000000){ - storage_area = 0x0CFC; //CONFIG_DATA - grab_macmem_ptr = machine_feexxx_mem; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - - ppc_set_cur_instruction(storage_area); } From 78e8b06cf125bfbcab1a3b8c35ab7177d9c4c399 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 23 Aug 2019 23:30:33 +0200 Subject: [PATCH 03/13] Add interfaces for PCI host and PCI device. --- devices/pcidevice.h | 34 ++++++++++++++++++++++++++++++++++ devices/pcihost.h | 15 +++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 devices/pcidevice.h create mode 100644 devices/pcihost.h diff --git a/devices/pcidevice.h b/devices/pcidevice.h new file mode 100644 index 0000000..e1985a6 --- /dev/null +++ b/devices/pcidevice.h @@ -0,0 +1,34 @@ +#ifndef PCI_DEVICE_H +#define PCI_DEVICE_H + +#include +#include +#include "mmiodevice.h" +#include "pcihost.h" + +/* convert little-endian DWORD to big-endian DWORD */ +#define LE2BE(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24) + +enum { + CFG_REG_BAR0 = 0x10 // base address register 0 +}; + + +class PCIDevice : public MMIODevice { +public: + PCIDevice(std::string name) {this->name = name;}; + virtual ~PCIDevice() = default; + + /* configuration space access methods */ + virtual uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size) = 0; + virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) = 0; + + virtual void set_host(PCIHost *host_instance) = 0; + +protected: + std::string name; // human-readable device name + PCIHost *host_instance; // host bridge instance to call back + uint32_t base_addr; // base address register 0 +}; + +#endif /* PCI_DEVICE_H */ diff --git a/devices/pcihost.h b/devices/pcihost.h new file mode 100644 index 0000000..acd3d1f --- /dev/null +++ b/devices/pcihost.h @@ -0,0 +1,15 @@ +#ifndef PCI_HOST_H +#define PCI_HOST_H + +#include + +class PCIDevice; // forward declaration to prevent errors + +class PCIHost { +public: + virtual bool pci_register_device(int dev_num, PCIDevice *dev_instance) = 0; + virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, + PCIDevice *obj) = 0; +}; + +#endif /* PCI_HOST_H */ From af5a096532ad8d7ca051cfa4d7958afbceb2116b Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 23 Aug 2019 21:30:30 +0200 Subject: [PATCH 04/13] MPC106: add support for PCI devices. --- devices/mpc106.cpp | 92 +++++++++++++++++++++++++++++----------------- devices/mpc106.h | 28 ++++++++++---- 2 files changed, 80 insertions(+), 40 deletions(-) diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp index 3607199..7c90630 100644 --- a/devices/mpc106.cpp +++ b/devices/mpc106.cpp @@ -16,20 +16,20 @@ #include "memctrlbase.h" #include "mmiodevice.h" -#include "../viacuda.h" #include "mpc106.h" -#include "../ppcemumain.h" -#include "../ppcmemory.h" -MPC106::MPC106() : MemCtrlBase("Grackle") +MPC106::MPC106() : MemCtrlBase("Grackle"), PCIDevice("Grackle PCI host bridge") { /* add memory mapped I/O region for MPC106 registers */ add_mmio_region(0xFEC00000, 0x300000, this); + + this->pci_0_bus.clear(); } MPC106::~MPC106() { + this->pci_0_bus.clear(); } uint32_t MPC106::read(uint32_t offset, int size) @@ -56,7 +56,7 @@ void MPC106::write(uint32_t offset, uint32_t value, int size) uint32_t MPC106::pci_read(uint32_t size) { - int bus_num, dev_num, fun_num, reg_num; + int bus_num, dev_num, fun_num, reg_offs; bus_num = (this->config_addr >> 8) & 0xFF; if (bus_num) { @@ -65,16 +65,20 @@ uint32_t MPC106::pci_read(uint32_t size) return 0; } - dev_num = (this->config_addr >> 19) & 0x1F; - fun_num = (this->config_addr >> 16) & 0x07; - reg_num = (this->config_addr >> 24) & 0xFC; + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_offs = (this->config_addr >> 24) & 0xFC; if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself - return myself_read(reg_num, size); + return this->pci_cfg_read(reg_offs, size); } else { - std::cout << this->name << " err: reading from device " << dev_num - << " not supported yet" << std::endl; - return 0; + if (this->pci_0_bus.count(dev_num)) { + return this->pci_0_bus[dev_num]->pci_cfg_read(reg_offs, size); + } else { + std::cout << this->name << " err: read attempt from non-existing PCI device " + << dev_num << std::endl; + return 0; + } } return 0; @@ -82,7 +86,7 @@ uint32_t MPC106::pci_read(uint32_t size) void MPC106::pci_write(uint32_t value, uint32_t size) { - int bus_num, dev_num, fun_num, reg_num; + int bus_num, dev_num, fun_num, reg_offs; bus_num = (this->config_addr >> 8) & 0xFF; if (bus_num) { @@ -91,33 +95,37 @@ void MPC106::pci_write(uint32_t value, uint32_t size) return; } - dev_num = (this->config_addr >> 19) & 0x1F; - fun_num = (this->config_addr >> 16) & 0x07; - reg_num = (this->config_addr >> 24) & 0xFC; + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_offs = (this->config_addr >> 24) & 0xFC; if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself - myself_write(reg_num, value, size); + this->pci_cfg_write(reg_offs, value, size); } else { - std::cout << this->name << " err: writing to device " << dev_num - << " not supported yet" << std::endl; + if (this->pci_0_bus.count(dev_num)) { + this->pci_0_bus[dev_num]->pci_cfg_write(reg_offs, value, size); + } else { + std::cout << this->name << " err: write attempt to non-existing PCI device " + << dev_num << std::endl; + } } } -uint32_t MPC106::myself_read(int reg_num, uint32_t size) +uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size) { #ifdef MPC106_DEBUG - printf("read from Grackle register %08X\n", reg_num); + printf("read from Grackle register %08X\n", reg_offs); #endif switch(size) { case 1: - return this->my_pci_cfg_hdr[reg_num]; + return this->my_pci_cfg_hdr[reg_offs]; break; case 2: - return READ_WORD_BE(&this->my_pci_cfg_hdr[reg_num]); + return READ_WORD_BE(&this->my_pci_cfg_hdr[reg_offs]); break; case 4: - return READ_DWORD_BE(&this->my_pci_cfg_hdr[reg_num]); + return READ_DWORD_BE(&this->my_pci_cfg_hdr[reg_offs]); break; default: std::cout << "MPC106 read error: invalid size parameter " << size @@ -127,29 +135,47 @@ uint32_t MPC106::myself_read(int reg_num, uint32_t size) return 0; } -void MPC106::myself_write(int reg_num, uint32_t value, uint32_t size) +void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) { #ifdef MPC106_DEBUG - printf("write %08X to Grackle register %08X\n", value, reg_num); + printf("write %08X to Grackle register %08X\n", value, reg_offs); #endif // FIXME: implement write-protection for read-only registers switch(size) { case 1: - this->my_pci_cfg_hdr[reg_num] = value & 0xFF; + this->my_pci_cfg_hdr[reg_offs] = value & 0xFF; break; case 2: - this->my_pci_cfg_hdr[reg_num] = (value >> 8) & 0xFF; - this->my_pci_cfg_hdr[reg_num+1] = value & 0xFF; + this->my_pci_cfg_hdr[reg_offs] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_offs+1] = value & 0xFF; break; case 4: - this->my_pci_cfg_hdr[reg_num] = (value >> 24) & 0xFF; - this->my_pci_cfg_hdr[reg_num+1] = (value >> 16) & 0xFF; - this->my_pci_cfg_hdr[reg_num+2] = (value >> 8) & 0xFF; - this->my_pci_cfg_hdr[reg_num+3] = value & 0xFF; + this->my_pci_cfg_hdr[reg_offs] = (value >> 24) & 0xFF; + this->my_pci_cfg_hdr[reg_offs+1] = (value >> 16) & 0xFF; + this->my_pci_cfg_hdr[reg_offs+2] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_offs+3] = value & 0xFF; break; default: std::cout << "MPC106 read error: invalid size parameter " << size << std::endl; } } + +bool MPC106::pci_register_device(int dev_num, PCIDevice *dev_instance) +{ + if (this->pci_0_bus.count(dev_num)) // is dev_num already registered? + return false; + + this->pci_0_bus[dev_num] = dev_instance; + + dev_instance->set_host(this); + + return true; +} + +bool MPC106::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj) +{ + // FIXME: add sanity checks! + return this->add_mmio_region(start_addr, size, obj); +} diff --git a/devices/mpc106.h b/devices/mpc106.h index 13f6b74..71898d0 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -9,7 +9,7 @@ Author: Max Poliakovski - Grackle IC is a combined memory and PCI controller manufactored by Motorola. + Grackle IC is a combined memory and PCI controller manufactured by Motorola. It's the central device in the Gossamer architecture. Manual: https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf @@ -23,11 +23,14 @@ #define MPC106_H_ #include +#include #include "memctrlbase.h" #include "mmiodevice.h" +#include "pcidevice.h" +#include "pcihost.h" -class MPC106 : public MemCtrlBase, public MMIODevice +class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost { public: using MemCtrlBase::name; @@ -37,14 +40,23 @@ public: uint32_t read(uint32_t offset, int size); void write(uint32_t offset, uint32_t value, int size); + /* PCI host bridge API */ + bool pci_register_device(int dev_num, PCIDevice *dev_instance); + protected: /* PCI access */ uint32_t pci_read(uint32_t size); void pci_write(uint32_t value, uint32_t size); - /* my own registers access */ - uint32_t myself_read(int reg_num, uint32_t size); - void myself_write(int reg_num, uint32_t value, uint32_t size); + /* my own PCI configuration registers access */ + uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size); + void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size); + + void set_host(PCIHost *host_instance) {}; // unimplemented for now + + /* PCI host bridge API */ + //bool pci_register_device(int dev_num, PCIDevice *dev_instance); + bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj); private: uint8_t my_pci_cfg_hdr[256] = { @@ -54,8 +66,8 @@ private: 0x80, 0x00, // PCI status 0x40, // revision ID: 4.0 0x00, // standard programming - 0x00, // subclass code - 0x06, // class code + 0x00, // subclass code: host bridge + 0x06, // class code: bridge device [0x73] = 0xCD, // default value for ODCR [0xA8] = 0x10, 0x00, 0x00, 0xFF, // PICR1 [0xAC] = 0x0C, 0x06, 0x0C, 0x00, // PICR2 @@ -70,6 +82,8 @@ private: uint32_t config_addr; //uint32_t config_data; + + std::unordered_map pci_0_bus; }; #endif From 3131325bff12adc26250f8a3a2170b1706e49567 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 23 Aug 2019 23:34:19 +0200 Subject: [PATCH 05/13] Initial implementation for Heathrow/Mac-io. --- devices/heathrow.cpp | 44 ++++++++++++++++++++ devices/macio.h | 97 ++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 30 +++++++++----- 3 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 devices/heathrow.cpp create mode 100644 devices/macio.h diff --git a/devices/heathrow.cpp b/devices/heathrow.cpp new file mode 100644 index 0000000..71222d4 --- /dev/null +++ b/devices/heathrow.cpp @@ -0,0 +1,44 @@ +#include +#include +#include "macio.h" + +using namespace std; + +uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size) +{ + return this->pci_cfg_hdr[reg_offs & 0xFF]; +} + +void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) +{ + switch(reg_offs) { + case CFG_REG_BAR0: // base address register + value = LE2BE(value); + if (value == 0xFFFFFFFF) { + cout << this->name << " err: BAR0 block size determination not " + << "implemented yet" << endl; + } else if (value & 1) { + cout << this->name << " err: BAR0 I/O space not supported!" << endl; + } else if (value & 0x06) { + cout << this->name << " err: BAR0 64-bit I/O space not supported!" + << endl; + } else { + this->base_addr = value & 0xFFFFFFF0; + this->host_instance->pci_register_mmio_region(this->base_addr, 0x80000, this); + cout << this->name << " base address set to " << hex << this->base_addr + << endl; + } + break; + } +} + +uint32_t HeathrowIC::read(uint32_t offset, int size) +{ + cout << this->name << ": reading from offset " << hex << offset << endl; + return 0; +} + +void HeathrowIC::write(uint32_t offset, uint32_t value, int size) +{ + cout << this->name << ": writing to offset " << hex << offset << endl; +} diff --git a/devices/macio.h b/devices/macio.h new file mode 100644 index 0000000..8c71cc4 --- /dev/null +++ b/devices/macio.h @@ -0,0 +1,97 @@ +/** MacIO device family emulation + + Mac I/O (MIO) is a family of ASICs to bring support for Apple legacy + I/O hardware to PCI-based Power Macintosh. That legacy hardware has + existed long before Power Macintosh was introduced. It includes: + - versatile interface adapter (VIA) + - Sander-Woz integrated machine (SWIM) that is a floppy disk controller + - CUDA MCU for ADB, parameter RAM, realtime clock and power management support + - serial communication controller (SCC) + - Macintosh Enhanced SCSI Hardware (MESH) + + In the 68k Macintosh era, all this hardware was implemented using several + custom chips. In PCI-compatible Power Macintosh, the above devices are part + of the MIO chip itself. MIO's functional blocks implementing virtual devices + are called "cells", i.e. "VIA cell", "SWIM cell" etc. + + MIO itself is PCI compliant while the legacy hardware it emulates isn't. + MIO occupies 512Kb of PCI memory space divided into registers space and DMA + space. Access to emulated legacy devices is accomplished by reading from/ + writing to MIO's PCI address space at predefined offsets. + + MIO includes a DMA controller that offers 15 DMA channels implementing + Apple's own DMA protocol called descriptor-based DMA (DBDMA). + + Official documentation (that is somewhat incomplete and erroneous) can be + found in the second chapter of the book "Macintosh Technology in the Common + Hardware Reference Platform" by Apple Computer, Inc. +*/ + +#ifndef MACIO_H +#define MACIO_H + +#include +#include "pcidevice.h" +#include "memctrlbase.h" +#include "mmiodevice.h" +#include "pcihost.h" + +/** + Heathrow ASIC emulation + + Author: Max Poliakovski + + Heathrow is a MIO-compliant ASIC used in the Gossamer architecture. It's + hard-wired to PCI device number 16. Its I/O memory (512Kb) will be configured + by the Macintosh firmware to live at 0xF3000000. + + Emulated subdevices and their offsets within Heathrow I/O space: + ---------------------------------------------------------------- + mesh(SCSI) register space: 0x00010000, DMA space: 0x00008000 + bmac(ethernet) register space: 0x00011000, DMA space: 0x00008200, 0x00008300 + escc(serial) register space: 0x00013000, size: 0x00001000 + DMA space: 0x00008400, size: 0x00000400 + escc:ch-a register space: 0x00013020, DMA space: 0x00008400, 0x00008500 + escc:ch-b register space: 0x00013000, DMA space: 0x00008600, 0x00008700 + davbus(sound) register space: 0x00014000, DMA space: 0x00008800, 0x00008900 + SWIM3(floppy) register space: 0x00015000, DMA space: 0x00008100 + NVRAM register space: 0x00060000, size: 0x00020000 + IDE register space: 0x00020000, DMA space: 0x00008b00 + VIA-CUDA register space: 0x00016000, size: 0x00002000 +*/ + +class HeathrowIC : public PCIDevice +{ +public: + using PCIDevice::name; + + HeathrowIC() : PCIDevice("mac-io/heathrow") {}; + ~HeathrowIC() = default; + + void set_host(PCIHost *host_instance) {this->host_instance = host_instance;}; + + /* PCI device methods */ + uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size); + void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size); + + /* MMIO device methods */ + uint32_t read(uint32_t offset, int size); + void write(uint32_t offset, uint32_t value, int size); + +private: + uint8_t pci_cfg_hdr[256] = { + 0x6B, 0x10, // vendor ID: Apple Computer Inc. + 0x10, 0x00, // device ID: Heathrow Mac I/O + 0x00, 0x00, // PCI command (set to 0 at power-up?) + 0x00, 0x00, // PCI status (set to 0 at power-up?) + 0x01, // revision ID + // class code is reported in OF property "class-code" as 0xff0000 + 0x00, // standard programming + 0x00, // subclass code + 0xFF, // class code: unassigned + 0x00, 0x00, // unknown defaults + 0x00, 0x00 // unknown defaults + }; +}; + +#endif /* MACIO_H */ diff --git a/main.cpp b/main.cpp index 99eb81d..16e4860 100644 --- a/main.cpp +++ b/main.cpp @@ -26,7 +26,8 @@ #include "devices/mpc106.h" #include "openpic.h" #include "debugger.h" -//#include +#include "devices/macio.h" +#include "devices/mpc106.h" #define max_16b_int 65535 #define max_32b_int 4294967295 @@ -83,6 +84,7 @@ uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA uint32_t return_value; MemCtrlBase *mem_ctrl_instance = 0; +HeathrowIC *heathrow = 0; //A pointer to a pointer, used for quick movement to one of the following //memory areas. These are listed right below. @@ -546,17 +548,22 @@ int main(int argc, char **argv) } switch(rom_id) { - case 0x476F7373: - cout << "Initialize Gossamer hardware..."; - mem_ctrl_instance = new MPC106(); - if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000) || - !mem_ctrl_instance->add_ram_region(0x00000000, 0x800000)) { - cout << "failure!\n" << endl; - delete(mem_ctrl_instance); - romFile.close(); - return 1; + case 0x476F7373: { + cout << "Initialize Gossamer hardware..."; + MPC106 *mpc106 = new MPC106(); + mem_ctrl_instance = mpc106; + if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000) || + !mem_ctrl_instance->add_ram_region(0x00000000, 0x800000)) { + cout << "failure!\n" << endl; + delete(mem_ctrl_instance); + romFile.close(); + return 1; + } + heathrow = new HeathrowIC(); + assert(heathrow != 0); + mpc106->pci_register_device(16, heathrow); + cout << "done" << endl; } - cout << "done" << endl; break; default: cout << "This machine not supported yet." << endl; @@ -785,6 +792,7 @@ int main(int argc, char **argv) std::cout << "playground - Mess around with and opcodes. " << endl; } + delete(heathrow); delete(mem_ctrl_instance); //Free memory after the emulation is completed. From 5fc7ca761e19870ed1912847d17a3e598eb183bc Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Tue, 27 Aug 2019 14:14:12 +0200 Subject: [PATCH 06/13] Initial implementation for VIA-CUDA device. --- devices/heathrow.cpp | 107 +++++++++++++++++++++++++++++- devices/macio.h | 16 ++++- devices/viacuda.cpp | 89 +++++++++++++++++++++++++ devices/viacuda.h | 46 +++++++++++++ main.cpp | 1 - ppcmemory.cpp | 1 - ppcopcodes.cpp | 8 +-- viacuda.cpp | 153 ------------------------------------------- viacuda.h | 48 -------------- 9 files changed, 258 insertions(+), 211 deletions(-) create mode 100644 devices/viacuda.cpp create mode 100644 devices/viacuda.h delete mode 100644 viacuda.cpp delete mode 100644 viacuda.h diff --git a/devices/heathrow.cpp b/devices/heathrow.cpp index 71222d4..429589b 100644 --- a/devices/heathrow.cpp +++ b/devices/heathrow.cpp @@ -1,9 +1,23 @@ #include #include #include "macio.h" +#include "viacuda.h" using namespace std; +HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow") +{ + this->viacuda = new ViaCuda(); + assert(this->viacuda); // FIXME: do proper exception handling! +} + +HeathrowIC::~HeathrowIC() +{ + if (this->viacuda) + delete(this->viacuda); +} + + uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size) { return this->pci_cfg_hdr[reg_offs & 0xFF]; @@ -23,7 +37,7 @@ void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) cout << this->name << " err: BAR0 64-bit I/O space not supported!" << endl; } else { - this->base_addr = value & 0xFFFFFFF0; + this->base_addr = value & 0xFFF80000; this->host_instance->pci_register_mmio_region(this->base_addr, 0x80000, this); cout << this->name << " base address set to " << hex << this->base_addr << endl; @@ -34,11 +48,100 @@ void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) uint32_t HeathrowIC::read(uint32_t offset, int size) { + uint32_t res = 0; + cout << this->name << ": reading from offset " << hex << offset << endl; - return 0; + + unsigned sub_dev = (offset >> 12) & 0x3F; + + switch(sub_dev) { + case 0: + res = mio_ctrl_read(offset, size); + break; + case 8: + cout << "DMA channel register space" << endl; + break; + case 0x14: + cout << "AWACS-Screamer register space" << endl; + break; + case 0x16: + case 0x17: + res = this->viacuda->read((offset - 0x16000) >> 9); + break; + default: + cout << "unmapped I/O space" << endl; + } + + return res; } void HeathrowIC::write(uint32_t offset, uint32_t value, int size) { cout << this->name << ": writing to offset " << hex << offset << endl; + + unsigned sub_dev = (offset >> 12) & 0x3F; + + switch(sub_dev) { + case 0: + mio_ctrl_write(offset, value, size); + break; + case 8: + cout << "DMA channel register space" << endl; + break; + case 0x14: + cout << "AWACS-Screamer register space" << endl; + break; + case 0x16: + case 0x17: + this->viacuda->write((offset - 0x16000) >> 9, value); + break; + default: + cout << "unmapped I/O space" << endl; + } +} + +uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) +{ + uint32_t res = 0; + + switch(offset & 0xFF) { + case 0x24: + cout << "read from MIO:Int_Mask1 register" << endl; + res = this->int_mask1; + break; + case 0x28: + cout << "read from MIO:Int_Clear1 register" << endl; + res = this->int_clear1; + break; + case 0x38: + cout << "read from MIO:Feat_Ctrl register" << endl; + res = this->feat_ctrl; + break; + default: + cout << "unknown MIO register at " << hex << offset << endl; + break; + } + + return res; +} + +void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) +{ + switch(offset & 0xFF) { + case 0x24: + cout << "write " << hex << value << " to MIO:Int_Mask1 register" << endl; + this->int_mask1 = value; + break; + case 0x28: + cout << "write " << hex << value << " to MIO:Int_Clear1 register" << endl; + this->int_clear1 = value; + break; + case 0x38: + cout << "write " << hex << value << " to MIO:Feat_Ctrl register" << endl; + this->feat_ctrl = value; + break; + default: + cout << "unknown MIO register at " << hex << offset << endl; + break; + } } diff --git a/devices/macio.h b/devices/macio.h index 8c71cc4..a34aeb3 100644 --- a/devices/macio.h +++ b/devices/macio.h @@ -35,6 +35,7 @@ #include "memctrlbase.h" #include "mmiodevice.h" #include "pcihost.h" +#include "viacuda.h" /** Heathrow ASIC emulation @@ -65,8 +66,8 @@ class HeathrowIC : public PCIDevice public: using PCIDevice::name; - HeathrowIC() : PCIDevice("mac-io/heathrow") {}; - ~HeathrowIC() = default; + HeathrowIC(); + ~HeathrowIC(); void set_host(PCIHost *host_instance) {this->host_instance = host_instance;}; @@ -78,6 +79,10 @@ public: uint32_t read(uint32_t offset, int size); void write(uint32_t offset, uint32_t value, int size); +protected: + uint32_t mio_ctrl_read(uint32_t offset, int size); + void mio_ctrl_write(uint32_t offset, uint32_t value, int size); + private: uint8_t pci_cfg_hdr[256] = { 0x6B, 0x10, // vendor ID: Apple Computer Inc. @@ -92,6 +97,13 @@ private: 0x00, 0x00, // unknown defaults 0x00, 0x00 // unknown defaults }; + + uint32_t int_mask1; + uint32_t int_clear1; + uint32_t feat_ctrl; // features control register + + /* device cells */ + ViaCuda *viacuda; /* VIA cell with Cuda MCU attached to it */ }; #endif /* MACIO_H */ diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp new file mode 100644 index 0000000..3fe1639 --- /dev/null +++ b/devices/viacuda.cpp @@ -0,0 +1,89 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +//Functionality for the VIA CUDA + +#include +#include +#include +#include "viacuda.h" + +using namespace std; + + +ViaCuda::ViaCuda() +{ + this->via_regs[VIA_A] = 0x80; + this->via_regs[VIA_DIRB] = 0xFF; + this->via_regs[VIA_DIRA] = 0xFF; + this->via_regs[VIA_T1LL] = 0xFF; + this->via_regs[VIA_T1LH] = 0xFF; + this->via_regs[VIA_IER] = 0x7F; +} + +uint8_t ViaCuda::read(int reg) +{ + uint8_t res; + + cout << "Read VIA reg " << hex << (uint32_t)reg << endl; + + res = this->via_regs[reg & 0xF]; + + /* reading from some VIA registers triggers special actions */ + switch(reg & 0xF) { + case VIA_IER: + res |= 0x80; /* bit 7 always reads as "1" */ + } + + return res; +} + +void ViaCuda::write(int reg, uint8_t value) +{ + switch(reg & 0xF) { + case VIA_B: + cout << "VIA_B = " << hex << (uint32_t)value << endl; + break; + case VIA_A: + cout << "VIA_A = " << hex << (uint32_t)value << endl; + break; + case VIA_DIRB: + cout << "VIA_DIRB = " << hex << (uint32_t)value << endl; + break; + case VIA_DIRA: + cout << "VIA_DIRA = " << hex << (uint32_t)value << endl; + break; + case VIA_PCR: + cout << "VIA_PCR = " << hex << (uint32_t)value << endl; + break; + case VIA_ACR: + cout << "VIA_ACR = " << hex << (uint32_t)value << endl; + break; + case VIA_IER: + this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F + : this->via_regs[VIA_IER] & ~value; + cout << "VIA_IER updated to " << hex << (uint32_t)this->via_regs[VIA_IER] + << endl; + print_enabled_ints(); + break; + case VIA_ANH: + cout << "VIA_ANH = " << hex << (uint32_t)value << endl; + break; + default: + this->via_regs[reg & 0xF] = value; + } +} + +void ViaCuda::print_enabled_ints() +{ + vector via_int_src = {"CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1"}; + + for (int i = 0; i < 7; i++) { + if (this->via_regs[VIA_IER] & (1 << i)) + cout << "VIA " << via_int_src[i] << " interrupt enabled." << endl; + } +} diff --git a/devices/viacuda.h b/devices/viacuda.h new file mode 100644 index 0000000..b47016b --- /dev/null +++ b/devices/viacuda.h @@ -0,0 +1,46 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +#ifndef VIACUDA_H +#define VIACUDA_H + +/** VIA register offsets. */ +enum { + VIA_B = 0x00, /* input/output register B */ + VIA_A = 0x01, /* input/output register A */ + VIA_DIRB = 0x02, /* direction B */ + VIA_DIRA = 0x03, /* direction A */ + VIA_T1CL = 0x04, /* low-order timer 1 counter */ + VIA_T1CH = 0x05, /* high-order timer 1 counter */ + VIA_T1LL = 0x06, /* low-order timer 1 latches */ + VIA_T1LH = 0x07, /* high-order timer 1 latches */ + VIA_T2CL = 0x08, /* low-order timer 2 latches */ + VIA_T2CH = 0x09, /* high-order timer 2 counter */ + VIA_SR = 0x0A, /* shift register */ + VIA_ACR = 0x0B, /* auxiliary control register */ + VIA_PCR = 0x0C, /* periheral control register */ + VIA_IFR = 0x0D, /* interrupt flag register */ + VIA_IER = 0x0E, /* interrupt enable register */ + VIA_ANH = 0x0F, /* input/output register A, no handshake */ +}; + +class ViaCuda +{ +public: + ViaCuda(); + ~ViaCuda() = default; + + uint8_t read(int reg); + void write(int reg, uint8_t value); + +private: + uint8_t via_regs[16]; /* VIA virtual registers */ + + void print_enabled_ints(); /* print enabled VIA interrupts and their sources */ +}; + +#endif /* VIACUDA_H */ diff --git a/main.cpp b/main.cpp index 16e4860..c5fe13a 100644 --- a/main.cpp +++ b/main.cpp @@ -22,7 +22,6 @@ #include "macioserial.h" #include "macswim3.h" #include "ppcmemory.h" -#include "viacuda.h" #include "devices/mpc106.h" #include "openpic.h" #include "debugger.h" diff --git a/ppcmemory.cpp b/ppcmemory.cpp index add6376..8c8dc0b 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -14,7 +14,6 @@ #include #include #include -#include "viacuda.h" #include "macioserial.h" #include "macswim3.h" #include "ppcemumain.h" diff --git a/ppcopcodes.cpp b/ppcopcodes.cpp index 7ff8792..3f037d0 100644 --- a/ppcopcodes.cpp +++ b/ppcopcodes.cpp @@ -1115,7 +1115,7 @@ void ppc_divwdot(){ void ppc_divwo(){ ppc_grab_regsdab(); - + //handle division by zero cases switch (ppc_result_b){ case 0: @@ -1889,15 +1889,15 @@ void ppc_twi(){ } void ppc_eieio(){ - std::cout << "Oops. Placeholder for eieio." << std::endl; + //std::cout << "Oops. Placeholder for eieio." << std::endl; } void ppc_isync(){ - std::cout << "Oops. Placeholder for isync." << std::endl; + //std::cout << "Oops. Placeholder for isync." << std::endl; } void ppc_sync(){ - std::cout << "Oops. Placeholder for sync." << std::endl; + //std::cout << "Oops. Placeholder for sync." << std::endl; } void ppc_icbi(){ diff --git a/viacuda.cpp b/viacuda.cpp deleted file mode 100644 index dd1c624..0000000 --- a/viacuda.cpp +++ /dev/null @@ -1,153 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the VIA CUDA - -#include -#include -#include "viacuda.h" -#include "ppcemumain.h" - -uint32_t via_cuda_address; -uint32_t via_set_mode; - -uint8_t via_opcode_store_bit; -uint8_t via_write_byte; -uint8_t via_read_byte; - -unsigned char porta_ca1, porta_ca2 = 0; -unsigned char porta_cb1, porta_cb2 = 0; - -bool via_cuda_confirm; -bool via_cuda_signal_read; -bool via_cuda_signal_write; - -void via_ifr_update(){ - if ((machine_iocontrolmem_mem[VIACUDA_IFR] & 127) && (machine_iocontrolmem_mem[VIACUDA_IER] & 127)){ - machine_iocontrolmem_mem[VIACUDA_IFR] |= 128; - } - else{ - machine_iocontrolmem_mem[VIACUDA_IFR] &= 127; - } -} - -void via_t1_update(){ - if (machine_iocontrolmem_mem[VIACUDA_T1CH] > 0){ - machine_iocontrolmem_mem[VIACUDA_T1CH]--; - } - else{ - machine_iocontrolmem_mem[VIACUDA_T1CH] = machine_iocontrolmem_mem[VIACUDA_T1LH]; - } - - - if (machine_iocontrolmem_mem[VIACUDA_T1CL] > 0){ - machine_iocontrolmem_mem[VIACUDA_T1CL]--; - } - else{ - machine_iocontrolmem_mem[VIACUDA_T1CL] = machine_iocontrolmem_mem[VIACUDA_T1LL]; - } -} - -void via_cuda_init(){ - machine_iocontrolmem_mem[VIACUDA_A] = 0x80; - machine_iocontrolmem_mem[VIACUDA_DIRB] = 0xFF; - machine_iocontrolmem_mem[VIACUDA_DIRA] = 0xFF; - machine_iocontrolmem_mem[VIACUDA_T1LL] = 0xFF; - machine_iocontrolmem_mem[VIACUDA_T1LH] = 0xFF; - machine_iocontrolmem_mem[VIACUDA_IER] = 0x7F; -} - -void via_cuda_read(){ - switch(via_cuda_address){ - case VIACUDA_B: - if (machine_iocontrolmem_mem[VIACUDA_DIRB] != 0){ - via_read_byte = (via_write_byte & ~machine_iocontrolmem_mem[VIACUDA_DIRB]) | (machine_iocontrolmem_mem[VIACUDA_B] & machine_iocontrolmem_mem[VIACUDA_DIRB]); - break; - } - case VIACUDA_A: - machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1; - - via_read_byte = (machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA]) | (machine_iocontrolmem_mem[VIACUDA_A] & machine_iocontrolmem_mem[VIACUDA_DIRA]); - break; - case VIACUDA_IER: - via_read_byte = machine_iocontrolmem_mem[VIACUDA_IER] | 0x80; - break; - case VIACUDA_ANH: - via_read_byte = machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA]; - break; - default: - via_read_byte = machine_iocontrolmem_mem[via_cuda_address]; - } - via_read_byte = machine_iocontrolmem_mem[via_cuda_address]; -} - -void via_cuda_write(){ - switch(via_cuda_address){ - case VIACUDA_B: - machine_iocontrolmem_mem[VIACUDA_B] = via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRB]; - break; - case VIACUDA_A: - machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1; - if ((machine_iocontrolmem_mem[VIACUDA_PCR] & 0x0A) != 0x02){ - machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca2; - } - via_ifr_update(); - machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]); - break; - case VIACUDA_DIRB: - machine_iocontrolmem_mem[VIACUDA_DIRB] = via_write_byte; - break; - case VIACUDA_DIRA: - machine_iocontrolmem_mem[VIACUDA_DIRA] = via_write_byte; - break; - case VIACUDA_T1LL: - case VIACUDA_T1LH: - via_t1_update(); - machine_iocontrolmem_mem[via_cuda_address] = via_write_byte; - break; - case VIACUDA_T2CH: - via_t1_update(); - machine_iocontrolmem_mem[VIACUDA_T2CH] = via_write_byte; - break; - case VIACUDA_PCR: - machine_iocontrolmem_mem[VIACUDA_PCR] = via_write_byte; - if ((via_write_byte & 0x0E) == 0x0C){ - porta_ca2 = 0; - } - else if ((via_write_byte & 0x08)){ - porta_ca2 = 1; - } - - if ((via_write_byte & 0xE0) == 0xC0){ - porta_cb2 = 0; - } - if ((via_write_byte & 0x80)){ - porta_cb2 = 1; - } - break; - case VIACUDA_IFR: - if (via_write_byte & 0x80){ - machine_iocontrolmem_mem[VIACUDA_IFR] &= (via_write_byte & 0x7F); - } - else{ - machine_iocontrolmem_mem[VIACUDA_IFR] &= ~(via_write_byte & 0x7F); - } - via_ifr_update(); - break; - case VIACUDA_IER: - machine_iocontrolmem_mem[VIACUDA_IER] &= ~(via_write_byte & 0x7F); - via_ifr_update(); - break; - case VIACUDA_ANH: - machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]); - break; - default: - machine_iocontrolmem_mem[via_cuda_address] = via_write_byte; - - } - machine_iocontrolmem_mem[via_cuda_address] = via_write_byte; -} diff --git a/viacuda.h b/viacuda.h deleted file mode 100644 index b54ad64..0000000 --- a/viacuda.h +++ /dev/null @@ -1,48 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -#ifndef VIACUDA_H_ -#define VIACUDA_H_ - -#define VIACUDA_B 0x3016000 /* B-side data */ -#define VIACUDA_A 0x3016200 /* A-side data */ -#define VIACUDA_DIRB 0x3016400 /* B-side direction (1=output) */ -#define VIACUDA_DIRA 0x3016600 /* A-side direction (1=output) */ -#define VIACUDA_T1CL 0x3016800 /* Timer 1 ctr/latch (low 8 bits) */ -#define VIACUDA_T1CH 0x3016A00 /* Timer 1 counter (high 8 bits) */ -#define VIACUDA_T1LL 0x3016C00 /* Timer 1 latch (low 8 bits) */ -#define VIACUDA_T1LH 0x3016E00 /* Timer 1 latch (high 8 bits) */ -#define VIACUDA_T2CL 0x3017000 /* Timer 2 ctr/latch (low 8 bits) */ -#define VIACUDA_T2CH 0x3017200 /* Timer 2 counter (high 8 bits) */ -#define VIACUDA_SR 0x3017400 /* Shift register */ -#define VIACUDA_ACR 0x3017600 /* Auxiliary control register */ -#define VIACUDA_PCR 0x3017800 /* Peripheral control register */ -#define VIACUDA_IFR 0x3017A00 /* Interrupt flag register */ -#define VIACUDA_IER 0x3017C00 /* Interrupt enable register */ -#define VIACUDA_ANH 0x3017E00 /* A-side data, no handshake */ - -extern uint32_t via_cuda_address; -extern uint8_t via_opcode_store_bit; - -extern uint8_t via_write_byte; -extern uint8_t via_read_byte; - -extern bool via_cuda_confirm; -extern bool via_cuda_signal_read; -extern bool via_cuda_signal_write; - -extern unsigned char porta_ca1, porta_ca2; -extern unsigned char porta_cb1, porta_cb2; -extern uint32_t via_set_mode; - -extern void via_ifr_update(); -extern void via_t1_update(); -extern void via_cuda_init(); -extern void via_cuda_read(); -extern void via_cuda_write(); - -#endif // VIACUDA_H From 12eada5bb130f547c3ad5488c3018ee4518bc0db Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Wed, 28 Aug 2019 02:39:29 +0200 Subject: [PATCH 07/13] Add VIA-CUDA description. --- devices/macio.h | 2 +- devices/mpc106.h | 2 +- devices/viacuda.cpp | 1 - devices/viacuda.h | 23 +++++++++++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/devices/macio.h b/devices/macio.h index a34aeb3..9ca9864 100644 --- a/devices/macio.h +++ b/devices/macio.h @@ -10,7 +10,7 @@ - Macintosh Enhanced SCSI Hardware (MESH) In the 68k Macintosh era, all this hardware was implemented using several - custom chips. In PCI-compatible Power Macintosh, the above devices are part + custom chips. In a PCI-compatible Power Macintosh, the above devices are part of the MIO chip itself. MIO's functional blocks implementing virtual devices are called "cells", i.e. "VIA cell", "SWIM cell" etc. diff --git a/devices/mpc106.h b/devices/mpc106.h index 71898d0..c5ddb8f 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -13,7 +13,7 @@ It's the central device in the Gossamer architecture. Manual: https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf - This code emulate as much functionality as needed to run PowerMac Beige G3. + This code emulates as much functionality as needed to run PowerMac Beige G3. This implies that - we only support address map B - our virtual device reports revision 4.0 as expected by machine firmware diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index 3fe1639..57d5ede 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -5,7 +5,6 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) -//Functionality for the VIA CUDA #include #include diff --git a/devices/viacuda.h b/devices/viacuda.h index b47016b..39972a0 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -5,6 +5,29 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) +/** VIA-CUDA combo device emulation. + + Author: Max Poliakovski 2019 + + Versatile interface adapter (VIA) is an old I/O controller that can be found + in nearly every Macintosh computer. In the 68k era, VIA was used to control + various peripherial devices. In a Power Macintosh, its function is limited + to the I/O interface for the Cuda MCU. I therefore decided to put VIA + emulation code here. + + Cuda MCU is a multipurpose IC built around a custom version of the Motorola + MC68HC05 microcontroller. It provides several functions including: + - Apple Desktop Bus (ADB) master + - I2C bus master + - Realtime clock (RTC) + - parameter RAM + - power management + + MC68HC05 doesn't provide any dedicated hardware for serial communication + protocols. All signals required for ADB and I2C will be generated by Cuda + firmware using bit banging (https://en.wikipedia.org/wiki/Bit_banging). +*/ + #ifndef VIACUDA_H #define VIACUDA_H From cf3f8b6db1e96a64e20b494326a912b25ef85d9d Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Sat, 21 Sep 2019 14:54:53 +0200 Subject: [PATCH 08/13] VIA-CUDA: support for I2C related pseudo commands. --- devices/viacuda.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++-- devices/viacuda.h | 35 ++++++++- 2 files changed, 197 insertions(+), 6 deletions(-) diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index 57d5ede..ef367e1 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -16,12 +16,25 @@ using namespace std; ViaCuda::ViaCuda() { + /* FIXME: is this the correct + VIA initialization? */ this->via_regs[VIA_A] = 0x80; this->via_regs[VIA_DIRB] = 0xFF; this->via_regs[VIA_DIRA] = 0xFF; this->via_regs[VIA_T1LL] = 0xFF; this->via_regs[VIA_T1LH] = 0xFF; this->via_regs[VIA_IER] = 0x7F; + + this->cuda_init(); +} + +void ViaCuda::cuda_init() +{ + this->old_tip = 0; + this->old_byteack = 0; + this->treq = 1; + this->in_count = 0; + this->out_count = 0; } uint8_t ViaCuda::read(int reg) @@ -34,6 +47,13 @@ uint8_t ViaCuda::read(int reg) /* reading from some VIA registers triggers special actions */ switch(reg & 0xF) { + case VIA_B: + res = this->via_regs[VIA_B]; + break; + case VIA_A: + case VIA_ANH: + cout << "WARNING: read attempt from VIA Port A!" << endl; + break; case VIA_IER: res |= 0x80; /* bit 7 always reads as "1" */ } @@ -45,22 +65,28 @@ void ViaCuda::write(int reg, uint8_t value) { switch(reg & 0xF) { case VIA_B: - cout << "VIA_B = " << hex << (uint32_t)value << endl; + this->via_regs[VIA_B] = value; + cuda_write(value); break; case VIA_A: - cout << "VIA_A = " << hex << (uint32_t)value << endl; + case VIA_ANH: + cout << "WARNING: write attempt to VIA Port A!" << endl; break; case VIA_DIRB: cout << "VIA_DIRB = " << hex << (uint32_t)value << endl; + this->via_regs[VIA_DIRB] = value; break; case VIA_DIRA: cout << "VIA_DIRA = " << hex << (uint32_t)value << endl; + this->via_regs[VIA_DIRA] = value; break; case VIA_PCR: cout << "VIA_PCR = " << hex << (uint32_t)value << endl; + this->via_regs[VIA_PCR] = value; break; case VIA_ACR: cout << "VIA_ACR = " << hex << (uint32_t)value << endl; + this->via_regs[VIA_ACR] = value; break; case VIA_IER: this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F @@ -69,9 +95,6 @@ void ViaCuda::write(int reg, uint8_t value) << endl; print_enabled_ints(); break; - case VIA_ANH: - cout << "VIA_ANH = " << hex << (uint32_t)value << endl; - break; default: this->via_regs[reg & 0xF] = value; } @@ -86,3 +109,138 @@ void ViaCuda::print_enabled_ints() cout << "VIA " << via_int_src[i] << " interrupt enabled." << endl; } } + +inline bool ViaCuda::cuda_ready() +{ + return ((this->via_regs[VIA_DIRB] & 0x38) == 0x30); +} + +inline void ViaCuda::assert_sr_int() +{ + this->via_regs[VIA_IFR] |= 0x84; +} + +void ViaCuda::cuda_write(uint8_t new_state) +{ + if (!cuda_ready()) { + cout << "Cuda not ready!" << endl; + return; + } + + int new_tip = !!(new_state & CUDA_TIP); + int new_byteack = !!(new_state & CUDA_BYTEACK); + + /* return if there is no state change */ + if (new_tip == this->old_tip && new_byteack == this->old_byteack) + return; + + cout << "Cuda state changed!" << endl; + + this->old_tip = new_tip; + this->old_byteack = new_byteack; + + if (new_tip) { + if (new_byteack) { + this->via_regs[VIA_B] |= CUDA_TREQ; /* negate TREQ */ + this->treq = 1; + + if (this->in_count) { + cuda_process_packet(); + + /* start response transaction */ + this->via_regs[VIA_B] &= ~CUDA_TREQ; /* assert TREQ */ + this->treq = 0; + } + + this->in_count = 0; + } else { + cout << "Cuda: enter sync state" << endl; + this->via_regs[VIA_B] &= ~CUDA_TREQ; /* assert TREQ */ + this->treq = 0; + this->in_count = 0; + this->out_count = 0; + } + + assert_sr_int(); /* send dummy byte as idle acknowledge or attention */ + } else { + if (this->via_regs[VIA_ACR] & 0x10) { /* data transfer: Host --> Cuda */ + if (this->in_count < 16) { + this->in_buf[this->in_count++] = this->via_regs[VIA_SR]; + assert_sr_int(); /* tell the system we've read the data */ + } else { + cout << "Cuda input buffer exhausted!" << endl; + } + } else { /* data transfer: Cuda --> Host */ + if (this->out_count) { + this->via_regs[VIA_SR] = this->out_buf[this->out_pos++]; + + if (this->out_pos >= this->out_count) { + cout << "Cuda: sending last byte" << endl; + this->out_count = 0; + this->via_regs[VIA_B] |= CUDA_TREQ; /* negate TREQ */ + this->treq = 1; + } + + assert_sr_int(); /* tell the system we've written the data */ + } + } + } +} + +void ViaCuda::cuda_null_response(uint32_t pkt_type, uint32_t pkt_flag, uint32_t cmd) +{ + this->out_buf[0] = pkt_type; + this->out_buf[1] = pkt_flag; + this->out_buf[2] = cmd; + this->out_count = 3; + this->out_pos = 0; +} + +void ViaCuda::cuda_process_packet() +{ + if (this->in_count < 2) { + cout << "Cuda: invalid packet (too few data)!" << endl; + return; + } + + switch(this->in_buf[0]) { + case 0: + cout << "Cuda: ADB packet received" << endl; + break; + case 1: + cout << "Cuda: pseudo command packet received" << endl; + cout << "Command: " << hex << (uint32_t)(this->in_buf[1]) << endl; + cout << "Data count: " << dec << this->in_count << endl; + for (int i = 0; i < this->in_count; i++) { + cout << hex << (uint32_t)(this->in_buf[i]) << ", "; + } + cout << endl; + cuda_pseudo_command(this->in_buf[1], this->in_count - 2); + break; + default: + cout << "Cuda: unsupported packet type = " << dec << (uint32_t)(this->in_buf[0]) << endl; + } +} + +void ViaCuda::cuda_pseudo_command(int cmd, int data_count) +{ + switch(cmd) { + case CUDA_READ_WRITE_I2C: + cuda_null_response(1, 0, cmd); + /* bit 0 of the I2C address byte indicates operation kind: + 0 - write to device, 1 - read from device + In the case of reading, Cuda will append one-byte result + to the response packet header */ + if (this->in_buf[2] & 1) { + this->out_buf[3] = 0xDD; /* send dummy byte for now */ + this->out_count++; + } + break; + case CUDA_OUT_PB0: /* undocumented call! */ + cout << "Cuda: send " << dec << (int)(this->in_buf[2]) << " to PB0" << endl; + cuda_null_response(1, 0, cmd); + break; + default: + cout << "Cuda: unsupported pseudo command 0x" << hex << cmd << endl; + } +} diff --git a/devices/viacuda.h b/devices/viacuda.h index 39972a0..a1d014d 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -20,7 +20,7 @@ - Apple Desktop Bus (ADB) master - I2C bus master - Realtime clock (RTC) - - parameter RAM + - parameter RAM (first generation of the Power Macintosh) - power management MC68HC05 doesn't provide any dedicated hardware for serial communication @@ -51,6 +51,21 @@ enum { VIA_ANH = 0x0F, /* input/output register A, no handshake */ }; +/** Cuda communication signals. */ +enum { + CUDA_TIP = 0x20, /* transaction in progress: 0 - true, 1 - false */ + CUDA_BYTEACK = 0x10, /* byte acknowledge: 0 - true, 1 - false */ + CUDA_TREQ = 0x08 /* Cuda requests transaction from host */ +}; + +/** Cuda pseudo commands. */ +enum { + CUDA_READ_WRITE_I2C = 0x22, /* read/write I2C device */ + CUDA_COMB_FMT_I2C = 0x25, /* combined format I2C transaction */ + CUDA_OUT_PB0 = 0x26, /* output one bit to Cuda's PB0 line */ +}; + + class ViaCuda { public: @@ -63,7 +78,25 @@ public: private: uint8_t via_regs[16]; /* VIA virtual registers */ + /* Cuda state. */ + uint8_t old_tip; + uint8_t old_byteack; + uint8_t treq; + uint8_t in_buf[16]; + int32_t in_count; + uint8_t out_buf[16]; + int32_t out_count; + int32_t out_pos; + void print_enabled_ints(); /* print enabled VIA interrupts and their sources */ + + void cuda_init(); + bool cuda_ready(); + void assert_sr_int(); + void cuda_write(uint8_t new_state); + void cuda_null_response(uint32_t pkt_type, uint32_t pkt_flag, uint32_t cmd); + void cuda_process_packet(); + void cuda_pseudo_command(int cmd, int data_count); }; #endif /* VIACUDA_H */ From 01c38b73487f72ff4c7dbd261d04436fd9a9990d Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 7 Oct 2019 03:18:18 +0200 Subject: [PATCH 09/13] VIA-CUDA: hackish support for SPD. --- devices/heathrow.cpp | 8 ++++ devices/viacuda.cpp | 98 ++++++++++++++++++++++++++++++++++++++++---- devices/viacuda.h | 23 ++++++++++- 3 files changed, 119 insertions(+), 10 deletions(-) diff --git a/devices/heathrow.cpp b/devices/heathrow.cpp index 429589b..3cb9fde 100644 --- a/devices/heathrow.cpp +++ b/devices/heathrow.cpp @@ -3,6 +3,11 @@ #include "macio.h" #include "viacuda.h" +/** Heathrow Mac I/O device emulation. + + Author: Max Poliakovski 2019 +*/ + using namespace std; HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow") @@ -113,6 +118,9 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) cout << "read from MIO:Int_Clear1 register" << endl; res = this->int_clear1; break; + case 0x34: /* heathrowIDs / HEATHROW_MBCR (Linux): media bay config reg? */ + res = 0xF0700000UL; + break; case 0x38: cout << "read from MIO:Feat_Ctrl register" << endl; res = this->feat_ctrl; diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index ef367e1..8377d94 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -5,6 +5,10 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) +/** VIA-CUDA combo device emulation. + + Author: Max Poliakovski 2019 +*/ #include #include @@ -187,15 +191,25 @@ void ViaCuda::cuda_write(uint8_t new_state) } } -void ViaCuda::cuda_null_response(uint32_t pkt_type, uint32_t pkt_flag, uint32_t cmd) +void ViaCuda::cuda_response_header(uint32_t pkt_type, uint32_t pkt_flag) { this->out_buf[0] = pkt_type; this->out_buf[1] = pkt_flag; - this->out_buf[2] = cmd; + this->out_buf[2] = this->in_buf[1]; /* copy original cmd */ this->out_count = 3; this->out_pos = 0; } +void ViaCuda::cuda_error_response(uint32_t error) +{ + this->out_buf[0] = CUDA_PKT_ERROR; + this->out_buf[1] = error; + this->out_buf[2] = this->in_buf[0]; + this->out_buf[3] = this->in_buf[1]; /* copy original cmd */ + this->out_count = 4; + this->out_pos = 0; +} + void ViaCuda::cuda_process_packet() { if (this->in_count < 2) { @@ -204,10 +218,10 @@ void ViaCuda::cuda_process_packet() } switch(this->in_buf[0]) { - case 0: + case CUDA_PKT_ADB: cout << "Cuda: ADB packet received" << endl; break; - case 1: + case CUDA_PKT_PSEUDO: cout << "Cuda: pseudo command packet received" << endl; cout << "Command: " << hex << (uint32_t)(this->in_buf[1]) << endl; cout << "Data count: " << dec << this->in_count << endl; @@ -226,21 +240,87 @@ void ViaCuda::cuda_pseudo_command(int cmd, int data_count) { switch(cmd) { case CUDA_READ_WRITE_I2C: - cuda_null_response(1, 0, cmd); + cuda_response_header(CUDA_PKT_PSEUDO, 0); /* bit 0 of the I2C address byte indicates operation kind: 0 - write to device, 1 - read from device In the case of reading, Cuda will append one-byte result to the response packet header */ - if (this->in_buf[2] & 1) { - this->out_buf[3] = 0xDD; /* send dummy byte for now */ - this->out_count++; + i2c_simple_transaction(this->in_buf[2], &this->in_buf[3], this->in_count - 3); + break; + case CUDA_COMB_FMT_I2C: + /* HACK: + This command performs the so-called open-ended transaction, i.e. + Cuda will continue to send data as long as handshaking is completed + for each byte. To support that, we'd need another emulation approach. + Fortunately, HWInit is known to read/write max. 4 bytes at once + so we're going to use a prefilled buffer to make it work. + */ + cuda_response_header(CUDA_PKT_PSEUDO, 0); + if (this->in_count >= 5) { + i2c_comb_transaction(this->in_buf[2], this->in_buf[3], this->in_buf[4], + &this->in_buf[5], this->in_count - 5); } break; case CUDA_OUT_PB0: /* undocumented call! */ cout << "Cuda: send " << dec << (int)(this->in_buf[2]) << " to PB0" << endl; - cuda_null_response(1, 0, cmd); + cuda_response_header(CUDA_PKT_PSEUDO, 0); break; default: cout << "Cuda: unsupported pseudo command 0x" << hex << cmd << endl; + cuda_error_response(CUDA_ERR_BAD_CMD); + } +} + +void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t *in_buf, + int in_bytes) +{ + int tr_type = dev_addr & 1; + + switch(dev_addr & 0xFE) { + case 0x50: /* unknown device on the Gossamer board */ + if (tr_type) { /* read */ + /* send dummy byte for now */ + this->out_buf[this->out_count++] = 0xDD; + } else { + /* ignore writes */ + } + break; + default: + cout << "Unsupported I2C device 0x" << hex << (int)dev_addr << endl; + cuda_error_response(CUDA_ERR_I2C); + } +} + +void ViaCuda::i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, + uint8_t dev_addr1, const uint8_t *in_buf, int in_bytes) +{ + int tr_type = dev_addr1 & 1; + + if ((dev_addr & 0xFE) != (dev_addr1 & 0xFE)) { + cout << "I2C combined, dev_addr mismatch!" << endl; + return; + } + + switch(dev_addr1 & 0xFE) { + case 0xAE: /* SDRAM EEPROM, no clue which one */ + if (tr_type) { /* read */ + if (sub_addr != 2) { + cout << "Unsupported read position 0x" << hex << (int)sub_addr + << " in SDRAM EEPROM 0x" << hex << (int)dev_addr1; + return; + } + /* FIXME: hardcoded SPD EEPROM values! This should be a proper + I2C device with user-configurable params */ + this->out_buf[this->out_count++] = 0x04; /* memory type = SDRAM */ + this->out_buf[this->out_count++] = 0x0B; /* row address bits per bank */ + this->out_buf[this->out_count++] = 0x09; /* col address bits per bank */ + this->out_buf[this->out_count++] = 0x02; /* num of RAM banks */ + } else { + /* ignore writes */ + } + break; + default: + cout << "Unsupported I2C device 0x" << hex << (int)dev_addr1 << endl; + cuda_error_response(CUDA_ERR_I2C); } } diff --git a/devices/viacuda.h b/devices/viacuda.h index a1d014d..f031370 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -58,6 +58,15 @@ enum { CUDA_TREQ = 0x08 /* Cuda requests transaction from host */ }; +/** Cuda packet types. */ +enum { + CUDA_PKT_ADB = 0, + CUDA_PKT_PSEUDO = 1, + CUDA_PKT_ERROR = 2, + CUDA_PKT_TICK = 3, + CUDA_PKT_POWER = 4 +}; + /** Cuda pseudo commands. */ enum { CUDA_READ_WRITE_I2C = 0x22, /* read/write I2C device */ @@ -65,6 +74,12 @@ enum { CUDA_OUT_PB0 = 0x26, /* output one bit to Cuda's PB0 line */ }; +/** Cuda error codes. */ +enum { + CUDA_ERR_BAD_CMD = 2, /* invalid pseudo command */ + CUDA_ERR_I2C = 5 /* invalid I2C data or no acknowledge */ +}; + class ViaCuda { @@ -94,9 +109,15 @@ private: bool cuda_ready(); void assert_sr_int(); void cuda_write(uint8_t new_state); - void cuda_null_response(uint32_t pkt_type, uint32_t pkt_flag, uint32_t cmd); + void cuda_response_header(uint32_t pkt_type, uint32_t pkt_flag); + void cuda_error_response(uint32_t error); void cuda_process_packet(); void cuda_pseudo_command(int cmd, int data_count); + + /* I2C related methods */ + void i2c_simple_transaction(uint8_t dev_addr, const uint8_t *in_buf, int in_bytes); + void i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1, + const uint8_t *in_buf, int in_bytes); }; #endif /* VIACUDA_H */ From 198b918a3c8f6422ad304f43ba5dbc8bb3b742b5 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 7 Oct 2019 03:21:01 +0200 Subject: [PATCH 10/13] MPC106: allocate RAM after software setup. Software will setup MPC106 internal registers and finally set MCCR1[MEMGO] flag. This is the right time for initializing physical RAM. --- devices/mmiodevice.h | 1 + devices/mpc106.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ devices/mpc106.h | 2 ++ main.cpp | 3 +-- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/devices/mmiodevice.h b/devices/mmiodevice.h index 454d1af..adc6140 100644 --- a/devices/mmiodevice.h +++ b/devices/mmiodevice.h @@ -6,6 +6,7 @@ #define READ_WORD_BE(addr) ((addr)[0] << 16) | (addr)[1] #define READ_DWORD_BE(addr) ((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3] +#define READ_DWORD_LE(addr) ((addr)[3] << 24) | ((addr)[2] << 16) | ((addr)[1] << 8) | (addr)[0] /** Abstract class representing a simple, memory-mapped I/O device */ class MMIODevice { diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp index 7c90630..2527b06 100644 --- a/devices/mpc106.cpp +++ b/devices/mpc106.cpp @@ -160,6 +160,13 @@ void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) std::cout << "MPC106 read error: invalid size parameter " << size << std::endl; } + + if (this->my_pci_cfg_hdr[0xF2] & 8) { +#ifdef MPC106_DEBUG + std::cout << "MPC106: MCCR1[MEMGO] was set! " << std::endl; +#endif + setup_ram(); + } } bool MPC106::pci_register_device(int dev_num, PCIDevice *dev_instance) @@ -179,3 +186,38 @@ bool MPC106::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDev // FIXME: add sanity checks! return this->add_mmio_region(start_addr, size, obj); } + +void MPC106::setup_ram() +{ + uint32_t mem_start, mem_end, ext_mem_start, ext_mem_end, bank_start, bank_end; + uint32_t ram_size = 0; + + uint8_t bank_en = this->my_pci_cfg_hdr[0xA0]; + + for (int bank = 0; bank < 8; bank++) { + if (bank_en & (1 << bank)) { + if (bank < 4) { + mem_start = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x80]); + ext_mem_start = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x88]); + mem_end = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x90]); + ext_mem_end = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x98]); + } else { + mem_start = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x84]); + ext_mem_start = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x8C]); + mem_end = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x94]); + ext_mem_end = READ_DWORD_LE(&this->my_pci_cfg_hdr[0x9C]); + } + bank_start = (((ext_mem_start >> bank * 8) & 3) << 30) | + (((mem_start >> bank * 8) & 0xFF) << 20); + bank_end = (((ext_mem_end >> bank * 8) & 3) << 30) | + (((mem_end >> bank * 8) & 0xFF) << 20) | 0xFFFFFUL; + if (bank && bank_start != ram_size) + std::cout << "MPC106 error: RAM not contiguous!" << std::endl; + ram_size += bank_end + 1; + } + } + + if (!this->add_ram_region(0, ram_size)) { + std::cout << "MPC106 RAM allocation failed!" << std::endl; + } +} diff --git a/devices/mpc106.h b/devices/mpc106.h index c5ddb8f..8166dd7 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -58,6 +58,8 @@ protected: //bool pci_register_device(int dev_num, PCIDevice *dev_instance); bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj); + void setup_ram(void); + private: uint8_t my_pci_cfg_hdr[256] = { 0x57, 0x10, // vendor ID: Motorola diff --git a/main.cpp b/main.cpp index c5fe13a..6f3af38 100644 --- a/main.cpp +++ b/main.cpp @@ -551,8 +551,7 @@ int main(int argc, char **argv) cout << "Initialize Gossamer hardware..."; MPC106 *mpc106 = new MPC106(); mem_ctrl_instance = mpc106; - if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000) || - !mem_ctrl_instance->add_ram_region(0x00000000, 0x800000)) { + if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000)) { cout << "failure!\n" << endl; delete(mem_ctrl_instance); romFile.close(); From ddb303c5c0435418ff26762ffb2ce9a633783e7a Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 14 Oct 2019 17:38:47 +0200 Subject: [PATCH 11/13] Add Machine ID register for the Gossamer architecture. --- devices/machineid.h | 37 +++++++++++++++++++++++++++++++++++++ main.cpp | 7 +++++++ 2 files changed, 44 insertions(+) create mode 100644 devices/machineid.h diff --git a/devices/machineid.h b/devices/machineid.h new file mode 100644 index 0000000..2f2cf8c --- /dev/null +++ b/devices/machineid.h @@ -0,0 +1,37 @@ +#ifndef MACHINE_ID_H +#define MACHINE_ID_H + +#include +#include "mmiodevice.h" + +/** + @file Contains definitions for PowerMacintosh machine ID registers. + + The machine ID register is a memory-based register containing hardcoded + values the system software can read to identify machine/board it's running on. + + Register location and value meaning are board-dependent. + */ + +/** + The machine ID for the Gossamer board is accesible at 0xFF000004 (phys). + It contains a 16-bit value revealing machine's capabilities like bus speed, + ROM speed, I/O configuration etc. + Because the meaning of these bits is poorly documented, the code below + simply return raw values obtained from real hardware. + */ +class GossamerID : public MMIODevice { +public: + GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; }; + ~GossamerID() = default; + + uint32_t read(uint32_t offset, int size) { + return ((!offset && size == 2) ? this->id : 0); }; + + void write(uint32_t offset, uint32_t value, int size) {}; /* not writable */ + +private: + uint16_t id; +}; + +#endif /* MACHINE_ID_H */ diff --git a/main.cpp b/main.cpp index 6f3af38..df342a1 100644 --- a/main.cpp +++ b/main.cpp @@ -25,6 +25,7 @@ #include "devices/mpc106.h" #include "openpic.h" #include "debugger.h" +#include "devices/machineid.h" #include "devices/macio.h" #include "devices/mpc106.h" @@ -84,6 +85,7 @@ uint32_t return_value; MemCtrlBase *mem_ctrl_instance = 0; HeathrowIC *heathrow = 0; +GossamerID *machine_id; //A pointer to a pointer, used for quick movement to one of the following //memory areas. These are listed right below. @@ -557,6 +559,10 @@ int main(int argc, char **argv) romFile.close(); return 1; } + machine_id = new GossamerID(0x3d8c); + assert(machine_id != 0); + mpc106->add_mmio_region(0xFF000004, 4096, machine_id); + heathrow = new HeathrowIC(); assert(heathrow != 0); mpc106->pci_register_device(16, heathrow); @@ -791,6 +797,7 @@ int main(int argc, char **argv) } delete(heathrow); + delete(machine_id); delete(mem_ctrl_instance); //Free memory after the emulation is completed. From c5fa279ad47f0ac9693d53af5a3964c658071982 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 14 Oct 2019 19:34:14 +0200 Subject: [PATCH 12/13] Remove device stubs (davbus, serial, SWIM etc). --- davbus.cpp | 35 ----------------- davbus.h | 22 ----------- macioserial.cpp | 102 ------------------------------------------------ macioserial.h | 22 ----------- macscsi.cpp | 31 --------------- macscsi.h | 21 ---------- macswim3.cpp | 29 -------------- macswim3.h | 19 --------- main.cpp | 2 - ppcmemory.cpp | 3 -- 10 files changed, 286 deletions(-) delete mode 100644 davbus.cpp delete mode 100644 davbus.h delete mode 100644 macioserial.cpp delete mode 100644 macioserial.h delete mode 100644 macscsi.cpp delete mode 100644 macscsi.h delete mode 100644 macswim3.cpp delete mode 100644 macswim3.h diff --git a/davbus.cpp b/davbus.cpp deleted file mode 100644 index 86f13ea..0000000 --- a/davbus.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the DAVBus (Sound Bus + Screamer?) - -#include -#include -#include -#include "ppcemumain.h" - -uint32_t davbus_address; -uint32_t davbus_write_word; -uint32_t davbus_read_word; - -void davbus_init(){ - -} - -void davbus_read(){ - davbus_read_word = (uint32_t)(machine_upperiocontrol_mem[davbus_address++]); - davbus_read_word = (uint32_t)((machine_upperiocontrol_mem[davbus_address++]) << 8); - davbus_read_word = (uint32_t)((machine_upperiocontrol_mem[davbus_address++]) << 16); - davbus_read_word = (uint32_t)((machine_upperiocontrol_mem[davbus_address]) << 24); -} - -void davbus_write(){ - machine_upperiocontrol_mem[davbus_address++] = (uint8_t)(davbus_write_word); - machine_upperiocontrol_mem[davbus_address++] = (uint8_t)((davbus_write_word) >> 8); - machine_upperiocontrol_mem[davbus_address++] = (uint8_t)((davbus_write_word) >> 16); - machine_upperiocontrol_mem[davbus_address] = (uint8_t)((davbus_write_word) >> 24); -} diff --git a/davbus.h b/davbus.h deleted file mode 100644 index 0f60a16..0000000 --- a/davbus.h +++ /dev/null @@ -1,22 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the DAVBus (Sound Bus + Screamer?) - -#ifndef DAVBUS_H_ -#define DAVBUS_H_ - -extern uint32_t davbus_address; -extern uint32_t davbus_write_word; -extern uint32_t davbus_read_word; - -extern void davbus_init(); -extern void davbus_read(); -extern void davbus_write(); - -#endif - diff --git a/macioserial.cpp b/macioserial.cpp deleted file mode 100644 index 5961ccd..0000000 --- a/macioserial.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the Serial Ports -// Based on the Zilog Z8530 SCC chip - -#include -#include -#include "macioserial.h" -#include "ppcemumain.h" - -uint32_t mac_serial_address; -uint8_t serial_write_byte; -uint8_t serial_read_byte; - -bool w7_prime; - -void mac_serial_init(){ - machine_iocontrolmem_mem[0x3013004] = 0x04; - machine_iocontrolmem_mem[0x3013009] = 0xC0; - machine_iocontrolmem_mem[0x301300B] = 0x08; - machine_iocontrolmem_mem[0x301300E] = 0x30; - machine_iocontrolmem_mem[0x301300F] = 0xF8; - machine_iocontrolmem_mem[0x3013010] = 0x44; - machine_iocontrolmem_mem[0x3013011] = 0x06; -} - -void mac_serial_read(){ - if (mac_serial_address >=0x3013020){ - mac_serial_address -= 0x20; - } - - if (w7_prime){ - if (((machine_iocontrolmem_mem[0x301301F] >> 2) & 0x1) & ((machine_iocontrolmem_mem[0x3013007] >> 6) & 0x1)){ - switch(mac_serial_address){ - case 0x14: case 0x15: - serial_read_byte = machine_iocontrolmem_mem[(mac_serial_address - 0x10)]; - break; - case 0x19: - serial_read_byte = machine_iocontrolmem_mem[0x3]; - break; - case 0x1B: - serial_read_byte = machine_iocontrolmem_mem[0x10]; - break; - case 0x1E: - serial_read_byte = machine_iocontrolmem_mem[0x07]; - break; - default: - serial_read_byte = machine_iocontrolmem_mem[mac_serial_address]; - break; - } - } - } - else{ - if ((machine_iocontrolmem_mem[0x301300F] >> 2) & 0x1){ - switch(mac_serial_address){ - case 0x14: case 0x15: - serial_read_byte = machine_iocontrolmem_mem[(mac_serial_address - 4)]; - break; - case 0x19: case 0x1B: - serial_read_byte = machine_iocontrolmem_mem[(mac_serial_address + 4)]; - break; - default: - serial_read_byte = machine_iocontrolmem_mem[mac_serial_address]; - break; - } - } - else { - switch(mac_serial_address){ - case 0x14: case 0x15: case 0x16: case 0x17: - serial_read_byte = machine_iocontrolmem_mem[(mac_serial_address - 4)]; - case 0x19: case 0x1B: - serial_read_byte = machine_iocontrolmem_mem[(mac_serial_address + 4)]; - break; - default: - serial_read_byte = machine_iocontrolmem_mem[mac_serial_address]; - break; - } - } - } -} - -void mac_serial_write(){ - if (mac_serial_address >=0x3013020){ - mac_serial_address -= 0x20; - } - machine_iocontrolmem_mem[mac_serial_address] = serial_write_byte; - - if ((machine_iocontrolmem_mem[0x0F]) & 0x1){ - w7_prime = true; - } - else{ - w7_prime = false; - } - - machine_iocontrolmem_mem[(mac_serial_address + 0x10)] = machine_iocontrolmem_mem[mac_serial_address]; - -} diff --git a/macioserial.h b/macioserial.h deleted file mode 100644 index 3ac8a4e..0000000 --- a/macioserial.h +++ /dev/null @@ -1,22 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the Serial Ports -// Based on the Zilog Z8530 SCC chip - -#ifndef MAC_IO_SERIAL_H -#define MAC_IO_SERIAL_H - -extern uint32_t mac_serial_address; -extern uint8_t serial_write_byte; -extern uint8_t serial_read_byte; - -extern void mac_serial_init(); -extern void mac_serial_read(); -extern void mac_serial_write(); - -#endif diff --git a/macscsi.cpp b/macscsi.cpp deleted file mode 100644 index 725f1dd..0000000 --- a/macscsi.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the SCSI - -#include -#include -#include -#include "ppcemumain.h" -#include "macscsi.h" - -uint32_t macscsi_address; -uint8_t macscsi_write_byte; -uint8_t macscsi_read_byte; - -void macscsi_init(){ - -} - -void macscsi_read(){ - -} - -void macscsi_write(){ - -} - diff --git a/macscsi.h b/macscsi.h deleted file mode 100644 index 1293dfc..0000000 --- a/macscsi.h +++ /dev/null @@ -1,21 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the SCSI - -#ifndef MACSCSI_H_ -#define MACSCSI_H_ - -extern uint32_t macscsi_address; -extern uint8_t macscsi_write_byte; -extern uint8_t macscsi_read_byte; - -extern void macscsi_init(); -extern void macscsi_read(); -extern void macscsi_write(); - -#endif diff --git a/macswim3.cpp b/macswim3.cpp deleted file mode 100644 index 3c20060..0000000 --- a/macswim3.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the Swim 3 Floppy Drive - -#include -#include -#include "macswim3.h" -#include "ppcemumain.h" - -uint32_t mac_swim3_address; -uint8_t swim3_write_byte; -uint8_t swim3_read_byte; - -void mac_swim3_init(){ - machine_iocontrolmem_mem[0x3015C00] = 0xF0; -} - -void mac_swim3_read(){ - swim3_read_byte = machine_iocontrolmem_mem[mac_swim3_address]; -} - -void mac_swim3_write(){ - machine_iocontrolmem_mem[mac_swim3_address] = swim3_write_byte; -} diff --git a/macswim3.h b/macswim3.h deleted file mode 100644 index 68763de..0000000 --- a/macswim3.h +++ /dev/null @@ -1,19 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -#ifndef MAC_SWIM3_H -#define MAC_SWIM3_H - -extern uint32_t mac_swim3_address; -extern uint8_t swim3_write_byte; -extern uint8_t swim3_read_byte; - -extern void mac_swim3_init(); -extern void mac_swim3_read(); -extern void mac_swim3_write(); - -#endif // MAC_IO_SERIAL_H diff --git a/main.cpp b/main.cpp index df342a1..4421166 100644 --- a/main.cpp +++ b/main.cpp @@ -19,8 +19,6 @@ #include #include #include "ppcemumain.h" -#include "macioserial.h" -#include "macswim3.h" #include "ppcmemory.h" #include "devices/mpc106.h" #include "openpic.h" diff --git a/ppcmemory.cpp b/ppcmemory.cpp index 8c8dc0b..a8b4970 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -14,15 +14,12 @@ #include #include #include -#include "macioserial.h" -#include "macswim3.h" #include "ppcemumain.h" #include "ppcmemory.h" #include "openpic.h" #include "devices/memctrlbase.h" #include "devices/mmiodevice.h" #include "devices/mpc106.h" -#include "davbus.h" std::vector pte_storage; From 43b9f47e6a42e138da7a37d91f22ccd027f5a6c4 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Mon, 14 Oct 2019 19:40:35 +0200 Subject: [PATCH 13/13] Remove unfinished OpenPIC stub. --- main.cpp | 1 - openpic.cpp | 136 -------------------------------------------------- openpic.h | 21 -------- ppcmemory.cpp | 1 - 4 files changed, 159 deletions(-) delete mode 100644 openpic.cpp delete mode 100644 openpic.h diff --git a/main.cpp b/main.cpp index 4421166..6da5e6d 100644 --- a/main.cpp +++ b/main.cpp @@ -21,7 +21,6 @@ #include "ppcemumain.h" #include "ppcmemory.h" #include "devices/mpc106.h" -#include "openpic.h" #include "debugger.h" #include "devices/machineid.h" #include "devices/macio.h" diff --git a/openpic.cpp b/openpic.cpp deleted file mode 100644 index 20489ef..0000000 --- a/openpic.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the OPENPIC - -#include -#include -#include -#include "ppcemumain.h" - -uint32_t openpic_address; -uint32_t openpic_write_word; -uint32_t openpic_read_word; -uint32_t openpic_prev_address; - -bool openpic_int_go; - -//OPENPIC ADDRESS MAP goes like this... - -//(Assuming that it's placed at 0x80040000 -//Per Processor Registers [private access] 0x40000 - 0x40fff -//Global registers 0x41000 - 0x4ffff -//Interrupt Source Configuration Registers 0x50000 - 0x5ffff -//Per Processor Registers [global access] 0x60000 - 0x7ffff - -//Taken from FreeBSD source code - -void openpic_init(){ - machine_upperiocontrol_mem[0x40000] = 0x14; - machine_upperiocontrol_mem[0x40001] = 0x10; - machine_upperiocontrol_mem[0x40002] = 0x46; - machine_upperiocontrol_mem[0x40003] = 0x00; - - machine_upperiocontrol_mem[0x40007] = 0x02; - - for (int i = 0x41004; i < 0x7FFFF; i++){ - if (i % 16 == 0){ - i += 4; - } - machine_upperiocontrol_mem[i] = 0xFF; - } - - machine_upperiocontrol_mem[0x41000] = 0x02; - machine_upperiocontrol_mem[0x41002] = 0x80; - - machine_upperiocontrol_mem[0x41080] = 0x14; - machine_upperiocontrol_mem[0x41081] = 0x46; - machine_upperiocontrol_mem[0x41090] = 0x01; - machine_upperiocontrol_mem[0x410E0] = 0xFF; -} - -void openpic_read(){ - if (openpic_address > 0x60000){ - openpic_address = (openpic_address % 0x8000) + 0x60000; - } - - openpic_read_word = (uint32_t)(machine_upperiocontrol_mem[openpic_address++]); - openpic_read_word = (uint32_t)((machine_upperiocontrol_mem[openpic_address++]) << 8); - openpic_read_word = (uint32_t)((machine_upperiocontrol_mem[openpic_address++]) << 16); - openpic_read_word = (uint32_t)((machine_upperiocontrol_mem[openpic_address]) << 24); - -} - -void openpic_write(){ - //Max of 128 interrupts per processor - //Each interrupt line takes up 0x8000 bytes - - uint32_t op_interrupt_check = (openpic_address & 0xFF); - - //We have only one processor - if (openpic_address > 0x60000){ - openpic_address = (openpic_address % 0x8000) + 0x60000; - } - - switch(openpic_address){ - //Make sure we don't touch any of the following read-only regs - case 0x41000: - case 0x41080: - case 0x41100: - case 0x41140: - case 0x41180: - case 0x411C0: - case 0x600A0: - case 0x600B0: - case 0x610A0: - case 0x610B0: - case 0x620A0: - case 0x620B0: - case 0x630A0: - case 0x630B0: - return; - default: - if (openpic_address == openpic_prev_address){ - return; - } - else{ - openpic_prev_address = openpic_address; - } - machine_upperiocontrol_mem[openpic_address++] = (uint8_t)(openpic_write_word); - machine_upperiocontrol_mem[openpic_address++] = (uint8_t)((openpic_write_word) >> 8); - machine_upperiocontrol_mem[openpic_address++] = (uint8_t)((openpic_write_word) >> 16); - machine_upperiocontrol_mem[openpic_address] = (uint8_t)((openpic_write_word) >> 24); - break; - } - - switch (op_interrupt_check){ - case 0x40: - printf("IPI 0 stuff goes here! \n"); - break; - case 0x50: - printf("IPI 1 stuff goes here! \n"); - break; - case 0x60: - printf("IPI 2 stuff goes here! \n"); - break; - case 0x70: - printf("IPI 3 stuff goes here! \n"); - break; - case 0x80: - printf("Task Priority Reg stuff goes here! \n"); - break; - case 0x90: - printf("WHOAMI stuff goes here! \n"); - break; - case 0xA0: - openpic_int_go = true; - break; - case 0xB0: - openpic_int_go = false; - break; - } -} diff --git a/openpic.h b/openpic.h deleted file mode 100644 index 064e978..0000000 --- a/openpic.h +++ /dev/null @@ -1,21 +0,0 @@ -//DingusPPC - Prototype 5bf2 -//Written by divingkatae -//(c)2018-20 (theweirdo) -//Please ask for permission -//if you want to distribute this. -//(divingkatae#1017 on Discord) - -//Functionality for the OPENPIC - -#ifndef OPENPIC_H_ -#define OPENPIC_H_ - -extern uint32_t openpic_address; -extern uint32_t openpic_write_word; -extern uint32_t openpic_read_word; - -extern void openpic_init(); -extern void openpic_read(); -extern void openpic_write(); - -#endif diff --git a/ppcmemory.cpp b/ppcmemory.cpp index a8b4970..a64fade 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -16,7 +16,6 @@ #include #include "ppcemumain.h" #include "ppcmemory.h" -#include "openpic.h" #include "devices/memctrlbase.h" #include "devices/mmiodevice.h" #include "devices/mpc106.h"