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/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/devices/heathrow.cpp b/devices/heathrow.cpp new file mode 100644 index 0000000..3cb9fde --- /dev/null +++ b/devices/heathrow.cpp @@ -0,0 +1,155 @@ +#include +#include +#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") +{ + 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]; +} + +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 & 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; + } + break; + } +} + +uint32_t HeathrowIC::read(uint32_t offset, int size) +{ + uint32_t res = 0; + + cout << this->name << ": reading from offset " << hex << offset << endl; + + 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 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; + 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/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/devices/macio.h b/devices/macio.h new file mode 100644 index 0000000..9ca9864 --- /dev/null +++ b/devices/macio.h @@ -0,0 +1,109 @@ +/** 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 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. + + 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" +#include "viacuda.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(); + ~HeathrowIC(); + + 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); + +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. + 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 + }; + + 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/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..adc6140 --- /dev/null +++ b/devices/mmiodevice.h @@ -0,0 +1,22 @@ +#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] +#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 { +public: + virtual uint32_t read(uint32_t offset, int size) = 0; + virtual void write(uint32_t offset, uint32_t value, int size) = 0; + virtual ~MMIODevice() = default; + +protected: + std::string name; +}; + +#endif /* MMIO_DEVICE_H */ diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp new file mode 100644 index 0000000..2527b06 --- /dev/null +++ b/devices/mpc106.cpp @@ -0,0 +1,223 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski +*/ + +#include +#include +#include + +#include "memctrlbase.h" +#include "mmiodevice.h" +#include "mpc106.h" + + +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) +{ + if (offset >= 0x200000) { + if (this->config_addr & 0x80) // process only if bit E (enable) is set + return pci_read(size); + } + + /* 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_offs; + + 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_offs = (this->config_addr >> 24) & 0xFC; + + if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself + return this->pci_cfg_read(reg_offs, size); + } else { + 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; +} + +void MPC106::pci_write(uint32_t value, uint32_t size) +{ + int bus_num, dev_num, fun_num, reg_offs; + + 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; + } + + 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 + this->pci_cfg_write(reg_offs, value, size); + } else { + 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::pci_cfg_read(uint32_t reg_offs, uint32_t size) +{ +#ifdef MPC106_DEBUG + printf("read from Grackle register %08X\n", reg_offs); +#endif + + switch(size) { + case 1: + return this->my_pci_cfg_hdr[reg_offs]; + break; + case 2: + return READ_WORD_BE(&this->my_pci_cfg_hdr[reg_offs]); + break; + case 4: + return READ_DWORD_BE(&this->my_pci_cfg_hdr[reg_offs]); + break; + default: + std::cout << "MPC106 read error: invalid size parameter " << size + << std::endl; + } + + return 0; +} + +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_offs); +#endif + + // FIXME: implement write-protection for read-only registers + switch(size) { + case 1: + this->my_pci_cfg_hdr[reg_offs] = value & 0xFF; + break; + case 2: + 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_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; + } + + 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) +{ + 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); +} + +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 new file mode 100644 index 0000000..8166dd7 --- /dev/null +++ b/devices/mpc106.h @@ -0,0 +1,91 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski + + 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 + + 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 +*/ + +#ifndef MPC106_H_ +#define MPC106_H_ + +#include +#include +#include "memctrlbase.h" +#include "mmiodevice.h" +#include "pcidevice.h" +#include "pcihost.h" + + +class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost +{ +public: + using MemCtrlBase::name; + + MPC106(); + ~MPC106(); + 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 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); + + void setup_ram(void); + +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: 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 + [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; + + std::unordered_map pci_0_bus; +}; + +#endif 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 */ diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp new file mode 100644 index 0000000..8377d94 --- /dev/null +++ b/devices/viacuda.cpp @@ -0,0 +1,326 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +/** VIA-CUDA combo device emulation. + + Author: Max Poliakovski 2019 +*/ + +#include +#include +#include +#include "viacuda.h" + +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) +{ + 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_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" */ + } + + return res; +} + +void ViaCuda::write(int reg, uint8_t value) +{ + switch(reg & 0xF) { + case VIA_B: + this->via_regs[VIA_B] = value; + cuda_write(value); + break; + case VIA_A: + 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 + : this->via_regs[VIA_IER] & ~value; + cout << "VIA_IER updated to " << hex << (uint32_t)this->via_regs[VIA_IER] + << endl; + print_enabled_ints(); + 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; + } +} + +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_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] = 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) { + cout << "Cuda: invalid packet (too few data)!" << endl; + return; + } + + switch(this->in_buf[0]) { + case CUDA_PKT_ADB: + cout << "Cuda: ADB packet received" << endl; + break; + 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; + 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_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 */ + 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_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 new file mode 100644 index 0000000..f031370 --- /dev/null +++ b/devices/viacuda.h @@ -0,0 +1,123 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//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 (first generation of the Power Macintosh) + - 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 + +/** 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 */ +}; + +/** 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 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 */ + CUDA_COMB_FMT_I2C = 0x25, /* combined format I2C transaction */ + 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 +{ +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 */ + + /* 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_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 */ 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 0971a97..6da5e6d 100644 --- a/main.cpp +++ b/main.cpp @@ -19,14 +19,12 @@ #include #include #include "ppcemumain.h" -#include "macioserial.h" -#include "macswim3.h" #include "ppcmemory.h" -#include "viacuda.h" -#include "mpc106.h" -#include "openpic.h" +#include "devices/mpc106.h" #include "debugger.h" -//#include +#include "devices/machineid.h" +#include "devices/macio.h" +#include "devices/mpc106.h" #define max_16b_int 65535 #define max_32b_int 4294967295 @@ -38,6 +36,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 +80,9 @@ 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; +GossamerID *machine_id; //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,43 @@ 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..."; + MPC106 *mpc106 = new MPC106(); + mem_ctrl_instance = mpc106; + if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000)) { + cout << "failure!\n" << endl; + delete(mem_ctrl_instance); + 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); + 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 +593,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 +793,9 @@ int main(int argc, char **argv) std::cout << "playground - Mess around with and opcodes. " << endl; } - romFile.close(); + delete(heathrow); + delete(machine_id); + delete(mem_ctrl_instance); //Free memory after the emulation is completed. free(machine_sysram_mem); 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/mpc106.cpp b/mpc106.cpp deleted file mode 100644 index e4ea06f..0000000 --- a/mpc106.cpp +++ /dev/null @@ -1,372 +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 MPC106 - -#include -#include -#include -#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] = -{ -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; -} - -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). - - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; - - 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; - } - - 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). - - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; - - uint32_t grab_value = 0; - - 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; - 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; - 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; - break; - case 0x0: - case 0x2: - case 0x4: - case 0x6: - case 0x70: - read_length = 2; - 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; - } -} diff --git a/mpc106.h b/mpc106.h deleted file mode 100644 index 91c96f5..0000000 --- a/mpc106.h +++ /dev/null @@ -1,38 +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 MPC106 - -#ifndef MPC106_H_ -#define MPC106_H_ - -#define mpc106_addres_map_a 1 -#define mpc106_addres_map_b 0 - -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; - -extern unsigned char* mpc106_regs; - -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); - -#endif 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/ppcemumain.h b/ppcemumain.h index 798b015..db0d6fc 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 @@ -102,7 +104,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; @@ -226,6 +228,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 ccea6c5..a64fade 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -14,14 +14,11 @@ #include #include #include -#include "viacuda.h" -#include "macioserial.h" -#include "macswim3.h" #include "ppcemumain.h" #include "ppcmemory.h" -#include "openpic.h" -#include "mpc106.h" -#include "davbus.h" +#include "devices/memctrlbase.h" +#include "devices/mmiodevice.h" +#include "devices/mpc106.h" std::vector pte_storage; @@ -94,76 +91,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 +273,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 +350,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 +552,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); } diff --git a/ppcopcodes.cpp b/ppcopcodes.cpp index 62e185e..6d52a46 100644 --- a/ppcopcodes.cpp +++ b/ppcopcodes.cpp @@ -1899,15 +1899,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