Improve MACE stub.

This commit is contained in:
Maxim Poliakovski 2024-07-23 01:38:37 +02:00
parent bda85a66df
commit 211f8adc0e
4 changed files with 150 additions and 49 deletions

View File

@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-22 divingkatae and maximum
Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -32,11 +32,24 @@ using namespace MaceEnet;
uint8_t MaceController::read(uint8_t reg_offset)
{
switch(reg_offset) {
case MaceReg::Interrupt:
LOG_F(INFO, "MACE: all interrupt flags cleared");
return 0;
case MaceReg::Rcv_Frame_Ctrl:
return this->rcv_fc;
case MaceReg::Interrupt: {
uint8_t ret_val = this->int_stat;
this->int_stat = 0;
LOG_F(9, "%s: all interrupt flags cleared", this->name.c_str());
return ret_val;
}
case MaceReg::Interrupt_Mask:
return this->int_mask;
case MaceReg::BIU_Config_Ctrl:
return this->biu_ctrl;
case MaceReg::Chip_ID_Lo:
return this->chip_id & 0xFFU;
case MaceReg::Chip_ID_Hi:
return (this->chip_id >> 8) & 0xFFU;
default:
LOG_F(INFO, "Reading MACE register %d", reg_offset);
LOG_F(INFO, "%s: reading from register %d", this->name.c_str(), reg_offset);
}
return 0;
@ -45,15 +58,57 @@ uint8_t MaceController::read(uint8_t reg_offset)
void MaceController::write(uint8_t reg_offset, uint8_t value)
{
switch(reg_offset) {
case MaceReg::Rcv_Frame_Ctrl:
this->rcv_fc = value;
break;
case MaceReg::Interrupt_Mask:
this->int_mask = value;
break;
case MaceReg::MAC_Config_Ctrl:
this->mac_cfg = value;
break;
case MaceReg::BIU_Config_Ctrl:
if (value & 1) {
LOG_F(INFO, "MACE Reset issued");
} else {
LOG_F(INFO, "MACE BIU Config set to 0x%X", value);
if (value & BIU_SWRST) {
LOG_F(INFO, "%s: soft reset asserted", this->name.c_str());
value &= ~BIU_SWRST; // acknowledge soft reset
}
this->biu_ctrl = value;
break;
case MaceReg::PLS_Config_Ctrl:
if (value != 7)
LOG_F(WARNING, "%s: unsupported transceiver interface 0x%X in PLSCC",
this->name.c_str(), value);
break;
case MaceReg::Int_Addr_Config:
if ((value & IAC_LOGADDR) && (value & IAC_PHYADDR))
value &= ~IAC_PHYADDR;
if (value & (IAC_LOGADDR | IAC_PHYADDR))
this->addr_ptr = 0;
this->addr_cfg = value;
break;
case MaceReg::Log_Addr_Flt:
if (this->addr_cfg & IAC_LOGADDR) {
uint64_t mask = ~(0xFFULL << (this->addr_ptr * 8));
this->log_addr = (this->log_addr & mask) | ((uint64_t)value << (this->addr_ptr * 8));
if (++this->addr_ptr >= 8) {
this->addr_cfg &= ~IAC_LOGADDR;
this->addr_ptr = 0;
}
}
break;
case MaceReg::Phys_Addr:
if (this->addr_cfg & IAC_PHYADDR) {
uint64_t mask = ~(0xFFULL << (this->addr_ptr * 8));
this->phys_addr = (this->phys_addr & mask) | ((uint64_t)value << (this->addr_ptr * 8));
if (++this->addr_ptr >= 6) {
this->addr_cfg &= ~IAC_PHYADDR;
this->addr_ptr = 0;
}
}
break;
default:
LOG_F(INFO, "Writing 0x%X to MACE register %d", value, reg_offset);
LOG_F(INFO, "%s: writing 0x%X to register %d", this->name.c_str(),
value, reg_offset);
}
}

View File

@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-22 divingkatae and maximum
Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -24,58 +24,74 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef MACE_H
#define MACE_H
#include <devices/common/dmacore.h>
#include <devices/common/hwcomponent.h>
#include <cinttypes>
#include <memory>
// MACE Chip ID from AMD datasheet
// TODO: compare with real HW
#define MACE_ID 0x3940
/** Known MACE chip IDs. */
#define MACE_ID_REV_B0 0x0940 // Darwin-0.3 source
#define MACE_ID_REV_A2 0x0941 // Darwin-0.3 source & Curio datasheet
// MACE registers offsets
/** MACE registers offsets. */
// Refer to the Am79C940 datasheet for details
namespace MaceEnet {
enum MaceReg : uint8_t {
Rcv_FIFO = 0,
Xmit_FIFO = 1,
Xmit_Frame_Ctrl = 2,
Xmit_Frame_Stat = 3,
Xmit_Retry_Cnt = 4,
Rcv_Frame_Ctrl = 5,
Rcv_Frame_Stat = 6,
FIFO_Frame_Cnt = 7,
Interrupt = 8,
Interrupt_Mask = 9,
Poll = 10,
BIU_Config_Ctrl = 11,
FIFO_Config = 12,
MAC_Config_Ctrl = 13,
PLS_Config_Ctrl = 14,
PHY_Config_Ctrl = 15,
Chip_ID_Lo = 16,
Chip_ID_Hi = 17,
Int_Addr_Config = 18,
Log_Addr_Flt = 20,
Phys_Addr = 21,
Missed_Pkt_Cnt = 24,
Runt_Pkt_Cnt = 26, // not used in Macintosh?
Rcv_Collis_Cnt = 27, // not used in Macintosh?
User_Test = 29,
Rsrvd_Test_1 = 30, // not used in Macintosh?
Rsrvd_Test_2 = 31, // not used in Macintosh?
};
enum MaceReg : uint8_t {
Rcv_FIFO = 0,
Xmit_FIFO = 1,
Xmit_Frame_Ctrl = 2,
Xmit_Frame_Stat = 3,
Xmit_Retry_Cnt = 4,
Rcv_Frame_Ctrl = 5,
Rcv_Frame_Stat = 6,
FIFO_Frame_Cnt = 7,
Interrupt = 8,
Interrupt_Mask = 9,
Poll = 0x0A,
BIU_Config_Ctrl = 0x0B,
FIFO_Config = 0x0C,
MAC_Config_Ctrl = 0x0D,
PLS_Config_Ctrl = 0x0E,
PHY_Config_Ctrl = 0x0F,
Chip_ID_Lo = 0x10,
Chip_ID_Hi = 0x11,
Addr_Config = 0x12,
Log_Addr_Flt = 0x14,
Phys_Addr = 0x15,
Missed_Pkt_Cnt = 0x18,
Runt_Pkt_Cnt = 0x1A, // not used in Macintosh?
Rcv_Collis_Cnt = 0x1B, // not used in Macintosh?
User_Test = 0x1D,
Rsrvd_Test_1 = 0x1E, // not used in Macintosh?
Rsrvd_Test_2 = 0x1F, // not used in Macintosh?
};
/** Bit definitions for BIU_Config_Ctrl register. */
enum {
BIU_SWRST = 1 << 0,
};
/** Bit definitions for the internal configuration register. */
enum {
IAC_LOGADDR = 1 << 1,
IAC_PHYADDR = 1 << 2,
IAC_ADDRCHG = 1 << 7
};
}; // namespace MaceEnet
class MaceController : public HWComponent {
class MaceController : public DmaDevice, public HWComponent {
public:
MaceController(uint16_t id) { this->chip_id = id; };
MaceController(uint16_t id) {
this->chip_id = id;
this->set_name("MACE");
this->supports_types(HWCompType::MMIO_DEV | HWCompType::ETHER_MAC);
};
~MaceController() = default;
static std::unique_ptr<HWComponent> create() {
return std::unique_ptr<MaceController>(new MaceController(MACE_ID));
return std::unique_ptr<MaceController>(new MaceController(MACE_ID_REV_A2));
}
// MACE registers access
@ -84,6 +100,17 @@ public:
private:
uint16_t chip_id; // per-instance MACE Chip ID
uint8_t addr_cfg = 0;
uint8_t addr_ptr = 0;
uint8_t rcv_fc = 1;
uint8_t biu_ctrl = 0;
uint8_t mac_cfg = 0;
uint64_t phys_addr = 0;
uint64_t log_addr = 0;
// interrupt stuff
uint8_t int_stat = 0;
uint8_t int_mask = 0;
};
#endif // MACE_H

View File

@ -129,6 +129,13 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io/grandcentral"), InterruptCtrl()
// connect Ethernet HW
this->mace = dynamic_cast<MaceController*>(gMachineObj->get_comp_by_name("Mace"));
this->enet_tx_dma = std::unique_ptr<DMAChannel> (new DMAChannel("mace_enet_tx"));
this->enet_tx_dma->register_dma_int(this, this->register_dma_int(IntSrc::DMA_ETHERNET_Tx));
this->enet_rx_dma = std::unique_ptr<DMAChannel> (new DMAChannel("mace_enet_rx"));
this->enet_rx_dma->register_dma_int(this, this->register_dma_int(IntSrc::DMA_ETHERNET_Rx));
this->enet_tx_dma->connect(this->mace);
this->enet_rx_dma->connect(this->mace);
this->mace->connect(this->enet_rx_dma.get());
// connect floppy disk HW
this->swim3 = dynamic_cast<Swim3::Swim3Ctrl*>(gMachineObj->get_comp_by_name("Swim3"));
@ -221,6 +228,10 @@ uint32_t GrandCentral::read(uint32_t rgn_start, uint32_t offset, int size)
return this->curio_dma->reg_read(offset & 0xFF, size);
case MIO_GC_DMA_FLOPPY:
return this->floppy_dma->reg_read(offset & 0xFF, size);
case MIO_GC_DMA_ETH_XMIT:
return this->enet_tx_dma->reg_read(offset & 0xFF, size);
case MIO_GC_DMA_ETH_RCV:
return this->enet_rx_dma->reg_read(offset & 0xFF, size);
case MIO_GC_DMA_ESCC_A_XMIT:
return this->escc_a_tx_dma->reg_read(offset & 0xFF, size);
case MIO_GC_DMA_ESCC_A_RCV:
@ -337,6 +348,12 @@ void GrandCentral::write(uint32_t rgn_start, uint32_t offset, uint32_t value, in
case MIO_GC_DMA_FLOPPY:
this->floppy_dma->reg_write(offset & 0xFF, value, size);
break;
case MIO_GC_DMA_ETH_XMIT:
this->enet_tx_dma->reg_write(offset & 0xFF, value, size);
break;
case MIO_GC_DMA_ETH_RCV:
this->enet_rx_dma->reg_write(offset & 0xFF, value, size);
break;
case MIO_GC_DMA_ESCC_A_XMIT:
this->escc_a_tx_dma->reg_write(offset & 0xFF, value, size);
break;

View File

@ -175,9 +175,9 @@ private:
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
std::unique_ptr<MeshStub> mesh_stub = nullptr;
MaceController* mace;
MaceController* mace; // Ethernet cell within Curio
ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it
EsccController* escc; // ESCC serial controller
EsccController* escc; // ESCC serial controller cell within Curio
MeshBase* mesh; // internal SCSI (fast)
Sc53C94* curio; // external SCSI (slow)
Swim3::Swim3Ctrl* swim3; // floppy disk controller
@ -187,6 +187,8 @@ private:
std::unique_ptr<DMAChannel> snd_out_dma;
std::unique_ptr<DMAChannel> snd_in_dma;
std::unique_ptr<DMAChannel> floppy_dma;
std::unique_ptr<DMAChannel> enet_tx_dma;
std::unique_ptr<DMAChannel> enet_rx_dma;
std::unique_ptr<DMAChannel> escc_a_tx_dma;
std::unique_ptr<DMAChannel> escc_a_rx_dma;
std::unique_ptr<DMAChannel> escc_b_tx_dma;