xaizek / tos (License: GPLv3 only) (since 2018-12-07)
This is an alternative version of sources presented as part of Write Your Own OS video tutorial by Viktor Engelmann.
<root> / src / hwcomm / Port.hpp (c41e188428549da26e1dd6343ea4a2f5341bcdbc) (1,688B) (mode 100644) [raw]
#ifndef TOS__HWCOMM__PORT_HPP__
#define TOS__HWCOMM__PORT_HPP__

#include <cstdint>

#include <type_traits>

namespace hwcomm {

template <typename T>
class Port
{
    static_assert(std::is_same<T, std::uint8_t>::value ||
                  std::is_same<T, std::uint16_t>::value ||
                  std::is_same<T, std::uint32_t>::value,
                  "Port only accepts std::uint{8,16,32} types!");

public:
    constexpr explicit Port(std::uint16_t portNumber) : portNumber(portNumber)
    {
    }

public:
    T read();
    void write(T data);

private:
    std::uint16_t portNumber;
};

using Port8 = Port<std::uint8_t>;
using Port16 = Port<std::uint16_t>;
using Port32 = Port<std::uint32_t>;

template <>
inline std::uint8_t
Port<std::uint8_t>::read()
{
    std::uint8_t result;
    asm volatile("inb %1, %0" : "=a"(result) : "Nd"(portNumber));
    return result;
}

template <>
inline std::uint16_t
Port<std::uint16_t>::read()
{
    std::uint16_t result;
    asm volatile("inw %1, %0" : "=a"(result) : "Nd"(portNumber));
    return result;
}

template <>
inline std::uint32_t
Port<std::uint32_t>::read()
{
    std::uint32_t result;
    asm volatile("inl %1, %0" : "=a"(result) : "Nd"(portNumber));
    return result;
}

template <>
inline void
Port<std::uint8_t>::write(std::uint8_t data)
{
    asm volatile("outb %0, %1" : : "a"(data), "Nd"(portNumber));
}

template <>
inline void
Port<std::uint16_t>::write(std::uint16_t data)
{
    asm volatile("outw %0, %1" : : "a"(data), "Nd"(portNumber));
}

template <>
inline void
Port<std::uint32_t>::write(std::uint32_t data)
{
    asm volatile("outl %0, %1" : : "a"(data), "Nd"(portNumber));
}

}

#endif // TOS__HWCOMM__PORT_HPP__
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master