AquilaOS documentation
How it works, and its code
Toggle main menu visibility
Loading...
Searching...
No Matches
io.h
Go to the documentation of this file.
1
#ifndef _X86_IO_H
2
#define _X86_IO_H
3
4
#include <
stdint.h
>
5
6
/*
7
* x86: devices' registers, as I/O ports or memory. Drivers use the
8
* io_in*() and io_out*() functions below with a struct ioaddr, which says
9
* which of the two a device's registers are, and how far apart they are.
10
* The __in* and __out* macros are the port instructions themselves.
11
*/
12
13
/* read a port */
14
#define __inb(port) \
15
({ \
16
uint8_t ret; \
17
asm volatile ("inb %%dx, %%al":"=a"(ret):"d"(port)); \
18
ret; \
19
})
20
21
#define __inw(port) \
22
({ \
23
uint16_t ret; \
24
asm volatile ("inw %%dx, %%ax":"=a"(ret):"dN"(port)); \
25
ret; \
26
})
27
28
#define __inl(port) \
29
({ \
30
uint32_t ret; \
31
asm volatile ("inl %%dx, %%eax":"=a"(ret):"d"(port)); \
32
ret; \
33
})
34
35
/* Read or write `count` 16-bit words through a port. rep insw and rep
36
* outsw change EDI (ESI) and ECX, so those are outputs for the
37
* compiler. */
38
#define __insw(port, count, buf) \
39
({ \
40
void *__buf = (buf); \
41
uint32_t __count = (count); \
42
asm volatile ("rep insw":"+D"(__buf), "+c"(__count):"d"(port):"memory"); \
43
})
44
45
#define __outsw(port, count, buf) \
46
({ \
47
const void *__buf = (buf); \
48
uint32_t __count = (count); \
49
asm volatile ("rep outsw":"+S"(__buf), "+c"(__count):"d"(port):"memory"); \
50
})
51
52
/* write a port */
53
#define __outb(port, value) \
54
({ \
55
asm volatile ("outb %%al, %%dx"::"d"((port)),"a"((value))); \
56
})
57
58
#define __outw(port, value) \
59
({ \
60
asm volatile ("outw %%ax, %%dx"::"d"(port),"a"(value)); \
61
})
62
63
#define __outl(port, value) \
64
({ \
65
asm volatile ("outl %%eax, %%dx"::"d"(port),"a"(value)); \
66
})
67
68
/* a short delay, for old devices that need time between accesses */
69
#define __io_wait() \
70
({ \
71
asm volatile ( "jmp 1f\n\t" \
72
"1:jmp 2f\n\t" \
73
"2:" ); \
74
})
75
76
/* read or write a memory-mapped register */
77
#define __mmio_inb(addr) (*((volatile uint8_t *)(addr)))
78
#define __mmio_inw(addr) (*((volatile uint16_t *)(addr)))
79
#define __mmio_inl(addr) (*((volatile uint32_t *)(addr)))
80
#define __mmio_inq(addr) (*((volatile uint64_t *)(addr)))
81
82
#define __mmio_outb(addr, v) (*((volatile uint8_t *)(addr)) = v)
83
#define __mmio_outw(addr, v) (*((volatile uint16_t *)(addr)) = v)
84
#define __mmio_outl(addr, v) (*((volatile uint32_t *)(addr)) = v)
85
#define __mmio_outq(addr, v) (*((volatile uint64_t *)(addr)) = v)
86
87
/* What a device's registers are: I/O ports, or memory with registers 1,
88
* 2 or 4 bytes apart. */
89
#define IOADDR_PORT 1
90
#define IOADDR_MMIO8 2
91
#define IOADDR_MMIO16 3
92
#define IOADDR_MMIO32 4
93
95
struct
ioaddr
{
96
char
type
;
/* IOADDR_* */
97
uintptr_t
addr
;
/* the first port, or the kernel address of the first register */
98
};
99
100
/* Returns the name of an ioaddr's type, for messages. */
101
static
inline
char
*
ioaddr_type_str
(
struct
ioaddr
*io)
102
{
103
switch
(io->
type
) {
104
case
IOADDR_PORT
:
105
return
"pio"
;
106
case
IOADDR_MMIO8
:
107
return
"mmio8"
;
108
case
IOADDR_MMIO16
:
109
return
"mmio16"
;
110
case
IOADDR_MMIO32
:
111
return
"mmio32"
;
112
}
113
114
return
NULL
;
115
}
116
117
/* Read or write register number `off` of a device, 8, 16 or 32 bits at
118
* a time. */
119
static
inline
uint8_t
io_in8
(
struct
ioaddr
*io,
uintptr_t
off)
120
{
121
switch
(io->
type
) {
122
case
IOADDR_PORT
:
123
return
__inb
(io->
addr
+ off);
124
case
IOADDR_MMIO8
:
125
return
__mmio_inb
(io->
addr
+ off);
126
case
IOADDR_MMIO16
:
127
return
__mmio_inb
(io->
addr
+ (off << 1));
128
case
IOADDR_MMIO32
:
129
return
__mmio_inb
(io->
addr
+ (off << 2));
130
}
131
132
return
0;
133
}
134
135
static
inline
uint16_t
io_in16
(
struct
ioaddr
*io,
uintptr_t
off)
136
{
137
switch
(io->
type
) {
138
case
IOADDR_PORT
:
139
return
__inw
(io->
addr
+ off);
140
case
IOADDR_MMIO8
:
141
return
__mmio_inw
(io->
addr
+ off);
142
case
IOADDR_MMIO16
:
143
return
__mmio_inw
(io->
addr
+ (off << 1));
144
case
IOADDR_MMIO32
:
145
return
__mmio_inw
(io->
addr
+ (off << 2));
146
}
147
148
return
0;
149
}
150
151
static
inline
uint32_t
io_in32
(
struct
ioaddr
*io,
uintptr_t
off)
152
{
153
switch
(io->
type
) {
154
case
IOADDR_PORT
:
155
return
__inl
(io->
addr
+ off);
156
case
IOADDR_MMIO8
:
157
return
__mmio_inl
(io->
addr
+ off);
158
case
IOADDR_MMIO16
:
159
return
__mmio_inl
(io->
addr
+ (off << 1));
160
case
IOADDR_MMIO32
:
161
return
__mmio_inl
(io->
addr
+ (off << 2));
162
}
163
164
return
0;
165
}
166
167
static
inline
void
io_out8
(
struct
ioaddr
*io,
uintptr_t
off,
uint8_t
val)
168
{
169
switch
(io->
type
) {
170
case
IOADDR_PORT
:
171
__outb
(io->
addr
+ off, val);
return
;
172
case
IOADDR_MMIO8
:
173
__mmio_outb
(io->
addr
+ off, val);
return
;
174
case
IOADDR_MMIO16
:
175
__mmio_outb
(io->
addr
+ (off << 1), val);
return
;
176
case
IOADDR_MMIO32
:
177
__mmio_outb
(io->
addr
+ (off << 2), val);
return
;
178
}
179
}
180
181
static
inline
void
io_out16
(
struct
ioaddr
*io,
uintptr_t
off,
uint16_t
val)
182
{
183
switch
(io->
type
) {
184
case
IOADDR_PORT
:
185
__outw
(io->
addr
+ off, val);
return
;
186
case
IOADDR_MMIO8
:
187
__mmio_outw
(io->
addr
+ off, val);
return
;
188
case
IOADDR_MMIO16
:
189
__mmio_outw
(io->
addr
+ (off << 1), val);
return
;
190
case
IOADDR_MMIO32
:
191
__mmio_outw
(io->
addr
+ (off << 2), val);
return
;
192
}
193
}
194
195
static
inline
void
io_out32
(
struct
ioaddr
*io,
uintptr_t
off,
uint32_t
val)
196
{
197
switch
(io->
type
) {
198
case
IOADDR_PORT
:
199
__outl
(io->
addr
+ off, val);
return
;
200
case
IOADDR_MMIO8
:
201
__mmio_outl
(io->
addr
+ off, val);
return
;
202
case
IOADDR_MMIO16
:
203
__mmio_outl
(io->
addr
+ (off << 1), val);
return
;
204
case
IOADDR_MMIO32
:
205
__mmio_outl
(io->
addr
+ (off << 2), val);
return
;
206
}
207
}
208
209
#endif
/* ! _X86_IO_H */
io_out16
static void io_out16(struct ioaddr *io, uintptr_t off, uint16_t val)
Definition
io.h:49
io_in32
static uint32_t io_in32(struct ioaddr *io, uintptr_t off)
Definition
io.h:38
io_in16
static uint16_t io_in16(struct ioaddr *io, uintptr_t off)
Definition
io.h:33
io_out32
static void io_out32(struct ioaddr *io, uintptr_t off, uint32_t val)
Definition
io.h:54
io_in8
static uint8_t io_in8(struct ioaddr *io, uintptr_t off)
Reads an 8-, 16- or 32-bit register.
Definition
io.h:28
io_out8
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
Definition
io.h:44
__outw
#define __outw(port, value)
Definition
io.h:58
__mmio_inl
#define __mmio_inl(addr)
Definition
io.h:79
ioaddr_type_str
static char * ioaddr_type_str(struct ioaddr *io)
Definition
io.h:101
__outb
#define __outb(port, value)
Definition
io.h:53
__mmio_outl
#define __mmio_outl(addr, v)
Definition
io.h:84
__mmio_inb
#define __mmio_inb(addr)
Definition
io.h:77
IOADDR_PORT
#define IOADDR_PORT
Definition
io.h:89
__mmio_outb
#define __mmio_outb(addr, v)
Definition
io.h:82
__inb
#define __inb(port)
Definition
io.h:14
__mmio_inw
#define __mmio_inw(addr)
Definition
io.h:78
__inw
#define __inw(port)
Definition
io.h:21
__outl
#define __outl(port, value)
Definition
io.h:63
IOADDR_MMIO16
#define IOADDR_MMIO16
Definition
io.h:91
__mmio_outw
#define __mmio_outw(addr, v)
Definition
io.h:83
IOADDR_MMIO8
#define IOADDR_MMIO8
Definition
io.h:90
__inl
#define __inl(port)
Definition
io.h:28
IOADDR_MMIO32
#define IOADDR_MMIO32
Definition
io.h:92
NULL
#define NULL
Definition
stddef.h:27
uintptr_t
__SIZE_TYPE__ uintptr_t
Definition
stddef.h:12
uint32_t
unsigned int uint32_t
Definition
stddef.h:22
uint8_t
unsigned char uint8_t
Definition
stddef.h:20
uint16_t
unsigned short int uint16_t
Definition
stddef.h:21
stdint.h
ioaddr
Where a device's registers are.
Definition
io.h:95
ioaddr::addr
uintptr_t addr
Definition
io.h:97
ioaddr::type
char type
Definition
io.h:96
kernel
arch
i386
include
cpu
io.h
Generated by
1.18.0