mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-05 10:30:28 +00:00
idechannel: split MacIO specific stuff into a separate class.
Now we got two classes: IdeChannel and MacioIdeChannel. The former models a generic IDE channel so it can be used elsewhere. The latter implements MacIO specific configuration register(s) and interrupt signaling.
This commit is contained in:
parent
4e78ac33c5
commit
f5c91968a2
@ -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 <https://www.gnu.org/licenses/>.
|
||||
/** 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 <devices/common/ata/atabasedevice.h>
|
||||
@ -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<InterruptCtrl*>(
|
||||
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<InterruptCtrl*>(
|
||||
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);
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
#include <devices/common/hwinterrupt.h>
|
||||
|
||||
#include <cinttypes>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@ -38,16 +39,6 @@ public:
|
||||
IdeChannel(const std::string name);
|
||||
~IdeChannel() = default;
|
||||
|
||||
static std::unique_ptr<HWComponent> create_first() {
|
||||
return std::unique_ptr<IdeChannel>(new IdeChannel("IDE0"));
|
||||
}
|
||||
|
||||
static std::unique_ptr<HWComponent> create_second() {
|
||||
return std::unique_ptr<IdeChannel>(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<void(const uint8_t intrq_state)> cb) {
|
||||
this->irq_callback = cb;
|
||||
}
|
||||
|
||||
void report_intrq(uint8_t intrq_state) {
|
||||
this->irq_callback(intrq_state);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<void(const uint8_t intrq_state)> 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<AtaInterface> 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<HWComponent> create_first() {
|
||||
return std::unique_ptr<IdeChannel>(new MacioIdeChannel("IDE0"));
|
||||
}
|
||||
|
||||
static std::unique_ptr<HWComponent> create_second() {
|
||||
return std::unique_ptr<IdeChannel>(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
|
||||
|
Loading…
Reference in New Issue
Block a user