Skip to content
Snippets Groups Projects
Commit 18863e0f authored by Felix Morgner's avatar Felix Morgner
Browse files

x86_64: io: implement simple port I/O operations

parent 25a02ae2
No related branches found
No related tags found
No related merge requests found
#ifndef TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP
#define TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace teachos::arch::io
{
/**
* @brief An I/O port of a given size at a given address.
*
* @tparam Address The address (port number) of the I/O port.
* @tparam Size The size (in bytes) of the I/O port.
*/
template<std::uint16_t Address, std::size_t Size>
struct port
{
static_assert(Size == 1 || Size == 2 || Size == 4, "A port must be either 1, 2, or 4 bytes in size");
using io_type =
std::conditional_t<Size == 1, std::byte, std::conditional_t<Size == 2, std::uint16_t, std::uint32_t>>;
/**
* @brief Write a byte to the I/O port.
*
* @param data The data to write to the I/O port.
*/
auto static write(io_type data) -> void
requires(Size == 1)
{
asm volatile("mov %[port], %%dx\n"
"mov %[data], %%al\n"
"out %%al, %%dx\n"
:
: [port] "i"(Address), [data] "im"(data)
: "dx", "al");
}
/**
* @brief Write a word to the I/O port.
*
* @param data The data to write to the I/O port.
*/
auto static write(io_type data) -> void
requires(Size == 2)
{
asm volatile("mov %[port], %%dx\n"
"mov %[data], %%ax\n"
"out %%ax, %%dx\n"
:
: [port] "i"(Address), [data] "im"(data)
: "dx", "ax");
}
/**
* @brief Write a double-word to the I/O port.
*
* @param data The data to write to the I/O port.
*/
auto static write(io_type data) -> void
requires(Size == 4)
{
asm volatile("mov %[port], %%dx\n"
"mov %[data], %%eax\n"
"out %%eax, %%dx\n"
:
: [port] "i"(Address), [data] "im"(data)
: "dx", "eax");
}
/**
* @brief Read a byte from the I/O port.
*
* @return The data read from the I/O port.
*/
auto static read() -> io_type
requires(Size == 1)
{
auto data = io_type{};
asm volatile("mov %[port], %%dx\n"
"in %%dx, %%al\n"
"mov %%al, %[data]\n"
: [data] "=m"(data)
: [port] "i"(Address)
: "dx", "al");
return data;
}
/**
* @brief Read a word from the I/O port.
*
* @return The data read from the I/O port.
*/
auto static read() -> io_type
requires(Size == 2)
{
auto data = io_type{};
asm volatile("mov %[port], %%dx\n"
"in %%dx, %%ax\n"
"mov %%ax, %[data]\n"
: [data] "=m"(data)
: [port] "i"(Address)
: "dx", "ax");
return data;
}
/**
* @brief Read a double-word from the I/O port.
*
* @return The data read from the I/O port.
*/
auto static read() -> io_type
requires(Size == 4)
{
auto data = io_type{};
asm volatile("mov %[port], %%dx\n"
"in %%dx, %%eax\n"
"mov %%eax, %[data]\n"
: [data] "=m"(data)
: [port] "i"(Address)
: "dx", "eax");
return data;
}
};
} // namespace teachos::arch::io
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment