aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-27 18:09:27 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-27 18:09:27 +0200
commitb5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb (patch)
tree0ae6e86cccf1f25e33b8fbd311d597b9326e54c2
parent1121cb81d66b704c7528356f450acffba4c0f62f (diff)
downloadkernel-b5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb.tar.xz
kernel-b5450cecbffdca1dd9dffdb58dd295a6a5d7f6eb.zip
x86_64: port PIT to devices resources
-rw-r--r--arch/x86_64/arch/debug/qemu_output.hpp2
-rw-r--r--arch/x86_64/arch/devices/init.cpp7
-rw-r--r--arch/x86_64/arch/drivers/pit.cpp33
-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.hpp1
-rw-r--r--kapi/kapi/devices/resource.hpp2
-rw-r--r--kernel/kapi/devices/device.cpp3
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 *