diff --git a/devices/common/ata/idechannel.cpp b/devices/common/ata/idechannel.cpp
index ca8c37131..948888632 100644
--- a/devices/common/ata/idechannel.cpp
+++ b/devices/common/ata/idechannel.cpp
@@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
-Copyright (C) 2018-23 divingkatae and maximum
+Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@@ -22,8 +22,12 @@ along with this program. If not, see .
/** IDE Channel (aka IDE port) emulation.
One IDE channel is capable of controlling up to two IDE devices.
- This class handles device registration and passing of messages
+
+ IdeChannel class handles device registration and passing of messages
from and to the host.
+
+ MacioIdeChannel class implements MacIO specific registers
+ and interrupt handling.
*/
#include
@@ -51,15 +55,6 @@ IdeChannel::IdeChannel(const std::string name)
this->devices[1] = this->device_stub.get();
}
-int IdeChannel::device_postinit() {
- this->int_ctrl = dynamic_cast(
- gMachineObj->get_comp_by_type(HWCompType::INT_CTRL));
- this->irq_id = this->int_ctrl->register_dev_int(
- this->name == "IDE0" ? IntSrc::IDE0 : IntSrc::IDE1);
-
- return 0;
-}
-
void IdeChannel::register_device(int id, AtaInterface* dev_obj) {
if (id < 0 || id >= 2)
ABORT_F("%s: invalid device ID", this->name.c_str());
@@ -69,44 +64,64 @@ void IdeChannel::register_device(int id, AtaInterface* dev_obj) {
((AtaBaseDevice*)dev_obj)->set_host(this, id);
}
-uint32_t IdeChannel::read(const uint8_t reg_addr, const int size)
+uint32_t IdeChannel::read(const uint8_t reg_addr, const int size) {
+ return this->devices[this->cur_dev]->read(reg_addr);
+}
+
+void IdeChannel::write(const uint8_t reg_addr, const uint32_t val, const int size)
+{
+ // keep track of the currently selected device
+ if (reg_addr == DEVICE_HEAD) {
+ this->cur_dev = (val >> 4) & 1;
+ }
+
+ // redirect register writes to both devices
+ for (auto& dev : this->devices) {
+ dev->write(reg_addr, val);
+ }
+}
+
+int MacioIdeChannel::device_postinit() {
+ this->int_ctrl = dynamic_cast(
+ gMachineObj->get_comp_by_type(HWCompType::INT_CTRL));
+ this->irq_id = this->int_ctrl->register_dev_int(
+ this->name == "IDE0" ? IntSrc::IDE0 : IntSrc::IDE1);
+
+ this->irq_callback = [this](const uint8_t intrq_state) {
+ this->int_ctrl->ack_int(this->irq_id, intrq_state);
+ };
+
+ return 0;
+}
+
+uint32_t MacioIdeChannel::read(const uint8_t reg_addr, const int size)
{
if (reg_addr == TIME_CONFIG) {
if (size != 4) {
- LOG_F(WARNING, "%s: non-DWORD read from the channel config", this->name.c_str());
+ LOG_F(WARNING, "%s: non-DWORD read from TIME_CONFIG", this->name.c_str());
}
return this->ch_config;
- } else {
- return this->devices[this->cur_dev]->read(reg_addr);
- }
+ } else
+ return IdeChannel::read(reg_addr, size);
}
-void IdeChannel::write(const uint8_t reg_addr, const uint32_t val, const int size)
+void MacioIdeChannel::write(const uint8_t reg_addr, const uint32_t val, const int size)
{
if (reg_addr == TIME_CONFIG) {
if (size != 4) {
- LOG_F(WARNING, "%s: non-DWORD write to the channel config", this->name.c_str());
+ LOG_F(WARNING, "%s: non-DWORD write to TIME_CONFIG", this->name.c_str());
}
this->ch_config = val;
- } else {
- // keep track of the currently selected device
- if (reg_addr == DEVICE_HEAD) {
- this->cur_dev = (val >> 4) & 1;
- }
-
- // redirect register writes to both devices
- for (auto& dev : this->devices) {
- dev->write(reg_addr, val);
- }
- }
+ } else
+ IdeChannel::write(reg_addr, val, size);
}
static const DeviceDescription Ide0_Descriptor = {
- IdeChannel::create_first, {}, {}
+ MacioIdeChannel::create_first, {}, {}
};
static const DeviceDescription Ide1_Descriptor = {
- IdeChannel::create_second, {}, {}
+ MacioIdeChannel::create_second, {}, {}
};
REGISTER_DEVICE(Ide0, Ide0_Descriptor);
diff --git a/devices/common/ata/idechannel.h b/devices/common/ata/idechannel.h
index 14608377e..427c49be8 100644
--- a/devices/common/ata/idechannel.h
+++ b/devices/common/ata/idechannel.h
@@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
-Copyright (C) 2018-23 divingkatae and maximum
+Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@@ -29,6 +29,7 @@ along with this program. If not, see .
#include
#include
+#include
#include
#include
@@ -38,16 +39,6 @@ class IdeChannel : public HWComponent
IdeChannel(const std::string name);
~IdeChannel() = default;
- static std::unique_ptr create_first() {
- return std::unique_ptr(new IdeChannel("IDE0"));
- }
-
- static std::unique_ptr create_second() {
- return std::unique_ptr(new IdeChannel("IDE1"));
- }
-
- int device_postinit() override;
-
void register_device(int id, AtaInterface* dev_obj);
uint32_t read(const uint8_t reg_addr, const int size);
@@ -55,26 +46,56 @@ class IdeChannel : public HWComponent
void assert_pdiag() {
this->devices[0]->pdiag_callback();
- };
+ }
bool is_device1_present() {
return this->devices[1]->get_device_id() != ata_interface::DEVICE_ID_INVALID;
}
+ void set_irq_callback(std::function cb) {
+ this->irq_callback = cb;
+ }
+
void report_intrq(uint8_t intrq_state) {
- this->int_ctrl->ack_int(this->irq_id, intrq_state);
+ this->irq_callback(intrq_state);
}
+protected:
+ std::function irq_callback = nullptr;
+
private:
int cur_dev = 0;
- uint32_t ch_config = 0; // timing configuration for this channel
AtaInterface* devices[2];
- // interrupt related stuff
+ std::unique_ptr device_stub;
+};
+
+/** This class models an IDE channel specific to MacIO ASICs. */
+class MacioIdeChannel : public IdeChannel
+{
+public:
+ MacioIdeChannel(const std::string name) : IdeChannel(name) {};
+ ~MacioIdeChannel() = default;
+
+ static std::unique_ptr create_first() {
+ return std::unique_ptr(new MacioIdeChannel("IDE0"));
+ }
+
+ static std::unique_ptr create_second() {
+ return std::unique_ptr(new MacioIdeChannel("IDE1"));
+ }
+
+ int device_postinit() override;
+
+ uint32_t read(const uint8_t reg_addr, const int size);
+ void write(const uint8_t reg_addr, const uint32_t val, const int size);
+
+private:
+ uint32_t ch_config = 0; // timing configuration for this channel
+
+ // interrupt stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
-
- std::unique_ptr device_stub;
};
#endif // IDE_CHANNEL_H