From d452a022cffeab8e273ff330e966b99dabae0e87 Mon Sep 17 00:00:00 2001 From: Jaby Date: Sun, 22 Jan 2023 14:07:58 +0100 Subject: [PATCH] Setup CD drive --- include/PSX/System/IOPorts/cd_io.hpp | 75 ++++++++++++++++---------- src/Library/include/CD/cd_internal.hpp | 24 ++++++++- src/Library/src/BootLoader/cd_boot.cpp | 20 ++++++- src/Library/src/CD/cd.cpp | 32 +++++++++++ 4 files changed, 119 insertions(+), 32 deletions(-) diff --git a/include/PSX/System/IOPorts/cd_io.hpp b/include/PSX/System/IOPorts/cd_io.hpp index 19f46d5a..270999e2 100644 --- a/include/PSX/System/IOPorts/cd_io.hpp +++ b/include/PSX/System/IOPorts/cd_io.hpp @@ -57,34 +57,6 @@ namespace JabyEngine { static constexpr auto ApplyChanges = Bit(5); }; - struct Interrupt { - static void enable(VolatileBitMapPOD& port) { - port.write(InterruptEnable::InterruptTypValue.max()); - } - - static void enable_extended(VolatileBitMapPOD& port) { - port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); - } - - static uint8_t get_type(const VolatileBitMapPOD& port) { - return port.read().get_value(InterruptFlag::InterruptTypValue); - } - - static void ack(VolatileBitMapPOD& port) { - port.write(InterruptFlag::InterruptTypValue.max()); - } - - static void ack_extended(VolatileBitMapPOD& port) { - port.write({InterruptFlag::with(InterruptFlag::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); - } - }; - - __declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800); - - static constexpr auto IORegister1Adr = 0x1F801801; - static constexpr auto IORegister2Adr = 0x1F801802; - static constexpr auto IORegister3Adr = 0x1F801803; - typedef VolatilePOD ResponseFifo_t; typedef VolatilePOD CommandFifo_t; typedef VolatilePOD DataFifo_t; @@ -98,6 +70,53 @@ namespace JabyEngine { typedef VolatileBitMapPOD SoundMapCodingInfo_t; typedef VolatileBitMapPOD AudioVolumeApplyChange_t; + struct Interrupt { + enum Type : uint8_t { + None = 0, + DataReady = 1, + Complete = 2, + Acknowledge = 3, + DataEnd = 4, + DiskError = 5 + }; + + static void enable(InterruptEnableRegister_t& port) { + port.write(InterruptEnable::InterruptTypValue.max()); + } + + static void enable_extended(InterruptEnableRegister_t& port) { + port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); + } + + static Type get_type(const InterruptFlagRegister_t& port) { + return static_cast(port.read().get_value(InterruptFlag::InterruptTypValue)); + } + + static void ack(InterruptFlagRegister_t& port) { + port.write(InterruptFlag::InterruptTypValue.max()); + } + + static void ack_extended(InterruptFlagRegister_t& port) { + port.write({InterruptFlag::with(InterruptFlag::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); + } + }; + + struct Command { + struct Info { + uint8_t id; + Interrupt::Type complete_irq; + }; + + static constexpr Info GetStat{0x1, Interrupt::Type::Acknowledge}; + static constexpr Info Init{0xA, Interrupt::Type::Complete}; + }; + + static constexpr auto IORegister1Adr = 0x1F801801; + static constexpr auto IORegister2Adr = 0x1F801802; + static constexpr auto IORegister3Adr = 0x1F801803; + + __declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800); + #define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr) #define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr) diff --git a/src/Library/include/CD/cd_internal.hpp b/src/Library/include/CD/cd_internal.hpp index 51ef7239..08b9900a 100644 --- a/src/Library/include/CD/cd_internal.hpp +++ b/src/Library/include/CD/cd_internal.hpp @@ -1,11 +1,31 @@ #ifndef __JABYENGINE_CD_INTERNAL_HPP__ #define __JABYENGINE_CD_INTERNAL_HPP__ -#include +#include namespace JabyEngine { namespace CD { namespace internal { - + extern VolatilePOD last_interrupt; + + struct Command { + static void wait_until(CD_IO::Interrupt::Type irq) { + while(last_interrupt.read() != irq); + } + + template + static void send(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { + while(CD_IO::IndexStatus.read().is_bit_set(CD_IO::IndexStatus::IsTransmissionBusy)); + + (parameter_fifo.write(static_cast(args)), ...); + cmd_fifo.write(cmd.id); + } + + template + static void send_wait(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { + send(cmd_fifo, parameter_fifo, cmd, args...); + wait_until(cmd.complete_irq); + } + }; } } } diff --git a/src/Library/src/BootLoader/cd_boot.cpp b/src/Library/src/BootLoader/cd_boot.cpp index e4c44fb7..66a79fe2 100644 --- a/src/Library/src/BootLoader/cd_boot.cpp +++ b/src/Library/src/BootLoader/cd_boot.cpp @@ -1,18 +1,25 @@ #include "../../include/BootLoader/boot_loader.hpp" -#include +#include "../../include/CD/cd_internal.hpp" #include #include #include namespace JabyEngine { + namespace CD { + namespace internal { + extern InterrupCallback callback; + } + } namespace boot { namespace CD { + using JabyEngine::CD::internal::Command; + void setup() { __syscall_EnterCriticalSection(); Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::SetupValue); Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::SetupValue); - //Equeue Callback? + __syscall_SysEnqIntRP(CdromIoIrq, &::JabyEngine::CD::internal::callback); CD_IO::PortIndex1::change_to(); CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlagRegister); @@ -21,6 +28,15 @@ namespace JabyEngine { Interrupt::ack_irq(Interrupt::CDROM); Interrupt::enable_irq(Interrupt::CDROM); __syscall_ExitCriticalSection(); + + + CD_IO::PortIndex0::change_to(); + + Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat); + Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat); + Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::Init); + + // Demute? } } } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index 43a6f3b5..c334f9e1 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -1,8 +1,40 @@ #include "../../include/CD/cd_internal.hpp" +#include +#include namespace JabyEngine { namespace CD { namespace internal { + VolatilePOD last_interrupt{CD_IO::Interrupt::Type::None}; + + static InterruptVerifierResult interrupt_verifier() { + if(Interrupt::is_irq(Interrupt::CDROM)) { + const uint8_t old_idx = (CD_IO::IndexStatus.read() & 0x3); + + CD_IO::PortIndex1::change_to(); + + last_interrupt.write(CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlagRegister)); + CD_IO::Interrupt::ack(CD_IO::PortIndex1::InterruptFlagRegister); + + CD_IO::IndexStatus.write({old_idx}); + return InterruptVerifierResult::ExecuteHandler; + } + + else { + return InterruptVerifierResult::SkipHandler; + } + } + + static void interrupt_handler(uint32_t) { + Interrupt::ack_irq(Interrupt::CDROM); + __syscall_ReturnFromException(); + } + + InterrupCallback callback = { + .next = nullptr, + .handler_function = reinterpret_cast(interrupt_handler), + .verifier_function = interrupt_verifier + }; } } } \ No newline at end of file