My Kernel v0.1.0
cpu.h
1#ifndef KERNEL_ARCH_I686_UTILS_CPU_OPS_H
2#define KERNEL_ARCH_I686_UTILS_CPU_OPS_H
3
4#include <kernel/types.h>
5
6#include <utils/compiler.h>
7#include <utils/map.h>
8
9// Read from a 32-bits register
10#define READ_REGISTER_OPS(_reg) \
11 static ALWAYS_INLINE u32 read_##_reg() \
12 { \
13 u32 res; \
14 ASM("movl %%" #_reg ", %0" : "=r"(res)); \
15 return res; \
16 }
17
18// Write into a 32-bits register
19#define WRITE_REGISTER_OPS(_reg) \
20 static ALWAYS_INLINE void write_##_reg(u32 value) \
21 { \
22 ASM("movl %0, %%" #_reg : : "r"(value)); \
23 }
24
25#define CPU_32BIT_REGISTERS \
26 cr0, cr1, cr2, cr3, cr4, esp, cs, ds, es, fs, gs, ss, eax
27
28MAP(READ_REGISTER_OPS, CPU_32BIT_REGISTERS)
29MAP(WRITE_REGISTER_OPS, CPU_32BIT_REGISTERS)
30
31#undef CPU_32BIT_REGISTERS
32#undef WRITE_REGISTER_OPS
33#undef READ_REGISTER_OPS
34
35/* Write a single byte at a given I/O port address. */
36static ALWAYS_INLINE void outb(uint16_t port, uint8_t val)
37{
38 ASM("out %0,%1" : : "a"(val), "Nd"(port) : "memory");
39}
40
41/* Write 2 bytes at a given I/O port address. */
42static ALWAYS_INLINE void outw(uint16_t port, uint16_t val)
43{
44 ASM("out %0,%1" : : "a"(val), "Nd"(port) : "memory");
45}
46
47/* Write 4 bytes at a given I/O port address. */
48static ALWAYS_INLINE void outl(uint16_t port, uint32_t val)
49{
50 ASM("out %0,%1" : : "a"(val), "Nd"(port) : "memory");
51}
52
53/* Read a single byte from a given I/O port address. */
54static ALWAYS_INLINE uint8_t inb(uint16_t port)
55{
56 uint8_t val;
57 ASM("in %1, %0" : "=a"(val) : "Nd"(port) : "memory");
58 return val;
59}
60
61/* Read 2 bytes from a given I/O port address. */
62static ALWAYS_INLINE uint16_t inw(uint16_t port)
63{
64 uint16_t val;
65 ASM("in %1, %0" : "=a"(val) : "Nd"(port) : "memory");
66 return val;
67}
68
69/* Read 4 bytes from a given I/O port address. */
70static ALWAYS_INLINE uint32_t inl(uint16_t port)
71{
72 uint32_t val;
73 ASM("in %1,%0" : "=a"(val) : "Nd"(port) : "memory");
74 return val;
75}
76
77static ALWAYS_INLINE void hlt(void)
78{
79 ASM("hlt");
80}
81
82static ALWAYS_INLINE void insb(uint16_t port, uint8_t *buffer, size_t size)
83{
84 size_t count = size / sizeof(*buffer);
85
86 asm volatile("cld; rep insb"
87 : "+D"(buffer), "+c"(count)
88 : "d"(port)
89 : "memory");
90}
91
92static ALWAYS_INLINE void insw(uint16_t port, uint16_t *buffer, size_t size)
93{
94 size_t count = size / sizeof(*buffer);
95
96 asm volatile("cld; rep insw"
97 : "+D"(buffer), "+c"(count)
98 : "d"(port)
99 : "memory");
100}
101
102static ALWAYS_INLINE void insl(uint16_t port, uint32_t *buffer, size_t size)
103{
104 size_t count = size / sizeof(*buffer);
105
106 asm volatile("cld; rep insl"
107 : "+D"(buffer), "+c"(count)
108 : "d"(port)
109 : "memory");
110}
111
112#endif /* KERNEL_I686_UTILS_CPU_OPS_H */
#define MAP(f,...)
Applies the function macro f to each of the remaining parameters.
Definition: map.h:60