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;