Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / arch / i386 / include / arch / io.h
1 #ifndef _ASM_IO_H
2 #define _ASM_IO_H
3
4 #include <stdint.h>
5
6 /*
7  * This file contains the definitions for the x86 IO instructions
8  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
9  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
10  * versions of the single-IO instructions (inb_p/inw_p/..).
11  */
12 #if defined(__ROMCC__)
13 static inline void outb(uint8_t value, uint16_t port)
14 {
15         __builtin_outb(value, port);
16 }
17
18 static inline void outw(uint16_t value, uint16_t port)
19 {
20         __builtin_outw(value, port);
21 }
22
23 static inline void outl(uint32_t value, uint16_t port)
24 {
25         __builtin_outl(value, port);
26 }
27
28
29 static inline uint8_t inb(uint16_t port)
30 {
31         return __builtin_inb(port);
32 }
33
34
35 static inline uint16_t inw(uint16_t port)
36 {
37         return __builtin_inw(port);
38 }
39
40 static inline uint32_t inl(uint16_t port)
41 {
42         return __builtin_inl(port);
43 }
44 #else
45 static inline void outb(uint8_t value, uint16_t port)
46 {
47         __asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port));
48 }
49
50 static inline void outw(uint16_t value, uint16_t port)
51 {
52         __asm__ __volatile__ ("outw %w0, %w1" : : "a" (value), "Nd" (port));
53 }
54
55 static inline void outl(uint32_t value, uint16_t port)
56 {
57         __asm__ __volatile__ ("outl %0, %w1" : : "a" (value), "Nd" (port));
58 }
59
60 static inline uint8_t inb(uint16_t port)
61 {
62         uint8_t value;
63         __asm__ __volatile__ ("inb %w1, %b0" : "=a"(value) : "Nd" (port));
64         return value;
65 }
66
67 static inline uint16_t inw(uint16_t port)
68 {
69         uint16_t value;
70         __asm__ __volatile__ ("inw %w1, %w0" : "=a"(value) : "Nd" (port));
71         return value;
72 }
73
74 static inline uint32_t inl(uint16_t port)
75 {
76         uint32_t value;
77         __asm__ __volatile__ ("inl %w1, %0" : "=a"(value) : "Nd" (port));
78         return value;
79 }
80 #endif /* __ROMCC__ */
81
82 static inline void outsb(uint16_t port, const void *addr, unsigned long count)
83 {
84         __asm__ __volatile__ (
85                 "cld ; rep ; outsb "
86                 : "=S" (addr), "=c" (count)
87                 : "d"(port), "0"(addr), "1" (count)
88                 );
89 }
90
91 static inline void outsw(uint16_t port, const void *addr, unsigned long count)
92 {
93         __asm__ __volatile__ (
94                 "cld ; rep ; outsw "
95                 : "=S" (addr), "=c" (count)
96                 : "d"(port), "0"(addr), "1" (count)
97                 );
98 }
99
100 static inline void outsl(uint16_t port, const void *addr, unsigned long count)
101 {
102         __asm__ __volatile__ (
103                 "cld ; rep ; outsl "
104                 : "=S" (addr), "=c" (count)
105                 : "d"(port), "0"(addr), "1" (count)
106                 );
107 }
108
109
110 static inline void insb(uint16_t port, void *addr, unsigned long count)
111 {
112         __asm__ __volatile__ (
113                 "cld ; rep ; insb "
114                 : "=D" (addr), "=c" (count)
115                 : "d"(port), "0"(addr), "1" (count)
116                 );
117 }
118
119 static inline void insw(uint16_t port, void *addr, unsigned long count)
120 {
121         __asm__ __volatile__ (
122                 "cld ; rep ; insw "
123                 : "=D" (addr), "=c" (count)
124                 : "d"(port), "0"(addr), "1" (count)
125                 );
126 }
127
128 static inline void insl(uint16_t port, void *addr, unsigned long count)
129 {
130         __asm__ __volatile__ (
131                 "cld ; rep ; insl "
132                 : "=D" (addr), "=c" (count)
133                 : "d"(port), "0"(addr), "1" (count)
134                 );
135 }
136
137 #if 0
138 /* XXX XXX XXX This is a story from the evil API from hell XXX XXX XXX
139  * We have different functions for memory access in pre-ram stage and ram
140  * stage. Those in pre-ram stage are called write32 and expect the address
141  * first and the address as a pointer type. Those in ram stage are called
142  * writel and expect the datum first and the address as an integer type.
143  * Until all code is checked and fixed, I'll add both versions here now.
144  */
145
146 static inline void writeb(uint8_t b, volatile void *addr)
147 {
148         *(volatile uint8_t *) addr = b;
149 }
150
151 static inline void writew(uint16_t b, volatile void *addr)
152 {
153         *(volatile uint16_t *) addr = b;
154 }
155
156 static inline void writel(uint32_t b, volatile void *addr)
157 {
158         *(volatile uint32_t *) addr = b;
159 }
160
161 static inline uint8_t readb(const volatile void *addr)
162 {
163         return *(volatile uint8_t *) addr;
164 }
165
166 static inline uint16_t readw(const volatile void *addr)
167 {
168         return *(volatile uint16_t *) addr;
169 }
170
171 static inline uint32_t readl(const volatile void *addr)
172 {
173         return *(volatile uint32_t *) addr;
174 }
175 #endif
176
177 #if !defined(__PRE_RAM__)
178 static inline __attribute__((always_inline)) uint8_t read8(unsigned long addr)
179 {
180         return *((volatile uint8_t *)(addr));
181 }
182
183 static inline __attribute__((always_inline)) uint16_t read16(unsigned long addr)
184 {
185         return *((volatile uint16_t *)(addr));
186 }
187
188 static inline __attribute__((always_inline)) uint32_t read32(unsigned long addr)
189 {
190         return *((volatile uint32_t *)(addr));
191 }
192
193 static inline __attribute__((always_inline)) void write8(unsigned long addr, uint8_t value)
194 {
195         *((volatile uint8_t *)(addr)) = value;
196 }
197
198 static inline __attribute__((always_inline)) void write16(unsigned long addr, uint16_t value)
199 {
200         *((volatile uint16_t *)(addr)) = value;
201 }
202
203 static inline __attribute__((always_inline)) void write32(unsigned long addr, uint32_t value)
204 {
205         *((volatile uint32_t *)(addr)) = value;
206 }
207 #endif
208
209 #endif
210