mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-24 12:30:05 +00:00
Improve MACE stub.
This commit is contained in:
parent
bda85a66df
commit
211f8adc0e
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-22 divingkatae and maximum
|
Copyright (C) 2018-24 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(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)
|
uint8_t MaceController::read(uint8_t reg_offset)
|
||||||
{
|
{
|
||||||
switch(reg_offset) {
|
switch(reg_offset) {
|
||||||
case MaceReg::Interrupt:
|
case MaceReg::Rcv_Frame_Ctrl:
|
||||||
LOG_F(INFO, "MACE: all interrupt flags cleared");
|
return this->rcv_fc;
|
||||||
return 0;
|
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:
|
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;
|
return 0;
|
||||||
@ -45,15 +58,57 @@ uint8_t MaceController::read(uint8_t reg_offset)
|
|||||||
void MaceController::write(uint8_t reg_offset, uint8_t value)
|
void MaceController::write(uint8_t reg_offset, uint8_t value)
|
||||||
{
|
{
|
||||||
switch(reg_offset) {
|
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:
|
case MaceReg::BIU_Config_Ctrl:
|
||||||
if (value & 1) {
|
if (value & BIU_SWRST) {
|
||||||
LOG_F(INFO, "MACE Reset issued");
|
LOG_F(INFO, "%s: soft reset asserted", this->name.c_str());
|
||||||
} else {
|
value &= ~BIU_SWRST; // acknowledge soft reset
|
||||||
LOG_F(INFO, "MACE BIU Config set to 0x%X", value);
|
}
|
||||||
|
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;
|
break;
|
||||||
default:
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||||
Copyright (C) 2018-22 divingkatae and maximum
|
Copyright (C) 2018-24 divingkatae and maximum
|
||||||
(theweirdo) spatium
|
(theweirdo) spatium
|
||||||
|
|
||||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
(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
|
#ifndef MACE_H
|
||||||
#define MACE_H
|
#define MACE_H
|
||||||
|
|
||||||
|
#include <devices/common/dmacore.h>
|
||||||
#include <devices/common/hwcomponent.h>
|
#include <devices/common/hwcomponent.h>
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// MACE Chip ID from AMD datasheet
|
/** Known MACE chip IDs. */
|
||||||
// TODO: compare with real HW
|
#define MACE_ID_REV_B0 0x0940 // Darwin-0.3 source
|
||||||
#define MACE_ID 0x3940
|
#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
|
// Refer to the Am79C940 datasheet for details
|
||||||
namespace MaceEnet {
|
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 {
|
/** Bit definitions for BIU_Config_Ctrl register. */
|
||||||
Rcv_FIFO = 0,
|
enum {
|
||||||
Xmit_FIFO = 1,
|
BIU_SWRST = 1 << 0,
|
||||||
Xmit_Frame_Ctrl = 2,
|
};
|
||||||
Xmit_Frame_Stat = 3,
|
|
||||||
Xmit_Retry_Cnt = 4,
|
/** Bit definitions for the internal configuration register. */
|
||||||
Rcv_Frame_Ctrl = 5,
|
enum {
|
||||||
Rcv_Frame_Stat = 6,
|
IAC_LOGADDR = 1 << 1,
|
||||||
FIFO_Frame_Cnt = 7,
|
IAC_PHYADDR = 1 << 2,
|
||||||
Interrupt = 8,
|
IAC_ADDRCHG = 1 << 7
|
||||||
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?
|
|
||||||
};
|
|
||||||
|
|
||||||
}; // namespace MaceEnet
|
}; // namespace MaceEnet
|
||||||
|
|
||||||
class MaceController : public HWComponent {
|
class MaceController : public DmaDevice, public HWComponent {
|
||||||
public:
|
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;
|
~MaceController() = default;
|
||||||
|
|
||||||
static std::unique_ptr<HWComponent> create() {
|
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
|
// MACE registers access
|
||||||
@ -84,6 +100,17 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t chip_id; // per-instance MACE Chip ID
|
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
|
#endif // MACE_H
|
||||||
|
@ -129,6 +129,13 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io/grandcentral"), InterruptCtrl()
|
|||||||
|
|
||||||
// connect Ethernet HW
|
// connect Ethernet HW
|
||||||
this->mace = dynamic_cast<MaceController*>(gMachineObj->get_comp_by_name("Mace"));
|
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
|
// connect floppy disk HW
|
||||||
this->swim3 = dynamic_cast<Swim3::Swim3Ctrl*>(gMachineObj->get_comp_by_name("Swim3"));
|
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);
|
return this->curio_dma->reg_read(offset & 0xFF, size);
|
||||||
case MIO_GC_DMA_FLOPPY:
|
case MIO_GC_DMA_FLOPPY:
|
||||||
return this->floppy_dma->reg_read(offset & 0xFF, size);
|
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:
|
case MIO_GC_DMA_ESCC_A_XMIT:
|
||||||
return this->escc_a_tx_dma->reg_read(offset & 0xFF, size);
|
return this->escc_a_tx_dma->reg_read(offset & 0xFF, size);
|
||||||
case MIO_GC_DMA_ESCC_A_RCV:
|
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:
|
case MIO_GC_DMA_FLOPPY:
|
||||||
this->floppy_dma->reg_write(offset & 0xFF, value, size);
|
this->floppy_dma->reg_write(offset & 0xFF, value, size);
|
||||||
break;
|
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:
|
case MIO_GC_DMA_ESCC_A_XMIT:
|
||||||
this->escc_a_tx_dma->reg_write(offset & 0xFF, value, size);
|
this->escc_a_tx_dma->reg_write(offset & 0xFF, value, size);
|
||||||
break;
|
break;
|
||||||
|
@ -175,9 +175,9 @@ private:
|
|||||||
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
|
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
|
||||||
std::unique_ptr<MeshStub> mesh_stub = nullptr;
|
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
|
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)
|
MeshBase* mesh; // internal SCSI (fast)
|
||||||
Sc53C94* curio; // external SCSI (slow)
|
Sc53C94* curio; // external SCSI (slow)
|
||||||
Swim3::Swim3Ctrl* swim3; // floppy disk controller
|
Swim3::Swim3Ctrl* swim3; // floppy disk controller
|
||||||
@ -187,6 +187,8 @@ private:
|
|||||||
std::unique_ptr<DMAChannel> snd_out_dma;
|
std::unique_ptr<DMAChannel> snd_out_dma;
|
||||||
std::unique_ptr<DMAChannel> snd_in_dma;
|
std::unique_ptr<DMAChannel> snd_in_dma;
|
||||||
std::unique_ptr<DMAChannel> floppy_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_tx_dma;
|
||||||
std::unique_ptr<DMAChannel> escc_a_rx_dma;
|
std::unique_ptr<DMAChannel> escc_a_rx_dma;
|
||||||
std::unique_ptr<DMAChannel> escc_b_tx_dma;
|
std::unique_ptr<DMAChannel> escc_b_tx_dma;
|
||||||
|
Loading…
Reference in New Issue
Block a user