diff --git a/devices/common/ata/idechannel.cpp b/devices/common/ata/idechannel.cpp
index ca8c371..9488886 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)
-{
- if (reg_addr == TIME_CONFIG) {
- if (size != 4) {
- LOG_F(WARNING, "%s: non-DWORD read from the channel config", this->name.c_str());
- }
- return this->ch_config;
- } else {
- return this->devices[this->cur_dev]->read(reg_addr);
- }
+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)
{
- if (reg_addr == TIME_CONFIG) {
- if (size != 4) {
- LOG_F(WARNING, "%s: non-DWORD write to the channel 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;
- }
+ // 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);
- }
+ // 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 TIME_CONFIG", this->name.c_str());
+ }
+ return this->ch_config;
+ } else
+ return IdeChannel::read(reg_addr, 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 TIME_CONFIG", this->name.c_str());
+ }
+ this->ch_config = 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 1460837..427c49b 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 @@ public:
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 @@ public:
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 report_intrq(uint8_t intrq_state) {
- this->int_ctrl->ack_int(this->irq_id, intrq_state);
+ void set_irq_callback(std::function cb) {
+ this->irq_callback = cb;
}
+ void report_intrq(uint8_t 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
- InterruptCtrl* int_ctrl = nullptr;
- uint32_t irq_id = 0;
-
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;
+};
+
#endif // IDE_CHANNEL_H