diff options
| -rw-r--r-- | arch/x86_64/arch/bus/isa.cpp | 29 | ||||
| -rw-r--r-- | arch/x86_64/arch/bus/isa.hpp | 35 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/init.cpp | 10 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/legacy_pit.cpp | 85 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/legacy_pit.hpp | 48 | ||||
| -rw-r--r-- | kapi/kapi/devices/bus.hpp | 2 | ||||
| -rw-r--r-- | kapi/kapi/devices/driver.hpp | 10 | ||||
| -rw-r--r-- | kernel/kapi/devices/bus.cpp | 4 | ||||
| -rw-r--r-- | kernel/kernel/devices/storage/ram_disk/controller.cpp | 2 | ||||
| -rw-r--r-- | kernel/kernel/devices/storage/ram_disk/controller.hpp | 2 |
10 files changed, 199 insertions, 28 deletions
diff --git a/arch/x86_64/arch/bus/isa.cpp b/arch/x86_64/arch/bus/isa.cpp index dd248f76..573feb72 100644 --- a/arch/x86_64/arch/bus/isa.cpp +++ b/arch/x86_64/arch/bus/isa.cpp @@ -2,6 +2,11 @@ #include <kapi/devices.hpp> +#include <kstd/result.hpp> + +#include <algorithm> +#include <cstdint> + namespace arch::bus { @@ -9,4 +14,28 @@ namespace arch::bus : kapi::devices::bus{"isa"} {} + auto isa::enumerate(kapi::devices::bus &) -> void + { + // NOTE: ISA does not support enumeration, but we need to fulfill the interface. + } + + auto isa::match(kapi::devices::device const & device, kapi::devices::driver const & driver) const + -> kstd::result<std::uint32_t> + { + auto identification = device.as<isa_identification>(); + auto claims = driver.as<isa_driver_identification>(); + + if (!identification || !claims || !std::ranges::contains(claims->supported_names(), identification->isa_name())) + { + return kstd::failure(kapi::devices::driver_match_errc::no_match); + } + + return 0u; + } + + auto isa::protocol() -> kapi::devices::bus_protocol * + { + return this; + } + } // namespace arch::bus
\ No newline at end of file diff --git a/arch/x86_64/arch/bus/isa.hpp b/arch/x86_64/arch/bus/isa.hpp index 5741a640..a09127dd 100644 --- a/arch/x86_64/arch/bus/isa.hpp +++ b/arch/x86_64/arch/bus/isa.hpp @@ -1,14 +1,45 @@ #ifndef TEACHOS_X86_64_BUS_ISA_HPP #define TEACHOS_X86_64_BUS_ISA_HPP -#include <kapi/devices/bus.hpp> +#include <kapi/devices.hpp> + +#include <kstd/result.hpp> + +#include <cstdint> +#include <span> +#include <string_view> namespace arch::bus { - struct isa final : public kapi::devices::bus + struct isa_identification + { + constexpr auto static id = kapi::devices::interface{"isa_identification"}; + + virtual ~isa_identification() = default; + + [[nodiscard]] virtual auto isa_name() const -> std::string_view = 0; + }; + + struct isa_driver_identification + { + constexpr auto static id = kapi::devices::interface{"isa_driver_identification"}; + + virtual ~isa_driver_identification() = default; + + [[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0; + }; + + struct isa final : public kapi::devices::bus, kapi::devices::bus_protocol { isa(); + + auto enumerate(kapi::devices::bus & self) -> void override; + + [[nodiscard]] auto match(kapi::devices::device const & device, kapi::devices::driver const & driver) const + -> kstd::result<std::uint32_t> override; + + [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override; }; } // namespace arch::bus diff --git a/arch/x86_64/arch/devices/init.cpp b/arch/x86_64/arch/devices/init.cpp index 2c4fb3c3..f6adcbcf 100644 --- a/arch/x86_64/arch/devices/init.cpp +++ b/arch/x86_64/arch/devices/init.cpp @@ -7,6 +7,7 @@ #include <kapi/acpi.hpp> #include <kapi/cpu.hpp> #include <kapi/devices.hpp> +#include <kapi/devices/driver_registry.hpp> #include <acpi/acpi.hpp> @@ -14,7 +15,6 @@ #include <kstd/print.hpp> #include <cstdint> -#include <utility> namespace arch::devices { @@ -63,12 +63,12 @@ namespace arch::devices kstd::println("[x86_64:DEV] Initializing ISA bus..."); auto isa_bus = kstd::make_shared<arch::bus::isa>(); + auto root_bus = kapi::devices::get_root_bus(); - auto pit = kstd::make_shared<arch::devices::legacy_pit>(pit_frequency_in_hz); - isa_bus->add_child(std::move(pit)); + root_bus->add_child(isa_bus); - auto root_bus = kapi::devices::get_root_bus(); - root_bus->add_child(std::move(isa_bus)); + kapi::devices::driver_registry::get().add(kstd::make_shared<pit_driver>(pit_frequency_in_hz)); + isa_bus->add_child(kstd::make_shared<pit_device>()); } } // namespace arch::devices diff --git a/arch/x86_64/arch/devices/legacy_pit.cpp b/arch/x86_64/arch/devices/legacy_pit.cpp index d93b38fd..5e968a6b 100644 --- a/arch/x86_64/arch/devices/legacy_pit.cpp +++ b/arch/x86_64/arch/devices/legacy_pit.cpp @@ -1,16 +1,25 @@ #include <arch/devices/legacy_pit.hpp> +#include <arch/bus/isa.hpp> #include <arch/device_io/port_io.hpp> #include <kapi/devices.hpp> #include <kapi/devices/device.hpp> #include <kapi/interrupts.hpp> +#include <kstd/memory.hpp> +#include <kstd/result.hpp> + +#include <array> #include <cstdint> +#include <span> +#include <string_view> namespace arch::devices { + using namespace std::string_view_literals; + namespace { using command_port = io::port<0x43, std::uint8_t, io::port_write>; @@ -20,19 +29,46 @@ namespace arch::devices constexpr auto base_frequency = 1'193'182u; constexpr auto square_wave_mode = 0x36; + + constexpr auto pit_names = std::array{"pit"sv}; } // namespace - legacy_pit::legacy_pit(std::uint32_t frequency_in_hz) - : kapi::devices::device{"legacy_pit"} - , m_irq_number{0} - , m_frequency_in_hz{frequency_in_hz} + pit_device::pit_device() + : device{"legacy_pit"} + {} + + auto pit_device::isa_name() const -> std::string_view + { + return "pit"; + } + + auto pit_device::init() -> bool + { + return true; + } + + auto pit_device::query_interface(kapi::devices::interface interface) -> void * + { + if (interface == arch::bus::isa_identification::id) + { + return static_cast<arch::bus::isa_identification *>(this); + } + + return kapi::devices::device::query_interface(interface); + } + + pit_driver::pit_driver(std::uint32_t frequency_in_hz) + : m_frequency_in_hz{frequency_in_hz} {} - auto legacy_pit::init() -> bool + auto pit_driver::probe(kapi::devices::device & device) -> kstd::result<void> { - auto divisor = static_cast<std::uint16_t>(base_frequency / m_frequency_in_hz); + auto data = kstd::make_shared<driver_data>(0, m_frequency_in_hz, 0); + device.set_driver_data(data); - kapi::interrupts::register_handler(m_irq_number, *this); + auto divisor = static_cast<std::uint16_t>(base_frequency / data->frequency_in_hz); + + kapi::interrupts::register_handler(data->irq_number, *this); command_port::write<std::uint8_t>(square_wave_mode); io::wait(); @@ -41,19 +77,46 @@ namespace arch::devices channel_0_port::write<std::uint8_t>(divisor >> 8 & 0xff); io::wait(); - return true; + return kstd::success(); } - auto legacy_pit::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status + auto pit_driver::unbind(kapi::devices::device & device) -> void { - if (irq_number != m_irq_number) + auto data = static_pointer_cast<driver_data>(device.driver_data()); + + kapi::interrupts::unregister_handler(data->irq_number, *this); + + device.set_driver_data(nullptr); + } + + auto pit_driver::supported_names() const -> std::span<std::string_view const> + { + return pit_names; + } + + auto pit_driver::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status + { + // auto data = static_pointer_cast<driver_data>(device.driver_data()); + + if (irq_number != 0) { return kapi::interrupts::status::unhandled; } - ++m_ticks; + // TODO: upgrade kapi interrupts to gain access to the device. + // ++m_ticks; return kapi::interrupts::status::handled; } + auto pit_driver::query_interface(kapi::devices::interface interface) -> void * + { + if (interface == arch::bus::isa_driver_identification::id) + { + return static_cast<arch::bus::isa_driver_identification *>(this); + } + + return kapi::devices::driver::query_interface(interface); + } + } // namespace arch::devices
\ No newline at end of file diff --git a/arch/x86_64/arch/devices/legacy_pit.hpp b/arch/x86_64/arch/devices/legacy_pit.hpp index 7a74144e..1bb41e2b 100644 --- a/arch/x86_64/arch/devices/legacy_pit.hpp +++ b/arch/x86_64/arch/devices/legacy_pit.hpp @@ -1,26 +1,64 @@ #ifndef TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP #define TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP -#include <kapi/devices/device.hpp> +#include <arch/bus/isa.hpp> + +#include <kapi/devices.hpp> #include <kapi/interrupts.hpp> +#include <kstd/result.hpp> + #include <cstdint> +#include <span> +#include <string_view> namespace arch::devices { - struct legacy_pit : kapi::devices::device, kapi::interrupts::handler + //! The ISA device for the legacy Programmable Interrupt Timer. + //! + //! This type identifies the PIT device node to the driver, so the driver can be matched successfully. + struct pit_device final : kapi::devices::device, arch::bus::isa_identification { - explicit legacy_pit(std::uint32_t frequency_in_hz); + pit_device(); + // TODO: remove auto init() -> bool override; + //! Get the synthetic ISA identifier for this device. + //! + //! @return the string "pit" + [[nodiscard]] auto isa_name() const -> std::string_view override; + + protected: + auto query_interface(kapi::devices::interface interface) -> void * override; + }; + + //! The driver for the legacy, ISA-connected Programmable Interrupt Timer. + struct pit_driver final : kapi::devices::driver, arch::bus::isa_driver_identification, kapi::interrupts::handler + { + explicit pit_driver(std::uint32_t frequency_in_hz); + + [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result<void> override; + + auto unbind(kapi::devices::device & device) -> void override; + + [[nodiscard]] auto supported_names() const -> std::span<std::string_view const> override; + auto handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status override; + protected: + auto query_interface(kapi::devices::interface interface) -> void * override; + private: - std::uint32_t m_irq_number{}; + struct driver_data + { + std::uint32_t irq_number{}; + std::uint32_t frequency_in_hz{}; + std::uint64_t ticks{}; + }; + std::uint32_t m_frequency_in_hz{}; - std::uint64_t m_ticks{}; }; } // namespace arch::devices diff --git a/kapi/kapi/devices/bus.hpp b/kapi/kapi/devices/bus.hpp index 0e654072..10b9c39d 100644 --- a/kapi/kapi/devices/bus.hpp +++ b/kapi/kapi/devices/bus.hpp @@ -50,7 +50,7 @@ namespace kapi::devices //! Enumerate the devices on the bus. //! //! @return true iff. the bus hardware is healthy, false otherwise. - auto virtual enumerate() -> bool; + auto virtual enumerate_old() -> bool; private: kstd::vector<kstd::shared_ptr<device>> m_devices; diff --git a/kapi/kapi/devices/driver.hpp b/kapi/kapi/devices/driver.hpp index fde5068c..254f7977 100644 --- a/kapi/kapi/devices/driver.hpp +++ b/kapi/kapi/devices/driver.hpp @@ -54,6 +54,16 @@ namespace kapi::devices return static_cast<InterfaceType *>(query_interface(InterfaceType::id)); } + //! Retrieve this drivers implementation of a given capability interface. + //! + //! @return A pointer to this drivers implementation of the requested interface, nullptr if this driver does not + //! support the requested interface. + template<typename InterfaceType> + [[nodiscard]] auto as() const -> InterfaceType const * + { + return static_cast<InterfaceType *>(const_cast<driver *>(this)->query_interface(InterfaceType::id)); + } + //! Check if this driver implements a given capability interface. //! //! @return true iff. this driver implements the requested capability interface, false otherwise. diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp index a63782c3..25e35733 100644 --- a/kernel/kapi/devices/bus.cpp +++ b/kernel/kapi/devices/bus.cpp @@ -27,7 +27,7 @@ namespace kapi::devices return true; } - if (!enumerate()) + if (!enumerate_old()) { kstd::println(kstd::print_sink::stderr, "[OS:DEV] Bus {} enumeration failed", name()); return false; @@ -77,7 +77,7 @@ namespace kapi::devices return nullptr; } - auto bus::enumerate() -> bool + auto bus::enumerate_old() -> bool { return true; } diff --git a/kernel/kernel/devices/storage/ram_disk/controller.cpp b/kernel/kernel/devices/storage/ram_disk/controller.cpp index 07ff702d..7550860e 100644 --- a/kernel/kernel/devices/storage/ram_disk/controller.cpp +++ b/kernel/kernel/devices/storage/ram_disk/controller.cpp @@ -17,7 +17,7 @@ namespace kernel::devices::storage::ram_disk , m_boot_module_registry(registry) {} - auto controller::enumerate() -> bool + auto controller::enumerate_old() -> bool { size_t current_device_index = 0; diff --git a/kernel/kernel/devices/storage/ram_disk/controller.hpp b/kernel/kernel/devices/storage/ram_disk/controller.hpp index b245dc1f..165fbdbd 100644 --- a/kernel/kernel/devices/storage/ram_disk/controller.hpp +++ b/kernel/kernel/devices/storage/ram_disk/controller.hpp @@ -21,7 +21,7 @@ namespace kernel::devices::storage::ram_disk /** * @brief Probe boot modules and create RAM-disk devices. */ - auto enumerate() -> bool override; + auto enumerate_old() -> bool override; private: kapi::boot_modules::boot_module_registry const * m_boot_module_registry; |
