mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-03-30 19:34:19 +00:00
Add basic PDM I/O emulation.
This commit is contained in:
parent
b4d399ffa2
commit
0f55877137
121
devices/amic.cpp
Normal file
121
devices/amic.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-21 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** Apple memory-mapped I/O controller emulation.
|
||||
|
||||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include "amic.h"
|
||||
#include "machines/machinebase.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "viacuda.h"
|
||||
#include <cinttypes>
|
||||
#include <loguru.hpp>
|
||||
|
||||
AMIC::AMIC()
|
||||
{
|
||||
this->name = "Apple Memory-mapped I/O Controller";
|
||||
|
||||
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>
|
||||
(gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
|
||||
|
||||
/* add memory mapped I/O region for the AMIC control registers */
|
||||
if (!mem_ctrl->add_mmio_region(0x50F00000, 0x00040000, this)) {
|
||||
LOG_F(ERROR, "Couldn't register AMIC registers!");
|
||||
}
|
||||
|
||||
this->viacuda = std::unique_ptr<ViaCuda> (new ViaCuda());
|
||||
}
|
||||
|
||||
bool AMIC::supports_type(HWCompType type) {
|
||||
if (type == HWCompType::MMIO_DEV) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
if (offset < 0x2000) {
|
||||
return this->viacuda->read(offset >> 9);
|
||||
}
|
||||
|
||||
LOG_F(INFO, "AMIC read!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
if (offset < 0x2000) {
|
||||
this->viacuda->write(offset >> 9, value);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(offset) {
|
||||
case AMICReg::Snd_Out_Cntl:
|
||||
LOG_F(INFO, "AMIC Sound Out Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::Snd_In_Cntl:
|
||||
LOG_F(INFO, "AMIC Sound In Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::VIA2_Slot_IER:
|
||||
LOG_F(INFO, "AMIC VIA2 Slot Interrupt Enable Register updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::VIA2_IER:
|
||||
LOG_F(INFO, "AMIC VIA2 Interrupt Enable Register updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::Video_Mode_Reg:
|
||||
LOG_F(INFO, "AMIC Video Mode Register set to %x", value);
|
||||
break;
|
||||
case AMICReg::Int_Cntl:
|
||||
LOG_F(INFO, "AMIC Interrupt Control Register set to %X", value);
|
||||
break;
|
||||
case AMICReg::Enet_DMA_Xmt_Cntl:
|
||||
LOG_F(INFO, "AMIC Ethernet Transmit DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SCSI_DMA_Cntl:
|
||||
LOG_F(INFO, "AMIC SCSI DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::Enet_DMA_Rcv_Cntl:
|
||||
LOG_F(INFO, "AMIC Ethernet Receive DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SWIM3_DMA_Cntl:
|
||||
LOG_F(INFO, "AMIC SWIM3 DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SCC_DMA_Xmt_A_Cntl:
|
||||
LOG_F(INFO, "AMIC SCC Transmit Ch A DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SCC_DMA_Rcv_A_Cntl:
|
||||
LOG_F(INFO, "AMIC SCC Receive Ch A DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SCC_DMA_Xmt_B_Cntl:
|
||||
LOG_F(INFO, "AMIC SCC Transmit Ch B DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
case AMICReg::SCC_DMA_Rcv_B_Cntl:
|
||||
LOG_F(INFO, "AMIC SCC Receive Ch B DMA Ctrl updated, val=%x", value);
|
||||
break;
|
||||
default:
|
||||
LOG_F(WARNING, "Unknown AMIC register write, offset=%x, val=%x",
|
||||
offset, value);
|
||||
}
|
||||
}
|
76
devices/amic.h
Normal file
76
devices/amic.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-21 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file Apple memory-mapped I/O controller emulation. */
|
||||
|
||||
#ifndef AMIC_H
|
||||
#define AMIC_H
|
||||
|
||||
#include "mmiodevice.h"
|
||||
#include "viacuda.h"
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
|
||||
/* AMIC DMA registers offsets from AMIC base (0x50F00000). */
|
||||
enum AMICReg : uint32_t {
|
||||
// Sound control registers
|
||||
Snd_Out_Cntl = 0x14010,
|
||||
Snd_In_Cntl = 0x14011,
|
||||
|
||||
// VIA2 registers
|
||||
VIA2_Slot_IER = 0x26012,
|
||||
VIA2_IER = 0x26013,
|
||||
|
||||
// Video control registers
|
||||
Video_Mode_Reg = 0x28000,
|
||||
|
||||
Int_Cntl = 0x2A000,
|
||||
|
||||
// DMA control registers
|
||||
Enet_DMA_Xmt_Cntl = 0x31C20,
|
||||
SCSI_DMA_Cntl = 0x32008,
|
||||
Enet_DMA_Rcv_Cntl = 0x32028,
|
||||
SWIM3_DMA_Cntl = 0x32068,
|
||||
SCC_DMA_Xmt_A_Cntl = 0x32088,
|
||||
SCC_DMA_Rcv_A_Cntl = 0x32098,
|
||||
SCC_DMA_Xmt_B_Cntl = 0x320A8,
|
||||
SCC_DMA_Rcv_B_Cntl = 0x320B8,
|
||||
};
|
||||
|
||||
class AMIC : public MMIODevice {
|
||||
public:
|
||||
AMIC();
|
||||
~AMIC() = default;
|
||||
|
||||
bool supports_type(HWCompType type);
|
||||
|
||||
/* MMIODevice methods */
|
||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
||||
|
||||
protected:
|
||||
void dma_reg_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ViaCuda> viacuda;
|
||||
};
|
||||
|
||||
#endif // AMIC_H
|
@ -35,6 +35,39 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
Register location and value meaning are board-dependent.
|
||||
*/
|
||||
|
||||
/**
|
||||
Machine ID register for Nubus Power Macs.
|
||||
It's located at physical address 0x5FFFFFFC and contains four bytes:
|
||||
+0 uint16_t signature = 0xA55A
|
||||
+1 uint8_t machine_type (3 - PowerMac)
|
||||
+2 uint8_t model (0x10 = PDM, 0x12 = Carl Sagan, 0x13 = Cold Fusion)
|
||||
*/
|
||||
class NubusMacID : public MMIODevice {
|
||||
public:
|
||||
NubusMacID(const uint16_t id) {
|
||||
this->name = "Nubus-Machine-id";
|
||||
this->id[0] = 0xA5;
|
||||
this->id[1] = 0x5A;
|
||||
this->id[2] = (id >> 8) & 0xFF;
|
||||
this->id[3] = id & 0xFF;
|
||||
};
|
||||
~NubusMacID() = default;
|
||||
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::MMIO_DEV;
|
||||
};
|
||||
|
||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
return (offset < 4 ? this->id[offset] : 0);
|
||||
};
|
||||
|
||||
/* not writable */
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {};
|
||||
|
||||
private:
|
||||
uint8_t id[4];
|
||||
};
|
||||
|
||||
/**
|
||||
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,
|
||||
@ -57,7 +90,8 @@ public:
|
||||
return ((!offset && size == 2) ? this->id : 0);
|
||||
};
|
||||
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size){}; /* not writable */
|
||||
/* not writable */
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {};
|
||||
|
||||
private:
|
||||
uint16_t id;
|
||||
|
@ -25,7 +25,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cpu/ppc/ppcemu.h"
|
||||
#include "devices/amic.h"
|
||||
#include "devices/hmc.h"
|
||||
#include "devices/machineid.h"
|
||||
#include "machinebase.h"
|
||||
#include "machineproperties.h"
|
||||
#include <loguru.hpp>
|
||||
@ -45,9 +47,19 @@ int create_pdm(std::string& id) {
|
||||
/* register HMC memory controller */
|
||||
gMachineObj->add_component("HMC", new HMC);
|
||||
|
||||
/* register AMIC I/O controller */
|
||||
gMachineObj->add_component("AMIC", new AMIC);
|
||||
|
||||
/* get raw pointer to HMC object */
|
||||
HMC* hmc_obj = dynamic_cast<HMC*>(gMachineObj->get_comp_by_name("HMC"));
|
||||
|
||||
/* allocate machine ID register and tell we're running PowerMac 6100 */
|
||||
// TODO: add a possibility to select another machine
|
||||
// to be used with the same ROM
|
||||
gMachineObj->add_component("MachineID", new NubusMacID(0x3010));
|
||||
hmc_obj->add_mmio_region(0x5FFFFFFC, 4,
|
||||
dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
||||
|
||||
/* allocate ROM region */
|
||||
if (!hmc_obj->add_rom_region(0x40000000, 0x400000)) {
|
||||
LOG_F(ERROR, "Could not allocate ROM region!\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user