diff --git a/devices/ioctrl/amic.cpp b/devices/ioctrl/amic.cpp
index 3f671db..0dbade5 100644
--- a/devices/ioctrl/amic.cpp
+++ b/devices/ioctrl/amic.cpp
@@ -24,6 +24,7 @@ along with this program. If not, see .
Author: Max Poliakovski
*/
+#include
#include
#include
#include
@@ -46,19 +47,12 @@ AMIC::AMIC() : MMIODevice()
{
this->name = "Apple Memory-mapped I/O Controller";
- MemCtrlBase *mem_ctrl = dynamic_cast
- (gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
-
- /* add memory mapped I/O region for the AMIC control registers */
- if (!mem_ctrl->add_mmio_region(0x50F00000, 0x00040000, this)) {
- LOG_F(ERROR, "Couldn't register AMIC registers!");
- }
-
// register I/O devices
this->scsi = std::unique_ptr (new Ncr53C94());
this->escc = std::unique_ptr (new EsccController());
this->mace = std::unique_ptr (new MaceController(MACE_ID));
this->viacuda = std::unique_ptr (new ViaCuda());
+ gMachineObj->add_subdevice("ViaCuda", this->viacuda.get());
// initialize sound HW
this->snd_out_dma = std::unique_ptr (new AmicSndOutDma());
@@ -73,6 +67,26 @@ AMIC::AMIC() : MMIODevice()
this->swim3 = std::unique_ptr (new Swim3::Swim3Ctrl());
}
+int AMIC::device_postinit()
+{
+ MemCtrlBase *mem_ctrl = dynamic_cast
+ (gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
+
+ // add memory mapped I/O region for the AMIC control registers
+ if (!mem_ctrl->add_mmio_region(0x50F00000, 0x00040000, this)) {
+ LOG_F(ERROR, "Couldn't register AMIC registers!");
+ }
+
+ // AMIC drives the VIA CA1 internally to generate 60.15 Hz interrupts
+ this->pseudo_vbl_tid = TimerManager::get_instance()->add_cyclic_timer(
+ static_cast((1.0f/60.15) * NS_PER_SEC + 0.5f),
+ [this]() {
+ this->viacuda->assert_ctrl_line(ViaLine::CA1);
+ });
+
+ return 0;
+}
+
uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
{
uint32_t phase_val;
diff --git a/devices/ioctrl/amic.h b/devices/ioctrl/amic.h
index 8373ab6..defd5b7 100644
--- a/devices/ioctrl/amic.h
+++ b/devices/ioctrl/amic.h
@@ -142,10 +142,13 @@ public:
AMIC();
~AMIC() = default;
+ // HWComponent methods
bool supports_type(HWCompType type) {
return (type == HWCompType::MMIO_DEV) || (type == HWCompType::INT_CTRL);
};
+ int device_postinit();
+
/* MMIODevice methods */
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
@@ -168,6 +171,8 @@ private:
uint8_t int_ctrl = 0;
uint8_t dev_irq_lines = 0; // state of the IRQ lines
+ uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer
+
// AMIC subdevices instances
std::unique_ptr scsi;
std::unique_ptr escc;