diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-27 18:09:27 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-27 18:09:27 +0200 |
| commit | b5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb (patch) | |
| tree | 0ae6e86cccf1f25e33b8fbd311d597b9326e54c2 | |
| parent | 1121cb81d66b704c7528356f450acffba4c0f62f (diff) | |
| download | kernel-b5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb.tar.xz kernel-b5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb.zip | |
x86_64: port PIT to devices resources
| -rw-r--r-- | arch/x86_64/arch/debug/qemu_output.hpp | 2 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/init.cpp | 7 | ||||
| -rw-r--r-- | arch/x86_64/arch/drivers/pit.cpp | 33 | ||||
| -rw-r--r-- | arch/x86_64/arch/io/port_io.hpp (renamed from arch/x86_64/arch/device_io/port_io.hpp) | 53 | ||||
| -rw-r--r-- | kapi/kapi/devices.hpp | 1 | ||||
| -rw-r--r-- | kapi/kapi/devices/resource.hpp | 2 | ||||
| -rw-r--r-- | kernel/kapi/devices/device.cpp | 3 |
7 files changed, 88 insertions, 13 deletions
diff --git a/arch/x86_64/arch/debug/qemu_output.hpp b/arch/x86_64/arch/debug/qemu_output.hpp index 5ddd4be3..27898395 100644 --- a/arch/x86_64/arch/debug/qemu_output.hpp +++ b/arch/x86_64/arch/debug/qemu_output.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_X86_64_DEBUG_QEMU_OUTPUT_HPP #define TEACHOS_X86_64_DEBUG_QEMU_OUTPUT_HPP -#include <arch/device_io/port_io.hpp> +#include <arch/io/port_io.hpp> #include <kapi/cio.hpp> diff --git a/arch/x86_64/arch/devices/init.cpp b/arch/x86_64/arch/devices/init.cpp index 03d082f6..e73ffa59 100644 --- a/arch/x86_64/arch/devices/init.cpp +++ b/arch/x86_64/arch/devices/init.cpp @@ -62,7 +62,12 @@ namespace arch::devices auto isa_bus = kstd::make_shared<arch::bus::isa>(); root_bus->add_child(isa_bus); - isa_bus->add_child(kstd::make_shared<pit>()); + auto pit_device = kstd::make_shared<pit>(); + pit_device->set_resources({ + kapi::devices::resource{kapi::devices::io_port{.start = 0x40, .count = 4}}, + kapi::devices::resource{kapi::devices::interrupt_line{.number = 0}}, + }); + isa_bus->add_child(pit_device); } } // namespace arch::devices diff --git a/arch/x86_64/arch/drivers/pit.cpp b/arch/x86_64/arch/drivers/pit.cpp index 650c4245..94fa19e9 100644 --- a/arch/x86_64/arch/drivers/pit.cpp +++ b/arch/x86_64/arch/drivers/pit.cpp @@ -1,7 +1,7 @@ #include <arch/drivers/pit.hpp> #include <arch/bus/isa.hpp> -#include <arch/device_io/port_io.hpp> +#include <arch/io/port_io.hpp> #include <kapi/devices.hpp> #include <kapi/interrupts.hpp> @@ -21,14 +21,12 @@ namespace arch::drivers namespace { - using command_port = io::port<0x43, std::uint8_t, io::port_write>; - using channel_0_port = io::port<0x40, std::uint8_t, io::port_write>; - using channel_1_port = io::port<0x41, std::uint8_t, io::port_write>; - using channel_2_port = io::port<0x42, std::uint8_t, io::port_write>; - constexpr auto base_frequency = 1'193'182u; constexpr auto square_wave_mode = 0x36; + constexpr auto channel_0_offset = 0u; + constexpr auto command_offset = 3u; + constexpr auto pit_names = std::array{"pit"sv}; } // namespace @@ -38,18 +36,33 @@ namespace arch::drivers auto pit::probe(kapi::devices::device & device) -> kstd::result<void> { - auto data = kstd::make_shared<pit::data>(0, 0); + auto port = device.request_resource<kapi::devices::resource_type::port>(); + if (!port) + { + return kstd::failure(port.error()); + } + + auto irq = device.request_resource<kapi::devices::resource_type::irq>(); + if (!irq) + { + return kstd::failure(irq.error()); + } + + auto base_port = port->start; + auto irq_number = irq->number; + + auto data = kstd::make_shared<pit::data>(irq_number, 0); device.set_driver_data(data); auto divisor = static_cast<std::uint16_t>(base_frequency / m_frequency_in_hz); kapi::interrupts::register_handler(data->irq_number, *this, data); - command_port::write<std::uint8_t>(square_wave_mode); + io::write_port<std::uint8_t>(static_cast<std::uint16_t>(base_port + command_offset), square_wave_mode); io::wait(); - channel_0_port::write<std::uint8_t>(divisor & 0xff); + io::write_port<std::uint8_t>(static_cast<std::uint16_t>(base_port + channel_0_offset), divisor & 0xff); io::wait(); - channel_0_port::write<std::uint8_t>(divisor >> 8 & 0xff); + io::write_port<std::uint8_t>(static_cast<std::uint16_t>(base_port + channel_0_offset), divisor >> 8 & 0xff); io::wait(); return kstd::success(); diff --git a/arch/x86_64/arch/device_io/port_io.hpp b/arch/x86_64/arch/io/port_io.hpp index 4c8d66ae..475e223b 100644 --- a/arch/x86_64/arch/device_io/port_io.hpp +++ b/arch/x86_64/arch/io/port_io.hpp @@ -107,6 +107,59 @@ namespace arch::io port<0x80, std::uint8_t, port_write>::write<std::uint8_t>(0); } + //! Read from a port whose address is only known at runtime. + //! + //! @tparam ValueType The type of the value to read. + //! @param address The address of the port to read from. + //! @return The value read from the port. + template<port_io_type ValueType> + [[nodiscard]] auto read_port(std::uint16_t address) noexcept -> ValueType + { + if constexpr (sizeof(ValueType) == 1) + { + auto data = std::uint8_t{}; + asm volatile("in %%dx, %%al" : "=a"(data) : "Nd"(address)); + return std::bit_cast<ValueType>(data); + } + else if constexpr (sizeof(ValueType) == 2) + { + auto data = std::uint16_t{}; + asm volatile("in %%dx, %%ax" : "=a"(data) : "Nd"(address)); + return std::bit_cast<ValueType>(data); + } + else + { + auto data = std::uint32_t{}; + asm volatile("in %%dx, %%eax" : "=a"(data) : "Nd"(address)); + return std::bit_cast<ValueType>(data); + } + } + + //! Write to a port whose address is only known at runtime. + //! + //! @tparam ValueType The type of the value to write. + //! @param address The address of the port to write to. + //! @param data The value to write. + template<port_io_type ValueType> + auto write_port(std::uint16_t address, ValueType data) noexcept -> void + { + if constexpr (sizeof(ValueType) == 1) + { + auto raw = std::bit_cast<std::uint8_t>(data); + asm volatile("out %%al, %%dx" : : "a"(raw), "Nd"(address)); + } + else if constexpr (sizeof(ValueType) == 2) + { + auto raw = std::bit_cast<std::uint16_t>(data); + asm volatile("out %%ax, %%dx" : : "a"(raw), "Nd"(address)); + } + else + { + auto raw = std::bit_cast<std::uint32_t>(data); + asm volatile("out %%eax, %%dx" : : "a"(raw), "Nd"(address)); + } + } + } // namespace arch::io #endif
\ No newline at end of file diff --git a/kapi/kapi/devices.hpp b/kapi/kapi/devices.hpp index 124cd2bb..8c0c238e 100644 --- a/kapi/kapi/devices.hpp +++ b/kapi/kapi/devices.hpp @@ -11,6 +11,7 @@ #include <kapi/devices/driver_registry.hpp> // IWYU pragma: export #include <kapi/devices/error.hpp> // IWYU pragma: export #include <kapi/devices/facet_registry.hpp> // IWYU pragma: export +#include <kapi/devices/resource.hpp> // IWYU pragma: export #include <kstd/memory.hpp> #include <kstd/result.hpp> diff --git a/kapi/kapi/devices/resource.hpp b/kapi/kapi/devices/resource.hpp index 6a682594..bcad5dd5 100644 --- a/kapi/kapi/devices/resource.hpp +++ b/kapi/kapi/devices/resource.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_KAPI_DEVICES_RESOURCE_HPP #define TEACHOS_KAPI_DEVICES_RESOURCE_HPP +// IWYU pragma: private, include <kapi/devices.hpp> + #include <kapi/memory.hpp> #include <kapi/system.hpp> diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index 237183c9..6f05954a 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -14,6 +14,7 @@ #include <algorithm> #include <cstddef> #include <ranges> +#include <utility> namespace kapi::devices { @@ -109,7 +110,7 @@ namespace kapi::devices auto device::set_resources(kstd::vector<resource> resources) -> void { auto guard = kstd::lock_guard{m_lock}; - m_resources = resources; + m_resources = std::move(resources); } auto device::query_facet(kapi::capabilities::facet_id) -> void * |
